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

How could I configure this?

Jpstafe

Well-Known Member
Joined
Aug 8, 2011
Messages
578
Reaction score
78
Hello otland community, I am configuring a store module in otclient for TFS 0.x and OTX2, which opens the shop through a button and buys the item, when you press "Purchase" you give OK and it buys the item through a talkactions command.
Up to this point everything works perfectly.
1723668941575.webp
There are two things I would like to change...
1-The talkactions command does not appear in the console. Is there a way to run it invisibly? To simulate as if you were buying with the otclient shop module.
1723669051769.webp

2- I would like that below the photo that says Store,
you can put a Balance: 0 and put a GET POINT button, when you press it you are redirected to the page in the shop section
This would be the idea I have in mind
1723669355257.webp

What would I have to pass to them to see where I can add these functions... of the points balance? Is there a way to execute the shop talkactions invisibly?

store_module.otui

XML:
ScrollCountWindow < MainWindow
  size: 210 100
  @onEscape: modules.store_module.destroyScrollCountWindow()

  Label
    text: Count:
    width: 38
    anchors.top: parent.top
    anchors.left: parent.left
    margin-top: 2

  SpinBox
    id: spinBox
    value: 1
    step: 1
    width: 50
    focusable: true
    anchors.top: parent.top
    anchors.left: prev.right

  Label
    id: prize
    color: white
    text: 2 Diamonds
    text-auto-resize: true
    icon-align: left
    icon: diamonds
    text-offset: 21 0
    font: verdana-11px-rounded
    anchors.verticalCenter: spinBox.verticalCenter
    anchors.left: spinBox.right
    margin-left: 3

  Button
    !text: tr('Cancel')
    width: 64
    anchors.bottom: parent.bottom
    anchors.right: parent.right
    @onClick: modules.store_module.destroyScrollCountWindow()

  Button
    id: okButton
    text: Ok
    width: 64
    anchors.bottom: parent.bottom
    anchors.right: prev.left
    margin-right: 5

StoreButton < UIButton
  font: verdana-11px-antialised
  text-offset: 42 0
  text-align: left
  background-color: alpha
  height: 36
  icon-rect: 5 0 32 32
  $focus:
    background-color: #00000077
    color: #ffffff

  $hover focus:
    background-color: #00000077
    color: #ffffff

  $hover !focus:
    background-color: #00000044
    color: #ffffff

  $hover !checked:
    background-color: #00000044
    color: #ffffff

  $disabled:
    background-color: alpha
    color: #ffffff22

  $checked:
    background-color: #00000077
    color: #ffffff

  $on !checked:
    background-color: #00000077
    color: #ffffff

ProductButton < UIButton
  font: verdana-11px-antialised
  text-align: left
  background-color: #00000022
  size: 96 114
  border: 1 #f0f4f6
  margin-right: 2
  margin-bottom: 2
  $hover:
    border: 1 #000000
    background-color: #000000

  Label
    id: productLabelTitle
    text-align: center
    text-offset: 0 0
    anchors.top: parent.top
    anchors.right: parent.right
    anchors.left: parent.left
    margin: 3
    border: 1 #bababa
    height: 16
    font: terminus-10px
    background-color: #00000077

  Label
    id: productLabelImage
    anchors.top: productLabelTitle.bottom
    anchors.right: parent.right
    anchors.left: parent.left
    margin: 3
    border: 1 #bababa
    size: 88 70
    visible: false
    virtual: true

  Item
    id: productLabelItem
    anchors.top: productLabelTitle.bottom
    anchors.right: parent.right
    anchors.left: parent.left
    margin: 3
    border: 1 #bababa
    size: 88 70
    visible: false
    virtual: true

  Label
    id: productLabelTokenPrice
    anchors.bottom: parent.bottom
    anchors.right: parent.right
    anchors.left: parent.left
    text-align: center
    text-offset: 0 0
    margin: 3
    border: 1 #bababa
    height: 16
    font: terminus-10px
    background-color: #00000077

  Label
    id: coinIcon
    image-source: shop/forge
    anchors.top: productLabelTokenPrice.top
    anchors.left: parent.left
    margin-left: 18
    margin-top: 2
    size: 58 20
    opacity: 1.0

ButtonShop < UIButton
  font: verdana-11px-antialised
  color: #dfdfdfff
  size: 92 22
  text-offset: 0 0
  image-source: shop/buttonShop
  image-color: #dfdfdf
  image-clip: 0 0 24 22
  image-border: 7
  padding: 5 10 5 10
  opacity: 1.0

  $hover !disabled:
    image-clip: 0 22 24 22

  $pressed:
    image-clip: 0 44 24 22

  $disabled:
    color: #dfdfdf88
    opacity: 0.8

MainWindow
  id: storeWindow
  size: 700 486
  padding: 3
  border: 1 #000305
  image-color: #626262
  background-color: #00000066

  @onEnter: modules.store_module.onCloseStore()
  @onEscape: modules.store_module.onCloseStore()

  Label
    id: title
    !text: tr('Shop items')
    text-align: center
    font: verdana-11px-antialised
    anchors.top: parent.top
    anchors.left: parent.left
    anchors.right: parent.right
    background-color: #1e1e1e
    border: 1 #727272
    height: 20
 
  Panel
    id: balanceInfo
    anchors.top: title.bottom
    anchors.left: parent.left
    margin-top: 3
    size: 185 54
    border: 1
    background-color: #00000077
    padding: 5
    align: center

    Label
      id: textYbalance
      !text: tr('')
      font: terminus-10px
      text-align: center
      anchors.top: parent.top
      anchors.left: parent.left
      anchors.right: parent.right

    Label
      id: coinBalance
      font: terminus-10px
      anchors.top: textYbalance.bottom
      anchors.left: parent.left
      height: 12
      margin-top: 8

    Label
      id: coinIcon
      image-source: shop/tibiaCoin
      anchors.top: coinBalance.top
      anchors.left: coinBalance.right
      margin-top: -20
      size: 180 78

  ButtonShop
    id: getCoins


    color: #ffffff
    width: 0
    anchors.top: balanceInfo.bottom
    anchors.left: parent.right
    icon-rect: 54 5 12 12

    margin-top: 3


  ButtonShop
    id: transferPoints
    anchors.top: getCoins.top
    anchors.right: balanceInfo.left

    width: 0

      margin-left: 100

  Panel
    id: indexDescription
    size: 507 78
    border: 1 #010406
    background-color: #00000077
    anchors.top: balanceInfo.top
    anchors.left: balanceInfo.right
    margin-left: 3

    Label
      id: imageDesc
      anchors.top: parent.top
      anchors.left: parent.left
      size: 64 64
      margin-top: 7
      margin-left: 10

    Label
      id: titleDesc
      font: verdana-11px-antialised
      anchors.top: imageDesc.top
      anchors.left: imageDesc.right
      width: 300
      margin-left: 10
      margin-top: 12
      text-wrap: true
      text-auto-resize:true

    Label
      id: description
      font: terminus-10px
      text-wrap: true
      text-auto-resize:true
      anchors.top: titleDesc.bottom
      anchors.left: imageDesc.right
      anchors.right: parent.right
      anchors.bottom: parent.bottom
      margin-left: 10
      margin-top: 5

  Label
    id: categories
    !text: tr('Categories:')
    anchors.top: getCoins.bottom
    anchors.left: parent.left
    font: terminus-10px
    size: 185 12
    margin-top: 3
    margin-left: 5

  TextList
    id: indexList
    anchors.top: categories.bottom
    anchors.left: parent.left
    size: 185 334
    background-color: #00000077
    border: 1 #050101
    margin-top: 3

  Label
    id: products
    !text: tr('Products:')
    anchors.top: categories.top
    anchors.left: indexList.right
    font: terminus-10px
    size: 185 12
    margin-left: 5

  ScrollablePanel
    id: productList
    anchors.top: products.bottom
    anchors.left: indexList.right
    size: 507 334
    border: 1 #050101
    padding: 3
    padding-right: 10
    background-color: #00000077
    margin-top: 3
    margin-left: 3
    vertical-scrollbar: productListScrollbar
    layout:
      type: grid
      flow: true
      cell-size: 96 114

  VerticalScrollBar
    id: productListScrollbar
    height: 332
    margin-top: 1
    margin-right: 1
    anchors.top: productList.top
    anchors.right: productList.right
    step: 14
    pixels-scroll: true

  Label
    background-color: #00000077
    border: 1 #727272
    height: 28
    anchors.bottom: parent.bottom
    anchors.left: parent.left
    anchors.right: parent.right

  ButtonShop
    id: closeButton
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.bottom: parent.bottom
    margin-bottom: 3
    !text: tr('Close')
    width: 50
    color: #ffffff
    @onClick: modules.store_module.toggle()
store_module.lua:
LUA:
dofile('ui/uistoreacceptbox')

local storeWindow = nil
local indexDescription = nil
local indexList = nil
local imageDesc = nil
local titleDesc = nil
local description = nil
local acceptWindow = nil
local transferPointsWindow = nil

storeCountWindow = nil


local function formatNumbers(number)
    local ret = number
    while true do
        ret, k = string.gsub(ret, "^(-?%d+)(%d%d%d)", '%1,%2')
        if k == 0 then
            break
        end
    end
    return ret
end

function onBuyWithScrollCount(itemInfos, customId, itemName, category_id, id, price)

    local count = 0
   
    local itemName = itemInfos.name
    local category_id = itemInfos.category_id
    local id = itemInfos.id
    local price = itemInfos.price
    local countMin = tonumber(itemInfos.countMin) or 1
    local countMax = tonumber(itemInfos.countMax) or 1
   
    storeCountWindow = g_ui.createWidget('StoreCountWindow', rootWidget)
    storeCountWindow:setText(itemName)
   
    -- storeProducts[j].name, storeProducts[j].category_id, storeProducts[j].id, storeProducts[j].price
    --[[
  local itembox = storeCountWindow:getChildById('item')
  itembox:setItemId(3028)
  --itembox:setItemId(item:getId())
  itembox:setItemCount(count)
  --]]
 
 
 local scrollbar = storeCountWindow:getChildById('countScrollBar')
  scrollbar:setMaximum(1)
scrollbar:setMinimum(1)
  scrollbar:setValue(1)

   
    local buyCost = storeCountWindow:getChildById('buyCost')
    buyCost:setText(price..' Diamond'..(price>1 and 's' or ''))
   
    local buyCount = storeCountWindow:getChildById('buyCount')
    buyCost:setText(Creating)
   
    local spinbox = storeCountWindow:getChildById('spinBox')
  --spinbox:setMaximum(count)
  spinbox:setMaximum(1)
  spinbox:setMinimum(1)
  spinbox:setValue(1)
  spinbox:hideButtons()
  spinbox:focus()
  spinbox.firstEdit = true

  local spinBoxValueChange = function(self, value)
    spinbox.firstEdit = false

  end
  spinbox.onValueChange = spinBoxValueChange

  local check = function()
    if spinbox.firstEdit then
      spinbox:setValue(spinbox:getMaximum())
      spinbox.firstEdit = false
    end
  end
 
  scrollbar.onValueChange = function(self, value)
    --itembox:setItemCount(value)

    buyCost:setText(value*price..' Diamond'..(price>1 and 's' or ''))
    spinbox.onValueChange = nil
    spinbox:setValue(value)
    spinbox.onValueChange = spinBoxValueChange
  end
   
   
   
   
    local okButton = storeCountWindow:getChildById('buttonOk')
  local moveFunc = function()
   g_game.talk('!shop'..itemName..'')
    okButton:getParent():destroy()
    storeCountWindow = nil
  end
  local cancelButton = storeCountWindow:getChildById('buttonCancel')
  local cancelFunc = function()
    cancelButton:getParent():destroy()
    storeCountWindow = nil
  end

  storeCountWindow.onEnter = moveFunc
  storeCountWindow.onEscape = cancelFunc

  okButton.onClick = moveFunc
  cancelButton.onClick = cancelFunc
   

end

function destroyScrollCountWindow()
    if scrollCountWindow then
        scrollCountWindow:destroy()
        scrollCountWindow = nil
    end
end
--

local function short(value)
  local text = value
  if string.len(text) >= 13 then
    shorten = string.sub(text, 1, 10)
    return shorten .. "..."
  else
    return text
  end
end

function init()
  g_ui.importStyle('ui/acceptwindow')
    g_ui.importStyle('ui/storecountwindow')
 
  storeWindow = g_ui.displayUI('store_module')
  storeWindow:hide()

  g_keyboard.bindKeyPress('Ctrl+F', toggle)
  ProtocolGame.registerExtendedOpcode(COINS_OPCODE, coinsBalance)
  print(COINS_OPCODE)
  transferPointsWindow = g_ui.displayUI('transferpoints')
 
  indexList = storeWindow:getChildById('indexList')
  indexDescription = storeWindow:getChildById('indexDescription')
  imageDesc = storeWindow:getChildById('indexDescription'):getChildById('imageDesc')
  titleDesc = storeWindow:getChildById('indexDescription'):getChildById('titleDesc')
  description = storeWindow:getChildById('indexDescription'):getChildById('description')
 
  productList = storeWindow:getChildById('productList')
 
  storeModule = modules.client_topmenu.addLeftGameButton('storeModule', tr('Shop') .. ' ', '/modules/game_forges/shop/forges', toggle)
 
  storeModule:setWidth(27)
   
 
  for i = 1, #storeIndex do
    local label = g_ui.createWidget('StoreButton', indexList)
   
    label:setId(i)
    label:setIcon(storeIndex[i].imageList)
    label:setText(tr(storeIndex[i].name))
    label.index = i
   
    local labelId = storeWindow:getChildById('indexList'):getChildById(i)
    labelId.onClick = function(self)
      local descriptionImage = storeWindow:getChildById('indexDescription'):getChildById('imageDesc')
      descriptionImage:setImageSource(storeIndex[i].image)
   
      local descriptionTitle = storeWindow:getChildById('indexDescription'):getChildById('titleDesc')
      descriptionTitle:setText(storeIndex[i].name)
   
      local description = storeWindow:getChildById('indexDescription'):getChildById('description')
      description:setText(storeIndex[i].description)
     
      local productsPanel = storeWindow:getChildById('productList')
      local children = productsPanel:getChildren()
      for k = 1, #children do
        children[k]:destroy()
      end
     
      for j=1, #storeProducts do
        if storeIndex[i].id == storeProducts[j].category_id then
          local productLabel = g_ui.createWidget('ProductButton', productList)

           
          productLabel:setId(j)
          productLabel:setTooltip(storeProducts[j].tooltip)
         
          local productLabelTitle = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelTitle')
          productLabelTitle:setText(short(storeProducts[j].name))
     
                local productLabelItem = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelItem')
          if storeProducts[j].clientId then
              productLabelItem:setVisible(true)
              productLabelItem:setItemId(storeProducts[j].clientId)
          else
              productLabelItem:setVisible(false)
          end

          local productLabelImage = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelImage')
          if storeProducts[j].image then
            productLabelImage:setVisible(true)
            productLabelImage:setImageSource(storeProducts[j].image)
            else
            productLabelImage:setVisible(false)
          end
         

           
          local productLabelTokenPrice = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelTokenPrice')
          productLabelTokenPrice:setText(formatNumbers(storeProducts[j].price))
         
          local buyWindow = storeWindow:getChildById('productList'):getChildById(j)
          buyWindow.onClick = function(self)
            if acceptWindow then
              return true
            end

            local acceptFunc = function()
              local balance = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance'):getText()
              local unformatted = balance:gsub(',', '')
              local balanceInfo = tonumber(unformatted)
              if balanceInfo >= storeProducts[j].price then
                g_game.talk(COMMAND_BUYITEM .. ' ' ..  storeIndex[i].id  .. ', ' .. storeProducts[j].id)
                acceptWindow:destroy()
                acceptWindow = nil
             
                local balance = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance'):getText()
                local unformatted = balance:gsub(',', '')
                local balanceInfo = tonumber(unformatted)
                local balanceAfterPurchase = balanceInfo - storeProducts[j].price
             
                local balanceLabel = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance')
                balanceLabel:setText((formatNumbers(balanceAfterPurchase)))
              else
                io.popen('start ' .. WEBSITE_GETCOINS)
                acceptWindow:destroy()
                acceptWindow = nil
              end
            end
 
            local cancelFunc = function() acceptWindow:destroy() acceptWindow = nil end
       
            transferPointsWindow:setVisible(false)
           
            -- local 2
            if true then
                print("local 2")
                onBuyWithScrollCount(storeProducts[j])
            else
                acceptWindow = displayAcceptBox(tr('Buy ' .. storeProducts[j].name), tr(storeProducts[j].description),
                  { { text=tr('Buy'), callback=acceptFunc },
                  { text=tr('Cancel'), callback=cancelFunc },
                  anchor=AnchorHorizontalCenter }, acceptFunc, cancelFunc)
            end
                   
            return true
          end
        end
      end
    end
  end

  connect(g_game, {
    onGameStart = refresh,
    onGameEnd = offline
  })
 
  refresh()
 
end

function terminate()
   
    storeModule:destroy()
  storeWindow:hide()
  g_keyboard.unbindKeyPress('Ctrl+U')
  ProtocolGame.unregisterExtendedOpcode(COINS_OPCODE)
 
  disconnect(g_game, {
    onGameStart = refresh,
    onGameEnd = offline
  })

end

function coinsBalance(protocol, opcode, buffer)
    local balanceLabel = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance')
    balanceLabel:setText(formatNumbers(buffer))
    print(COINS_OPCODE)
end

function refresh()
    local player = g_game.getLocalPlayer()
    if not player then
        return
    end
end

function offline()
  storeWindow:hide()
  if storeCountWindow then
    storeCountWindow:destroy()
    storeCountWindow = nil
  end
  if storeCountWindow then
    storeCountWindow:destroy()
    storeCountWindow = nil
  end
end

function toggle()
  if storeWindow:isVisible() then
    onCloseStore()
  else
    onOpenStore()
  end
end

function onOpenStore()
    --storeModule:setOn(true)
  storeWindow:show()
  storeWindow:raise()
  storeWindow:focus()
 
  local descriptionImage = storeWindow:getChildById('indexDescription'):getChildById('imageDesc')
  descriptionImage:setImageSource(storeIndex[1].image)
   
  local descriptionTitle = storeWindow:getChildById('indexDescription'):getChildById('titleDesc')
  descriptionTitle:setText(storeIndex[1].name)
   
  local description = storeWindow:getChildById('indexDescription'):getChildById('description')
  description:setText(storeIndex[1].description)

  local productsPanel = storeWindow:getChildById('productList')
  local children = productsPanel:getChildren()
  for k = 1, #children do
    children[k]:destroy()
  end

  for j=1, #storeProducts do
    if storeIndex[1].id == storeProducts[j].category_id then
      local productLabel = g_ui.createWidget('ProductButton', productList)
           
      productLabel:setId(j)
      productLabel:setTooltip(storeProducts[j].tooltip)
      local productLabelTitle = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelTitle')
      productLabelTitle:setText(short(storeProducts[j].name))
     
   
          local productLabelItem = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelItem')
          if storeProducts[j].clientId then
              productLabelItem:setVisible(true)
              productLabelItem:setItemId(storeProducts[j].clientId)
          else
              productLabelItem:setVisible(false)
          end  

         local productLabelImage = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelImage')
          if storeProducts[j].image then
              productLabelImage:setVisible(true)
              productLabelImage:setImageSource(storeProducts[j].image)
            else
              productLabelImage:setVisible(false)
          end
         
 
           
           
           
      local productLabelTokenPrice = storeWindow:getChildById('productList'):getChildById(j):getChildById('productLabelTokenPrice')
      productLabelTokenPrice:setText(formatNumbers(storeProducts[j].price))
     
      local buyWindow = storeWindow:getChildById('productList'):getChildById(j)
      buyWindow.onClick = function(self)
        if acceptWindow then
          return true
        end

        local acceptFunc = function()
          local balance = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance'):getText()
          local unformatted = balance:gsub(',', '')
          local balanceInfo = tonumber(unformatted)
          if balanceInfo >= storeProducts[j].price then
            g_game.talk(COMMAND_BUYITEM .. ' ' ..  storeIndex[1].id  .. ', ' .. storeProducts[j].id)
            acceptWindow:destroy()
            acceptWindow = nil
             
            local balance = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance'):getText()
            local unformatted = balance:gsub(',', '')
            local balanceInfo = tonumber(unformatted)
            local balanceAfterPurchase = balanceInfo - storeProducts[j].price
             
            local balanceLabel = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance')
            balanceLabel:setText((formatNumbers(balanceAfterPurchase)))
          else
            io.popen('start ' .. WEBSITE_GETCOINS)
            acceptWindow:destroy()
            acceptWindow = nil
          end
        end
 
        local cancelFunc = function() acceptWindow:destroy() acceptWindow = nil end
       
        transferPointsWindow:setVisible(false)
       
        -- local 1  
        if true then
            onBuyWithScrollCount(storeProducts[j])
        else
        acceptWindow = displayAcceptBox(tr('Buy ' .. storeProducts[j].name), tr(storeProducts[j].description),
          { { text=tr('Buy'), callback=acceptFunc },
          { text=tr('Cancel'), callback=cancelFunc },
          anchor=AnchorHorizontalCenter }, acceptFunc, cancelFunc)
        end
         
         
        return true
      end
    end
  end
end

function onCloseStore()
  storeWindow:hide()
  transferPointsWindow:setVisible(false)
  if acceptWindow then
    acceptWindow:destroy()
    acceptWindow = nil
  end
  if storeCountWindow then
    storeCountWindow:destroy()
    storeCountWindow = nil
  end
end


function transferPoints()
  local value = transferPointsWindow:getChildById('transferPointsValue')
  value:setText(tr('0'))
 
  local balanceInfo = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance'):getText()
  local balance = transferPointsWindow:getChildById('coinBalance2')
  balance:setText(formatNumbers(balanceInfo))
  transferPointsWindow:setVisible(true)
  transferPointsWindow:focus()
  transferPointsWindow:raise()
 
  acceptWindow:destroy()
  acceptWindow = nil
end

function transferAccept()
  local nickname = transferPointsWindow:getChildById('transferPointsText'):getText()
  local value = transferPointsWindow:getChildById('transferPointsValue'):getText()
  g_game.talk(COMMAND_TRANSFER .. ' ' .. nickname .. ', '.. value)
 
  local balance = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance'):getText()
  local unformatted = balance:gsub(',', '')
  local balanceInfo = tonumber(unformatted)
  local getValue = tonumber(value)
  local balanceAfterSend = balanceInfo - getValue
 
  local balanceLabel = storeWindow:getChildById('balanceInfo'):getChildById('coinBalance')
  balanceLabel:setText((formatNumbers(balanceAfterSend)))
  transferPointsWindow:setVisible(false)
end

function transferCancel()
  transferPointsWindow:setVisible(false)
end

function getCoins()
 io.popen('start ' .. WEBSITE_GETCOINS)
end
 
Back
Top