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

Solved NPC OnCreatureSay Error

Loth Gena

Roxeria 8.60 Developer
Joined
Feb 5, 2014
Messages
245
Reaction score
23
Location
UK
Hi all, using TFS 0.2.8 client 8.62.

I have got a NPC that would recharge a physical ring for some money once used, but when a player goes to the NPC and says "hi" the NPC doesn't respond at all and i get this error in the server log:

Code:
Lua Script Error: [Npc interface]
data/npc/scripts/physical.lua:onCreatureSay

data/npc/lib/npc.lua:46: attempt to perform arithmetic on global 'sx' (a table value)
stack traceback:
data/npc/lib/npc.lua:46: in function 'getDistanceToCreature'
data/npc/scripts/physical.lua:43: in function <data/npc/scripts/physical.lua:33>

Here is my NPC XML FILE:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Physical Ring" script="data/npc/scripts/physical.lua" walkinterval="111" floorchange="0">
    <health now="100" max="100"/>
    <look type="134" head="78" body="88" legs="0" feet="88" addons="3"/>
</npc>

And here is my NPC LUA FILE:
Code:
local focus = 0
local talk_start = 0
local target = 0
local following = false
local attacking = false

function onThingMove(creature, thing, oldpos, oldstackpos)

end

function onCreatureAppear(creature)
end

function onCreatureDisappear(cid, pos)
    if focus == cid then
        selfSay('Good bye then.')
        focus = 0
        talk_start = 0
    end
end


function onCreatureTurn(creature)
    
end


function msgcontains(txt, str)
return (string.find(txt, str) and not string.find(txt, '(%w+)' .. str) and not string.find(txt, str .. '(%w+)'))
end


function onCreatureSay(cid, type, msg)
local player_gold = getPlayerItemCount(cid,2148)
local player_plat = getPlayerItemCount(cid,2152)*100
local player_crys = getPlayerItemCount(cid,2160)*10000
local player_money = player_gold + player_plat + player_crys
local playerCap = getPlayerFreeCap(cid)
local item = 7697 --Ring
local itemweight = getItemWeight(item, 1)
msg = string.lower(msg)

if (msgcontains(msg, 'hi') and (focus == 0)) and getDistanceToCreature(cid) < 4 then
selfSay('Hi. I will refill your physical ring for 50k! Say ring to refill.')
focus = cid
talk_start = os.clock()

elseif msgcontains(msg, 'hi') and (focus ~= cid) and getDistanceToCreature(cid) < 4 then
selfSay('You will have to wait, ' .. getPlayerName(cid) .. '.')

elseif focus == cid then
talk_start = os.clock()

if msgcontains(msg, 'ring') then
if getPlayerItemCount(cid,2258) == 1 and player_money >= 100000 then
doPlayerTakeItem(cid,2258,1)
doPlayerRemoveMoney(cid,50000)
doPlayerAddItem(cid,item,1)
else
selfSay('Please bring with you a physical ring!')
end
end
end
if msgcontains(msg, 'ihhihohohihiohoi') then
if getPlayerStorageValue(cid,21545) == 1 then
selfSay('Good job, you defeated the Demon Oak! Now search for the secret grave!')
setPlayerStorageValue(cid,21545,2)
else
selfSay('Go defeat the demon oak.')
end
end
if msgcontains(msg, 'bye') and getDistanceToCreature(cid) < 4 then
selfSay('Good bye, ' .. getPlayerName(cid) .. '!')
focus = 0
end
end




function onThink()

if (os.clock() - talk_start) > 30 then
if focus > 0 then
selfSay('Next Please...')
end
focus = 0
end
if focus ~= 0 then
if getDistanceToCreature(focus) > 2 then
selfSay('Good bye then.')
focus = 0
end
end
end

Please any help much appreciated, thank you
 
Solution
Code:
   sx, sy, sz = selfGetPosition()
this returns a table value and it's only assigned to sx because of that
you want to use something like
Code:
local pos = selfGetPosition()
local sx, sy, sz = pos.x, pos.y, pos.z
Hi all, using TFS 0.2.8 client 8.62.

I have got a NPC that would recharge a physical ring for some money once used, but when a player goes to the NPC and says "hi" the NPC doesn't respond at all and i get this error in the server log:

Code:
Lua Script Error: [Npc interface]
data/npc/scripts/physical.lua:onCreatureSay

data/npc/lib/npc.lua:46: attempt to perform arithmetic on global 'sx' (a table value)
stack traceback:
data/npc/lib/npc.lua:46: in function 'getDistanceToCreature'
data/npc/scripts/physical.lua:43: in function <data/npc/scripts/physical.lua:33>

Here is my NPC XML FILE:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Physical Ring" script="data/npc/scripts/physical.lua" walkinterval="111" floorchange="0">
    <health now="100" max="100"/>
    <look type="134" head="78" body="88" legs="0" feet="88" addons="3"/>
</npc>

And here is my NPC LUA FILE:
Code:
local focus = 0
local talk_start = 0
local target = 0
local following = false
local attacking = false

function onThingMove(creature, thing, oldpos, oldstackpos)

end

function onCreatureAppear(creature)
end

function onCreatureDisappear(cid, pos)
    if focus == cid then
        selfSay('Good bye then.')
        focus = 0
        talk_start = 0
    end
end


function onCreatureTurn(creature)
 
end


function msgcontains(txt, str)
return (string.find(txt, str) and not string.find(txt, '(%w+)' .. str) and not string.find(txt, str .. '(%w+)'))
end


function onCreatureSay(cid, type, msg)
local player_gold = getPlayerItemCount(cid,2148)
local player_plat = getPlayerItemCount(cid,2152)*100
local player_crys = getPlayerItemCount(cid,2160)*10000
local player_money = player_gold + player_plat + player_crys
local playerCap = getPlayerFreeCap(cid)
local item = 7697 --Ring
local itemweight = getItemWeight(item, 1)
msg = string.lower(msg)

if (msgcontains(msg, 'hi') and (focus == 0)) and getDistanceToCreature(cid) < 4 then
selfSay('Hi. I will refill your physical ring for 50k! Say ring to refill.')
focus = cid
talk_start = os.clock()

elseif msgcontains(msg, 'hi') and (focus ~= cid) and getDistanceToCreature(cid) < 4 then
selfSay('You will have to wait, ' .. getPlayerName(cid) .. '.')

elseif focus == cid then
talk_start = os.clock()

if msgcontains(msg, 'ring') then
if getPlayerItemCount(cid,2258) == 1 and player_money >= 100000 then
doPlayerTakeItem(cid,2258,1)
doPlayerRemoveMoney(cid,50000)
doPlayerAddItem(cid,item,1)
else
selfSay('Please bring with you a physical ring!')
end
end
end
if msgcontains(msg, 'ihhihohohihiohoi') then
if getPlayerStorageValue(cid,21545) == 1 then
selfSay('Good job, you defeated the Demon Oak! Now search for the secret grave!')
setPlayerStorageValue(cid,21545,2)
else
selfSay('Go defeat the demon oak.')
end
end
if msgcontains(msg, 'bye') and getDistanceToCreature(cid) < 4 then
selfSay('Good bye, ' .. getPlayerName(cid) .. '!')
focus = 0
end
end




function onThink()

if (os.clock() - talk_start) > 30 then
if focus > 0 then
selfSay('Next Please...')
end
focus = 0
end
if focus ~= 0 then
if getDistanceToCreature(focus) > 2 then
selfSay('Good bye then.')
focus = 0
end
end
end

Please any help much appreciated, thank you

try change:
Code:
if (msgcontains(msg, 'hi') and (focus == 0)) and getDistanceToCreature(cid) < 4 then
and
elseif msgcontains(msg, 'hi') and (focus ~= cid) and getDistanceToCreature(cid) < 4 then

to:
Code:
if (msgcontains(msg, 'hi') and (focus == 0)) then
and
elseif msgcontains(msg, 'hi') and (focus ~= cid) then

then the problem is finding the distance to the player/npc

edit: can u post the lib/npc.lua aswell
 
So i edited what you said, now the NPC responds to the player, but still moves around and doesn't face towards the player. Also my server log keeps spamming this error:
Code:
[02/01/2017 00:21:15] Lua Script Error: [Npc interface]
[02/01/2017 00:21:15] data/npc/scripts/physical.lua:onThink

[02/01/2017 00:21:15] data/npc/lib/npc.lua:46: attempt to perform arithmetic on global 'sx' (a table value)
[02/01/2017 00:21:15] stack traceback:
[02/01/2017 00:21:15]     data/npc/lib/npc.lua:46: in function 'getDistanceToCreature'
[02/01/2017 00:21:15]     data/npc/scripts/physical.lua:90: in function <data/npc/scripts/physical.lua:81>

My NPC.LUA FILE:
Code:
-- Including the Advanced NPC System
dofile('data/npc/lib/npcsystem/npcsystem.lua')

do
    doPlayerAddStackable = doPlayerAddItem
    --Returns table with UIDs of added items
    doPlayerAddItem = function(cid, itemid, amount, subType)
        local amount = amount or 1
        local subAmount = 0
        local subType = subType or 0

        if(isItemStackable(itemid) == TRUE) then
            return doPlayerAddStackable(cid, itemid, amount), amount
        end

        local items = {}
        local ret = 0
        local a = 0
        for i = 1, amount do
            items[i] = doCreateItemEx(itemid, subType)
            ret = doPlayerAddItemEx(cid, items[i], 1)
            if(ret ~= RETURNVALUE_NOERROR) then
                break
            end
            a = a + 1
        end

        return items, a
    end
end

function getDistanceToCreature(id)
    if id == 0 or id == nil then
        selfGotoIdle()
    end

    local creaturePosition = getCreaturePosition(id)
    cx = creaturePosition.x
    cy = creaturePosition.y
    cz = creaturePosition.z
    if cx == nil then
        return nil
    end

    sx, sy, sz = selfGetPosition()
    return math.max(math.abs(sx - cx), math.abs(sy - cy))
end

function moveToPosition(x,y,z)
    selfMoveTo(x, y, z)
end

function moveToCreature(id)
    if id == 0 or id == nil then
        selfGotoIdle()
    end

    tx, ty, tz = getCreaturePosition(id)
    if tx == nil then
        selfGotoIdle()
    else
        moveToPosition(tx, ty, tz)
    end
end

function selfGotoIdle()
    following = false
    attacking = false
    selfAttackCreature(0)
    target = 0
end

function isPlayerPremiumCallback(cid)
    return isPremium(cid) == TRUE and true or false
end

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 selfSayChannel(cid, message)
    return selfSay(message, cid, FALSE)
end

function doPosRemoveItem(_itemid, n, position)
    local thing = getThingfromPos({x = position.x, y = position.y, z = position.z, stackpos = 1})
    if thing.itemid == _itemid then
        doRemoveItem(thing.uid, n)
    else
        return false
    end
    return true
end
 
Code:
   sx, sy, sz = selfGetPosition()
this returns a table value and it's only assigned to sx because of that
you want to use something like
Code:
local pos = selfGetPosition()
local sx, sy, sz = pos.x, pos.y, pos.z
 
Solution
Code:
   sx, sy, sz = selfGetPosition()
this returns a table value and it's only assigned to sx because of that
you want to use something like
Code:
local pos = selfGetPosition()
local sx, sy, sz = pos.x, pos.y, pos.z

This worked, Thank you!
 
Back
Top