Postado Abril 30, 2014 11 anos Este é um post popular. Olá pessoal, para quem não sabe esse sistema permite vender items na "porta" da sua house, um tipo de market.Requisitos: Ultimas versões do TFS, caso contrário não irá funcionar!Imagens: Bom, a iamgem mostra tudo ... sua casa deve ter algo borda acessível, e no caso da iamgem, foi usado uma cesta, e dentro colocamos uma label e umas bag com os itens que serão vendidos dentro, na label ficará como o exemplo:sell [demon shield, 40000;] buy [dragon shield, 5000;] Bem simples né? Para implementar esses sistema devemos fazer os passos a seguir:[ 1 ] • Adicionar a seguinte tabela em sua database pelo phpmyadmin: Spoiler CREATE TABLE IF NOT EXISTS `onlogin_sendtoinbox` ( `player_id` int(11) NOT NULL DEFAULT '0', `itemtype` smallint(6) NOT NULL DEFAULT '0', `count` smallint(5) NOT NULL DEFAULT '0', `price` bigint(20) unsigned NOT NULL DEFAULT '0', `actionid` bigint(20) unsigned NOT NULL DEFAULT '0', `description` varchar(255) NOT NULL DEFAULT '', `text` varchar(1023) NOT NULL DEFAULT '', `writer_guid` int(11) NOT NULL DEFAULT 0, `written_at` bigint(20) NOT NULL, FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB [ 2 ] • Agora crie um arquivo em data/actions/script/, com o nome de house_shop.lua e coloque esse código dentro: Spoiler house_shop_cfg = { shop_id = 1989 } --[[ install query CREATE TABLE IF NOT EXISTS `onlogin_sendtoinbox` ( `player_id` int(11) NOT NULL DEFAULT '0', `itemtype` smallint(6) NOT NULL DEFAULT '0', `count` smallint(5) NOT NULL DEFAULT '0', `price` bigint(20) unsigned NOT NULL DEFAULT '0', `actionid` bigint(20) unsigned NOT NULL DEFAULT '0', `description` varchar(255) NOT NULL DEFAULT '', `text` varchar(1023) NOT NULL DEFAULT '', `writer_guid` int(11) NOT NULL DEFAULT 0, `written_at` bigint(20) NOT NULL, FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE ) ENGINE=InnoDB ]]-- --[[ enable if you get errors function isHousetile(position) local t = Tile(position) if t == nil then return false end return t:hasFlag(TILESTATE_HOUSE) end function playerExists(name) local a = db.storeQuery('SELECT `name` FROM `players` WHERE `name` = "' .. name .. '" LIMIT 1') if a then return true end return false end ]]-- function getPlayerBalanceByGUID(guid) local b = getPlayerByName(getPlayerNameByGUID(guid)) if b then return getPlayerBalance(b) end local a = db.storeQuery('SELECT `balance` FROM `players` WHERE `id` = ' .. guid .. ' LIMIT 1') if a then return result.getDataInt(a, "balance") end return nil end function getPlayerNameByGUID(guid) local a = db.storeQuery('SELECT `name` FROM `players` WHERE `id` = ' .. guid .. ' LIMIT 1') if a then return result.getDataString(a, "name") end return nil end function isInContainer(uid, id) for i = 0, getContainerSize(uid) - 1 do if getContainerItem(uid, i).itemid == id then return true end end return false end function getContainerItemCount(uid, id, deepSearch) c_i_count = 0 for i = 0, getContainerSize(uid) - 1 do if getContainerItem(uid, i).itemid == id then c_i_count = c_i_count + Item(getContainerItem(uid, i).uid):getCount() end if deepSearch then if isContainer(getContainerItem(uid, i).uid) then c_i_count = c_i_count + getContainerItemCount(getContainerItem(uid, i).uid, id, true) end end end return c_i_count end function getContainerItemById(uid, itemid, deepSearch) for i = 0, getContainerSize(uid) - 1 do if getContainerItem(uid, i).itemid == itemid then return getContainerItem(uid, i) end if deepSearch then if isContainer(getContainerItem(uid, i).uid) then if getContainerItemById(getContainerItem(uid, i).uid, itemid, true).uid > 0 then return getContainerItemById(getContainerItem(uid, i).uid, itemid, true) end end end end return {name = "", itemid = 0, uid = 0, actionid = 0, type = 0} end function doCopyItem_extended(item) return Item(item.uid):clone():getUniqueId() end function refreshHouseTradeWindow(cid, item) closeShopWindow(cid) addEvent(basketWindow, 10, cid, item, getThingPos(item.uid)) end function i_n(item, amount) if amount == 1 then return getItemName(item) end return ItemType(item):getPluralName() end function i_ar(item, amount) if ItemType(item):getArticle() == "" then return amount .. "x" else if amount == 1 then return ItemType(item):getArticle() else return amount end end end function sendBoughtItemsToPlayer(cid, container, item, amount) while amount > 0 do local c = getContainerItemById(container.uid, item, true) if amount - Item(c.uid):getCount() > -1 then doPlayerAddItemEx(cid, doCopyItem_extended(c)) amount = amount - Item(c.uid):getCount() doRemoveItem(c.uid) else doPlayerAddItemEx(cid, doCopyItem_extended(c)) doChangeTypeItem(c.uid, Item(c.uid):getCount() - amount) return true end end return true end function addInboxQueue(name, item, profit) if getPlayerGUIDByName(name) == 0 then error("player with such name does not exist") return false end if item == nil then error("item is nil") return false end if item.uid == 0 then return false end if tonumber(profit) == nil then profit = 0 end db.query("INSERT INTO `onlogin_sendtoinbox` (`player_id`,`itemtype`,`count`,`price`,`actionid`,`description`,`text`,`writer_guid`,`written_at`) VALUES (" .. getPlayerGUIDByName(name) .. "," .. item.itemid .. "," .. Item(item.uid):getCount() .. "," .. profit .. "," .. item.actionid .. ",'" .. Item(item.uid):getAttribute(4) .. "','" .. Item(item.uid):getAttribute(8) .. "'," .. getPlayerGUIDByName(Item(item.uid):getAttribute(32)) .. "," .. Item(item.uid):getAttribute(16) .. ")") if(isContainer(item.uid)) then for i = (getContainerSize(item.uid) - 1), 0, -1 do local tmp = getContainerItem(item.uid, i) if(tmp.itemid > 0) then addInboxQueue(name, tmp, 0) end end end return true end shop_label = {} function onSell(cid, item, subType, amount) if amount < 1 then return true end local b = getTileItemById(houseShop[cid], house_shop_cfg.shop_id) local c = b.uid if c == 0 then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Service unavailable.") closeShopWindow(cid) return true else local last_i = getContainerSize(c) - 1 for i = 0, last_i do if Item(getContainerItem(c, i).uid):getAttribute(8) ~= "" then shop_label[cid] = Item(getContainerItem(c, i).uid) break end if i == last_i then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Service unavailable.") closeShopWindow(cid) return true end end if not playerExists(shop_label[cid]:getAttribute(32)) then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Error: Unable to find shop owner.") closeShopWindow(cid) return true end if getDistanceBetween(getThingPos(cid), getThingPos(c)) == 1 then local g = getPlayerGUIDByName(shop_label[cid]:getAttribute(32)) local k = shop_label[cid]:getAttribute(8) local kx = k:match('Buy%[(.-)%]') local offers = kx:split(";") for i = 1, #offers do local o_e = offers[i]:split(",") if getItemIdByName(o_e[1]) == item then if tonumber(o_e[3]) ~= nil then if amount > tonumber(o_e[3]) then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "This market will accept only " .. tonumber(o_e[3]) .. " " .. i_n(item, amount) .. " more.") refreshHouseTradeWindow(cid, b) return true end end if amount * tonumber(o_e[2]) > getPlayerBalanceByGUID(g) then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Shop owner doesn't have enough money.") refreshHouseTradeWindow(cid, b) return true end if amount > getPlayerItemCount(cid, item) then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You don't have enough items.") refreshHouseTradeWindow(cid, b) return true end if tonumber(o_e[3]) ~= nil then house_shop_amount_points = amount house_shop_newtext = "Buy[" for j = 1, #offers do local o_ex = offers[j]:split(",") if getItemIdByName(o_ex[1]) == item then house_shop_amount_points = o_ex[3] - house_shop_amount_points if house_shop_amount_points > 0 then house_shop_newtext = house_shop_newtext .. o_ex[1] .. ", " .. o_ex[2] .. ", " .. house_shop_amount_points end else house_shop_newtext = house_shop_newtext .. offers[j] end house_shop_newtext = house_shop_newtext .. ";" end house_shop_newtext = house_shop_newtext .. "]\nSell[" .. k:match('Sell%[(.-)%]') .. "]" shop_label[cid]:setAttribute(8, house_shop_newtext) end if isItemStackable(item) then doPlayerTakeItem(cid, item, amount) local target = getPlayerNameByGUID(g) local tid = getPlayerByName(target) if(tid) then doPlayerSetBalance(tid, getPlayerBalance(tid) - (amount * tonumber(o_e[2]))) Player(tid):getInbox():addItem(item, amount, true, 1) doPlayerSendTextMessage(tid, MESSAGE_STATUS_CONSOLE_BLUE, "[Store]: You bought " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. amount * tonumber(o_e[2]) .. " gold. Item sent to your inbox.") else if playerExists(target) then db.query("UPDATE `players` SET `balance` = `balance` - '" .. (amount * tonumber(o_e[2])) .. "' WHERE `name` = '" .. target .. "'") db.query("INSERT INTO `player_inboxitems` (`player_id`, `itemtype`, `count`) VALUES (" .. g .. "," .. item .. ", " .. amount .. ")") end end doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Sold " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. amount * tonumber(o_e[2]) .. " gold.") doPlayerAddMoney(cid, amount * tonumber(o_e[2])) refreshHouseTradeWindow(cid, b) return true else local target = getPlayerNameByGUID(g) local tid = getPlayerByName(target) if(tid) then doPlayerSetBalance(tid, getPlayerBalance(tid) - (amount * tonumber(o_e[2]))) for i = 1, amount do addInboxQueue(target, getPlayerItemById(cid, true, item), amount * tonumber(o_e[2])) doRemoveItem(getPlayerItemById(cid, true, item).uid) end doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Sold " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. amount * tonumber(o_e[2]) .. " gold.") doPlayerSendTextMessage(tid, MESSAGE_STATUS_CONSOLE_BLUE, "[Store]: You bought " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. amount * tonumber(o_e[2]) .. " gold. Item will be sent to your inbox on your next login.") else local p_exist = playerExists(target) for i = 1, amount do if p_exist then addInboxQueue(target, getPlayerItemById(cid, true, item), amount * tonumber(o_e[2])) end doRemoveItem(getPlayerItemById(cid, true, item).uid) end if p_exist then db.query("UPDATE `players` SET `balance` = `balance` - '" .. (amount * tonumber(o_e[2])) .. "' WHERE `name` = '" .. target .. "'") end end doPlayerAddMoney(cid, amount * tonumber(o_e[2])) doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Sold " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. amount * tonumber(o_e[2]) .. " gold.") refreshHouseTradeWindow(cid, b) return true end end end else doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You are too far to perform this trade.") closeShopWindow(cid) return true end end end function onBuy(cid, item, subType, amount, ignoreCap, inBackpacks) if amount < 1 then return true end local b = getTileItemById(houseShop[cid], house_shop_cfg.shop_id) local c = b.uid if c == 0 then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Service unavailable.") closeShopWindow(cid) return true else if getDistanceBetween(getThingPos(cid), getThingPos(c)) == 1 then if getContainerItemById(c, item, true).uid > 0 then local x = getContainerItemCount(c, item, true) if amount > x then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Not enough items in shop.\nAvailable: " .. x) refreshHouseTradeWindow(cid, b) return true else for i = 1, #houseShopList[cid] do if item == houseShopList[cid][i].id then if houseShopList[cid][i].buy ~= nil then local price = houseShopList[cid][i].buy * amount if getPlayerMoney(cid) >= price then doPlayerRemoveMoney(cid, price) doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Bought " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. price .. " gold.") local last_i = getContainerSize(c) - 1 for i = 0, last_i do if Item(getContainerItem(c, i).uid):getAttribute(8) ~= "" then shop_label[cid] = Item(getContainerItem(c, i).uid) break end end local g = getPlayerGUIDByName(shop_label[cid]:getAttribute(32)) if g ~= 0 then local target = getPlayerNameByGUID(g) local tid = getPlayerByName(target) if(tid) then doPlayerSetBalance(tid, getPlayerBalance(tid) + price) doPlayerSendTextMessage(tid, MESSAGE_STATUS_CONSOLE_BLUE, "[Store]: " .. getPlayerName(cid) .. " has bought " .. i_ar(item, amount) .. " " .. i_n(item, amount) .. " for " .. price .. " gold.") else if(playerExists(target)) then db.query("UPDATE `players` SET `balance` = `balance` + '" .. price .. "' WHERE `name` = '" .. target .. "'") end end end sendBoughtItemsToPlayer(cid, b, item, amount) refreshHouseTradeWindow(cid, b) return true else doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You don't have enough money.") refreshHouseTradeWindow(cid, b) return true end break end end end doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Service unavailable.") refreshHouseTradeWindow(cid, b) return true end else doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Item unavailable.") refreshHouseTradeWindow(cid, b) return true end else doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You are too far to perform this trade.") closeShopWindow(cid) return true end end end houseShopList = {} houseShop = {} function basketWindow(cid, item, pos) houseShopList[cid] = {} if(not isContainer(item.uid)) then if pos ~= nil then item.uid = getTileItemById(houseShop[cid], house_shop_cfg.shop_id).uid end end local last_i = getContainerSize(item.uid) - 1 for i = 0, last_i do if Item(getContainerItem(item.uid, i).uid):getAttribute(8) ~= "" then shop_label[cid] = Item(getContainerItem(item.uid, i).uid) break end if i == last_i then doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Service unavailable.") closeShopWindow(cid) return true end end local k = shop_label[cid]:getAttribute(8) local s = k:match('Sell%[(.-)%]') local b = k:match('Buy%[(.-)%]') -- sell window, example: Sell[demon shield, 40000; mace, 30; skull staff, 6000] if s ~= nil then local offers = s:split(";") if offers[1] ~= nil then for i = 1, #offers do local o_e = offers[i]:split(",") local o_i = getItemIdByName(o_e[1]) if tonumber(o_i) ~= nil then if tonumber(o_e[2]) ~= nil then if getContainerItemById(item.uid, tonumber(o_i), true).uid > 0 then table.insert(houseShopList[cid], {id = tonumber(o_i), buy = tonumber(o_e[2]), name = o_e[1]}) end end end end end end -- buy window, example: Buy[demon shield, 40000, 2; mace, 30, 5; skull staff, 6000, 1], if no amount then infinite, buy limit wip if b ~= nil then local offers = b:split(";") if offers[1] ~= nil then for i = 1, #offers do local o_e = offers[i]:split(",") local o_i = getItemIdByName(o_e[1]) local o_x_amount = tonumber(o_e[3]) if tonumber(o_i) ~= nil then if tonumber(o_e[2]) ~= nil then if o_x_amount == nil then o_x_amount = 1 end if getPlayerBalanceByGUID(getPlayerGUIDByName(shop_label[cid]:getAttribute(32))) >= tonumber(o_e[2]) * o_x_amount then table.insert(houseShopList[cid], {id = tonumber(o_i), sell = tonumber(o_e[2]), name = o_e[1]}) end end end end end end houseShop[cid] = getThingPos(item.uid) openShopWindow(cid, houseShopList[cid], onBuy, onSell) return true end function onUse(cid, item, frompos, item2, topos) if isHousetile(getThingPos(item.uid)) then if(not isHousetile(getThingPos(cid)))then basketWindow(cid, item) return true end end end [ 3 ] • Adicione a tag em data/actions/actions.xml <action itemid="1989" script="house_shop.lua"/> [ 4 ] • Adicione em data/events/events.xml: <event class="Player" method="onMoveItem" enabled="1"/> <event class="Player" method="onTradeRequest" enabled="1"/> [ 5 ] • Em data/events/scripts ... procure pelo arquivo player.lua e substitua essa parte: Spoiler função do Jogador: OnMoveItem (item, conta, fromPosition, toPosition) return true final Por esta: Spoiler function Player:onMoveItem(item, count, fromPosition, toPosition) function isHousetile(position) local t = Tile(position) if t == nil then return false end return t:hasFlag(TILESTATE_HOUSE) end if isHousetile(item:getPosition()) then -- yup, it's a housetile if self:getAccountType() == ACCOUNT_TYPE_GOD and self:getGroup():getAccess() then -- is server admin return true end if Tile(item:getPosition()):getHouse():getOwnerGuid() == self:getGuid() then -- is house owner return true end if isHousetile(self:getPosition()) then -- is inside a house return true end -- random player self:sendCancelMessage("Sorry, not possible.") return false end return true end [ 6 ] • Em data/events/scripts/player.lua, adicione isso: Spoiler function Player:onTradeRequest(target, item) if isHousetile(item:getPosition()) then -- is this a house if self:getAccountType() == ACCOUNT_TYPE_GOD and self:getGroup():getAccess() then -- is server admin return true end if Tile(item:getPosition()):getHouse():getOwnerGuid() == self:getGuid() then -- is house owner return true end if isHousetile(self:getPosition()) then -- is inside a house return true end -- random player self:sendCancelMessage("This item doesn't belong to you.") return false end return true end [ 7 ] • Em data/creaturescripts/scripts/login.lua, adicione isso acima de return true: Spoiler home_market_spend = 0 home_market_items = {} home_market_items_msg = "" for i = 1, 30 do -- don't let them send milions of trash and then get it at once! local a = db.storeQuery("SELECT * FROM `onlogin_sendtoinbox` WHERE `player_id` = " .. getPlayerGUID(cid) .. " LIMIT 1") if a then local it_id = Player(cid):getInbox():addItem(result.getDataInt(a, "itemtype"), result.getDataInt(a, "count"), true, 1) it_id:setAttribute(1, result.getDataInt(a, "actionid")) it_id:setAttribute(4, result.getDataString(a, "description")) it_id:setAttribute(8, result.getDataString(a, "text")) it_id:setAttribute(32, getPlayerNameByGUID(result.getDataInt(a, "writer_guid"))) it_id:setAttribute(16, getPlayerNameByGUID(result.getDataInt(a, "written_at"))) home_market_spend = home_market_spend + result.getDataInt(a, "price") table.insert(home_market_items, {getItemName(result.getDataInt(a, "itemtype")), result.getDataInt(a, "count")}) db.query("DELETE FROM `onlogin_sendtoinbox` WHERE `player_id` = " .. getPlayerGUID(cid) .. " LIMIT 1") else break end end if #home_market_items > 0 then for i = 1, #home_market_items do home_market_items_msg = home_market_items_msg .. i_ar(home_market_items[i][1], home_market_items[i][2]) .. " " .. i_n(home_market_items[i][1], home_market_items[i][2]) if #home_market_items ~= 1 and i ~= #home_market_items then home_market_items_msg = home_market_items_msg .. ", " end end doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "[Store]: During your absence, players sold you " .. #home_market_items .. " item(s) for " .. home_market_spend .. " gold coins in total.") if #home_market_items < 31 then doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "[Store]: Items you bought: " .. home_market_items_msg) else doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "[Store]: Check your inbox to see items you received.") end end Créditos: zbizu É isso pessoal, só repassei, espero que ajude alguém, abração! Editado Novembro 14, 2018 6 anos por luanluciano93 (veja o histórico de edições)
Postado Maio 6, 2014 11 anos Muito daora esse negócio de inbox. Vou dar uma nos novos métodos do TFS 1.0 e ver se dá alguma ideia daora :B
Postado Outubro 14, 2014 10 anos CREATE TABLE IF NOT EXISTS `onlogin_sendtoinbox` (`player_id` int(11) NOT NULL DEFAULT '0',`itemtype` smallint(6) NOT NULL DEFAULT '0',`count` smallint(5) NOT NULL DEFAULT '0',`price` bigint(20) unsigned NOT NULL DEFAULT '0',`actionid` bigint(20) unsigned NOT NULL DEFAULT '0',`description` varchar(255) NOT NULL DEFAULT '',`text` varchar(1023) NOT NULL DEFAULT '',`writer_guid` int(11) NOT NULL DEFAULT 0,`written_at` bigint(20) NOT NULL,FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE) ENGINE=InnoDB n funcionou na minha data base
Participe da conversa
Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.