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

TalkAction Shop-System.

Joined
Apr 17, 2008
Messages
1,922
Solutions
1
Reaction score
188
Location
Venezuela
Here is a shop-system that i made like 1 month ago... it works via talkactions, note that i didn't added options to add/remove items from shop with a command because you can do it with the website or via phpMyAdmin.

So let's start..

First execute this with phpMyAdmin
SQL:
CREATE TABLE IF NOT EXISTS `shop_items` (
  `product_id` int(11) NOT NULL auto_increment,
  `product_name` text NOT NULL,
  `product_item` int(11) NOT NULL,
  `product_count` int(11) NOT NULL,
  `product_container` int(11) NOT NULL,
  `product_containerCount` int(11) NOT NULL,
  `product_type` int(11) NOT NULL,
  `product_price` int(11) NOT NULL,
  `product_desc` text NOT NULL,
  PRIMARY KEY  (`product_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=16 ;

CREATE TABLE IF NOT EXISTS `shop_history` (
  `product_id` int(11) NOT NULL,
  `product_name` text NOT NULL,
  `product_item` int(11) NOT NULL,
  `product_count` int(11) NOT NULL,
  `product_container` int(11) NOT NULL,
  `product_containerCount` int(11) NOT NULL,
  `product_type` int(11) NOT NULL,
  `product_price` int(11) NOT NULL,
  `product_desc` text NOT NULL,
  `product_buyer` int(11) NOT NULL,
  `purchase_date` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

ALTER TABLE accounts ADD credits int NOT NULL DEFAULT 0;

Now create a file on data/lib called 200-shop.lua and paste this:
Lua:
TYPE_ITEM = 1
TYPE_REMOVESKULL = 2
TYPE_CHANGENAME = 3
TYPE_OUTFIT = 4

timeBetweenNameChange = 30 * 24 * 60 * 60 --30 days

shop =
{
	productExists = function (productid)
		local query = db.getResult("select product_id from shop_items where product_id = " .. productid .. ";")
		return query:getID() ~= -1 and true or false
	end,

	getProductInfo = function (productid)
		local query = db.getResult("select * from shop_items where product_id = " .. productid .. ";")
		return query:getID() ~= -1 and
		{
			id = productid,
			name = query:getDataString("product_name"),
			item = query:getDataInt("product_item"),
			count = query:getDataInt("product_count"),
			container = query:getDataInt("product_container"),
			containerCount = query:getDataInt("product_containerCount"),
			type = query:getDataInt("product_type"),
			price = query:getDataInt("product_price"),
			desc = query:getDataString("product_desc"),
			info = "Transaction Id: " .. query:getDataInt("product_id") .. "\nName: " .. query:getDataString("product_name") .. "\n" .. (query:getDataInt("product_type") == TYPE_ITEM and "Item: " .. (query:getDataInt("product_item") > 0 and getItemNameById(query:getDataInt("product_item")) or "-") .. "\nCount: " .. (query:getDataInt("product_type") == TYPE_ITEM and query:getDataInt("product_count") or "-") .. "\n" or "") .. (query:getDataInt("product_container") > 0 and "\nContainer: " .. (isItemContainer(query:getDataInt("product_container")) and getItemNameById(query:getDataInt("product_container")) or "Not valid container... please report") .. "\nContainer slots: " .. query:getDataInt("product_containerCount") .. "\n" or "") .. "\nPrice: " .. query:getDataInt("product_price") .. "\nDesc: " .. query:getDataString("product_desc")
		} or false
	end,

	getAccountCredits = function (cid)
		local query = db.getResult("select credits from accounts where id = " .. getPlayerAccountId(cid) .. ";")
		if query:getID() ~= 1 then
			return query:getDataInt("credits")
		end
		return false
	end,

	buyItem = function (cid, productid)
		local cdt = shop.getAccountCredits(cid)
		if shop.productExists(productid) then
			local shopInfo = shop.getProductInfo(productid)
			if cdt and cdt >= shopInfo.price then
				if shopInfo.type == TYPE_ITEM then
					if shopInfo.container > 0 and shopInfo.containerCount > 0 then
						if not isItemContainer(shopInfo.container) then
							doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.")
							return print("Transaction id " .. productid .. " could not be executed, error with container " .. shopInfo.container .. ".") and false
						end
						if shop.playerDoPayment(cid, shopInfo) then
							local container =  doPlayerAddItem(cid, shopInfo.container, 1)
							for i = 1, shopInfo.containerCount do
								doAddContainerItem(container, shopInfo.item, shopInfo.count)
							end
							shop.addHistory(cid, shopInfo.id)
							return true
						else
							return doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.") and false
						end
					else
						if shop.playerDoPayment(cid, shopInfo) then
							local _query = db.executeQuery("insert into shop_transhistory (product_id, product_item, product_count, product_container, product_containerCount, product_type, product_price, product_desc, product_buyer, purchase_date) values (" .. productid .. ", " .. shopInfo.item .. ", " .. shopInfo.count .. ", " .. shopInfo.container .. ", " .. shopInfo.containerCount .. ", " .. shopInfo.type .. ", " .. shopInfo.price .. ", " .. db.escapeString(shopInfo.desc) .. ", " .. getPlayerGUID(cid) .. ", " .. db.escapeString(os.date()) .. ");")
							shop.addHistory(cid, shopInfo.id)
							return doPlayerAddItem(cid, shopInfo.item, shopInfo.count)
						else
							return doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.") and false
						end
					end
				elseif shopInfo.type == TYPE_REMOVESKULL then
					if not getTileInfo(getThingPos(cid)).pz then
						return doPlayerSendCancel(cid, "You need to be in protection zone to buy this product.") and false
					end
					if getCreatureSkullType(cid) >= SKULL_WHITE then
						if shop.playerDoPayment(cid, shopInfo) then
							local query_ = db.executeQuery("update killers set unjustified = 0 where id in(select kill_id from player_killers where player_id = " .. getPlayerGUID(cid) .. ")")
							shop.addHistory(cid, shopInfo.id)
							return query_ or false
						else
							return doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.") and false
						end
					else
						return doPlayerSendCancel(cid, "You are not white skull or higher.") and false
					end
				elseif shopInfo.type == TYPE_CHANGENAME then
					if not getTileInfo(getThingPos(cid)).pz then
						return doPlayerSendCancel(cid, "You need to be in protection zone to buy this product.") and false
					end
					local lastChange = db.getResult("select last_namechange from players where id = " .. getPlayerGUID(cid) .. ";")
					if lastChange:getID() ~= -1 then
						if os.time(t) - timeBetweenNameChange < lastChange:getDataInt("last_namechange") then
							return doPlayerSendCancel(cid, "You only can change your name every " .. timeBetweenNameChange / (24 * 60 * 60) .. " days.") and false
						end
						lastChange:free()
						if shop.playerDoPayment(cid, shopInfo) then
							shop.addHistory(cid, shopInfo.id)
							addEvent(doRemoveCreature, 5 * 1000, cid)
							doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You will be kicked in 5 seconds.")
							db.executeQuery("insert into bans (id, type, value, param, active, expires, added, admin_id, comment, reason, action, statement) values (null, 2, " .. getPlayerGUID(cid) .. ", 2, 1, -1, " .. os.time() .. ", 0, " .. db.escapeString("Bought " .. shopInfo.name) .. ", 0, 3, '');")
							db.executeQuery("insert into bans (id, type, value, param, active, expires, added, admin_id, comment, reason, action, statement) values (null, 3, " .. getPlayerAccountId(cid) .. ", 7, 1, " .. os.time() .. ", " .. os.time() .. ", 0, " .. db.escapeString("Bought " .. shopInfo.name) .. ", 0, 3, '');")
							db.executeQuery("update players set last_namechange = " .. os.time(t) .. " where id = " .. getPlayerGUID(cid) .. ";")
							return true
						else
							return doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.") and false
						end
					else
						return doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.") and false
					end
				elseif shopInfo.type == TYPE_OUTFIT then
					if shop.playerDoPayment(cid, shopInfo) then
						if canPlayerWearOutfit(cid, tonumber((getPlayerSex(cid) == 1 and string.sub(shopInfo.item, 1, 3) or string.sub(shopInfo.item, 3, 6)))) then
							return doPlayerAddOutfit(cid, tonumber((getPlayerSex(cid) == 1 and string.sub(shopInfo.item, 1, 3) or string.sub(shopInfo.item, 3, 6))), shopInfo.count) and shop.addHistory(cid, shopInfo.id)
						else
							return doPlayerSendCancel(cid, "You cannot wear this outfit.") and false
						end
					else
						return doPlayerSendCancel(cid, "There is a tecnical problem, please report it to a gamemaster.") and false
					end									
				end
			else
				return doPlayerSendCancel(cid, "You need " .. shopInfo.price .. " credits to buy this product.") and false
			end
		end
		return false
	end,
	
	getHistory = function ()
		local text = ""
		local query = db.getResult("select * from shop_history order by purchase_date;")
		local i = 0
		if query:getID() ~= -1 then
			while(true) do
				i = i + 1
				text = text .. "[" .. query:getDataString("purchase_date") .. "]>> Transaction Id: " .. query:getDataInt("product_id") .. ", Name: " .. query:getDataString("product_name") .. ", " .. (query:getDataInt("product_type") == TYPE_ITEM and "Item: " .. (query:getDataInt("product_item") > 0 and getItemNameById(query:getDataInt("product_item")) or "-") .. ", Count: " .. (query:getDataInt("product_type") == TYPE_ITEM and query:getDataInt("product_count") or "-") .. "," or "") .. (query:getDataInt("product_container") > 0 and " Container: " .. (isItemContainer(query:getDataInt("product_container")) and getItemNameById(query:getDataInt("product_container")) or "Not valid container... please report") .. ", Container slots: " .. query:getDataInt("product_containerCount") .. "," or "") .. " Price: " .. query:getDataInt("product_price") .. ", Desc: " .. query:getDataString("product_desc") .. ", Buyer: " .. getPlayerNameByGUID(query:getDataInt("product_buyer")) .. "\n\n"
				if not query:next() then text = text .. "Total of " .. i .. " transactions." break end
			end
		end
		return text ~= "" and text or "No History."
	end,

	getPlayerHistory = function (cid)
		local text = ""
		local query = db.getResult("select * from shop_history where product_buyer = " .. getPlayerGUID(cid) .. " order by purchase_date;")
		local i = 0
		if query:getID() ~= -1 then
			while(true) do
				i = i + 1
				text = text .. "[" .. query:getDataString("purchase_date") .. "] Transaction Id: " .. query:getDataInt("product_id") .. ", Name: " .. query:getDataString("product_name") .. ", " .. (query:getDataInt("product_type") == TYPE_ITEM and "Item: " .. (query:getDataInt("product_item") > 0 and getItemNameById(query:getDataInt("product_item")) or "-") .. ", Count: " .. (query:getDataInt("product_type") == TYPE_ITEM and query:getDataInt("product_count") or "-") .. "," or "") .. (query:getDataInt("product_container") > 0 and " Container: " .. (isItemContainer(query:getDataInt("product_container")) and getItemNameById(query:getDataInt("product_container")) or "Not valid container... please report") .. ", Container slots: " .. query:getDataInt("product_containerCount") .. "," or "") .. " Price: " .. query:getDataInt("product_price") .. ", Desc: " .. query:getDataString("product_desc") .. "\n\n"
				if not query:next() then text = text .. "Total of " .. i .. " transactions." break end
			end
		end
		return text ~= "" and text or "No History."
	end,

	getList = function ()
		local text = ""
		local query = db.getResult("select * from shop_items order by product_id;")
		if query:getID() ~= -1 then
			while(true) do
				text = text .. "[" .. query:getDataInt("product_id") .. "] Transaction Id: " .. query:getDataInt("product_id") .. ", Name: " .. query:getDataString("product_name") .. ", " .. (query:getDataInt("product_type") == TYPE_ITEM and "Item: " .. (query:getDataInt("product_item") > 0 and getItemNameById(query:getDataInt("product_item")) or "-") .. ", Count: " .. (query:getDataInt("product_type") == TYPE_ITEM and query:getDataInt("product_count") or "-") .. "," or "") .. (query:getDataInt("product_container") > 0 and " Container: " .. (isItemContainer(query:getDataInt("product_container")) and getItemNameById(query:getDataInt("product_container")) or "Not valid container... please report") .. ", Container slots: " .. query:getDataInt("product_containerCount") .. "," or "") .. " Price: " .. query:getDataInt("product_price") .. ", Desc: " .. query:getDataString("product_desc") .. "\n\n"
				if not query:next() then break end
			end
		end
		return text ~= "" and text or "The is not any product."
	end,

	playerDoPayment = function (cid, productuid)
		local query = db.executeQuery("update accounts set credits = credits - " .. productuid.price .. " where id = " .. getPlayerAccountId(cid) .. ";")
		return query or false
	end,

	addHistory = function (cid, productid)
		local shopInfo = shop.getProductInfo(productid)
		local _query = db.executeQuery("insert into shop_history (product_id, product_name, product_item, product_count, product_container, product_containerCount, product_type, product_price, product_desc, product_buyer, purchase_date) values (" .. productid .. ", " .. db.escapeString(shopInfo.name) .. ", " .. shopInfo.item .. ", " .. shopInfo.count .. ", " .. shopInfo.container .. ", " .. shopInfo.containerCount .. ", " .. shopInfo.type .. ", " .. shopInfo.price .. ", " .. db.escapeString(shopInfo.desc) .. ", " .. getPlayerGUID(cid) .. ", " .. db.escapeString(os.date()) .. ");")
		if not _query then
			doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "The transaction could not be added to the player-history.")
			print("Transaction could not be added to 'shop_history' (" .. productid .. ", " .. shopInfo.name .. ", " .. shopInfo.item .. ", " .. shopInfo.count .. ", " .. shopInfo.container ..", " .. shopInfo.containerCount .. ", " .. shopInfo.type .. ", " .. shopInfo.price .. ", " .. shopInfo.desc .. ", " .. getPlayerGUID(cid) .. ", " .. os.date() .. ")")
		end
		return true
	end
}

Now go to data/talkactions/scripts and create a file called shop.lua and paste this:
Lua:
function onSay(cid, words, param)

	param = string.explode(param, ",")
	if param[1] == "buy" then
		if tonumber(param[2]) and shop.productExists(tonumber(math.abs(param[2]))) then
			shopItem = shop.getProductInfo(tonumber(math.abs(param[2])))
			if shop.getAccountCredits(cid) < shopItem.price then
				return doPlayerSendCancel(cid, "You do not have enough credits to buy this item.")
			end

			if shop.buyItem(cid, shopItem.id) then
				if shopItem.type == TYPE_ITEM then
					if isItemContainer(shopItem.container) then
						doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You bought a " .. getItemNameById(shopItem.container) .. " with x" .. shopItem.containerCount * shopItem.count .. " " .. getItemNameById(shopItem.item) .. " by " .. shopItem.price .. " credits.")
					else
						doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You bought x" .. shopItem.count .. " " .. getItemNameById(shopItem.item) .. " by " .. shopItem.price .. " credits.")
					end
				elseif isInArray({TYPE_REMOVESKULL, TYPE_NAMECHANGE, TYPE_OUTFIT}, shopItem.type) then
					doPlayerSendTextMessage(cid, MESSAGE_INFO_DESCR, "You bought " .. shopItem.name .. " by " .. shopItem.price .. " credits.")
				end
				return doSendMagicEffect(getCreaturePosition(cid), CONST_ME_MAGIC_RED) and doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE, shop.getAccountCredits(cid) .. " credits left.")
			end
			return doSendMagicEffect(getCreaturePosition(cid), CONST_ME_POFF)
		else
			return doPlayerSendCancel(cid, "Invalid product id.")
		end
	elseif param[1] == "list" then
		return doShowTextDialog(cid, 1948, shop.getList())
	elseif param[1] == "history" then
		return doShowTextDialog(cid, 1948, shop.getPlayerHistory(cid))
	elseif param[1] == "allhistory" then
		if getPlayerGroupId(cid) > 3 then
			return doShowTextDialog(cid, 2195, shop.getHistory(cid))
		end
		return false
	elseif param[1] == "generate" then
		if getPlayerGroupId(cid) < 3 then
			return false
		end
		if param[2] == "" then
			return doPlayerSendCancel(cid, "No directory declared.")
		end

		local f = io.open(param[2], "a+")
		if f ~= nil then
			f:write(shop.getHistory())
			doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "Transactions History saved on " .. param[2])
			return f:close()
		else
			return doPlayerSendCancel(cid, "Invalid directory.")
		end
	elseif param[1] == "info" then
		if tonumber(param[2]) and shop.productExists(param[2]) then
			local shopInfo = shop.getProductInfo(param[2])
			return doShowTextDialog(cid, (shopInfo.type == TYPE_ITEM and shopInfo.item or 1948), shopInfo.info)
		else
			return doPlayerSendCancel(cid, "Invalid product id.")
		end 
	end
	return true
end

Paste this on talkactions.xml
XML:
	<talkaction words="!offer" case-sensitive="no" event="script" value="shop.lua"/>

How to add items in shop?... Example:
SQL:
insert into shop_items (product_id, product_name, product_item, product_count, product_container, product_containerCount, product_type, product_price, product_desc) values (null, 'Backpack of Sudden Death Runes', 2268, 50, 1988, 20, 1, 200, 'A backpack with 50x sudden death runes in each slot.');
This command will add to shop a Backpack of Sudden Death Runes with 50x charges each one... How is that possible?!?
SQL:
product_id = Autoincrement, you do not need to add value here, default = null.
product_name = The product name of course.
product_item = Item that will be sold, Example: 2268 = Sudden Death Rune.
product_count = Charges/Count for stackable items.
product_container = Will be the item sold in a container? To disable it use 0, if the container id is invalid (Item is not container) player will not buy the product and will get a message with the text "There is a tecnical problem."
product_containerCount = Container slots that will be filled, Example: 15 = Player will get a Backpack of Sudden Death Runes with 15 runes inside.
product_type = [1] = Item, [2] = Remove skull, [3] = Name Changer, [4] = Outfit
product_price = I think you know what it is.
product_desc = A more detailed description for the product, Example: "A super mega backpack of sudden death runes that will give you the power to kill anybody."

----

Now, to configure it for outfits, you need to put Male outfit + Female outfit on product_item, Example:

Warrior Outfit = Male: 134, Female: 142

So you will put on product_item: 134142 and you will put on product_count the addon that will be added, 0 = no addon, 1 = first addon, 2 = second addon, 3 = all addons.

---

To configure it for removeskull or changename, just change de product_type, product_name, product_price and product_desc.. other parameters do not need to be declared because it will not be displayed on the product list/info/history.
Note: Players who buy name changer will get namelock.


How to use?
  • !offer buy, productid --Will buy product id Ex: !offer buy, 15
  • !offer info, productid --Will get more info about product id E: !offer info, 15
  • !offer history --Player will see its transactions history.
  • !offer list --Player will see products availables.
  • !offer generate, directory --(GroupID >= 3) Staff member will generate a file with all transactions in server.

And that's all :)
 
To use premiumpoints only need modified this
Replace this
PHP:
getAccountCredits = function (cid)
		local query = db.getResult("select credits from accounts where id = " .. getPlayerAccountId(cid) .. ";")
		if query:getID() ~= 1 then
			return query:getDataInt("credits")
		end
		return false
	end,
For
PHP:
getAccountCredits = function (cid)
		local query = db.getResult("select premium_points from accounts where id = " .. getPlayerAccountId(cid) .. ";")
		if query:getID() ~= 1 then
			return query:getDataInt("premium_points") //not sure for this line!
		end
		return false
	end,

:D
 
Last edited:
doesn't work for me... appear an error in 200-shop.lua in the line 168 ,51 and in the shop.lua line 11
 
lol, you and your epic releases ! it pwnz
ht3.jpg
jh88.jpg
dh3.jpg
 
Its work with gesior ? and can use with gift? !buy Name Player,Name Item?
Thanks
 
Back
Top