• 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+ Kill task error in function onKill

Unknown Soldier

Mapping a map
Joined
Oct 30, 2010
Messages
297
Solutions
11
Reaction score
670
Hello,

I am out if ideas so decided to ask. TFS 1.4.2

While doing a task, ocasionally console error shows up

Code:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/killtasks.lua:onKill
data/creaturescripts/scripts/killtasks.lua:24: attempt to index local 'monster' (a nil value)
stack traceback:
        [C]: in function '__index'
        data/creaturescripts/scripts/killtasks.lua:24: in function <data/creaturescripts/scripts/killtasks.lua:10>

And I guess it might be related to monster summons, the script is trying to find a monster, but cannot, even though I did a check at the beginning not target:getMaster(). What am I missing here?

Thanks in advance!

Lua:
local config = {
     ['necromancer'] = {name ="Necromancer", amount = 12, storage = 19004, startstorage = 5014, startvalue = 1, storageCorr= 5114},
     ['vampire'] = {name ="Vampire", amount = 15, storage = 19005, startstorage = 5015, startvalue = 1, storageCorr= 5115},
     ['hellspawn'] = {name ="Hellspawn", amount = 10, storage = 19006, startstorage = 5016, startvalue = 1, storageCorr= 5116},
     ['wyrm'] = {name = "Wyrm", amount = 10, storage = 19007, startstorage = 5017, startvalue = 1, storageCorr= 5117},
     ['elder wyrm'] = {name ="Wyrm", amount = 10, storage = 19007, startstorage = 5017, startvalue = 1, storageCorr= 5117},
     ['sea serpent'] = {name ="Sea Serpent", amount = 10, storage = 19008, startstorage = 5018, startvalue = 1, storageCorr = 5118},
}

function onKill(creature, target)
    if creature:isPlayer() and target:isMonster() and not target:getMaster() then
        local party = creature:getParty()
        local members = {}
       
        if party then
            members = party:getMembers()
            table.insert(members, party:getLeader())
        else
            members = {creature}
        end
       
        for _, member in pairs(members) do
            local monster = config[target:getName():lower()]
            local stor = member:getStorageValue(monster.storage)+1 --sometimes it gives error here, related to monster summons?
             if stor < monster.amount and member:getStorageValue(monster.startstorage) >= monster.startvalue then
                 member:setStorageValue(monster.storage, stor)
                 local textName = ''..monster.name..' task: Already killed '..(stor +1)..' of '..monster.amount..' creatures.'
                 member:openChannel(10)
                 member:sendChannelMessage('', textName, TALKTYPE_CHANNEL_O, 10)
             end          
             if (stor +1) == monster.amount then
                local finaltext = ''..target:getName()..' task: Congratulations, you have completed the task killing '..monster.amount..' creatures.'
                 member:sendTextMessage(MESSAGE_EVENT_ADVANCE, finaltext)
                 member:sendChannelMessage('', finaltext, TALKTYPE_CHANNEL_R1, 10)
                 member:setStorageValue(monster.storage, monster.amount)
                 member:setStorageValue(monster.storageCorr, 2)
             end
        end
    end
     return true
end

@edit
Damn, I am a spammer.
Additional check helped:
if monster then
after local monster
Whatever...
 
Last edited:
heyo,
Lua:
local monster = config[target:getName():lower()]
this pointing to table like config["necromancer"] if any monster will be killed and he is not in that list it will return nil, simple check if "monster" check exsists will fix it

nvm i am blind, i see ure solved it already.
 
Here, this part is correct!
Lua:
local monsterConfig = config[target:getName():lower()]

        if monsterConfig then
            for _, member in pairs(members) do
                local stor = member:getStorageValue(monsterConfig.storage) + 1

                if stor < monsterConfig.amount and member:getStorageValue(monsterConfig.startstorage) >= monsterConfig.startvalue then
                    member:setStorageValue(monsterConfig.storage, stor)
                    local textName = '' .. monsterConfig.name .. ' task: Already killed ' .. (stor + 1) .. ' of ' .. monsterConfig.amount .. ' creatures.'
                    member:openChannel(10)
                    member:sendChannelMessage('', textName, TALKTYPE_CHANNEL_O, 10)
                end
 
It's best to check if the config key exists right at the start of the script, then you can just return early.
Lua:
function onKill(creature, target)
    if creature:isPlayer() and target:isMonster() and not target:getMaster() then
        local monster = config[target:getName():lower()]
        if not monster then
            return true
        end

I would also fix the poor logic regarding the storages for you, but if your server is live, it will bug. Let me know if you are still in development, and ill post it here.
 
Last edited:
heyo,
Lua:
local monster = config[target:getName():lower()]
this pointing to table like config["necromancer"] if any monster will be killed and he is not in that list it will return nil, simple check if "monster" check exsists will fix it

nvm i am blind, i see ure solved it already.
Here, this part is correct!
Lua:
local monsterConfig = config[target:getName():lower()]

        if monsterConfig then
            for _, member in pairs(members) do
                local stor = member:getStorageValue(monsterConfig.storage) + 1

                if stor < monsterConfig.amount and member:getStorageValue(monsterConfig.startstorage) >= monsterConfig.startvalue then
                    member:setStorageValue(monsterConfig.storage, stor)
                    local textName = '' .. monsterConfig.name .. ' task: Already killed ' .. (stor + 1) .. ' of ' .. monsterConfig.amount .. ' creatures.'
                    member:openChannel(10)
                    member:sendChannelMessage('', textName, TALKTYPE_CHANNEL_O, 10)
                end
Thank you both, you are both right :)

It's best to check if the config key exists right at the start of the script, then you can just return early.
Lua:
function onKill(creature, target)
    if creature:isPlayer() and target:isMonster() and not target:getMaster() then
        local monster = config[target:getName():lower()]
        if not monster then
            return true
        end

I would also fix the poor logic regarding the storages for you, but if your server is live, it will bug. Let me know if you are still in development, and ill post it here.
Absolutely right, I moved it to the top as you did, thank you for the suggestion. At this point I just watned it to work, but now I can focus on improving it further. The server is in development, so this script can be changed basically with no limits.
 
Thank you both, you are both right :)


Absolutely right, I moved it to the top as you did, thank you for the suggestion. At this point I just watned it to work, but now I can focus on improving it further. The server is in development, so this script can be changed basically with no limits.
Test this out, it's written a little cleaner...
Lua:
local config = {
     ['necromancer'] = {name ="Necromancer", amount = 12, storage = 19004, startstorage = 5014, startvalue = 1, storageCorr= 5114},
     ['vampire'] = {name ="Vampire", amount = 15, storage = 19005, startstorage = 5015, startvalue = 1, storageCorr= 5115},
     ['hellspawn'] = {name ="Hellspawn", amount = 10, storage = 19006, startstorage = 5016, startvalue = 1, storageCorr= 5116},
     ['wyrm'] = {name = "Wyrm", amount = 10, storage = 19007, startstorage = 5017, startvalue = 1, storageCorr= 5117},
     ['elder wyrm'] = {name ="Wyrm", amount = 10, storage = 19007, startstorage = 5017, startvalue = 1, storageCorr= 5117},
     ['sea serpent'] = {name ="Sea Serpent", amount = 10, storage = 19008, startstorage = 5018, startvalue = 1, storageCorr = 5118},
}

function onKill(creature, target)
    if creature:isPlayer() and target:isMonster() and not target:getMaster() then
      
        local monster = config[target:getName():lower()]
        if not monster then
            return true
        end
      
        local targetPos = target:getPosition() 
        local party = creature:getParty()
        local members = party and party:getMembers() or {creature}
        if party then
            table.insert(members, party:getLeader())
        end
     
        for _, member in pairs(members) do
            local memberPos = member:getPosition()
          
            if getTilePzInfo(memberPos) == false
            and memberPos:getDistance(targetPos) < 25
            and member:getStorageValue(monster.storageCorr) < 2
            and member:getStorageValue(monster.startstorage) >= monster.startvalue  then
          
                local currentKills = member:getStorageValue(monster.storage)
                currentKills = currentKills < 1 and 0 or currentKills
                local newKills = currentKills + 1
              
                member:setStorageValue(monster.storage, newKills)
                member:openChannel(10)  
              
                if newKills < monster.amount then
                    local message = ('%s task: Killed %d of %d creatures.'):format(monster.name, newKills, monster.amount)
                    member:sendChannelMessage('', message, TALKTYPE_CHANNEL_O, 10)
                elseif newKills == monster.amount then
                    local message = ('%s task: Congratulations, you have completed this task.'):format(target:getName())
                    member:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
                    member:sendChannelMessage('', message, TALKTYPE_CHANNEL_R1, 10)
                    member:setStorageValue(monster.storageCorr, 2)
                end  
              
            end
        end
    end
  
    return true
end
 
Last edited:
Test this out, it's written a little cleaner...
Lua:
local config = {
     ['necromancer'] = {name ="Necromancer", amount = 12, storage = 19004, startstorage = 5014, startvalue = 1, storageCorr= 5114},
     ['vampire'] = {name ="Vampire", amount = 15, storage = 19005, startstorage = 5015, startvalue = 1, storageCorr= 5115},
     ['hellspawn'] = {name ="Hellspawn", amount = 10, storage = 19006, startstorage = 5016, startvalue = 1, storageCorr= 5116},
     ['wyrm'] = {name = "Wyrm", amount = 10, storage = 19007, startstorage = 5017, startvalue = 1, storageCorr= 5117},
     ['elder wyrm'] = {name ="Wyrm", amount = 10, storage = 19007, startstorage = 5017, startvalue = 1, storageCorr= 5117},
     ['sea serpent'] = {name ="Sea Serpent", amount = 10, storage = 19008, startstorage = 5018, startvalue = 1, storageCorr = 5118},
}

function onKill(creature, target)
    if creature:isPlayer() and target:isMonster() and not target:getMaster() then
       
        local monster = config[target:getName():lower()]
        if not monster then
            return true
        end
       
        local party = creature:getParty()
        local members = party and party:getMembers() or {creature}
      
        if party then
            table.insert(members, party:getLeader())
        end
      
        for _, member in pairs(members) do               
            if member:getStorageValue(monster.storageCorr) < 2
            and member:getStorageValue(monster.startstorage) >= monster.startvalue  then
           
                local currentKills = member:getStorageValue(monster.storage)
                currentKills = currentKills < 1 and 0 or currentKills
                local newKills = currentKills + 1
               
                member:setStorageValue(monster.storage, newKills)
                member:openChannel(10)   
               
                if newKills < monster.amount then
                    local message = ('%s task: Killed %d of %d creatures.'):format(monster.name, newKills, monster.amount)
                    member:sendChannelMessage('', message, TALKTYPE_CHANNEL_O, 10)
                elseif newKills == monster.amount then
                    local message = ('%s task: Congratulations, you have completed this task.'):format(target:getName())
                    member:sendTextMessage(MESSAGE_EVENT_ADVANCE, message)
                    member:sendChannelMessage('', message, TALKTYPE_CHANNEL_R1, 10)
                    member:setStorageValue(monster.storageCorr, 2)
                end   
               
            end
        end
    end
   
    return true
end
It certainly looks much more professional, but somehow it refuses to count the kills, but I'll take a look at this later, as I don't have that much time and I rather think slowly while scripting :rolleyes:

Besides, I have added 2 checks in order to prevent party abusing (both working fine), if you are still interested in refining this script, you may also include them

Lua:
local creaturePos = member:getPosition()
local killedMobPos = target:getPosition()

if getTilePzInfo(creaturePos) == false then
if killedMobPos:getDistance(creaturePos) < 25 then
 
It certainly looks much more professional, but somehow it refuses to count the kills, but I'll take a look at this later, as I don't have that much time and I rather think slowly while scripting :rolleyes:
Did you clear the storages? If you dont want to clear all the storages, make sure that the startstorage keys have a value or 1 and storageCorr should be lower than 2, as 2 is what defines the task as being complete.
startstorage = 5018, startvalue = 1, storageCorr = 5118

If it still doesn't work, just add a few prints and see which part its failing on... the logic is pretty identical, just cleaned up

Besides, I have added 2 checks in order to prevent party abusing (both working fine), if you are still interested in refining this script, you may also include them
Lua:
local creaturePos = member:getPosition()
local killedMobPos = target:getPosition()

if getTilePzInfo(creaturePos) == false then
if killedMobPos:getDistance(creaturePos) < 25 then
Yeah good catch, I've re-edited my last post.
 
Last edited:
Did you clear the storages? If you dont want to clear all the storages, make sure that the startstorage keys have a value or 1 and storageCorr should be lower than 2, as 2 is what defines the task as being complete.
startstorage = 5018, startvalue = 1, storageCorr = 5118

If it still doesn't work, just add a few prints and see which part its failing on... the logic is pretty identical, just cleaned up



Yeah good catch, I've re-edited my last post.
Alright, seems to be working nicely, the problem must have been with my NPC file where I changed some stuff since posting this thread, because it is working nicely now :) Thanks for you time!
 
Back
Top