• 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 Snavy & Levi - Free Scripting Service - TFS 1.3

Status
Not open for further replies.

Snavy

Bakasta
Senator
Joined
Apr 1, 2012
Messages
1,249
Solutions
71
Reaction score
621
Location
Hell
@Levi999x and I will be providing scripting service for free.
The thread will be locked after a while but might be unlocked again later.



[ REQUIREMENTS ]

TFS
: 1.3(+) ( github.com/otland/forgottenserver )

SCRIPTS: Actions, Creaturescripts, Globalevents, Movements, Talkactions

INFO: Give a detailed explanation of what you want.
If we fail to understand what you're saying your request will probably be ignored.



[ SUPPORT ]
If you have any problems with the scripts, feel free to open a new thread in the
support board and make sure you follow the rules.



[⚠️ WARNING ⚠️]
Your post will be deleted if you ask for help in this thread.
You may not PM either of us for script requests.
Requests which require source modifications will be ignored.

Requests for the following engines will be ignored.
  • OTBR,
  • OTX,
  • TFS 1.2(or lower)



If either of us reacts like (👍) on your request, that means it is accepted.
 
Last edited:
what you mean tfs doesnt have?
it does :eek:?
It definitely exists. xP
Lua:
    ["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},

sorry, I meant 8.6 tfs 1.3 by nekiro
 
A couple of boss spells a "spell pack" if you will. Do one, do all, do none up to you guys haha. I could come up with 30+ more if you want different ideas lol.

1 = a boss shoots an icicle out at everyone at once hitting them for configurable damage and freezing them in place for 5 seconds (can't move but can cast etc)

2 = boss spawns a mob that locks onto a target and it increases in speed each second untill it either reaches 10 seconds and explodes or it reaches its target and explodesnfor a configed amount of damage.

3 = the boss does a frontal "cone" type sythe shaped slash of damage.

4 = boss does a life sap, he saps every player around him for 25% of their hp and heals himself with it. With a cool animation.

5 = boss marks an area, after 5 seconds rock's fall and you take a considerable amount of damage if you don't move out of the area.

Your welcome to tweak them a bit or change them completly lol. That's all off the top of my head could go on for hours but boss spells I think are fare and few between on otland.

Cheers
 
Last edited:
Hi friends, there is a possibility that the monster corpse appears in another position or that a teleport is generated under the monster and when the corpse leaves it will be teleported to another position, I am attentive to your answer if it can be done and help me with that code
 
Hey bro, I would like a talkaction that I could mute players on any channel by specifying this way:

/pmute, (player name), (channel name or id), (muted time hours), (reason)

And unmute with:

/punmute, (player name)

Thank you Sir!
global.lua
Lua:
CHAT_CHANNEL_ID_BEGIN = 153810

data/scripts/mutechannel.lua
Lua:
local channelNames = {
    ['tutor'] = 2,
    ['world'] = 3,
    ['english'] = 4,
    ['advertising'] = 5,
    ['advertising-rookgaard'] = 6,
    ['help'] = 7
}

local timeConfig = {
    ['h'] = 60 * 60,
    ['m'] = 60,
    ['s'] = 1
}

local function getChannelName(id)
    for name, chid in pairs(channelNames) do
        if chid == id then return name end
    end
    return nil
end

local ta = TalkAction('!mute','!unmute')
function ta.onSay(player, words, param)
    --[[
        Usage:
            !mute <player name>,<channel name|id>,<time>,<reason>
            examples:
            !mute Potato,help,5m,lolnub rekt xD
            !mute Potato,5,15s,kekw
            !mute Potato,advertising,10h,shut pls
        ---------------------------------------------------------------
        Usage:
            !unmute <player name>,<channel name|id>
        examples:
            !unmute Potato,3
    ]]

    local word = words:split(' ')[1]
    param = param:split(',')

    local targetPlayer = Player(param[1])
    if not targetPlayer then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Player does not exist or is currently offline.')
        return false
    end

    if not param[2] then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'channel name/id required.')
        return false
    end

    local channelId = tonumber(param[2]) or channelNames[param[2]:lower()]
    if not channelId then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Unknown channel.')
        return false
    end

    local channelName = getChannelName(channelId)
    channelId = CHAT_CHANNEL_ID_BEGIN + channelId

    if word == '!unmute' then
        if targetPlayer:getStorageValue(channelId) <= os.time() then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Player is not muted.')
            return false
        end
        targetPlayer:setStorageValue(channelId, 0)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Player has been unmuted from ' .. channelName .. ' chat.')
        targetPlayer:sendTextMessage(MESSAGE_STATUS_SMALL, 'You have been unmuted from ' .. channelName .. ' chat.')
        return false
    end

    local timeString = param[3]
    if not timeString or #timeString <= 1 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Invalid time input format.')
        return false
    end

    local timeUnit = string.sub(param[3], -1) -- h, m or s
    local digits = tonumber(param[3]:sub(1, #param[3] - 1))
    if not digits then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Invalid time input.')
        return false
    end

    if not timeConfig[timeUnit] then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Unknown timeUnit ('..timeUnit..')')
        return false
    end

    targetPlayer:setStorageValue(channelId, os.time() + (timeConfig[timeUnit] * digits))
    targetPlayer:sendTextMessage(
        MESSAGE_STATUS_CONSOLE_ORANGE, 
        'You have been muted on '.. channelName ..' chat for '
            ..(digits .. timeUnit .. (digits > 1 and '\'s' or ''))..
        '.\nReason: '.. (param[4] or 'None.')
    )
    return false
end
ta:separator(' ')
ta:register()

Note you need to add the following lines in each channel file:
data/chatchannels/scripts/<channelName>.lua
Lua:
local WORLD_CHAT_ID = 3 -- channel ID, change according to chatchannels.xml

-- place this inside onSpeak function
local storageMuted = player:getStorageValue(CHAT_CHANNEL_ID_BEGIN + WORLD_CHAT_ID)
if storageMuted > os.time() then
    player:sendCancelMessage('You have been muted in this channel. Try again later.')
    return false
end
 
global.lua
Lua:
CHAT_CHANNEL_ID_BEGIN = 153810

data/scripts/mutechannel.lua
Lua:
local channelNames = {
    ['tutor'] = 2,
    ['world'] = 3,
    ['english'] = 4,
    ['advertising'] = 5,
    ['advertising-rookgaard'] = 6,
    ['help'] = 7
}

local timeConfig = {
    ['h'] = 60 * 60,
    ['m'] = 60,
    ['s'] = 1
}

local function getChannelName(id)
    for name, chid in pairs(channelNames) do
        if chid == id then return name end
    end
    return nil
end

local ta = TalkAction('!mute','!unmute')
function ta.onSay(player, words, param)
    --[[
        Usage:
            !mute <player name>,<channel name|id>,<time>,<reason>
            examples:
            !mute Potato,help,5m,lolnub rekt xD
            !mute Potato,5,15s,kekw
            !mute Potato,advertising,10h,shut pls
        ---------------------------------------------------------------
        Usage:
            !unmute <player name>,<channel name|id>
        examples:
            !unmute Potato,3
    ]]

    local word = words:split(' ')[1]
    param = param:split(',')

    local targetPlayer = Player(param[1])
    if not targetPlayer then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Player does not exist or is currently offline.')
        return false
    end

    if not param[2] then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'channel name/id required.')
        return false
    end

    local channelId = tonumber(param[2]) or channelNames[param[2]:lower()]
    if not channelId then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Unknown channel.')
        return false
    end

    local channelName = getChannelName(channelId)
    channelId = CHAT_CHANNEL_ID_BEGIN + channelId

    if word == '!unmute' then
        if targetPlayer:getStorageValue(channelId) <= os.time() then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Player is not muted.')
            return false
        end
        targetPlayer:setStorageValue(channelId, 0)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_ORANGE, 'Player has been unmuted from ' .. channelName .. ' chat.')
        targetPlayer:sendTextMessage(MESSAGE_STATUS_SMALL, 'You have been unmuted from ' .. channelName .. ' chat.')
        return false
    end

    local timeString = param[3]
    if not timeString or #timeString <= 1 then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Invalid time input format.')
        return false
    end

    local timeUnit = string.sub(param[3], -1) -- h, m or s
    local digits = tonumber(param[3]:sub(1, #param[3] - 1))
    if not digits then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Invalid time input.')
        return false
    end

    if not timeConfig[timeUnit] then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'Unknown timeUnit ('..timeUnit..')')
        return false
    end

    targetPlayer:setStorageValue(channelId, os.time() + (timeConfig[timeUnit] * digits))
    targetPlayer:sendTextMessage(
        MESSAGE_STATUS_CONSOLE_ORANGE,
        'You have been muted on '.. channelName ..' chat for '
            ..(digits .. timeUnit .. (digits > 1 and '\'s' or ''))..
        '.\nReason: '.. (param[4] or 'None.')
    )
    return false
end
ta:separator(' ')
ta:register()

Note you need to add the following lines in each channel file:
data/chatchannels/scripts/<channelName>.lua
Lua:
local WORLD_CHAT_ID = 3 -- channel ID, change according to chatchannels.xml

-- place this inside onSpeak function
local storageMuted = player:getStorageValue(CHAT_CHANNEL_ID_BEGIN + WORLD_CHAT_ID)
if storageMuted > os.time() then
    player:sendCancelMessage('You have been muted in this channel. Try again later.')
    return false
end
You are the man! Thank you!

The command !mute is working perfectly, but for some reason the command !unmute is not performing the function, it sends on the default in yellow and does not give any error in the distro.
 
[Talkaction]
Teleport player to player. Basically that works like this

If that target you want to teleport is with Skull ur able to do so, but if he doesnt have a skull you cant teleport to him (so its like sensing the player) another think if you want to teleport to a target you have to be higher level then him if hes level 50 you have to be =>50 and not below so people wont abuse quests, and probably it shouldnt allow to teleport to a player if hes in protect zeno so they wont telport in houses or depos and abuse it. And should have 1 hour cooldown, and take 100 stamina. And thats it i think cant think about anything else that would be game breaking.
 
I would like a talkaction that works with the same idea as old illegalWords, where inside the talkaction script there is a field where I can add words or phrases, and if any player tries to type them, receive a notice and also an muted time.

And that the word or phrase is identified within a message for example:

BLOCK WORDS: evil, shut up, monkey,

Msg player to block: "You are a monkey", "Shut up man"
Something like that

And this is identified in all channels, including Default.

Example of old illegalwords talkaction
<talkaction words="illegalWords" event="script" value="block.lua"/>
 
Hello fellas!

I would love a Daily Task chest option, not the NPC version but so a chest that can be looted at x hours every day like 10.00.

Type of Reward:

1: Items/exp or both in one day.
2: Max hp/mana boost.
3: Regeneration boos.
4: Higher exp rate in %. (like 5% extra exp the whole day) - If this is overkill then dump nr 4.



Example below on daily's:

Monday = 1 gold
Tuesday = 1 gold
Wednesday
= 1 gold
Thursday
= 1 gold
Friday
= 1 gold
Saturday
= 1 gold
Sunday = 1 gold.



Keep up the good work!

Thanks you!

Obtainable random reward every 24h:

Lua:
---[ CUSTOM FUNCTIONS ]---
local function getTableLength(t)
    local count = 0
    for k, v in pairs(t) do count = count + 1 end
    return count
end

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

---[ CONFIGURATION ]---
local config = {
    -- HEALTH BOOST
    HP_BOOST_TIME    = 10, -- 10 seconds
    HP_BOOST_PERCENT = 10, -- +10%
    HP_BOOST_STORAGE = 13450,

    -- MANA BOOST
    MP_BOOST_TIME    = 10, -- 10 seconds
    MP_BOOST_PERCENT = 10, -- +10%
    MP_BOOST_STORAGE = 13451,

    -- EXP_RATE
    EXPERIENCE_AMOUNT = 10,
    EXTRA_EXP_RATE    = 1.05, -- +5%
    EXTRA_EXP_STORAGE = 181233,
    EXTRA_EXP_TIME    = 60,

    STORAGE_LAST_USED = 181234,
    REWARD_TIME = 24 * 3600
}

local REWARD_TYPE = {
    ITEM         = 1,
    EXPERIENCE   = 2,
    EXTRA_HP     = 3,
    EXTRA_MP     = 4,
    EXP_RATE     = 5
}

local rewards = {}
rewards[REWARD_TYPE.ITEM]       = {2160, 10}
rewards[REWARD_TYPE.EXPERIENCE] = config.EXPERIENCE_AMOUNT -- want to add constant amount of xp to every player or modified?
rewards[REWARD_TYPE.EXTRA_HP] = Condition(CONDITION_ATTRIBUTES)
rewards[REWARD_TYPE.EXTRA_HP]:setParameter(CONDITION_PARAM_SUBID, 1234)
rewards[REWARD_TYPE.EXTRA_HP]:setParameter(CONDITION_PARAM_STAT_MAXHITPOINTSPERCENT, 100 + config.HP_BOOST_PERCENT)
rewards[REWARD_TYPE.EXTRA_HP]:setParameter(CONDITION_PARAM_TICKS, config.HP_BOOST_TIME * 1000)

rewards[REWARD_TYPE.EXTRA_MP] = Condition(CONDITION_ATTRIBUTES)
rewards[REWARD_TYPE.EXTRA_HP]:setParameter(CONDITION_PARAM_SUBID, 1235)
rewards[REWARD_TYPE.EXTRA_MP]:setParameter(CONDITION_PARAM_STAT_MAXMANAPOINTSPERCENT, 100 + config.MP_BOOST_PERCENT)
rewards[REWARD_TYPE.EXTRA_MP]:setParameter(CONDITION_PARAM_TICKS, config.MP_BOOST_TIME * 1000)

rewards[REWARD_TYPE.EXP_RATE] = config.EXTRA_EXP_RATE

---[ ACTION SCRIPT ]---
local act = Action()
function act.onUse(player, item, fromPosition, itemEx, toPosition)
    if player:getStorageValue(config.STORAGE_LAST_USED) > os.time() then
        player:sendTextMessage(MESSAGE_STATUS_SMALL, 'You can only use this chest every 24h!')
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    local rewardType = math.random(1, getTableLength(REWARD_TYPE))
    if not rewards[rewardType] then
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'An error has occured. Contact admin.')
        print('[Warning - DailyRewardChest] Unknown reward. Type ('.. rewardType ..')')
        return true
    end

    player:setStorageValue(config.STORAGE_LAST_USED, os.time() + config.REWARD_TIME)
    player:getPosition():sendMagicEffect(CONST_ME_MAGIC_BLUE)

    -- +EXPERIENCE --
    if rewardType == REWARD_TYPE.EXPERIENCE then
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'You have received ' .. rewards[rewardType] .. ' exp.')
        player:addExperience(rewards[rewardType])
        return true
    end

    -- EXTRA EXP RATE --
    if rewardType == REWARD_TYPE.EXP_RATE then
        player:setStorageValue(config.EXTRA_EXP_STORAGE, os.time() + config.EXTRA_EXP_TIME)
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE,
            'You have received extra exp rate of +'
                .. (config.EXTRA_EXP_RATE * 100) - 100
                .. '% for '
                .. secondsToReadable(config.EXTRA_EXP_TIME)
            )
        return true
    end

    -- ITEM --
    if rewardType == REWARD_TYPE.ITEM then
        local item = rewards[rewardType]
        player:addItem(item[1], item[2])
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, 'You have found an item.')
        return true
    end

    -- EXTRA HP / MANA --
    if rewardType == REWARD_TYPE.EXTRA_HP then
        player:addCondition(rewards[rewardType])
        player:sendTextMessage(
            MESSAGE_EVENT_ADVANCE,
            'You have received +'.. config.HP_BOOST_PERCENT ..'% health boost for '
            .. secondsToReadable(config.HP_BOOST_TIME)
        )
        return true
    end

    if rewardType == REWARD_TYPE.EXTRA_MP then
        player:addCondition(rewards[rewardType])
        player:sendTextMessage(
            MESSAGE_EVENT_ADVANCE,
            'You have received +'.. config.MP_BOOST_PERCENT ..'% mana boost for '
            .. secondsToReadable(config.MP_BOOST_TIME)
        )
    end
    return true
end
act:id(2135) -- change this
act:register()

--------[ EVENTS ]--------
local ecb = EventCallback
ecb.onGainExperience = function(self, source, exp, rawExp)
    if not source or source:isPlayer() then
        return exp
    end

    if self:getStorageValue(config.EXTRA_EXP_STORAGE) < os.time() then
        return exp
    end

    exp = exp * config.EXTRA_EXP_RATE
    return exp
end
ecb:register(1)
 
I would like a talkaction that works with the same idea as old illegalWords, where inside the talkaction script there is a field where I can add words or phrases, and if any player tries to type them, receive a notice and also an muted time.

And that the word or phrase is identified within a message for example:

BLOCK WORDS: evil, shut up, monkey,

Msg player to block: "You are a monkey", "Shut up man"
Something like that

And this is identified in all channels, including Default.

Example of old illegalwords talkaction
<talkaction words="illegalWords" event="script" value="block.lua"/>

isn't that very easy to do with our onHear event? otland/forgottenserver (https://github.com/otland/forgottenserver/blob/master/data/events/scripts/creature.lua#L30)

(btw this is a proper example)
 
Hi can u revscript task system NPC , Item upgrade, exp ring? :D Thank you.
 
Hi friends, there is a possibility that the monster corpse appears in another position or that a teleport is generated under the monster and when the corpse leaves it will be teleported to another position, I am attentive to your answer if it can be done and help me with that code
Good morning friends, it seems that you did not understand me, what I want is for the monster's corpse to appear in another position not in the usual one when it dies, explanation in a few words I want the monster's corpse to appear in another position xyz if that cannot be achieved then make when the monster dies a teleport appears below the monster and this allows the corpse to be teleported but not player
 
Good morning friends, it seems that you did not understand me, what I want is for the monster's corpse to appear in another position not in the usual one when it dies, explanation in a few words I want the monster's corpse to appear in another position xyz if that cannot be achieved then make when the monster dies a teleport appears below the monster and this allows the corpse to be teleported but not player
I would love to know what u need this for xD
 
Appreciate all of you guys that do these scripting threads. I learn so much every day from these kinds of threads :)

I would like to request an event where a monster/something attackable will spawn in a random location based on a list of configurable locations and then broadcast it's location.
When attacked and loses a certain amount of hp% it should spawn randomly either some loot or monsters or both from a list around itself in a defined radius. So if there's many attackers and high dps happening then it would be spawning loot/monsters quite often.
When it dies it should spawn lots of just loot from the list and trigger the countdown for the next spawn. So max 1 on the map at any time.
 
I would love to know what u need this for xD
I need to do the quest of the pale worm, as you know you have to enter and hit another static monster and when you hit the static monster the damage is reflected in the pale the worm, but that damage is not added to the reward so I would not gain anything, for this reason I am making that when I kill the aesthetic monster I create the corpse of the pale worm and send it to a position x and z or be teleported to a position x
 
I need to do the quest of the pale worm, as you know you have to enter and hit another static monster and when you hit the static monster the damage is reflected in the pale the worm, but that damage is not added to the reward so I would not gain anything, for this reason I am making that when I kill the aesthetic monster I create the corpse of the pale worm and send it to a position x and z or be teleported to a position x
I still don't understand why you need it. lol

Anyway, here you go.

bandicam-2021-04-10-11-52-26-855.gif

Put this in the monster.
XML:
<script>
    <event name="PaleWormDeath" />
</script>
put this in data/scripts
Lua:
local creatureevent = CreatureEvent("PaleWormDeath")

function creatureevent.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
    corpse:moveTo(Position(250, 250, 7))
    return true
end

creatureevent:register()
 
Status
Not open for further replies.
Back
Top