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

OTClient OTClient Inventory not working.

Pinshivic

New Member
Joined
Sep 19, 2022
Messages
3
Reaction score
0
Hello, today I was trying to add new inventory slots for my server, server side everything seems to be working correctly, but with the client its a complete different story.

Getting this on my log and console in the client.
Lua:
ERROR: Lua exception: /game_inventory/inventory.lua:2: table index is nil
stack traceback:
    [C]: in function '__newindex'
    /game_inventory/inventory.lua:2: in main chunk
    [C]: in function 'ensureModuleLoaded'
    /init.lua:59: in main chunk
ERROR: Unable to load module 'game_inventory': LUA ERROR:
/game_inventory/inventory.lua:2: table index is nil
stack traceback:
    [C]: in function '__newindex'
    /game_inventory/inventory.lua:2: in main chunk
    [C]: in function 'ensureModuleLoaded'
    /init.lua:59: in main chunk

This is my inventory.lua:

Lua:
InventorySlotStyles = {
    [InventorySlotNecklaceLeft] = 'NeckSlotLeft',
    [InventorySlotHead] = 'HeadSlot',
    [InventorySlotNecklaceRight] = 'NeckSlotRight',
    [InventorySlotLeft] = 'LeftSlot',
    [InventorySlotBody] = 'BodySlot',
    [InventorySlotRight] = 'RightSlot',
    [InventorySlotRingLeft] = 'RingSlotLeft',
    [InventorySlotLegs] = 'LegSlot',
    [InventorySlotRingRight] = 'RingSlotRight',
    [InventorySlotTrinket] = 'TrinketSlot',
    [InventorySlotFeet] = 'FeetSlot',
    [InventorySlotAmmo] = 'AmmoSlot',
    [InventorySlotBackpack] = 'BackSlotOne',
    [InventorySlotBackpackTwo] = 'BackSlotTwo',
    [InventorySlotBackpackThree] = 'BackSlotThree',
    [InventorySlotBackpackFour] = 'BackSlotFour',
    [InventorySlotBackpackFive] = 'BackSlotFive',
    [InventorySlotBackpackSix] = 'BackSlotSix'
}


inventoryWindow = nil
inventoryPanel = nil
inventoryButton = nil
purseButton = nil


function init()
    connect(LocalPlayer, {
        onInventoryChange = onInventoryChange,
        onBlessingsChange = onBlessingsChange
    })
    connect(g_game, {
        onGameStart = online,
        onGameEnd = offline
    })


    g_keyboard.bindKeyDown('Ctrl+I', toggle)


    inventoryButton = modules.client_topmenu.addRightGameToggleButton('inventoryButton', tr('Inventory') .. ' (Ctrl+I)',
                                                                      '/images/topbuttons/inventory', toggle)
    inventoryButton:setOn(true)


    inventoryWindow = g_ui.loadUI('inventory')
    inventoryWindow:disableResize()
    inventoryPanel = inventoryWindow:getChildById('contentsPanel')


    purseButton = inventoryPanel:getChildById('purseButton')
    local function purseFunction()
        local purse = g_game.getLocalPlayer():getInventoryItem(InventorySlotPurse)
        if purse then
            g_game.use(purse)
        end
    end
    purseButton.onClick = purseFunction


    refresh()
    inventoryWindow:setup()
    if g_game.isOnline() then
        inventoryWindow:setupOnStart()
    end
end


function terminate()
    disconnect(LocalPlayer, {
        onInventoryChange = onInventoryChange,
        onBlessingsChange = onBlessingsChange
    })
    disconnect(g_game, {
        onGameStart = online,
        onGameEnd = offline
    })


    g_keyboard.unbindKeyDown('Ctrl+I')


    inventoryWindow:destroy()
    inventoryButton:destroy()


    inventoryWindow = nil
    inventoryPanel = nil
    inventoryButton = nil
    purseButton = nil
end


function toggleAdventurerStyle(hasBlessing)
    for slot = InventorySlotFirst, InventorySlotLast do
        local itemWidget = inventoryPanel:getChildById('slot' .. slot)
        if itemWidget then
            itemWidget:setOn(hasBlessing)
        end
    end
end


function online()
    inventoryWindow:setupOnStart() -- load character window configuration
    refresh()
end


function offline()
    inventoryWindow:setParent(nil, true)
end


function refresh()
    local player = g_game.getLocalPlayer()
    for i = InventorySlotFirst, InventorySlotPurse do
        if g_game.isOnline() then
            onInventoryChange(player, i, player:getInventoryItem(i))
        else
            onInventoryChange(player, i, nil)
        end
        toggleAdventurerStyle(player and Bit.hasBit(player:getBlessings(), Blessings.Adventurer) or false)
    end


    purseButton:setVisible(g_game.getFeature(GamePurseSlot))
end


function toggle()
    if inventoryButton:isOn() then
        inventoryWindow:close()
        inventoryButton:setOn(false)
    else
        inventoryWindow:open()
        inventoryButton:setOn(true)
    end
end


function onMiniWindowOpen()
    inventoryButton:setOn(true)
end


function onMiniWindowClose()
    inventoryButton:setOn(false)
end


-- hooked events
function onInventoryChange(player, slot, item, oldItem)
    if slot > InventorySlotPurse then
        return
    end


    if slot == InventorySlotPurse then
        if g_game.getFeature(GamePurseSlot) then
            purseButton:setEnabled(item and true or false)
        end
        return
    end


    local itemWidget = inventoryPanel:getChildById('slot' .. slot)
    if item then
        itemWidget:setStyle('InventoryItem')
        itemWidget:setItem(item)
    else
        itemWidget:setStyle(InventorySlotStyles[slot])
        itemWidget:setItem(nil)
    end
end


function onBlessingsChange(player, blessings, oldBlessings)
    local hasAdventurerBlessing = Bit.hasBit(blessings, Blessings.Adventurer)
    if hasAdventurerBlessing ~= Bit.hasBit(oldBlessings, Blessings.Adventurer) then
        toggleAdventurerStyle(hasAdventurerBlessing)
    end
end

And this would be my inventory.otui

Code:
InventoryItem < Item
  $on:
    image-source: /images/ui/item-blessed
   
NeckSlotLeft < InventoryItem
  id: slot1
  image-source: /images/game/slots/neck
  &position: {x=65535, y=2, z=0}
  $on:
    image-source: /images/game/slots/neck-blessed

LeftSlot < InventoryItem
  id: slot4
  image-source: /images/game/slots/left-hand
  &position: {x=65535, y=6, z=0}
  $on:
    image-source: /images/game/slots/left-hand-blessed

RingSlotLeft < InventoryItem
  id: slot7
  image-source: /images/game/slots/finger
  &position: {x=65535, y=9, z=0}
  $on:
    image-source: /images/game/slots/finger-blessed
   
TrinketSlot < InventoryItem
  id: slot10
  image-source: /images/game/slots/finger
  &position: {x=65535, y=9, z=0}
  $on:
    image-source: /images/game/slots/finger-blessed

HeadSlot < InventoryItem
  id: slot2
  image-source: /images/game/slots/head
  &position: {x=65535, y=1, z=0}
  $on:
    image-source: /images/game/slots/head-blessed

BodySlot < InventoryItem
  id: slot5
  image-source: /images/game/slots/body
  &position: {x=65535, y=4, z=0}
  $on:
    image-source: /images/game/slots/body-blessed

LegSlot < InventoryItem
  id: slot8
  image-source: /images/game/slots/legs
  &position: {x=65535, y=7, z=0}
  $on:
    image-source: /images/game/slots/legs-blessed

FeetSlot < InventoryItem
  id: slot11
  image-source: /images/game/slots/feet
  &position: {x=65535, y=8, z=0}
  $on:
    image-source: /images/game/slots/feet-blessed
   
NeckSlotRight < InventoryItem
  id: slot3
  image-source: /images/game/slots/neck
  &position: {x=65535, y=2, z=0}
  $on:
    image-source: /images/game/slots/neck-blessed

RightSlot < InventoryItem
  id: slot6
  image-source: /images/game/slots/right-hand
  &position: {x=65535, y=5, z=0}
  $on:
    image-source: /images/game/slots/right-hand-blessed

RingSlotRight < InventoryItem
  id: slot9
  image-source: /images/game/slots/finger
  &position: {x=65535, y=9, z=0}
  $on:
    image-source: /images/game/slots/finger-blessed
   
AmmoSlot < InventoryItem
  id: slot12
  image-source: /images/game/slots/ammo
  &position: {x=65535, y=10, z=0}
  $on:
    image-source: /images/game/slots/ammo-blessed

BackSlotOne < InventoryItem
  id: slot13
  image-source: /images/game/slots/back
  &position: {x=65535, y=3, z=0}
  $on:
    image-source: /images/game/slots/back-blessed
   
BackSlotTwo < InventoryItem
  id: slot14
  image-source: /images/game/slots/back
  &position: {x=65535, y=3, z=0}
  $on:
    image-source: /images/game/slots/back-blessed
   
BackSlotThree < InventoryItem
  id: slot15
  image-source: /images/game/slots/back
  &position: {x=65535, y=3, z=0}
  $on:
    image-source: /images/game/slots/back-blessed
   
BackSlotFour < InventoryItem
  id: slot16
  image-source: /images/game/slots/back
  &position: {x=65535, y=3, z=0}
  $on:
    image-source: /images/game/slots/back-blessed
   
BackSlotFive < InventoryItem
  id: slot17
  image-source: /images/game/slots/back
  &position: {x=65535, y=3, z=0}
  $on:
    image-source: /images/game/slots/back-blessed
   
BackSlotSix < InventoryItem
  id: slot18
  image-source: /images/game/slots/back
  &position: {x=65535, y=3, z=0}
  $on:
    image-source: /images/game/slots/back-blessed

PurseButton < Button
  id: purseButton
  size: 26 26
  !tooltip: tr('Open purse')
  icon-source: /images/game/slots/purse
  icon-size: 24 24
  icon-offset: 1 1

MiniWindow
  id: inventoryWindow
  !text: tr('Inventory')
  icon: /images/topbuttons/inventory
  height: 175
  @onOpen: modules.game_inventory.onMiniWindowOpen()
  @onClose: modules.game_inventory.onMiniWindowClose()
  &save: true

  MiniWindowContents
    HeadSlot
      anchors.top: parent.top
      anchors.horizontalCenter: parent.horizontalCenter
      margin-top: 3

    BodySlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3

    LegSlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3

    FeetSlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3

    NeckSlotLeft
      anchors.top: parent.top
      anchors.right: slot2.left
      margin-right: 5

    LeftSlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3
     
    RingSlotLeft
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3
     
    TrinketSlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3
     
    NeckSlotRight
      anchors.top: parent.top
      anchors.left: slot2.right
      margin-right: 5
     
    RightSlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3
     
    RingSlotRight
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3
     
    AmmoSlot
      anchors.top: prev.bottom
      anchors.horizontalCenter: prev.horizontalCenter
      margin-top: 3
     
    BackSlot
      anchors.top: slot10.bottom
      anchors.horizontalCenter: slot10.horizontalCenter
      margin-top: 5
     
    BackSlotTwo
      anchors.top: prev.top
      anchors.horizontalCenter: slot11.horizontalCenter
      margin-top: 5
     
    BackSlotThree
      anchors.top: prev.top
      anchors.horizontalCenter: slot12.horizontalCenter
      margin-top: 5
     
    BackSlotFour
      anchors.top: prev.bottom
      anchors.horizontalCenter: slot10.horizontalCenter
      margin-top: 5
     
    BackSlotFive
      anchors.top: prev.top
      anchors.horizontalCenter: slot11.horizontalCenter
      margin-top: 5
     
    BackSlotSix
      anchors.top: prev.top
      anchors.horizontalCenter: slot12.horizontalCenter
      margin-top: 5
 
Last edited:
Found solution, for some reason, some of the declarations of inventory slots in gamelib/player.lua were incorrect, also had to get rid of the purse don't know what was going on there.
 
Back
Top