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

RevScripts โค โ„ฑ๐“‡๐‘’๐‘’ ๐’ฎ๐’ธ๐“‡๐’พ๐“…๐“‰๐’พ๐“ƒ๐‘” ๐’ฎ๐‘’๐“‡๐“‹๐’พ๐’ธ๐‘’ ๐’ฏโ„ฑ๐’ฎ ๐Ÿท.๐Ÿป+ โค

Sarah Wesker

ฦฦ–ั”gฮฑฮทั‚ Sัƒฮทั‚ฮฑx โค
Staff member
TFS Developer
Support Team
Joined
Mar 16, 2017
Messages
1,407
Solutions
154
Reaction score
1,957
Location
London
GitHub
MillhioreBT
Twitch
millhiorebt
โค ๐…๐ซ๐ž๐ž ๐’๐œ๐ซ๐ข๐ฉ๐ญ๐ข๐ง๐  ๐’๐ž๐ซ๐ฏ๐ข๐œ๐ž ๐Ÿ.๐Ÿ“+ โค

๐Ÿ“š (ใฃโ—”โ—กโ—”)ใฃ โ„๐“ƒ๐’ป๐‘œ๐“‡๐“‚๐’ถ๐“‰๐’พ๐‘œ๐“ƒ ๐Ÿ“š
โค โ„ฐ๐“ƒ๐‘”๐’พ๐“ƒ๐‘’: ๐’ฏโ„ฑ๐’ฎ ๐’ช๐’ป๐’พ๐’ธ๐’พ๐’ถ๐“
โค โ„ฐ๐“ƒ๐‘”๐’พ๐“ƒ๐‘’ ๐’ฑ๐‘’๐“‡๐“ˆ๐’พ๐‘œ๐“ƒ: ๐Ÿท.๐Ÿป+

โš™๐Ÿ”งโ„‹๐‘œ๐“Œ ๐“‰๐‘œ ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰ ๐’ถ ๐“ˆ๐’ธ๐“‡๐’พ๐“…๐“‰?
โค โ„ณ๐’ถ๐“€๐‘’ ๐“ˆ๐“Š๐“‡๐‘’ ๐“Ž๐‘œ๐“Š ๐“‚๐‘’๐‘’๐“‰ ๐“‰๐’ฝ๐‘’ ๐’ธ๐‘œ๐“‡๐“‡๐‘’๐’ธ๐“‰ ๐“‹๐‘’๐“‡๐“ˆ๐’พ๐‘œ๐“ƒ ๐’ถ๐“ƒ๐’น ๐‘’๐“ƒ๐‘”๐’พ๐“ƒ๐‘’.
โค ๐’ฏ๐“‡๐“Ž ๐“ƒ๐‘œ๐“‰ ๐“‰๐‘œ ๐“‚๐’ถ๐“€๐‘’ ๐“Ž๐‘œ๐“Š๐“‡ ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰ ๐“‰๐‘œ๐‘œ ๐’ธ๐‘œ๐“‚๐“…๐“๐‘’๐“, ๐’ถ๐“ˆ ๐“‰๐’ฝ๐‘’ ๐“ˆ๐’พ๐“‚๐“…๐“๐‘’๐“ˆ๐“‰ ๐‘œ๐“ƒ๐‘’๐“ˆ ๐“Œ๐’พ๐“๐“ ๐’ท๐‘’ ๐“‰๐’ถ๐“€๐‘’๐“ƒ ๐’ธ๐’ถ๐“‡๐‘’ ๐‘œ๐’ป ๐’ป๐’พ๐“‡๐“ˆ๐“‰.
โค ๐’ด๐‘œ๐“Š ๐’ถ๐‘”๐“‡๐‘’๐‘’ ๐“ƒ๐‘œ๐“‰ ๐“‰๐‘œ ๐’ป๐’พ๐“๐‘’ ๐’ถ ๐‘”๐“‡๐’พ๐‘’๐“‹๐’ถ๐“ƒ๐’ธ๐‘’๐“ˆ ๐’พ๐’ป ๐“Ž๐‘œ๐“Š๐“‡ ๐’ถ๐“…๐“…๐“๐’พ๐’ธ๐’ถ๐“‰๐’พ๐‘œ๐“ƒ ๐’พ๐“ˆ ๐’ถ๐’ธ๐’ธ๐‘’๐“…๐“‰๐‘’๐’น ๐’ท๐“Š๐“‰ ๐“ƒ๐‘’๐“‹๐‘’๐“‡ ๐“‡๐‘’๐“ˆ๐‘œ๐“๐“‹๐‘’๐’น.
โค ๐’ด๐‘œ๐“Š ๐“‚๐“Š๐“ˆ๐“‰ ๐’ฝ๐’ถ๐“‹๐‘’ ๐’ถ ๐’ธ๐‘’๐“‡๐“‰๐’ถ๐’พ๐“ƒ ๐“‡๐‘’๐“…๐“Š๐“‰๐’ถ๐“‰๐’พ๐‘œ๐“ƒ ๐’พ๐“ƒ ๐“‰๐’ฝ๐‘’ ๐’ป๐‘œ๐“‡๐“Š๐“‚, โ„ ๐’น๐‘œ ๐“ƒ๐‘œ๐“‰ ๐’ถ๐’ธ๐’ธ๐‘’๐“…๐“‰ ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰๐“ˆ ๐’ป๐‘œ๐“‡ ๐“ƒ๐‘’๐“Œ ๐‘œ๐“‡ ๐“ˆ๐“Š๐“ˆ๐“…๐’พ๐’ธ๐’พ๐‘œ๐“Š๐“ˆ ๐’ถ๐’ธ๐’ธ๐‘œ๐“Š๐“ƒ๐“‰๐“ˆ, ๐“‰๐“‡๐“Ž ๐“ƒ๐‘œ๐“‰ ๐“‰๐‘œ ๐“Š๐“ˆ๐‘’ โ„ฑ๐’œ๐’ฆโ„ฐ๐’ฎ.
โค โ„›๐‘’๐“‚๐‘’๐“‚๐’ท๐‘’๐“‡ ๐“‹๐‘’๐“‡๐“Ž ๐“Œ๐‘’๐“๐“ ๐“‰๐’ฝ๐’ถ๐“‰ ๐’พ๐“‰ ๐’พ๐“ˆ ๐’ป๐‘œ๐“‡ ๐’ช๐’ป๐’ป๐’พ๐’ธ๐’พ๐’ถ๐“ ๐’ฏโ„ฑ๐’ฎ ๐“ˆ๐‘œ ๐’น๐‘œ๐“ƒ'๐“‰ ๐’ท๐‘œ๐“‰๐’ฝ๐‘’๐“‡ ๐’ถ๐“ˆ๐“€๐’พ๐“ƒ๐‘” ๐’ป๐‘œ๐“‡ ๐“ˆ๐‘œ๐“‚๐‘’๐“‰๐’ฝ๐’พ๐“ƒ๐‘” ๐’ป๐‘œ๐“‡ ๐“Ž๐‘œ๐“Š๐“‡ ๐‘œ๐“‰๐’ฝ๐‘’๐“‡ ๐‘’๐“ƒ๐‘”๐’พ๐“ƒ๐‘’, ๐’ถ๐“ˆ โ„ ๐“Œ๐’พ๐“๐“ ๐’พ๐‘”๐“ƒ๐‘œ๐“‡๐‘’ ๐“ˆ๐’ถ๐’พ๐’น ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰.
โค ๐’ฏ๐’ฝ๐‘’ ๐’น๐‘’๐“ˆ๐’ธ๐“‡๐’พ๐“…๐“‰๐’พ๐‘œ๐“ƒ ๐“‚๐“Š๐“ˆ๐“‰ ๐’ท๐‘’ ๐’พ๐“ƒ โ„ฐ๐“ƒ๐‘”๐“๐’พ๐“ˆ๐’ฝ ๐’ถ๐“ƒ๐’น ๐“Œ๐‘’๐“๐“ ๐‘’๐“๐“…๐“๐’ถ๐’พ๐“ƒ๐‘’๐’น ๐“Œ๐’พ๐“‰๐’ฝ๐‘œ๐“Š๐“‰ ๐“‰๐‘œ๐‘œ ๐“‚๐’ถ๐“ƒ๐“Ž ๐“Œ๐‘œ๐“‡๐’น๐“ˆ.

๐ŸŽ€โ„‹๐‘œ๐“Œ ๐’น๐‘œ โ„ ๐“€๐“ƒ๐‘œ๐“Œ ๐’พ๐’ป ๐“‚๐“Ž ๐’ถ๐“…๐“…๐“๐’พ๐’ธ๐’ถ๐“‰๐’พ๐‘œ๐“ƒ ๐“Œ๐’ถ๐“ˆ ๐’ถ๐’ธ๐’ธ๐‘’๐“…๐“‰๐‘’๐’น?๐ŸŽ€
โค โ„๐’ป ๐“Ž๐‘œ๐“Š๐“‡ ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰ ๐’ฝ๐’ถ๐“ˆ ๐“‚๐“Ž ๐“๐’พ๐“€๐‘’, ๐’พ๐“‰ ๐“‚๐‘’๐’ถ๐“ƒ๐“ˆ ๐“‰๐’ฝ๐’ถ๐“‰ ๐’พ๐“‰ ๐“Œ๐’ถ๐“ˆ ๐’ถ๐’ธ๐’ธ๐‘’๐“…๐“‰๐‘’๐’น.
โค โ„๐’ป ๐“Ž๐‘œ๐“Š๐“‡ ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰ ๐’พ๐“ˆ ๐’ถ๐’ธ๐’ธ๐‘’๐“…๐“‰๐‘’๐’น, ๐“Ž๐‘œ๐“Š ๐’ฟ๐“Š๐“ˆ๐“‰ ๐’ฝ๐’ถ๐“‹๐‘’ ๐“‰๐‘œ ๐“Œ๐’ถ๐’พ๐“‰ ๐’ป๐‘œ๐“‡ ๐“‚๐‘’ ๐“‰๐‘œ ๐’ถ๐“ƒ๐“ˆ๐“Œ๐‘’๐“‡ ๐“Ž๐‘œ๐“Š๐“‡ ๐“‡๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰.

๐’ฏ๐’ฝ๐’พ๐“ˆ ๐’พ๐“ˆ ๐“‚๐“Ž ๐‘œ๐“๐’น ๐’ป๐“‡๐‘’๐‘’ ๐“ˆ๐‘’๐“‡๐“‹๐’พ๐’ธ๐‘’๐“ˆ ๐“‰๐’ฝ๐“‡๐‘’๐’ถ๐’น ๐’พ๐’ป ๐“Ž๐‘œ๐“Š'๐’น ๐“๐’พ๐“€๐‘’ ๐“‰๐‘œ ๐’ธ๐’ฝ๐‘’๐’ธ๐“€ ๐’ท๐‘’๐’ป๐‘œ๐“‡๐‘’ ๐“Ž๐‘œ๐“Š ๐’ถ๐“ˆ๐“€ ๐’ป๐‘œ๐“‡ ๐“ˆ๐‘œ๐“‚๐‘’๐“‰๐’ฝ๐’พ๐“ƒ๐‘” ๐“‡๐‘’๐“…๐‘’๐’ถ๐“‰๐‘’๐’น.

๐Ÿ“Œ โ„›๐‘’๐“†๐“Š๐‘’๐“ˆ๐“‰ ๐‘’๐“๐’ถ๐“‚๐“…๐“๐‘’: ๐Ÿ“Œ

โ„ฐ๐“ƒ๐‘”๐’พ๐“ƒ๐‘’ ๐’ถ๐“ƒ๐’น ๐’ฑ๐‘’๐“‡๐“ˆ๐’พ๐‘œ๐“ƒ โœ…
๐’Ÿ๐‘’๐“ˆ๐’ธ๐“‡๐’พ๐“…๐“‰๐’พ๐‘œ๐“ƒ ๐Ÿ“‘
...
 
Hi! I want to take the opportunity to add one more idea for a script :)
It's something very simple, I think. When a creature drops an item that has "loot chance" less or equal (<=) than "5000", send a magic effect or a text that advice the player that he/she has looted a rare item. This effect must come from the corpse of the creature,

Regards! And gl with all the requests.
 
Hi! I want to take the opportunity to add one more idea for a script :)

Lua:
if not self:getCustomAttribute("Display_Rare") then
    if (itemCount ~= 0 and not itemType:isContainer()) then
        if item.chance <= 5000 then
            local player = Player(self:getCorpseOwner())
            if player then          
                player:say("Rare Item!", TALKTYPE_MONSTER_SAY, false, nil, self:getPosition())
            end
            self:setCustomAttribute("Display_Rare", 1)
            self:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
        end
    end
end


EDIT: Added a check to not repeat the rare effect in case monster drop more than 1 item with <= chance
 
Last edited:
hello! i will like a capture djinn script.

You see a djinn's lamp.
It weighs 5.00 oz.
(This item has 1 charges left).

if you use this item on a djinn (monster) you got %% chances of capture it.

if success then

You see a djinn's lamp.
It weighs 5.00 oz.
(description) it contains a powerfull RED djinn.

then if you use it you will summon a Djinn with your name. (you see a Djinn (ilknight) )
(so it need to be summoned in a diferent place first to rename)

if possible locals to edit the %%chances, the target creatures and the descriptions for each one because i want to make 4 different races to capture.

thanks in advance!
 
Lua:
if not self:getCustomAttribute("Display_Rare") then
    if (itemCount ~= 0 and not itemType:isContainer()) then
        if item.chance <= 5000 then
            local player = Player(self:getCorpseOwner())
            if player then         
                player:say("Rare Item!", TALKTYPE_MONSTER_SAY, false, nil, self:getPosition())
            end
            self:setCustomAttribute("Display_Rare", 1)
            self:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
        end
    end
end


EDIT: Added a check to not repeat the rare effect in case monster drop more than 1 item with <= chance

Thanks a lot! I have this issue right now in the console
1655055233393.png
 
Thanks a lot @Roddet working perfectly.
I would like to request another idea. It's simple to explain. A command for GODs and GMs to move between Remere's waypoints in-game.
Not sure if there's possibilies to read waypoints, in case that is not possible, just use a table as coordinator register tool.

Example usage:

/waypoint 1 or /waypoint "location name"

Regards!
 
Thanks a lot @Roddet working perfectly.
I would like to request another idea. It's simple to explain. A command for GODs and GMs to move between Remere's waypoints in-game.
Not sure if there's possibilies to read waypoints, in case that is not possible, just use a table as coordinator register tool.

Example usage:
/waypoint 1 or /waypoint "location name"

Regards!

TFS already have this script, just use "/pos x, y, z"
 
Thanks a lot @Roddet working perfectly.
I would like to request another idea. It's simple to explain. A command for GODs and GMs to move between Remere's waypoints in-game.
Not sure if there's possibilies to read waypoints, in case that is not possible, just use a table as coordinator register tool.

Example usage:
/waypoint 1 or /waypoint "location name"

Regards!

Lua:
local talk = TalkAction("/posi", "!posi")

function talk.onSay(player, words, param)

    player:teleportTo(getWaypointPositionByName(param))
    return false
end

talk:separator(" ")
talk:register()

/posi waypointName
 
Hello Sarah Wesker,

I would like to request a Skill stage script, Vocation based.
For an Example:
Sorc below Magic Level 20 gains 10x Multiplier and over 20 gains 8x Multiplier

Same for Dist/Club/Axe/Fist, Fishing isnt that important
If its possible would be nice to have if its not possible in REVscript let me know and I will try to find an other solution

But thanks anyway for doing such an impressive work :)

 
@Levi999x Thanks a lot! It worked well. The only this is that when I use a wrong param or a number in the name the following appears, but it's nothing since it still work.

1655229061135.png

Lua:
if not self:getCustomAttribute("Display_Rare") then
    if (itemCount ~= 0 and not itemType:isContainer()) then
        if item.chance <= 5000 then
            local player = Player(self:getCorpseOwner())
            if player then        
                player:say("Rare Item!", TALKTYPE_MONSTER_SAY, false, nil, self:getPosition())
            end
            self:setCustomAttribute("Display_Rare", 1)
            self:getPosition():sendMagicEffect(CONST_ME_HOLYAREA)
        end
    end
end


EDIT: Added a check to not repeat the rare effect in case monster drop more than 1 item with <= chance

Hey @Roddet, In case I leave it like this

Code:
    if not self:getCustomAttribute("Display_Rare") then
    if (itemCount ~= 0 and not itemType:isContainer()) then
        if item.chance <= 5000 then
            local player = Player(self:getCorpseOwner())
            if player then         
               --- player:say("Rare Item!", TALKTYPE_MONSTER_SAY, false, nil, self:getPosition())
            end
            self:setCustomAttribute("Display_Rare", 1)
            self:getPosition():sendMagicEffect(CONST_ME_TUTORIALARROW)
        end
    end
end

How can I make the "tutorial arrow" effect stand for more seconds? For example, 3 seconds of Tutorial_Arrow effect when a rare loot is droped.
Thanks in advance!
 
Last edited:
@Levi999x Thanks a lot! It worked well. The only this is that when I use a wrong param or a number in the name the following appears, but it's nothing since it still work.

View attachment 68564



Hey @Roddet, I case I leave it like this

Code:
    if not self:getCustomAttribute("Display_Rare") then
    if (itemCount ~= 0 and not itemType:isContainer()) then
        if item.chance <= 5000 then
            local player = Player(self:getCorpseOwner())
            if player then         
               --- player:say("Rare Item!", TALKTYPE_MONSTER_SAY, false, nil, self:getPosition())
            end
            self:setCustomAttribute("Display_Rare", 1)
            self:getPosition():sendMagicEffect(CONST_ME_TUTORIALARROW)
        end
    end
end

How can I make the "tutorial arrow" effect stand for more seconds? For example, 3 seconds of Tutorial_Arrow effect when a rare loot is droped.
Thanks in advance!
my bad
Lua:
local talk = TalkAction("/posi", "!posi")

function talk.onSay(player, words, param)

    if not param == getWaypointPositionByName(param) then
        return false
    end
    player:teleportTo(getWaypointPositionByName(param))
    return false
end

talk:separator(" ")
talk:register()
 
Maybe a faction fighting script, the concept is basic and is present in various other MMO's and i don't think i've ever seen it on tibia

1. people would be allowed to choose between 2 factions, and they would be able to kill players from the other faction without any punishment, and unable to attack players from the same faction...

2.to make it more interesting maybe some points could be added as a reward when you kill players from the other faction, or even a killcount for players

3. the fighting could be delimited maybe to work only on a certain zone (like PVP or no loggout), but could work on the entire map as well
data/scripts/factions.lua

Lua:
local config = {
    talkAction = "!faction",
    storage = 888999,
    storageCount = 888998,
    storageDeaths = 888997,
    options = {
        ["red"] = {
            id = 1,
            text = "Red",
            allowPvp = true
        },
        ["blue"] = {
            id = 2,
            text = "Blue",
            allowPvp = true
        }
    }
}

config.optionsByIndex = {}
for k, v in pairs(config.options) do
    config.optionsByIndex[v.id] = v
end

local function getFaction(player)
    return config.optionsByIndex[player.storage[config.storage]]
end

local talkAction = TalkAction(config.talkAction)

function talkAction.onSay(player, words, param, type)
    local option = config.options[param:lower()]
    if not option then
        player:sendCancelMessage("This faction is not exist.")
        return false
    end
    local faction = getFaction(player)
    if faction then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You already have a faction.")
        return false
    end
    player.storage[config.storage] = option.id
    player.storage[config.storageCount] = 0
    player.storage[config.storageDeaths] = 0
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Cangratulations! You have joined " .. option.text .. " faction.")
    player:getPosition():sendMagicEffect(CONST_ME_FIREWORK_YELLOW)
    player:registerEvent("FactionDeaths")
    return false
end

talkAction:separator(" ")
talkAction:register()

local ec = EventCallback

function ec.onLook(player, thing, position, distance, description)
    if not thing:isCreature() then
        return description
    end
    local other = thing:getPlayer()
    if not other then
        return description
    end
    local playerFaction = getFaction(other)
    if not playerFaction then
        return description
    end
    description = string.format("%s\nFaction: %s | Kills: %d | Deaths: %d", description, playerFaction.text, other.storage[config.storageCount], other.storage[config.storageDeaths])
    return description
end

ec:register(1)

local ec = EventCallback

function ec.onTargetCombat(creature, target)
    if not creature or not target then
        return RETURNVALUE_NOERROR
    end
    local player = creature:getPlayer()
    if not player then
        return RETURNVALUE_NOERROR
    end
    local other = target:getPlayer()
    if not other then
        return RETURNVALUE_NOERROR
    end
    local playerFaction = getFaction(player)
    if not playerFaction then
        return RETURNVALUE_NOERROR
    end
    local otherFaction = getFaction(other)
    if not otherFaction then
        return RETURNVALUE_NOERROR
    end
    if playerFaction.id == otherFaction.id then
        return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER
    end
    if playerFaction.allowPvp and otherFaction.allowPvp then
        return RETURNVALUE_NOERROR
    end
    return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER
end

ec:register(-1)

local function getLastDamagers(player)
    local lastDamagers = {}
    local timeNow = os.mtime()
    local inFightTicks = configManager.getNumber(configKeys.PZ_LOCKED)
    for uid, cb in pairs(player:getDamageMap()) do
        local otherPlayer = Player(uid)
        if otherPlayer and otherPlayer:getId() ~= player:getId() then
            if timeNow - cb.ticks <= inFightTicks then
                lastDamagers[#lastDamagers + 1] = otherPlayer
            end
        end
    end
    return lastDamagers
end

local creatureEvent = CreatureEvent("FactionDeaths")

function creatureEvent.onDeath(player, corpse, lastHitKiller, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    local playerFaction = getFaction(player)
    if not playerFaction then
        return true
    end
    local lastDamagers = getLastDamagers(player)
    if not next(lastDamagers) then
        return true
    end
    local killedByOtherFaction = false
    for _, damager in ipairs(lastDamagers) do
        local damagerFaction = getFaction(damager)
        if damagerFaction and damagerFaction.id ~= playerFaction.id then
            damager.storage[config.storageCount] = damager.storage[config.storageCount] + 1
            damager:sendTextMessage(MESSAGE_INFO_DESCR, "You received 1 faction kill point for killing " .. player:getName() .. ".")
            killedByOtherFaction = true
        end
    end
    if killedByOtherFaction then
        player.storage[config.storageDeaths] = player.storage[config.storageDeaths] + 1
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You received 1 faction death point for being killed by another faction.")
    end
    return true
end

creatureEvent:register()

local creatureEvent = CreatureEvent("FactionLogin")

function creatureEvent.onLogin(player)
    local playerFaction = getFaction(player)
    if not playerFaction then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You have to join a faction first, please choose one by typing '!faction red' or '!faction blue'.")
        return true
    end
    player:registerEvent("FactionDeaths")
    return true
end

creatureEvent:register()

When a player has no faction then they will be prompted to choose one when they log in.
The factions can`t deal damage to each other same faction.
The player description will show the faction you belong to and the deaths and kills.
1656146311970.png
Post automatically merged:

An aura appear on you when you wear some set and this aura spin on you with a cool effect
I'm not sure if I understood what you wanted, but here I did this for you, I hope it helps.

data/scripts/looktypeaura.lua

Lua:
local config = {
    lookTypes = {136, 128}, -- Citizen
    auraDistanceEffect = CONST_ANI_DEATH,
    auraStepDirs = {
        DIRECTION_NORTHWEST,
        DIRECTION_NORTH,
        DIRECTION_NORTHEAST,
        DIRECTION_EAST,
        DIRECTION_SOUTHEAST,
        DIRECTION_SOUTH,
        DIRECTION_SOUTHWEST,
        DIRECTION_WEST
    },
    events = {}
}

local function initAura(playerId)
    local player = Player(playerId)
    if not player then
        config.events[playerId] = nil
        return
    end

    local initPosition = player:getPosition()
    initPosition.x = initPosition.x - 1
    initPosition.y = initPosition.y - 1
    for i = 1, 8 do
        addEvent(function (playerId, lastDir, toDir)
            local player = Player(playerId)
            if not player then
                return
            end

            local playerPosition = player:getPosition()
            local lastPos = playerPosition + Position.directionOffset[lastDir]
            local toPos = playerPosition + Position.directionOffset[toDir]
            lastPos:sendDistanceEffect(toPos, config.auraDistanceEffect)
        end, i * 100, playerId, config.auraStepDirs[i], config.auraStepDirs[i + 1] or config.auraStepDirs[1])
    end

    config.events[playerId] = addEvent(initAura, 800, playerId)
end

local ec = EventCallback

function ec.onChangeOutfit(creature, outfit)
    if not creature:isPlayer() then
        return true
    end

    if table.contains(config.lookTypes, outfit.lookType) then
        initAura(creature:getId())
    else
        local playerId = creature:getId()
        stopEvent(config.events[playerId])
        config.events[playerId] = nil
    end
    return true
end

ec:register(666)

local creatureEvent = CreatureEvent("AuraLogin")

function creatureEvent.onLogin(player)
    if table.contains(config.lookTypes, player:getOutfit().lookType) then
        initAura(player:getId())
    end
    return true
end

creatureEvent:register()

The lookTypes in the config will cause this aura to appear.
citizen.gif
Post automatically merged:

Hi,

A room with a door when 1 player get inside no one else can get through the door untill the first player gets out of a room by a teleport.


And a room that you can get through the door only at specific time once a day with a broadcast message.

Thanks
Hi @tomaszek123

data/scripts/roomDoorTomas.lua

Lua:
local config = {
    closedDoorId = 6250,
    openDoorId = 6251,
    doorActionId = 30000,
    roomArea = {
        fromPosition = Position(3196, 1804, 7),
        toPosition = Position(3198, 1806, 7)
    },
    withTime = false,
    time = {
        from = {
            hour = 7,
            minute = 40
        },
        to = {
            hour = 7,
            minute = 45
        }
    }
}

config.roomArea.diffX = config.roomArea.toPosition.x - config.roomArea.fromPosition.x
config.roomArea.diffY = config.roomArea.toPosition.y - config.roomArea.fromPosition.y
config.roomArea.centerPosition = Position(config.roomArea.fromPosition.x + config.roomArea.diffX / 2, config.roomArea.fromPosition.y + config.roomArea.diffY / 2, config.roomArea.fromPosition.z)

local function getTime()
    local time = os.date("*t")
    return {
        hour = time.hour,
        minute = time.min
    }
end

local action = Action()

function action.onUse(player, item, fromPos, target, toPos, isHotkey)
    if config.withTime then
        local time = getTime()
        if time.hour < config.time.from.hour or (time.hour == config.time.from.hour and time.minute < config.time.from.minute) then
            player:sendTextMessage(MESSAGE_STATUS_WARNING, string.format("The door is not available yet.\nIt will be available from %d:%d to %d:%d.", config.time.from.hour, config.time.from.minute, config.time.to.hour, config.time.to.minute))
            return true
        end
        if time.hour > config.time.to.hour or (time.hour == config.time.to.hour and time.minute > config.time.to.minute) then
            player:sendTextMessage(MESSAGE_STATUS_WARNING, string.format("The door is not available yet.\nIt will be available from %d:%d to %d:%d.", config.time.from.hour, config.time.from.minute, config.time.to.hour, config.time.to.minute))
            return true
        end
    end
    local spectators = Game.getSpectators(config.roomArea.centerPosition, false, true, config.roomArea.diffX, config.roomArea.diffX, config.roomArea.diffY, config.roomArea.diffY)
    if #spectators ~= 0 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "There is already a player in this room.")
        return true
    end
    item:transform(item:getId() == config.openDoorId and config.closedDoorId or config.openDoorId)
    return true
end

action:aid(config.doorActionId)
action:register()

local moveEvent = MoveEvent()

function moveEvent.onStepIn(creature, item, pos, fromPosition)
    if not creature:isPlayer() then
        return true
    end

    local player = creature:getPlayer()
    local tile = Tile(pos)
    if tile:getCreatureCount() > 1 then
        player:teleportTo(fromPosition, false)
        player:sendTextMessage(MESSAGE_STATUS_SMALL, "You cannot pass.")
        return true
    end
    return true
end

moveEvent:aid(config.doorActionId)
moveEvent:register()

local moveEvent = MoveEvent()

function moveEvent.onStepOut(creature, item, pos, fromPosition)
    if not creature:isPlayer() then
        return true
    end

    local tile = Tile(pos)
    if tile:getCreatureCount() == 0 then
        item:transform(config.closedDoorId)
    end
    return true
end

moveEvent:aid(config.doorActionId)
moveEvent:register()

You must remember to set the IDs of the door you are using.
If you want the door to work with time just change config.withTime to true
If you want to have two gates, one with time and one not, just duplicate the file and set your other gate with a different actionID...
1656158271509.pngGIF 25-06-2022 07-58-55 a. m..gif
 
Last edited:
Tfs 1.5

Like to have a reverse oracle, I did already made a concept. It basically reset all skills and send you to rook without a vocation at lvl 1.

Lua:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)

function onCreatureAppear(cid)            npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)        npcHandler:onCreatureDisappear(cid)            end
function onCreatureSay(cid, type, msg)        npcHandler:onCreatureSay(cid, type, msg)        end
function onThink()                npcHandler:onThink()                    end

if msgcontains(msg, 'rookgaard') then
    npcHandler:say('Hmmm. Long time I visited that isle. Not very exciting place. Why do you ask? Do you wish to go there?')
    talk_state = 3
  
    elseif msgcontains(msg, 'yes') and talk_state == 3 then
    npcHandler:say('Careful, careful, it\'s a one-way ticket only! You can never come back here if you leave now, and you will lose all your equipment and products!?')
    talk_state = 4
    elseif msgcontains(msg, 'no') and talk_state == 3 then
    npcHandler:say('A wise decision. It\'s much better here, believe me. Been there, done that.')
    talk_state = 0
  
    elseif msgcontains(msg, 'yes') and talk_state == 4 then
    npcHandler:say('Then so be it. I\'m sorry to see you go, but if this is what you want, step this way... right. Now, cover your eyes... GO!')

    doPlayerSetVocation(cid, 0)
    doPlayerSetTown(cid, 1)

    doPlayerSetMagicLevel(cid, 0)
    doPlayerSetSkillLevel(cid, SKILL_SHIELD, 10)
    doPlayerSetSkillLevel(cid, SKILL_DISTANCE, 10)
    doPlayerSetSkillLevel(cid, SKILL_AXE, 10)
     doPlayerSetSkillLevel(cid, SKILL_SWORD, 10)
    doPlayerSetSkillLevel(cid, SKILL_CLUB, 10)
    player:removeExperience(player:getExperience() - getExpForLevel(1), false) 
    player:setMaxHealth(150)
    player:setMaxMana(55)
    player:addHealth(player:getMaxHealth())
    player:addMana(player:getMaxMana())
    player:setCapacity(400)

    doTeleportThing(cid, {x=32097,y=32219,z=7})
    doSendMagicEffect(destination, CONST_ME_MAGIC_BLUE)

    local slots = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    for _, slot in pairs(slots) do
    local item = player:getSlotItem(slot)
    if item then
        item:remove()
    end
end

    doPlayerAddItem(cid, 1987, 1)
    doAddContainerItem(bag,2650,1)
    doAddContainerItem(bag,2382,1)
    doAddContainerItem(bag,2674,1)
end

npcHandler:addModule(FocusModule:new())
data/npc/Reverse The Oracle.xml

XML:
<npc name="Reverse The Oracle" script="Reverse The Oracle.lua" walkinterval="0" speechbubble="3">
    <look typeex="1448" />
    <parameters>
        <parameter key="message_greet" value="|PLAYERNAME|, ARE YOU PREPARED TO RESET CHARACTER?" />
        <parameter key="message_walkaway" value="COME BACK WHEN YOU ARE PREPARED TO FACE YOUR DESTINY!" />
        <parameter key="message_farewell" value="COME BACK WHEN YOU ARE PREPARED TO FACE YOUR DESTINY!" />
    </parameters>
</npc>

data/npc/scripts/Reverse The Oracle.lua

Lua:
local config = {
    destine = Position(32097, 32219, 7),
    defaultFemaleOutfit = {
        lookType = 136,
        lookHead = 0,
        lookBody = 0,
        lookLegs = 0,
        lookFeet = 0,
        lookAddons = 0,
        lookMount = 0
    },
    defaultMaleOutfit = {
        lookType = 128,
        lookHead = 0,
        lookBody = 0,
        lookLegs = 0,
        lookFeet = 0,
        lookAddons = 0,
        lookMount = 0
    },
    maxHealth = 150,
    maxMana = 55,
    capacity = 400,
    defaultSkillLevel = 10,
    bag = {
        id = 1988,
        content = {
            {
                id = 2650,
                count = 1
            },
            {
                id = 2382,
                count = 1
            },
            {
                id = 2674,
                count = 1
            }
        }
    }
}

local function resetPlayer(player)
    player:setVocation(0)
    player:setTown(1)
    player:setSkullType(SKULL_NONE)
    player:setSkullTime(0)
    player:setStamina(4200)
    player:setOutfit(player:getSex() == PLAYERSEX_FEMALE and config.defaultFemaleOutfit or config.defaultMaleOutfit)
    player:removeManaSpent(player:getManaSpent())
    for skillId = SKILL_FIST, SKILL_FISHING do
        player:removeSkillTries(skillId, player:getSkillTries(skillId))
        player:addSkillLevel(skillId, config.defaultSkillLevel)
    end
    for slotId = CONST_SLOT_HEAD, CONST_SLOT_AMMO do
        local slotItem = player:getSlotItem(slotId)
        if slotItem then
            slotItem:remove()
        end
    end
    player:removeExperience(player:getExperience() - Game.getExperienceForLevel(1), false)
    player:setMaxHealth(config.maxHealth)
    player:setMaxMana(config.maxMana)
    player:addHealth(config.maxHealth)
    player:addMana(config.maxMana)
    player:setCapacity(config.capacity)
    player:getPosition():sendMagicEffect(CONST_ME_POFF)
    player:teleportTo(config.destine)
    config.destine:sendMagicEffect(CONST_ME_TELEPORT)
    local bag = Game.createItem(config.bag.id, 1)
    for _, item in ipairs(config.bag.content) do
        bag:addItem(item.id, item.count)
    end
    if player:addItemEx(bag) ~= RETURNVALUE_NOERROR then
        bag:remove()
    end
end

local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
function onCreatureAppear(cid)              npcHandler:onCreatureAppear(cid)            end
function onCreatureDisappear(cid)           npcHandler:onCreatureDisappear(cid)         end
function onCreatureSay(cid, type, msg)      npcHandler:onCreatureSay(cid, type, msg)    end
function onThink()                          npcHandler:onThink()                        end

local function greetCallback(cid)
    local player = Player(cid)
    if player:getVocation():getId() == 0 then
        npcHandler:say("YOU NO HAVE A VOCATION!", cid)
        return false
    end
    return true
end

local function creatureSayCallback(cid, type, msg)
    if not npcHandler:isFocused(cid) then
        return false
    end
    if msgcontains(msg, "yes") and npcHandler.topic[cid] == 0 then
        npcHandler:say("You are about to lose your progress with the character. Are you sure you want to continue?", cid)
        npcHandler.topic[cid] = 1
    elseif npcHandler.topic[cid] == 1 then
        if msgcontains(msg, "yes") then
            npcHandler:say("Congratulations! You have lost all your progress with the character." , cid)
            resetPlayer(Player(cid))
        else
            npcHandler:say("You have chosen to keep your progress with the character. I hope you will come back to me later.", cid)
        end
        npcHandler.topic[cid] = nil
    end
    return true
end

local function onAddFocus(cid)
    town[cid] = 0
    vocation[cid] = 0
    destination[cid] = 0
end

local function onReleaseFocus(cid)
    town[cid] = nil
    vocation[cid] = nil
    destination[cid] = nil
end

npcHandler:setCallback(CALLBACK_ONADDFOCUS, onAddFocus)
npcHandler:setCallback(CALLBACK_ONRELEASEFOCUS, onReleaseFocus)
npcHandler:setCallback(CALLBACK_GREET, greetCallback)
npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())

I haven't test it but it should work, let me know if it doesn't, literally I just update your script to TFS 1.5
Don't forget to set the table config.
 
Hello Sarah!
TFS VERSIร“N: 1.4.1
DESCRIPTION: Let's say i want a 3 different bags that gives random items to a player and for stackable items "count" can be random too, let's say a player receive gold coins between 1 to 100 gold coins (can be any other stackable item, just the gold coins as refference).

Bag 1 gives random items (no need for a key)
Bag 2 and Bag 3 needs an special key to open (player have to use the key on the box to open it.)

Thank in advance!
 
I would like a script of a box that of random items with a percentage of chance of coming X item, the percentage would also have a category being: Common, Uncommon, Semi-rare, rare, legendary.
data/scripts/randombox.lua

Lua:
local RANDOM_ITEM_CATEGORY_COMMON = 1
local RANDOM_ITEM_CATEGORY_UNCOMMON = 2
local RANDOM_ITEM_CATEGORY_SEMI_RARE = 3
local RANDOM_ITEM_CATEGORY_RARE = 4
local RANDOM_ITEM_CATEGORY_LEGENDARY = 5

local config = {
    talkAction = "!randombox", -- only for admins
    randomItems = {
        {
            id = 2432, -- fire axe
            chance = 50, -- 50%
            count = {1, 1}, -- 1-1
            allowCategories = {
                RANDOM_ITEM_CATEGORY_COMMON,
                RANDOM_ITEM_CATEGORY_UNCOMMON
            }
        },
        {
            id = 2494, -- suddent death rune
            chance = 50, -- 50%
            count = {1, 100},
            allowCategories = {
                RANDOM_ITEM_CATEGORY_SEMI_RARE,
                RANDOM_ITEM_CATEGORY_RARE
            }
        },
        {
            id = "crystal coin",
            chance = 50, -- 50%
            count = {1, 20}, -- 1-20
            allowCategories = {
                RANDOM_ITEM_CATEGORY_COMMON,
                RANDOM_ITEM_CATEGORY_UNCOMMON
            }
        },
        {
            id = "red bag",
            chance = 50, -- 50%
            count = {1, 30}, -- 1-30
            allowCategories = {
                RANDOM_ITEM_CATEGORY_COMMON,
                RANDOM_ITEM_CATEGORY_UNCOMMON
            }
        },
        {
            id = "demon armor",
            chance = 50, -- 50%
            count = {1, 30}, -- 1-30
            allowCategories = {
                RANDOM_ITEM_CATEGORY_COMMON,
                RANDOM_ITEM_CATEGORY_UNCOMMON
            }
        }
    },
    customAttributeKey = "randomBoxCategory",
    categories = {
        {
            id = RANDOM_ITEM_CATEGORY_COMMON,
            name = "Common",
            chance = 70, -- 70%
        },
        {
            id = RANDOM_ITEM_CATEGORY_UNCOMMON,
            name = "Uncommon",
            chance = 50, -- 50%
        },
        {
            id = RANDOM_ITEM_CATEGORY_SEMI_RARE,
            name = "Semi-Rare",
            chance = 30, -- 30%
        },
        {
            id = RANDOM_ITEM_CATEGORY_RARE,
            name = "Rare",
            chance = 10, -- 10%
        },
        {
            id = RANDOM_ITEM_CATEGORY_LEGENDARY,
            name = "Legendary",
            chance = 1, -- 1%
        }
    },

    boxItemId = 1738, -- box
    boxRewardCount = 3, -- count of items in box
    boxCustomName = "Reward Box", -- box custom name
    boxCustomDescription = "This is a reward box.", -- box custom description
    boxPrice = 10000 * 70, -- box price 70 crystal coins
    leverActionId = 30006, -- lever action id
    leverItemdIdOn = 1945, -- lever item id on
    leverItemdIdOff = 1946 -- lever item id off
}

local function getRandomCategory(allowCategories)
    for _, ac in pairs(allowCategories) do
        local category = config.categories[ac]
        if category then
            if category.chance >= math.random(1, 100) then
                return category
            end
        end
    end
end

local function createRandomBox()
    local box = Game.createItem(config.boxItemId, 1)
    if box then
        box:setAttribute(ITEM_ATTRIBUTE_NAME, config.boxCustomName)
        box:setAttribute(ITEM_ATTRIBUTE_DESCRIPTION, config.boxCustomDescription)
        for _, randomItem in pairs(config.randomItems) do
            if randomItem.chance >= math.random(0, 100) then
                local count = math.random(randomItem.count[1], randomItem.count[2])
                for i = 1, randomItem.stacks or 1 do
                    local item = Game.createItem(randomItem.id, count)
                    if item then
                        if randomItem.allowCategories then
                            local category = getRandomCategory(randomItem.allowCategories)
                            if category then
                                item:setCustomAttribute(config.customAttributeKey, category.id)
                            end
                        end

                        if box:addItemEx(item) ~= RETURNVALUE_NOERROR then
                            item:remove()
                            break
                        end
                    end
                end
            end
        end
        return box
    end
end

local talkAction = TalkAction(config.talkAction)

function talkAction.onSay(player, words, param, type)
    local target = Player(param)
    if not target then
        player:sendCancelMessage("Player not found.")
        return false
    end

    local box = createRandomBox()
    if not box then
        debugPrint("[RandomBox] Error: Could not create box.")
        return false
    end

    local returnValue = target:addItemEx(box)
    if returnValue ~= RETURNVALUE_NOERROR then
        box:remove()
        player:sendCancelMessage(returnValue)
        return false
    end

    target:sendTextMessage(MESSAGE_INFO_DESCR, "You have received a reward box.\n" .. (target:getId() ~= player:getId() and "From: " .. player:getName() or ""))
    return false
end

talkAction:accountType(ACCOUNT_TYPE_GOD)
talkAction:access(true)
talkAction:separator(" ")
talkAction:register()

local action = Action()

function action.onUse(player, item, fromPos, target, toPos, isHotkey)
    if player:getMoney() < config.boxPrice then
        player:sendCancelMessage("You do not have enough money.")
        return true
    end

    local box = createRandomBox()
    if not box then
        debugPrint("[RandomBox] Error: Could not create box.")
        return true
    end

    if player:addItemEx(box) ~= RETURNVALUE_NOERROR then
        box:remove()
        player:sendCancelMessage(RETURNVALUE_NOTPOSSIBLE)
        return true
    end

    player:removeMoney(config.boxPrice)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "You buyed a reward box.")
    item:transform(item:getId() == config.leverItemdIdOn and config.leverItemdIdOff or config.leverItemdIdOn)
    player:getPosition():sendMagicEffect(CONST_ME_FIREWORK_YELLOW)
    return true
end

action:aid(config.leverActionId)
action:register()

local ec = EventCallback

function ec.onLook(player, thing, position, distance, description)
    if thing:isItem() then
        local category = thing:getCustomAttribute(config.customAttributeKey)
        if category then
            description = description .. "\nIt is " .. config.categories[category].name .. "."
        end
    end
    return description
end

ec:register(1)

Explore the settings and if you don't understand something let me know, but it should be easy.
Don't forget to set the ActionID of the toggle
GIF 25-06-2022 08-39-30 p. m..gif

If you have a God character on your God account you can use the command !randombox <playerName> for give item.
 
Tfs 1.5

A scroll when you use you learn a custom spell. ( instead of npc)


โ€”โ€”

Tfs 1.5

Kill points:

So when you kill creature in game you get a point, when a creature is stronger you get more points ( only selected creatures fully customisable in scripts config)

Once you kill creature that has been selected in config you get notification in server log. E.g You have earned 2 points, killed dragon lords 38
When you say command !points you will see how many you have points

Once you have earned for example 1000 points you can exchange it for a item by command. !points exchange. And there i can be a modal window or just a command !exchange with a name of item e.g !exchange stamina doll.

The killed creatures count never reset.


Thank you so much !
Post automatically merged:

Sorry for many requests if you think it is to complex just ignore thanks!

TFS 1.5
Statue that gives you a mount/addon once clicked
 
Last edited:
Back
Top