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

Lua [SOLVED] VIPs lose 20% less XP when die TFS 1.3

3221920

New Member
Joined
May 9, 2023
Messages
12
Reaction score
2
Location
España
Hello.

First of all, thank you for reading this post.

Is it possible that someone can help me develop a script/system that makes VIP players on my server lose 20% less experience when they die?

Let me explain myself a little better: my server has blessings and a lower penalty if you have the promotion, I use a VIP system that doesnt use storagevalue, its by "isVip". I would like the script to check if the player is a VIP and if so, when this character dies, he will lose 20% less experience due to that death. I've tried a couple of things with creaturescripts but haven't made any changes. I would like to avoid anything that requires recompiling if possible.

I am using tfs 1.3 and my server is 8.60. If I am forgetting to provide any important information, let me know.

Thank you so much.
 
Hello, little information, right? Maybe show your vip script, so we can get an idea of how to check this.


Lua:
    if isVIP(playerId) then
        local penaltyPercentage = 5 -- ajuste conforme necessário
        local playerExperience = player:getExperience()
        local experienceLoss = math.floor(playerExperience * (penaltyPercentage / 100))
        
        player:addExperience(-experienceLoss)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Como você é um jogador VIP, você perdeu " .. penaltyPercentage .. "% da sua experiência.")
    end
 
Hello, little information, right? Maybe show your vip script, so we can get an idea of how to check this.


Lua:
    if isVIP(playerId) then
        local penaltyPercentage = 5 -- ajuste conforme necessário
        local playerExperience = player:getExperience()
        local experienceLoss = math.floor(playerExperience * (penaltyPercentage / 100))
       
        player:addExperience(-experienceLoss)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Como você é um jogador VIP, você perdeu " .. penaltyPercentage .. "% da sua experiência.")
    end
hello, thanks for answering me ^^. I'm using this vip system
Lua:
local config = {
    -- true = player will be teleported to this position if Vip runs out
    -- false = player will not be teleported
    useTeleport = true,
    expirationPosition = Position(797, 741, 2),

    -- true = player will received the message you set
    -- false = player will not receive a message
    useMessage = true,
    expirationMessage = 'Your VIP time is over, renew to continue enjoying all the VIP benefits.',
    expirationMessageType = MESSAGE_STATUS_WARNING
}

if not VipData then
    VipData = { }
end

function Player.onRemoveVip(self)
    if config.useTeleport then
        self:teleportTo(config.expirationPosition)
        config.expirationPosition:sendMagicEffect(CONST_ME_TELEPORT)
    end

    if config.useMessage then
        self:sendTextMessage(config.expirationMessageType, config.expirationMessage)
    end
end

function Player.getVipDays(self)
    return VipData[self:getId()].days
end

function Player.getLastVipDay(self)
    return VipData[self:getId()].lastDay
end

function Player.isVip(self)
    return self:getVipDays() > 0
end

function Player.addInfiniteVip(self)
    local data = VipData[self:getId()]
    data.days = 0xFFFF
    data.lastDay = 0

    db.query(string.format('UPDATE `accounts` SET `vipdays` = %i, `viplastday` = %i WHERE `id` = %i;', 0xFFFF, 0, self:getAccountId()))
end

function Player.addVipDays(self, amount)
    local data = VipData[self:getId()]
    local amount = math.min(0xFFFE - data.days, amount)
    if amount > 0 then
        if data.days == 0 then
            local time = os.time()
            db.query(string.format('UPDATE `accounts` SET `vipdays` = `vipdays` + %i, `viplastday` = %i WHERE `id` = %i;', amount, time, self:getAccountId()))
            data.lastDay = time
        else
            db.query(string.format('UPDATE `accounts` SET `vipdays` = `vipdays` + %i WHERE `id` = %i;', amount, self:getAccountId()))
        end
        data.days = data.days + amount
    end

    return true
end

function Player.removeVipDays(self, amount)
    local data = VipData[self:getId()]
    if data.days == 0xFFFF then
        return false
    end

    local amount = math.min(data.days, amount)
    if amount > 0 then
        db.query(string.format('UPDATE `accounts` SET `vipdays` = `vipdays` - %i WHERE `id` = %i;', amount, self:getAccountId()))
        data.days = data.days - amount

        if data.days == 0 then
            self:onRemoveVip()
        end
    end

    return true
end

function Player.removeVip(self)
    local data = VipData[self:getId()]
    if data.days == 0 then
        return
    end

    data.days = 0
    data.lastDay = 0

    self:onRemoveVip()

    db.query(string.format('UPDATE `accounts` SET `vipdays` = 0, `viplastday` = 0 WHERE `id` = %i;', self:getAccountId()))
end

function Player.loadVipData(self)
    local resultId = db.storeQuery(string.format('SELECT `vipdays`, `viplastday` FROM `accounts` WHERE `id` = %i;', self:getAccountId()))
    if resultId then
        VipData[self:getId()] = {
            days = result.getDataInt(resultId, 'vipdays'),
            lastDay = result.getDataInt(resultId, 'viplastday')
        }

        result.free(resultId)
        return true
    end

    VipData[self:getId()] = { days = 0, lastDay = 0 }
    return false
end

function Player.updateVipTime(self)
    local save = false

    local data = VipData[self:getId()]
    local days, lastDay = data.days, data.lastDay
    local daysBefore = days
    if days == 0 or days == 0xFFFF then
        if lastDay ~= 0 then
            lastDay = 0
            save = true
        end
    elseif lastDay == 0 then
        lastDay = os.time()
        save = true
    else
        local time = os.time()
        local elapsedDays = math.floor((time - lastDay) / 86400)
        if elapsedDays > 0 then
            if elapsedDays >= days then
                days = 0
                lastDay = 0
            else
                days = days - elapsedDays
                lastDay = time - ((time - lastDay) % 86400)
            end
            save = true
        end
    end

    if save then
        if daysBefore > 0 and days == 0 then
            self:onRemoveVip()
        end

        db.query(string.format('UPDATE `accounts` SET `vipdays` = %i, `viplastday` = %i WHERE `id` = %i;', days, lastDay, self:getAccountId()))
        data.days = days
        data.lastDay = lastDay
    end
end

I tried to use the script that you gave me as a creature script in this way and it didn't work for me. maybe I'm doing something wrong.

data\creaturescripts\scripts
Lua:
function onPrepareDeath(player, killer, corpse, deathList)
    if player:isVip() then
        local penaltyPercentage = 5 -- Ajusta el porcentaje según sea necesario
        local playerExperience = player:getExperience()
        local experienceLoss = math.floor(playerExperience * (penaltyPercentage / 100))
        
        player:addExperience(-experienceLoss)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Como você é um jogador VIP, você perdeu " .. penaltyPercentage .. "% da sua experiência.")
    end
end

Code:
player:registerEvent("vipdeath")

XML:
<event type="preparedeath" name="vipdeath" script="vipdeath.lua"/>
 
Revscripts

Lua:
local creatureevent = CreatureEvent("VIPExperienceLoss")

function creatureevent.onPrepareDeath(creature, killer)
    if creature:isPlayer() then
        local player = Player(creature)
        if player:isVip() then
            local penaltyPercentage = 20 -- Adjust as needed (20% in this example)
            local playerExperience = player:getExperience()
            local experienceLoss = math.floor(playerExperience * (penaltyPercentage / 100))
           
            player:addExperience(-experienceLoss)
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Since you are a VIP player, you lost " .. penaltyPercentage .. "% of your experience.")
        end
    end
end


creatureevent:register()
 
Revscripts

Lua:
local creatureevent = CreatureEvent("VIPExperienceLoss")

function creatureevent.onPrepareDeath(creature, killer)
    if creature:isPlayer() then
        local player = Player(creature)
        if player:isVip() then
            local penaltyPercentage = 20 -- Adjust as needed (20% in this example)
            local playerExperience = player:getExperience()
            local experienceLoss = math.floor(playerExperience * (penaltyPercentage / 100))
          
            player:addExperience(-experienceLoss)
            player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "Since you are a VIP player, you lost " .. penaltyPercentage .. "% of your experience.")
        end
    end
end


creatureevent:register()
I'm afraid my distribution does not support revscript. Is there any way to adapt it? Thanks a lot.
 
Lua:
local vipLossRate = 0.20

function onPrepareDeath(cid, lastHitKiller, mostDamageKiller)
    local player = Player(cid)

    if player:isVip() then
        local experienceLoss = math.ceil(player:getExperience() * vipLossRate)
        player:sendTextMessage(MESSAGE_STATUS_WARNING, "You lost " .. experienceLoss .. " of experience when dying.")
        player:setDeathPenalty(PLAYERLOSS_EXPERIENCE, experienceLoss)
    end

    return true
end
 
Last edited:
Lua:
local vipLossRate = 0.20

function onPrepareDeath(cid, lastHitKiller, mostDamageKiller)
    local p = getPosition(cid)

    if player:isVip(cid) then
        local experienceLoss = math.ceil(getExperience(cid) * vipLossRate)
        player:sendTextMessage(cid, MESSAGE_STATUS_WARNING, "You lost " .. experienceLoss .. " of experience when dying.")
        player.setDeathPenalty(cid, PLAYERLOSS_EXPERIENCE, experienceLoss)
    end

    return true
end

add player = Player(cid)
otherwise player will be nil
 
Thanks to both of you. I have copied the corrected script and now what happens is that the non VIP players die normally but the VIP players cannot die and it continuously displays the message seen in the image.

Code:
You lost 25877960 of experience when dying.
1694900316057.png
In creaturescript.xml I have the following:
XML:
<event type="preparedeath" name="vipdeath" script="vipdeath.lua"/>

EDIT:
I have this error in console

Code:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/vipdeath.lua:onPrepareDeath
data/creaturescripts/scripts/vipdeath.lua:9: attempt to call method 'setDeathPenalty' (a nil value)
stack traceback:
        [C]: in function 'setDeathPenalty'
        data/creaturescripts/scripts/vipdeath.lua:9: in function <data/creaturescripts/scripts/vipdeath.lua:3>
 
Last edited:
Lua:
local vipLossRate = 0.20

function onPrepareDeath(cid, lastHitKiller, mostDamageKiller)
    local player = Player(cid)

    if player:isVip() then
        local experienceLoss = math.ceil(player:getExperience() * vipLossRate)
        player:sendTextMessage(MESSAGE_STATUS_WARNING, "You lost " .. experienceLoss .. " of experience when dying.")
        player:addExperience(-experienceLoss)
    end

    return true
end
 
Lua:
local vipLossRate = 0.20

function onPrepareDeath(cid, lastHitKiller, mostDamageKiller)
    local player = Player(cid)

    if player:isVip() then
        local experienceLoss = math.ceil(player:getExperience() * vipLossRate)
        player:sendTextMessage(MESSAGE_STATUS_WARNING, "You lost " .. experienceLoss .. " of experience when dying.")
        player:addExperience(-experienceLoss)
    end

    return true
end
I think we are about to achieve it, now I notice that at least it affects the character. The problem I'm seeing is that the script causes the player to lose "x" percentage of experience upon death with each death, regardless of whether they have blessings or promotion. I think it is directly reducing the default exp loss of my server by 20% without adding to the other variables. As it is now, VIPs even lose more exp than non-VIP players, but I'm excited, it's the first of all the attempts that really shows its effect on the character and doesnt show errors.
 
The onDeath function was used to handle a player's death and apply death penalty logic to VIP players only.
Lua:
local vipExperienceBonus = 0.20

function onDeath(cid, corpse, killer)
    local player = Player(cid)

    if player:isVip() then
        local experienceLoss = math.ceil(player:getExperience() * (1 - vipExperienceBonus))
        player:sendTextMessage(MESSAGE_STATUS_WARNING, "You lost " .. experienceLoss .. " of experience when dying.")
        player:addExperience(-experienceLoss)
    end

    return true
end
 
I'm thinking about how to turn the issue around and it occurs to me that perhaps what the script could do is simply determine how much experience the player has lost and return 20% of it. I don't know if this path we are following is easier or this other one that occurs to me. I have been trying to modify what you are giving me with chatgpt but I can't get it to help me as much as you do.
 

Attachments

EDIT:
I found a solution thanks to the suggestions made to me in this post, that's why I decided to share with everyone the solution and the system that resulted. At the end of the day, this is a community made to share knowledge and if I have relied so much on the content of the forum I can also contribute with something.

I have divided the system into two creaturescripts, an onlogin event and an ondeath event, so the system can determine the values before dying and grant the reward after connecting.

Note: It has not been possible for me to determine exactly 20% because there are many variables that intervene such as blessings or promotion, but by adjusting the value of vipExperienceBonus it can be regulated according to need.
XML:
    <event type="death" name="vipdeath" script="vipdeath.lua"/>
    <event type="login" name="vipdeathlogin" script="vipdeathlogin.lua"/>

vipdeath.lua
Lua:
local vipExperienceBonus = 0.30

function onDeath(cid, corpse, killer)
    local player = Player(cid)

    if player:isVip() then
        local experienceBeforeDeath = player:getExperience()
        player:setStorageValue(STORAGE_VIP_EXPERIENCE_BEFORE_DEATH, experienceBeforeDeath)
    end

    return true
end
vipdeathlogin.lua
Lua:
function onLogin(cid)
    local player = Player(cid)
    local experienceBeforeDeath = player:getStorageValue(STORAGE_VIP_EXPERIENCE_BEFORE_DEATH)
    local vipExperienceBonus = 0.30
    
    if experienceBeforeDeath > 0 then
        local experienceAfterDeath = player:getExperience()
        local experienceLost = experienceBeforeDeath - experienceAfterDeath
        local experienceRestored = math.ceil(experienceLost * vipExperienceBonus)
        
        if experienceRestored > 0 then
            player:addExperience(experienceRestored, true)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You received an experience bonus for your previous death becouse you are a VIP player.")
        end
        
        player:setStorageValue(STORAGE_VIP_EXPERIENCE_BEFORE_DEATH, 0)
    end

    return true
end

event registration in login.lua
Lua:
player:registerEvent("vipdeath")
player:registerEvent("vipdeathlogin")

If you have any suggestions to improve it, I am open to listening.

Thanks to all of you.

Reference images of how it works.
1694953974114.png
1694954010043.png1694954028945.png
 
Last edited:
EDIT:
I found a solution thanks to the suggestions made to me in this post, that's why I decided to share with everyone the solution and the system that resulted. At the end of the day, this is a community made to share knowledge and if I have relied so much on the content of the forum I can also contribute with something.

I have divided the system into two creaturescripts, an onlogin event and an ondeath event, so the system can determine the values before dying and grant the reward after connecting.

Note: It has not been possible for me to determine exactly 20% because there are many variables that intervene such as blessings or promotion, but by adjusting the value of vipExperienceBonus it can be regulated according to need.
XML:
    <event type="death" name="vipdeath" script="vipdeath.lua"/>
    <event type="login" name="vipdeathlogin" script="vipdeathlogin.lua"/>

vipdeath.lua
Lua:
local vipExperienceBonus = 0.30

function onDeath(cid, corpse, killer)
    local player = Player(cid)

    if player:isVip() then
        local experienceBeforeDeath = player:getExperience()
        player:setStorageValue(STORAGE_VIP_EXPERIENCE_BEFORE_DEATH, experienceBeforeDeath)
    end

    return true
end
vipdeathlogin.lua
Lua:
function onLogin(cid)
    local player = Player(cid)
    local experienceBeforeDeath = player:getStorageValue(STORAGE_VIP_EXPERIENCE_BEFORE_DEATH)
    local vipExperienceBonus = 0.30
   
    if experienceBeforeDeath > 0 then
        local experienceAfterDeath = player:getExperience()
        local experienceLost = experienceBeforeDeath - experienceAfterDeath
        local experienceRestored = math.ceil(experienceLost * vipExperienceBonus)
       
        if experienceRestored > 0 then
            player:addExperience(experienceRestored, true)
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "You received an experience bonus for your previous death becouse you are a VIP player.")
        end
       
        player:setStorageValue(STORAGE_VIP_EXPERIENCE_BEFORE_DEATH, 0)
    end

    return true
end

event registration in login.lua
Lua:
player:registerEvent("vipdeath")
player:registerEvent("vipdeathlogin")

If you have any suggestions to improve it, I am open to listening.

Thanks to all of you.

Reference images of how it works.
View attachment 78488
View attachment 78489View attachment 78490
Glad it resolved! I was about to research and study the case, but you found the solution. Congratulations! This is important for your learning.
 
Back
Top