• 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+ Monster killed counter, every 10 kills

vexler222

Active Member
Joined
Apr 22, 2012
Messages
714
Solutions
15
Reaction score
46
Hi, its possible to make "monster killed counter", and send message every 10 kills, without writing all monster name to script and unqi storage for them?
If it possible, can someone tell me how? Im not asking to write the entire script or anything, but to point me in the right direction.
Thanks


You killed 1 Dragon
You killed 10 Dragons
You killed 20 Dragons
 
Solution
Here is an alternative option, that does as you ask.

Lua:
local monsters = {
    ["dragon"] = {storageKey = 45001},
    ["demon"] = {storageKey = 45002}
}

local creatureEvent = CreatureEvent("KillMonsterCounter")

function creatureEvent.onKill(player, monster)
    local creatureName = monster:getName():lower()
    local index = monsters[creatureName]
    if not index then
        return true
    end
 
    local count = player:getStorageValue(index.storageKey)
    local newCount = (count > 0 and count or 0) + 1
    player:setStorageValue(index.storageKey, newCount)
 
    if newCount % 10 == 0 or newCount == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You killed " .. newCount .. " " .. creatureName .. "" .. (newCount == 1 and ""...
It may not be exactly what you are looking for but I will leave you this example that I made for you especially:
data/scripts/example.lua -- TFS 1.5+
Lua:
local STORAGE_BASE = 75500

local records = {
    ["Dragon"] = {
        records = {
            { count = 10, message = "You killed 10 dragons." },
            { count = 50, message = "You killed 50 dragons." },
            { count = 100, message = "You killed 100 dragons." },
            { count = 250, message = "You killed 250 dragons." },
            { count = 500, message = "You killed 500 dragons." },
            { count = 1000, message = "You killed 1000 dragons." },
            { count = 2000, message = "You killed 2000 dragons." },
            { count = 5000, message = "You killed 5000 dragons." },
            { count = 10000, message = "You killed 10000 dragons." },
            { count = 20000, message = "You killed 20000 dragons." },
            { count = 50000, message = "You killed 50000 dragons." },
            { count = 100000, message = "You killed 100000 dragons." },
            { count = 200000, message = "You killed 200000 dragons." },
            { count = 500000, message = "You killed 500000 dragons." },
            { count = 1000000, message = "You killed 1000000 dragons." },
            { count = 2000000, message = "You killed 2000000 dragons." },
            { count = 5000000, message = "You killed 5000000 dragons." },
            { count = 10000000, message = "You killed 10000000 dragons." },
            { count = 20000000, message = "You killed 20000000 dragons." },
            { count = 50000000, message = "You killed 50000000 dragons." }
        }
    },
    ["Demon"] = {
        records = {
            { count = 10, message = "You killed 10 demons." },
            { count = 50, message = "You killed 50 demons." },
            { count = 100, message = "You killed 100 demons." },
            { count = 250, message = "You killed 250 demons." },
            { count = 500, message = "You killed 500 demons." },
            { count = 1000, message = "You killed 1000 demons." },
            { count = 2000, message = "You killed 2000 demons." },
            { count = 5000, message = "You killed 5000 demons." },
            { count = 10000, message = "You killed 10000 demons." },
            { count = 20000, message = "You killed 20000 demons." },
            { count = 50000, message = "You killed 50000 demons." },
            { count = 100000, message = "You killed 100000 demons." },
            { count = 200000, message = "You killed 200000 demons." },
            { count = 500000, message = "You killed 500000 demons." },
            { count = 1000000, message = "You killed 1000000 demons." },
            { count = 2000000, message = "You killed 2000000 demons." },
            { count = 5000000, message = "You killed 5000000 demons." },
            { count = 10000000, message = "You killed 10000000 demons." },
            { count = 20000000, message = "You killed 20000000 demons." },
            { count = 50000000, message = "You killed 50000000 demons." }
        }
    }
}

for name, record in pairs(records) do
    local storage = 0
    for i = 1, #name do
        storage = storage + name:byte(i)
    end
    records[name].storage = STORAGE_BASE + storage
end

local creatureEvent = CreatureEvent("KillMonsterCounter")

function creatureEvent.onKill(player, monster)
    local record = records[monster:getName()]
    if not record then
        return true
    end

    local storage = record.storage
    local count = math.max(0, tonumber(player.storage[storage]) or 0)
    for _, record in pairs(record.records) do
        if count < record.count then
            player.storage[storage] = count + 1
            if count + 1 == record.count then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, record.message)
            end
            return true
        end
    end
    return true
end

creatureEvent:register()

local creatureEvent = CreatureEvent("LoginMonsterCounter")

function creatureEvent.onLogin(player)
    player:registerEvent("KillMonsterCounter")
    return true
end

creatureEvent:register()
Just make sure you use the correct spelling of monster names with their first letter capitalized.
example: Dragon instead dragon
Lua:
...
["Dragon"] = { -- see HERE
        records = {
            { count = 10, message = "You killed 10 dragons." },
            ...
 
Here is an alternative option, that does as you ask.

Lua:
local monsters = {
    ["dragon"] = {storageKey = 45001},
    ["demon"] = {storageKey = 45002}
}

local creatureEvent = CreatureEvent("KillMonsterCounter")

function creatureEvent.onKill(player, monster)
    local creatureName = monster:getName():lower()
    local index = monsters[creatureName]
    if not index then
        return true
    end
 
    local count = player:getStorageValue(index.storageKey)
    local newCount = (count > 0 and count or 0) + 1
    player:setStorageValue(index.storageKey, newCount)
 
    if newCount % 10 == 0 or newCount == 1 then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You killed " .. newCount .. " " .. creatureName .. "" .. (newCount == 1 and "" or "s") .. ".")
    end
    return true
end

creatureEvent:register()

local creatureEvent = CreatureEvent("LoginMonsterCounter")

function creatureEvent.onLogin(player)
    player:registerEvent("KillMonsterCounter")
    return true
end

creatureEvent:register()
 
Last edited:
Solution
No its not possible to do that unless you don't care if the kills reset every time the server shuts down.
 
Somewhere the data must be stored, if you dont wanna use storages you can store the informations on database
 
The storages are saved to the database when the character is saved, usually this happens when the player logout.
If you want the changes to be reflected on the web page you must save the character manually in the script.
Lua:
player:save()

So yes, it's fine to use storage for this kind of thing, it's much better than working directly writing and reading from the database.
 
The storages are saved to the database when the character is saved, usually this happens when the player logout.
If you want the changes to be reflected on the web page you must save the character manually in the script.
Lua:
player:save()

So yes, it's fine to use storage for this kind of thing, it's much better than working directly writing and reading from the database.
May i ask why storage is better than dirrectly reading / writing database?
 
It may not be exactly what you are looking for but I will leave you this example that I made for you especially:
data/scripts/example.lua -- TFS 1.5+
Lua:
local STORAGE_BASE = 75500

local records = {
    ["Dragon"] = {
        records = {
            { count = 10, message = "You killed 10 dragons." },
            { count = 50, message = "You killed 50 dragons." },
            { count = 100, message = "You killed 100 dragons." },
            { count = 250, message = "You killed 250 dragons." },
            { count = 500, message = "You killed 500 dragons." },
            { count = 1000, message = "You killed 1000 dragons." },
            { count = 2000, message = "You killed 2000 dragons." },
            { count = 5000, message = "You killed 5000 dragons." },
            { count = 10000, message = "You killed 10000 dragons." },
            { count = 20000, message = "You killed 20000 dragons." },
            { count = 50000, message = "You killed 50000 dragons." },
            { count = 100000, message = "You killed 100000 dragons." },
            { count = 200000, message = "You killed 200000 dragons." },
            { count = 500000, message = "You killed 500000 dragons." },
            { count = 1000000, message = "You killed 1000000 dragons." },
            { count = 2000000, message = "You killed 2000000 dragons." },
            { count = 5000000, message = "You killed 5000000 dragons." },
            { count = 10000000, message = "You killed 10000000 dragons." },
            { count = 20000000, message = "You killed 20000000 dragons." },
            { count = 50000000, message = "You killed 50000000 dragons." }
        }
    },
    ["Demon"] = {
        records = {
            { count = 10, message = "You killed 10 demons." },
            { count = 50, message = "You killed 50 demons." },
            { count = 100, message = "You killed 100 demons." },
            { count = 250, message = "You killed 250 demons." },
            { count = 500, message = "You killed 500 demons." },
            { count = 1000, message = "You killed 1000 demons." },
            { count = 2000, message = "You killed 2000 demons." },
            { count = 5000, message = "You killed 5000 demons." },
            { count = 10000, message = "You killed 10000 demons." },
            { count = 20000, message = "You killed 20000 demons." },
            { count = 50000, message = "You killed 50000 demons." },
            { count = 100000, message = "You killed 100000 demons." },
            { count = 200000, message = "You killed 200000 demons." },
            { count = 500000, message = "You killed 500000 demons." },
            { count = 1000000, message = "You killed 1000000 demons." },
            { count = 2000000, message = "You killed 2000000 demons." },
            { count = 5000000, message = "You killed 5000000 demons." },
            { count = 10000000, message = "You killed 10000000 demons." },
            { count = 20000000, message = "You killed 20000000 demons." },
            { count = 50000000, message = "You killed 50000000 demons." }
        }
    }
}

for name, record in pairs(records) do
    local storage = 0
    for i = 1, #name do
        storage = storage + name:byte(i)
    end
    records[name].storage = STORAGE_BASE + storage
end

local creatureEvent = CreatureEvent("KillMonsterCounter")

function creatureEvent.onKill(player, monster)
    local record = records[monster:getName()]
    if not record then
        return true
    end

    local storage = record.storage
    local count = math.max(0, tonumber(player.storage[storage]) or 0)
    for _, record in pairs(record.records) do
        if count < record.count then
            player.storage[storage] = count + 1
            if count + 1 == record.count then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, record.message)
            end
            return true
        end
    end
    return true
end

creatureEvent:register()

local creatureEvent = CreatureEvent("LoginMonsterCounter")

function creatureEvent.onLogin(player)
    player:registerEvent("KillMonsterCounter")
    return true
end

creatureEvent:register()
Just make sure you use the correct spelling of monster names with their first letter capitalized.
example: Dragon instead dragon
Lua:
...
["Dragon"] = { -- see HERE
        records = {
            { count = 10, message = "You killed 10 dragons." },
            ...
Hey, thanks.
One question, your script saving count in storage, and storage is a default value+ value from monster name byte(?), So its possibile to save count/monster storage, on moment when player targeting monster? Something like creature:getName(target)? Or it non sens?
Btw "byte" from monster name is a monster id? Or how it work?
 
May i ask why storage is better than dirrectly reading / writing database?
The storages are loaded and stored in RAM when the player login.
Getting a value stored in a storage will only cost the search in the storage map, this is almost instantaneous. (The same for setStorageValue)
I'm not saying that using the database directly is bad, just that you can save some time and use things that already work well like storages.
If the information you want to store is something more than just numbers, then I suppose you will have to use the database directly and create your own tables with fields of type that can store text or other data types more complex than a number.
Post automatically merged:

Hey, thanks.
One question, your script saving count in storage, and storage is a default value+ value from monster name byte(?), So its possibile to save count/monster storage, on moment when player targeting monster? Something like creature:getName(target)? Or it non sens?
Btw "byte" from monster name is a monster id? Or how it work?
Hello, my script is not so simple as to have left it as an example, sorry for that.
But basically I'm using a simple trick to generate the storage keys for each type of monster based on the name automatically.
This trick is not necessary, you can add your own keys manually just like he did @Xikini HERE

If you don't want to use auto-generated keys, you can remove the following code snippets:
Lua:
local STORAGE_BASE = 75500
Lua:
for name, record in pairs(records) do
    local storage = 0
    for i = 1, #name do
        storage = storage + name:byte(i)
    end
    records[name].storage = STORAGE_BASE + storage
end

But if you do this, you'll need to make sure you add your own storage keys, for example:
Lua:
...
local records = {
    ["Dragon"] = {
        storage = 75565, -- example!
        records = {
            { count = 10, message = "You killed 10 dragons." },
            { count = 50, message = "You killed 50 dragons." },
            { count = 100, message = "You killed 100 dragons." },
...

Example Complete:
data/scripts/killmonstercounter.lua
Lua:
local records = {
    ["Dragon"] = {
        storage = 75500,
        records = {
            10, 50, 100, 250, 500, 1000
        }
    },
    ["Demon"] = {
        storage = 75501,
        records = {
            10, 50, 100, 250, 500, 1000
        }
    }
}

local creatureEvent = CreatureEvent("KillMonsterCounter")

function creatureEvent.onKill(player, monster)
    local monsterName = monster:getName()
    local record = records[monsterName]
    if not record then
        return true
    end

    local currentCount = math.max(0, player:getStorageValue(record.storage))
    for _, count in pairs(record.records) do
        if currentCount < count then
            local newCount = currentCount + 1
            player:setStorageValue(record.storage, newCount)
            if newCount == count then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You killed %d %s.", newCount, monsterName))
            end
            return true
        end
    end
    return true
end

creatureEvent:register()

local creatureEvent = CreatureEvent("LoginMonsterCounter")

function creatureEvent.onLogin(player)
    player:registerEvent("KillMonsterCounter")
    return true
end

creatureEvent:register()
 
Last edited:
The storages are loaded and stored in RAM when the player login.
Getting a value stored in a storage will only cost the search in the storage map, this is almost instantaneous. (The same for setStorageValue)
I'm not saying that using the database directly is bad, just that you can save some time and use things that already work well like storages.
If the information you want to store is something more than just numbers, then I suppose you will have to use the database directly and create your own tables with fields of type that can store text or other data types more complex than a number.
Post automatically merged:


Hello, my script is not so simple as to have left it as an example, sorry for that.
But basically I'm using a simple trick to generate the storage keys for each type of monster based on the name automatically.
This trick is not necessary, you can add your own keys manually just like he did @Xikini HERE

If you don't want to use auto-generated keys, you can remove the following code snippets:
Lua:
local STORAGE_BASE = 75500
Lua:
for name, record in pairs(records) do
    local storage = 0
    for i = 1, #name do
        storage = storage + name:byte(i)
    end
    records[name].storage = STORAGE_BASE + storage
end

But if you do this, you'll need to make sure you add your own storage keys, for example:
Lua:
...
local records = {
    ["Dragon"] = {
        storage = 75565, -- example!
        records = {
            { count = 10, message = "You killed 10 dragons." },
            { count = 50, message = "You killed 50 dragons." },
            { count = 100, message = "You killed 100 dragons." },
...

Example Complete:
data/scripts/killmonstercounter.lua
Lua:
local records = {
    ["Dragon"] = {
        storage = 75500,
        records = {
            10, 50, 100, 250, 500, 1000
        }
    },
    ["Demon"] = {
        storage = 75501,
        records = {
            10, 50, 100, 250, 500, 1000
        }
    }
}

local creatureEvent = CreatureEvent("KillMonsterCounter")

function creatureEvent.onKill(player, monster)
    local monsterName = monster:getName()
    local record = records[monsterName]
    if not record then
        return true
    end

    local currentCount = math.max(0, player:getStorageValue(record.storage))
    for _, count in pairs(record.records) do
        if currentCount < count then
            local newCount = currentCount + 1
            player:setStorageValue(record.storage, newCount)
            if newCount == count then
                player:sendTextMessage(MESSAGE_EVENT_ADVANCE, string.format("You killed %d %s.", newCount, monsterName))
            end
            return true
        end
    end
    return true
end

creatureEvent:register()

local creatureEvent = CreatureEvent("LoginMonsterCounter")

function creatureEvent.onLogin(player)
    player:registerEvent("KillMonsterCounter")
    return true
end

creatureEvent:register()

Okey thanks :D
I have one more question for you, is possible to make message counter every 10 kills without writing it in script like now? or i must put all in script?
You killed 10 dragons, 20, 30, 40, 50 ...
 
Okey thanks :D
I have one more question for you, is possible to make message counter every 10 kills without writing it in script like now? or i must put all in script?
You killed 10 dragons, 20, 30, 40, 50 ...
Look at my script example to see how that is done.
Line 19.
 
Back
Top