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

Lua NPC responds only after reload

LeOnArd0

Member
Joined
Jan 24, 2010
Messages
76
Reaction score
14
Hi guys!

Distro: TFS 1.5


I have a weird problem with some npcs.

After restarting the server, they simply don't respond, but I just have to /reload npcs and they respond again. I've already tried using the exact same script as one of the NPCs that respond and it still doesn't respond o_O

The worst thing is that this happens to some npcs only, not everyone.

Does anyone know what can it be?

215t8fo.gif


Because in theory, after the server restart, the reload would have already been given to the npcs, correct?

Lua:
-- Including the Advanced NPC System
dofile('data/npc/lib/npcsystem/npcsystem.lua')

function msgcontains(message, keyword)
    local message, keyword = message:lower(), keyword:lower()
    if message == keyword then
        return true
    end

    return message:find(keyword) and not message:find('(%w+)' .. keyword)
end

function doNpcSellItem(cid, itemid, amount, subType, ignoreCap, inBackpacks, backpack)
    local amount = amount or 1
    local subType = subType or 0
    local item = 0
    if ItemType(itemid):isStackable() then
        if inBackpacks then
            stuff = Game.createItem(backpack, 1)
            item = stuff:addItem(itemid, math.min(100, amount))
        else
            stuff = Game.createItem(itemid, math.min(100, amount))
        end
        return Player(cid):addItemEx(stuff, ignoreCap) ~= RETURNVALUE_NOERROR and 0 or amount, 0
    end

    local a = 0
    if inBackpacks then
        local container, b = Game.createItem(backpack, 1), 1
        for i = 1, amount do
            local item = container:addItem(itemid, subType)
            if table.contains({(ItemType(backpack):getCapacity() * b), amount}, i) then
                if Player(cid):addItemEx(container, ignoreCap) ~= RETURNVALUE_NOERROR then
                    b = b - 1
                    break
                end

                a = i
                if amount > i then
                    container = Game.createItem(backpack, 1)
                    b = b + 1
                end
            end
        end
        return a, b
    end

    for i = 1, amount do -- normal method for non-stackable items
        local item = Game.createItem(itemid, subType)
        if Player(cid):addItemEx(item, ignoreCap) ~= RETURNVALUE_NOERROR then
            break
        end
        a = i
    end
    return a, 0
end

local func = function(cid, text, type, e, pcid)
    if Player(pcid):isPlayer() then
        local creature = Creature(cid)
        creature:say(text, type, false, pcid, creature:getPosition())
        e.done = true
    end
end

function doCreatureSayWithDelay(cid, text, type, delay, e, pcid)
    if Player(pcid):isPlayer() then
        e.done = false
        e.event = addEvent(func, delay < 1 and 1000 or delay, cid, text, type, e, pcid)
    end
end

function doPlayerSellItem(cid, itemid, count, cost)
    local player = Player(cid)
    if player:removeItem(itemid, count) then
        if not player:addMoney(cost) then
            error('Could not add money to ' .. player:getName() .. '(' .. cost .. 'gp)')
        end
        return true
    end
    return false
end

function doPlayerBuyItemContainer(cid, containerid, itemid, count, cost, charges)
    local player = Player(cid)
    if not player:removeTotalMoney(cost) then
        return false
    end

    for i = 1, count do
        local container = Game.createItem(containerid, 1)
        for x = 1, ItemType(containerid):getCapacity() do
            container:addItem(itemid, charges)
        end

        if player:addItemEx(container, true) ~= RETURNVALUE_NOERROR then
            return false
        end
    end
    return true
end

function getCount(string)
    local b, e = string:find("%d+")
    local tonumber = tonumber(string:sub(b, e))
    if tonumber > 2 ^ 32 - 1 then
        print("Warning: Casting value to 32bit to prevent crash\n"..debug.traceback())
    end
    return b and e and math.min(2 ^ 32 - 1, tonumber) or -1
end

function Player.getTotalMoney(self)
    return self:getMoney() + self:getBankBalance()
end

function isValidMoney(money)
    return isNumber(money) and money > 0
end

function getMoneyCount(string)
    local b, e = string:find("%d+")
    local tonumber = tonumber(string:sub(b, e))
    if tonumber > 2 ^ 32 - 1 then
        print("Warning: Casting value to 32bit to prevent crash\n"..debug.traceback())
    end
    local money = b and e and math.min(2 ^ 32 - 1, tonumber) or -1
    if isValidMoney(money) then
        return money
    end
    return -1
end

function getMoneyWeight(money)
    local weight, currencyItems = 0, Game.getCurrencyItems()
    for index = #currencyItems, 1, -1 do
        local currency = currencyItems[index]
        local worth = currency:getWorth()
        local currencyCoins = math.floor(money / worth)
        if currencyCoins > 0 then
            money = money - (currencyCoins * worth)
            weight = weight + currency:getWeight(currencyCoins)
        end
    end
    return weight
end

Lua:
-- Advanced NPC System by Jiddo

shop_amount = {}
shop_cost = {}
shop_rlname = {}
shop_itemid = {}
shop_container = {}
shop_npcuid = {}
shop_eventtype = {}
shop_subtype = {}
shop_destination = {}
shop_premium = {}

npcs_loaded_shop = {}
npcs_loaded_travel = {}

if not NpcSystem then
    -- Loads the underlying classes of the npcsystem.
    dofile('data/npc/lib/npcsystem/keywordhandler.lua')
    dofile('data/npc/lib/npcsystem/npchandler.lua')
    dofile('data/npc/lib/npcsystem/modules.lua')

    -- Global npc constants:

    -- Greeting and unGreeting keywords. For more information look at the top of modules.lua
    FOCUS_GREETWORDS = {'hi', 'hello'}
    FOCUS_FAREWELLWORDS = {'bye', 'farewell'}

    -- The word for requesting trade window. For more information look at the top of modules.lua
    SHOP_TRADEREQUEST = {'trade'}

    -- The word for accepting/declining an offer. CAN ONLY CONTAIN ONE FIELD! For more information look at the top of modules.lua
    SHOP_YESWORD = {'yes'}
    SHOP_NOWORD = {'no'}

    -- Pattern used to get the amount of an item a player wants to buy/sell.
    PATTERN_COUNT = '%d+'

    -- Talkdelay behavior. For more information, look at the top of npchandler.lua.
    NPCHANDLER_TALKDELAY = TALKDELAY_NONE

    -- Constant strings defining the keywords to replace in the default messages.
    --    For more information, look at the top of npchandler.lua...
    TAG_PLAYERNAME = '|PLAYERNAME|'
    TAG_ITEMCOUNT = '|ITEMCOUNT|'
    TAG_TOTALCOST = '|TOTALCOST|'
    TAG_ITEMNAME = '|ITEMNAME|'

    NpcSystem = {}

    -- Gets an npcparameter with the specified key. Returns nil if no such parameter is found.
    function NpcSystem.getParameter(key)
        local ret = getNpcParameter(tostring(key))
        if (type(ret) == 'number' and ret == 0) then
            return nil
        else
            return ret
        end
    end

    -- Parses all known parameters for the npc. Also parses parseable modules.
    function NpcSystem.parseParameters(npcHandler)
        local ret = NpcSystem.getParameter('idletime')
        if ret then
            npcHandler.idleTime = tonumber(ret)
        end
        local ret = NpcSystem.getParameter('talkradius')
        if ret then
            npcHandler.talkRadius = tonumber(ret)
        end
        local ret = NpcSystem.getParameter('message_greet')
        if ret then
            npcHandler:setMessage(MESSAGE_GREET, ret)
        end
        local ret = NpcSystem.getParameter('message_farewell')
        if ret then
            npcHandler:setMessage(MESSAGE_FAREWELL, ret)
        end
        local ret = NpcSystem.getParameter('message_decline')
        if ret then
            npcHandler:setMessage(MESSAGE_DECLINE, ret)
        end
        local ret = NpcSystem.getParameter('message_needmorespace')
        if ret then
            npcHandler:setMessage(MESSAGE_NEEDMORESPACE, ret)
        end
        local ret = NpcSystem.getParameter('message_needspace')
        if ret then
            npcHandler:setMessage(MESSAGE_NEEDSPACE, ret)
        end
        local ret = NpcSystem.getParameter('message_sendtrade')
        if ret then
            npcHandler:setMessage(MESSAGE_SENDTRADE, ret)
        end
        local ret = NpcSystem.getParameter('message_noshop')
        if ret then
            npcHandler:setMessage(MESSAGE_NOSHOP, ret)
        end
        local ret = NpcSystem.getParameter('message_oncloseshop')
        if ret then
            npcHandler:setMessage(MESSAGE_ONCLOSESHOP, ret)
        end
        local ret = NpcSystem.getParameter('message_onbuy')
        if ret then
            npcHandler:setMessage(MESSAGE_ONBUY, ret)
        end
        local ret = NpcSystem.getParameter('message_onsell')
        if ret then
            npcHandler:setMessage(MESSAGE_ONSELL, ret)
        end
        local ret = NpcSystem.getParameter('message_missingmoney')
        if ret then
            npcHandler:setMessage(MESSAGE_MISSINGMONEY, ret)
        end
        local ret = NpcSystem.getParameter('message_needmoney')
        if ret then
            npcHandler:setMessage(MESSAGE_NEEDMONEY, ret)
        end
        local ret = NpcSystem.getParameter('message_missingitem')
        if ret then
            npcHandler:setMessage(MESSAGE_MISSINGITEM, ret)
        end
        local ret = NpcSystem.getParameter('message_needitem')
        if ret then
            npcHandler:setMessage(MESSAGE_NEEDITEM, ret)
        end
        local ret = NpcSystem.getParameter('message_idletimeout')
        if ret then
            npcHandler:setMessage(MESSAGE_IDLETIMEOUT, ret)
        end
        local ret = NpcSystem.getParameter('message_walkaway')
        if ret then
            npcHandler:setMessage(MESSAGE_WALKAWAY, ret)
        end
        local ret = NpcSystem.getParameter('message_alreadyfocused')
        if ret then
            npcHandler:setMessage(MESSAGE_ALREADYFOCUSED, ret)
        end
        local ret = NpcSystem.getParameter('message_buy')
        if ret then
            npcHandler:setMessage(MESSAGE_BUY, ret)
        end
        local ret = NpcSystem.getParameter('message_sell')
        if ret then
            npcHandler:setMessage(MESSAGE_SELL, ret)
        end
        local ret = NpcSystem.getParameter('message_bought')
        if ret then
            npcHandler:setMessage(MESSAGE_BOUGHT, ret)
        end
        local ret = NpcSystem.getParameter('message_sold')
        if ret then
            npcHandler:setMessage(MESSAGE_SOLD, ret)
        end
        local ret = NpcSystem.getParameter('message_walkaway_male')
        if ret then
            npcHandler:setMessage(MESSAGE_WALKAWAY_MALE, ret)
        end
        local ret = NpcSystem.getParameter('message_walkaway_female')
        if ret then
            npcHandler:setMessage(MESSAGE_WALKAWAY_FEMALE, ret)
        end

        -- Parse modules.
        for parameter, module in pairs(Modules.parseableModules) do
            local ret = NpcSystem.getParameter(parameter)
            if ret then
                local number = tonumber(ret)
                if number ~= 0 and module.parseParameters then
                    local instance = module:new()
                    npcHandler:addModule(instance)
                    instance:parseParameters()
                end
            end
        end
    end
end

Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Lector" script="default.lua" walkinterval="2000" access="3" floorchange="0">
    <health now="100" max="100"/>
    <look type="128" head="79" body="38" legs="0" feet="124" addons="0"/>
    <parameters>
  
        <parameter key="message_greet" value="Welcome to my humble meat shop, |PLAYERNAME|."/>
        <parameter key="message_farewell" value="Please come and buy again, |PLAYERNAME|."/>
        <parameter key="message_sendtrade" value="Of course, take a good look at my meat."/>
        <parameter key="module_keywords" value="1" />
        <parameter key="keywords" value="name;job;offer;" />
        <parameter key="keyword_reply1" value="My father named me Lector." />
        <parameter key="keyword_reply2" value="I am the butcher. I am selling delicious meat." />
        <parameter key="keyword_reply3" value="I can offer you ham or meat." />

        <parameter key="module_shop" value="1"/>
        <parameter key="shop_buyable" value="ham,2671,6;meat,2666,3;" />
        <parameter key="shop_sellable" value="" />
    </parameters>
</npc>

Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

-- OTServ event handling functions start
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
-- OTServ event handling functions end

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

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

Thank you and anyone who can give me a light with this.

At.
Leo
 
Last edited:
I took a new test and there really is something very strange.

I put an npc on the top floor (z=6) and he responds normally after opening the server.

Only the floor npc (z=7) does not respond.

c6e4c3f083039b25d0d0f7fce9fdcaf6.gif

I've tried deleting the below and applying it again, but to no avail.
 
Last edited:
Back
Top