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

Add Player 3% Mana per sec needed

Hashirama479

World of Ninja
Joined
Dec 19, 2016
Messages
536
Solutions
6
Reaction score
74
Yo I need a script which gives players 3% mana per sec and it should work forever also its shouldnt be like using a item = getting mana it should always heal doenst matter if you log off or what ever haha xD ( sorry if the script alredy exists but cant find it.... )
 
You want to jump from start to finish with no rise in performance? Ok here you go:

Code:
function onThink(interval)
end


It might be more less effective to use globalscripts onThink over creaturescripts onThink in this case, but not devastatingly. But aside from that, your code also "does something to all online players via lua" and "every tick get all online players" is also done, but by C++. Perhaps he uses an additional table compared to you etc but as I said this isn't devastating. Might not be great though but not as you say.
Simpliest explaination:
Just for you, I launched this script on machine with single core CPU 1.7 GHz and 500MB RAM while was 16 bots online.
When I reloaded globalevents - server and OS just frozen. Mouse cursor needed 3 seconds to move by 2 inches on monitor. After 2 minutes of fighting and listening that heavy loud sound of CPU fan I decided to hit reset.
 
Simpliest explaination:
Just for you, I launched this script on machine with single core CPU 1.7 GHz and 500MB RAM while was 16 bots online.
When I reloaded globalevents - server and OS just frozen. Mouse cursor needed 3 seconds to move by 2 inches on monitor. After 2 minutes of fighting and listening that heavy loud sound of CPU fan I decided to hit reset.
What interval did you have? 1 ms? Impossible to freeze the OS with 16 players online. The code isn't that heavy. Maybe it's not efficient (compared to other available options), but what you're saying is ridiculous. It would impossibly freeze the server with 16 players. Even with 500 players it wouldn't freeze. MAYBE lag slightly but not freeze. Perhaps you couldn't handle 16 mcs.

I'm not gonna run 16 mc's though, but I settled for 2.

Code:
local mpGainPercent = 3

local function onlinePlayers()
    local players = {}
    local p = getOnlinePlayers()
    for i = 1, 100000 do
        table.insert(players, p[2] and p[2] or p[1])
    end
    return players
end

function onThink(interval)
    local startTime = os.mtime()
    local players = onlinePlayers()
    if (#players == 0) then
        return true
    end
    for i = 1, #players do
        local cid = getPlayerByName(players[i])
        local maxMana = getPlayerMaxMana(cid)
        if getPlayerMana(cid) ~= maxMana then
            doPlayerAddMana(cid, maxMana * (mpGainPercent/100))
        end
    end
    print("EXECUTION TIME:", os.mtime() - startTime)
    return true
end
(globalevent interval 1000ms)

This code was executed in 100 ms causing no lag. However, if I increased it to 1 million entries in the table, it would lag for a second during the execution of the event. With 1000 players it was executed in 1 millisecond.

Yes yes I know, it's not like having players online, but the difference isn't significant. A tip for you: don't use 16 mcs.
 
Last edited:
change
Code:
"no"
to
Code:
"no",

Did but nothing has been changed. The error is gone at console xD

-

local mpGainPercent = 3 local function onlinePlayers() local players = {} local p = getOnlinePlayers() for i = 1, 100000 do table.insert(players, p[2] and p[2] or p[1]) end return players end function onThink(interval) local startTime = os.mtime() local players = onlinePlayers() if (#players == 0) then return true end for i = 1, #players do local cid = getPlayerByName(players) local maxMana = getPlayerMaxMana(cid) if getPlayerMana(cid) ~= maxMana then doPlayerAddMana(cid, maxMana * (mpGainPercent/100)) end end print("EXECUTION TIME:", os.mtime() - startTime) return true end

It adds 100% mana instead of 3% xD
 
Conditions doesn't have good support in sources. They loads before function so you can't use variables like cid. Unless you decide to make alot of conditions to match different players' max mana. This option will be memory absorbing.

You can access the player methods, you just need to create the condition outside the function and then add parameters inside the function, or just create a new function to create your desired condition. The only bad thing about this is what you'll have to the old condition and create a new one when you level up, as your max stats change.
 
You can access the player methods, you just need to create the condition outside the function and then add parameters inside the function, or just create a new function to create your desired condition. The only bad thing about this is what you'll have to the old condition and create a new one when you level up, as your max stats change.
you dont need to create new condition objects
you can just reset condition params and update them each interval (incase stats change)
 
creature/global script onThink vs creaturescript onLogin addEvent?

If I am not mistaken, onLogin queries stuff once, and data is being passed to an event timeout, which can have exacly 1 second interval. No need to query for online list as onLogin already passes player object as param, no need to re-query for the player as it can be passed along the event.

Fetch entire online list and loop through it every 1 second, or fetch player on login and use an interval.

A few drawbacks with addEvent interval, you must recheck that cid is a player and stop the event in-case he logs out.
Also not sure how the garbage collector works when it comes to events calling themselves. Potential memmory hog?

Code:
function specialRegen(player)
    if player:getId() != nil then -- Player still online check
        -- todo: code
        AddEvent(specialRegen, 1000, player) -- Recall this function in 1 second.
    end
end

function onLogin(player)
    AddEvent(specialRegen, 1000, player)
end

This code looks WAY more sane than fetching online list, loop through and fetch player by name every 1 second.
 
Last edited:
I would prolly use creaturescript for this, just because then the execute time would be different for every player not all at once.
But it shouldn't rly matter is it done in globalEvents or Creaturescripts.

If you rly want to take next step and reduce the amount of this creaturescript executing then, unregister event when mana is full and register event when mana is taken/used

if 3% is a lot and most of the time players go in and out of full mana then make combat check if mana is full. If his in combat then don't unregister.
 
creature/global script onThink vs creaturescript onLogin addEvent?

If I am not mistaken, onLogin queries stuff once, and data is being passed to an event timeout, which can have exacly 1 second interval. No need to query for online list as onLogin already passes player object as param, no need to re-query for the player as it can be passed along the event.

Fetch entire online list and loop through it every 1 second, or fetch player on login and use an interval.

A few drawbacks with addEvent interval, you must recheck that cid is a player and stop the event in-case he logs out.
Also not sure how the garbage collector works when it comes to events calling themselves. Potential memmory hog?

Code:
function specialRegen(player)
    if player:getId() != nil then -- Player still online check
        -- todo: code
        AddEvent(specialRegen, 1000, player) -- Recall this function in 1 second.
    end
end

function onLogin(player)
    AddEvent(specialRegen, 1000, player)
end

This code looks WAY more sane than fetching online list, loop through and fetch player by name every 1 second.
Firstly, never call addEvent with userdata (pass cid instead). Secondly, addEvent not AddEvent, ~= not !=. Also I don't believe addEvent is any better than a creaturescript and not significantly better than a globalevent. No there are no memory issues with the event recalling itself, it isn't recursion.
 
Firstly, never call addEvent with userdata (pass cid instead). Secondly, addEvent not AddEvent, ~= not !=. Also I don't believe addEvent is any better than a creaturescript and not significantly better than a globalevent. No there are no memory issues with the event recalling itself, it isn't recursion.

Ahh I keep forgetting. I'm mostly coding PHP so :p
 
@Znote
besides the few mistakes It actually is the worst solution.
Because compared other solutions (creaturescript and globalevent)
You have to construct the Player userdata and check was it created.

Sure addEvent will put himself on the event stack when there is room (sometimes executes few millisec later to let something else does his thing), but I think adding addEvent is more of a job then executing creatuescript or globalevent every fixed interval.

but hey that is just speculation from person who only writes in Lua. Someone who knows source troughout could tell better what is the fastest and most effective solution when this feature done in Lua.
 
So this:
Code:
local function onlinePlayers()
    local players = {}
    local p = getOnlinePlayers()
    for i = 1, 100000 do
        table.insert(players, p[2] and p[2] or p[1])
    end
    return players
end

function onThink(interval)
    local startTime = os.mtime()
    local players = onlinePlayers()
    if (#players == 0) then
        return true
    end
    for i = 1, #players do
        local cid = getPlayerByName(players[i])
        local maxMana = getPlayerMaxMana(cid)
        if getPlayerMana(cid) ~= maxMana then
            doPlayerAddMana(cid, maxMana * (3/100))
        end
    end

    return true
end

Is better than this?:
Code:
function specialRegen(cid)
    local player = Player(cid)
    if player ~= nil then
        if player:getMana() ~= player:getMaxMana() then
            player:addMana(player:getMaxMana() * (3/100))
        end
        AddEvent(specialRegen, 1000, player:getId())
    end
end

function onLogin(player)
    AddEvent(specialRegen, 1000, player:getId())
end

Hmm, well I guess 500 players online = 500 addEvent calls/sec, instead of just fetching online list once.

The events would smooth out / load throughout the second, instead of in bulk. So even though it performs a bit worse, on big servers it may still avoid CPU spikes.
 
Last edited:
So this:
Code:
local function onlinePlayers()
    local players = {}
    local p = getOnlinePlayers()
    for i = 1, 100000 do
        table.insert(players, p[2] and p[2] or p[1])
    end
    return players
end

function onThink(interval)
    local startTime = os.mtime()
    local players = onlinePlayers()
    if (#players == 0) then
        return true
    end
    for i = 1, #players do
        local cid = getPlayerByName(players[i])
        local maxMana = getPlayerMaxMana(cid)
        if getPlayerMana(cid) ~= maxMana then
            doPlayerAddMana(cid, maxMana * (3/100))
        end
    end

    return true
end

Is better than this?:
Code:
function specialRegen(cid)
    local player = Player(cid)
    if player ~= nil then
        if player:getMana() ~= player:getMaxMana() then
            player:addMana(maxMana * (3/100))
        end
        AddEvent(specialRegen, 1000, player:getId())
    end
end

function onLogin(player)
    AddEvent(specialRegen, 1000, player:getId())
end

Hmm, well I guess 500 players online = 500 addEvent calls/sec, instead of just fetching online list once.

The events would smooth out / load throughout the second, instead of in bulk. So even though it performs a bit worse, on big servers it may still avoid CPU spikes.
Actually as someone said, let's stop pretending like we know what is going on in the engine. I cannot tell whether filling the event stack with 500 events all the time is slower or faster than calling for a players table each second. I don't think you can either. So leave that alone or call in someone who might know.

Aside from that, it's very obvious creaturescripts is the fastest approach. Our previous discussion was not about what is faster, but rather how much faster?
 
@Znote
This is my logic why I think globalEvent is better than addEvent chain:

Every time you call Lua function, it goes trough LuascriptInterface. before the return values are processed by the engine.
I globalEvent feature you use: 4 functions
in addEvent feature you use: 5 functions (addEvent is 5th)

You maybe think Game.getPlayers() is huge issue because it creates and returns entire online playerlist.
Constructing Player(playerID) is actually means it loops trough all online players and compares if the the given parameter exist in the playerlist, before it returns the correct player userdata.

Hence with 500 people online, you tap into the playerlist 500 times.
where with globalevent you simply return the entire playerlist once regadless of online player amount.
But not only that, if someone logs out within 1 sec, you still going to try to fetch the player with addEvent, so a little addition there too.

The only benefit of addEvent I see right now is that the requests are divided troughout few milliseconds so it wont cause any hickups, but then again if server cant handle such small amount of requests per sec it does require a hardware update. Or use creaturescript instead of globalevent. What logically should have same speed as gobalevent, but doesn't execute all the requests at once.
 
Probably goes back to what Colandus said, speculations as to what happens in the backend.
For instance, if cid value is used as a key in an online list array, you don't have to traverse it.

PHP sample:
PHP:
$onlinecreatures = array(
    0 => array(
        'getName' => 'Znote',
        'isPlayer' => true,
        'getMana' => 60,
        'getMaxMana' => 100,
    ),
    1 => array(
        'getName' => 'Colandus',
        'isPlayer' => true,
        'getMana' => 120,
        'getMaxMana' => 120,
    ),
    2 => array(
        'getName' => 'Whiteevo',
        'isPlayer' => true,
        'getMana' => 90,
        'getMaxMana' => 110,
    ),
    3 => array(
        'getName' => 'Orc Berserker',
        'isPlayer' => false,
        'getMana' => 100,
        'getMaxMana' => 100,
    )
);

$cid = 2; // Cid represent index/key of online/active creature list.

$player = $onlinecreatures[$cid]; // local player = Player(cid)
echo $player['getName']; // player:getName()

The PHP code is able to find the correct creature object because cid is a reference to where the object is in the array. So you do not need to loop through the array to find which element match cid.
 
Last edited:
Probably goes back to what Colandus said, speculations as to what happens in the backend.
For instance, if cid value is used as a key in an online list array, you don't have to traverse it.

PHP sample:
PHP:
$onlinecreatures = array(
    0 => array(
        'getName' => 'Znote',
        'isPlayer' => true,
        'getMana' => 60,
        'getMaxMana' => 100,
    ),
    1 => array(
        'getName' => 'Colandus',
        'isPlayer' => true,
        'getMana' => 120,
        'getMaxMana' => 120,
    ),
    2 => array(
        'getName' => 'Whiteevo',
        'isPlayer' => true,
        'getMana' => 90,
        'getMaxMana' => 110,
    ),
    3 => array(
        'getName' => 'Orc Berserker',
        'isPlayer' => false,
        'getMana' => 100,
        'getMaxMana' => 100,
    )
);

$cid = 2; // Cid represent index/key of online/active creature list.

$player = $onlinecreatures[$cid]; // local player = Player(cid)
echo $player['getName']; // player:getName()

The PHP code is able to find the correct creature object because cid is a reference to where the object is in the array. So you do not need to loop through the array to find which element match cid.

Please do not use meme language as a reference.
 
@Znote
are you sure $onlinecreatures[$cid] is not short solution for looping trough table and returning the requested value?

I'm very bad at coding terms, I was trying to find in google how the tables are stored in memory and what happens if values is requested by key, found no good results.
 
Back
Top