hkzorman / advanced_npc

Advanced NPC for Minetest, using mobs_redo API
Other
18 stars 5 forks source link

NPC does not stand still #24

Closed BrunoMine closed 6 years ago

BrunoMine commented 6 years ago

I am only try maintain a NPC sleeping (by 10 seconds). He just sits on the bed and gets up. (Apparently)

do_custom = function(self, dtime)   

    -- Inicialize NPC
    if self.initialized == nil then
        npc.initialize(self, self.object:getpos(), true)
        self.tamed = false
        self.owner = nil
    end

    -- Action queue timer
    -- Check if actions and timers aren't locked
    if self.actions.action_timer_lock == false then
        -- Increment action timer
        self.actions.action_timer = self.actions.action_timer + dtime
        if self.actions.action_timer >= self.actions.action_interval then
            -- Reset action timer
            self.actions.action_timer = 0
            -- Check if NPC is walking
            if self.actions.walking.is_walking == true then
                -- Move NPC to expected position to ensure not getting lost
                local pos = self.actions.walking.target_pos
                self.object:moveto({x=pos.x, y=pos.y, z=pos.z})
            end
            -- Execute action
            self.freeze = npc.execute_action(self)
            -- Check if there are still remaining actions in the queue
            if self.freeze == nil and table.getn(self.actions.queue) > 0 then
                self.freeze = false
            end
        end
    end

    -- Lay in the bed
    if not self.tested and minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}) then
        self.tested = true
        npc.add_task(self, npc.actions.cmd.USE_BED, {
            pos = minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}),
            action = npc.actions.const.beds.LAY,
        })
        npc.add_action(self, npc.actions.cmd.SET_INTERVAL, {
            interval = 10,
            freeze=true,
        })
    end
end,
hkzorman commented 6 years ago

What is happening is that the mobs_redo mob_step function is kicking in. In order to avoid that you need to return false at the end of the function. In advanced_npc, it is handled by returning self.freeze.

Two things:

Like this:

do_custom = function(self, dtime)
    -- Inicialize NPC
    if self.initialized == nil then
        npc.initialize(self, self.object:getpos(), true)
        self.tamed = false
        self.owner = nil
    end

    -- Action queue timer
    -- Check if actions and timers aren't locked
    if self.actions.action_timer_lock == false then
        -- Increment action timer
        self.actions.action_timer = self.actions.action_timer + dtime
        if self.actions.action_timer >= self.actions.action_interval then
            -- Reset action timer
            self.actions.action_timer = 0
            -- Check if NPC is walking
            if self.actions.walking.is_walking == true then
                -- Move NPC to expected position to ensure not getting lost
                local pos = self.actions.walking.target_pos
                self.object:moveto({x=pos.x, y=pos.y, z=pos.z})
            end
            -- Execute action
            self.freeze = npc.execute_action(self)
            -- Check if there are still remaining actions in the queue
            if self.freeze == nil and table.getn(self.actions.queue) > 0 then
                self.freeze = false
            end
        end
    end

    -- Lay in the bed
    if not self.tested and minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}) then
        self.tested = true
        npc.add_task(self, npc.actions.cmd.USE_BED, {
            pos = minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}),
            action = npc.actions.const.beds.LAY
        })
        npc.add_action(self, npc.actions.cmd.SET_INTERVAL, {
            interval = 10,
            freeze = true,
        })
        npc.add_task(self, npc.actions.cmd.USE_BED, {
            pos = minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}),
            action = npc.actions.const.beds.GET_UP
        })
    end

    return self.freeze

end,

With the new code you can also do:

-- Lay in the bed
if not self.tested and minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}) then
    self.tested = true
    npc.add_task(self, npc.actions.cmd.USE_BED, {
        pos = minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}),
        action = npc.actions.const.beds.LAY
    })
    npc.add_action(self, npc.actions.cmd.SET_INTERVAL, {
        interval = 10,
        freeze = true,
    })
    npc.add_task(self, npc.actions.cmd.USE_BED, {
        pos = minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}),
        action = npc.actions.const.beds.GET_UP
    })
end

return npc.step(self, dtime)
BrunoMine commented 6 years ago

Thank you. But the method npc.add_task can not be used if NPC not be initialized. So I use on_spawn.

on_spawn = function(self)
    npc.initialize(self, self.object:getpos(), true)
end,

Works fine.