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

How would you do it?

Codinablack

Dreamer
Content Editor
Joined
Dec 26, 2013
Messages
1,609
Solutions
11
Reaction score
836
Ok so this isn't really a support issue, I'm kind of just looking for a bit of brainstorming or really opinions on performance and optimization for a kill counter.

YES I know kill counters have been done countless times before.

Here is the thing, kill counters are normally saved via storage values to the player, right? Well that is really a last option for me, and here are the reasons why

1.My system I want to make will include counters for EVERY monster type that exists in the server, and to make a storage value for every single monster in the server, well would frankly be a waste of my storage values.

2. The system I would like to make would only be counting the monsters per server session. What I mean is, once the server restarts, crashes or shuts down, then the kills should be back at 0. Resetting every users storage values at startup could be a bit overkill on resources, and just feels hackish to me.

What I'm looking for is a way to store all this data temporarily, and only use it when necessary. So once the server shuts down , the data is gone and no need to write a script to clear the data. Also I'm looking for a way to implement this without it being super resource intensive, such as 1874 creaturescripts running on every player at login. One way, would be to only register an event with the player once they kill that monster, but then at the same time, everytime someone kills just one monster they now add another event to themselves which could pile on very quickly.

OPTIONS

I could make the data save to a killCounter/PlayerName.lua file for each player and then have the files all deleted on startup.

I could make the creatures themselves hold the events, and then check versus that one player (if player has reached kill limit or w/e)

I could use a global table that is stored in memory at startup and then ofc released at shutdown, but I'm unsure how huge this table could get on memory.

Maybe create a new type of data for the database, tied to each player, that would store their kill counts? This would also be resource intensive I believe, and I honestly don't know much about the types of data that could be stored and read from in the mysql database.

So my question is, how would you do it? Store a counter for every single type of monster in the game, and be able to use it with no latency issues. Register events to players or creatures? Save in a table in the memory or save and utilize the data in another manner? What do you guys think?

I hope no one minds, but I am gonna tag a few people who's opinion I value, and are typically willing to give their opinion and/or help people, and are also still active.

@Sarah Wesker @Xikini @zbizu @forgee @Summ @oen432 @Printer -- sorry I know you don't post much lately but I still highly respect your opinion printer.

There are others I'm not so sure about, how active they are now, and others I can't remember off the top of my head, and no one should feel obliged to respond here, if you want me to remove your name tagged just tell me and I will do so, but I'm pretty indecisive and right now, I'm super indecisive about how to go about a system like this, mainly I want to set a kill limit on each type of monster, and ideally each type would have its own limit (source edit is possible waaaaay later to achieve this), but for now I'm ok with a global limit and a way to do this without causing major lag to the server.

As always I am using TFS 1.x+ , specifically I'm using 1.4 right now

Any ideas guys?
Post automatically merged:

@Evil Puncker
 
Last edited:
Just make a new global table, it will reset every time server shutdown
Give me 5 min and ill give you some examples
 
Yeah, the global table idea was mentioned. Do you by chance happen to have any kind of rough idea on how much memory a table like that would use with say 100 players online? I'm not being sarcastic at all, because I honestly have no freaking clue
 
Ok so this isn't really a support issue, I'm kind of just looking for a bit of brainstorming or really opinions on performance and optimization for a kill counter.

YES I know kill counters have been done countless times before.

Here is the thing, kill counters are normally saved via storage values to the player, right? Well that is really a last option for me, and here are the reasons why

1.My system I want to make will include counters for EVERY monster type that exists in the server, and to make a storage value for every single monster in the server, well would frankly be a waste of my storage values.

2. The system I would like to make would only be counting the monsters per server session. What I mean is, once the server restarts, crashes or shuts down, then the kills should be back at 0. Resetting every users storage values at startup could be a bit overkill on resources, and just feels hackish to me.

What I'm looking for is a way to store all this data temporarily, and only use it when necessary. So once the server shuts down , the data is gone and no need to write a script to clear the data. Also I'm looking for a way to implement this without it being super resource intensive, such as 1874 creaturescripts running on every player at login. One way, would be to only register an event with the player once they kill that monster, but then at the same time, everytime someone kills just one monster they now add another event to themselves which could pile on very quickly.

OPTIONS

I could make the data save to a killCounter/PlayerName.lua file for each player and then have the files all deleted on startup.

I could make the creatures themselves hold the events, and then check versus that one player (if player has reached kill limit or w/e)

I could use a global table that is stored in memory at startup and then ofc released at shutdown, but I'm unsure how huge this table could get on memory.

Maybe create a new type of data for the database, tied to each player, that would store their kill counts? This would also be resource intensive I believe, and I honestly don't know much about the types of data that could be stored and read from in the mysql database.

So my question is, how would you do it? Store a counter for every single type of monster in the game, and be able to use it with no latency issues. Register events to players or creatures? Save in a table in the memory or save and utilize the data in another manner? What do you guys think?

I hope no one minds, but I am gonna tag a few people who's opinion I value, and are typically willing to give their opinion and/or help people, and are also still active.

@Sarah Wesker @Xikini @zbizu @forgee @Summ @oen432 @Printer -- sorry I know you don't post much lately but I still highly respect your opinion printer.

There are others I'm not so sure about, how active they are now, and others I can't remember off the top of my head, and no one should feel obliged to respond here, if you want me to remove your name tagged just tell me and I will do so, but I'm pretty indecisive and right now, I'm super indecisive about how to go about a system like this, mainly I want to set a kill limit on each type of monster, and ideally each type would have its own limit (source edit is possible waaaaay later to achieve this), but for now I'm ok with a global limit and a way to do this without causing major lag to the server.

As always I am using TFS 1.x+ , specifically I'm using 1.4 right now

Any ideas guys?
Post automatically merged:

@Evil Puncker

Creating and deleting files for every single player would be more resource intensive than using a storage value, for sure. sounds like a nightmware.

Adding the events to all the creatures would probably be more work and likely the same as just using storage values.

A new type of data for the database sounds like you're just re-inventing storagevalues...



Tbh, I don't see any issue wit using storage values, you have thousands of storage values to choose from... if you're running out of storage values to use, sounds like something else is wrong.
 
Thats true that if I'm running out of storage values something else must definitely be wrong 😂

To tell the truth that is not really my issue, its the shear amount of storage values it would take, and every last one of them would need to be reset at startup. Also there would ofc need to be good management of a starting point for the storage values, meaning which one to start with for first monster, plus the system would need to be created with each monster always reading for exact same storage value, and now what if I change the monsters? Maybe just the name, maybe create new ones, or deleted unused ones? All this would be needed in the system to adapt for those possible changes, otherwise, once the system is in use, changes to monsters could cause the counter to break for the players.

or my other option doing it this way is to manually program each monster into a table and then use that table for the assignment of the storage values, and im just not going to manually add each monster when the system is intended to be used for all monsters.
 
Yeah, the global table idea was mentioned.
Oh, tbh didnt read all thread xD

Well, the idea is to index everything directly by using player's guid and monsters counter will be created on the progress
 
Oh, tbh didnt read all thread xD

Well, the idea is to index everything directly by using player's guid and monsters counter will be created on the progress
I actually love this idea, as it wouldn't have the problems mentioned with storage values, and wouldn't have to worry about deleting the data myself, my biggest concern and really only concern for this method is how much ram it would use on a busy server, which I have nothing to base it on or any knowledge on how much tables that can grow normally use up.

Also, say I did do it this way and it doesn't eat up much memory, how would you then customize a different limit for each monster? Any ideas? The best I come up with is doing it by race, which doesn't feel right to me, but is definitely an option
Post automatically merged:

Thanks guys for fast responses, I don't mean to argue each point, just trying to brainstorm solutions
 
Idea is pretty basic
Lua:
function onLogin(player)
    local guid = player:getGuid()
    if not globalTable[guid] then
        globalTable[guid] = {}
    end
end
 
function onKill(player, target)
    local counter = globalTable[player:getGuid()][target:getName():lower()]
    counter = (counter or 0) + 1
end

About your concern, im actually not sure but you can run some tests
I found this on stackoverflow: link

- EDIT -

Just to make an example:

creating 100,000 keys on a table on my crappy pc took 0.017 microseconds
using collectgargabe returned 2068 kilobytes
 
Last edited:
and every last one of them would need to be reset at startup

It's really not hard to do... You can make a 1 line SQL query, as long as you dedicate a range, (Eg 10,000 to 20,000 reserved for monster kill counts) and add it to your existing startup script.

If you made a 2nd table, you'd also need to update your source files to save this data in separate table again.
 
2068 kilobytes
Outstanding! Could you possible alter it slightly and fill the table with values as well? like random strings or just a number value, just for a bit further reference?

It's really not hard to do... You can make a 1 line SQL query, as long as you dedicate a range, (Eg 10,000 to 20,000 reserved for monster kill counts) and add it to your existing startup script.
I had no idea you could do it in one query, I imagined a loop thru each value, and each time executing a query, and for each player, which stacked up in my head to be ALOT of queries. but I'm definitely not really familiar with the queries tbh, could you possibly show me what a one line query to delete multiple storage values at once would look like?
Post automatically merged:

100k only 2068 kbs , honestly blows my mind, I mean I knew the footprint of lua was low, but that's amazing
 
Agree with above.

Simple global table is best.
Memory usage would be minimal. Everything you're saving to memory essentially boils down to a simple text document.

How you setup the table(s) depends on what you want to do.
You'd have to give more specific information.
 
Outstanding! Could you possible alter it slightly and fill the table with values as well? like random strings or just a number value, just for a bit further reference?


I had no idea you could do it in one query, I imagined a loop thru each value, and each time executing a query, and for each player, which stacked up in my head to be ALOT of queries. but I'm definitely not really familiar with the queries tbh, could you possibly show me what a one line query to delete multiple storage values at once would look like?
Post automatically merged:

100k only 2068 kbs , honestly blows my mind, I mean I knew the footprint of lua was low, but that's amazing

Even if you had to do multiple lines, you can keep it in 1 query. Doing shit like this is what SQL was made for, so it's not intensive.
 
Make a new database table with monster name, id, and playerid.

monster - monsterID - playerID - count

Its the best option if you want to keep storage values clean. It also makes it so its easy to remember how to call the information.

player:getKillCount("Rat")

or

player:getKillCount(1)

Then you can create a table that stores the monster ids

Lua:
local monsters = {
       ["Rat"] = 1
}
If you dont want to add the monsters yourself you could make the table update itself with the ids

Lua:
local nextID = 0
if #monsters > 0 then
     nextID = #monsters + 1
else
     nextID = 1
end

monsters[target:getName()] = nextID

or you cant make an iteratable table like

Lua:
if not monsters[target:getName()] then
     monsters[#monsters + 1] = target:getName()
end

That would go in a onKill(creature, target) that is linked to the player. It would execute on every monster killed. just add

Lua:
if not target:isMonster() then return true end

obviously and delete the database info on server close.

If you need the id of a monster just do

Lua:
local monsterID = monsters[monsName]

You don't actually need the ID of the monster I just like having multiple ways to call things.
 
Last edited:
I am currently working on a project aswell and faced the same situation. I also had similar ideas on my mind which you mentioned already.
As I am working with laravel I thought about a preparing table, not really inserting the data into SQL as that would eat to much resources but instead let laravel do the inserting job while the server just saves the data which needs to be inserted. I haven't done performance checks yet but I am mostly sure that 100k in less than 0.02 seconds is probably the best result you can get. That's actually insanely fast.
 
You don't actually need the ID of the monster I just like having multiple ways to call things.
I'm the same way :D

I also like to make my own methods/functions for ease of use like

player:getKillCount("Rat")

I'm leaning towards the global table solution, only real problem with it (seeing as how there is not a memory issue), is making sure to restart the server everyday, which is easily solved with global event
Post automatically merged:

That's actually insanely fast.
IKR? I was definitely impressed :D

I have never used laravel, just googled it and seen its php! That is some grade A out of the box thinking, thats the kind of stuff I was looking for! I'm assuming with your method you are saving a permanent kill counter though?

I love the idea, but unfortunately php is like perl to me, its just a foreign language that definitely looks foreign to me
 
I have never used laravel, just googled it and seen its php! That is some grade A out of the box thinking, thats the kind of stuff I was looking for! I'm assuming with your method you are saving a permanent kill counter though?
Laravel comes with task scheduling which helps to build cronjobs thought PHP pretty easy. My kill counter should be permanent, yes. I want to build up a chart where you can check how many times a monster has been killed or even killed a player.
 
Thanks for the ideas guys, much appreciated! I went with global table, and made this simple thing here using @Roddet 's method and his code he shared, could definitely have some features added, like a daily time for each day it resets, incase you don't want to restart the server, or even just a server shutdown added to it for global time, or modal windows to look for each creatures current kill count, ect. But it works, and thought I would share, and say thanks again for the brainstorming, I am quite happy with the final result.
 
To store it globally is something i would do aswell. And the memory it would take wont be a problem. Even with 1k players. The amount of kills doesnt change the memory usage cause each monster you kill gets a dedicated amount of bits to use. So if you kill 1 million rats or 5 rats (potentially) takes the same amount of memory(per player).

Looking at it logically is that each and every player will not even kill 20% of all monster types you have on the server each reset.
It will really only take more memory when a player kills a brand new monster. I think i would save it like this (i think someone did show it previous posts)

Lua:
local monsterList = {
       ["Rat"] = {
               ["player1"] = 5,
            ["player2"] = 10
       },
       ["Rotworm"] = {
               ["player1"] = 100,
            ["player5"] = 1000,
            ["player6"] = 10000,
            ["player20"] = 10000
       }
}

//and then have a function that would handle all of this for you where you send the name of the monster that is killed and the player's name.

function addKill(monsterName, playerName)
    //suedo code
    //check if the monster has been killed ever since server start
        //if not, add it to the list
   
    //add the player to the list and add +1 to the player on that monster
   
    return true
end

function getPlayerKills(monsterName, playerName)
    return monsterList[monsterName][playerName]
end
 
Back
Top