• 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.4/1.5] Exp arrows on killing monster with chance

Marko999x

999x era
Premium User
Joined
Dec 14, 2017
Messages
2,832
Solutions
82
Reaction score
1,948
Location
Germany
Killing monster has a chance to drop a exp arrow which gives you double exp for next 60 seconds
You must go to the effect to start the double exp like on the gif:

You can check your time by using !exp

The way how its scripted is prob screwed up so im sorry xD im not a lua expert

data/scripts/spiderman.lua
Lua:
local custom_exp_damage_effect = CreatureEvent("custom_exp_damage_effect")

local config = {
    ['Rotworm'] = { chance = 100 }, -- 100 means 1%
    ['Crocodile'] = { chance = 100 },
    ['Mutated Bat'] = { chance = 100 },
    ['Mutated Human'] = { chance = 100 },
    ['Brimstone Bug'] = { chance = 100 },
    ['Troll'] = { chance = 100 },
    ['Coldheart'] = { chance = 100 },
    ['Crazed Beggar'] = { chance = 100 }
}

local function sendMessage(target)
    if not target then
        return true
    end
    target:sendMagicEffect(56)
    target:sendMagicEffect(57)
end

function custom_exp_damage_effect.onKill(creature, target)
    if target:isPlayer() then
        return true
    end
    local monster = config[target:getName()]
    if not monster then
        return true
    end
    if math.random(1, 10000) <= monster.chance then
        local tile = Tile(target:getPosition())
        if tile then
            local ground = tile:getGround()
            if ground then
                ground:setActionId(6000)
                target:say('DOUBLE EXP!', TALKTYPE_MONSTER_SAY)
                for i = 0, 3 do
                    addEvent(sendMessage, 750 * i, target:getPosition())
                end
            end
        end
    end
    return true
end

custom_exp_damage_effect:type("kill")
custom_exp_damage_effect:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local custom_exp_damage_effect_login = CreatureEvent("custom_exp_damage_effect_login")

function custom_exp_damage_effect_login.onLogin(player)
    player:registerEvent("custom_exp_damage_effect")
    return true
end

custom_exp_damage_effect_login:type("login")
custom_exp_damage_effect_login:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local custom_exp_damage_effect_movement = MoveEvent()
custom_exp_damage_effect_movement:type("stepin")

local function sendEffect(cid)
    local player = Player(cid)
    if not player then
        return true
    end
    local pos = player:getPosition()
    local pos2 = player:getPosition() + Position(math.random(-2, 2), math.random(-2, 2), 0)
    pos2:sendDistanceEffect(pos, 31)
end

function custom_exp_damage_effect_movement.onStepIn(player, item, position, fromPosition)
    if player:isMonster() then
        return true
    end
    local tile = Tile(player:getPosition())
    if tile then
        local ground = tile:getGround()
        if ground then
            ground:setActionId()
            player:setStorageValue(6000, os.time() + 60)
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received double experience for the next 60 seconds.')
            for i = 0, 25 do
                addEvent(sendEffect, 100 * i, player:getId())
            end
        end
    end
    return true
end

custom_exp_damage_effect_movement:aid(6000)

custom_exp_damage_effect_movement:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local expCheck = TalkAction("!exp")

local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.fmod(s, 3600)/60)
    local seconds = math.floor(math.fmod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

function expCheck.onSay(player, words)
 
    local exhaust = 6000
    if player:getStorageValue(exhaust) - os.time() > 0 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "Your extra exp will end in : "..player:getStorageValue(exhaust) - os.time().."")
        return false
    end
    return false
end

expCheck:separator(" ")
expCheck:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local ec = EventCallback

function ec.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

ec:register(1)
 
Last edited by a moderator:
Killing monster has a chance to drop a exp arrow which gives you double exp for next 60 seconds
You must go to the effect to start the double exp like on the gif:

You can check your time by using !exp

The way how its scripted is prob screwed up so im sorry xD im not a lua expert

data/scripts/spiderman.lua
Lua:
local custom_exp_damage_effect = CreatureEvent("custom_exp_damage_effect")

local config = {
    ['Rotworm'] = { chance = 100 }, -- 100 means 1%
    ['Crocodile'] = { chance = 100 },
    ['Mutated Bat'] = { chance = 100 },
    ['Mutated Human'] = { chance = 100 },
    ['Brimstone Bug'] = { chance = 100 },
    ['Troll'] = { chance = 100 },
    ['Coldheart'] = { chance = 100 },
    ['Crazed Beggar'] = { chance = 100 }
}

local function sendMessage(target)
    if not target then
        return true
    end
    target:sendMagicEffect(56)
    target:sendMagicEffect(57)
end

function custom_exp_damage_effect.onKill(creature, target)
    if target:isPlayer() then
        return true
    end
    local monster = config[target:getName()]
    if not monster then
        return true
    end
    if math.random(1, 10000) <= monster.chance then
        local tile = Tile(target:getPosition())
        if tile then
            local ground = tile:getGround()
            if ground then
                ground:setActionId(6000)
                target:say('DOUBLE EXP!', TALKTYPE_MONSTER_SAY)
                for i = 0, 3 do
                    addEvent(sendMessage, 750 * i, target:getPosition())
                end
            end
        end
    end
    return true
end

custom_exp_damage_effect:type("kill")
custom_exp_damage_effect:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local custom_exp_damage_effect_login = CreatureEvent("custom_exp_damage_effect_login")

function custom_exp_damage_effect_login.onLogin(player)
    player:registerEvent("custom_exp_damage_effect")
    return true
end

custom_exp_damage_effect_login:type("login")
custom_exp_damage_effect_login:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local custom_exp_damage_effect_movement = MoveEvent()
custom_exp_damage_effect_movement:type("stepin")

local function sendEffect(cid)
    local player = Player(cid)
    if not player then
        return true
    end
    local pos = player:getPosition()
    local pos2 = player:getPosition() + Position(math.random(-2, 2), math.random(-2, 2), 0)
    pos2:sendDistanceEffect(pos, 31)
end

function custom_exp_damage_effect_movement.onStepIn(player, item, position, fromPosition)
    if player:isMonster() then
        return true
    end
    local tile = Tile(player:getPosition())
    if tile then
        local ground = tile:getGround()
        if ground then
            ground:setActionId()
            player:setStorageValue(6000, os.time() + 60)
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received double experience for the next 60 seconds.')
            for i = 0, 25 do
                addEvent(sendEffect, 100 * i, player:getId())
            end
        end
    end
    return true
end

custom_exp_damage_effect_movement:aid(6000)

custom_exp_damage_effect_movement:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local expCheck = TalkAction("!exp")

local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.fmod(s, 3600)/60)
    local seconds = math.floor(math.fmod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

function expCheck.onSay(player, words)
 
    local exhaust = 6000
    if player:getStorageValue(exhaust) - os.time() > 0 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "Your extra exp will end in : "..player:getStorageValue(exhaust) - os.time().."")
        return false
    end
    return false
end

expCheck:separator(" ")
expCheck:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local ec = EventCallback

function ec.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

ec:register(1)
1651342655308.png

when starting the server it shows this error. I made the following change in case this is a creaturescript
Lua:
local EcGainExperience = CreatureEvent("EcGainExperience")

function EcGainExperience.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

EcGainExperience:register(1)

and displays the following error

1651342766261.png

Server Base - Canary
 
View attachment 67449

when starting the server it shows this error. I made the following change in case this is a creaturescript
Lua:
local EcGainExperience = CreatureEvent("EcGainExperience")

function EcGainExperience.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

EcGainExperience:register(1)

and displays the following error

View attachment 67450

Server Base - Canary
Do u use tfs or otbr??
 
when starting the server it shows this error. I made the following change in case this is a creaturescript
Lua:
local EcGainExperience = CreatureEvent("EcGainExperience")

function EcGainExperience.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

EcGainExperience:register(1)

and displays the following error

Server Base - Canary

canary doesn't have eventcallbacks (what a pity 🤭), that is why thread title have [1.4/1.5] on it
 
Great release man, thanks for sharing! I love the effect of powering up :D
 
is there any way to modify this script for the otbr version?

remove this:
Lua:
local ec = EventCallback

function ec.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

ec:register(1)

data/events/player.lua
Search this under onGainExperience:
Lua:
    if not source or source:isPlayer() then
        return exp
    end

and then add this under it:
Lua:
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end

If its not working then no clue sorry :D Im not using otbr
 
Last edited:
remove this:
Lua:
local ec = EventCallback

function ec.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

ec:register(1)

Search this under onGainExperience:
Lua:
    if not source or source:isPlayer() then
        return exp
    end

and then add this under it:
Lua:
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end

If its not working then no clue sorry :D Im not using otbr
thanks, it worked perfectly!
 
I have tested this script on my test server 1.4 TFS but it seems to not work for me at all.
I`m like getting no experience at all anymore.

with or without the exp buff :/
This is my normal onGainExperience method

Lua:
function Player:onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end

    -- Soul regeneration
    local vocation = self:getVocation()
    if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
        soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
        self:addCondition(soulCondition)
    end

    -- Apply experience stage multiplier
    exp = exp * Game.getExperienceStage(self:getLevel())

    -- Stamina modifier
    if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
        useStamina(self)

        local staminaMinutes = self:getStamina()
        if staminaMinutes > 2400 and self:isPremium() then
            exp = exp * 1.5
        elseif staminaMinutes <= 840 then
            exp = exp * 0.5
        end
    end

    return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
end

--- EDIT ---

If I don't use the callback and use it as described for otbr canary it does work... weird...
 
Last edited:
I have tested this script on my test server 1.4 TFS but it seems to not work for me at all.
I`m like getting no experience at all anymore.

with or without the exp buff :/
This is my normal onGainExperience method

Lua:
function Player:onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end

    -- Soul regeneration
    local vocation = self:getVocation()
    if self:getSoul() < vocation:getMaxSoul() and exp >= self:getLevel() then
        soulCondition:setParameter(CONDITION_PARAM_SOULTICKS, vocation:getSoulGainTicks() * 1000)
        self:addCondition(soulCondition)
    end

    -- Apply experience stage multiplier
    exp = exp * Game.getExperienceStage(self:getLevel())

    -- Stamina modifier
    if configManager.getBoolean(configKeys.STAMINA_SYSTEM) then
        useStamina(self)

        local staminaMinutes = self:getStamina()
        if staminaMinutes > 2400 and self:isPremium() then
            exp = exp * 1.5
        elseif staminaMinutes <= 840 then
            exp = exp * 0.5
        end
    end

    return hasEventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE) and EventCallback(EVENT_CALLBACK_ONGAINEXPERIENCE, self, source, exp, rawExp) or exp
end

--- EDIT ---

If I don't use the callback and use it as described for otbr canary it does work... weird...

Does any error appear?
 
I have same problem as Raikou. When I use this script my gain expirience system not working. From every monster I get 0 exp. TFS 1.4. My console show no errors.
 
I have same problem as Raikou. When I use this script my gain expirience system not working. From every monster I get 0 exp. TFS 1.4. My console show no errors.

remove this:
Lua:
local ec = EventCallback

function ec.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

ec:register(1)

data/events/player.lua
Search this under onGainExperience:
Lua:
    if not source or source:isPlayer() then
        return exp
    end

and then add this under it:
Lua:
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end

If its not working then no clue sorry :D Im not using otbr
 
Killing monster has a chance to drop a exp arrow which gives you double exp for next 60 seconds
You must go to the effect to start the double exp like on the gif:

You can check your time by using !exp

The way how its scripted is prob screwed up so im sorry xD im not a lua expert

data/scripts/spiderman.lua
Lua:
local custom_exp_damage_effect = CreatureEvent("custom_exp_damage_effect")

local config = {
    ['Rotworm'] = { chance = 100 }, -- 100 means 1%
    ['Crocodile'] = { chance = 100 },
    ['Mutated Bat'] = { chance = 100 },
    ['Mutated Human'] = { chance = 100 },
    ['Brimstone Bug'] = { chance = 100 },
    ['Troll'] = { chance = 100 },
    ['Coldheart'] = { chance = 100 },
    ['Crazed Beggar'] = { chance = 100 }
}

local function sendMessage(target)
    if not target then
        return true
    end
    target:sendMagicEffect(56)
    target:sendMagicEffect(57)
end

function custom_exp_damage_effect.onKill(creature, target)
    if target:isPlayer() then
        return true
    end
    local monster = config[target:getName()]
    if not monster then
        return true
    end
    if math.random(1, 10000) <= monster.chance then
        local tile = Tile(target:getPosition())
        if tile then
            local ground = tile:getGround()
            if ground then
                ground:setActionId(6000)
                target:say('DOUBLE EXP!', TALKTYPE_MONSTER_SAY)
                for i = 0, 3 do
                    addEvent(sendMessage, 750 * i, target:getPosition())
                end
            end
        end
    end
    return true
end

custom_exp_damage_effect:type("kill")
custom_exp_damage_effect:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local custom_exp_damage_effect_login = CreatureEvent("custom_exp_damage_effect_login")

function custom_exp_damage_effect_login.onLogin(player)
    player:registerEvent("custom_exp_damage_effect")
    return true
end

custom_exp_damage_effect_login:type("login")
custom_exp_damage_effect_login:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local custom_exp_damage_effect_movement = MoveEvent()
custom_exp_damage_effect_movement:type("stepin")

local function sendEffect(cid)
    local player = Player(cid)
    if not player then
        return true
    end
    local pos = player:getPosition()
    local pos2 = player:getPosition() + Position(math.random(-2, 2), math.random(-2, 2), 0)
    pos2:sendDistanceEffect(pos, 31)
end

function custom_exp_damage_effect_movement.onStepIn(player, item, position, fromPosition)
    if player:isMonster() then
        return true
    end
    local tile = Tile(player:getPosition())
    if tile then
        local ground = tile:getGround()
        if ground then
            ground:setActionId()
            player:setStorageValue(6000, os.time() + 60)
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'You have received double experience for the next 60 seconds.')
            for i = 0, 25 do
                addEvent(sendEffect, 100 * i, player:getId())
            end
        end
    end
    return true
end

custom_exp_damage_effect_movement:aid(6000)

custom_exp_damage_effect_movement:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local expCheck = TalkAction("!exp")

local function secondsToReadable(s)
    local hours   = math.floor(s / 3600)
    local minutes = math.floor(math.fmod(s, 3600)/60)
    local seconds = math.floor(math.fmod(s, 60))
    return (hours   > 0 and (hours   .. ' hour'   .. (hours   > 1 and 's ' or ' ')) or '') ..
           (minutes > 0 and (minutes .. ' minute' .. (minutes > 1 and 's ' or ' ')) or '') ..
           (seconds > 0 and (seconds .. ' second' .. (seconds > 1 and 's ' or ' ')) or '')
end

function expCheck.onSay(player, words)
 
    local exhaust = 6000
    if player:getStorageValue(exhaust) - os.time() > 0 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "Your extra exp will end in : "..player:getStorageValue(exhaust) - os.time().."")
        return false
    end
    return false
end

expCheck:separator(" ")
expCheck:register()
---------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
local ec = EventCallback

function ec.onGainExperience(source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end
 
    if self:getStorageValue(6000) >= os.time() then
        exp = exp * 2.00
    end
    return exp
end

ec:register(1)
how to put this for all creatures in the game without having to configure the creatures?
 
how to put this for all creatures in the game without having to configure the creatures?
Remove lines 26-29, and on line 30 change "monster.chance" into a number representing the chance, then it should work like you asked
 
Back
Top