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

CreatureEvent [TFS 1.x] Award premium points on level advance

forgee

Veteran OT User
Joined
May 9, 2011
Messages
328
Solutions
18
Reaction score
286
Location
Sweden
GitHub
forgee
I made this after it was requested here.
Not much to say, players are awarded premium points for reaching certain levels. See script comments for configuration.

Supports TFS 1.0+.
Works with both Gesior and ZnoteAAC, probably works with any AAC as long as you know where the points are stored.

creaturescripts.xml:
Code:
<event type="login" name="register_points_reward" script="points_reward.lua"/>
<event type="advance" name="points_reward" script="points_reward.lua"/>

points_reward.lua:
Code:
--[[
    Award premium points for reaching certain levels
    Only for TFS 1.0+

    config:
        You need to know where premium points are stored in the database
        Below are the values for Gesior and ZnoteAAC
       
        db_table:             ZnoteAAC: 'znote_accounts'    Gesior: 'accounts'
        db_pointsColumn:     ZnoteAAC: 'points'            Gesior: 'premium_points'
        db_idColumn:         ZnoteAAC: 'account_id'        Gesior: 'id'

        storage:        set to a unused storage value
        messageType:    set the type of message the player receives, for example MESSAGE_STATUS_CONSOLE_BLUE

    rewards:
        Configure the amount of points awarded for reaching a certain level
        format:    [level] = points
]]

local config = {
    storage = 123, -- Select unused storage
    messageType = MESSAGE_STATUS_CONSOLE_BLUE,
    db_table = 'accounts',
    db_pointsColumn = 'premium_points',
    db_idColumn = 'id',
}

local rewards = {
    --[level] = points
    [50] = 1,
    [100] = 5,
    [200] = 10,
}
-- End config

function onAdvance(player, skill, oldLevel, newLevel)
    player = Player(player) -- for TFS 1.0
    if not player then
        return true
    end
    if skill == SKILL_LEVEL then
        if newLevel > player:getStorageValue(config.storage) then
            player:setStorageValue(config.storage, newLevel)
            local points = 0
            for i = oldLevel + 1, newLevel do
                if rewards[i] then
                    points = points + rewards[i]
                    player:sendTextMessage(config.messageType, string.format("Congratulations! You have been awarded %s premium point%s for reaching level %s!", rewards[i], rewards[i] > 1 and "s" or "", i))
                end
            end
            if points > 0 then
                db.asyncQuery("UPDATE `"..config.db_table.."` SET `"..config.db_pointsColumn.."` = `"..config.db_pointsColumn.."` + "..points.." WHERE `"..config.db_idColumn.."` = "..player:getAccountId())
            end
        end
    end
    return true
end

function onLogin(player)
    player = Player(player) -- for TFS 1.0
    if player then
        player:registerEvent("points_reward")
    end   
    return true
end
 
[Warning - Event::checkScript] Can not load script: scripts/points_reward.lua
data/creaturescripts/scripts/points_reward.lua:64: 'end' expected (to close 'fun
ction' at line 45) near '<eof>'

Anything we can do?
 
Copy the script again and make sure you get all the lines. It looks like you missed the last line or two.
 
I made this after it was requested here.
Not much to say, players are awarded premium points for reaching certain levels. See script comments for configuration.

Supports TFS 1.0+.
Works with both Gesior and ZnoteAAC, probably works with any AAC as long as you know where the points are stored.

creaturescripts.xml:
Code:
<event type="login" name="register_points_reward" script="points_reward.lua"/>
<event type="advance" name="points_reward" script="points_reward.lua"/>

points_reward.lua:
Code:
--[[
    Award premium points for reaching certain levels
    Only for TFS 1.0+

    config:
        You need to know where premium points are stored in the database
        Below are the values for Gesior and ZnoteAAC
      
        db_table:             ZnoteAAC: 'znote_accounts'    Gesior: 'accounts'
        db_pointsColumn:     ZnoteAAC: 'points'            Gesior: 'premium_points'
        db_idColumn:         ZnoteAAC: 'account_id'        Gesior: 'id'

        storage:        set to a unused storage value
        messageType:    set the type of message the player receives, for example MESSAGE_STATUS_CONSOLE_BLUE

    rewards:
        Configure the amount of points awarded for reaching a certain level
        format:    [level] = points
]]

local config = {
    storage = 123, -- Select unused storage
    messageType = MESSAGE_STATUS_CONSOLE_BLUE,
    db_table = 'accounts',
    db_pointsColumn = 'premium_points',
    db_idColumn = 'id',
}

local rewards = {
    --[level] = points
    [50] = 1,
    [100] = 5,
    [200] = 10,
}
-- End config

function onAdvance(player, skill, oldLevel, newLevel)
    player = Player(player) -- for TFS 1.0
    if not player then
        return true
    end
    if skill == SKILL_LEVEL then
        if newLevel > player:getStorageValue(config.storage) then
            player:setStorageValue(config.storage, newLevel)
            local points = 0
            for i = oldLevel + 1, newLevel do
                if rewards[i] then
                    points = points + rewards[i]
                    player:sendTextMessage(config.messageType, string.format("Congratulations! You have been awarded %s premium point%s for reaching level %s!", rewards[i], rewards[i] > 1 and "s" or "", i))
                end
            end
            if points > 0 then
                db.asyncQuery("UPDATE `"..config.db_table.."` SET `"..config.db_pointsColumn.."` = `"..config.db_pointsColumn.."` + "..points.." WHERE `"..config.db_idColumn.."` = "..player:getAccountId())
            end
        end
    end
    return true
end

function onLogin(player)
    player = Player(player) -- for TFS 1.0
    if player then
        player:registerEvent("points_reward")
    end  
    return true
end

Could you add in this script that only first 10 players who reach xx level receive premium points? I would be grateful for that.
 
Could you add in this script that only first 10 players who reach xx level receive premium points? I would be grateful for that.
Here is a quick edit, I didn't test it so let me know if it works.
It will create a file called points_reward.save in "data/creaturescripts" (next to creaturescripts.xml), if you need to reset the counter just delete this file.
Code:
--[[
    Award premium points for reaching certain levels
    Only for TFS 1.0+

    config:
        You need to know where premium points are stored in the database
        Below are the values for Gesior and ZnoteAAC
       
        db_table:             ZnoteAAC: 'znote_accounts'    Gesior: 'accounts'
        db_pointsColumn:     ZnoteAAC: 'points'            Gesior: 'premium_points'
        db_idColumn:         ZnoteAAC: 'account_id'        Gesior: 'id'

        storage:        set to a unused storage value
        messageType:    set the type of message the player receives, for example MESSAGE_STATUS_CONSOLE_BLUE
        maxPlayers:     set the number of players that can get the reward for each level or false to disable

    rewards:
        Configure the amount of points awarded for reaching a certain level
        format:    [level] = points
]]

local config = {
    storage = 123, -- Select unused storage
    messageType = MESSAGE_STATUS_CONSOLE_BLUE,
    db_table = 'accounts',
    db_pointsColumn = 'premium_points',
    db_idColumn = 'id',
    maxPlayers = 10, -- Set to false to allow everyone the get the rewards
}

local rewards = {
    --[level] = points
    [50] = 1,
    [100] = 5,
    [200] = 10,
}
-- End config

local counts = {} -- Leave this as is

-- Serialize table
local defaultIndent = "    "
function table.serialize(t, pretty, prettyIndent)
    local indentLevel = 0
    local prettyIndent = prettyIndent or defaultIndent
    local function indentLine(level, indentation)
        local s, i = "\n", 0
        while (i < level) do
            s = s .. indentation
            i = i + 1
        end
        return s
    end
    local function rec(t)
        local s = "{"
        indentLevel = indentLevel + 1
        for k, v in pairs(t) do
            if k and v then
                s = s .. (pretty and indentLine(indentLevel, prettyIndent) or "")
                if type(k) == "number" then
                    s = s .. "["..k.."] = "
                else
                    s = s .. '["'..k..'"] = '
                end
                if type(v) == "table" then
                    s = s .. rec(v)
                elseif type(v) == "string" then
                    s = s .. db.escapeString(v)
                elseif type(v) == "number" then
                    s = s .. tostring(v)
                elseif type(v) == "boolean" then
                    --v = v and "true" or "false"
                    s = s .. (v and "true" or "false")
                elseif type(v) == "function" then
                    s = s .. string.dump(v)
                end
                s = s .. ","
            end
        end
        indentLevel = indentLevel - 1
        s = s .. (pretty and indentLine(indentLevel, prettyIndent) or "") .. "}"
        return s
    end
   
    return rec(t)
end

-- Unserialize table from string
function table.unserialize(str)
    str = str or ""
    local text = loadstring("return " .. str)
    if text then
        return text()
    end
    return nil
end

local function load()
    local file = io.open("data/creaturescripts/points_reward.save", "r")
    if file then
        counts = table.unserialize(file:read("*a"))
        file:close()
    else
        for level, _ in pairs(rewards) do
            counts[level] = 0
        end
    end
end

local function update(level)
    counts[level] = counts[level] + 1
    local file, err = io.open("data/creaturescripts/points_reward.save", "w")
    if file then
        file:write(table.serialize(counts))
        file:close()
    else
        print(err)
    end
end

local function check(level)
    return counts[level] <= config.maxPlayers
end

load()

function onAdvance(player, skill, oldLevel, newLevel)
    player = Player(player) -- for TFS 1.0
    if not player then
        return true
    end
    if skill == SKILL_LEVEL then
        if newLevel > player:getStorageValue(config.storage) then
            player:setStorageValue(config.storage, newLevel)
            local points = 0
            for i = oldLevel + 1, newLevel do
                if rewards[i] then
                    if not config.maxPlayers or check(i) then
                        points = points + rewards[i]
                        if config.maxPlayers then
                            player:sendTextMessage(config.messageType, string.format("Congratulations! You are among the first %s players to reach level %s and have been awarded %s premium point%s!", config.maxPlayers, i, rewards[i], rewards[i] > 1 and "s" or ""))
                            update(i)
                        else
                            player:sendTextMessage(config.messageType, string.format("Congratulations! You have been awarded %s premium point%s for reaching level %s!", rewards[i], rewards[i] > 1 and "s" or "", i))
                        end
                    end
                end
            end
            if points > 0 then
                db.asyncQuery("UPDATE `"..config.db_table.."` SET `"..config.db_pointsColumn.."` = `"..config.db_pointsColumn.."` + "..points.." WHERE `"..config.db_idColumn.."` = "..player:getAccountId())
            end
        end
    end
    return true
end

function onLogin(player)
    player = Player(player) -- for TFS 1.0
    if player then
        player:registerEvent("points_reward")
    end  
    return true
end
 
Here is a quick edit, I didn't test it so let me know if it works.
It will create a file called points_reward.save in "data/creaturescripts" (next to creaturescripts.xml), if you need to reset the counter just delete this file.
Code:
--[[
    Award premium points for reaching certain levels
    Only for TFS 1.0+

    config:
        You need to know where premium points are stored in the database
        Below are the values for Gesior and ZnoteAAC
      
        db_table:             ZnoteAAC: 'znote_accounts'    Gesior: 'accounts'
        db_pointsColumn:     ZnoteAAC: 'points'            Gesior: 'premium_points'
        db_idColumn:         ZnoteAAC: 'account_id'        Gesior: 'id'

        storage:        set to a unused storage value
        messageType:    set the type of message the player receives, for example MESSAGE_STATUS_CONSOLE_BLUE
        maxPlayers:     set the number of players that can get the reward for each level or false to disable

    rewards:
        Configure the amount of points awarded for reaching a certain level
        format:    [level] = points
]]

local config = {
    storage = 123, -- Select unused storage
    messageType = MESSAGE_STATUS_CONSOLE_BLUE,
    db_table = 'accounts',
    db_pointsColumn = 'premium_points',
    db_idColumn = 'id',
    maxPlayers = 10, -- Set to false to allow everyone the get the rewards
}

local rewards = {
    --[level] = points
    [50] = 1,
    [100] = 5,
    [200] = 10,
}
-- End config

local counts = {} -- Leave this as is

-- Serialize table
local defaultIndent = "    "
function table.serialize(t, pretty, prettyIndent)
    local indentLevel = 0
    local prettyIndent = prettyIndent or defaultIndent
    local function indentLine(level, indentation)
        local s, i = "\n", 0
        while (i < level) do
            s = s .. indentation
            i = i + 1
        end
        return s
    end
    local function rec(t)
        local s = "{"
        indentLevel = indentLevel + 1
        for k, v in pairs(t) do
            if k and v then
                s = s .. (pretty and indentLine(indentLevel, prettyIndent) or "")
                if type(k) == "number" then
                    s = s .. "["..k.."] = "
                else
                    s = s .. '["'..k..'"] = '
                end
                if type(v) == "table" then
                    s = s .. rec(v)
                elseif type(v) == "string" then
                    s = s .. db.escapeString(v)
                elseif type(v) == "number" then
                    s = s .. tostring(v)
                elseif type(v) == "boolean" then
                    --v = v and "true" or "false"
                    s = s .. (v and "true" or "false")
                elseif type(v) == "function" then
                    s = s .. string.dump(v)
                end
                s = s .. ","
            end
        end
        indentLevel = indentLevel - 1
        s = s .. (pretty and indentLine(indentLevel, prettyIndent) or "") .. "}"
        return s
    end
  
    return rec(t)
end

-- Unserialize table from string
function table.unserialize(str)
    str = str or ""
    local text = loadstring("return " .. str)
    if text then
        return text()
    end
    return nil
end

local function load()
    local file = io.open("data/creaturescripts/points_reward.save", "r")
    if file then
        counts = table.unserialize(file:read("*a"))
        file:close()
    else
        for level, _ in pairs(rewards) do
            counts[level] = 0
        end
    end
end

local function update(level)
    counts[level] = counts[level] + 1
    local file, err = io.open("data/creaturescripts/points_reward.save", "w")
    if file then
        file:write(table.serialize(counts))
        file:close()
    else
        print(err)
    end
end

local function check(level)
    return counts[level] <= config.maxPlayers
end

load()

function onAdvance(player, skill, oldLevel, newLevel)
    player = Player(player) -- for TFS 1.0
    if not player then
        return true
    end
    if skill == SKILL_LEVEL then
        if newLevel > player:getStorageValue(config.storage) then
            player:setStorageValue(config.storage, newLevel)
            local points = 0
            for i = oldLevel + 1, newLevel do
                if rewards[i] then
                    if not config.maxPlayers or check(i) then
                        points = points + rewards[i]
                        if config.maxPlayers then
                            player:sendTextMessage(config.messageType, string.format("Congratulations! You are among the first %s players to reach level %s and have been awarded %s premium point%s!", config.maxPlayers, i, rewards[i], rewards[i] > 1 and "s" or ""))
                            update(i)
                        else
                            player:sendTextMessage(config.messageType, string.format("Congratulations! You have been awarded %s premium point%s for reaching level %s!", rewards[i], rewards[i] > 1 and "s" or "", i))
                        end
                    end
                end
            end
            if points > 0 then
                db.asyncQuery("UPDATE `"..config.db_table.."` SET `"..config.db_pointsColumn.."` = `"..config.db_pointsColumn.."` + "..points.." WHERE `"..config.db_idColumn.."` = "..player:getAccountId())
            end
        end
    end
    return true
end

function onLogin(player)
    player = Player(player) -- for TFS 1.0
    if player then
        player:registerEvent("points_reward")
    end 
    return true
end


Hey! Thanks you for your fast answer.
The script is giving points for level and sending message to player but there are 2 bugs :

1. the file points_reward.save cant be created because of permissions (console error: data/creaturescripts/points_reward.save: Permission denied)
2. this is just the little bug in the message : 15:59 Congratulations! You are among the first 2 players to reach level 200 and have been awarded 10 premium points! [Missing the "of" in : You are among the first of x players..] :p
3. Could you make the broadcast in general for every players not just the one who reach x lvl. They will know like that if they have to speed to lvl up with a chance to get points or not. If ou know what i mean ^^
 
Hey! Thanks you for your fast answer.
The script is giving points for level and sending message to player but there are 2 bugs :

1. the file points_reward.save cant be created because of permissions (console error: data/creaturescripts/points_reward.save: Permission denied)
2. this is just the little bug in the message : 15:59 Congratulations! You are among the first 2 players to reach level 200 and have been awarded 10 premium points! [Missing the "of" in : You are among the first of x players..] :p
3. Could you make the broadcast in general for every players not just the one who reach x lvl. They will know like that if they have to speed to lvl up with a chance to get points or not. If ou know what i mean ^^
1. I thought the server would have write access in the data directory. You can create the file yourself and set read/write permissions for the user account the server is running under.
2. I would say "You are among the first 2", without "of", but you can of course edit the message to your preference.
3. Yes.

I can send you a script in PM and once we get the details ironed out I will update this thread.
 
Hi Forge!
Thanks for the script. I'm having some issues inplementing this on my server. I'm running @Nekiro 8.6 downgrade based on TFS 1.3 and MyAAC.
Config in others/advance_prem_points.lua is:
Lua:
local config = {
    storage = 5637, -- Select unused storage
    messageType = MESSAGE_STATUS_CONSOLE_BLUE,
    db_table = 'accounts',
    db_pointsColumn = 'premium_points',
    db_idColumn = 'id',
}
creaturescripts.xml
XML:
    <event type="advance" name="points_reward" script="others/advance_prem_points.lua" />   
    <event type="login" name="register_points_reward" script="others/advance_prem_points.lua" />

I get no errors in the server logs.. Can't figure out what im doing wrong.
 
For anyone looking, I was able to solve this problem by changing the following lines. It did not work before i declared current storagevalue to a variable to use in the if-loop.
Lua:
if skill == SKILL_LEVEL then
        if newLevel > player:getStorageValue(config.storage) then
            player:setStorageValue(config.storage, newLevel)
            local points = 0
            for i = oldLevel + 1, newLevel do
                if rewards[i] then
                    points = points + rewards[i]
                    player:sendTextMessage(config.messageType, string.format("Congratulations! You have been awarded %s premium point%s for reaching level %s!", rewards[i], rewards[i] > 1 and "s" or "", i))
                end
            end
            if points > 0 then
                db.asyncQuery("UPDATE `"..config.db_table.."` SET `"..config.db_pointsColumn.."` = `"..config.db_pointsColumn.."` + "..points.." WHERE `"..config.db_idColumn.."` = "..player:getAccountId())
            end
        end
    end
to
Lua:
if skill == SKILL_LEVEL then
local storagevar = player:getStorageValue(config.storage)
        if newLevel > storagevar then
            player:setStorageValue(config.storage, newLevel)
            local points = 0
            for i = oldLevel + 1, newLevel do
                if rewards[i] then
                    points = points + rewards[i]
                    player:sendTextMessage(config.messageType, string.format("Congratulations! You have been awarded %s premium point%s for reaching level %s!", rewards[i], rewards[i] > 1 and "s" or "", i))
                end
            end
            if points > 0 then
                db.asyncQuery("UPDATE `"..config.db_table.."` SET `"..config.db_pointsColumn.."` = `"..config.db_pointsColumn.."` + "..points.." WHERE `"..config.db_idColumn.."` = "..player:getAccountId())
            end
        end
    end
 
Back
Top