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

storage outfit

Mateus Robeerto

Excellent OT User
Joined
Jun 5, 2016
Messages
1,520
Solutions
78
Reaction score
940
Location
ლ(ಠ益ಠლ)
Hello Otland community, I managed to put a "storage" to buy clothes and deliver to the player, working ok... However, it only delivers one. I can't place another storage to deliver another outfit, without success... Can someone help me, please?

follow the video:


I chose the 'Nordic Chieftain' outfit, but he gave away the 'Formal Dress'. I tried to put several different functions in without success... I need to finish this store soon, for God's sake.

in creaturescript.. game_store.lua.

LUA:
local category3 = addCategory({
    type = "outfit",
    name = " News Outfits ",
    outfit = {
      type = 128, -- This type is for displaying an image for the store.

      rotating = false
    }
})

 -- for the player to choose the outfit and buy!
category3.addOutfit(9, {
storage = 535923,

    type = 1500, 

    rotating = true
}, "Nordic Chieftain", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")

category3.addOutfit(9, {
storage = 535924,

    type = 1489, 

    rotating = true
}, "Ghost Blade", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")


category3.addOutfit(9, {
storage = 535925,
    type = 1460, 
    rotating = true
}, "Formal Dress", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")


this part to buy.
LUA:
function defaultItemBuyAction(player, offer)
  if player:addItem(offer["itemId"], offer["count"], false) then
    return true
  end
  return "Unable to add item! you have enough space?"
end

local config = {
    -- Nordic Chieftain
    storage = 535923,
    looktype = 1500,
    -- Ghost Blade
    storage = 535924,
    looktype = 1489,
    -- Formal Dress
    storage = 535925,
    looktype = 1460
}


function defaultOutfitBuyAction(player, offer)
  local outfit = offer['outfit']
 

  if player:getStorageValue(config.storage) < 1 then
      player:addOutfit(config.looktype)
     player:sendTextMessage(MESSAGE_INFO_DESCR, "You already own this outfit!")
    return false
  end
 

  local points = getPoints(player)
  if offer['cost'] > points or points < 1 then
    player:sendTextMessage(MESSAGE_INFO_DESCR, "You don't have enough points to buy this outfit")
    return false
  end
 
  -- Remover pontos do jogador
 db.query("UPDATE `znote_accounts` SET `points` = `points` - " .. offer['cost'] .. " WHERE `id` = " .. player:getAccountId())
 
    player:setStorageValue(config.storage, 1)
      player:addOutfit(outfit)
     player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations, you bought an outfit")

 

  db.asyncQuery("INSERT INTO `shop_history` (`account`, `player`, `date`, `title`, `cost`, `details`) VALUES ('" .. player:getAccountId() .. "', '" .. player:getGuid() .. "', NOW(), " .. db.escapeString(offer['title']) .. ", " .. db.escapeString(offer['cost']) .. ", " .. db.escapeString(json.encode(offer)) .. ")")
 
local outfitName = outfit.name or "Unknown Outfit"
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully purchased the outfit '" .. outfitName .. "'.")


  return true
end
 
Solution
I belive it’s related to the way how it converts arrays to json and how it count elements (#array) so try define it like:

LUA:
category3.addOutfit(9, {
    mount = 0,
    feet = 114,
    legs = 114,
    body = 116,
    type = 1490,
    lookType = { 1490, 1489 },
    auxType = 0,
    addons = 0,
    head = 2,
    rotating = true
}, "Nordic Chieftain", "This is your cool new outfit. You can buy it here")

And add like:
LUA:
local sex = player:getSex()
local lookType = outfit.lookType[sex + 1]
local addons = outfit.addons

player:addOutfitAddon(lookType, addons)

Or add for both always:
LUA:
local addons = outfit.addons

for _, lookType in ipairs(outfit.lookType) do
    player:addOutfitAddon(lookType, addons)
end
First:
- redefinition of properties with same key in one object: config:

LUA:
local config = {
    -- Nordic Chieftain
    storage = 535923,
    looktype = 1500,
    -- Ghost Blade
    storage = 535924,
    looktype = 1489,
    -- Formal Dress
    storage = 535925,
    looktype = 1460
}
You end up with it being always:
LUA:
local config = {
    storage = 535925,
    looktype = 1460
}

I'm not sure how this conecpt works in general but I assume it's like offer in the defaultOutfitBuyAction does already contain info of the outfit that player bought. But you're mixing some things doing it once with this config(wrong) and also with offer['outfit']:
LUA:
player:addOutfit(outfit)

If for some reason you need storage ID's for outfits just pass it to the offer config and add it in addition but you're missing looktype config, either define some key => value map or pass these in addition to the offer config:
LUA:
category3.addOutfit(9, {
    storage = 535924,
    type = 1489, -- I guess it's looktype???
    rotating = true
}, "Ghost Blade", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")
 
Last edited:
local config = { storage = 535925, looktype = 1460 }
I did that, but it only delivers one. I tried to separate it in another storage and it doesn't work to deliver another outfit
player:addOutfit(outfit)
I removed that line and tested it, laundry delivery is working properly. The only problem is that storage part. When I try to buy the 'Nordic Chieftain' outfit, BUT IT DELIVERED IT WAS THE 'Formal Dress'. I tried to buy again and still he repeatedly delivered the 'Formal Dress'. It doesn't work at all

I still tried another way, but nothing works and doesn't even deliver
LUA:
local config = {
    [535923] = {
        looktype = 1500, -- Nordic Chieftain
    },
    [535924] = {
        looktype = 1489, -- Ghost Blade
    },
    [535925] = {
        looktype = 1460, -- Formal Dress
    }
}
 
Try get rid of this config and use it like:
LUA:
function defaultOutfitBuyAction(player, offer)
    local config = offer['outfit']
    if not config then
        print('Wrong offer config!')
        return false
    end

    if player:getStorageValue(config.storage) > 0 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You already own this outfit!")
        return false
    end

    local points = getPoints(player)
    if offer['cost'] > points or points < 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You don't have enough points to buy this outfit")
        return false
    end

    local accountId = player:getAccountId()
    db.query("UPDATE `znote_accounts` SET `points` = `points` - " ..offer['cost'] .. " WHERE `id` = " .. accountId)

    player:setStorageValue(config.storage, 1)
    player:addOutfit(config.type)
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations, you bought an outfit")

    db.asyncQuery("INSERT INTO `shop_history` (`account`, `player`, `date`, `title`, `cost`, `details`) VALUES ('" .. accountId .. "', '" .. player:getGuid() .. "', NOW(), " .. db.escapeString(offer['title']) .. ", " .. db.escapeString(offer['cost']) .. ", " .. db.escapeString(json.encode(offer)) .. ")")

    local outfitName = offer.title or "Unknown Outfit"
    player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully purchased the outfit '" .. outfitName .. "'.")

    return true
end

Still not sure why do you need this storage? To tell whether player has already outift?
Why not simple check player:hasOutfit(lookType, addons) instead?
What about male/female looktypes, they're separate offers or you simply care only about male outfits?
 
Last edited:
Try get rid of this config and use it like:
This script doesn't work... I removed that 'config storage' part. It just doesn't give anything away.
Still not sure why do you need this storage? To tell whether player has already outift?
Why not simple check player:hasOutfit(lookType, addons) instead?
Without storage, it doesn't deliver anything. It is necessary to put the storage, but I do not know. I still don't quite understand...
-- for the player to choose the outfit and buy! category3.addOutfit(9, { storage = 535923, type = 1500, rotating = true }, "Nordic Chieftain", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")
See this part to verify that it is correct??. I'm thinking there's something wrong with this part.
 
First of all clear storage of your character as your code was always using single storage value: 535925 (from config) but outfit was correctly taken from the selected offer config
 
What's the result then, does it give any error? Is the storage being set but no outfit is given? More details you give the better hints I can give.

Try with changing storage criteria to (as for some distros it's -1 by default and I keep forgetting that it's not JS):
LUA:
if player:getStorageValue(config.storage) > 0 then
   ...
end
 
Last edited:
I managed to do it myself. The problem is already solved! It's working and delivering the outfit to the player normally at the moment

LUA:
function defaultOutfitBuyAction(player, offer)
    local outfit = offer['outfit']
 
 
    if player:getStorageValue(outfit['storage']) > 0 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Você já possui este outfit!")
        return false
    end
 
 
    local points = getPoints(player)
    if offer['cost'] > points or points < 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Você não possui pontos suficientes para comprar este outfit")
        return false
    end
 
 
    db.query("UPDATE `accounts` SET `premium_points` = `premium_points` - " .. offer['cost'] .. " WHERE `id` = " .. player:getAccountId())
 
 
    player:addOutfit(outfit['type'], outfit['addons'])
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Você comprou seu novo outfit!")
 
 
    player:setStorageValue(outfit['storage'], 1)
 
 
    db.asyncQuery("INSERT INTO `shop_history` (`account`, `player`, `date`, `title`, `cost`, `details`) VALUES ('" .. player:getAccountId() .. "', '" .. player:getGuid() .. "', NOW(), " .. db.escapeString(offer['title']) .. ", " .. db.escapeString(offer['cost']) .. ", " .. db.escapeString(json.encode(offer)) .. ")")
 
    return true
end
Post automatically merged:

This script is working and delivering for the male character... I'm trying to put it on for the female character
Post automatically merged:

The only solution is to split the lists into female and male. For example, the Outfits on the list for men need to be all ready, and then create another list for women, also with all ready and working, to deliver Outfits for women normally

LUA:
category3.addOutfit(9, {
    mount = 0,
    feet = 114,
    legs = 114,
    body = 116,
    type = 1490, -- ID Outfit- FEMALE
    auxType = 0,
    addons = 0,
    head = 2,
    rotating = true
}, "Nordic Chieftain", "This is your cool new outfit. You can buy it here")
 
Last edited:
You could also define things like:

LUA:
category3.addOutfit(9, {
    mount = 0,
    feet = 114,
    legs = 114,
    body = 116,
    type = 1490, -- ID Outfit- FEMALE
    lookType = {
        [PLAYERSEX_FEMALE] = 1490,
        [PLAYERSEX_MALE] = 1489
    },
    auxType = 0,
    addons = 0,
    head = 2,
    rotating = true
}, "Nordic Chieftain", "This is your cool new outfit. You can buy it here")

And do it like that in the code:
LUA:
local sex = player:getSex()
local lookType = outfit.lookType[sex]
local addons = outfit.addons

player:addOutfitAddon(lookType, addons)

Or in case you have some "gender change" option you can add for both at once

Or in general rework whole shop to evaluate correct type based on player sex to also present correct image
 
Last edited:
lookType = { [PLAYERSEX_FEMALE] = 1490, [PLAYERSEX_MALE] = 1489 },
This one doesn't work, got an error here

LUA:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/game_store.lua:onExtendedOpcode
data/lib/core/json.lua:80: invalid table: sparse array
stack traceback:
        [C]: at 0x7ff615ae2810
        [C]: in function 'error'
        data/lib/core/json.lua:80: in function 'encode'
        data/lib/core/json.lua:95: in function 'encode'
        data/lib/core/json.lua:95: in function 'encode'
        data/lib/core/json.lua:84: in function 'encode'
        data/lib/core/json.lua:95: in function 'encode'
        data/lib/core/json.lua:84: in function 'encode'
        data/lib/core/json.lua:95: in function 'encode'
        data/lib/core/json.lua:137: in function 'encode'
        data/creaturescripts/scripts/game_store.lua:285: in function 'sendJSON'
        data/creaturescripts/scripts/game_store.lua:341: in function <data/creaturescripts/scripts/game_store.lua:321>
 
Hello Otland community, I managed to put a "storage" to buy clothes and deliver to the player, working ok... However, it only delivers one. I can't place another storage to deliver another outfit, without success... Can someone help me, please?

follow the video:


I chose the 'Nordic Chieftain' outfit, but he gave away the 'Formal Dress'. I tried to put several different functions in without success... I need to finish this store soon, for God's sake.

in creaturescript.. game_store.lua.

LUA:
local category3 = addCategory({
    type = "outfit",
    name = " News Outfits ",
    outfit = {
      type = 128, -- This type is for displaying an image for the store.

      rotating = false
    }
})

 -- for the player to choose the outfit and buy!
category3.addOutfit(9, {
storage = 535923,

    type = 1500,

    rotating = true
}, "Nordic Chieftain", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")

category3.addOutfit(9, {
storage = 535924,

    type = 1489,

    rotating = true
}, "Ghost Blade", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")


category3.addOutfit(9, {
storage = 535925,
    type = 1460,
    rotating = true
}, "Formal Dress", "esta e a sua nova roupa legal. Voce pode compra-lo aqui")


this part to buy.
LUA:
function defaultItemBuyAction(player, offer)
  if player:addItem(offer["itemId"], offer["count"], false) then
    return true
  end
  return "Unable to add item! you have enough space?"
end

local config = {
    -- Nordic Chieftain
    storage = 535923,
    looktype = 1500,
    -- Ghost Blade
    storage = 535924,
    looktype = 1489,
    -- Formal Dress
    storage = 535925,
    looktype = 1460
}


function defaultOutfitBuyAction(player, offer)
  local outfit = offer['outfit']
 

  if player:getStorageValue(config.storage) < 1 then
      player:addOutfit(config.looktype)
     player:sendTextMessage(MESSAGE_INFO_DESCR, "You already own this outfit!")
    return false
  end
 

  local points = getPoints(player)
  if offer['cost'] > points or points < 1 then
    player:sendTextMessage(MESSAGE_INFO_DESCR, "You don't have enough points to buy this outfit")
    return false
  end
 
  -- Remover pontos do jogador
 db.query("UPDATE `znote_accounts` SET `points` = `points` - " .. offer['cost'] .. " WHERE `id` = " .. player:getAccountId())
 
    player:setStorageValue(config.storage, 1)
      player:addOutfit(outfit)
     player:sendTextMessage(MESSAGE_INFO_DESCR, "Congratulations, you bought an outfit")

 

  db.asyncQuery("INSERT INTO `shop_history` (`account`, `player`, `date`, `title`, `cost`, `details`) VALUES ('" .. player:getAccountId() .. "', '" .. player:getGuid() .. "', NOW(), " .. db.escapeString(offer['title']) .. ", " .. db.escapeString(offer['cost']) .. ", " .. db.escapeString(json.encode(offer)) .. ")")
 
local outfitName = outfit.name or "Unknown Outfit"
player:sendTextMessage(MESSAGE_INFO_DESCR, "You have successfully purchased the outfit '" .. outfitName .. "'.")


  return true
end
hello I just managed to make that part work I hope it works for you king <3


I use the forgotten server 1.3 tibia 10.98
 
I belive it’s related to the way how it converts arrays to json and how it count elements (#array) so try define it like:

LUA:
category3.addOutfit(9, {
    mount = 0,
    feet = 114,
    legs = 114,
    body = 116,
    type = 1490,
    lookType = { 1490, 1489 },
    auxType = 0,
    addons = 0,
    head = 2,
    rotating = true
}, "Nordic Chieftain", "This is your cool new outfit. You can buy it here")

And add like:
LUA:
local sex = player:getSex()
local lookType = outfit.lookType[sex + 1]
local addons = outfit.addons

player:addOutfitAddon(lookType, addons)

Or add for both always:
LUA:
local addons = outfit.addons

for _, lookType in ipairs(outfit.lookType) do
    player:addOutfitAddon(lookType, addons)
end
 
Last edited:
Solution
hello I just managed to make that part work I hope it works for you king <3


I use the forgotten server 1.3 tibia 10.98
Good morning, thank you for your reply. I tested your script and it's the same as mine that normally delivers Outfits, ok. There are only a few differences, but I like it, I'm going to take advantage of it and get some for my shop. Thanks! However, what I want is that, according to the player's sex, for example, if he is female and sees the store, female Outfits appear. And when you're a male player and you see the store, the correct images for sex automatically appear, you know?
Code:
category3.addOutfit(9, {
    mount = 0,
    feet = 114,
    legs = 114,
    body = 116,
    type = 1490,
    lookType = { 1490, 1489 },
    auxType = 0,
    addons = 0,
    head = 2,
    rotating = true
}, "Nordic Chieftain", "This is your cool new outfit. You can buy it here")
Now yes, it's working fine. I created two characters, one male and one female. I made the purchase and it was delivered correctly for the male character, OK, and for the female character it was also delivered correctly, with no errors. Thank you very much for your time.

Can you tell me what this MAX SIZE is for?
local MAX_PACKET_SIZE = 50000
 
Good morning, thank you for your reply. I tested your script and it's the same as mine that normally delivers Outfits, ok. There are only a few differences, but I like it, I'm going to take advantage of it and get some for my shop. Thanks! However, what I want is that, according to the player's sex, for example, if he is female and sees the store, female Outfits appear. And when you're a male player and you see the store, the correct images for sex automatically appear, you know?

Now yes, it's working fine. I created two characters, one male and one female. I made the purchase and it was delivered correctly for the male character, OK, and for the female character it was also delivered correctly, with no errors. Thank you very much for your time.

Can you tell me what this MAX SIZE is for?
I hope it works for you and if it is the solution mark it with a ticket greetings and good day king
 
Lua:
Code:
function defaultOutfitBuyAction(player, offer)
    local outfit = offer['outfit']
 
 
    if player:getStorageValue(outfit['storage']) > 0 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Você já possui este outfit!")
        return false
    end
 
 
    local points = getPoints(player)
    if offer['cost'] > points or points < 1 then
        player:sendTextMessage(MESSAGE_INFO_DESCR, "Você não possui pontos suficientes para comprar este outfit")
        return false
    end
 
 
    db.query("UPDATE `accounts` SET `premium_points` = `premium_points` - " .. offer['cost'] .. " WHERE `id` = " .. player:getAccountId())
 
 
    player:addOutfit(outfit['type'], outfit['addons'])
    player:sendTextMessage(MESSAGE_INFO_DESCR, "Você comprou seu novo outfit!")
 
 
    player:setStorageValue(outfit['storage'], 1)
 
 
    db.asyncQuery("INSERT INTO `shop_history` (`account`, `player`, `date`, `title`, `cost`, `details`) VALUES ('" .. player:getAccountId() .. "', '" .. player:getGuid() .. "', NOW(), " .. db.escapeString(offer['title']) .. ", " .. db.escapeString(offer['cost']) .. ", " .. db.escapeString(json.encode(offer)) .. ")")
 
    return true
end
The one I made is working fine to deliver Outfits normally. I was just asking to adjust it for gender, male and female, that's all. Already mark as resolved regarding sex. The rest is working fine. Thanks.
 
You'd need to rework how offers are initialized, as from the init code there's no player instance. I'd try maybe with doing like:
LUA:
function init(player)
    local sex = player:getSex()
    local category3 = addCategory({
        type = "outfit",
        name = " News Outfits ",
        sex = sex,
        outfit = {
            lookType = { 127, 128 }, -- female, male lookType
            rotating = false
        }
    })
end

Ofc pass the player instance from:
LUA:
function onExtendedOpcode(player, opcode, buffer)
    if not SHOP_CATEGORIES then
        init(player)
    end
end

And put the logic responsible for picking the correct one to the addOutfit like:
LUA:
function addCategory(data)
  local sex = data.sex or PLAYERSEX_MALE
  if data.type == "outfit" then
     local outfit = data.outfit
     outfit.type = outfit.lookType[sex + 1]
  end

  data['offers'] = {}
  table.insert(SHOP_CATEGORIES, data)
  table.insert(SHOP_CALLBACKS, {})
  local index = #SHOP_CATEGORIES

  return {
    addItem = function(cost, itemId, count, title, description, callback)
      -- code removed to increase readability
    end,
    addOutfit = function(cost, outfit, title, description, callback)
      if not callback then
        callback = defaultOutfitBuyAction
      end

      outfit.type = outfit.lookType[sex + 1]
      table.insert(SHOP_CATEGORIES[index]['offers'], {
        cost = cost,
        type = "outfit",
        outfit = outfit,
        title = title,
        description = description
      })
      table.insert(SHOP_CALLBACKS[index], callback)
    end,
    addImage = function(cost, image, title, description, callback)
      -- code removed to increase readability
    end
  }
end

And then you could simply use outfit['type'] in defaultOutfitBuyAction instead
Note: ofc. outfit would be gone once player decide to change its gender
I'm also afriad you'd have to initialize shop per player and not globally like with use of SHOP_CATEGORIES (unconditional init(player) call should do the trick) assuming all other states are cleared once it's called
 
Last edited:
You'd need to rework how offers are initialized, as from the init code there's no player instance. I'd try maybe with doing like:
LUA:
function init(player)
    local sex = player:getSex()
    local category3 = addCategory({
        type = "outfit",
        name = " News Outfits ",
        sex = sex,
        outfit = {
            lookType = { 127, 128 }, -- female, male lookType
            rotating = false
        }
    })
end

Ofc pass the player instance from:
LUA:
function onExtendedOpcode(player, opcode, buffer)
    if not SHOP_CATEGORIES then
        init(player)
    end
end

And put the logic responsible for picking the correct one to the addOutfit like:
LUA:
function addCategory(data)
  local sex = data.sex or PLAYERSEX_MALE
  data['offers'] = {}
  table.insert(SHOP_CATEGORIES, data)
  table.insert(SHOP_CALLBACKS, {})
  local index = #SHOP_CATEGORIES

  return {
    addItem = function(cost, itemId, count, title, description, callback)
      -- code removed to increase readability
    end,
    addOutfit = function(cost, outfit, title, description, callback)
      if not callback then
        callback = defaultOutfitBuyAction
      end

      outfit.type = outfit.lookType[sex + 1]
      table.insert(SHOP_CATEGORIES[index]['offers'], {
        cost = cost,
        type = "outfit",
        outfit = outfit,
        title = title,
        description = description
      })
      table.insert(SHOP_CALLBACKS[index], callback)
    end,
    addImage = function(cost, image, title, description, callback)
      -- code removed to increase readability
    end
  }
end

And then you could simply use outfit['type'] in defaultOutfitBuyAction instead
Note: ofc. outfit would be gone once player decide to change its gender
I'm also afriad you'd have to initialize shop per player and not globally like with use of SHOP_CATEGORIES (unconditional init(player) call should do the trick) assuming all other states are cleared once it's called
store.png
It's not showing. The script has now been resolved. If you don't worry too much, thank you for your time. I've already made the decision to put images that come together for both male and female in each store. Players will have to read the Outfit's name and buy it ready. Solved, simple.


Now I'm struggling to study how to deliver mounts, auras and wings... it's hard, kkkkk.
 
View attachment 76976
It's not showing. The script has now been resolved. If you don't worry too much, thank you for your time. I've already made the decision to put images that come together for both male and female in each store. Players will have to read the Outfit's name and buy it ready. Solved, simple.


Now I'm struggling to study how to deliver mounts, auras and wings... it's hard, kkkkk.
It's really not difficult if you already have addWings, addAura and addShader included in your sources, you just have to do the same thing that is done with the addoutfit in the code and in a custom one do the delivery integration
 
Back
Top