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

Adorius Black

Advanced OT User
Joined
Mar 31, 2020
Messages
301
Solutions
3
Reaction score
180
Hi. I have 2 problems with shop system.
The OTX Server Global - Version: (3.10)

- 2 weeks ago I didnt have these problems and from tihs time I didnt touch these scripts. But in these two weeks I did a lot changes so i dont know where is problem hiding.


1.) When I order more same items on webpage (example: 3 Solar Axes) then i go to game and say !shop it give me 1 solar axe "18:09 Congratulations! You have received 1 x solar axe!" and if i say again !shop it say to me "17:23 You have no orders.".

Here you can see scripts i use:
XML:
<talkaction words="!shop" script="shop.lua" />
shop.lua
Lua:
function onSay(cid, words, param)
local storage = 54073 -- Make sure to select non-used storage. This is used to prevent SQL load attacks.
local cooldown = 0 -- in seconds.
local player = Player(cid)
if player:getStorageValue(storage) <= os.time() then
player:setStorageValue(storage, os.time() + cooldown)
-- Create the query
local orderQuery = db.storeQuery("SELECT `id`, `type`, `itemid`, `count` FROM `shop_orders` WHERE `account_id` = " .. player:getAccountId() .. " LIMIT 1;")
-- Detect if we got any results
if orderQuery ~= false then
-- Fetch order values
local q_id = result.getDataInt(orderQuery, "id")
local q_type = result.getDataInt(orderQuery, "type")
local q_itemid = result.getDataInt(orderQuery, "itemid")
local q_count = result.getDataInt(orderQuery, "count")
result.free(orderQuery)
-- ORDER TYPE 1 (Regular item shop products)
if q_type == 1 then
-- Get wheight
if player:getFreeCapacity() >= ItemType(q_itemid):getWeight(q_count) then
db.query("DELETE FROM `shop_orders` WHERE `id` = " .. q_id .. ";")
player:addItem(q_itemid, q_count)
player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. q_count .. " x " .. ItemType(q_itemid):getName() .. "!")
else
player:sendTextMessage(MESSAGE_STATUS_WARNING, "Need more CAP!")
end
end
-- Add custom order types here
-- Type 2 is reserved for premium days and is handled on website, not needed here.
-- Type 3 is reserved for character gender(sex) change and is handled on website as well.
-- So use type 4+ for custom stuff, like etc packages.
-- if q_type == 4 then
-- end
else
player:sendTextMessage(MESSAGE_STATUS_WARNING, "You have no orders.")
end
else
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Can only be executed once every " .. cooldown .. " seconds. Remaining cooldown: " .. player:getStorageValue(storage) - os.time())
end
return false
end

same problem i have when i use another method : ModalWindow Shop
With this method I have another problem.

NOTE: Second problem I have only when i use my own map. When I use realmap, problem is solved.


2.) If I choose item in modal window it say "18:08 You got a parcel with: Solar axe, it is in (City) depot." but in depot is not parcel. I already add in Map Editor -> Depot Properties -> City.
2121.png

So I write /shop one time -> choose item -> click OK I didnt recieve my item in Depot and when I write second time /shop all items are gone.

adqqq.png

ada.png

XML:
<talkaction words="/shop" script="shopp.lua" />
shopp.lua
Lua:
function onSay(player, words, param)
local function ucfirst(str)
  return (str:gsub("^%l", string.upper))
end
local my_db = db.storeQuery("SELECT `id`, `type`, `itemid`, `count` FROM `shop_orders` WHERE `account_id` = " .. player:getAccountId() .. "")
player:registerEvent('shop')

local title = "- SHOP LIST -"
local townas = player:getTown()
local name = townas:getName()

local message = "----------------------------------------\nYou have some items from website shop, when you press\ntake it you will get a parcel in your town ("..name..").\n\n----------------------------------------\n"
local my_window = ModalWindow(4, title, message)

if my_db == false then
return player:sendTextMessage(MESSAGE_INFO_DESCR,"You don't have any orders.")
end

if my_db ~= false then
local suma = 0
repeat

local id = result.getDataInt(my_db, "itemid")
local choiceid = result.getDataInt(my_db, "id")
suma = suma + 1

if (ItemType(id):getAttack() > 0) and (ItemType(id):getDefense() > 0) then

my_window:addChoice(choiceid,''..suma..'. '..ucfirst(ItemType(id):getName())..'  (Atk: '..ItemType(id):getAttack()..'  |  Def: '..ItemType(id):getDefense()..')')
elseif ItemType(id):getArmor() then
my_window:addChoice(choiceid,''..suma..'. '..ucfirst(ItemType(id):getName())..'  (Arm: '..ItemType(id):getArmor()..')')
else
my_window:addChoice(choiceid,''..suma..'. '..ucfirst(ItemType(id):getName()))
end

until not result.next(my_db)
result.free(my_db)

my_window:addButton(1,'Take it')
my_window:addButton(2,'Exit')
my_window:sendToPlayer(player)
end
end


Please... Is here anyone who know how to solve it?

In my opinion it can be issue somewhere in my database? I am not realy good at this so if you want more codes or pictures just write and I will post it. :)
 
Last edited by a moderator:
Solution
Ok. I think I did things by the book here. Added missing sanity checks too.

Lua:
-- Be sure to fucking have this location set to a mailbox -- Lessaire
local MAILBOX = Position(32350, 32222, 7)

function onModalWindow(player, modalWindowId, buttonId, choiceId)
    local function ucfirst(str)
        return (str:gsub("^%l", string.upper))
    end
    if modalWindowId == 4 then
        player:unregisterEvent('shop')

        local spot = Tile(MAILBOX);
        if spot == nil then
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'ERROR: Configured mailbox location does not exist.')
            return false
        end
        if not spot:hasFlag(TILESTATE_MAILBOX) then
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'ERROR...
first script


Lua:
function onSay(cid, words, param)
    local storage = 54073 -- Make sure to select non-used storage. This is used to prevent SQL load attacks.
    local cooldown = 0 -- in seconds.
    local player = Player(cid)
    if player:getStorageValue(storage) <= os.time() then
        player:setStorageValue(storage, os.time() + cooldown)
        -- Create the query
        local orderQuery = db.storeQuery("SELECT `id`, `type`, `itemid`, `count` FROM `shop_orders` WHERE `account_id` = " .. player:getAccountId() .. " LIMIT 1;")
        -- Detect if we got any results
        if orderQuery ~= false then
            -- Fetch order values
            local q_id = result.getDataInt(orderQuery, "id")
            local q_type = result.getDataInt(orderQuery, "type")
            local q_itemid = result.getDataInt(orderQuery, "itemid")
            local q_count = result.getDataInt(orderQuery, "count")
            result.free(orderQuery)
            -- ORDER TYPE 1 (Regular item shop products)
            if q_type == 1 then
                -- Get wheight
                if player:getFreeCapacity() >= ItemType(q_itemid):getWeight(q_count) then
                    db.query("DELETE FROM `shop_orders` WHERE `id` = " .. q_id .. ";")

                    if(ItemType(q_itemid):isRune() or ItemType(q_itemid):isStackable()) then
                        player:addItem(q_itemid, q_count)
                    else
                        for qty=1,q_count do
                            player:addItem(q_itemid, q_count)
                        end
                    end

                    player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations! You have received " .. q_count .. " x " .. ItemType(q_itemid):getName() .. "!")
                else
                    player:sendTextMessage(MESSAGE_STATUS_WARNING, "Need more CAP!")
                end
            end
            -- Add custom order types here
            -- Type 2 is reserved for premium days and is handled on website, not needed here.
            -- Type 3 is reserved for character gender(sex) change and is handled on website as well.
            -- So use type 4+ for custom stuff, like etc packages.
            -- if q_type == 4 then
            -- end
        else
            player:sendTextMessage(MESSAGE_STATUS_WARNING, "You have no orders.")
        end
    else
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Can only be executed once every " .. cooldown .. " seconds. Remaining cooldown: " .. player:getStorageValue(storage) - os.time())
    end
    return false
end


Second script code does not have part where player picking order is handled. It only makes the modal window. So problem would be some other script.
 
Still dont work.
Here is script what i use in creaturescript
Lua:
function onModalWindow(player, modalWindowId, buttonId, choiceId)
local function ucfirst(str)
return (str:gsub("^%l", string.upper))
end
if modalWindowId == 4 then
player:unregisterEvent('shop')

if buttonId == 1 then
local my_db = db.storeQuery("SELECT `id`, `account_id`, `type`, `itemid`, `count` FROM `shop_orders` WHERE `id` = " .. choiceId .. "")
local id = result.getDataInt(my_db, "itemid")
local acc_id = result.getDataInt(my_db, "account_id")
local count = result.getDataInt(my_db, "count")

if my_db ~= false and player:getAccountId() == acc_id then
local townas = player:getTown()
local name = townas:getName()
player:sendTextMessage(MESSAGE_INFO_DESCR,'You got a parcel with: '..ucfirst(ItemType(id):getName())..', it is in ('..name..') depot.')
local container = Game.createItem(2595, 1)
local label = container:addItem(2599, 1)
container:addItem(id, count)
label:setAttribute(ITEM_ATTRIBUTE_TEXT, ''..player:getName()..'\n'..name..'')
container:moveTo(Position(32350,32222,7))
db.query("DELETE FROM `shop_orders` WHERE `id` = " .. choiceId .. ";")
end
--BUTTON ID END
end
--
if buttonId == 2 then
return false
end
--MODAL ID END
end
--
end
 
Ok. I think I did things by the book here. Added missing sanity checks too.

Lua:
-- Be sure to fucking have this location set to a mailbox -- Lessaire
local MAILBOX = Position(32350, 32222, 7)

function onModalWindow(player, modalWindowId, buttonId, choiceId)
    local function ucfirst(str)
        return (str:gsub("^%l", string.upper))
    end
    if modalWindowId == 4 then
        player:unregisterEvent('shop')

        local spot = Tile(MAILBOX);
        if spot == nil then
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'ERROR: Configured mailbox location does not exist.')
            return false
        end
        if not spot:hasFlag(TILESTATE_MAILBOX) then
            player:sendTextMessage(MESSAGE_INFO_DESCR, 'ERROR: Configured mailbox location does not harbor a working mailbox.')
            return false
        end
        if buttonId == 1 then
            local my_db = db.storeQuery("SELECT `id`, `account_id`, `type`, `itemid`, `count` FROM `shop_orders` WHERE `id` = " .. choiceId .. "")
            local itemid = result.getDataInt(my_db, "itemid")
            local acc_id = result.getDataInt(my_db, "account_id")
            local count = result.getDataInt(my_db, "count")
            
            if my_db ~= false and player:getAccountId() == acc_id then
                local townas = player:getTown()
                local city = townas:getName()
                player:sendTextMessage(MESSAGE_INFO_DESCR, 'You got a parcel with: '..ucfirst(ItemType(itemid):getName()) .. ', it is in ('..city..') depot.')

                local parcel = Game.createItem(ITEM_PARCEL, 1)
                local label = Game.createItem(ITEM_LABEL, 1)
                label:setAttribute(ITEM_ATTRIBUTE_TEXT, string.format('%s\n%s', player:getName(), city))
                parcel:addItemEx(label)

                for qty=1,count do
                    local purchase = Game.createItem(itemid, 1)
                    parcel:addItemEx(purchase)
                end

                spot:addItemEx(parcel) --parcel:moveTo(MAILBOX)
                db.query("DELETE FROM `shop_orders` WHERE `id` = " .. choiceId .. ";")
            end
            --BUTTON ID END
        end
        --
        if buttonId == 2 then
            return false
        end
        --MODAL ID END
    end
    --
end
 
Solution
Back
Top