• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

[TFS 1.3] Script Optimization - Mount taming

Snavy

Bakasta
Senator
Joined
Apr 1, 2012
Messages
1,249
Solutions
71
Reaction score
621
Location
Hell
Hello, OT Plebs.

I have written a script for taming mounts and I would like to receive some feedback and maybe optimize it [a bit] with your help.

Here's the code:

XML:
<action itemid="13307" script="mounts/tame.lua"/>
<action itemid="13538" script="mounts/tame.lua"/>

Lua:
local config = {
    ["Wailing Widow"] = { mount_id = 1, storage = 20001, tamingItemId = 13307 },
    ["Panda"] = { mount_id = 19, storage = 20002, tamingItemId = 13538 }

    -- ... etc
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)

    -- Make sure target is a monster
    local targetCreature = Creature(target)
    if(targetCreature and not targetCreature:isPlayer()) then

        -- confirm existence in config
        local mount = config[targetCreature:getName()]
        if(mount) then

            -- confirm that the player doesn't already possess the mount.
            if(player:getStorageValue(mount.storage) <= 0) then

                player:setStorageValue(mount.storage, 1)
                player:addMount(mount.mount_id)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "You have received the ".. targetCreature:getName() .." mount.")
                player:getPosition():sendMagicEffect(31)

                -- Remove tamed monster
                target:remove()

                -- remove taming item
                player:removeItem(mount.tamingItemId, 1)

            else
                player:sendCancelMessage("You already have this mount.")
                player:getPosition():sendMagicEffect(CONST_ME_POFF)
            end
        end

    else
        player:sendCancelMessage("Invalid target.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
    end

    return true
end
 
Last edited:
The script should work as intended. It could be written other way but when it comes to performance I don't think it would make any difference.

Edit: I would use hasMount check instead of storage.

Something like this:
Lua:
local config = {
    ["Wailing Widow"] = {mount_id = 1, tamingItemId = 13307},
    ["Panda"] = {mount_id = 19, tamingItemId = 13538}
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    -- Make sure target is a monster
    local targetCreature = Creature(target)
    if(targetCreature and not targetCreature:isPlayer()) then
        -- confirm existence in config
        local mount = config[targetCreature:getName()]
        if(mount) then
            -- confirm that the player doesn't already possess the mount.
            if not player:hasMount(mount.mount_id) then
                player:addMount(mount.mount_id)
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "You have received the ".. targetCreature:getName() .." mount.")
                player:getPosition():sendMagicEffect(31)
                -- Remove tamed monster
                target:remove()
                -- remove taming item
                player:removeItem(mount.tamingItemId, 1)
            else
                player:sendCancelMessage("You already have this mount.")
                player:getPosition():sendMagicEffect(CONST_ME_POFF)
            end
        end
    else
        player:sendCancelMessage("Invalid target.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
    end
    return true
end
 
I would done something like this, just make stuff more easy to read. Also use itemId as key instead. Anyway, the code is fast enough even if it takes seconds to run it 10 million times, if you're having problems with the performance of that you should reconsider your use of keys and values.

Lua:
local config = {
    [13307] = {name = "wailing widow", id = 1},
    [13538] = {name = "Panda", id = 19}
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if type(target) == "userdata" and not target:isMonster() then
        player:sendCancelMessage("Invalid target.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    local mount = config[item.itemid]
    if target:getName():lower() ~= mount.name:lower() then
        return true
    end

    if player:hasMount(mount.id) then
        player:sendCancelMessage("You already have this mount.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    player:addMount(mount.id)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "You have received the ".. target:getName() .." mount.")
    target:remove()
    toPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)
    item:remove(1)
    return true
end
 
Last edited:
I would done something like this, just make stuff more easy to read. Also use itemId as key instead. Anyway, the code is fast enough even if it takes seconds to run it 10 million times, if you're having problems with the performance of that you should reconsider your use of keys and values.

Lua:
local config = {
    [13307] = {name = "wailing widow", id = 1},
    [13538] = {name = "Panda", id = 19}
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if type(target) == "userdata" and not target:isMonster() then
        player:sendCancelMessage("Invalid target.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    local mount = config[item.itemid]
    if target:getName():lower() ~= mount.name:lower() then
        return true
    end

    if player:hasMount(mount.id) then
        player:sendCancelMessage("You already have this mount.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    player:addMount(mount.id)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "You have received the ".. target:getName() .." mount.")
    target:remove()
    toPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)
    item:remove(1)
    return true
end

Just tested this and it works nice. Also the code looks much cleaner than the original :D
 
I would done something like this, just make stuff more easy to read. Also use itemId as key instead. Anyway, the code is fast enough even if it takes seconds to run it 10 million times, if you're having problems with the performance of that you should reconsider your use of keys and values.

Lua:
local config = {
    [13307] = {name = "wailing widow", id = 1},
    [13538] = {name = "Panda", id = 19}
}

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if type(target) == "userdata" and not target:isMonster() then
        player:sendCancelMessage("Invalid target.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    local mount = config[item.itemid]
    if target:getName():lower() ~= mount.name:lower() then
        return true
    end

    if player:hasMount(mount.id) then
        player:sendCancelMessage("You already have this mount.")
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end

    player:addMount(mount.id)
    player:sendTextMessage(MESSAGE_STATUS_CONSOLE_RED, "You have received the ".. target:getName() .." mount.")
    target:remove()
    toPosition:sendMagicEffect(CONST_ME_MAGIC_BLUE)
    item:remove(1)
    return true
end

your code working good but not working on Uniwheel and Tin Lizard (send to me Invalid target.).
maybe beacuse it's not a monster.

can you fix it for me?
 
Back
Top