• 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!
  • New resources must be posted under Resources tab. A discussion thread will be created automatically, you can't open threads manually anymore.

NPC (beta release)NPC that sell players items

Gesior.pl

Mega Noob&LOL 2012
Senator
Joined
Sep 18, 2007
Messages
2,983
Solutions
102
Reaction score
3,430
Location
Poland
GitHub
gesior
Someone posted good idea for NPC. I tried to make this NPC.
Player can give this NPC items and set price for each item type.
Other player can come and say:
offer of Player Name - show offer of player with nick XX in 'trade' window
search Item Name - show 5 cheapest offers of item with name XX in form:
19:59 Cheapest offers of stone skin amulet:
50 gp (charges: 15) - Banatoorooo
1000000 gp (charges: 5) - Banatoorooo
All commands and how to use NPC say when player say "how to use":
19:59 GOD Gesior [150]: how to use
19:59 Shopper: What you want to do? Say {add my item to offer}, {get my item from offer}, {check how much money from items I have}, {get my cash from items}, {change price ofitem in offer}, {buy item of other player} or {search item}.
19:59 GOD Gesior [150]: add my item to offer
19:59 Shopper: First put your item in left hand (under BP slot), then say {add item xx} where xx is number of items that you want add to offer, then NPC will ask you for price, say{price yy}, where yy is price for 1 item.

-----------------------------------
It's beat version for tests only. Work with TFS0.2pl16 (tibia 8.3) and my modified .exe file (fixed one bug with NPC trade window, but we must wait for official release of new TFS 0.2 with NPC system fixed).
NPC .xml file:
PHP:
<?xml version="1.0" encoding="UTF-8"?>
<npc name="Shopper" script="data/npc/scripts/shopper.lua" walkinterval="2000" floorchange="0">
	<health now="100" max="100"/>
	<look type="290" head="39" body="122" legs="125" feet="57" addons="0"/>
	<parameters />
</npc>
NPC .lua script:
Code:
local keywordHandler = KeywordHandler:new()
local npcHandler = NpcHandler:new(keywordHandler)
NpcSystem.parseParameters(npcHandler)
shop_offers = {}
shop_last_item = {}
function onCreatureAppear(cid)		npcHandler:onCreatureAppear(cid)		end
function onCreatureDisappear(cid)	npcHandler:onCreatureDisappear(cid)		end
function onCreatureSay(cid, type, msg)	npcHandler:onCreatureSay(cid, type, msg)	end
function onThink()			npcHandler:onThink()				end

function creatureSayCallback(cid, type, msg)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	npcHandler:say('I don\'t understand. Ask me for {how to use} to get available actions.', cid)
end

function onBuyItemNPC(cid, itemid, subType, amount)
	if(NPCHANDLER_CONVBEHAVIOR ~= CONVERSATION_DEFAULT) then
		npcHandler.talkStart[cid] = os.time()
	else
		npcHandler.talkStart = os.time()
	end
	local offers = shop_offers[cid]
	local item = {id=0}
	for i = 1, #offers do
		print('test: ' .. offers[i].itemid .. ' = ' .. itemid .. ' : ' .. offers[i].subType .. ' = ' .. subType)
		if itemid == offers[i].itemid and subType == offers[i].subType then
			item = getItemWithId(offers[i].id)
			item = getItemWithItemId(offers[i].name, offers[i].itemid, offers[i].subType)
		end
	end
	if (not (item.id > 0)) then
		npcHandler:say('This item is not available in this player offer.', cid)
		return true
	end
	local amount2 = amount
	if amount2 > item.count then
		amount2 = item.count
	end
	if item.name == getCreatureName(cid) then
		local boughtItems, i = addPlayerItemFromShop(cid, item.itemid, amount2, item.subType)
		if(i < amount) then
			if(i > 0) then
				removeItemsFromOffer(item.name, item.itemid, item.subType, i)
				if amount == amount2 then
					npcHandler:say('Here you are your ' .. i .. ' of requested ' .. amount .. ' ' .. item.item_name .. ', because you do not have enought capacity for all.', cid)
				else
					npcHandler:say('Here you are your ' .. i .. ' of requested ' .. amount .. ' ' .. item.item_name .. ', because I do not have more your items of this type.', cid)
					closeShopWindow(cid)
				end
			else
				npcHandler:say('You do not have capacity for this item.', cid)
			end
		else
			removeItemsFromOffer(item.name, item.itemid, item.subType, i)
			npcHandler:say('Here you are your ' .. amount .. ' ' .. item.item_name .. '.', cid)
		end
	else
		if (getPlayerMoney(cid) < amount * item.price) then
			if(amount == 1) then
				npcHandler:say(item.item_name .. ' cost ' .. item.price .. ' gp, you got only ' .. getPlayerMoney(cid) .. ' gp.', cid)
			else
				npcHandler:say(amount .. ' ' .. item.item_name ..'s cost ' .. amount * item.price .. ' gp, you got only ' .. getPlayerMoney(cid) .. ' gp.', cid)
			end
			return true
		end
		--print(amount2 .. "<<amount2 || " .. amount .. " < amount || count > " .. item.count)
		local boughtItems, i = addPlayerItemFromShop(cid, item.itemid, amount2, item.subType)
		if(i < amount) then
			if(i > 0) then
				removeItemsFromOffer(item.name, item.itemid, item.subType, i)
				doPlayerRemoveMoney(cid, i * item.price)
				setCash(name, getCash(name)+i * item.price)
				if amount == amount2 then
					npcHandler:say('Here you are ' .. i .. ' of requested ' .. amount .. ' ' .. item.item_name .. ' for ' .. i * item.price .. ' gp, because you do not have enought capacity for all.', cid)
				else
					npcHandler:say('Here you are ' .. i .. ' of requested ' .. amount .. ' ' .. item.item_name .. ' for ' .. i * item.price .. ' gp, because I do not have more for sell.', cid)
					closeShopWindow(cid)
				end
				doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You bought " .. i .. "x " .. item.item_name .. ".")
			else
				npcHandler:say('You do not have capacity for this item.', cid)
			end
		else
			removeItemsFromOffer(item.name, item.itemid, item.subType, i)
			doPlayerRemoveMoney(cid, i * item.price)
			setCash(name, getCash(name)+i * item.price)
			npcHandler:say('Here you are ' .. amount .. ' ' .. item.item_name .. ' for ' .. i * item.price .. ' gp.', cid)
			doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You bought " .. i .. "x " .. item.item_name .. ".")
		end
	end
	return true
end

function onSellItemNPC(cid, itemid, subType, amount)
	return true
end

function showOfferOfPlayerNPC(cid, message, keywords, parameters, node)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	local name = ''
	if keywords[1] == 'my offer' or keywords[1] == 'get item' then
		name = getCreatureName(cid)
		npcHandler:say('You can take your items if you don\'t want sell them.', cid)
	else
		name = string.sub(message, 10)
		npcHandler:say('Offer of ' .. name .. '.', cid)
	end
	local offer = getOfferOfPlayer(name)
	shop_offers[cid] = offer
	local itemWindow = {}
	local item = {}
	for i = 1, #offer do
		if keywords[1] == 'my offer' or keywords[1] == 'get item' then
			item = {id = offer[i].itemid, buy = 1, sell = 0, subType = offer[i].subType, name = offer[i].item_name .. "(" .. offer[i].count .. ")"}
		else
			item = {id = offer[i].itemid, buy = offer[i].price, sell = 0, subType = offer[i].subType, name = offer[i].item_name .. "(" .. offer[i].count .. ")"}
		end
		table.insert(itemWindow, item)
	end
	openShopWindow(cid, itemWindow, function(cid, itemid, subType, amount) onBuyItemNPC(cid, itemid, subType, amount) end, function(cid, itemid, subType, amount) onSellItemNPC(cid, itemid, subType, amount) end)
	npcHandler:resetNpc()
	return true
end

function showOfferOfItemNPC(cid, message, keywords, parameters, node)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	local item_name = string.sub(message, 8)
	local offer = getOfferOfItem(item_name)
	local msg = ''
	if #offer == 0 then
		msg = "Can\'t find offer of item with name >" .. item_name .. "<"
	else
		msg = "Cheapest offers of " .. item_name .. ":\n"
		for i = 1, #offer do
			if offer[i].subType > 0 then
				msg = msg .. offer[i].price .. " gp (charges: " .. offer[i].subType .. ") - " .. offer[i].name
			else
				msg = msg .. offer[i].price .. " gp - " .. offer[i].name
			end
			if #offer ~= i then
				msg = msg .. "\n"
			end
		end
	end
	doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, msg)
	npcHandler:resetNpc()
	return true
end

function addItemToOfferNPC(cid, message, keywords, parameters, node)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	local number = 0
	for word in string.gmatch(tostring(message), "(%w+)") do
		if tostring(tonumber(word)) == word then
			number = tonumber(word)
		end
	end
	if (parameters.setprice == true) then
		local item_db = getItemWithItemId(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType)
		if number < 1 then
			number = 1
		end
		changePriceOfItem(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType, number)
		item_db = getItemWithItemId(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType)
		if item_db.subType > 0 then
			npcHandler:say('Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' (charges: ' .. item_db.subType .. ') in offer, price for each is now ' .. item_db.price .. ' gp. Say {set price} to change price of items.', cid)
		else
			npcHandler:say('Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' in offer, price for each is now ' .. item_db.price .. ' gp. Say {set price} to change price of items.', cid)
		end
		shop_last_item[cid] = {}
		npcHandler:resetNpc()
	elseif (parameters.setprice == false) then
		item_db = getItemWithItemId(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType)
		npcHandler:say('Ok. I do not change price for ' .. getItemName(shop_last_item[cid].itemid) ..'. It is ' .. item_db.price .. ' gp/each now.', cid)
		shop_last_item[cid] = {}
		npcHandler:resetNpc()
	else
		local item = getPlayerSlotItem(cid, 5)
		if (item.itemid == 0) then
			npcHandler:say('Your left hand (under BP slot) is empty.', cid)
			npcHandler:resetNpc()
			return true
		end
		if (isItemContainer(item.itemid) == TRUE and getContainerItem(uid, 0).uid > 0) then
			npcHandler:say('In your left hand (under BP slot) is not empty container. You can add to offer only item and empty containers.', cid)
			npcHandler:resetNpc()
			return true
		end
		if number < 1 then
			number = 1
		end
		if (item.type > 0 and not(isItemStackable(item.itemid) == TRUE)) then
			number = 1
			doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, 'You can\'t sell more then one ' .. getItemName(item.itemid) .. ' (charges: ' .. item.type .. '). Sorry.')
		end
		local to_remove = number
		shop_last_item[cid] = {itemid = item.itemid, subType = item.type}
		if (number > getPlayerItemCount(cid, item.itemid)) then
			number = getPlayerItemCount(cid, item.itemid)
		end
		if (isItemStackable(item.itemid) == TRUE) then
			item.type = 0
		end
		if (number == 1) and (isItemStackable(item.itemid) == TRUE) then
			doRemoveItem(item.uid, number)
		elseif (number == 1) and not(isItemStackable(item.itemid) == TRUE) then
			doRemoveItem(item.uid, 1)
		else
			doPlayerRemoveItem(cid, item.itemid, number)
		end
		addItemToOffer(getCreatureName(cid), item.itemid, item.type, number)
		item_db = getItemWithItemId(getCreatureName(cid), item.itemid, item.type)
		if item.type > 0 then
			npcHandler:say('Added ' .. number .. ' ' .. getItemName(item.itemid) .. ' (charges: ' .. item.type .. ') to your offer. Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' (charges: ' .. item_db.subType .. ') in offer, price for each is ' .. item_db.price .. '. Do you want to change price? Say {no} or {price xxx}, where xxx is number of gp.', cid)
		else
			npcHandler:say('Added ' .. number .. ' ' .. getItemName(item.itemid) .. ' to your offer. Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' in offer, price for each is ' .. item_db.price .. '. Do you want to change price? Say {no} or {price xxx}, where xxx is number of gp.', cid)
		end
	end
	return true
end

function setItemPriceNPC(cid, message, keywords, parameters, node)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	local number = 0
	for word in string.gmatch(tostring(message), "(%w+)") do
		if tostring(tonumber(word)) == word then
			number = tonumber(word)
		end
	end
	if (parameters.setprice == true) then
		local item_db = getItemWithItemId(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType)
		if number < 1 then
			number = 1
		end
		changePriceOfItem(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType, number)
		item_db = getItemWithItemId(getCreatureName(cid), shop_last_item[cid].itemid, shop_last_item[cid].subType)
		if item_db.subType > 0 then
			npcHandler:say('Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' (charges: ' .. item_db.subType .. ') in offer, price for each is now ' .. item_db.price .. ' gp. Say {set price} to change price of items.', cid)
		else
			npcHandler:say('Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' in offer, price for each is now ' .. item_db.price .. ' gp. Say {set price} to change price of items.', cid)
		end
		shop_last_item[cid] = {}
		npcHandler:resetNpc()
	else
		if number > 0 then -- player said offer ID
			local item_db = getItemWithId(number)
			if item_db.id == 0 then
				npcHandler:say('I don\'t know offer with ID >' .. number .. '<, say {set price} to view list of your items IDs.', cid)
				npcHandler:resetNpc()
				return true
			end
			if item_db.name ~= getCreatureName(cid) then
				npcHandler:say('It\'s not offer of your item, say {set price} to view list of your items IDs.', cid)
				npcHandler:resetNpc()
				return true
			end
			if item_db.subType > 0 then
				npcHandler:say('Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' (charges: ' .. item_db.subType .. ') in offer, price for each is ' .. item_db.price .. '. Do you want to change price? Say {no} or {price xxx}, where xxx is number of gp.', cid)
			else
				npcHandler:say('Actually you have ' .. item_db.count ..' ' .. item_db.item_name .. ' in offer, price for each is ' .. item_db.price .. '. Do you want to change price? Say {no} or {price xxx}, where xxx is number of gp.', cid)
			end
			shop_last_item[cid] = {itemid = item_db.itemid, subType = item_db.subType}
		else -- player ask for ID
			local offer = getOfferOfPlayer(getCreatureName(cid))
			if #offer == 0 then
				npcHandler:say('You don\'t have any item in offer. You can\'t change price.', cid)
			else
				doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "Your offers info:\n")
				for i = 1, #offer do
					if offer[i].subType > 0 then
						doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, offer[i].count .. "x " .. offer[i].item_name .. " (charges: " .. offer[i].subType .. ") - price: " .. offer[i].price .. " - offer ID: " .. offer[i].id )
					else
						doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, offer[i].count .. "x " .. offer[i].item_name .. " - price: " .. offer[i].price .. " - offer ID: " .. offer[i].id )
					end
				end
				npcHandler:say('To change price of item say {set price xx}. Where xx is ID of item.', cid)
			end
			npcHandler:resetNpc()
		end
	end
	return true
end

function getCashBalanceFromItemsNPC(cid, message, keywords, parameters, node)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	npcHandler:say('I have ' .. getCash(getCreatureName(cid)) .. ' gp for you.', cid)
	return true
end

function getCashFromItemsNPC(cid, message, keywords, parameters, node)
	if(not npcHandler:isFocused(cid)) then
		return false
	end
	local player_cash = getCash(getCreatureName(cid))
	if player_cash > 0 then
		if doPlayerAddMoney(cid, cost) ~= TRUE then
			npcHandler:say('I can\'t give you cash. Try again.', cid)
		else
			npcHandler:say(player_cash ..' for you. It was a pleasure doing business with you.', cid)
		end
	else
		npcHandler:say('I don\'t have cash for you.', cid)
	end
	return true
end


local sellitemprice1 = KeywordNode:new({'no'}, addItemToOfferNPC, {setprice = false})
local sellitemprice2 = KeywordNode:new({'price'}, addItemToOfferNPC, {setprice = true})
local sellitemprice3 = KeywordNode:new({'gp'}, addItemToOfferNPC, {setprice = true})

local setitemprice1 = KeywordNode:new({'no'}, setItemPriceNPC, {setprice = false})
local setitemprice2 = KeywordNode:new({'price'}, setItemPriceNPC, {setprice = true})
local setitemprice3 = KeywordNode:new({'gp'}, setItemPriceNPC, {setprice = true})

keywordHandler:addKeyword({'offer of'}, showOfferOfPlayerNPC, {})
keywordHandler:addKeyword({'search'}, showOfferOfItemNPC, {})
local node = keywordHandler:addKeyword({'add item'}, addItemToOfferNPC, {})
	node:addChildKeywordNode(sellitemprice1)
	node:addChildKeywordNode(sellitemprice2)
	node:addChildKeywordNode(sellitemprice3)
local node = keywordHandler:addKeyword({'set price'}, setItemPriceNPC, {setprice = false})
	node:addChildKeywordNode(setitemprice1)
	node:addChildKeywordNode(setitemprice2)
	node:addChildKeywordNode(setitemprice3)
local node = keywordHandler:addKeyword({'change price'}, setItemPriceNPC, {setprice = false})
	node:addChildKeywordNode(setitemprice1)
	node:addChildKeywordNode(setitemprice2)
	node:addChildKeywordNode(setitemprice3)
keywordHandler:addKeyword({'my offer'}, showOfferOfPlayerNPC, {})
keywordHandler:addKeyword({'get item'}, showOfferOfPlayerNPC, {})
keywordHandler:addKeyword({'balance'}, getCashBalanceFromItemsNPC, {})
keywordHandler:addKeyword({'get cash'}, getCashFromItemsNPC, {})
keywordHandler:addKeyword({'withdraw'}, getCashFromItemsNPC, {})
local node = keywordHandler:addKeyword({'how to use'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'What you want to do? Say {add my item to offer}, {get my item from offer}, {check how much money from items I have}, {get my cash from items}, {change price of item in offer}, {buy item of other player} or {search item}.'})
	node:addChildKeyword({'add my item to offer'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'First put your item in left hand (under BP slot), then say {add item xx} where xx is number of items that you want add to offer, then NPC will ask you for price, say {price yy}, where yy is price for 1 item.'})
	node:addChildKeyword({'get my item from offer'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Say {my offer} or {get item} to view list of your items, all items will have price 1 gp, but when you press "Buy" you will get your item for free.'})
	node:addChildKeyword({'check how mu'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Say {balance} to view how much money NPC has for you.'})
	node:addChildKeyword({'get my cash'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Say {get cash} or {withdraw} to get your cash from NPC.'})
	node:addChildKeyword({'change price of item in offer'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Say {change price} or {set price} to view list of your items, prices and offer IDs. Say {change price xx} or {set price xx}, where xx is item offer ID, then NPC will show you item name and ask for new price, say {price yy}, where yy is new price.'})
	node:addChildKeyword({'buy item of other player'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Say {offer of Xx Yy}, where Xx Yy is name of player. NPC will show you offer of this player in trade window.'})
	node:addChildKeyword({'search item'}, StdModule.say, {npcHandler = npcHandler, onlyFocus = true, text = 'Say {search Xxx Yyy}, where Xxx Yyy is name of item. Npc will show you few cheapest offers and names of players. That say {offer of Xxx}, where Xxx is name of player to view his offer and buy item.'})
npcHandler:setMessage(MESSAGE_GREET, "Greetings |PLAYERNAME|. I can trade your items with other players. Say {how to use} if you don\'t know commands.")

npcHandler:setCallback(CALLBACK_MESSAGE_DEFAULT, creatureSayCallback)
npcHandler:addModule(FocusModule:new())
In global.lua add functions:
Code:
-- shop system
dofile("./config.lua")
function getOfferOfPlayer(name)
	offer = {}
	env = assert(luasql.mysql())
	con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	result_items = assert(con:execute("SELECT `id`, `name`, `item_name`, `itemid`, `subType`, `count`, `price` FROM `ots_playersshopsystem` WHERE `name` = '" .. escapeString(name) .. "' AND `count` > '0' AND `itemid` != '66'"))
	item = result_items:fetch({}, "a")
	while item do
		table.insert(offer, {id = tonumber(item.id), name = tostring(item.name), item_name = tostring(item.item_name), itemid = tonumber(item.itemid), subType = tonumber(item.subType), count = tonumber(item.count), price = tonumber(item.price)})
		item = result_items:fetch(item, "a")
	end
	con:close()
	env:close()
	return offer
end

function getOfferOfItem(item_name)
	local offer = {}
    env = assert(luasql.mysql())
    con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
    result_items = assert(con:execute("SELECT `id`, `name`, `item_name`, `itemid`, `subType`, `count`, `price` FROM `ots_playersshopsystem` WHERE `item_name` = '" .. escapeString(item_name) .. "' AND `count` > '0' AND `itemid` != '66' ORDER BY `price` ASC LIMIT 5"))
    item = result_items:fetch({}, "a")
	while item do
		table.insert(offer, {id = tonumber(item.id), name = tostring(item.name), item_name = tostring(item.item_name), itemid = tonumber(item.itemid), subType = tonumber(item.subType), count = tonumber(item.count), price = tonumber(item.price)})
		item = result_items:fetch(item, "a")
	end
    con:close()
    env:close()
	return offer
end

function addItemToOffer(name, itemid, subType, count)
	if itemid == 0 then
		return false
	end
	env = assert(luasql.mysql())
    con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	local inDB_id = 0
	local inDB_count = 0
	local do_return = 0
    local result_offers = assert(con:execute("SELECT `id`, `count` FROM `ots_playersshopsystem` WHERE `name` = '" .. escapeString(name) .. "' AND `itemid` = '" .. itemid .. "' AND `subType` = '" .. subType .. "' AND `itemid` != '66'"))
    local offers = result_offers:fetch({}, "a")
    while offers do
		inDB_id = tonumber(offers.id)
		inDB_count = tonumber(offers.count)
	    offers = result_offers:fetch (offers, "a")
    end
	if inDB_id ~= 0 then
		assert(con:execute("UPDATE `ots_playersshopsystem` SET `count` = `ots_playersshopsystem`.`count` + " .. count .." WHERE `id` = '" .. inDB_id .. "' AND `subType` = '" .. subType .. "' AND `itemid` != '66'"))
	else
		assert(con:execute("INSERT INTO `tfs`.`ots_playersshopsystem` (`id`, `name`, `item_name`, `itemid`, `subType`, `count`, `price`) VALUES (NULL, '" .. escapeString(name) .. "', '" .. escapeString(getItemName(itemid)) .. "', '" .. itemid .. "', '" .. subType .. "', '" .. count .. "', 1000000)"))
	end
    con:close()
    env:close()
	return true
end

function removeItemsFromOffer(name, itemid, subType, count)
	if count == 0 or itemid == 0 then
		return false
	end
    env = assert(luasql.mysql())
    con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	assert(con:execute("UPDATE `ots_playersshopsystem` SET `count` = `ots_playersshopsystem`.`count` - " .. count .." WHERE `name` = '" .. escapeString(name) .. "' AND `itemid` = '" .. itemid .. "' AND `subType` = '" .. subType .. "' AND `itemid` != '66'"))
    con:close()
    env:close()
	return true
end

function changePriceOfItem(name, itemid, subType, price)
	if itemid == 0 or price == 0 then
		return false
	end
    env = assert(luasql.mysql())
    con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	assert(con:execute("UPDATE `ots_playersshopsystem` SET `price` = " .. price .." WHERE `name` = '" .. escapeString(name) .. "' AND `itemid` = '" .. itemid .. "' AND `subType` = '" .. subType .. "' AND `itemid` != '66'"))
    con:close()
    env:close()
	return true
end

function getItemWithId(id)
	item2 = {id=0}
	env = assert(luasql.mysql())
	con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	result_items = assert(con:execute("SELECT `id`, `name`, `item_name`, `itemid`, `subType`, `count`, `price` FROM `ots_playersshopsystem` WHERE `id` = '" .. id .. "' AND `count` > 0 AND `itemid` != '66'"))
	item = result_items:fetch({}, "a")
	while item do
		item2 = {id = tonumber(item.id), name = tostring(item.name), item_name = tostring(item.item_name), itemid = tonumber(item.itemid), subType = tonumber(item.subType), count = tonumber(item.count), price = tonumber(item.price)}
		item = result_items:fetch(item, "a")
	end
	con:close()
	env:close()
	return item2
end

function getItemWithItemId(name, itemid, subType)
	if itemid == 0 then
		return false
	end
	item2 = {id=0}
	env = assert(luasql.mysql())
	con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	result_items = assert(con:execute("SELECT `id`, `name`, `item_name`, `itemid`, `subType`, `count`, `price` FROM `ots_playersshopsystem` WHERE `name` = '" .. escapeString(name) .. "' AND `itemid` = '" .. itemid .. "' AND `subType` = '" .. subType .. "' AND `count` > 0 AND `itemid` != '66'"))
	item = result_items:fetch({}, "a")
	while item do
		item2 = {id = tonumber(item.id), name = tostring(item.name), item_name = tostring(item.item_name), itemid = tonumber(item.itemid), subType = tonumber(item.subType), count = tonumber(item.count), price = tonumber(item.price)}
		item = result_items:fetch(item, "a")
	end
	con:close()
	env:close()
	return item2
end

function getCash(name)
	env = assert(luasql.mysql())
    con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	local inDB_id = 0
	local inDB_count = 0
	local do_return = 0
    local result_offers = assert(con:execute("SELECT `id`, `count` FROM `ots_playersshopsystem` WHERE `name` = '" .. escapeString(name) .. "' AND `itemid` = '66'"))
    local offers = result_offers:fetch({}, "a")
    while offers do
		inDB_id = tonumber(offers.id)
		inDB_count = tonumber(offers.count)
	    offers = result_offers:fetch (offers, "a")
    end
	if inDB_id == 0 then
		assert(con:execute("INSERT INTO `tfs`.`ots_playersshopsystem` (`id`, `name`, `item_name`, `itemid`, `count`, `price`) VALUES ('', '" .. escapeString(name) .. "', 'Player Cash', '66', '0', '0')"))
	end
    con:close()
    env:close()
	return inDB_count
end

function setCash(name, count)
	env = assert(luasql.mysql())
    con = assert(env:connect(mysqlDatabase, mysqlUser, mysqlPass, mysqlHost, mysqlPort))
	assert(con:execute("UPDATE `ots_playersshopsystem` SET `count` = " .. count ..", `price` = " .. count .." WHERE `name` = '" .. escapeString(name) .. "' AND `itemid` = '66'"))
    con:close()
    env:close()
	return true
end

function addPlayerItemFromShop(cid, itemid, amount, subType)
	local amount = amount or 1
	local subType = subType or 0
	if(isItemStackable(itemid) == TRUE) then
		local item = doCreateItemEx(itemid, amount)
		local ret = doPlayerAddItemEx(cid, item)
		if(ret ~= RETURNVALUE_NOERROR) then
			return {}, 0
		end
		return {item}, amount
	end
	local items = {}
	local ret = 0
	local a = 0
	for i = 1, amount do
		items[i] = doCreateItemEx(itemid, subType)
		ret = doPlayerAddItemEx(cid, items[i])
		if(ret ~= RETURNVALUE_NOERROR) then
			break
		end
		a = a + 1
	end
	return items, a
end
My .exe file:
TFS83.exe
If you use your modified version of TFS 0.2 pl 16 engine, you must only replace your function (file npc.cpp):
PHP:
int32_t NpcScriptInterface::luaOpenShopWindow(lua_State* L)
{
   ...
}
With:
PHP:
int32_t NpcScriptInterface::luaOpenShopWindow(lua_State* L)
{
	//openShopWindow(cid, items, onBuy callback, onSell callback)
	ScriptEnviroment* env = getScriptEnv();
	Npc* npc = env->getNpc();
	if(!npc)
	{
		reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
		lua_pushnumber(L, LUA_ERROR);
		return 1;
	}

	int32_t sellCallback = -1;
	if(lua_isfunction(L, -1) == 0)
		lua_pop(L, 1); // skip it - use default value
	else
		sellCallback = popCallback(L);

	int32_t buyCallback = -1;
	if(lua_isfunction(L, -1) == 0)
		lua_pop(L, 1);
	else
		buyCallback = popCallback(L);

		if(lua_istable(L, -1) == 0)
		{
			reportError(__FUNCTION__, "item list is not a table.");
			lua_pushnumber(L, LUA_ERROR);
			return 1;
		}

		ShopInfo item;
		npc->shopItemList.clear();
		// first key
		lua_pushnil(L);
		while(lua_next(L, -2) != 0)
		{
			item.itemId = getField(L, "id");
			item.subType = getField(L, "subType");
			item.buyPrice = getField(L, "buy");
			item.sellPrice = getField(L, "sell");
			item.itemName = getFieldString(L, "name");
			npc->shopItemList.push_back(item);

			lua_pop(L, 1);
		}
		sortItems(npc->shopItemList);
	lua_pop(L, 1);

	Player* player = env->getPlayerByUID(popNumber(L));
	if(!player)
	{
		reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
		lua_pushnumber(L, LUA_ERROR);
		return 1;
	}

	player->closeShopWindow();

	npc->addShopPlayer(player);
	player->setShopOwner(npc, buyCallback, sellCallback);
	player->sendShop(npc->shopItemList);
	player->sendGoods(g_game.getMoney(player), player->parseGoods(npc->shopItemList));

	lua_pushnumber(L, LUA_NO_ERROR);
	return 1;
}
FOR TESTS ONLY
 
Last edited by a moderator:
Really nice, I saw that on a online game can't remember the name, anyway Great release gesior and without "By Gesior" on the tittle :p gratz :)

Edit: Gonna test it
 
First put your item in left hand (under BP slot)

is ur bp at the left o.0?
 
Back
Top