• 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 Xikini's Free Scripting Service TFS 1.3

Status
Not open for further replies.

Xikini

I whore myself out for likes
Senator
Joined
Nov 17, 2010
Messages
6,942
Solutions
589
Reaction score
5,606
Please request
actions / creatureevents / globalevents / npcs / movements / talkactions

Do not request
spells / weapons / monsters / source editing / database queries

My goal of this thread is to learn TFS 1.3 scripting.

------------------------------------
Support

If you have an issue with one of my scripts, I will attempt to help you, but not in this thread.
Make a thread in the support board.
Ensure to follow all rules of the support board.
Without all neccesary information it's impossible to help you.

------------------------------------
I will only be scripting for TFS 1.3

Not TFS 1.1 / 1.2
Not OTServBR / OTX
and certainly not TFS 0.4

When requesting a script, don't ask for "this script I saw on super popular OT".

I don't care where the idea came from.
I don't want to see a video of the script in action.

I'm here to learn how to script better.
Just describe what the script is supposed to do, and I'll try to make it.

Any script that I make in response to a request from this thread will be shared publically, here, in this thread.

I'm not going to make anything in private, so post your request in this thread only.
Please, for the love of god, don't pm me asking to make a script.
I will actually add you to my ignore list if you do that.
--------------

Anyways!

Thanks for coming by and checking the thread out.
If you think there is a better way to script something, feel free to let me know.
I'm here to learn.

Cheers,

Xikini

----

Completed Scripts

DPS Dummy -> using RevScripts
!playerinfo character name -> using RevScripts
Positional Text talkaction -> using RevScripts
||--> Updated version that can use text & effects
Vocational Item Bonus's -> using RevScripts
||--> Updated version with easier config.
Simple damge buff potion -> using Revscripts
Kill monster in specific area, remove stone for x seconds -> using RevScripts
Training Room Teleporter -> using RevScripts
Lever that removes/adds/transforms objects or ground tiles -> using RevScripts
Loot from monster goes into single backpack, no matter how much loot there is.
Extra loot in monsters, based on chance and tier list -> using RevScripts
||--> Updated version that allows specific monsters to have their own loot table
Random Item chest that disappears after use, and respawns after x time -> using RevScripts
Multiple players required to open passageway.
Monster Arena Lever (x amount of waves, complete all waves, teleport appears) -> using RevScripts
Daily Boosted Creatures (experience & loot chance of items)
||--> Updated main file of boosted creatures, so that it triggers at midnight, instead of when the server starts up.
Reward Chest - Extremely simple. -> using Revscripts
Simple Npc that can sell an item, via text.

----

Extremely useful libs that I use quite often.

data/lib/core/player.lua
Give player items by table

data/lib/core/container.lua
getContainerFreeSlots

----

To-Do List

Shalaby - Player death counter. (Movement and talkaction)
Shalaby - Npc kill monster task, with item reward.
Shalaby - Boss respawn after x time.

-------

Last spot I've read messages
 
Last edited:
I would like to see a script which allows players to buy inactive houses
As explain if someone has a House and hes more than 14+ days Inactive you can use a Command like
!inactivehouse but you must stand infront of the house door of the inactive player house
If the player is inactive more than 14 days the house will be sold and the guy can buy it normaly with !buyhouse
If the player is not inactive you getting a message with "Player name is not inactive"
Exhaustion Time of using command 30 seconds
 
I would like to see a script which allows players to buy inactive houses
As explain if someone has a House and hes more than 14+ days Inactive you can use a Command like
!inactivehouse but you must stand infront of the house door of the inactive player house
If the player is inactive more than 14 days the house will be sold and the guy can buy it normaly with !buyhouse
If the player is not inactive you getting a message with "Player name is not inactive"
Exhaustion Time of using command 30 seconds

Might be better to just edit the !buyhouse function to do that so your players don't have to learn an extra command, it'll just do the work for them automatically in the background.
 
Was wondering if is it possible to turn this Talking Signs into an actions script , I mean maybe changing positions with actionId like "Text1" if actionid xx "Text 2" if action id XX
in order to if i intented to set an immediat event i'll use /attr aid XX with the desired TEXT
There's no real point in using the actionID, since without the position.. we'd have to scan the entire map looking for it anyway.. which would be incredibly taxing on the server.

Instead, we'll just use the position data, and hold it in a table along with the text you want to use.

bandicam-2020-08-20-22-32-11-931.gif

data\scripts\ positionaltext.lua
LUA:
local positions = {} -- {positionData, text}

local globalevent = GlobalEvent("positional_text")

function globalevent.onThink(interval)
    local player = Game.getPlayers()
    if #player < 1 then
        return true
    end
    for i = 1, #positions do
        player[1]:say(positions[i][2], TALKTYPE_MONSTER_SAY, false, nil, positions[i][1])
    end
    return true
end

globalevent:interval(3000)
globalevent:register()

-----------------------------------------------------------------------------

local talk = TalkAction("/positionaltext")

function talk.onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return false
    end
    
    local playerPosition = player:getPosition()
    
    for i = 1, #positions do
        if positions[i][1] == playerPosition then
            if param == "" then
                table.remove(positions, i)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Text for this position has been turned off.")
                return false
            end
            positions[i][2] = param
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been updated.")
            return false
        end
    end
    
    if param == "" then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Requires param; /positionaltext text here")
        return false
    end
    
    table.insert(positions, {playerPosition, param})
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been activated.")
    return false
end

talk:separator(" ")
talk:register()
 
Guildmaster npc just like in the old days, here you can make your guild/invite new members/kick members/disband guild/give members an nickname.
 
You can extract first login from database using db.storeQuery, it should be located in players table. Last death would be most likely more complex, but again a query to player_deaths and conditional to look for most recent death. (time column)
I thinking about going back and adding the extra portions in.
Seems a waste to leave it out, and gives me a reason to learn database queries.

Will have to wait until my sleep schedule it better though. xD
I always end up scripting when I'm super tired. 🤷‍♂️

very nice thread and initiative!


well you could try using vocation:getRequiredManaSpent(magicLevel) to achieve this in a simple way.


I have a request tho, if you don't mind :p it will be very useful to the community (and players of course), to have a working Imbuing, system, but I thought about a really simple system (idea from this thread), no modal window involved so it can be used on lower tibia versions:

"Imbuing system" Adding attributes to items by slot

talkactions, for example

!imbue head, life leech, basic

and it will give player SPECIALSKILL_LIFELEECHCHANCE, 100 and SPECIALSKILL_LIFELEECHAMOUNT, 5 for 20 hours, at cost of 5k and 25 Vampire Teeth


okay, this seems a little more complicated than I thought as of writing it now 😁 If anyone feels like giving ideas on how to make it easier/more conceivable, I'm all ears
If I do this system, I'd rather do it in modal windows tbh.
Need to learn how they work. xP

I can do it with talkactions as well though.. or an npc?
I would just split/explode the strings apart and compare/evaluate them against a table.

Let me know which way you'd prefer.

I would like to see a script which allows players to buy inactive houses
As explain if someone has a House and hes more than 14+ days Inactive you can use a Command like
!inactivehouse but you must stand infront of the house door of the inactive player house
If the player is inactive more than 14 days the house will be sold and the guy can buy it normaly with !buyhouse
If the player is not inactive you getting a message with "Player name is not inactive"
Exhaustion Time of using command 30 seconds
Don't think this one is happening, as the entire thing is basically database queries.
This is similar, but made for TFS 1.2
It'll probably work?
Guildmaster npc just like in the old days, here you can make your guild/invite new members/kick members/disband guild/give members an nickname.
Adding this to my to-do list, so I can learn about guild functions.
Idk how useful the script itself will be though.. since you can literally do all of these things through the standard default websites everyone installs.

---------------

I've added a to-do list in the first post.

and I've basically fallen in love with RevScripts.
Everything about a system in a single file.. it's just so sexy.

Unless I absolutely have to script something differently, I'm going to be using RevScripts for everything.
 
There's no real point in using the actionID, since without the position.. we'd have to scan the entire map looking for it anyway.. which would be incredibly taxing on the server.

Instead, we'll just use the position data, and hold it in a table along with the text you want to use.

View attachment 49002

data\scripts\ positionaltext.lua
LUA:
local positions = {} -- {positionData, text}

local globalevent = GlobalEvent("positional_text")

function globalevent.onThink(interval)
    local player = Game.getPlayers()
    if #player < 1 then
        return true
    end
    for i = 1, #positions do
        player[1]:say(positions[i][2], TALKTYPE_MONSTER_SAY, false, nil, positions[i][1])
    end
    return true
end

globalevent:interval(3000)
globalevent:register()

-----------------------------------------------------------------------------

local talk = TalkAction("/positionaltext")

function talk.onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return false
    end

    local playerPosition = player:getPosition()

    for i = 1, #positions do
        if positions[i][1] == playerPosition then
            if param == "" then
                table.remove(positions, i)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Text for this position has been turned off.")
                return false
            end
            positions[i][2] = param
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been updated.")
            return false
        end
    end

    if param == "" then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Requires param; /positionaltext text here")
        return false
    end

    table.insert(positions, {playerPosition, param})
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been activated.")
    return false
end

talk:separator(" ")
talk:register()
Hmm i think u got me right! , Can i get it working for eariler tfs versions like OTX or tfs 1.2?
Also i see it appears permanently i mean , if it works like a count down will be better ? hmm appears every 2 seconds?
 
Hmm i think u got me right! , Can i get it working for eariler tfs versions like OTX or tfs 1.2?
As noted in the first post, I will only be working and creating scripts for tfs 1.3.
If they happen to work in another server type, that's entirely coincidental.
I simply don't know enough about TFS 1.0+ in order to know what will work on each specific server version.

hmm appears every 2 seconds?
It currently appears every 3 seconds, but it's easy to change it to whatever seconds you want.
LUA:
globalevent:interval(3000)


Also i see it appears permanently i mean , if it works like a count down will be better ?
I can modify the script to include additional functionality if you wish, but you'll need to explain what you need it to do.
 
As noted in the first post, I will only be working and creating scripts for tfs 1.3.
If they happen to work in another server type, that's entirely coincidental.
I simply don't know enough about TFS 1.0+ in order to know what will work on each specific server version.


It currently appears every 3 seconds, but it's easy to change it to whatever seconds you want.
LUA:
globalevent:interval(3000)



I can modify the script to include additional functionality if you wish, but you'll need to explain what you need it to do.

Unfortunatley , i guess rev scripts only work in newer tfs versions , I don't know if it works in eariler versions since it doesn't contain the script folder
Hmm , if u can add more functions like beside setting a text adding/removing an effect with a name like /positionaltext ,text1 , #EFFECT_NAME it also appears with the text
 
Last edited:
Unfortunatley , i guess rev scripts only work in newer tfs versions , I don't know if it works in eariler versions since it doesn't contain the script folder
Hmm , if u can add more functions like beside setting a text adding/removing an effect with a name like /positionaltext ,text1 , #EFFECT_NAME it also appears with the text
I was specifically mentioning TFS 1.3, due to the functions / source requirements possibly required by the scripts I will be creating.

As long as you have the other folders in your distribution, you can convert RevScript scripts into their equal counterparts and install it 'normally'

Example, using the script you requested.

data/lib/core/core.lua -- ADD
LUA:
dofile('data/lib/core/xikini_tables.lua')

create a new file
data/lib/core/xikini_tables.lua
LUA:
-- note that this is now a global table, so it might be prudent to change it's name to something less commonly used.
-- subsequently, you'd need to modify the talkaction and globalevent to use the new name as well
positions = {} -- {positionData, text}

data/globalevents/globalevents.xml
XML:
<event type="think" name="positional_text" interval="3000" script="positional_text.lua" />

data/globalevents/scripts/positional_text.lua
LUA:
function onThink(interval)
    local player = Game.getPlayers()
    if #player < 1 then
        return true
    end
    for i = 1, #positions do
        player[1]:say(positions[i][2], TALKTYPE_MONSTER_SAY, false, nil, positions[i][1])
    end
    return true
end

data/talkactions/talkactions.xml
XML:
<talkaction words="/positionaltext" separator=" " script="positionaltext.lua" />

data/talkactions/scripts/positionaltext.lua
LUA:
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return false
    end
   
    local playerPosition = player:getPosition()
   
    for i = 1, #positions do
        if positions[i][1] == playerPosition then
            if param == "" then
                table.remove(positions, i)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Text for this position has been turned off.")
                return false
            end
            positions[i][2] = param
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been updated.")
            return false
        end
    end
   
    if param == "" then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Requires param; /positionaltext text here")
        return false
    end
   
    table.insert(positions, {playerPosition, param})
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been activated.")
    return false
end
 
I was specifically mentioning TFS 1.3, due to the functions / source requirements possibly required by the scripts I will be creating.

As long as you have the other folders in your distribution, you can convert RevScript scripts into their equal counterparts and install it 'normally'

Example, using the script you requested.

data/lib/core/core.lua -- ADD
LUA:
dofile('data/lib/core/xikini_tables.lua')

create a new file
data/lib/core/xikini_tables.lua
LUA:
-- note that this is now a global table, so it might be prudent to change it's name to something less commonly used.
-- subsequently, you'd need to modify the talkaction and globalevent to use the new name as well
positions = {} -- {positionData, text}

data/globalevents/globalevents.xml
XML:
<event type="think" name="positional_text" interval="3000" script="positional_text.lua" />

data/globalevents/scripts/positional_text.lua
LUA:
function onThink(interval)
    local player = Game.getPlayers()
    if #player < 1 then
        return true
    end
    for i = 1, #positions do
        player[1]:say(positions[i][2], TALKTYPE_MONSTER_SAY, false, nil, positions[i][1])
    end
    return true
end

data/talkactions/talkactions.xml
XML:
<talkaction words="/positionaltext" separator=" " script="positionaltext.lua" />

data/talkactions/scripts/positionaltext.lua
LUA:
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return false
    end

    local playerPosition = player:getPosition()

    for i = 1, #positions do
        if positions[i][1] == playerPosition then
            if param == "" then
                table.remove(positions, i)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Text for this position has been turned off.")
                return false
            end
            positions[i][2] = param
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been updated.")
            return false
        end
    end

    if param == "" then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Requires param; /positionaltext text here")
        return false
    end

    table.insert(positions, {playerPosition, param})
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text for this position has been activated.")
    return false
end
Nvm i'll try it in 1.3 because i think it won't work that way,
If you can add the other funcionality that i suggested will be Great, which will be a way to add an effect beside the text with the same command like /positionaltext test1,#EFFECT NAME
If adding all effects will consume u forever , just add an effect or two
 
Last edited:
Nvm i'll try it in 1.3 because i think it won't work that way,
If you can add the other funcionality that i suggested will be Great, which will be a way to add an effect beside the text with the same command like /positionaltext test1,#EFFECT NAME
If adding all effects will consume u forever , just add an effect or two
I finished this earlier today but forgot to post it.
LUA:
/positionaltext
/positionaltext text
/positionaltext text, effect
/positionaltext no text, effect

-- putting text with no effect will display text only.
Example 1: /positionaltext text with no effect

-- using a , to separate the text from the effect will allow you to use the text and effect at the same time.
Example 2: /positionaltext teleport effect with text, CONST_ME_TELEPORT

-- using "no text" as the text, will stop the script from displaying text on that position.
Example 3: /positionaltext no text, CONST_ME_TELEPORT")

-- You can use the name or number of the effect. Both will work!
Example 4: /positionaltext no text, 11")

-- To disable text on a position, use no parameters
Example 5: /positionaltext

-- also, if a position has text/effects already on it, and you use the talkaction on that tile...
-- with the same / updated text/effect information, the script will simply update the information in the table.
bandicam-2020-08-21-15-52-39-147.gif

data\scripts\talkactions\ positionaltext.lua
LUA:
local effects = {CONST_ME_NONE, CONST_ME_DRAWBLOOD, CONST_ME_LOSEENERGY, CONST_ME_POFF, CONST_ME_BLOCKHIT, CONST_ME_EXPLOSIONAREA, CONST_ME_EXPLOSIONHIT, CONST_ME_FIREAREA, CONST_ME_YELLOW_RINGS, CONST_ME_GREEN_RINGS, CONST_ME_HITAREA, CONST_ME_TELEPORT, CONST_ME_ENERGYHIT, CONST_ME_MAGIC_BLUE, CONST_ME_MAGIC_RED, CONST_ME_MAGIC_GREEN, CONST_ME_HITBYFIRE, CONST_ME_HITBYPOISON, CONST_ME_MORTAREA, CONST_ME_SOUND_GREEN, CONST_ME_SOUND_RED, CONST_ME_POISONAREA, CONST_ME_SOUND_YELLOW, CONST_ME_SOUND_PURPLE, CONST_ME_SOUND_BLUE, CONST_ME_SOUND_WHITE, CONST_ME_BUBBLES, CONST_ME_CRAPS, CONST_ME_GIFT_WRAPS, CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_RED, CONST_ME_FIREWORK_BLUE, CONST_ME_STUN, CONST_ME_SLEEP, CONST_ME_WATERCREATURE, CONST_ME_GROUNDSHAKER, CONST_ME_HEARTS, CONST_ME_FIREATTACK, CONST_ME_ENERGYAREA, CONST_ME_SMALLCLOUDS, CONST_ME_HOLYDAMAGE, CONST_ME_BIGCLOUDS, CONST_ME_ICEAREA, CONST_ME_ICETORNADO, CONST_ME_ICEATTACK, CONST_ME_STONES, CONST_ME_SMALLPLANTS, CONST_ME_CARNIPHILA, CONST_ME_PURPLEENERGY, CONST_ME_YELLOWENERGY, CONST_ME_HOLYAREA, CONST_ME_BIGPLANTS, CONST_ME_CAKE, CONST_ME_GIANTICE, CONST_ME_WATERSPLASH, CONST_ME_PLANTATTACK, CONST_ME_TUTORIALARROW, CONST_ME_TUTORIALSQUARE, CONST_ME_MIRRORHORIZONTAL, CONST_ME_MIRRORVERTICAL, CONST_ME_SKULLHORIZONTAL, CONST_ME_SKULLVERTICAL, CONST_ME_ASSASSIN, CONST_ME_STEPSHORIZONTAL, CONST_ME_BLOODYSTEPS, CONST_ME_STEPSVERTICAL, CONST_ME_YALAHARIGHOST, CONST_ME_BATS, CONST_ME_SMOKE, CONST_ME_INSECTS, CONST_ME_DRAGONHEAD, CONST_ME_ORCSHAMAN, CONST_ME_ORCSHAMAN_FIRE, CONST_ME_THUNDER, CONST_ME_FERUMBRAS, CONST_ME_CONFETTI_HORIZONTAL, CONST_ME_CONFETTI_VERTICAL, CONST_ME_BLACKSMOKE, CONST_ME_REDSMOKE, CONST_ME_YELLOWSMOKE, CONST_ME_GREENSMOKE, CONST_ME_PURPLESMOKE, CONST_ME_EARLY_THUNDER, CONST_ME_RAGIAZ_BONECAPSULE, CONST_ME_CRITICAL_DAMAGE, CONST_ME_PLUNGING_FISH}
local positions = {} -- {positionData, text, effect}

local globalevent = GlobalEvent("positional_text")

function globalevent.onThink(interval)
    local player = Game.getPlayers()
    if #player < 1 then
        return true
    end
    for i = 1, #positions do
        if positions[i][2] ~= "no text" then
            player[1]:say(positions[i][2], TALKTYPE_MONSTER_SAY, false, nil, positions[i][1])
        end
        if positions[i][3] ~= CONST_ME_NONE then
            positions[i][1]:sendMagicEffect(positions[i][3])
        end
    end
    return true
end

globalevent:interval(3000)
globalevent:register()

-----------------------------------------------------------------------------

local talk = TalkAction("/positionaltext")

function talk.onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return false
    end

    local playerPosition = player:getPosition()

    local split = param:splitTrimmed(",")
    if not split[2] then
        split[2] = "CONST_ME_NONE"
    end

    local text = split[1]
    local effect = (tonumber(split[2]) ~= nil and tonumber(split[2]) or _G[split[2]]) -- converts the string into a number if possible otherwise the variable name or string into number

    if not isInArray(effects, effect) then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Effect parameter (" .. split[2] .. ") is invalid. Check spelling, or use the number variant.")
        return false
    end

    for i = 1, #positions do
        if positions[i][1] == playerPosition then
            if param == "" then
                table.remove(positions, i)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "This position will no longer have text or effects.")
                return false
            end
            positions[i][2] = text
            positions[i][3] = effect
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text and effects for this position have been updated.")
            return false
        end
    end

    if param == "" then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Requires param; /positionaltext text[, effect] -> /positionaltext no text, effect\nExample 1: /positionaltext text with no effect\nExample 2: /positionaltext teleport effect with text, CONST_ME_TELEPORT\nExample 3: /positionaltext no text, CONST_ME_TELEPORT")
        return false
    end

    table.insert(positions, {playerPosition, text, effect})
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text and effects for this position has been activated.")
    return false
end

talk:separator(" ")
talk:register()
 
Last edited:
I finished this earlier today but forgot to post it.
LUA:
/positionaltext
/positionaltext text
/positionaltext text, effect
/positionaltext no text, effect

-- putting text with no effect will display text only.
Example 1: /positionaltext text with no effect

-- using a , to separate the text from the effect will allow you to use the text and effect at the same time.
Example 2: /positionaltext teleport effect with text, CONST_ME_TELEPORT

-- using "no text" as the text, will stop the script from displaying text on that position.
Example 3: /positionaltext no text, CONST_ME_TELEPORT")

-- You can use the name or number of the effect. Both will work!
Example 4: /positionaltext no text, 11")

-- To disable text on a position, use no parameters
Example 5: /positionaltext

-- also, if a position has text/effects already on it, and you use the talkaction on that tile...
-- with the same / updated text/effect information, the script will simply update the information in the table.
View attachment 49077

data\scripts\talkactions\ positionaltext.lua
LUA:
local effects = {CONST_ME_NONE, CONST_ME_DRAWBLOOD, CONST_ME_LOSEENERGY, CONST_ME_POFF, CONST_ME_BLOCKHIT, CONST_ME_EXPLOSIONAREA, CONST_ME_EXPLOSIONHIT, CONST_ME_FIREAREA, CONST_ME_YELLOW_RINGS, CONST_ME_GREEN_RINGS, CONST_ME_HITAREA, CONST_ME_TELEPORT, CONST_ME_ENERGYHIT, CONST_ME_MAGIC_BLUE, CONST_ME_MAGIC_RED, CONST_ME_MAGIC_GREEN, CONST_ME_HITBYFIRE, CONST_ME_HITBYPOISON, CONST_ME_MORTAREA, CONST_ME_SOUND_GREEN, CONST_ME_SOUND_RED, CONST_ME_POISONAREA, CONST_ME_SOUND_YELLOW, CONST_ME_SOUND_PURPLE, CONST_ME_SOUND_BLUE, CONST_ME_SOUND_WHITE, CONST_ME_BUBBLES, CONST_ME_CRAPS, CONST_ME_GIFT_WRAPS, CONST_ME_FIREWORK_YELLOW, CONST_ME_FIREWORK_RED, CONST_ME_FIREWORK_BLUE, CONST_ME_STUN, CONST_ME_SLEEP, CONST_ME_WATERCREATURE, CONST_ME_GROUNDSHAKER, CONST_ME_HEARTS, CONST_ME_FIREATTACK, CONST_ME_ENERGYAREA, CONST_ME_SMALLCLOUDS, CONST_ME_HOLYDAMAGE, CONST_ME_BIGCLOUDS, CONST_ME_ICEAREA, CONST_ME_ICETORNADO, CONST_ME_ICEATTACK, CONST_ME_STONES, CONST_ME_SMALLPLANTS, CONST_ME_CARNIPHILA, CONST_ME_PURPLEENERGY, CONST_ME_YELLOWENERGY, CONST_ME_HOLYAREA, CONST_ME_BIGPLANTS, CONST_ME_CAKE, CONST_ME_GIANTICE, CONST_ME_WATERSPLASH, CONST_ME_PLANTATTACK, CONST_ME_TUTORIALARROW, CONST_ME_TUTORIALSQUARE, CONST_ME_MIRRORHORIZONTAL, CONST_ME_MIRRORVERTICAL, CONST_ME_SKULLHORIZONTAL, CONST_ME_SKULLVERTICAL, CONST_ME_ASSASSIN, CONST_ME_STEPSHORIZONTAL, CONST_ME_BLOODYSTEPS, CONST_ME_STEPSVERTICAL, CONST_ME_YALAHARIGHOST, CONST_ME_BATS, CONST_ME_SMOKE, CONST_ME_INSECTS, CONST_ME_DRAGONHEAD, CONST_ME_ORCSHAMAN, CONST_ME_ORCSHAMAN_FIRE, CONST_ME_THUNDER, CONST_ME_FERUMBRAS, CONST_ME_CONFETTI_HORIZONTAL, CONST_ME_CONFETTI_VERTICAL, CONST_ME_BLACKSMOKE, CONST_ME_REDSMOKE, CONST_ME_YELLOWSMOKE, CONST_ME_GREENSMOKE, CONST_ME_PURPLESMOKE, CONST_ME_EARLY_THUNDER, CONST_ME_RAGIAZ_BONECAPSULE, CONST_ME_CRITICAL_DAMAGE, CONST_ME_PLUNGING_FISH}
local positions = {} -- {positionData, text, effect}

local globalevent = GlobalEvent("positional_text")

function globalevent.onThink(interval)
    local player = Game.getPlayers()
    if #player < 1 then
        return true
    end
    for i = 1, #positions do
        if positions[i][2] ~= "no text" then
            player[1]:say(positions[i][2], TALKTYPE_MONSTER_SAY, false, nil, positions[i][1])
        end
        if positions[i][3] ~= CONST_ME_NONE then
            positions[i][1]:sendMagicEffect(positions[i][3])
        end
    end
    return true
end

globalevent:interval(3000)
globalevent:register()

-----------------------------------------------------------------------------

local talk = TalkAction("/positionaltext")

function talk.onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return false
    end

    local playerPosition = player:getPosition()

    local split = param:splitTrimmed(",")
    if not split[2] then
        split[2] = "CONST_ME_NONE"
    end

    local text = split[1]
    local effect = (tonumber(split[2]) ~= nil and tonumber(split[2]) or _G[split[2]]) -- converts the string into a number if possible otherwise the variable name or string into number

    if not isInArray(effects, effect) then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Effect parameter (" .. split[2] .. ") is invalid. Check spelling, or use the number variant.")
        return false
    end

    for i = 1, #positions do
        if positions[i][1] == playerPosition then
            if param == "" then
                table.remove(positions, i)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "This position will no longer have text or effects.")
                return false
            end
            positions[i][2] = text
            positions[i][3] = effect
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text and effects for this position have been updated.")
            return false
        end
    end

    if param == "" then
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, "Requires param; /positionaltext text[, effect] -> /positionaltext no text, effect\nExample 1: /positionaltext text with no effect\nExample 2: /positionaltext teleport effect with text, CONST_ME_TELEPORT\nExample 3: /positionaltext no text, CONST_ME_TELEPORT")
        return false
    end

    table.insert(positions, {playerPosition, text, effect})
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Text and effects for this position has been activated.")
    return false
end

talk:separator(" ")
talk:register()
Awesome!!
Here we go , i am thinking if u can make a recovery back item system it will be usefull for all if they liked to use!
A token can put owner name on an item(if i used a token on itemx it will hold myname) this not the only purpose of this token , It also used to upgrade this item to be able to use rare attributes(which it's now able to do after using this token) 1 token open 1 attribute.
Now the recvoery part , this token should work on specefic item names , There should be a talkaction script which u can use to get this item back if you lost for a specific amount of money and level, also it can only be used twice each week , using the command only without item name should show a list that contain name of items that u can get back , character's name , Also if there is a way to allow this item to be only threw on specific tiles
You may also add more functionalities if u wish
 
You could create a script in which when you click X item, you get monsters, and in order to click X item again you have to kill the monsters, and so on up to 4 times so that at the end a boss appears and when you kill it create a teleport that will take you somewhere.
 
now make a configurable script where a specific piece of armor grants separate bonuses based on the vocation of the wearer
example:
sorc -> gain magic level
druid -> gain mana
pally -> gain dist
knight -> gain melee
Alright, so I finally got around to it. xD

There are 32 different attributes you can apply to an item.

When registering an item you need to put the itemid in 3 spots.
Config Table, onEquip and onDeEquip.

I should note here that if the item is already registered in regular movements.xml, this code won't work on that item.

data\scripts\movements\ vocations_item_bonus.lua
LUA:
local config  = {
    [1111] = { -- itemid
        slot = "ammo", -- ("head", "necklace", "backpack", "armor", "shield", "weapon", "legs", "feet", "ring", "ammo")
        {
            [{1, 5}] = { -- vocation 1 and vocation 5
                ["statMain"] = {
                    -- flat_bonus_stats
                    {"life increase", 50},
                    {"mana increase", -200}, -- negative numbers will reduce a players stats
                    {"magic", 5},
                    {"melee", 15}, -- sword/axe/club
                    {"fist", 5},
                    {"club", 5}, -- if both melee and club exist on a single item, club will be the one that will trigger.
                    {"sword", 5}, -- example: (melee 20) -> (sword 5) ----> Result: (club 20) (sword 5) (axe 20)
                    {"axe", 5},
                    {"distance", 5},
                    {"shield", 5},
                    {"fishing", 5},
                    {"critical hit chance", 5},
                    {"critical hit damage", 5},
                    {"life leech chance", 5},
                    {"life leech amount", 5},
                    {"mana leech chance", 5},
                    {"mana leech amount", 5},
                    -- percent_bonus_stats
                    {"life increase percent", 200}, -- If using flat_bonus_stats and percent_bonus_stats on the same item, the percent_bonus_stats is the only one that will trigger.
                    {"mana increase percent", 200}, -- same idea as melee/club, but for flat/percent
                    {"magic percent", 3000},
                    {"melee percent", 200},
                    {"fist percent", 200}, -- 200 = 200%  -> 15 fisting would turn into 30
                    {"club percent", 200},
                    {"sword percent", 200},
                    {"axe percent", 200},
                    {"distance percent", 200},
                    {"shield percent", 200},
                    {"fishing percent", 200}
                },
                ["statSpeed"] = {
                    {"speed", 1000} -- when testing, it only gave half of this value. Might just be my client though
                },
                ["statRegen"] = {
                    {"life regen", 5, 5000}, --{type, amount, ticks_in_milliseconds}
                    {"mana regen", 5, 5000}  -- (can't go lower then 1 second)
                },
                ["statSoulRegen"] = {
                    {"soul regen", 5, 5000}
                },
            },
            [{2, 6}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            },
            [{3, 7}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            },
            [{4, 8}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            }
        }
    },
    [2222] = {
        slot = "armor",
        {
            [{1, 5}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            },
            [{2, 6}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            },
            [{3, 7}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            },
            [{4, 8}] = {
                ["statMain"] = {},
                ["statSpeed"] = {},
                ["statRegen"] = {},
                ["statSoulRegen"] = {}
            }
        }
    },
    [3333] = {
        slot = "ammo",
        {
            [{1, 5}] = {["statMain"] = {{"magic", 5}} },
            [{2, 6}] = {["statSpeed"] = {{"speed", 500}} },
            [{3, 7}] = {["statRegen"] = {{"life regen", 5, 5000}} },
            [{4, 8}] = {["statSoulRegen"] = {{"soul regen", 5, 5000}} }
        }
    }
}

local function convertSlotTextToNumber(slot)
    local text = nil
    if slot == "head" then
        slot = 1
    elseif slot == "necklace" then
        slot = 2
    elseif slot == "backpack" then
        slot = 3
    elseif slot == "armor" then
        slot = 4
    elseif slot == "shield" then
        slot = 5
    elseif slot == "weapon" then
        slot = 6
    elseif slot == "legs" then
        slot = 7
    elseif slot == "feet" then
        slot = 8
    elseif slot == "ring" then
        slot = 9
    elseif slot == "ammo" then
        slot = 10
    end
    return slot
end

local condition_ids = {
    CONDITIONID_HEAD,
    CONDITIONID_NECKLACE,
    CONDITIONID_BACKPACK,
    CONDITIONID_ARMOR,
    CONDITIONID_RIGHT,
    CONDITIONID_LEFT,
    CONDITIONID_LEGS,
    CONDITIONID_FEET,
    CONDITIONID_RING,
    CONDITIONID_AMMO
}

local conditions = {
    ["life increase"] = {CONDITION_PARAM_STAT_MAXHITPOINTS},
    ["mana increase"] = {CONDITION_PARAM_STAT_MAXMANAPOINTS},
    ["speed"] = {CONDITION_PARAM_SPEED},
    ["magic"] = {CONDITION_PARAM_STAT_MAGICPOINTS},
    ["melee"] = {CONDITION_PARAM_SKILL_MELEE},
    ["fist"] = {CONDITION_PARAM_SKILL_FIST},
    ["club"] = {CONDITION_PARAM_SKILL_CLUB},
    ["sword"] = {CONDITION_PARAM_SKILL_SWORD},
    ["axe"] = {CONDITION_PARAM_SKILL_AXE},
    ["distance"] = {CONDITION_PARAM_SKILL_DISTANCE},
    ["shield"] = {CONDITION_PARAM_SKILL_SHIELD},
    ["fishing"] = {CONDITION_PARAM_SKILL_FISHING},
    ["critical hit chance"] = {CONDITION_PARAM_SPECIALSKILL_CRITICALHITCHANCE},
    ["critical hit damage"] = {CONDITION_PARAM_SPECIALSKILL_CRITICALHITAMOUNT},
    ["life leech chance"] = {CONDITION_PARAM_SPECIALSKILL_LIFELEECHCHANCE},
    ["life leech amount"] = {CONDITION_PARAM_SPECIALSKILL_LIFELEECHAMOUNT},
    ["mana leech chance"] = {CONDITION_PARAM_SPECIALSKILL_MANALEECHCHANCE},
    ["mana leech amount"] = {CONDITION_PARAM_SPECIALSKILL_MANALEECHAMOUNT},
    ["life increase percent"] = {CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT},
    ["mana increase percent"] = {CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT},
    ["magic percent"] = {CONDITION_PARAM_STAT_MAGICPOINTSPERCENT},
    ["melee percent"] = {CONDITION_PARAM_SKILL_MELEEPERCENT},
    ["fist percent"] = {CONDITION_PARAM_SKILL_FISTPERCENT},
    ["club percent"] = {CONDITION_PARAM_SKILL_CLUBPERCENT},
    ["sword percent"] = {CONDITION_PARAM_SKILL_SWORDPERCENT},
    ["axe percent"] = {CONDITION_PARAM_SKILL_AXEPERCENT},
    ["distance percent"] = {CONDITION_PARAM_SKILL_DISTANCEPERCENT},
    ["shield percent"] = {CONDITION_PARAM_SKILL_SHIELDPERCENT},
    ["fishing percent"] = {CONDITION_PARAM_SKILL_FISHINGPERCENT},
    ["life regen"] = {CONDITION_PARAM_HEALTHGAIN, CONDITION_PARAM_HEALTHTICKS},
    ["mana regen"] = {CONDITION_PARAM_MANAGAIN, CONDITION_PARAM_MANATICKS},
    ["soul regen"] = {CONDITION_PARAM_SOULGAIN, CONDITION_PARAM_SOULTICKS}
}

local main_attributes = {CONDITION_ATTRIBUTES, CONDITION_HASTE, CONDITION_REGENERATION, CONDITION_SOUL}
local main_stats = {"statMain", "statSpeed", "statRegen", "statSoulRegen"}

local function giveItemBonus(playerid)
    local player = Player(playerid)
    local player_equipment = {}
  
    -- find all player equipment
    for i = 1, 10 do
        local slotItem = player:getSlotItem(i)
        if slotItem then
            slotItem = slotItem.itemid
            if not config[slotItem] or convertSlotTextToNumber(config[slotItem].slot) ~= i then
                slotItem = 0
            end
        else
            slotItem = 0
        end
        table.insert(player_equipment, slotItem)
    end
  
    -- remove all buffs from armor
    for i = 1, 10 do
        for n = 1, 4 do
            if player:getCondition(main_attributes[n], condition_ids[i]) then
                player:removeCondition(main_attributes[n], condition_ids[i])
            end
        end
    end
  
    -- add all buffs from equipment
    local vocation = player:getVocation():getId()
    for i = 1, 10 do
        local itemID = player_equipment[i]
        if itemID ~= 0 then
            for voc, _ in pairs(config[itemID][1]) do
                if isInArray(voc, vocation) then
                    for n = 1, 4 do
                        if config[itemID][1][voc][main_stats[n]] then
                            local condition = Condition(main_attributes[n], condition_ids[i])
                            condition:setParameter(CONDITION_PARAM_TICKS, -1)
                            local itemBonusIndex = config[itemID][1][voc][main_stats[n]]
                            for h = 1, #itemBonusIndex do
                                for p = 1, #conditions[itemBonusIndex[h][1]] do
                                    condition:setParameter(conditions[itemBonusIndex[h][1]][p], itemBonusIndex[h][2])
                                end
                            end
                            player:addCondition(condition)
                        end
                    end
                end
            end
        end
    end
    return true
end


-- HEAD -------------------------------------------------------------------------------
local onEquip_Head = MoveEvent()

function onEquip_Head.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Head:slot("head")
onEquip_Head:id(1111, 2222, 3333)
onEquip_Head:register()


local onDeEquip_Head = MoveEvent()

function onDeEquip_Head.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Head:slot("head")
onDeEquip_Head:id(1111, 2222, 3333)
onDeEquip_Head:register()



-- NECKLACE -------------------------------------------------------------------------------
local onEquip_Necklace = MoveEvent()

function onEquip_Necklace.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Necklace:slot("necklace")
onEquip_Necklace:id(1111, 2222, 3333)
onEquip_Necklace:register()


local onDeEquip_Necklace = MoveEvent()

function onDeEquip_Necklace.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Necklace:slot("necklace")
onDeEquip_Necklace:id(1111, 2222, 3333)
onDeEquip_Necklace:register()


-- BACKPACK -------------------------------------------------------------------------------
local onEquip_Backpack = MoveEvent()

function onEquip_Backpack.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Backpack:slot("backpack")
onEquip_Backpack:id(1111, 2222, 3333)
onEquip_Backpack:register()


local onDeEquip_Backpack = MoveEvent()

function onDeEquip_Backpack.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Backpack:slot("backpack")
onDeEquip_Backpack:id(1111, 2222, 3333)
onDeEquip_Backpack:register()


-- ARMOR -------------------------------------------------------------------------------
local onEquip_Armor = MoveEvent()

function onEquip_Armor.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Armor:slot("armor")
onEquip_Armor:id(1111, 2222, 3333)
onEquip_Armor:register()


local onDeEquip_Armor = MoveEvent()

function onDeEquip_Armor.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Armor:slot("armor")
onDeEquip_Armor:id(1111, 2222, 3333)
onDeEquip_Armor:register()


-- WEAPONS AND SHIELDS (hands) --------------------------------------------------------
local onEquip_Hands = MoveEvent()

function onEquip_Hands.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Hands:slot("hand")
onEquip_Hands:id(1111, 2222, 3333)
onEquip_Hands:register()

local onDeEquip_Hands = MoveEvent()

function onDeEquip_Hands.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Hands:slot("hand")
onDeEquip_Hands:id(1111, 2222, 3333)
onDeEquip_Hands:register()

-- LEGS -------------------------------------------------------------------------------
local onEquip_Legs = MoveEvent()

function onEquip_Legs.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Legs:slot("legs")
onEquip_Legs:id(1111, 2222, 3333)
onEquip_Legs:register()


local onDeEquip_Legs = MoveEvent()

function onDeEquip_Legs.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Legs:slot("legs")
onDeEquip_Legs:id(1111, 2222, 3333)
onDeEquip_Legs:register()


-- FEET -------------------------------------------------------------------------------
local onEquip_Feet = MoveEvent()

function onEquip_Feet.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Feet:slot("feet")
onEquip_Feet:id(1111, 2222, 3333)
onEquip_Feet:register()


local onDeEquip_Feet = MoveEvent()

function onDeEquip_Feet.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Feet:slot("feet")
onDeEquip_Feet:id(1111, 2222, 3333)
onDeEquip_Feet:register()


-- RING -------------------------------------------------------------------------------
local onEquip_Ring = MoveEvent()

function onEquip_Ring.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Ring:slot("ring")
onEquip_Ring:id(1111, 2222, 3333)
onEquip_Ring:register()


local onDeEquip_Ring = MoveEvent()

function onDeEquip_Ring.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Ring:slot("ring")
onDeEquip_Ring:id(1111, 2222, 3333)
onDeEquip_Ring:register()


-- AMMO -------------------------------------------------------------------------------
local onEquip_Ammo = MoveEvent()

function onEquip_Ammo.onEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onEquip_Ammo:slot("ammo")
onEquip_Ammo:id(1111, 2222, 3333)
onEquip_Ammo:register()


local onDeEquip_Ammo = MoveEvent()

function onDeEquip_Ammo.onDeEquip(player, item, slot, isCheck)
    if not isCheck then
        addEvent(giveItemBonus, 0, player:getId())
    end
    return true
end

onDeEquip_Ammo:slot("ammo")
onDeEquip_Ammo:id(1111, 2222, 3333)
onDeEquip_Ammo:register()


-- LOGIN ------------------------------------------------------------------------------
local loginEvent = CreatureEvent("newLoginEvent")
loginEvent:type("login")

function loginEvent.onLogin(player)
    addEvent(giveItemBonus, 0, player:getId())
    return true
end

loginEvent:register()
 
Last edited:
Is it one script per person? in case you say no, you could make a script of an npc that sells tibia coins and it executes a sql query to add it to the database, but that you can buy from 1 tibia coin to infinity, of course with a price of 'X' by tibia coin.
 
how about fix this one.


Incomplete script. It indeed work, but you need to do a function to verify every tile for free slots after every teleportation, otherwise when someone is teleported to a tile, it never clear itself, even before the player leaves. So the way that is, only one player can use all slots if he leaves and come back, then after using all slots, no one can enter anymore...

or make it onMove and spawn the trainer too if player stepin
 
Daily boosted creature please
Sorry,
It should preferably yield 2x more experience, 2x more loot and start everyday at server startup
I'll look into it, but no promises. xD
Is it one script per person?
Request as many as you like.
I won't guarantee that I can do them all though.
you could make a script of an npc that sells tibia coins and it executes a sql query to add it to the database, but that you can buy from 1 tibia coin to infinity, of course with a price of 'X' by tibia coin.
as per main post.. VV
Sorry.
Do not request
spells / weapons / monsters / source editing / [B]database queries[/B]
how about fix this one.


Incomplete script. It indeed work, but you need to do a function to verify every tile for free slots after every teleportation, otherwise when someone is teleported to a tile, it never clear itself, even before the player leaves. So the way that is, only one player can use all slots if he leaves and come back, then after using all slots, no one can enter anymore...

or make it onMove and spawn the trainer too if player stepin
Can you please explain what you want the script to do?
 
Status
Not open for further replies.

Similar threads

Back
Top