Problem with restoring of hp.

Post Reply
User avatar
Andrey01
Member
Posts: 2574
Joined: Wed Oct 19, 2016 15:18
GitHub: Andrey2470T
In-game: Andrey01
Location: Russia, Moscow

Problem with restoring of hp.

by Andrey01 » Post

I`ve registered "healing pill" for my Medicine mod that will restore hp temporarily after 5 seconds some hps while hp won`t be equal 20. However it restores after 5 seconds hp entirely. Why? Here is a code below:

Code: Select all

local function healing_effect(itemstack, user)
    local player_hp = user:get_hp()
    
    local hp_change = 3
    
    local player_pos = user:get_pos()
    
    if player_hp < 20 then
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x + 0.4, y = player_pos.y + 2, z = player_pos.z + 0.4},
                maxpos = {x = player_pos.x + 0.8, y = player_pos.y + 2, z = player_pos.z + 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x - 0.4, y = player_pos.y + 2, z = player_pos.z - 0.4},
                maxpos = {x = player_pos.x - 0.8, y = player_pos.y + 2, z = player_pos.z - 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x - 0.4, y = player_pos.y + 2, z = player_pos.z + 0.4},
                maxpos = {x = player_pos.x - 0.8, y = player_pos.y + 2, z = player_pos.z + 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x + 0.4, y = player_pos.y + 2, z = player_pos.z - 0.4},
                maxpos = {x = player_pos.x + 0.8, y = player_pos.y + 2, z = player_pos.z - 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            while player_hp ~= 20 do
                if player_hp >= 20 then
                    local playername = user:get_player_name()
                    minetest.chat_send_player(playername, "You are cured!")
                    break
            
                end
                player_hp = player_hp + hp_change
            
                minetest.after(3, function()
                    user:set_hp(player_hp)
                end)
            
        
           end
    end
end

minetest.register_craftitem('medicine:healing_pill', {
    description = 'Healing Pill',
    inventory_image = 'healing_pill.png',
    stack_max = 12,
    on_use = function(itemstack, user, pointed_thing)
        itemstack:take_item()
        
        return itemstack, healing_effect(itemstack, user)
end

}) 

User avatar
Andrey01
Member
Posts: 2574
Joined: Wed Oct 19, 2016 15:18
GitHub: Andrey2470T
In-game: Andrey01
Location: Russia, Moscow

Re: Problem with restoring of hp.

by Andrey01 » Post

I have rewritten a bit the code. Here:

Code: Select all

local function healing_effect(itemstack, user)
    local player_hp = user:get_hp()
    
    local hp_change = 3
    
    local player_pos = user:get_pos()
            
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x + 0.4, y = player_pos.y + 2, z = player_pos.z + 0.4},
                maxpos = {x = player_pos.x + 0.8, y = player_pos.y + 2, z = player_pos.z + 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x - 0.4, y = player_pos.y + 2, z = player_pos.z - 0.4},
                maxpos = {x = player_pos.x - 0.8, y = player_pos.y + 2, z = player_pos.z - 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x - 0.4, y = player_pos.y + 2, z = player_pos.z + 0.4},
                maxpos = {x = player_pos.x - 0.8, y = player_pos.y + 2, z = player_pos.z + 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            minetest.add_particlespawner({
                amount = 1,
                time = 2,
                minpos = {x = player_pos.x + 0.4, y = player_pos.y + 2, z = player_pos.z - 0.4},
                maxpos = {x = player_pos.x + 0.8, y = player_pos.y + 2, z = player_pos.z - 0.8},
                minvel = {x = 0, y = 0.2, z = 0},
                maxvel = {x = 0, y = 0.4, z = 0},
                minexptime = time,
                maxexptime = time,
                minsize = 4,
                colissiondetection = true,
                texture = "healing_effect.png",
                playername = user:get_player_name()
            })
        
            local is_cycle_finished = false
            
            while player_hp ~= 20 do
                minetest.after(3, function()
                    if player_hp >= 20 then
                        minetest.chat_send_player(user:get_player_name(), "You are cured!")
                        is_cycle_finished = true
                    end
                    
                    player_hp = player_hp + hp_change
                    
                    user:set_hp(player_hp)
                    
                end)
                
                if is_cycle_finished then
                    is_cycle_finished = false
                    break
                end
                
        
           end
    end


minetest.register_craftitem('medicine:healing_pill', {
    description = 'Healing Pill',
    inventory_image = 'healing_pill.png',
    stack_max = 12,
    on_use = function(itemstack, user, pointed_thing)
        if user:get_hp() ~= 20 then
            itemstack:take_item()
            return itemstack, healing_effect(itemstack, user)
        end
end

}) 
However, when "while" loop was starting to implement the server shutdowned. Why so?

User avatar
AspireMint
Member
Posts: 415
Joined: Mon Jul 09, 2012 12:59
GitHub: AspireMint
IRC: AspireMint
In-game: AspireMint
Location: Stuck at spawn

Re: Problem with restoring of hp.

by AspireMint » Post

Problem is, while loop is repeated 1.000.000.000.000.001 times before your first minetest.after start :-P (well depends on your cpu speed and cpu strategy and ram size) Probably it will crash your server, OOM or something.

Fix:

Code: Select all

if player_hp ~= 20 then
    heal(user:get_player_name())
end

function heal(player_name)
    minetest.after(3, function(playername)
        local player = minetest.get_player_by_name(playername)
        if player then
            player:set_hp(player:get_hp() + 3)
            if player:get_hp() < 20 then
                heal(playername) -- heal me again!
            else
               player:set_hp(20) -- do not allow more hp than 20 (necessary?)
            end
        else
           minetest.chat_send_all("o ou, player " .. playername .. " is offline")
        end
    end, player_name)
end
(not tested, should work x))

User avatar
Andrey01
Member
Posts: 2574
Joined: Wed Oct 19, 2016 15:18
GitHub: Andrey2470T
In-game: Andrey01
Location: Russia, Moscow

Re: Problem with restoring of hp.

by Andrey01 » Post

Ah, thanks. I guessed my code was being looped this time before next minetest.after() call.

User avatar
Andrey01
Member
Posts: 2574
Joined: Wed Oct 19, 2016 15:18
GitHub: Andrey2470T
In-game: Andrey01
Location: Russia, Moscow

Re: Problem with restoring of hp.

by Andrey01 » Post

AspireMint wrote:Problem is, while loop is repeated 1.000.000.000.000.001 times before your first minetest.after start :-P (well depends on your cpu speed and cpu strategy and ram size) Probably it will crash your server, OOM or something.

Fix:

Code: Select all

if player_hp ~= 20 then
    heal(user:get_player_name())
end

function heal(player_name)
    minetest.after(3, function(playername)
        local player = minetest.get_player_by_name(playername)
        if player then
            player:set_hp(player:get_hp() + 3)
            if player:get_hp() < 20 then
                heal(playername) -- heal me again!
            else
               player:set_hp(20) -- do not allow more hp than 20 (necessary?)
            end
        else
           minetest.chat_send_all("o ou, player " .. playername .. " is offline")
        end
    end, player_name)
end
(not tested, should work x))
I`ve made healing effect today, but here is something strange error with your code:

Code: Select all

2018-07-03 21:55:11: ERROR[Main]: ServerError: AsyncErr: environment_Step: Runtime error from mod 'medicine' in callback environment_Step(): /home/user/.minetest/mods/medicine/diseases.lua:279: bad argument #1 to 'get_player_by_name' (string expected, got nil)
2018-07-03 21:55:11: ERROR[Main]: stack traceback:
2018-07-03 21:55:11: ERROR[Main]: 	[C]: in function 'get_player_by_name'
2018-07-03 21:55:11: ERROR[Main]: 	/home/user/.minetest/mods/medicine/diseases.lua:279: in function 'func'
2018-07-03 21:55:11: ERROR[Main]: 	/usr/share/minetest/builtin/common/after.lua:18: in function </usr/share/minetest/builtin/common/after.lua:4>
2018-07-03 21:55:11: ERROR[Main]: 	/usr/share/minetest/builtin/game/register.lua:412: in function </usr/share/minetest/builtin/game/register.lua:392>
How can "player" get nil from minetest.get_player_by_name() if "playername" is string actually? I checked my code and i saw i made all right without any mistakes.

Code: Select all

function effects.register_healing_effect(itemstack, user, hp_change, particle_time, interval)
    local player_hp = user:get_hp()
    
    if player_hp == 20 then
        return
    
    elseif player_hp < 20 then
        local player_pos = user:get_pos()
        
        local playername = user:get_player_name()
        misc.create_particle_spawner(4, user, {     -- particle_spawner function works fine for noticing
            {1, 1, 1, 1},
            {particle_time, particle_time, particle_time, particle_time},
            {{{player_pos.x + 0.4, player_pos.y + 2, player_pos.z + 0.4}, 
              {player_pos.x - 0.4, player_pos.y + 2, player_pos.z - 0.4}, 
              {player_pos.x - 0.4, player_pos.y + 2, player_pos.z + 0.4},
              {player_pos.x + 0.4, player_pos.y + 2, player_pos.z - 0.4}
             },
             {{player_pos.x + 0.8, player_pos.y + 2, player_pos.z + 0.8},
              {player_pos.x - 0.8, player_pos.y + 2, player_pos.z - 0.8},
              {player_pos.x - 0.8, player_pos.y + 2, player_pos.z + 0.8},
              {player_pos.x + 0.8, player_pos.y + 2, player_pos.z - 0.8}
             }
            },
            {{{0, 0.2, 0}, 
              {0, 0.2, 0}, 
              {0, 0.2, 0},
              {0, 0.2, 0}
             },
             {{0, 0.4, 0},
              {0, 0.4, 0},
              {0, 0.4, 0},
              {0, 0.4, 0}
             }
            },
            {{{0, 0.2, 0}, 
              {0, 0.2, 0}, 
              {0, 0.2, 0},
              {0, 0.2, 0}
             },
             {{0, 0.4, 0},
              {0, 0.4, 0},
              {0, 0.4, 0},
              {0, 0.4, 0}
             }
            },
            {{particle_time, particle_time, particle_time, particle_time},
             {particle_time, particle_time, particle_time, particle_time}
            },
            {{2.5, 2.5, 2.5, 2.5},
             {4.5, 4.5, 4.5, 4.5}
            },
            {true, true, true, true},
            {true, true, true, true},
            {"healing_effect.png", "healing_effect.png", "healing_effect.png", "healing_effect.png"},
            {playername, playername, playername, playername}     -- The table gets true values
        })
            
        heal_player(playername, interval, hp_change)
    end
end

function heal_player(playername, heal_interval, heal_amount)
    minetest.after(heal_interval, function (playername)
        local player = minetest.get_player_by_name(playername)    -- Here is an error
        
        player:set_hp(player:get_hp() + heal_amount)
        if player:get_hp() < 20 then
            heal_player(playername, heal_interval, heal_amount)
            
        elseif player:get_hp() >= 20 then
            minetest.chat_send_player(playername, "You are cured!")
            return
        end
    end)
end

User avatar
AspireMint
Member
Posts: 415
Joined: Mon Jul 09, 2012 12:59
GitHub: AspireMint
IRC: AspireMint
In-game: AspireMint
Location: Stuck at spawn

Re: Problem with restoring of hp.

by AspireMint » Post

You forgot to add third parameter into after function

minetest.after(heal_interval, function (playername)
...
end, playername)

https://dev.minetest.net/minetest.after
Last edited by AspireMint on Tue Jul 03, 2018 20:04, edited 1 time in total.

User avatar
Andrey01
Member
Posts: 2574
Joined: Wed Oct 19, 2016 15:18
GitHub: Andrey2470T
In-game: Andrey01
Location: Russia, Moscow

Re: Problem with restoring of hp.

by Andrey01 » Post

AspireMint wrote:You forget to add third parameter into after function

minetest.after(heal_interval, function (playername)
...
end, playername)

https://dev.minetest.net/minetest.after
Ah, yes. Thanks, i`ll fix it.

Post Reply

Who is online

Users browsing this forum: No registered users and 7 guests