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
Now create a file on data/lib called 200-shop.lua and paste this:
Now go to data/talkactions/scripts and create a file called shop.lua and paste this:
Paste this on talkactions.xml
How to add items in shop?... Example:
This command will add to shop a Backpack of Sudden Death Runes with 50x charges each one... How is that possible?!?
How to use?
And that's all![Smile :) :)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)
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.');
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