hkzorman / advanced_npc

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

Erro: Index field 'actions' (a nil value) #20

Closed BrunoMine closed 6 years ago

BrunoMine commented 6 years ago

I do not know if I'm doing this correctly, I just tried to follow what the documentation says.

My npc do_custom:

do_custom = function(self, dtime)
        if not self.testou and minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}) then
            self.testou = 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.cmd.LAY,
            })
        end
    end,

This is what happens when I put a bed next to it.

2017-10-07 19:23:32: ERROR[Main]: ServerError: AsyncErr: ServerThread::run Lua: Runtime error from mod 'mobs_npc' in callback luaentity_Step(): ...ods/minetest_0-4-16/bin/../mods/advanced_npc/npc.lua:731: attempt to index field 'actions' (a nil value)
2017-10-07 19:23:32: ERROR[Main]: stack traceback:
2017-10-07 19:23:32: ERROR[Main]:   ...ods/minetest_0-4-16/bin/../mods/advanced_npc/npc.lua:731: in function 'add_task'
2017-10-07 19:23:32: ERROR[Main]:   ...e Mods/minetest_0-4-16/bin/../mods/mobs_npc/igor.lua:115: in function 'do_custom'
2017-10-07 19:23:32: ERROR[Main]:   ...e Mods/minetest_0-4-16/bin/../mods/mobs_redo/api.lua:2573: in function <...e Mods/minetest_0-4-16/bin/../mods/mobs_redo/api.lua:2515>
hkzorman commented 6 years ago

I think your NPC has to be initialized. When spawning your NPC, do npc.initialize(). You can also do it from the do_custom(). This is an example:

if self.initialized == nil then
    npc.initialize(self, self.object:getpos(), true)
    self.tamed = false
    self.owner = nil
end
BrunoMine commented 6 years ago

Okay, but he not lay.

do_custom = function(self, dtime)   

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

    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.cmd.LAY,
        })
    end
end,
hkzorman commented 6 years ago

The action is not correct. Task arguments should be:

args = {
         pos = npc.places.PLACE_TYPE.BED.PRIMARY,
          action = npc.actions.const.beds.LAY
}
hkzorman commented 6 years ago

You can refer to data/occupations/default.lua for example actions and tasks

BrunoMine commented 6 years ago

The code still does not work, but I'm a bit confused by it.

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

    -- Lay in the bed
    if not self.tested then
        self.tested = true
        npc.add_task(self, npc.actions.cmd.USE_BED, {
            pos = npc.places.PLACE_TYPE.BED.PRIMARY,
            action = npc.actions.const.beds.LAY,
        })
    end
end,

pos should be a position of bed to be used (wiki), but it's a string. So where the coordinate is set?

hkzorman commented 6 years ago

It can receive a string (this is set when NPC is spawned using the spawn egg or the auto spawn), a position table, or a table with other data. Your previous code was good, you only needed this: action = npc.actions.const.beds.LAY instead of: action = npc.actions.cmd.LAY

BrunoMine commented 6 years ago

Are you referring to this? Not work. I had tried that too. Maybe it's some API error. No error message is displayed.

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
    -- 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,
        })
    end
end,
hkzorman commented 6 years ago

What does minetest.find_node_near(self.object:getpos(), 3, {"beds:bed_bottom"}) returns? Is it a single node?

BrunoMine commented 6 years ago

Yes, or nil if not find. EDIT: It is a position/coordinate {x,y,z}

hkzorman commented 6 years ago

I got it! I have missed all the time that you are not using the normal do_custom() that the NPC has defined in npc.lua.

At the very least you need to add this to your do_custom():

-- 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

All of those variables should be defined after initialization.

BrunoMine commented 6 years ago

Now it works fine, I'm beginning to understand API mechanics , but it still needs a lot of documentation. I will discuss issues related to documentation in the future.

hkzorman commented 6 years ago

Agreed, documentation is very lacking. I truly need to work on it. Thanks for your patience!