• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.X+ attempt to call method getId

peteralto

Member
Joined
Nov 1, 2020
Messages
93
Solutions
1
Reaction score
17
I tried to use/adapt the code from an NPC from the Canary base, but in TFS 1.3+ it is giving the following errors:

Code:
Lua Script Error: [Npc interface]
data/npc/scripts/Maeryn.lua:onCreatureSay
data/npc/scripts/Maeryn.lua:25: attempt to call method 'getId' (a nil value)
stack traceback:
    [C]: in function 'getId'
    data/npc/scripts/Maeryn.lua:25: in function 'callback'
    data/npc/lib/npcsystem/npchandler.lua:358: in function 'greet'
    data/npc/lib/npcsystem/npchandler.lua:557: in function 'onGreet'
    data/npc/lib/npcsystem/modules.lua:335: in function 'callback'
    data/npc/lib/npcsystem/keywordhandler.lua:31: in function 'processMessage'
    data/npc/lib/npcsystem/keywordhandler.lua:186: in function 'processNodeMessage'
    data/npc/lib/npcsystem/keywordhandler.lua:154: in function 'processMessage'
    data/npc/lib/npcsystem/npchandler.lua:432: in function 'onCreatureSay'
    data/npc/scripts/Maeryn.lua:7: in function <data/npc/scripts/Maeryn.lua:7>

Lua Script Error: [Npc interface]
data/npc/scripts/Maeryn.lua:onCreatureSay
data/npc/scripts/Maeryn.lua:32: attempt to index local 'player' (a nil value)
stack traceback:
    [C]: in function '__index'
    data/npc/scripts/Maeryn.lua:32: in function 'callback'
    data/npc/lib/npcsystem/npchandler.lua:435: in function 'onCreatureSay'
    data/npc/scripts/Maeryn.lua:7: in function <data/npc/scripts/Maeryn.lua:7>

Script.lua
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)        npcHandler:onCreatureDisappear(cid)            end
function onCreatureSay(cid, type, msg)        npcHandler:onCreatureSay(cid, type, msg)        end
function onThink()                npcHandler:onThink()                    end


local vocations = {
    ['sorcerer'] = 0,
    ['druid'] = 1,
    ['paladin'] = 2,
    ['knight'] = {
        ['club'] = 3,
        ['axe'] = 4,
        ['sword'] = 5,
    }
}

local knightChoice = {}

local function greetCallback(npc, creature)
    local playerId = creature:getId()
    knightChoice[playerId] = nil
    return true
end

local function creatureSayCallback(npc, creature, type, message)
    local player = Player(creature)
    local playerId = player:getId()

    if MsgContains(message, 'helmet') then
        npcHandler:say("You brought the wolven helmet, as i see. Do you want to change something?", npc, creature)
        npcHandler:setTopic(playerId, 1)
    elseif MsgContains(message, 'yes') then
        if npcHandler:getTopic(playerId) == 1 then
            npcHandler:say("So, which profession would you give preference to when enchanting the helmet: {knight}, {sorcerer}, {druid} or {paladin}?", npc, creature)
            npcHandler:setTopic(playerId, 2)
        end
    elseif isInArray({'knight', 'sorcerer', 'druid', 'paladin'}, message:lower()) and npcHandler:getTopic(playerId) == 2 then
        local helmet = message:lower()
        if not vocations[helmet] then
            return false
        end
        if message:lower() == 'knight' then
            npcHandler:say("And what would be your preferred weapon? {Club}, {axe} or {sword}", npc, creature)
            knightChoice[playerId] = helmet
            npcHandler:setTopic(playerId, 3)
        end
        if npcHandler:getTopic(playerId) == 2 then
            player:setStorageValue(Storage.Grimvale.WereHelmetEnchant, vocations[helmet])
            npcHandler:say("So this is your choice. If you want to change it, you will have to come to me again.", npc, creature)
            npcHandler:setTopic(playerId, 0)
        end
    elseif isInArray({'axe', 'club', 'sword'}, message:lower()) and npcHandler:getTopic(playerId) == 3 then
        local weapontype = message:lower()
        if not vocations[knightChoice[playerId]][weapontype] then
            return false
        else
            player:setStorageValue(Storage.Grimvale.WereHelmetEnchant, vocations[knightChoice[playerId]][weapontype])
            npcHandler:say("So this is your choice. If you want to change it, you will have to come to me again.", npc, creature)
            knightChoice[playerId] = nil
            npcHandler:setTopic(playerId, 0)
        end
    end
end

npcHandler:setMessage(MESSAGE_GREET, "Greetings, visitor. I wonder what may lead you to this dangerous place.")
npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
 
Solution
ok..
npc.lua
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}

function onCreatureAppear(cid)
    npcHandler:onCreatureAppear(cid)
end

function onCreatureDisappear(cid)
    npcHandler:onCreatureDisappear(cid)
end

function onCreatureSay(cid, type, msg)
    npcHandler:onCreatureSay(cid, type, msg)
end

function onThink()
    npcHandler:onThink()
end

local vocations = {
    ['sorcerer'] = 0,
    ['druid'] = 1,
    ['paladin'] = 2,
    ['knight'] = {
        ['club'] = 3,
        ['axe'] = 4,
        ['sword'] = 5,
    }
}

local knightChoice = {}

local function creatureSayCallback(cid, type, msg)
    if not...
So, you tried to adapt it for this NPC that is supposed to enchant items with each vocation, right? I didn't quite understand this NPC. Could you explain its purpose to me until I understand it, and I can adapt it correctly for you?
 
So, you tried to adapt it for this NPC that is supposed to enchant items with each vocation, right? I didn't quite understand this NPC. Could you explain its purpose to me until I understand it, and I can adapt it correctly for you?
This NPC works together with an item called moonlight crystal, used to enchant werewolf items. The crystal works in a parallel script.
When speaking to the NPC, the player chooses which enchantment he wants, and the NPC set the respective storage to the enchantment.

Here is the moonlight crystal script:

Lua:
local moonlightCrystals = Action()

function moonlightCrystals.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if target.itemid == 24716 then
        target:transform(24717)
        item:remove(1)
        return true
    elseif target.itemid == 24718 then
        if (player:getStorageValue(Storage.Grimvale.WereHelmetEnchant) == 0) or (player:getStorageValue(Storage.Grimvale.WereHelmetEnchant) == 1) then
            target:transform(24771) -- Magic level helmet
            item:remove(1)
        elseif player:getStorageValue(Storage.Grimvale.WereHelmetEnchant) == 2 then
            target:transform(24770) -- Paladin helmet
            item:remove(1)
        elseif player:getStorageValue(Storage.Grimvale.WereHelmetEnchant) == 3 then
            target:transform(24769) -- Knight club
            item:remove(1)
        elseif player:getStorageValue(Storage.Grimvale.WereHelmetEnchant) == 4 then
            target:transform(24744) -- Knight axe
            item:remove(1)
        elseif player:getStorageValue(Storage.Grimvale.WereHelmetEnchant) == 5 then
            target:transform(24772) -- Knight sword
            item:remove(1)
        else
            return false
        end
        return true
    end
    return false
end

moonlightCrystals:id(24739)
moonlightCrystals:register()
 
ok..
npc.lua
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}

function onCreatureAppear(cid)
    npcHandler:onCreatureAppear(cid)
end

function onCreatureDisappear(cid)
    npcHandler:onCreatureDisappear(cid)
end

function onCreatureSay(cid, type, msg)
    npcHandler:onCreatureSay(cid, type, msg)
end

function onThink()
    npcHandler:onThink()
end

local vocations = {
    ['sorcerer'] = 0,
    ['druid'] = 1,
    ['paladin'] = 2,
    ['knight'] = {
        ['club'] = 3,
        ['axe'] = 4,
        ['sword'] = 5,
    }
}

local knightChoice = {}

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)

    if msgcontains(msg, 'helmet') then
        selfSay('You brought the wolven helmet, as I see. Do you want to change something?', cid)
        talkState[cid] = 1
    elseif talkState[cid] == 1 and msgcontains(msg, 'yes') then
        selfSay("So, which profession would you give preference to when enchanting the helmet: {knight}, {sorcerer}, {druid} or {paladin}?", cid)
        talkState[cid] = 2
    elseif talkState[cid] == 2 and isInArray({'knight', 'sorcerer', 'druid', 'paladin'}, msg:lower()) then
        local helmet = msg:lower()
        if not vocations[helmet] then
            return false
        end

        local enchantmentValue
        if helmet == 'knight' then
            selfSay("And what would be your preferred weapon? {Club}, {axe} or {sword}", cid)
            knightChoice[cid] = helmet
            talkState[cid] = 3
        else
            enchantmentValue = vocations[helmet]
            selfSay("So this is your choice. If you want to change it, you will have to come to me again.", cid)
            talkState[cid] = 0
        end
        player:setStorageValue(Storage.Grimvale.WereHelmetEnchant, enchantmentValue)
    elseif talkState[cid] == 3 and isInArray({'Club', 'Axe', 'Sword'}, msg:lower()) then
        local weapontype = msg:lower()
        if not vocations[knightChoice[cid]][weapontype] then
            return false
        else
            local enchantmentValue = vocations[knightChoice[cid]][weapontype]
            selfSay("So this is your choice. If you want to change it, you will have to come to me again.", cid)
            knightChoice[cid] = nil
            talkState[cid] = 0
            player:setStorageValue(Storage.Grimvale.WereHelmetEnchant, enchantmentValue)
        end
    end

    return true
end

npcHandler:setMessage(MESSAGE_GREET, "Greetings, visitor. I wonder what may lead you to this dangerous place.")
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

moonlight crystal.lua
Lua:
local moonlightCrystals = Action()

function moonlightCrystals.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if target.itemid == 24716 then
        target:transform(24717)
        player:getPosition():sendMagicEffect(40)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Item enchanted successfully.')
        item:remove(1)
        return true
    elseif target.itemid == 24718 then
        local enchantmentLevel = player:getStorageValue(Storage.Grimvale.WereHelmetEnchant)

        if enchantmentLevel >= 0 and enchantmentLevel <= 5 then
            local transformedItemId = {
                24771, -- Magic level helmet
                24770, -- Paladin helmet
                24769, -- Knight club
                24744, -- Knight axe
                24772  -- Knight sword
            }

            target:transform(transformedItemId[enchantmentLevel + 1])
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Item enchanted successfully.')
            item:remove(1)
            return true
        else
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Unable to enchant this item.')
            player:getPosition():sendMagicEffect(CONST_ME_POFF)
            return false
        end
    end

    return false
end

moonlightCrystals:id(24739)
moonlightCrystals:register()
 
Solution
ok..
npc.lua
Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
local talkState = {}

function onCreatureAppear(cid)
    npcHandler:onCreatureAppear(cid)
end

function onCreatureDisappear(cid)
    npcHandler:onCreatureDisappear(cid)
end

function onCreatureSay(cid, type, msg)
    npcHandler:onCreatureSay(cid, type, msg)
end

function onThink()
    npcHandler:onThink()
end

local vocations = {
    ['sorcerer'] = 0,
    ['druid'] = 1,
    ['paladin'] = 2,
    ['knight'] = {
        ['club'] = 3,
        ['axe'] = 4,
        ['sword'] = 5,
    }
}

local knightChoice = {}

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end

    local player = Player(cid)

    if msgcontains(msg, 'helmet') then
        selfSay('You brought the wolven helmet, as I see. Do you want to change something?', cid)
        talkState[cid] = 1
    elseif talkState[cid] == 1 and msgcontains(msg, 'yes') then
        selfSay("So, which profession would you give preference to when enchanting the helmet: {knight}, {sorcerer}, {druid} or {paladin}?", cid)
        talkState[cid] = 2
    elseif talkState[cid] == 2 and isInArray({'knight', 'sorcerer', 'druid', 'paladin'}, msg:lower()) then
        local helmet = msg:lower()
        if not vocations[helmet] then
            return false
        end

        local enchantmentValue
        if helmet == 'knight' then
            selfSay("And what would be your preferred weapon? {Club}, {axe} or {sword}", cid)
            knightChoice[cid] = helmet
            talkState[cid] = 3
        else
            enchantmentValue = vocations[helmet]
            selfSay("So this is your choice. If you want to change it, you will have to come to me again.", cid)
            talkState[cid] = 0
        end
        player:setStorageValue(Storage.Grimvale.WereHelmetEnchant, enchantmentValue)
    elseif talkState[cid] == 3 and isInArray({'Club', 'Axe', 'Sword'}, msg:lower()) then
        local weapontype = msg:lower()
        if not vocations[knightChoice[cid]][weapontype] then
            return false
        else
            local enchantmentValue = vocations[knightChoice[cid]][weapontype]
            selfSay("So this is your choice. If you want to change it, you will have to come to me again.", cid)
            knightChoice[cid] = nil
            talkState[cid] = 0
            player:setStorageValue(Storage.Grimvale.WereHelmetEnchant, enchantmentValue)
        end
    end

    return true
end

npcHandler:setMessage(MESSAGE_GREET, "Greetings, visitor. I wonder what may lead you to this dangerous place.")
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

moonlight crystal.lua
Lua:
local moonlightCrystals = Action()

function moonlightCrystals.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if target.itemid == 24716 then
        target:transform(24717)
        player:getPosition():sendMagicEffect(40)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Item enchanted successfully.')
        item:remove(1)
        return true
    elseif target.itemid == 24718 then
        local enchantmentLevel = player:getStorageValue(Storage.Grimvale.WereHelmetEnchant)

        if enchantmentLevel >= 0 and enchantmentLevel <= 5 then
            local transformedItemId = {
                24771, -- Magic level helmet
                24770, -- Paladin helmet
                24769, -- Knight club
                24744, -- Knight axe
                24772  -- Knight sword
            }

            target:transform(transformedItemId[enchantmentLevel + 1])
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Item enchanted successfully.')
            item:remove(1)
            return true
        else
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Unable to enchant this item.')
            player:getPosition():sendMagicEffect(CONST_ME_POFF)
            return false
        end
    end

    return false
end

moonlightCrystals:id(24739)
moonlightCrystals:register()
Thank you!
 
Back
Top