• Sign up for TFS Icon Competition! The prize includes Otland Premium time and a medal, as well as obviously taking part in TFS history.
  • 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 0.X Auction system + upgrade system

samandriel

Active Member
Joined
Oct 19, 2016
Messages
223
Solutions
1
Reaction score
45
I got this upgrade system from @jacqen and @zabuzo TFS 0.X - Caracter [] bug on upgrade system (https://otland.net/threads/caracter-bug-on-upgrade-system.273485/#post-2634658)
And i want to make it works with my auction system (trade off / market) script

I'm already manage to store the upgrade_level in DB also name with upgrade
When add the offer on market


But now how to when players buy the item:
It add upgrade status to the item (name and status)?

talkactions/scripts/auctionsystem.lua
Code:
--[[
Offline player to player item trader (Auction System) by vDk
Script version: 1.2a [ -- FIXED CLONE ITEMS BUG -- ]
]]--
local config = {
    levelRequiredToAdd = 5,
    SendOffersOnlyInPZ = true,
    blocked_items = {2165, 2152, 2148, 2160, 2166, 2167, 2168, 2169, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215, 2343, 2433, 2640, 6132, 6300, 6301, 9932, 9933, 6093, 2123}
}

local function updatePlayerBalance(name, value)
    db.query('UPDATE players SET balance=' .. value .. ' WHERE name=' .. db.escapeString(name) .. ' LIMIT 1')
end

function itemExtractNameLevel(item_uid)
    local nameLv = {
        [1] = "[R]",
        [2] = "[G]",
        [3] = "[B]",
        [4] = "[W]",
        [5] = "[D]",
    }

    local name = getItemAttribute(item_uid, "name")
    local level = 0
    for lvl, flourish in ipairs(nameLv) do
        if name:find(flourish) then
            level = lvl
        end
    end
    return name, lvl, flourish
end

function getRarity(str)
    local value = 0
    local n = str:match("%[(.-)%]")
    if n == "R" then
       value = 1
    elseif n == "G" then
       value = 2
    elseif n == "B" then
       value = 3
    elseif n == "W" then
       value = 4
    elseif n == "D" then
       value = 5
    end
    return value
end

function onSay(cid, words, param, channel)
    if(param == '') then
        local msg = "Market:\n\n/market buy, ID\n/market remove, ID\n/market add, ItemPrice\n\nMore information look in us website!"
        doPlayerPopupFYI(cid, msg)
        return true
    end

    local maxOffersPerPlayer = math.floor(getPlayerLevel(cid) / 5)
    local pricePerOffer = 500
 
    local t = string.explode(param, ",")
    if(t[1] == "add") then
        local Item_Price = t[2]

        if(not Item_Price) then
            local msg = "/market add, ItemPrice"
            doPlayerPopupFYI(cid, msg)
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, msg)
            return true
        end
 
        if(not tonumber(Item_Price)) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You don't set valid price or items count.")
            return true
        end
 
        if(string.len(Item_Price) > 7) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "This price or item count is too high.")
            return true
        end

        if getPlayerSlotItem(cid, CONST_SLOT_AMMO).itemid == 0 then
            return doPlayerSendCancel(cid, "You have no item in your equipament arrow slot to sell!")
        end
        
        local item = getPlayerSlotItem(cid, CONST_SLOT_AMMO).itemid
        local itemUniqueID = getPlayerSlotItem(cid, CONST_SLOT_AMMO).uid
        local Item_Count = getPlayerSlotItem(cid, CONST_SLOT_AMMO).type

        if(tonumber(Item_Count) < 1) then
            Item_Count = 1
        end
        local Item_Name = getItemNameById(item)

        if(getPlayerLevel(cid) < config.levelRequiredToAdd) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You don't have required (" .. config.levelRequiredToAdd .. ") level.")
            return true
        end
 
        if(isInArray(config.blocked_items, item)) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "This item is blocked.")
            return true
        end
 
        local check = db.getResult("SELECT `id` FROM `auction_system` WHERE `player` = " .. getPlayerGUID(cid) .. ";")
        if(check:getID() == -1) then
        elseif(check:getRows(true) >= maxOffersPerPlayer) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Sorry you can't add more offers (max for your level: " .. maxOffersPerPlayer .. ")")
            return true
        end
 
        if(config.SendOffersOnlyInPZ) then
            if(not getTilePzInfo(getPlayerPosition(cid))) then
                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You must be in PZ area when you add offert to database.")
                return true
            end
        end
 
        if((tonumber(Item_Price) < 1)) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You have to type a number higher than 0.")
            return true
        end

        if(getPlayerBalance(cid) < 500) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You need to have 500GPs in your bank balance to make a offer.")
            return true
        end

        -- check if it is enchanted
        -- check if before name there is:
        -- [XXX] itemname
        local itemname = Item_Name
        local nameWithRarity = itemExtractNameLevel(itemUniqueID)
        local rarityOnly = getRarity(nameWithRarity)

        doPlayerSetBalance(cid, getPlayerBalance(cid) - 500)
        updatePlayerBalance(getCreatureByName(cid), getPlayerBalance(cid))
 
        local itemcount, costgp = math.floor(Item_Count), math.floor(Item_Price)
        doPlayerRemoveItem(cid, item, itemcount)
        db.executeQuery("INSERT INTO `auction_system` (`player`, `item_name`, `item_id`, `count`, `cost`, `date`, `upgrade_level`) VALUES (" .. getPlayerGUID(cid) .. ", \"" .. nameWithRarity .. "\", " .. getItemIdByName(Item_Name) .. ", " .. itemcount .. ", " .. costgp ..", " .. os.time() .. ", ".. rarityOnly ..")")
        doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You successfully add " .. itemcount .." " .. nameWithRarity .." for " .. costgp .. " gps to offerts database.")
    end
 
    if(t[1] == "buy") then
        if(not tonumber(t[2])) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Wrong ID.")
            return true
        end
 
        local buy = db.getResult("SELECT * FROM `auction_system` WHERE `id` = " .. (tonumber(t[2])) .. ";")
        if(buy:getID() ~= -1) then
            if (getPlayerBalance(cid) < buy:getDataInt("cost")) then
                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You don't have enoguh Bank Balance.")
                buy:free()
                return true
            end
 
            if(getPlayerName(cid) == getPlayerNameByGUID(buy:getDataInt("player"))) then
                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Sorry, you can't buy your own items.")
                buy:free()
                return true
            end
 
            if(getPlayerFreeCap(cid) < getItemWeightById(buy:getDataInt("item_id"), buy:getDataInt("count")))then
                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You try to buy a " .. buy:getDataString("item_name") .. ". It weight " .. getItemWeightById(buy:getDataInt("item_id"), buy:getDataInt("count")) .. " cap oz. and you have only " .. getPlayerFreeCap(cid) .. " oz. free capacity. Put some items to depot and try again.")
                buy:free()
                return true
            end
 
            if(isItemStackable((buy:getDataString("item_id")))) then
                doPlayerAddItem(cid, buy:getDataString("item_id"), buy:getDataInt("count"))
            else
                for i = 1, buy:getDataInt("count") do
                    doPlayerAddItem(cid, buy:getDataString("item_id"), 1)
                end
            end
            doPlayerSetBalance(cid, getPlayerBalance(cid) - buy:getDataInt("cost"))
            updatePlayerBalance(getCreatureName(cid), getPlayerBalance(cid))
            
            db.executeQuery("DELETE FROM `auction_system` WHERE `id` = " .. t[2] .. ";")
            doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You bought " .. buy:getDataInt("count") .. " ".. buy:getDataString("item_name") .. " for " .. buy:getDataInt("cost") .. " gps!")
           
            local tid = getPlayerByGUID(buy:getDataInt("player"))
            if(isPlayer(tid)) then
                doPlayerSetBalance(tid, getPlayerBalance(tid) + buy:getDataInt("cost"))
            else
                db.executeQuery("UPDATE `players` SET `balance` = `balance` + " .. buy:getDataInt("cost") .. " WHERE `id` = " .. buy:getDataInt("player") .. ";")
            end
 
            buy:free()
        else
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Wrong ID.")
        end
    end
 
    if(t[1] == "remove") then
        if((not tonumber(t[2]))) then
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Wrong ID.")
            return true
        end
 
        if(config.SendOffersOnlyInPZ) then
            if(not getTilePzInfo(getPlayerPosition(cid))) then
                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You must be in PZ area when you remove offerts from database.")
                return true
            end
        end
 
        local delete = db.getResult("SELECT * FROM `auction_system` WHERE `id` = " .. (tonumber(t[2])) .. ";")
        if(delete:getID() ~= -1) then
            if(getPlayerGUID(cid) == delete:getDataInt("player")) then
                db.executeQuery("DELETE FROM `auction_system` WHERE `id` = " .. t[2] .. ";")
                if(isItemStackable(delete:getDataString("item_id"))) then
                    doPlayerAddItem(cid, delete:getDataString("item_id"), delete:getDataInt("count"))
                else
                    for i = 1, delete:getDataInt("count") do
                        doPlayerAddItem(cid, delete:getDataString("item_id"), 1)
                    end
                end
 
                doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Your offert has been deleted from offerts database.")
            else
                doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "This is not your offert!")
            end
           
            delete:free()
        else
            doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Wrong ID.")
        end
    end
    return true
end
 

nadjsyrb

Member
Joined
Jun 9, 2020
Messages
24
Reaction score
16
the only thing left is:
when players buy something on auction system get the upgrade level on DB and when the other player got that item recreate the upgrade on the new item, right?
 
OP
samandriel

samandriel

Active Member
Joined
Oct 19, 2016
Messages
223
Solutions
1
Reaction score
45
The upgrade system is on the other topic, but bring it to here...

Code:
--PERFECT UPGRADE SYSTEM
UpgradeHandler = {
    nameLv = {
        [1] = "[R]",
        [2] = "[G]",
        [3] = "[B]",
        [4] = "[W]",
        [5] = "[D]",
    },
    completeNameLv = {
        [1] = "red",
        [2] = "green",
        [3] = "blue",
        [4] = "white",
        [5] = "dark",
    },
    levels = {
          [1] = {65, false, false},
          [2] = {40, false, false},
          [3] = {25, false, false},
          [4] = {10, false, false},
          [5] = {5, true, true},
    },
    broadcast = 5,
    attributes = {
          ["attack"] = 3,
          ["defense"] = 2,
          ["armor"] = 1
    },
    message = {
          console = "Trying to refine %s to level +%s with %s%% success rate.",
          success = "You have upgraded %s to level %s",
          fail = "You have failed in upgrade of %s to level +%s",
          downgrade = "The upgrade level of %s has downgraded to +%s",
          erase = "The upgrade level of %s has been erased.",
          maxlevel = "The targeted %s is already on max upgrade level.",
          notupgradeable = "This item is not upgradeable.",
          broadcast = "The player %s was successful in upgrading %s to level %s.\nCongratulations!!",
          invalidtool = "This is not a valid upgrade tool.",
          toolrange = "This upgrade tool can only be used in items with level between +%s and +%s"
    },
    tools = {
        [8306] = {range = {0, 10}, info = {chance = 0, removeable = true}},
        [8300] = {range = {0, 10}, info = {chance = 20, removeable = true}}
    },
    isEquipment = function(self)
        local weaponType = self:getItemWeaponType()
        return ((weaponType > 0 and weaponType < 8) or self.item.armor ~= 0)
    end,
    setItemName = function(self, name)
        return doItemSetAttribute(self.item.uid, "name", name)
    end,
    chance = function(self)
        local chances = {}
        chances.upgrade = (self.levels[self.item.level + 1][1] or 100)
        chances.downgrade = (self.item.level * 5)
        chances.erase = (self.item.level * 3)
        return chances
    end
}
function UpgradeHandler:new(item)
    local obj, ret = {}
    obj.item = {}
    obj.item.level = 0
    obj.item.uid = item.uid
    for key, value in pairs(getItemInfo(item.itemid)) do
        obj.item[key] = value
    end
    ret = setmetatable(obj, {
        __index = function(self, index)
            if _G[index] then
                return (setmetatable({callback = _G[index]},
                    {__call = function(self, ...)
                        return self.callback(item.uid, ...)
                    end}
                ))
            else
                return UpgradeHandler[index]
            end
    end})
    if ret:isEquipment() then
        ret:update()
        return ret
    end
    return false
end
function UpgradeHandler:update()
   -- this will return the level by the quality or 0 if it has no quality.
    self.item.level = 0
    for r, v in ipairs(self.nameLv) do
        if self:getItemName():find(v) then
            self.item.level = r
        end
    end
end
function UpgradeHandler:refine(uid, item)
    if not self.item then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_BLUE, self.message.notupgradeable)
        return "miss"
    end
    local tool = self.tools[item.itemid]
    if(tool == nil) then
        doPlayerSendTextMessage(uid, MESSAGE_EVENT_DEFAULT, self.message.invalidtool)
        return "miss"
    end
    if(self.item.level > #self.levels) then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.maxlevel:format(self.item.name))
        return "miss"
    end
    if(tool.range[1] and self.item.level < tool.range[1]) or (tool.range[2] and self.item.level >= tool.range[2]) then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_RED, self.message.toolrange:format(unpack(tool.range)))
        return "miss"
    end
    local chance = (self:chance().upgrade + tool.info.chance)
    doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_BLUE, self.message.console:format(self.item.name, (self.item.level + 1), math.min(100, chance)))
    if(tool.info.removeable == true) then
        doRemoveItem(item.uid, 1)
    end
    if chance * 100 > math.random(1, 10000) then
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_ORANGE, self.message.success:format(self.item.name, (self.completeNameLv[self.item.level + 1])))
        if (self.item.level + 1) >= self.broadcast then
            doBroadcastMessage(self.message.broadcast:format(getCreatureName(uid), self.item.name, self.completeNameLv[self.item.level + 1]))
        end
        -- it says if the item's level is greater then 0 (meaning is level equal to 1 or more) if it is add 1 more
        -- if the current level equals 0 add 1 to it
        --self:setItemName(self.item.level > 0 and (self:getItemName():gsub(self.nameLv[self.item.level], ""))..self.nameLv[self.item.level + 1] or self:getItemName().." "..self.nameLv[1])
        self:setItemName(self.item.level > 0 and self.nameLv[self.item.level + 1]..(self:getItemName():gsub("%["..self.nameLv[self.item.level].."%]", "")) or self.nameLv[1].." "..self:getItemName())
        for key, value in pairs(self.attributes) do
            if getItemAttribute(self.item.uid, key) ~= nil or self.item[key] ~= 0 then
                doItemSetAttribute(self.item.uid, key, (self.item.level > 0 and getItemAttribute(self.item.uid, key) or self.item[key]) + value)
            end
        end
        return "success"
    else
        if item.itemid == 8300 then
            if self.item.level > 0 then
                -- this will remove any number with a + sign in front of it from the string
                --self:setItemName(self:getItemName():gsub((" "..self.nameLv[self.item.level]), ""))
                self:setItemName(self:getItemName():gsub(("%["..self.nameLv[self.item.level].."%] "), ""))
                for key, value in pairs(self.attributes) do
                    if getItemAttribute(self.item.uid, key) ~= nil or self.item[key] ~= 0 then
                        doItemSetAttribute(self.item.uid, key, getItemAttribute(self.item.uid, key) - self.item.level * value)
                    end
                end
            end
        else
            doRemoveItem(self.item.uid, 1)
        end
        doPlayerSendTextMessage(uid, MESSAGE_STATUS_CONSOLE_BLUE, item.itemid == 8300 and "Your item level has been reseted." or "You have broken your item while trying to upgrade it.")
    end
end

Is anybody know how to cut the upgrade part and put on that talkaction?
 
Top