From 94a3346acfe73b5caa9bee6c3ed3ca70bdead2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rodrigo=20Paix=C3=A3o?= Date: Mon, 12 May 2025 14:31:32 -0300 Subject: [PATCH] feat: new shop (based in store) (#1151) --- README.md | 2 +- modules/game_shop/changename.otui | 41 + modules/game_shop/game_shop.lua | 849 ++++++++++++++++++ modules/game_shop/game_shop.otmod | 9 + modules/game_shop/game_shop.otui | 649 +++++++++++++ modules/game_shop/gift.otui | 28 + modules/game_shop/giftcoins.otui | 148 +++ modules/game_shop/images/180_days.png | Bin 0 -> 1031 bytes modules/game_shop/images/30_days.png | Bin 0 -> 741 bytes modules/game_shop/images/360_days.png | Bin 0 -> 1243 bytes modules/game_shop/images/90_days.png | Bin 0 -> 914 bytes .../images/All_regular_Blessings.png | Bin 0 -> 4403 bytes .../images/Blood_of_the_Mountain.png | Bin 0 -> 4279 bytes .../images/Heart_of_the_Mountain.png | Bin 0 -> 4253 bytes modules/game_shop/images/Name_Change.png | Bin 0 -> 1147 bytes modules/game_shop/images/Sex_Change.png | Bin 0 -> 765 bytes modules/game_shop/images/Temple_Teleport.png | Bin 0 -> 1486 bytes .../game_shop/images/The_Embrace_of_Tibia.png | Bin 0 -> 3255 bytes .../game_shop/images/The_Fire_of_the_Suns.png | Bin 0 -> 3302 bytes .../images/The_Spark_of_the_Phoenix.png | Bin 0 -> 3268 bytes .../images/The_Spiritual_Shielding.png | Bin 0 -> 3239 bytes .../images/The_Wisdom_of_Solitude.png | Bin 0 -> 3267 bytes modules/game_shop/images/Twist_of_Fate.png | Bin 0 -> 2970 bytes modules/game_shop/images/arrow_down.png | Bin 0 -> 561 bytes modules/game_shop/images/arrow_right.png | Bin 0 -> 566 bytes modules/game_shop/images/categories.png | Bin 0 -> 11768 bytes modules/game_shop/images/coin.png | Bin 0 -> 508 bytes modules/game_shop/images/coin_second.png | Bin 0 -> 328 bytes .../game_shop/images/ex/00001[64x64x8BPP].png | Bin 0 -> 4051 bytes .../game_shop/images/ex/00002[64x64x8BPP].png | Bin 0 -> 3181 bytes .../game_shop/images/ex/00005[64x64x8BPP].png | Bin 0 -> 4976 bytes .../game_shop/images/ex/00010[64x64x8BPP].png | Bin 0 -> 2085 bytes .../game_shop/images/ex/00012[64x64x8BPP].png | Bin 0 -> 1460 bytes .../game_shop/images/ex/00013[64x64x8BPP].png | Bin 0 -> 3351 bytes .../game_shop/images/ex/00015[64x64x8BPP].png | Bin 0 -> 1747 bytes .../game_shop/images/ex/00017[64x64x8BPP].png | Bin 0 -> 4675 bytes .../game_shop/images/ex/00020[27x52x8BPP].png | Bin 0 -> 1335 bytes .../game_shop/images/ex/00021[64x64x8BPP].png | Bin 0 -> 9100 bytes .../game_shop/images/ex/00025[64x64x8BPP].png | Bin 0 -> 3424 bytes .../game_shop/images/ex/00026[64x64x8BPP].png | Bin 0 -> 2193 bytes .../game_shop/images/ex/00027[64x64x8BPP].png | Bin 0 -> 4471 bytes .../game_shop/images/ex/00029[64x64x8BPP].png | Bin 0 -> 2185 bytes .../game_shop/images/ex/00031[64x64x8BPP].png | Bin 0 -> 1224 bytes .../game_shop/images/ex/00036[64x64x8BPP].png | Bin 0 -> 2315 bytes .../game_shop/images/ex/00045[64x64x8BPP].png | Bin 0 -> 1435 bytes .../game_shop/images/ex/00051[64x64x8BPP].png | Bin 0 -> 2910 bytes .../game_shop/images/ex/00052[64x64x8BPP].png | Bin 0 -> 2082 bytes .../game_shop/images/ex/00053[64x64x8BPP].png | Bin 0 -> 1487 bytes .../game_shop/images/ex/00054[64x64x4BPP].png | Bin 0 -> 670 bytes .../game_shop/images/ex/00057[64x64x8BPP].png | Bin 0 -> 796 bytes .../game_shop/images/ex/00058[64x64x8BPP].png | Bin 0 -> 2253 bytes .../game_shop/images/ex/00060[64x64x8BPP].png | Bin 0 -> 1486 bytes .../game_shop/images/ex/00062[64x64x8BPP].png | Bin 0 -> 2616 bytes .../game_shop/images/ex/00063[64x64x4BPP].png | Bin 0 -> 735 bytes modules/game_shop/images/giftcoin.png | Bin 0 -> 308 bytes modules/game_shop/images/mount.png | Bin 0 -> 10623 bytes modules/game_shop/images/search.png | Bin 0 -> 11279 bytes .../creaturescripts/scripts/shopSERVER.lua | 361 -------- .../serverSIDE/data/scripts/game_shop.lua | 846 +++++++++++++++++ modules/game_shop/serverSIDE/server.txt | 67 +- modules/game_shop/shop.lua | 676 -------------- modules/game_shop/shop.otmod | 10 - modules/game_shop/shop.otui | 246 ----- modules/game_shop/transfer.otui | 80 -- 64 files changed, 2620 insertions(+), 1392 deletions(-) create mode 100644 modules/game_shop/changename.otui create mode 100644 modules/game_shop/game_shop.lua create mode 100644 modules/game_shop/game_shop.otmod create mode 100644 modules/game_shop/game_shop.otui create mode 100644 modules/game_shop/gift.otui create mode 100644 modules/game_shop/giftcoins.otui create mode 100644 modules/game_shop/images/180_days.png create mode 100644 modules/game_shop/images/30_days.png create mode 100644 modules/game_shop/images/360_days.png create mode 100644 modules/game_shop/images/90_days.png create mode 100644 modules/game_shop/images/All_regular_Blessings.png create mode 100644 modules/game_shop/images/Blood_of_the_Mountain.png create mode 100644 modules/game_shop/images/Heart_of_the_Mountain.png create mode 100644 modules/game_shop/images/Name_Change.png create mode 100644 modules/game_shop/images/Sex_Change.png create mode 100644 modules/game_shop/images/Temple_Teleport.png create mode 100644 modules/game_shop/images/The_Embrace_of_Tibia.png create mode 100644 modules/game_shop/images/The_Fire_of_the_Suns.png create mode 100644 modules/game_shop/images/The_Spark_of_the_Phoenix.png create mode 100644 modules/game_shop/images/The_Spiritual_Shielding.png create mode 100644 modules/game_shop/images/The_Wisdom_of_Solitude.png create mode 100644 modules/game_shop/images/Twist_of_Fate.png create mode 100644 modules/game_shop/images/arrow_down.png create mode 100644 modules/game_shop/images/arrow_right.png create mode 100644 modules/game_shop/images/categories.png create mode 100644 modules/game_shop/images/coin.png create mode 100644 modules/game_shop/images/coin_second.png create mode 100644 modules/game_shop/images/ex/00001[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00002[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00005[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00010[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00012[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00013[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00015[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00017[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00020[27x52x8BPP].png create mode 100644 modules/game_shop/images/ex/00021[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00025[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00026[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00027[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00029[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00031[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00036[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00045[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00051[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00052[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00053[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00054[64x64x4BPP].png create mode 100644 modules/game_shop/images/ex/00057[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00058[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00060[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00062[64x64x8BPP].png create mode 100644 modules/game_shop/images/ex/00063[64x64x4BPP].png create mode 100644 modules/game_shop/images/giftcoin.png create mode 100644 modules/game_shop/images/mount.png create mode 100644 modules/game_shop/images/search.png delete mode 100644 modules/game_shop/serverSIDE/data/creaturescripts/scripts/shopSERVER.lua create mode 100644 modules/game_shop/serverSIDE/data/scripts/game_shop.lua delete mode 100644 modules/game_shop/shop.lua delete mode 100644 modules/game_shop/shop.otmod delete mode 100644 modules/game_shop/shop.otui delete mode 100644 modules/game_shop/transfer.otui diff --git a/README.md b/README.md index 2cb35e021..79d145775 100644 --- a/README.md +++ b/README.md @@ -398,7 +398,7 @@ Beyond of it's flexibility with scripts, otclient comes with tons of other featu Layout based on tibia 13 by @marcosvf132 - by [@marcosvf132](https://github.com/marcosvf132) - - Game_shop v8 + - Game_shop based in Store by [@Oskar1121](https://github.com/Oskar1121/Store) and modified/fixed by [@Nottinghster](https://github.com/Nottinghster/) - Minimap WorldTime - tfs c++(old): `void ProtocolGame::sendWorldTime()` diff --git a/modules/game_shop/changename.otui b/modules/game_shop/changename.otui new file mode 100644 index 000000000..8f716aba8 --- /dev/null +++ b/modules/game_shop/changename.otui @@ -0,0 +1,41 @@ +MainWindow + size: 400 125 + !text: 'Enter New Character Name' + @onEnter: modules.game_shop.confirmChangeName() + + Button + id: buttonCancel + anchors.bottom: parent.bottom + anchors.right: parent.right + !text: 'Cancel' + width: 64 + @onClick: modules.game_shop.cancelChangeName() + + Button + id: buttonConfirm + anchors.bottom: parent.bottom + anchors.right: prev.left + margin-right: 13 + !text: 'Ok' + width: 64 + @onClick: modules.game_shop.confirmChangeName() + + HorizontalSeparator + anchors.bottom: prev.top + anchors.right: parent.right + anchors.left: parent.left + margin-bottom: 10 + + Label + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + text-align: top + !text: 'Please enter the new name for your character:' + + TextEdit + id: targetName + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin-top: 5 diff --git a/modules/game_shop/game_shop.lua b/modules/game_shop/game_shop.lua new file mode 100644 index 000000000..22f9831b6 --- /dev/null +++ b/modules/game_shop/game_shop.lua @@ -0,0 +1,849 @@ +local DONATION_URL = nil +local GAME_SHOP_CODE = 201 + +local categories = {} +local offers = {} +local history = {} + +local gameShopWindow = nil +local selected = nil +local selectedOffer = nil +local changeNameWindow = nil +local msgWindow = nil +local transferWindow = nil + +local premiumPoints = 0 +local premiumSecondPoints = -1 + +local CATEGORY_NONE = -1 +local CATEGORY_PREMIUM = 0 +local CATEGORY_ITEM = 1 +local CATEGORY_BLESSING = 2 +local CATEGORY_OUTFIT = 3 +local CATEGORY_MOUNT = 4 +local CATEGORY_EXTRAS = 5 + +local searchResultCategoryId = "Search Results" + +function init() + connect( + g_game, + { + onGameStart = create, + onGameEnd = destroy + } + ) + + ProtocolGame.registerExtendedOpcode(GAME_SHOP_CODE, onExtendedOpcode) + if g_game.isOnline() then + create() + end +end + +function terminate() + disconnect( + g_game, + { + onGameStart = create, + onGameEnd = destroy + } + ) + + ProtocolGame.unregisterExtendedOpcode(GAME_SHOP_CODE, onExtendedOpcode) + destroy() +end + +function onExtendedOpcode(protocol, code, buffer) + local json_status, json_data = + pcall( + function() + return json.decode(buffer) + end + ) + if not json_status then + g_logger.error("SHOP json error: " .. json_data) + return false + end + + local action = json_data["action"] + local data = json_data["data"] + if not action or not data then + return false + end + + if action == "fetchBase" then + onGameShopFetchBase(data) + elseif action == "fetchOffers" then + onGameShopFetchOffers(data) + elseif action == "points" then + onGameShopUpdatePoints(data) + elseif action == "history" then + onGameShopUpdateHistory(data) + elseif action == "msg" then + onGameShopMsg(data) + end +end + +function create() + if gameShopWindow then + return + end + gameShopWindow = g_ui.displayUI("game_shop") + gameShopWindow:hide() + + local protocolGame = g_game.getProtocolGame() + if protocolGame then + protocolGame:sendExtendedOpcode(GAME_SHOP_CODE, json.encode({action = "fetch", data = {}})) + end + createTransferWindow() +end + +function destroy() + if gameShopWindow then + gameShopWindow:destroy() + gameShopWindow = nil + end + + if msgWindow then + msgWindow:destroy() + msgWindow = nil + end + + if changeNameWindow then + changeNameWindow:destroy() + changeNameWindow = nil + end + + if transferWindow then + transferWindow:destroy() + transferWindow = nil + end + + selected = nil + selectedOffer = nil +end + +function onGameShopFetchBase(data) + for i = 1, #data.categories do + addCategory(data.categories[i]) + end + + DONATION_URL = data.url +end + +function hideTransferWindow() + if transferWindow then + transferWindow:hide() + end +end + +function show() + hideTransferWindow() + if not gameShopWindow then + return + end + + hideHistory() + gameShopWindow:show() + gameShopWindow:raise() + gameShopWindow:focus() +end + +function hide() + hideTransferWindow() + if gameShopWindow then + gameShopWindow:hide() + end +end + +function showHistory() + deselect() + gameShopWindow:getChildById("offers"):hide() + gameShopWindow:getChildById("history"):show() +end + +function hideHistory() + gameShopWindow:getChildById("offers"):show() + gameShopWindow:getChildById("history"):hide() +end + +local entriesPerPage = 26 +local currentPage = 1 +local totalPages = 1 + +function updateHistory() + local historyPanel = gameShopWindow:getChildById("history") + local historyList = historyPanel:getChildById("list") + historyList:destroyChildren() + + local index = ((currentPage - 1) * entriesPerPage) + 1 + for i = index, math.min(#history, index + entriesPerPage - 1) do + local widget = g_ui.createWidget("HistoryWidget", historyList) + widget:getChildById("date"):setText(history[i].date) + widget:getChildById("price"):setText((history[i].price > 0 and "+" or "") .. comma_value(history[i].price)) + widget:getChildById("price"):setOn(history[i].price > 0) + widget:getChildById("coin"):setOn(history[i].isSecondPrice) + + if history[i].count > 1 then + widget:getChildById("description"):setText(history[i].count .. " " .. history[i].name) + else + widget:getChildById("description"):setText(history[i].name) + end + end + + historyPanel:getChildById("pageLabel"):setText("Page " .. currentPage .. "/" .. totalPages) +end + +function onGameShopUpdateHistory(historyList) + -- date + -- price + -- name + -- count + currentPage = 1 + history = historyList + totalPages = math.max(1, math.ceil(#history / entriesPerPage)) + + local historyPanel = gameShopWindow:getChildById("history") + updateHistory() + historyPanel:getChildById("nextPageButton"):setVisible(totalPages > 1) +end + +function prevPage() + if currentPage == 1 then + return true + end + + currentPage = currentPage - 1 + + local historyPanel = gameShopWindow:getChildById("history") + updateHistory() + + historyPanel:getChildById("nextPageButton"):setVisible(currentPage < totalPages) + historyPanel:getChildById("prevPageButton"):setVisible(currentPage > 1) +end + +function nextPage() + if currentPage == totalPages then + return true + end + + currentPage = currentPage + 1 + + local historyPanel = gameShopWindow:getChildById("history") + updateHistory() + + historyPanel:getChildById("nextPageButton"):setVisible(currentPage < totalPages) + historyPanel:getChildById("prevPageButton"):setVisible(currentPage > 1) +end + +function deselect() + if selected then + selected:getChildById("button"):setChecked(false) + local arrow = selected:getChildById("selectArrow") + if arrow then + arrow:hide() + end + + if not selected:getChildById("subCategories") then + selected = selected:getParent():getParent() + selected:getChildById("expandArrow"):show() + end + + selected:setHeight(22) + selected:getChildById("subCategories"):hide() + end +end + +function comma_value(n) + local left, num, right = string.match(n, "^([^%d]*%d)(%d*)(.-)$") + return left .. (num:reverse():gsub("(%d%d%d)", "%1,"):reverse()) .. right +end + +function buyPoints() + g_platform.openUrl(DONATION_URL) +end + +function onGameShopFetchOffers(data) + -- parent + -- name + -- id + -- price + -- isSecondPrice + -- count + -- description + -- categoryId + offers[data.category] = data.offers + if not selected and data.category == "Premium Time" then + select(gameShopWindow:getChildById("categoriesList"):getChildren()[1]:getChildById("button")) + end +end + +function addCategory(data) + -- title + -- parent + -- iconId + -- categoryId + -- description + + categories[data.title] = data + + local categoriesList = gameShopWindow:getChildById("categoriesList") + local category + if data.parent then + local parentPanel = categoriesList:getChildById(data.parent) + category = g_ui.createWidget("ShopSubCategory", parentPanel:getChildById("subCategories")) + parentPanel:getChildById("expandArrow"):show() + else + category = g_ui.createWidget("ShopCategory", categoriesList) + end + + category:setId(data.title) + category:getChildById("button"):setIconClip(data.iconId * 13 .. " 0 13 13") + category:getChildById("name"):setText(data.title) +end + +function onGameShopUpdatePoints(data) + premiumPoints = tonumber(data.points) + premiumSecondPoints = tonumber(data.secondPoints) + local pointsWidget = gameShopWindow:getChildById("balance"):getChildById("value") + pointsWidget:setText(comma_value(premiumPoints)) + + local balanceSecondWidget = gameShopWindow:getChildById("balanceSecond") + if premiumSecondPoints ~= -1 then + balanceSecondWidget:getChildById("value"):setText(comma_value(premiumSecondPoints)) + balanceSecondWidget:show() + balanceSecondWidget:setWidth(105) + balanceSecondWidget:setMarginLeft(6) + transferWindow.taskPointsLabelCoin:show() + transferWindow.taskPointsAmountScrollbar:show() + transferWindow.taskPointsCoin:show() + transferWindow.taskPointsBalance:show() + transferWindow.taskPointsBalance:setText(tr("Transferable Task points: ") .. comma_value(premiumSecondPoints)) + transferWindow.taskPointsAmountScrollbar:setMaximum(premiumSecondPoints) + else + balanceSecondWidget:hide() + balanceSecondWidget:setWidth(1) + balanceSecondWidget:setMarginLeft(0) + transferWindow.taskPointsBalance:hide() + transferWindow.taskPointsAmountLabel:hide() + transferWindow.taskPointsLabelCoin:hide() + transferWindow.taskPointsAmountScrollbar:hide() + transferWindow.taskPointsCoin:hide() + end + + transferWindow.coinsBalance:setText(tr("Transferable Tibia Coins: ") .. comma_value(premiumPoints)) + transferWindow.coinsAmountScrollbar:setMaximum(premiumPoints) +end + +function select(self, ignoreSearch) + hideHistory() + if not ignoreSearch then + eraseSearchResults() + end + + local selfParent = self:getParent() + local panel = selfParent:getChildById("subCategories") + if panel then + deselect() + selected = selfParent + + if panel:getChildCount() > 0 then + panel:show() + selfParent:setHeight((panel:getChildCount() + 1) * 22) + selfParent:getChildById("expandArrow"):hide() + select(panel:getChildren()[1]:getChildById("button")) + else + self:setChecked(true) + end + else + if selected then + selected:getChildById("button"):setChecked(false) + + local arrow = selected:getChildById("selectArrow") + if arrow then + arrow:hide() + end + end + + selected = selfParent + + self:setChecked(true) + selfParent:getChildById("selectArrow"):show() + end + + showOffers(selfParent:getId()) +end + +function selectOffer(self) + if selectedOffer then + selectedOffer:setChecked(false) + end + + self:setChecked(true) + selectedOffer = self + + updateDescription(self) +end + +function showOffers(id) + local offersCache = offers[id] + if not offersCache then + return + end + + local currentOutfit = g_game.getLocalPlayer():getOutfit() + local offersPanel = gameShopWindow:getChildById("offers") + local offersList = offersPanel:getChildById("offersList") + offersList:destroyChildren() + + for i = 1, #offersCache do + local widget = offersList:getChildById(offersCache[i].name) + local price = offersCache[i].price + if widget then + local additionalPriceWidget = widget:getChildById("additionalPrice") + additionalPriceWidget:getChildById("coin"):setOn(offersCache[i].isSecondPrice) + additionalPriceWidget:getChildById("value"):setText(comma_value(price)) + additionalPriceWidget:show() + + local additionalCountWidget = widget:getChildById("additionalCount") + additionalCountWidget:setText(offersCache[i].count .. "x") + additionalCountWidget:show() + + widget:getChildById("count"):show() + widget.additionalPriceValue = price + widget.additionalIsSecondPrice = isSecondPrice + widget.additionalCountValue = offersCache[i].count + + if i == 2 then + selectOffer(widget) + end + else + local widget = g_ui.createWidget("OfferWidget", offersList) + local priceWidget = widget:getChildById("price") + priceWidget:getChildById("coin"):setOn(offersCache[i].isSecondPrice) + priceWidget:getChildById("value"):setText(comma_value(price)) + + widget:getChildById("name"):setText(offersCache[i].name) + widget:getChildById("count"):setText(offersCache[i].count .. "x") + widget:setId(offersCache[i].name) + widget.data = offersCache[i] + widget.categoryId = id + + local imagePanel = widget:getChildById("imagePanel") + + if type(offersCache[i].id) == "string" then + local image = imagePanel:getChildById("image") + image:show() + image:setImageSource("/game_shop/images/" .. offersCache[i].id) + elseif type(offersCache[i].id) == "number" then + local categoryId = offersCache[i].categoryId + widget.offerCategoryId = categoryId + if categoryId == CATEGORY_ITEM then + local item = imagePanel:getChildById("item") + item:show() + item:setItemId(offersCache[i].id) + widget:getChildById("count"):show() + elseif categoryId == CATEGORY_OUTFIT then + local outfit = imagePanel:getChildById("outfit") + currentOutfit.type = offersCache[i].id + outfit:show() + outfit:setOutfit(currentOutfit) + elseif categoryId == CATEGORY_MOUNT then + local mount = imagePanel:getChildById("mount") + mount:show() + mount:setOutfit({type = offersCache[i].id}) + end + end + + if i == 1 then + selectOffer(widget) + end + end + end +end + +function updateDescription(self) + local offersPanel = gameShopWindow:getChildById("offers") + local offerDetails = offersPanel:getChildById("offerDetails") + offerDetails:show() + offerDetails:getChildById("name"):setText(self.data.name) + + local descriptionPanel = offerDetails:getChildById("description") + local widget = descriptionPanel:getChildren()[1] + if not widget then + widget = g_ui.createWidget("OfferDescripionLabel", descriptionPanel) + end + + local description = categories[self.categoryId].description + if not description or description == "" then + description = self.data.description + end + + widget:setText(description) + + local buyButton = offerDetails:getChildById("buyButton") + local priceWidget = offerDetails:getChildById("price") + local additionalBuyButton = offerDetails:getChildById("additionalBuyButton") + local additionalPriceWidget = offerDetails:getChildById("additionalPrice") + + priceWidget:setOn(self.data.isSecondPrice) + priceWidget:setText(comma_value(self.data.price)) + + local globalPoints = self.data.isSecondPrice and premiumSecondPoints or premiumPoints + priceWidget:setEnabled(self.data.price <= globalPoints) + buyButton:setEnabled(self.data.price <= globalPoints) + + if self.additionalPriceValue and self.additionalCountValue then + buyButton:setText("Buy " .. self.data.count) + + additionalPriceWidget:setEnabled(self.additionalPriceValue <= globalPoints) + additionalBuyButton:setText("Buy " .. self.additionalCountValue) + additionalBuyButton:show() + additionalBuyButton:setEnabled(self.additionalPriceValue <= globalPoints) + additionalBuyButton.price = self.additionalPriceValue + additionalBuyButton.count = self.additionalCountValue + buyButton.secondPrice = self.data.secondPrice + buyButton.price = self.data.price + buyButton.count = self.data.count + + additionalPriceWidget:setOn(self.data.isSecondPrice) + additionalPriceWidget:setText(comma_value(self.additionalPriceValue)) + additionalPriceWidget:show() + else + additionalBuyButton:hide() + + buyButton.secondPrice = nil + buyButton.price = nil + buyButton.count = nil + + buyButton:setText("Buy") + additionalPriceWidget:hide() + end + + local currentOutfit = g_game.getLocalPlayer():getOutfit() + local imagePanel = offerDetails:getChildById("imagePanel") + local image = imagePanel:getChildById("image") + local item = imagePanel:getChildById("item") + local outfit = imagePanel:getChildById("outfit") + local mount = imagePanel:getChildById("mount") + image:hide() + item:hide() + outfit:hide() + mount:hide() + if type(self.data.id) == "string" then + image:show() + image:setImageSource("/game_shop/images/" .. self.data.id) + elseif type(self.data.id) == "number" then + -- local categoryId = categories[self.categoryId].categoryId + local categoryId = self.offerCategoryId + if categoryId == CATEGORY_ITEM then + item:show() + item:setItemId(self.data.id) + elseif categoryId == CATEGORY_OUTFIT then + currentOutfit.type = self.data.id + outfit:show() + outfit:setOutfit(currentOutfit) + elseif categoryId == CATEGORY_MOUNT then + mount:show() + mount:setOutfit({type = self.data.id}) + end + end +end + +function onOfferBuy(self) + if not selectedOffer then + displayInfoBox("Error", "Something went wrong, make sure to select category and offer.") + return + end + + hide() + + local title = "Purchase Confirmation" + local msg + if self.count and self.count > 1 then + msg = + "Do you want to buy " .. + self.count .. "x " .. selectedOffer.data.name .. " for " .. comma_value(self.price) .. " points?" + else + msg = + "Do you want to buy " .. + selectedOffer.data.name .. " for " .. comma_value(selectedOffer.data.price) .. " points?" + end + + if selectedOffer.data.name == "Name Change" then + msgWindow = + displayGeneralBox( + title, + msg, + { + {text = "Yes", callback = changeName}, + {text = "No", callback = buyCanceled}, + anchor = AnchorHorizontalCenter + }, + changeName, + buyCanceled + ) + else + msgWindow = + displayGeneralBox( + title, + msg, + { + {text = "Yes", callback = buyConfirmed}, + {text = "No", callback = buyCanceled}, + anchor = AnchorHorizontalCenter + }, + buyConfirmed, + buyCanceled + ) + end + + if self.count and self.count > 1 then + msgWindow.count = self.count + msgWindow.price = self.price + else + msgWindow.count = selectedOffer.data.count + msgWindow.price = selectedOffer.data.price + end +end + +function buyConfirmed() + local protocolGame = g_game.getProtocolGame() + if protocolGame then + protocolGame:sendExtendedOpcode( + GAME_SHOP_CODE, + json.encode( + { + action = "purchase", + data = { + count = msgWindow.count, + price = msgWindow.price, + name = selectedOffer.data.name, + id = selectedOffer.data.id, + parent = selectedOffer.data.parent + } + } + ) + ) + end + + msgWindow:destroy() + msgWindow = nil +end + +function buyCanceled() + msgWindow:destroy() + msgWindow = nil + show() +end + +function changeName() + msgWindow:destroy() + msgWindow = nil + if changeNameWindow then + return + end + + changeNameWindow = g_ui.displayUI("changename") +end + +function confirmChangeName() + local protocolGame = g_game.getProtocolGame() + if protocolGame then + protocolGame:sendExtendedOpcode( + GAME_SHOP_CODE, + json.encode( + { + action = "purchase", + data = { + count = selectedOffer.data.count, + price = selectedOffer.data.price, + name = selectedOffer.data.name, + id = selectedOffer.data.id, + parent = selectedOffer.data.parent, + nick = changeNameWindow:getChildById("targetName"):getText() + } + } + ) + ) + + changeNameWindow:destroy() + changeNameWindow = nil + end +end + +function cancelChangeName() + changeNameWindow:destroy() + changeNameWindow = nil +end + +function onGameShopMsg(data) + local type = data.type + local text = data.msg + + local title = nil + local close = false + if type == "info" then + title = "Store Information" + close = data.close + elseif type == "error" then + title = "Store Error" + close = true + end + + if close then + hideHistory() + hide() + end + + displayInfoBoxWithCallback( + title, + text, + {{text = "Ok", callback = defaultCallback}}, + function() + show() + end + ) +end + +function displayInfoBoxWithCallback(title, message, callback) + local messageBox + local defaultCallback = function() + if callback then + show() + end + messageBox:ok() + end + + messageBox = + UIMessageBox.display( + title, + message, + {{text = "Ok", callback = defaultCallback}}, + defaultCallback, + defaultCallback + ) + return messageBox +end + +function changeCoinsAmount(value) + transferWindow:getChildById("coinsAmountLabel"):setText("Amount to gift: " .. comma_value(value)) +end + +function changeTaskPointsAmount(value) + transferWindow:getChildById("taskPointsAmountLabel"):setText("Amount to gift: " .. comma_value(value)) +end + +function confirmGiftCoins() + if not transferWindow then + return + end + + local protocolGame = g_game.getProtocolGame() + if protocolGame then + protocolGame:sendExtendedOpcode( + GAME_SHOP_CODE, + json.encode( + { + action = "transfer", + data = { + amount = tonumber(transferWindow.coinsAmountScrollbar:getValue()), + amountSecond = tonumber(transferWindow.taskPointsAmountScrollbar:getValue()), + target = transferWindow.recipient:getText() + } + } + ) + ) + transferWindow.recipient:setText("") + transferWindow.coinsAmountScrollbar:setValue(0) + transferWindow.taskPointsAmountScrollbar:setValue(0) + end +end + +function cancelGiftCoins() + if transferWindow then + transferWindow:hide() + show() + end +end + +function createTransferWindow() + if not transferWindow then + transferWindow = g_ui.displayUI("giftcoins") + transferWindow:hide() + end +end + +function toggle() + if not gameShopWindow then + return + end + + if gameShopWindow:isVisible() then + return hide() + end + + show() +end + +function toggleGiftCoins() + if transferWindow then + hide() + transferWindow:show() + transferWindow:raise() + transferWindow:focus() + transferWindow:setOn(premiumSecondPoints ~= -1) + end +end + +function onTypeSearch(self) + gameShopWindow:getChildById("searchButton"):setEnabled(#self:getText() > 2) +end + +function eraseSearchResults() + local widget = gameShopWindow:getChildById("categoriesList"):getChildById(searchResultCategoryId) + if widget then + if selected == widget then + selected = nil + end + widget:destroy() + end +end + +function onSearch() + local searchTextEdit = gameShopWindow:getChildById("searchTextEdit") + local text = searchTextEdit:getText() + + if #text < 3 then + return + end + + eraseSearchResults() + addCategory( + { + title = searchResultCategoryId, + iconId = 7, + categoryId = CATEGORY_NONE + } + ) + + offers[searchResultCategoryId] = {} + local results = {} + local searchTerm = text:lower() + + for categoryId, offerData in pairs(offers) do + for _, offer in pairs(offerData) do + if string.find(offer.name:lower(), searchTerm) then + table.insert(results, offer) + end + end + end + + for _, offer in ipairs(results) do + table.insert(offers[searchResultCategoryId], offer) + end + + local children = gameShopWindow:getChildById("categoriesList"):getChildren() + select(children[#children]:getChildById("button"), true) + searchTextEdit:clearText() +end diff --git a/modules/game_shop/game_shop.otmod b/modules/game_shop/game_shop.otmod new file mode 100644 index 000000000..bfc4cade9 --- /dev/null +++ b/modules/game_shop/game_shop.otmod @@ -0,0 +1,9 @@ +Module + name: game_shop + description: In-game shop + author: MatC, Nottinghster + website: None + sandboxed: true + scripts: [ game_shop ] + @onLoad: init() + @onUnload: terminate() \ No newline at end of file diff --git a/modules/game_shop/game_shop.otui b/modules/game_shop/game_shop.otui new file mode 100644 index 000000000..39da798e8 --- /dev/null +++ b/modules/game_shop/game_shop.otui @@ -0,0 +1,649 @@ +ShopCategory < FlatPanel + height: 22 + margin: 5 + focusable: false + + Button + id: button + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + height: 22 + icon-source: images/categories + icon-align: left + icon-offset: 6 0 + @onClick: modules.game_shop.select(self) + $checked: + image-clip: 0 46 22 23 + text-offset: 1 1 + + Label + id: name + anchors.fill: prev + text-offset: 24 0 + text-align: left + color: #C0C0C0 + + UIWidget + id: expandArrow + anchors.top: parent.top + anchors.right: parent.right + margin-top: 8 + margin-right: 8 + image-source: images/arrow_down + visible: false + + FlatPanel + id: subCategories + anchors.top: button.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + layout: verticalBox + visible: false + image-color: #A0A0A0 + +ShopSubCategory < UIWidget + height: 22 + focusable: false + + Button + id: button + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + margin-left: 14 + height: 22 + icon-source: images/categories + icon-align: left + icon-offset: 6 0 + @onClick: modules.game_shop.select(self) + $checked: + image-clip: 0 46 22 23 + text-offset: 1 1 + + Label + id: name + anchors.fill: prev + text-offset: 24 0 + text-align: left + color: #C0C0C0 + + UIWidget + id: selectArrow + anchors.verticalcenter: parent.verticalcenter + anchors.left: parent.left + margin-top: 1 + margin-left: 4 + image-source: images/arrow_right + visible: false + +HistoryLabel < Label + anchors.top: parent.top + anchors.bottom: parent.bottom + color: #C0C0C0 + text-offset: 3 0 + +HistoryWidget < UIWidget + height: 15 + background-color: alpha + focusable: false + $hover: + background-color: #555555 + $pressed: + background-color: #272727 + + $alternate: + background-color: #383838 + $alternate hover: + background-color: #2e2e2e + $alternate pressed: + background-color: #1d1d1d + + HistoryLabel + id: date + anchors.left: parent.left + margin-left: 1 + width: 150 + + VerticalSeparator + anchors.top: parent.top + anchors.left: prev.right + anchors.bottom: parent.bottom + + HistoryLabel + id: price + anchors.left: prev.right + text-align: right + margin-left: 1 + size: 70 21 + color: #D33C3C + $on: + color: #44AD25 + + UIWidget + id: coin + anchors.verticalcenter: parent.verticalcenter + anchors.left: prev.right + image-source: images/coin + margin-left: 6 + margin-bottom: 1 + phantom: true + $on: + image-source: images/coin_second + + VerticalSeparator + anchors.top: parent.top + anchors.left: prev.right + anchors.bottom: parent.bottom + margin-left: 3 + + HistoryLabel + id: description + anchors.left: prev.right + anchors.right: parent.right + margin-left: 1 + margin-right: 1 + height: 21 + +HistoryHeader < FlatPanel + anchors.top: parent.top + image-color: #A0A0A0 + text-align: left + text-offset: 3 0 + focusable: false + +OfferBuyButton < Button + anchors.top: prev.bottom + anchors.left: prev.left + anchors.right: prev.right + image-color: #3B86C7 + focusable: false + @onClick: modules.game_shop.onOfferBuy(self) + $disabled: + image-color: #1B3F5E + +OfferBuyPrice < FlatPanel + anchors.top: prev.bottom + anchors.left: prev.left + anchors.right: prev.right + margin-top: 4 + image-color: #A0A0A0 + height: 21 + text: 0 + text-align: center + color: #C0C0C0 + icon: images/coin + icon-size: 12 12 + icon-offset-x: 88 + icon-offset-y: 4 + focusable: false + $disabled: + color: #ff1f1f + $on: + icon: images/coin_second + +OfferDescripionLabel < Label + text-align: topLeft + text-wrap: true + text-vertical-auto-resize: true + color: #C0C0C0 + +ShopBalanceWidget < FlatPanel + image-color: #A0A0A0 + height: 21 + focusable: false + + Label + id: value + anchors.fill: parent + margin-right: 20 + text-align: right + text: 0 + color: #C0C0C0 + + UIWidget + id: coin + anchors.right: parent.right + anchors.verticalcenter: parent.verticalcenter + image-source: images/coin + margin-right: 3 + phantom: true + $on: + image-source: images/coin_second + +ShopBalanceSecondWidget < FlatPanel + image-color: #A0A0A0 + focusable: false + + Label + id: value + anchors.fill: parent + margin-right: 20 + text-align: right + text: 0 + color: #C0C0C0 + + UIWidget + anchors.right: parent.right + anchors.verticalcenter: parent.verticalcenter + image-source: images/coin_second + margin-right: 3 + phantom: true + +OfferPriceLabel < Label + anchors.left: parent.left + margin-right: 6 + margin-bottom: 2 + text-align: right + color: #C0C0C0 + visible: false + +OfferWidget < FlatPanel + height: 78 + margin-top: 5 + phantom: false + border: 0 white + focusable: false + @onClick: modules.game_shop.selectOffer(self) + $checked: + border: 2 white + + ShopBalanceWidget + id: price + size: 100 21 + anchors.right: parent.right + anchors.bottom: parent.bottom + margin: 4 + + ShopBalanceWidget + id: additionalPrice + size: 100 21 + anchors.right: prev.right + anchors.bottom: prev.top + margin-bottom: 4 + visible: false + + OfferPriceLabel + id: count + anchors.right: price.left + anchors.verticalcenter: price.verticalcenter + + OfferPriceLabel + id: additionalCount + anchors.right: additionalPrice.left + anchors.verticalcenter: additionalPrice.verticalcenter + + FlatPanel + id: imagePanel + anchors.left: parent.left + anchors.verticalcenter: parent.verticalcenter + margin-left: 4 + size: 70 70 + + UIWidget + id: image + anchors.fill: parent + margin: 3 + visible: false + phantom: true + + UICreature + id: outfit + anchors.fill: parent + margin-right: 6 + margin-bottom: 6 + visible: false + phantom: true + animate: true + + UICreature + id: mount + anchors.fill: parent + margin-right: 8 + margin-bottom: 8 + visible: false + phantom: true + animate: true + + UIItem + id: item + anchors.centerIn: parent + size: 34 34 + virtual: true + visible: false + phantom: true + + Label + id: name + anchors.top: parent.top + anchors.left: prev.right + anchors.right: parent.right + anchors.bottom: parent.bottom + margin: 8 + text-align: topLeft + text-wrap: true + color: #C0C0C0 + +MainWindow + id: shopWindow + !text: 'Store' + size: 776 533 + color: #909090 + @onEscape: modules.game_shop.hide() + @onEnter: modules.game_shop.onSearch() + + FlatPanel + id: categoriesList + anchors.top: parent.top + anchors.left: parent.left + anchors.bottom: parent.bottom + margin-bottom: 40 + width: 180 + image-color: #C0C0C0 + layout: verticalBox + focusable: false + + TextEdit + id: searchTextEdit + width: 150 + anchors.left: prev.left + anchors.right: prev.right + anchors.bottom: prev.bottom + margin: 7 + margin-right: 29 + placeholder: Type to search + placeholder-color: #667070 + color: #C0C0C0 + @onTextChange: modules.game_shop.onTypeSearch(self) + + Button + id: searchButton + anchors.top: prev.top + anchors.left: prev.right + anchors.bottom: prev.bottom + icon-source: images/search + icon-align: center + icon-size: 16 16 + icon-offset: 2 2 + icon-color: #FFFFFFFF + width: 22 + enabled: false + focusable: false + @onClick: modules.game_shop.onSearch() + $pressed: + icon-offset: 4 4 + $disabled: + icon-color: #C0C0C066 + + HorizontalSeparator + anchors.top: categoriesList.bottom + anchors.right: parent.right + anchors.left: parent.left + margin-top: 8 + + Button + id: buttonCancel + !text: 'Close' + width: 64 + anchors.right: parent.right + anchors.bottom: parent.bottom + color: #C0C0C0 + focusable: false + @onClick: modules.game_shop.hide() + + Button + id: historyButtonTop + !text: 'History' + width: 64 + anchors.top: prev.top + anchors.right: prev.left + margin-right: 5 + color: #C0C0C0 + focusable: false + @onClick: modules.game_shop.showHistory() + + ShopBalanceWidget + id: balance + size: 105 21 + anchors.left: parent.left + anchors.bottom: parent.bottom + + ShopBalanceSecondWidget + id: balanceSecond + size: 105 21 + margin-left: 6 + anchors.top: prev.top + anchors.left: prev.right + + Button + anchors.top: prev.top + anchors.left: prev.right + text: Get + text-align: left + text-offset: 16 0 + color: #C0C0C0 + image-color: #89ff89 + icon: images/coin + icon-size: 12 12 + icon-offset: 40 5 + size: 64 20 + margin-left: 6 + focusable: false + @onClick: modules.game_shop.buyPoints() + $pressed: + text-offset: 17 1 + icon-offset: 41 5 + $on: + icon: images/coin_second + + Button + anchors.top: prev.top + anchors.left: prev.right + size: 87 20 + margin-left: 6 + icon: images/giftcoin + icon-offset: 0 0 + focusable: false + @onClick: modules.game_shop.toggleGiftCoins() + $pressed: + icon-offset: 1 0 + + FlatPanel + id: history + anchors.top: parent.top + anchors.right: parent.right + anchors.left: categoriesList.right + anchors.bottom: categoriesList.bottom + margin-left: 6 + padding: 7 + visible: false + focusable: false + + HistoryHeader + anchors.left: parent.left + text: Date + size: 150 16 + + VerticalSeparator + anchors.top: parent.top + anchors.left: prev.right + height: 16 + + HistoryHeader + anchors.left: prev.right + margin-left: 1 + text: Balance + size: 90 16 + + VerticalSeparator + anchors.top: parent.top + anchors.left: prev.right + height: 16 + + HistoryHeader + anchors.left: prev.right + anchors.right: parent.right + margin-left: 1 + text: Description + height: 16 + + FlatPanel + id: list + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: next.top + margin-top: 1 + margin-bottom: 5 + layout: verticalBox + + Button + id: prevPageButton + text: Prev Page + width: 96 + anchors.bottom: parent.bottom + anchors.left: parent.left + visible: false + @onClick: modules.game_shop.prevPage() + + Button + id: nextPageButton + text: Next Page + width: 96 + anchors.bottom: parent.bottom + anchors.right: parent.right + visible: false + @onClick: modules.game_shop.nextPage() + + Label + id: pageLabel + anchors.verticalcenter: prevPageButton.verticalcenter + anchors.left: prevPageButton.right + anchors.right: nextPageButton.left + text-align: center + color: #C0C0C0 + text: Page 1/1 + + FlatPanel + id: offers + anchors.top: parent.top + anchors.right: parent.right + anchors.left: categoriesList.right + anchors.bottom: categoriesList.bottom + margin-left: 6 + visible: false + focusable: false + + ScrollableFlatPanel + id: offersList + anchors.top: parent.top + anchors.left: parent.left + anchors.bottom: parent.bottom + padding-right: 17 + padding-left: 5 + margin: 5 + width: 260 + vertical-scrollbar: offersListScrollBar + layout: verticalBox + + VerticalScrollBar + id: offersListScrollBar + anchors.top: prev.top + anchors.bottom: prev.bottom + anchors.right: prev.right + step: 50 + pixels-scroll: true + + UIWidget + id: offerDetails + anchors.top: prev.top + anchors.bottom: prev.bottom + anchors.left: prev.right + anchors.right: parent.right + margin-left: 5 + margin-right: 5 + visible: false + + Label + id: name + anchors.fill: parent + text-align: top + margin-top: 3 + color: #C0C0C0 + + FlatPanel + id: imagePanel + anchors.top: parent.top + anchors.left: parent.left + margin-top: 23 + margin-left: 5 + size: 130 130 + + UIWidget + id: image + anchors.fill: parent + margin: 3 + visible: false + + UICreature + id: outfit + anchors.fill: parent + margin-right: 6 + margin-bottom: 6 + visible: false + animate: true + + UICreature + id: mount + anchors.fill: parent + margin-right: 8 + margin-bottom: 8 + visible: false + animate: true + + UIItem + id: item + anchors.centerIn: parent + size: 68 68 + virtual: true + visible: false + + OfferBuyButton + id: buyButton + anchors.top: prev.top + anchors.left: prev.right + anchors.right: parent.right + margin-left: 8 + margin-right: 3 + + OfferBuyPrice + id: price + + OfferBuyButton + id: additionalBuyButton + margin-top: 4 + + OfferBuyPrice + id: additionalPrice + + ScrollableFlatPanel + id: description + anchors.top: imagePanel.bottom + anchors.left: imagePanel.left + anchors.right: parent.right + anchors.bottom: parent.bottom + image-color: #A0A0A0 + margin-top: 10 + margin-right: 13 + padding: 5 + vertical-scrollbar: descriptionScrollBar + layout: verticalBox + + VerticalScrollBar + id: descriptionScrollBar + anchors.top: prev.top + anchors.bottom: prev.bottom + anchors.left: prev.right + step: 50 + pixels-scroll: true \ No newline at end of file diff --git a/modules/game_shop/gift.otui b/modules/game_shop/gift.otui new file mode 100644 index 000000000..f627823d7 --- /dev/null +++ b/modules/game_shop/gift.otui @@ -0,0 +1,28 @@ +MainWindow + size: 400 110 + !text: 'Enter player name' + @onEnter: modules.game_shop.confirmGift() + + Button + id: buttonConfirm + anchors.bottom: parent.bottom + anchors.right: parent.right + !text: 'Confirm' + width: 64 + @onClick: modules.game_shop.confirmGift() + + Button + id: buttonCancel + anchors.bottom: parent.bottom + anchors.left: parent.left + !text: 'Cancel' + width: 64 + @onClick: modules.game_shop.cancelGift() + + TextEdit + id: targetName + anchors.top: parent.top + anchors.left: buttonCancel.right + anchors.right: buttonConfirm.left + margin-left: 10 + margin-right: 10 \ No newline at end of file diff --git a/modules/game_shop/giftcoins.otui b/modules/game_shop/giftcoins.otui new file mode 100644 index 000000000..8a3ade919 --- /dev/null +++ b/modules/game_shop/giftcoins.otui @@ -0,0 +1,148 @@ +GiftCoinsLabel < Label + color: #C0C0C0 + +MainWindow + id: transferWindow + !text: tr('Gift Tibia Coins') + size: 280 238 + color: #909090 + @onEscape: modules.game_shop.cancelGiftCoins() + $on: + size: 280 300 + + GiftCoinsLabel + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + margin-top: 4 + text-wrap: true + height: 56 + text: Please select the amount of Tibia Coins you like to gift and enter the name of the character that should receive the Tibia Coins. + + GiftCoinsLabel + anchors.top: prev.bottom + anchors.left: parent.left + margin-top: 10 + text: Reciepient: + + TextEdit + id: recipient + anchors.verticalCenter: prev.verticalCenter + anchors.right: parent.right + width: 150 + text-align: left + + GiftCoinsLabel + id: coinsBalance + anchors.top: prev.bottom + anchors.left: parent.left + margin-top: 10 + text-align: left + text-horizontal-auto-resize: true + text: Transferable Tibia Coins: + + UIWidget + anchors.left: prev.right + anchors.verticalcenter: prev.verticalcenter + image-source: images/coin + margin-left: 6 + phantom: true + + GiftCoinsLabel + id: coinsAmountLabel + anchors.top: prev.bottom + anchors.left: parent.left + margin-top: 10 + text-align: left + text-horizontal-auto-resize: true + text: Amount to gift: 0 + + UIWidget + anchors.left: prev.right + anchors.verticalcenter: prev.verticalcenter + image-source: images/coin + margin-left: 6 + phantom: true + + HorizontalScrollBar + id: coinsAmountScrollbar + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin-top: 10 + step: 25 + minimum: 0 + maximum: 0 + @onValueChange: modules.game_shop.changeCoinsAmount(self:getValue()) + + GiftCoinsLabel + id: taskPointsBalance + anchors.top: prev.bottom + anchors.left: parent.left + margin-top: 10 + text-align: left + text-horizontal-auto-resize: true + text: Transferable Task points: + + UIWidget + id: taskPointsCoin + anchors.left: prev.right + anchors.verticalcenter: prev.verticalcenter + image-source: images/coin_second + margin-left: 6 + phantom: true + + GiftCoinsLabel + id: taskPointsAmountLabel + anchors.top: prev.bottom + anchors.left: parent.left + margin-top: 10 + text-align: left + text-horizontal-auto-resize: true + text: Amount to gift: 0 + + UIWidget + id: taskPointsLabelCoin + anchors.left: prev.right + anchors.verticalcenter: prev.verticalcenter + image-source: images/coin_second + margin-left: 6 + phantom: true + + HorizontalScrollBar + id: taskPointsAmountScrollbar + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + margin-top: 10 + step: 25 + minimum: 0 + maximum: 0 + @onValueChange: modules.game_shop.changeTaskPointsAmount(self:getValue()) + + HorizontalSeparator + anchors.right: parent.right + anchors.left: parent.left + anchors.bottom: cancelButton.top + margin-bottom: 8 + + Button + id: cancelButton + !text: tr('Cancel') + font: cipsoftFont + anchors.right: parent.right + anchors.bottom: parent.bottom + size: 45 21 + margin-top: 15 + margin-right: 5 + @onClick: modules.game_shop.cancelGiftCoins() + + Button + id: giftButton + !text: tr('Gift') + font: cipsoftFont + size: 45 21 + anchors.verticalCenter: prev.verticalCenter + anchors.right: prev.left + margin-right: 5 + @onClick: modules.game_shop.confirmGiftCoins() \ No newline at end of file diff --git a/modules/game_shop/images/180_days.png b/modules/game_shop/images/180_days.png new file mode 100644 index 0000000000000000000000000000000000000000..98968e3810beddd6f40b93146a3f147a309b9080 GIT binary patch literal 1031 zcmV+i1o-=jP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0000# zP)t-s00010G#2luLi^R9DjpF2^W@x&DPv<}Mlu@O*V4Ybx2b3w|NHfI3=xkK53d>* z79}IiBOs1W6#u%p_ee#wa*2`v0004WQchC4*|=EfcO~z24dpR4EzHi1fDzK_m%{WADs`h-|y2P za9Zdkfwwdn`jIv44~OHvKR_QNTt?DN6q9&X7&!bKy9G{B(v`qb!mWOZ#kpJ2|;Bl*_mewP6*^Z0Dv(d3OpQ?036<20WNdEj{<@OM50JU zR#31Z0Dc^>p$0%@YQa1c=9f}nAZkNlhf6J3T`x%uY^V+}nShYt4DBeTRu}*Qr6w%` zgu>Q?48080SQ3>97A9j7_KpFX7GVHp8z|N}F8LQb>bj6@PF1g2Y*uaS3Kz5xvKQ6Y zAaOyRMG2ZlZgv7k^oq0QW!eDk3aA61UP|T%eFxxO0{}Z|1Hf7Gg0v}-L}BXl0iXo2 zysfFoz70SyumgHCgqC}~Zq&2^k^}5JxdQ;OtPW@Z#76+OhW1CT2Gi8K0n7pN;z2e5 zJ>C)nPz~TLt0pO-s$S5i@EVXhKq{PBhu~rNM&s*RCMaWuD(A$Y>FtAo}{a*p8 zyG8|cYUlI$aw+ZP?Y|PH0OsM?XB*(MuB!rWdnhluxZ~?;=}u5U1E4$r;O)f^ejdx5 z^cN)=pq004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0000X zP)t-s00010G#2luLi^R9DjpF2^W@x&DXC~1Mlu?XP80wD0Iy`BZvX%Q0d!JMQvg8b z*k%9#00Cl4M??UK1szBL000SaNLh0L01FZT01FZU(%pXi0006MNkl^=Z81Vs-3wm!Jmj3Mar29`VEvn9|LP?`!n1B&5{ zT>BWbe;)_}O&-B!r^yG<4!Ar}e!GEv;0hSZ!)CXK=wV~^H@6@D?58MuaKkta3SSBl zz8g1yR!w^V+KsZH5o$zOMw>+kqPzig2y_5mcaLc(Pmjg8v2GZaZrlACjmiTN{5$a* XFrmvQwwmXe00000NkvXXu0mjf8@n*2 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/360_days.png b/modules/game_shop/images/360_days.png new file mode 100644 index 0000000000000000000000000000000000000000..99c021eb813c1cfa51fbc3d1909b20729fd297c9 GIT binary patch literal 1243 zcmV<11SI>3P)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0000; zP)t-s00010G!{lO8mVX-`_-TCs6zhp9xXP84HfWB>W^+Sk%`3=#kP^-D`j zj}i~QySJ|z7tJFekdTo7y1DmAMF0Q*5~i1M00001bW%=J06^y0W&i*H0b)x>L;#2d z9Y_EG010qNS#tmY3labT3lag+-G2N400ZMmL_t(o!|j&YlG`8R z_cmCIEl;N6msBM@%&^@fB>dnq>h|SIgc+kXk zgwst09KG4w?VZ~t-naumxO(Ev-fruigenOE9suwdgW#%Y@6D6lmZcZUb`x33F;tUa z!Q;@KH_vuk=cA+9Aqqo4K+8pIUGxvl&YRWlEpAaF?2gi|fVK@bV%o)5Z#KJE3sC-1 zLTpVWAS%INO8gqpoj0r9l|VpH0u6WoR3BD=mCYM%DXk{38xS_60GnJ&#i3w?IZ3Gi zuvEK6^wp$Tu1)&tk`KM<``&o$8k!7qLO){4IBd*CFST0%-9!KgHZ>Cg{W!t^@3E32 z8VLkoX!Vjub`LH@i|pIJPpNSVm<|^l>4qTRH z2BBeed+J9cEX$q*CO(E2fTiID5S{?k<7%_6;f#F+phTkTQM||;oGt*(LQsd064xL@ zbjFH10&p>qZ$kjfpMV+7L}Vc`g6xw3fI5RZJU*2)fdEF%G4EpqFh2^Qb9moEiAH=f zfF^juHEg7NeFe}39cdDLNie$mr}7cT0vHt_Fth+z1g40@vHKPfD}Y}k9-0#Rj`xbH zlzRjL7qY_qvj>-K34jWK$c;mnsc#mHO&+?(JjnorbkwKLVlh*N#Pif{qR+C-;zdWX zSd)e>A&8+n64Imq>=T{}2!oD)^C%P=&M&MgurdI4e-nxexFH7Brl-PMbkt_*@rVA; z3umwi6ZT23kBq1W=M^usRSNH4)Tb)y`0RrlQq1ZP=6M0|Q zSoFYoj?m@#^(x@a=l>IeEnZ?Z=j@~zTXBygk(g0j;yibxGE=?eG86j{0-0`ju zfcXykDZ?#!6UB=Hnlw!WI0eiA^c!Fz0JgpP*~QO|UjbeL^R0gZunz3^fa|q`3mz%} z?i-*}7v2M`Eit$%0EQAU-th=;fNOT8lFsyAf0Yt24b=j?9rtks3=;uwvtV)UagmYl z39h34Xu&ux6%gzEGU|6eoawQG?ZQgbT2=yPsK=e;yl&v-d?f@<>yp>Iz=9`XDf)T| zbQAA$d004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0000g zP)t-s00010G#2luLi^R9DjpF2^W@x&DXC~1Mlu?83=xkK53d>*%_AU=P87-`8P)&* z00DGTPE!Ct=GbNc0004EOGiWihy@);00009a7bBm000XT000XT0n*)m`~Uy~xJg7o zR7l6|)iH0{KokIAEHQYjjcUYtf%ASBlhv)PR#eK8)ai_4-DSlhzDfZJQH3N!2DaE6 zQ-zt*rBd0lbZEy)nfNb#XB*=rN?9wlZ?KK;yLWf*PNq`%AAf5oFSY=EcN=)W1=O|x zW#`ELGoa4{O|~dj3KZ?>$`sUut6_cc;Woy0Y0b)RHhLRg>M2lna6=A#05{3==A z9{Lhc1|ubg1?(ok`Nq9AdjO~(FX74>@iH-J2gV7S`EI?z60}o5Aj5L5??~YJIjEvW zvY6oUGv< z_+XZ$LX8nd)N);yz!G7-n5WyanZ#Ju0R+hkk=20*1yIc#Koe}p8i?XVRk>_;T}tJy oBUwt=3dV~QRdt?;f9OBzH^p0LNfjK@z5oCK07*qoM6N<$f-oR`x&QzG literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/All_regular_Blessings.png b/modules/game_shop/images/All_regular_Blessings.png new file mode 100644 index 0000000000000000000000000000000000000000..44a63b6173abc5238623e63fc9cc95e2d2599424 GIT binary patch literal 4403 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 XUdh>n=;e@|-x&JZhFbX=*8~0ob-R%a literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/Blood_of_the_Mountain.png b/modules/game_shop/images/Blood_of_the_Mountain.png new file mode 100644 index 0000000000000000000000000000000000000000..86ba6804f364738381e8f1dcba654936e0249fb4 GIT binary patch literal 4279 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/Heart_of_the_Mountain.png b/modules/game_shop/images/Heart_of_the_Mountain.png new file mode 100644 index 0000000000000000000000000000000000000000..dce80532060c66073d3235d3bf3f835699800c88 GIT binary patch literal 4253 zcmd^B_gfQb*PhTs5X1tas}jPZD29+gfJ8z|D3KPaL5hSF2$Dh)AfZV|rT3;7sTLGi zr71{>h@gOofKn6-VnJ60gvCYPxU2iUKkW7X1K)Ga%v0vvr`+e9x#lFn!CFCXha3O^ z3V0iwlXy1!e#=UVpJ$q4=fu-?o+Xjz%%btaNE|9)PGR{`!FUGApXx*vu=f=NEb6o^%D$I$>Wrc9a;(X9FeuBl^{cl6x1;yT=9XWJyQb<8K7CD4LW%BSi z3`G1!heD^IDP%GNi9qN<4JarI)WA@m1obnZ>O>%(zBv3MqzM`DtxKW)>+wtrxa{wEfVNoAsgxW89;vEDgVXb-<2vp5l6!Q=@6QR zM3Ue}R6i(+f;57{;bJO{5C~l;O_z+&Md=|7_5Ac9FtLlU@5S?9#q{$?T%q5W|Fnj9 z^G|b8nc|M(h+Aj;0xm|}kpRKY#S#zQlpcEI+3l2;{9|R|cuzayg(=~9Tii@95dSg9vB9B&Q(|XG2sa*Fbok>T~dIL4=q1v#A*COglPmULJ>V+pij+J;B?@A9P z9(O$uZEJZx$~Kel8F&brdQ=asp^z2smEm%zD3O;J?1obP1r&le!5FW<{{q2o;DlepN!NzBBd3UVeO1iH>dY$% zhcoz|A08H7B05%v9etD+bn6WH+$pa+<$;qo6K|a+_f`b;71K#>=Jh8-o_3uOSR04a zoE+d=ujEE&3cRRZHU&|^{TEmzaqhhpfqj=agO|D8xl}iVb|4WuRG-ii7gB(=7^>h_ zGCZ=wy$>0~>q?W`PDPPDEK}*O-37QV__O=_XlXUhu!?74yW>FoeuJDS-)_GDE}4zl5k6VrK2JIugKafK9QO;Htp1$; zIMTrHt7IGxa!(H-3Mh^wlb!B()Kej!pszaGASmZsSA*;I?eA6z3L>4F&Sy<_J)(Ub zMZ&2O5Pr(@XoXr(oEn9w8S)V3oP8Kv3#AlhB7RFJgyYoX#O!EW|Br~<#0LQNK zAW;QlZEY>>#R*LS00BHF2WRp2|MLKxm)427kj=y6%w7276=MS87XRJrK1yW}G%R)3 zC#!;$aORuAJLCd14!FYCW3{@=WZ1VBiTR`D0kUQJI$7*%zTKx98{Kj;6EcOuTUN%6 z+M`z|#>o@jH^Qdo-h2q1N?Bd?iQBn8V{mx&oB3wM)4|sHff4~t6}#rIN;WOT2)y>G ztH;8p6$<hyqa@E=vD%!MXlS~1Vv@Nyn0S5=G(*StC1<$LeBX~~tBm8Bcc-}_qVR*!>h z-&wQESk8&)+st0dU0D$>t64mXrmpR1Muogp5A%8Q+Q~p02w*0e(4Ks~Y*&0Gap%;z z?4VhxB@UmNxDxAH?tkl}Sj-wHU0b++kF@>0~FQ%GKOv65c%-Wj;^k=$t z!$mpR!zV>%=FVssdwg#X>+;Iui=Jyz;J(49h6I;~lXfv~lLAOyp+f5ZwhQ~b8v@4n zZoD~uM2)wIk}88l0{djQDywXJ4(Q(tviE}|=ky1EzGnY<@#$AGdGz`vH72I@Z9|@% zrAzKw7alN5ojsd;(<#Sx^81T;53U{UDvstGN>%7W{SO-I)J3ekBW7 z0e1jpo}qzdMRrxUef5=u^v7*aSAG9D^`-l_&m#BQK?}2IrrQZ#lbd%`e$GUEK{nc3z z8pOX;?mIX&A+1@R-+q5$LQ9*)c2yae^5Eav)21zgMQ;NCoR~f9?lPd-o(u5FTV$*OQ;=e!v+vbu z0soET!ECa`L5qv5o$=rDo_NnFD;GIXqq}g^lPE_ukYW+mQw=zJC;LP9t$XWRmLwJs z+Frw5dU|4^gpJdaEmqJU7{_xa=AG>~ciexjO!j%9uOrOJz@gEAH)-htIt6 zWHdT>Zj=bY<3AtNd0jhp@lXhQ(lk%>W=Z16g*i8(so&He^P<(#QWM*z?tsh@&0cTg z($J`ny}PXG#kV)HjaDVMfSQ$FNIZPQtCP6_1r|cWLd!FKl2;E(hlK0~*8O21lE1T0 zd4m3WY)5K7Q~L`P+yTFH&A8OohfqDTJH#m9BysMSJNxno&*$&gc5j;g>O861F5bDLU#yz%tn}MPwqS%{W$H9p;qXWzo<(7Do#Q<6K+C|vrR?%g-52YKVtbl{h!$H_^b!ca4WsiYXM;M#*LUPDbab_-` zs9tkxWc`zvGpyt-z6nKG&{$mFoZ9FX*@o-!`UkG?@F0D(71nJsHs#{4RHkU~I zkU*a_H~*>ych+**yA1ejlWq2@--T9bE$#~Jx;a9No%d^+piehZD3qXthziN|Cc6a- zL9u4+PtPsY72?4?ikM|dm`rB|csWE%OMeRaY$qQ$)TgO8(yd8dmTyXykraHoFzpHDTu0s)?$@s(U(|SuM6AoHJzH;7r~*1k7K-ObBq4_b6SgT8gxcFT zz8sWQP(DBMc0~8>$j5cL2FqH_q3?G*`8|2}303yfjk5gxArPf)SygVLRrJ`ChA9)B zt<P*tK}r=C)Rf zoM@@MHhJhP-zRYmu@EGEP)G9R+Bbj1G<>MKs*xHLJ-_tfEB2{kOvUx7rQaP_7QQh) cn}TG3ReNddtBibs_{SB%TRPybSop^M2T5$)b^rhX literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/Name_Change.png b/modules/game_shop/images/Name_Change.png new file mode 100644 index 0000000000000000000000000000000000000000..f4f83bef53ecc8c1f55bb7ea54dda322f6698541 GIT binary patch literal 1147 zcmV->1cdvEP)004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0002q zP)t-s0001lZ8rb=w*UYD-q+2osiQeGEf*UVbnO5F$p8SL00s;P5h4{yk6AfxMI%Hj z1Ox+RL^?+~E>m7G7#J504h=6`Ijf#-u&I-Jibp+nOG=PhzqzD*bYVM2MKWSNmX3SV z&bl%!BPvoeUOO;NKYIcJ0U9$PS!!vVtf+sLl%;4@PBADR6AxBKiDy)#UQL!mDk2>c z4^lHKd`>_;CLaL;0TB)yCm0lpS4U+*I0z34GawpwOFfoeO;SoLOhqb8F(^1P9tjc) zVm&gDT1pQc5)>yGG-W?KFkNQzBz*t?00DGTPE!Ct=GbNc0004EOGiWihy@);00009 za7bBm000XT000XT0n*)m`~Uy~?MXyIR9M69mTgy?Fcim0NuY|>=&W;~w)TN-)>VP( zx(((wsO`T07h0YPQk8Jd&fe_y6bQ}#mz(6?n_AXiFaY#h8$buBt1?@&Z6f`5n`i;~ zR^CC)wlFHcLkK#Z4ye9@h#0@p2fGmfRn(|_A^`9@pcFxRcQhL9Q6T_Zz@?t8f#^%k zsQ}izE@E zCHgCuwYFRX;fX^9)I`L}R;4eLBh~>;Jb+IptpIWrYinSu!Su;G!o-u*zY3_$pmgZj zIM8BI-vTXu9J#&hz72q2eJ}`J4Z!mQ&?tx1TmUp1R3z&u=yqMCl7fXe)7R5c_dw+= z8Na*Jb<0<5%K>@@P;0uB$34n6P9vDNRl z0-Sh9Z@rV#cNqIY8z*qD*E{ge&d>T61K)2$@Q4jB@#*MdJQ$4eaSI;?{n2nZI=h@; zJocx@VQA_Hen0teKKghyyZ$u4xt&LG5}E<}Q@psknk;75clV!fZtyZm41K^;+{cUA zm&w;SO1`CWlo`5!=eKEm_x<6=Pom9|I86-!7RF%|$G;x(WsyV?nSv?6vcjlH^E{8T zRkBQ50n%jk82EXzO42lI1xSl^5Nz^jnUPtT1FSI1Vm}B5ak?T-v;bImm2QF{cwA004R>004l5008;`004mK004C`008P>0026e000+ooVrmw0000s zP)t-s0000hB?LG!2LJ15)xIRWs34({9CT+DT~rW2ISR?NBNrPLw4on#?Ep#OIb#l_hKNPua2^ypC| zDEiIL5Rr4ik;`8YEVyOX*91V~cADYa@wsgE9U+ge)I86>%z|O`>#zs&bquViY#1be zZo*{&E>!r0`6J(75 zJ^+}l1JEX9z;Xg$XtuorkTzhRMT$W5yT)99XP^on7(nBvQ=ow0-?vu&i$U%fJo@$8 zL_i7N|K5AOJwXVb{XL*2j&YsG+IN$K*RKjF1c<5XR&d)#aywD|zzzVP%)lfMd-%~m z5kMhGKSlp*{Ia#X;6Esp`Z@o^__}65C1j8{7*c7W?aNQdlJ~JBOYT|XM^xqjFl4B> zWz7i;PzVCGtHhN3sWNLVu+vh_1ncaO3lQR21+^MO+O?VA5i~v3(+rv~r+`FgqKn-d z06#zQMgT5H5r`829syzq;0Hjw6cd2%4(rz-oQb?&1Bj<=+(m0G76R)+h=ZU$1aC!2 zMj?dN(9R(f;uRtWfHsvYAcr7*p|O+}c*vsz;BZTjN^=3g^Z_77fST%R0I*~cT7V;n zPkz@)ImLe3|81`cu({IQ3kJt`9+YC&gLjfgxDeec2&K+1{;NwBLX1ANi-!Y<^Fk}H vxXYKyCE!0#ox6az7k2>DjhE`9NB8sx*DWH?2qTEU00000NkvXXu0mjfp};uo literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/Temple_Teleport.png b/modules/game_shop/images/Temple_Teleport.png new file mode 100644 index 0000000000000000000000000000000000000000..366ac193cbdd036b0903d3601a5bf2b95002d952 GIT binary patch literal 1486 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/The_Fire_of_the_Suns.png b/modules/game_shop/images/The_Fire_of_the_Suns.png new file mode 100644 index 0000000000000000000000000000000000000000..00e1b8dae480872cd6151d434397498bf1bd399b GIT binary patch literal 3302 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/The_Spark_of_the_Phoenix.png b/modules/game_shop/images/The_Spark_of_the_Phoenix.png new file mode 100644 index 0000000000000000000000000000000000000000..35b03575f4aeae81f36233dad46ce6fbffb17fed GIT binary patch literal 3268 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 Bdr<%Y literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/Twist_of_Fate.png b/modules/game_shop/images/Twist_of_Fate.png new file mode 100644 index 0000000000000000000000000000000000000000..b8e3930179a0dd1dcdc77900165e97c7f54bba98 GIT binary patch literal 2970 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/arrow_right.png b/modules/game_shop/images/arrow_right.png new file mode 100644 index 0000000000000000000000000000000000000000..169e790b79c424adc850af79d9082840331ad4a9 GIT binary patch literal 566 zcmV-60?GY}P)EX>4Tx04R}tkv&MmKpe$iQ?*4Z4rUN>$WV2$ASxnGQpF-zC~bvS9ZW9$5Slb3 zDK3tJYr(;f#j1mgv#t)Vf*|+-;_Tq0=prTlFDs^Frd7t}p^r$(D0X~U%mKml^yiPo| zX&apPiA7eFRpN8vQIjr6{K$2s!Ec-kE(<(UG}FmBVv$%Xw6W60tY~V)lf+?F(poLBz0#I1-Scpn?sQU?W1SPKt#j?MFTQ1Fk+gyS4HY^gkK0DZ7%NrjXAA?`QN)S)lJ0=w5B~*4)SG1CXY!mTrK9 zLtwZ-*=ru}4z~C9@0n(QKiffa(aq@!)&Kwi24YJ`L;(K){{a7>y{D4^000SaNLh0L z01FcU01FcV0GgZ_00007bV*G`2j~U}6et~8Lnq$=001&cL_t&t*JEISf&&K*{AWM| zOvoH`1x)CwkriM_A}hcu>EPhNh*c6M!GO;(3=9km0MFVH$oYKH+5i9m07*qoM6N<$ Ef;|%PNB{r; literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/categories.png b/modules/game_shop/images/categories.png new file mode 100644 index 0000000000000000000000000000000000000000..9273fbf77221550b5c8843a24c10d0a009decb70 GIT binary patch literal 11768 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/coin.png b/modules/game_shop/images/coin.png new file mode 100644 index 0000000000000000000000000000000000000000..30d79355854d7e4956d135280b9b54e379721a73 GIT binary patch literal 508 zcmV(#ArjC`*%tVJ%6TY>>5u5-IeEvS39vWGp6Ztdv<ia)nB`Yv{^FWk{0iHza zVjWUR)WzS)6H=@+RAOKz1gs7hBI*RS1krVj<{UrmG}n+i>ms+Qf}R$A=B9~I5VspW z_ywM(d8df>8Y_v;d*~qQC%3WIkPgT54C!Pl03jsEyPU$p&^F?GZLp-FLkWV^+Xw-7 z@)@%41*4m9u!(&NJ|wbm>?RQz>%h@&5_hLL5X5RsY7GSdMW$I#u}T^(P6^UiW$={3 z{YeI#HpvJm59qA=)T2HDQfFJRNHNu8OFBy%;nEANQA|#j?LeX8u!O0t^7iv8pGU2e<+N0000FVe+tx_i8L_wKzDB;iifOIpDEWg^`D+F$bgY!d+RHNE@AToFl-M5tnN z*5~f}AyYqNWoo8=#xn0RR52S~$31y(r$*pOoWGtx7X|>3-wrU8+FBK%iYj` z`WYXO-dUNNm8orFob_!|qA4!wB^*kP$sg aUt%RHd#&|hCpg&c-?)CqdH?`6T3MPo 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 T4_D|K00000NkvXXu0mjfNvQYX literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00005[64x64x8BPP].png b/modules/game_shop/images/ex/00005[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..01c7a327e04766596a2f2a7182c06613e9a6e025 GIT binary patch literal 4976 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00012[64x64x8BPP].png b/modules/game_shop/images/ex/00012[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..4d97b790de3eef9ef31a0740f8df971548b7aecc GIT binary patch literal 1460 zcmaJ>eQXnD7{6_djm-i=)NKJd4i+5odSAV3?^xOTu}b4QXIEfG9bE6;w#U|9y*q3> zqv4|A@Q6LyTMFj;TI%UL}0e@KEZYyH4@aFFQy65+N z{GR8zj>d+kOeGa12!fcr%iMmr)@I-00yyv7zkUcVef5H*M$KYY#+;1CAsRudYm#wMY6S)w1Ysp+$8PowV5lP7 zv6ZZk^u=8uqAY9IKvR1|Kx%K5cp0l%idH8Ds2~aq5lu$hV!DvDV`F*+xX)e_7&<0m zwA!(8r<#3@s7uuV%9=S`q8J*r@@9(VX`AIqlqM;TAT0#N;}j#n$3mhL1B2EyIVAYq zo(WsiBnx$z5=VV^SIjcp) zgB-Bnl!cR7S>z}lgmQW&!#f=g)<&`}o^#R^Rma(!9ymLwItS@uoK8;;>y7D#7?VKG zwgPQWV4V-d3N8(ZhN=ZrwJlc#jS*M@NloW zKn!-223yBIxUdek9n)AJsJn9EptFWWx)D=p>Byhw7lmh4ZY;CxT3qfaG5$bi;D!0e zk>vwVZ_Ch!GjCkqU6#pYDtDgHApBv&-_Qh){~Jid!YXT2XMgvuI>i`pTk@3Xu7CQ;#Cv8D)dhI<9s0Ytua@ zv}fe^Hy>YpZTFND2P&3T4L`Qvy3|lxdQ5t5jrWDwr~6N$nU=3=x0j@L&8t26{$ICd zz7?8(O5Cx&VD7Z-XPiOX$6qX_1{oErI T{dQ<>_CM;aYjE#%uHNu3VHyhu literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00013[64x64x8BPP].png b/modules/game_shop/images/ex/00013[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..6d66d09831121599d45179d52bfe75382e031993 GIT binary patch literal 3351 zcmaJ^dpMM78-Hhz8RgLAoM8@Zw9R>FW{|5uoY&t`XREmJK3 z0JJ^WEI-xCTzX;4RNrEL>?_q`B6ACpZ52hz5;zhNaOR03K$M4o69xK#9A0AV1JD5g z)KdBWL9!rkF9ug6z;l*#@N$7zg$4izC%KrzjR9q-2r!B-bi|BR-NvB!JV#8RtvAtI z>;v?Y+pIFcQMNM(@LqrN;C zl{X15lHteN_{Ep%oSofhG>V(sSFDFnD&q*b;8)*#mG3WD%D-Y6t`d+V6G{9< zqVK+TflstZCXz;r#3)x+RnW@4#`2WCx zM<;_6YGfpiMg(~{I)zHaap-nb9F1%T61g1EjzghfzTkO(%io`Us*{uIr0UP5?O%hTI{Yp~)3T zMXnj4w@OMwuL6_vRtlQ*oVHJU-I*<2qW}K*y$CP zcMRcpEDB$3ka*5?{P_{9gJ;)9SHzUmcM}wPXm@CG{xJB+u ze(Ilk?IGTT@ToG+(h!N#ZtNbMy`hYq>cr+GTw607@~+^L^2$@TPmO8W>G#$|D}`i~ zHgWIb=H`^faov%g;Ix!FlttQEnmN?f)Wsy<;;gev%|lcz@w5ZA@_N*_YfBH=ndYx&~?2QI`6x`efN1I)Tsp>HUZ}J(9vfy!wHykQ z34N5u@9aN_h9SLHgp^m<{vRtVjPw`IY3@T}Irk6cGq*a01>FqS+YDhhSJhXZ*Sfaa zuN(SU%-F-IT2Sv79FfF6yzk_)X`PB_ylHM<)RJMccP1f4V? zv&L<3KNeoQgAsS6{d3RUM?1*b8@pE<_j`NjXHMm$tm(k^8g2+Y83qWjzgt299p|={ z3$tL&h!ohoI!|X7LMn_`&piL@?9Lm9^K2+HExN4TPflB=*QKAn<5iVsp!@Y1l3pNf;D)>=tCO&3QMjC9q6%Rd6@Q_07k>~d?1kpcu zj;(nFFYOzCYF#ibbfIR2KT8F6d1z&6?EQTpb~z$wu{?!hhzcH0$={;rj0sHt2}qt= zA$%t`5T^m5xiE4eE$V_Y7?GM+r{H>o4^=f^zVU!!`wMN3mM8 z&3RDIqjeqJPwa<8X*@p7tfUj#A+mws@lu@v54~nomNEeJVGIe{6Wwl`ROhLLK0)aF zQ(_A=&r|b7@nlMVCQ$aI|3*Omp}x!r_6@Uw0L`G1$-=xkcfhJXM~9uWfoYFaplo2t zGQhxjrws5+>3$2uw=hCA^Bx$n<%~Gy#ilh|G}+GE+aZzT4MX@n5}D#jUII(=)=SBY zPKLskjx2a9d11h)YjK1WMbeo^b*!73WdGHvn+G0c6>LW;I&P)LKi>m%EpF0O{uaBi zFSJ+&2us(#1@v8RQA%wf#?PnU0cN|)832~)p&5-&J^4lz3e%)?r&Ha`@d4m^`IQ2- z@zv-f(28~l%(TIL(SHPZkd4{IK=I=aejWzY(+je1+xGN(u4-o}K0LMh#a~ld;UX+j z8@BEa9ojZiRr_L#^?oe|vwI%!5>CG#+3GYMRne$_+vxZ(V3ru58LmMb0Y<0Qtl>f0 zdip7omx>LT5%%Y9?AeYvHTQlf7^w(5TmGEUoS2uL;-@ie^SQP3 zMhiC|M6^NO;595=Q8GqY_xetV$$BJRE3=`x+7v#N@LSJ%?@VL}3$C{pndMM<^_rY_dxIaf@CghDe1ujtrr97L7 zeRe`UspX0W)iWhbr&+u%=bNX zG7$GiXs;NZ-}SPruiIt&vOBdsw;$O4&apS`w)ia5oiyrt6>?g`Y4YPw25Z{p%-oMk zr+T;A%Ow~aMwBcty8CjCGXGPjPT#JF3Wh~@%j}y{`U+iPC|1xMsf(Q-50Xtd@I!Jr zvmjsMvNuaT);5hc0~6yQQ+tz>4@i8r?dW(#WtTR8${sSV+jtSp)(f|Me literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00015[64x64x8BPP].png b/modules/game_shop/images/ex/00015[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..c3c12dc20a3b4ea86fd6c61037a5ccf879dd0a41 GIT binary patch literal 1747 zcmaJ=c~BEq7~g=(Rg_YWRxK_8Ei!JB-JBZd7E~|e0s!|iLs|x%k(eOWkwy;Y#BgjzGs6aesC70orrS!;pq9uom}Knnue;cw0hh7U zg^9dGa}1Gfh%cgu4Mj<5x}vQ*6lbrC2BU0JMuCx_G0rhqXdMSwz%2-3lP1QeqjScoDL!5R?Z!6GhCz=cr==1ZAJzys$Oo3TdW zdTFX^{k$#aCSzyQv{}mKTCG-&mCqrmEQX7sTpq$j5QsrQmO>Ma*&vf8%%wp^Sag)Z zOdCiO=+ua5$$VPIW;~q>!DvoQe5%-FnNJjxGOi6Xb72mTYcx9JnnhdaRN_B3o{6@k z6`BcdDq$h>DIHS}eVB{PFwtt2jLrPv;09cZ>vV_^ zLHLjeM{!6b7GRK8LCW28y@6z)uJ_0KR;@B7^B2mV|aI9E@#-b=97AO%^ z0ju~57guev(3nX_xNI93+w)w-bGgzOioj@+N+Zc!R~MvYlQe0`Ce2_>jI-)Oju4DU zH<)nJYFX_p)Lh&uf-)2k_H8lK?=EQS#=EI}ZxR-}W3Jb@5GwI~Yl`ItZi z6R1Qik+A3a`2R9E*QtzziNx%3NU9eKF<3%qAru!%AQ)y+DM1h(r03}n9?D0=e64`Z zWnAPso9BPcO4Lj4d(K6xCj$7Q4}*eojH*&GGiB-l8_dA((c6^hmS?p;EPhD z0U)m$a2)a4m>szS0DXa(nHdXq{|CPH}^`0b07V5BC4TkVR~3;O;~ZX;NcRR&!r`-oJXPZ=!GYXJ&v{> z%HL5}=_7yO*E$8tcPAVT0{pjB2=na+Vpj?JD#H6j>@+zK==fe5KcHFMW@5ShwP}3E zF4lMB{ts>SD*x_to3DuuDJP}^E~zsmM~0>@zWjcx8^~(bOAb5QKgfHj-n}D#N%^!p z+yoGve&fTx`&?ecf4p;9eg`=bn0ODVNpEjD9rGzDN>p7;i@#}mY zH>>)Ni374ja&v;p%-2&C8|{-r(aVQ>o^*R%ScwBYx&roK+1|_!5AmdO(EZwvZBvU& zu5yBY*5A|EkIQ;5lzQA~OshP-%;@O4xNWe?rfq7}l+I`X`AwF}ukC=Lr4h}%8t8wt zbMoqlSH!EUdbs!RG_yXc+NLi~U7KKjr@-p5z<>AW)V>321`ZAwwkM44`6jf%?g(-O zlbTz}kwDM6kcydA!R6=bA+O2s9pY~kaegfFT~q65f)muX~1gl z9l1Li7X7z3@64X5VBI<|&-#^BT`N8eceDb1G9YV6oKx5^-aS}>?#!vCIH$aSc?+lB zi@Rf6S{&KiT)v$QpRW9*aHRb~&G_D1zmdxGQ9I8j4|Tb{0KDmGJy>}EZXDCWfI2ow J^@TFCZwhrs{< literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00017[64x64x8BPP].png b/modules/game_shop/images/ex/00017[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..275db3005927ca4900f1200a2895e7e40fe15f01 GIT binary patch literal 4675 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00020[27x52x8BPP].png b/modules/game_shop/images/ex/00020[27x52x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..f68613e7f39187ca1af1ba3d9467f8d2e90919ad GIT binary patch literal 1335 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00025[64x64x8BPP].png b/modules/game_shop/images/ex/00025[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..0d82a889d759a012145d27d607e72440454b5a23 GIT binary patch literal 3424 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00026[64x64x8BPP].png b/modules/game_shop/images/ex/00026[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..6be2442d1b09cec5a827793f0e0b4c6d5b967201 GIT binary patch literal 2193 zcmaJ@30Mk$kd z(8ZRDqEHbJ3IeM@YXxh86+~_7x*k*uS`4Dx)SW1}efDuX&&>SCeDC+Y-}OJUdtFSJ zo$V@H1Oj0f5zdK)$6(WAV+FtKL|OOX!5Ioog5qRpkczJW5iFr>3kXC=_~~FQ$QR~j zT>}FU2n(qwJ_$z&#Fx7ItKny~_7BF2T4Mab0YexejVIVq@ z!o_ptAz+3mT%!QvG%@i4jaWbzqM1QJfSLg-kbn>$P)jnUN`^WR{YEbXo}0FDXyAHc4vTTI_&PST(A{dU{9~&|W!fY686(Tq({7jBakSzhFPy{Cs4S&H3 zMM8#9ARtnRL=uK7qzf@r8kvvTLIuef0+}kL2>Db39ZXx)^FBO<9)c$lI0O=%LMISH z*(?f$MJH0IBs!Z-B2!6=*a)c-;!6eKqHPgudjX68Lo6di0rDZ4B3>rTT&#k188S$w z%#g`}kPtZQ1UlfID3S_gDy5GpO>e#CfC^C#C|skENq{$TW{BRyfkVNQLTMyA(GSlu z@u%a-exWQnn@p#$Su8vay?_1*8j!gU@|yUk^HV`7PsI^G)>>N0K9nDM4%Mz z90lAWhaOB!A`r-y2o5V=ZFsgpoEgpfAV`(0%V@@Uyc}K;+c*|Y2_IQ|$lZPz_o^C& zwny%c|E$PZ3~;R0WaI*%CawSKRJ#hz~(TV;nzNThK2O;j51! zzyE%}zIIf2ZQ%7lxt4qz(GuV8Y`~HWDZQCzBEg4leB;Jo}N=nlE0c+I{!sb-Af)}Rao-v{fXx#&9PlmH9ayY3h-=R+8?k_ zJ{MnK&-=s|Tj1j`?mFD(^I6n*N&AkWa69?x7wUi}>#3D9<<_aLa`BLALr@&l1F=Vy1pNIy!(olo9)%ZHRDblE~1kunkI(bGH6!7F8GnO`MH>Q z%bku!Y1-$HWdUfj4HlK?Tl2e?e7=u=c{5|X`Aw!KO79V)wVFS-WJQ4W(38FKg$>O7 z9SJ<&0ly8KFdE(+=3aoEzWEg|gs-}=X1_hhd$TzCR~l-b~| z?dscx_;%-u(y?;u@N$&C&!V&N?1PSFca#sNtJtpQx~{orkA~Na9jsV`SmV&ol&y2$ z`F|)M8_^6NaPk+5O9vl;6Fr%>d5)=joe3@t_azT+Gsh9Njj7Id1#>fhvSLlEE18r# zyKh(DJbKrXqYS({6Wq^xsmn1xo1fO>ap&T3eUMnvkCimpMRJdtDWZcI6Vp-)xtsC+ z=%r50QoYkx)_+G#Nxts$-fW$p7}Ng7C?(1IK%sJM=B3$AV%v0Eo+LieA zGr=Lh>@6C(fl!$Td3@uS8W~)I{La&e-RGl>xWe2yxkt0@ap&ddNJVkjU!4m(-6Wm= zsH$t?I(8$S{ygVEacqfUxJkdXd>So1QFZTC&jr+M<4;FUhwW){Kj^XIKx8-dP+(ER z)r`i+n}9-TT*b!oB;_{um>K=?D%;=Gy{olo(-6$-OC9;IMJi8Dv z>=NSO$`0{m(>QoDQ=CZ<9U<_8r4TO2k1vqWgBbXaymVwdJ59vnKAK2<8F=$qhd6hZ z6V6g7hH+GVkiZ5(1Dp{}pF|}aQVcfY3_t^r2$G0~Ab~`oQ$V_*G49h3k9ZSvyy?zX zHlKVUPYgU)DizU*#K6En{Xj!~q1cB=qS0tX(12)QKtL=Al3;-p3L*$3x}O=WUFL0#v|1Nf{_=QO@P=`1A;f(5HtoM3T$NH^_k6HAdx}>HvBmn9>PTN;=o>1W0(Mu zVH&{*LYQc5jxhnEQ8{F)H`Ry@8-K*pEyXY-6^dPjLjGs%I(@DU&e9UmDv6>`!Rfj2 z1RP6G$WiNOL7o=?2DhlJN$RLe4>h)+(u}Pvjcp8RBx@4M z+T7g2!r0oFY-D9^MX|P^S>r!pk>37`TIR4c@ZVyIUxKmYNs#^oe>xXjVE<1eJ`dqX zHWnRX&+c&~Aqa_i*6HlzKLt#NK?=nHq$15SM5JIyh6!FqFro|?@`g#UHwh+DKH~$q zFhcqF*8Z(ub8aL;Z)qSThRuDD?eMSqF+jH5*V35-vAK}I2S(0ZB7Qc_*~97op3Hxy z@HvP7kI4{cvzcoWaZXHs_3z`_SI07v`^PEdte+izdC4FTUtUwN0I8E0c?oqHB@P3C zI?LY5+%@Py|H)9%k8a=A37KI|Lt7iZXWChumbb;;K5Rrx1s%*iMMn8zY_fdjN^JQ4s07jt?WXCg?vG2{E}T8Jnq@=) zw5FR|cHqM`@iRBp-)re+LmHT2whA+(@qiNA5fJbFfL^I-inW+<2Tm6)Odn~>jN~`D zr$zlK!zv|_3@Qw;1Oovb7}~+!+C1am?VMLdp;BjrOz6DxUICk?of%cr?MHh{;lTC+Nz|MBT>v0{_0Jp8y}rmKu!?v zxUIKmDy){G(D_~)ARlHdxM|XK>ASJzD!|RFDmOFNecup=Rg(K(yRTj3Tl~6X-im>Qc<#fcN~m6~cREa*EIC$G18AKG z6T`Xp2!HHd|In~~FovGMiL2Ir2-=RlqFRH|OswoM7Vtd6h#g*MMsu(p(-;X!eJL2s z-ul{fe*4B-=p*5ct2;uDPyec;u@Xo)TT~yO?sclmr?t3XAopQTc7OE3o99(^JWpcJ zqAVKC2x~+i}GaU(Mf9In){uWQ*FYY z0-jpBhRtS2$va0a8M`0npmZ|)glUXJJw(5rJ!_shTyMOnsR*cIkBOhZ;HI{WFD-4m zuj8}RaT4IChlSqZCIWmz^`M9FQ-P)`zDU9K4!t9Z3b;G#RYWAJ@P!0pi9Tk7cQ z>Ha!GS=YNP^b1=U`08ejI!wK zdGS06d^Bd0`zrA6_J&PW5nHAu!|78Wgl;)+JAEV2t4v%kPPU(?lw~OnI!^FXPVqM(CO{&vvihMgtov>ACKj-^y1HhT-KUS2Ew^lVonoT)9a9ow#r?zl# zqB-v6x%_L}#w!Z#A0*ughG8vq1Tl2ww!-lHJ`^Pk{yZB%Ur7McZ4b1IqQ{rFzMq)% z8+~<<9z4=@y}xzjgG0!Ij{3W=*y0?8CJQwl(Ols3l=)wh;^01`r%xYO7MD-*^4|RB z&&L7ek^Pw3A$=LqN~>5$3ynh6ok{H9!08$#a%(n4`fuJj&Ods6*Ngr)d8xNwPm(4+ zOpi4D?sl=idCcSXl(R?Vd!u{xKNFAI{l2)7Qjx4KEB3Fc2?@giJFX|%EH4k1djg&} zBDTbAt|`m=NwO+?Ce7pJx&A?&h1LFDGsBOcQKshg(ui-|ObeOX9+mEwtBQ(u>sG7C z&9U&^6n}Nx`NcZjp}}UVK$D(o}wJL!~bM>5C5h1c#(aZXO1-g{u`&x<*uPbTj|+y3O=%`P6;@UFi7 z*v0<$?OFE06UFfu=D`sg^;#7mH;0Q3Q3gCaZDcW6mSe<+nGJm%p&bayN`D;eR#(Lnc`*^QMFJm^j z$W>&q`ai7iAiEzqNz7_&ymvbW3T6CWvHc1b`&|dQfQ1co$kImP&bvIm2{?fcm?fcM z<_-lb7?KM!3_zuCyFQ?Y!5Q+gZyMe!*Kgf2Mlq$)E{HU2LX(D4=lewF36q9ao;g#n zfAZ>`J2+sWQ#HV>>GU0h-|Xa>L!I@l-FKF)ZN9emMroe8HE=*PqGGz~Ql5HE_%Z6wy8et>9R?z=jdpRWHRdM?V@AVAz3z!>OZ@7)&(g+<-G;86vLMbR6ux?bK-c) zS>}*2_FXxk^Jr7#nX1Z8L*=v>pdz@~K6G{QfPd&yrhQ+@0+c*#{LONM@XbfhIc9vn zJaz3FZCPocx9wJ$p4RXy6GGQzS4HWevXm*MJvl#Jbsq!bUk{8JJK!UDI@ghw?Lpe$XH8DW+ zINb8!LSc8HWjAFH`I$h)X|O-iUK@XoiDJ$>ri8ig*|JoTiXZrp_RF(7LC-Q93ir3h zhW&6$-7!A>35~YCX`N@c(($9okCh8YR2F;V(f9w1<0VY#1%{33^q5%pb(pMkX$LqC zo5x&a*X55ZmaQsUQW)%b6Q_}V@BSDV6Y`Xin4OeWG%y^1vJoEOrRoB;;cL0;2puMH zZUy;Jij7C#cIuj_iL8NKX0^%uwxEL~RyGK&4#Plteb_`>6>PfZ+NPQ|ukaNc#}kho z*B)RKaiC^w3Z;dF+raS1ng=ek`!(16c;|SVhljE3+1J?8KqxA`28#Zx_b$ zM5*@kYnEfmkCaFl3*FZ^azs8qwdXp5lV)N(MnbwX0D8;^ENBNZ2UKCa-@!_60uLZcBt%VC> zG4k|hc=dROBM{BZ?p%mgf&!)(*tc8vmjHzm!_%IB)JaZVR=N4(8nn4(!jgyuPa@=( z?4U{&=3&wyK+(S{IlrXygl}9vFR&7vsRD`v=Z)`^U)rJyOm7sr#ru;2b_1Q*)tm20 z3O;Dy+D!IiEiR$Z{LY7ZvQF;!BN2Rg3zk|L^ixxhS|Jq8ydM%eWb<2TD|j6n>` z=$H>GaGx!v{cH`TKhw9lOy)-xX%za#KA9)~v6Io&a_1~7&hpk-R+_Hq0m*Ayj9^La z+Zolav~w-h19H3iBy;k2@0Mt-Ujx$1*V?=Yb&mzmi?F49lq6M?3cDbxl=2|~i4X`>K>#5k{sJC(1M$!| zP*nto2PontfI?FwyCingCUs)$W)nNM65Gpe{IRxo*Rgk#EIMcRjPK0enambDedzq8 zt2=Y&w`b1%-E;3fcNQ#IuwcQ01q&7|Sg>Hh!lw|na=9$+bw^9H@?dg4Z8MT)r?^i7 z4!sWj(xH}E00R9G-;#i`!NpTqQwUXLKsE>BAv~Vvsfdpj@_Ud9nLH+!T98iY3`-}+%(NaA)bT?QUMz54sv3* zcQ@Ui>3RqNjdcC`2&f#^a?c)f1ArUWa_cqRfxb@D+}@6T5cd1ZORKpZ6`@7|R6goy zgsJISXy4xoOKUk;DLLWyS61oy&t8sD{qwgMsovPwRB^>;TJGiRS7A?M69gjx<$ZeG z$*GSZ5ebn9ExxUtYHTjQt%9fopjG5-90IM5C zIN8%l4*&FpMtFT>%jx_1`|#t>HNzVhmmnGm!uZW;=QL~8*?8ApwgU5Cp7 z$vY`pYy%z-J;${Jsu86{y%A#TY4Mc5fBG9RerpE&9yeS|&MKW}Xhrzd(3;A~_fCZ2 z&0)C+S}p>4ydavfD-%H!0{zD5K>YGg=b@f;!`2>)meDXmG|mEG+nuGX%GvK8^^;>} zMCgxi!oQ~NQl2&vjO?-qZQ-C{hx)o&;kW-BF)ad30db#ZXw?=)$Sh{bv0o3S!Rc~R zd#PB0Q(e2@eDV>*V@-+(S}yW_G|)`<$P*($&o1+E_Yg(kDXR5*Uo;9s6G>AdC~Ls; z&wfT}oSD5x9hQl(oG-waUw97YQupA@^Lyc~_bZDRpDEZ`axj-C5s-`RzZuF%c`R;M zTa4yEbM@@9Z&00{xV=JkD!e^B3@&#_5y576Liu535tj+FOT3v&uRy@>g~G-ry#S4) z%3M(SL?j63Mm{9|pD!=K>EjU)4^-&nK&P9o13oWB0=NILKPu(%h~nttC^J{jF7mY_ zkG`)KHkHob&19hea2Eu3yWs3AFH*rRRaXG)IK$K6rjd_$8kHAuBw&pqjNX}3M8HTu zzzK`tMO~ziS1ESCf;tkffjxECP0d z3*Lvk9ufiXfANo7bQMj%ZzjA6qVIpXFhY^K$Ll3AP+Ux{2S;zztOKe{@b+w4RdW=e2TKF0oYue24uKf2d9PdcL(Pg_S{!DQa7MHUW1)}d92_hn)PNzW)*J^(1L^aMG(tAw+9?$n^N#z%fa%jHv|nfn^N$e zpP_B6p_(kM6mro1YV@&oPrEv3_3!Rzh4IN*IMS6+C31-N<}lS^ubV``q7py`9DOZ3 zL#3Lwpwms|u&=U^ajl0=Pvtq+_*+ErovjhWoPgV6)e( z-Ot2TwKfVwhq>b-WKJ>O6wmjDVtw?-Q?iI(8pOK)~mtT8pW4CBr<}(xU3u zV?T)KAtjlcvJSD6Hw#&4ay4!_UD~V>4|MEmdE!0t^&&%t_){TOtKk%2mC{QoRXcV@ z&si<7qs+fo+~S+*-b6 zryp!k_&Rp!&q)#3QSF?Uad-`JR6W8)P){hR3d{EN{P^n0UTAA=R<&K5%TT#k%}_t~ z6wvDohqgAvnJ=3jTD#Ym7gY9ST)tNp+)^bWnz)^*i3H36@Cy@w4a6-FQ5ymF$|($u zc^aE&d#U_b4s?(U2w^TdtmQy8Y_)Ahn8;;oxO%_kjBxO362>O)8rn5n17fiViGYQH zdo@l2nFBZ{A3Ul!s|OSYMZ!>Lu~>*gzf<`YZ-XGraTd*t2sm|71We@vlI@&P^Vb-r z#Q25i{JW!Y>a$1S-OZzxmdg`gCIL-cHsYk->_-mQ`-1;L? zo|cK~MD?utlwXSkTM3fmy~~3ZJ@~)+=1)LBJh`;62>h26yZ&)+kSRb@TT{v_5lR4CNOclY;|ZWgK>8mfuteZf z8&gR@c~1`zaqZQ+deeYMm^%glfB{K4OF;S54lA#sWTNjypF#l2RR^CMWJT2c0Dh_o zN8mj&7Qoj4eu)Gog6G>*@JSxrzA<~dvpIa0*75p=UeK{A32F&B@ZKCxz(2it?h=sm z4LsL9sXh(V3UbbleZv$BD0Pr*_D#WCfH5E8{apf1=c+|OL{3!C^9#HRH8FqBBYQr8 zJw417idw6{QvTe@op`4~@+w$ngj0P3Ll_sd&1N3y%S`q<#I&i^k{k@vbMwkucMg2a2X~5{s06pKqUc0lpLFz9f_m!KvM2t^YKF2 z^gV&lXps_-9H2!2NYFM*NN5f|M}P-j34lZN2v8Exu5|!w8V|^w1TFC1X%Pe@;OTp0 z0VO1OvX-C-&;3#bG3rTjQy?NBI;A$B2G)|76oX)%T8hE(mG}U!eGqW&4p0^R^>Am9 zhy*1d=L4*^BLbS91)?ZWQZy+zd+~ZiLK2Gvc7hgo)CG97tE+&5ZyFPfw!E09P}U*> zWOxK{Ij=1qeb%LAV6-@DyF|jbA0Zhk3c3WmC2Iq3IUsChMd4OM#;LZDJ z8Db(_GAaUBSxaCv5}pfZ{RH9HGf(U>W>!@L_@g#e8OA~M`OCWy@iuEzB}4uUx%%g7OkeZ)U7pnuq|b z1i3f>-yJM2Pv^h6Z;nw|a4D#pb;m9rXD1JOa_nQGMO1 zqiH!weiOiTteav}M5iV`zRvk*3U5&H^$$Y70X->P64 zLDY9a$)e-Ha8!qYJUXAIU~ze107Pf;Ia~ST^fT0K@fwlAoDQoX0acDC72JkuI(^!c{kHH!RGVNQ1`+kq*{v}ozu0vo9)g_>4<}?f9(oqc6r=wah zJbbF_5a^ev(kM}be%@4@-eoO9bgCRg8KFbf;M+P2RUe4~Vh6BNxdD6{4DsbO4$deV zgg|T>j~BpUv6T>q%i&Pp2QRpJRZyvAaWX{ag)bYb$;KGN|LNxe1>F~iR&mF#n51lb?QGyuX z=lfXvu+3xQq2!V!@lAD3DTzq7a((DSqS!N{EJ>3u*J&(>ArNI?uz!Eq4|meMUabGJ z>Ed}mBGJZIGFI&}Ihg)82Hn*rw(bacy=RjzJ@z&3~H|WX)_To~L zgI^Q5#jUGuXkFTq$%5KDw8C?KTUt7os1q-O7lQsZu*+nA-DvZ&k=WhUH>$QLbpWFr zz#P|1ZzwdG`yLO@f76cI7TC)A9*^<}VXtnQV+nSotT!%%HC6+XNs@Um*UAm(+5WZv z--}I4`{R#%k}~#s_KG|!pnd1#qlvj2tG1?$Rg6S!)|l)FDI3=v9vZi}a9wuY&^fE7 z`rfQ~zP*)A#i8X%URE_#kB?WjuD+-9nsJ6qFz@L2{n+4*o5u&-52uW&(`K8lazjJD z1!{(i&#o*{DAHGNzf{v}!zA0orpAj~Z(BNiu8NiboWU96g{1xEOTC(l<4*f`Z6>?P zzP)?dh6uDj|4-1NXXKo?oJ|aB|MIevF0d}-ytceml7Duw`>`SWYj9lJuY4b(l)R%l zbNuvO?t|aQB8zsezFAXm*I`G#JU0`#X26oWo?S7kj`*5}zNvWL&W)&$?DFx>Or$RB zO`p-~a%1FiO1U)h`?3qx^N1(+oETkGOephQdm^p=^ykqo-|3z-c#yZwRaKle8QiYT zwGD{u^)M~$3$aZJ_ zM2ch{30tx$@88?{EV9-fXs2~MAL{Ua)dl1nQ27%NP@H;+Z6_}{#o3JUdtS~094jf# zj(x=6mS#wMP&Vn%&Uw+|>Ithhoz8CsfRMD4fuKXgnX0cRAEVx=Yqz}%5ma} zt!{hTtopyIboLxE)ZQbRC=Q*wXZ)h1#Q5}IVwF=Ok^7$f`3|+iUj#ij+q!N%T6FYC z)v3jcQ+&_ceU&!>Dm1PAww|wDZ8US1eOhc9Rjgj9lFj{RQgNqui<2Edu9pGNG&dKu zRLLiehj=>$CYMz+&n0#ZTp`7bUapAxQR)qL1IYzSNn(_jovGM^(31fi1NJ04q=S!4 z$Ah1yJTN_5;xTg^-d7YXaz5%b@ZgesqF?Z3$eTHB7v1eWw=}oKaOS`)uAI&U${U$+1?JALDI!05^FhD8dSuDFjOu9=M%l~cMnf_y1u=S^ug^uzsO3I>| zj%E4BE@%|5aka}=!vwpTFDwLY)L#xfd~@G+c_7_qc3sI<664@geKpa!y}y`kwbw82 z!5NBE_Y({AzWM6|yL0RJ)jp3lZ+jGBx=on)0}e}}h_#f3d~NpW`l7+kbB@|o#Ja_l z$R6PE;5?>fWf(ccb3sXy8axN>eW537R}gMLc}VNK`&o_s6WDm`YIC;ZoqS#QQ%eK# z>}5wz>v;dVnkpi#;a$s|44y_8<0gTh)pOyXY2{XzET?)`jz z&&Th1o>*x~VM_9@WB@>lyU685Yi|5c(xLg(7jI6ZWv5!;SIgvp8sQWO@&vg8V(uVU z3B8aL>JE;=YyfmeM4w;vdx}|J4jQ?*j4>JvAv6HlInfZuS3?!6fR&=;Fx(pY#(;@} z!?2I`m^`6;SS1$KE3mA-#K+fH^Ne7~c^1o#vPeM?svH&#)<|JC>M$(pWzjxvio}wS`U&LzSwASb~T|BF2c>C@Yl+%P@qAA}9(+5_q^yQn@HDg)lARMBcD_6%i$ct8vMEZ4gST+vPBz7o#8wtibaWO;KjtDlh_W zwOKg4!U`=oX|W2lz*$KK1`>MK!#izGCrwfo#>QAkvcT#zQ3Wn0pP@)AWv2?L1lBEu zRZikz!nTNPuVT#)#IpGck|0OIPsbCr z61NK~;%iXYqsT#QnQ2yB#|s-D;CRN2%8BL?4ZOvU+Zn-*3l_nOp3rPV46NXV`xsoQ zRCI$P2_+n212oN%c36Qk0&T}h5>aWVC=(tq@sx=%Q#Nyj#XukziFoncS4@d3RH5@x1$?0S<+q8ww=Dw`d36B3F#&un`+qW zTuj%$I(B6CbnM09p8Avp-ECP@{Xu$<=H<4Dd2Dl<>7$ci=EI>!%9>i5t7C<^S=ZB_ zyRrR_KKirTz4Iac#>*SWJjF+Q&nKn++kb2{_54EC?%HsAI{?4wv>MIVTlC!4E8ovO z)oyF@x20AYM?_ulOy|V5q$i&2o*UNm9W&N6cN}Wd!c3;4u&I4Z%y-8=TlnbY;G|bIll`~t`k!WKXp-3u9 zha6$B^-@&mTAnC&b!@S%P_p%mj(wg#diM8v{eIu?_w)U{-=F*S`tA4g*>-^qFq)g>D!fo5`j|1k%NE-U&009%ot827yxqk39=s01psuV z!l3QS?W}DSo+JjvS=2$r$4Iqk0B~`OmvVR_PzmRPkwUR6VydMb0T=RJ5h2bj3`^<> zMhU$V zcyggsDU^uei;NtuBv$E)(0ckYgcvD{^*6Ct@hMT-l%eA}QZyEYLC3@_#`Qs4p$q{3 z>&6$g6+sD75FG$2B(ZXywjKhT&tPrt{@Ku?qShOVuUx1t3MZN-;l;*)VkML2iqPJm z_(DDfPvmm3Ad!Q_;5Zy4+1Uw;Bst@`NIstrl1Lz4faME5^Lz4pzW|4aUgo`Jq1^c+TOLdfEpPHQ*0s>F4}J>LC*k zC@rkw_qnd7aPKg0l{YHgt?8-j<1&Tf{nWxu#k*%N*2_%o`5j~qt^ii{$gBr z6y!9jzsuLRs&j0w9>!*)C8apO{MO5>V+Bu31om^} zO>6lWaImJE5%Hkr`teI{6!MQlrKhij_v=ru8n+5kwPwnV*0B#DHbMpfVA>|S*hvs; zmF!eh>_qTL5a+0`oLqJyURfCUwEf|!sh4%4!|Lx)Mrh7A_k$NjHx7EVQt`wqAtKtb3Mm^~vh z*3xu+ru({~HbwdGTiTjCw5C?@x?9&|I$c~pY;<=pd+&>ZU~01oOdy)nL_5HPj4u*}g8k|-wWm{?%ZZr~QEx%s( z9=ga|n#1&Z5<8ibiTchz!k>AywS8-!I`dDixqALL$I&iWC-T}sJ)x}Q(SVT^Z9BAR zG%S3r*))9SQj!9N{I)5}G-)^UX$etfhhM(YGa6_#wCoRpTQHMNcC`lF)E{hh^n`dQ zDx{=iE0Zg9QVlYpV(2l`V@|~;^SJ8CkewAciI;CsC$G=WGtH>1uj)luW2W=mwJOsG zJKz7>ZGH0qeqo1rrmk&k){5*JBS7!ug@!5fz8%>m+nOTKe%1F={@ndrsXyYxKsa3Q zC;afQhWF;)7U=jz_#obQT2f6iN0kFAFive34D@!*y;Vpa-8a3TfzF!68L-=Ily)zM zQ$~zA4jYWe6npD&21g6_nIpz~^Vb^pNLvPiI~wBDR|DhrokCinu36ku?aXQ7T2Jnr ze=?Z+aMz%|Ei%*oKt7DQ^x^(j{5_;aNm{}iQk|MAUC4-^|KsP_UYCIJ*ZBoiboC08jJoEb*Tmp;R?-=IJM5$# zB+bwEST}d4``yi)_KZ%pDO}HHM&T@Nd$oW%Do1xgXGN%#JErI7cL`)uzKA-j)71gN zKIOtS(5NMED=8W?1Zx<$&~{x91H-u>r^)Cl^?kb#BuLyzsauz7M z+Vj$r$vYpTOZ875aW_-k9zVEp+XQcV^qKgHz6G%RPO_#o(J>o-vD=S?g*RxVid6S9 z;EtU^2B72fy?!_WCcapc6s=gclv-KlUXTyhsbC`}CAu`^#x}+77qmMDUu{jBc)-4Z z%Bp>!-t{bQZf*JRoe`_-YZMD(oM!7(=smddu90wM%F&3-Gs%qts&S(~RzIK4EER^| zBWo(Yj%?za-ZT>QJ|W~D3Auyu3oV^!>1A&o=8LOv*U#B2ELUyv1gO`a8>5bxTk>(?6+u8p(xb7^Amyv< zhTZC)^1Dl5l?G;@9NkJt^O=V$4=5%4dbype0LN#<_MkAG7x|NyR zf*((~kY|5I`d<0gaP|#+ZKk`rgM4d&hV3y_i$oE}zEN!)a3$1TpjOEv3OW>=bs z^0v|vpbD(@U(?)gE%VZ#MOCL=8Q&2)?%6yH0f4i?_1nwejg&#Ot=WDpu#cZU)^(D#nyf?xCAW9{;&9-Y@{NrWPeQ0%5cG`ac-6g^k literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00052[64x64x8BPP].png b/modules/game_shop/images/ex/00052[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..240e31df5be272e79dbdd272e5d473ec9df6e118 GIT binary patch literal 2082 zcmV+-2;KLIP)Px%`cO<%MF0Q*Fe4v8EF(`pIV2eu8d8EQ9vdK7h#XUa z9261_MRgxnhX4Qo8Wt55O?_EOLt$NC0XJr0RahMg2>}!)98`pZb9WIC4@o&Q0WMV& z5fOK4Z4wR)Hz_1TN=phta#>Ax7EXQ_78ZVa zhL@C>9#)1ENq9eQnbgU~7#JEie!6jFXCWUSk%5IEAtJ1zr7vxvKW~~eW|BciNIE}2 zH)oSPYnD80m@;CHje~q78W%DtB&eUG$Gp5bX_P^4nLTZoI%<_UX_Y!_mq$1=J8F~{ zPk%dWmjgR$13GFFN_sqNlmadAqYn450mrQMpPH&JtZkf!&zh8Kh&&0tROnDzwgGFhJ zG-HebE>_dX#6D}4IA@YHWRL|rYb05R3qWrxQ+Uq9!OFnBy0Wsiudo?WfI4cFIB1f~ z!M;Cjmm(4j&cndBuCH5lk4j{K7*KyuY>3RkztF|P$-cbByScNgt1ccG$iBQ-U}eF! zwZ*!*$-cYEzrDJzu*ST*#l5?TgOJ0xx0I2WhlY%$pP`I~k)E2Jz_qh|eTI&WlZk_c zhl7tfDI=bjoxZZNBoq#At zt*pATwV{}uv8$|#gpZ}1pSrQMrk>PsGgygkC>pE zoT{Lro|c`>J8owH0004WQchC_uJW#ZQ^i@jLYR1C8M{Fma);OD^rq*c$00#06tmNNtrmsyQr@fE#yfuFU%Vb zypc;vBpEHZTr!l&!{G>H(3(RZMwDj}mM7&b7$YL*DzrjT>c&$}z2VM>Qt7s~HiP9R zOfiOrzDYfK{du=O_(UrG^19cJDLD$pP+NPdeFEf}RQkmio=<|n_oc{e?@`Geq(7UyVF#rZ1 z-LfzdfKNZHeec~38$SDk{`LEB-(~q_dQm+s(LuS_c5Y)bHQb3H^Zc z15jlHg=`uI;5C{SCmjcnIhI%rQx8)r1u(7v4^Yz4Nh<7>Kr58W?RVh7ILtIgph8tO z($TC@Ez&&~g#Q3c4|atLRizZBfzplLb(~WwXB>|Pc7v5mX+=eaMl8#!+m71639yiG z!0rHm5P>Po0MMn%V`iX%Jz*R5PJ%wbKv-7S-eONxZYwqu3gFwYs)zDEKo7)17zXlj zyAgmr;Gjh;F2FkIQ5NL@@N@1vmBJdb2#N4Xowtz2j>`p5=-g)L0cmO>Fc3=Q&?9JU zSq=bS1iYTqwGg7J5z=%BJ!#gZIRelP(sU3R&xfJuU_CZV+)!@EUIJe`gw)sb#b{YX z%>t7VH^n05NE?7{JP&~B-LR%fY^NN6>^}s)8vy8nqn-g!cV%T}%SfPSISiy8+wnB~ zAkIA2uD37b%ySh1oQwlPApovWl#7-w6(eC;y|*a3X~r(R76pW&(U5s_3!MM9dc__J zSdnHlYF@Jv3HW5w)FJhCN+!B)!fy_9CGryTBvTOejHj1drU}0}OcObXA=8w6J`+Cg zgD{haKRG4lT)!4G3n58r6~%Dg5=p#rIvM}%6DnE17V`}St^&>mVM1_|P)D&+L-qJW5DL5Q~T^e@|Alf#ct!6g{Fm0O$AX{wv7ykeHekPV^P5=M^ M07*qoM6N<$f=BX~+yDRo literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00053[64x64x8BPP].png b/modules/game_shop/images/ex/00053[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..b89d8abc5cc47f2d6adb4e69a66a1578667e1d02 GIT binary patch literal 1487 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 SZe-B>gCUayh);>4Gyf0Q!ic2+ literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/ex/00060[64x64x8BPP].png b/modules/game_shop/images/ex/00060[64x64x8BPP].png new file mode 100644 index 0000000000000000000000000000000000000000..366ac193cbdd036b0903d3601a5bf2b95002d952 GIT binary patch literal 1486 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

+|q(zuE}J@Syy77 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 literal 0 HcmV?d00001 diff --git a/modules/game_shop/images/search.png b/modules/game_shop/images/search.png new file mode 100644 index 0000000000000000000000000000000000000000..b157e697891120ca9cd62096d1304e4d7b58eecb GIT binary patch literal 11279 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 K&@y?m=l=uVc*ku3 literal 0 HcmV?d00001 diff --git a/modules/game_shop/serverSIDE/data/creaturescripts/scripts/shopSERVER.lua b/modules/game_shop/serverSIDE/data/creaturescripts/scripts/shopSERVER.lua deleted file mode 100644 index 7f38b109f..000000000 --- a/modules/game_shop/serverSIDE/data/creaturescripts/scripts/shopSERVER.lua +++ /dev/null @@ -1,361 +0,0 @@ --- Instruction: --- creaturescripts.xml --- and in login.lua player:registerEvent("Shop") --- create sql table shop_history --- set variables --- set up function init(), add there items and categories, follow examples --- set up callbacks at the bottom to add player item/outfit/whatever you want - -local SHOP_EXTENDED_OPCODE = 201 -local SHOP_OFFERS = {} -local SHOP_CALLBACKS = {} -local SHOP_CATEGORIES = nil -local SHOP_BUY_URL = "http://otland.net" -- can be empty -local SHOP_AD = { -- can be nil - image = "", - url = "http://otclient.ovh", - text = "" -} -local MAX_PACKET_SIZE = 50000 --- local MAX_PACKET_SIZE = 5088 ---[[ SQL TABLE - -CREATE TABLE `shop_history` ( - `id` int(11) NOT NULL, - `account` int(11) NOT NULL, - `player` int(11) NOT NULL, - `date` datetime NOT NULL, - `title` varchar(100) NOT NULL, - `cost` int(11) NOT NULL, - `details` varchar(500) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; - -ALTER TABLE `shop_history` - ADD PRIMARY KEY (`id`); -ALTER TABLE `shop_history` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; - -]]-- - -function init() - -- print(json.encode(g_game.getLocalPlayer():getOutfit())) -- in console in otclient, will print current outfit and mount - - SHOP_CATEGORIES = {} - - local category1 = addCategory({ - type="item", - item=ItemType(2160):getClientId(), - count=100, - name="Items" - }) - local category2 = addCategory({ - type="outfit", - name="Outfits", - outfit={ - mount=0, - feet=114, - legs=114, - body=116, - type=143, - auxType=0, - addons=3, - head=2, - rotating=true - } - }) - local category3 = addCategory({ - type="image", - image="http://otclient.ovh/images/137.png", - name="Category with http image" - }) - local category4 = addCategory({ - type="image", - image="/data/images/game/states/electrified.png", - name="Category with local image" - }) - - - category1.addItem(1, 2160, 1, "1 Crystal coin", "description of cristal coin") - category1.addItem(5, 2160, 5, "5 Crystal coin", "description of cristal coin") - category1.addItem(50, 2160, 50, "50 Crystal coin", "description of cristal coin") - category1.addItem(90, 2160, 100, "100 Crystal coin", "description of cristal coin") - category1.addItem(200, 2493, 1, "Demon helmet1", "woo\ndemon helmet\nnice, you should buy it") - category1.addItem(1, 2160, 1, "1 Crystal coin1", "description of cristal coin") - category1.addItem(5, 2160, 5, "5 Crystal coin1", "description of cristal coin") - category1.addItem(50, 2160, 50, "50 Crystal coin1", "description of cristal coin") - category1.addItem(90, 2160, 100, "100 Crystal coin1", "description of cristal coin") - category1.addItem(200, 2493, 1, "Demon helmet2", "woo\ndemon helmet\nnice, you should buy it") - category1.addItem(1, 2160, 1, "1 Crystal coin3", "description of cristal coin") - category1.addItem(5, 2160, 5, "5 Crystal coin3", "description of cristal coin") - category1.addItem(50, 2160, 50, "50 Crystal coin3", "description of cristal coin") - category1.addItem(90, 2160, 100, "100 Crystal coin3", "description of cristal coin") - category1.addItem(200, 2493, 1, "Demon helmet3", "wooxD\ndemon helmet\nnice, you should buy it") - - category2.addOutfit(500, { - mount=0, - feet=114, - legs=114, - body=116, - type=143, - auxType=0, - addons=3, - head=2, - rotating=true - }, "title of this cool outfit or whatever", "this is your new cool outfit. You can buy it here.\nsrlsy") - category2.addOutfit(100, { - mount=682, - feet=0, - legs=0, - body=0, - type=143, - auxType=0, - addons=0, - head=0, - rotating=true - }, "MOUNT!!!", "DOUBLE CLICK TO BUY THIS MOUNT. IDK NAME") - - category2.addOutfit(100, { - mount=0, - feet=0, - legs=0, - body=0, - type=35, - auxType=0, - addons=0, - head=0, - rotating=true - }, "Demon outfit", "Want be a demon?\nNo problem") - category2.addOutfit(100, { - mount=0, - feet=0, - legs=0, - body=0, - type=35, - auxType=0, - addons=0, - head=0, - rotating=false - }, "Demon outfit2", "This one is not rotating") - - category4.addImage(10000, "/data/images/game/states/haste.png", "Offer with local image", "another local image\n/data/images/game/states/haste.png") - category4.addImage(10000, "http://otclient.ovh/images/freezing.png", "Offer with remote image and custom buy action", "blalasdasd image\nhttp://otclient.ovh/images/freezing.png", customImageBuyAction) -end - -function addCategory(data) - data['offers'] = {} - table.insert(SHOP_CATEGORIES, data) - table.insert(SHOP_CALLBACKS, {}) - local index = #SHOP_CATEGORIES - return { - addItem = function(cost, itemId, count, title, description, callback) - if not callback then - callback = defaultItemBuyAction - end - table.insert(SHOP_CATEGORIES[index]['offers'], { - cost=cost, - type="item", - item=ItemType(itemId):getClientId(), -- displayed - itemId=itemId, - count=count, - title=title, - description=description - }) - table.insert(SHOP_CALLBACKS[index], callback) - end, - addOutfit = function(cost, outfit, title, description, callback) - if not callback then - callback = defaultOutfitBuyAction - end - 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) - if not callback then - callback = defaultImageBuyAction - end - table.insert(SHOP_CATEGORIES[index]['offers'], { - cost=cost, - type="image", - image=image, - title=title, - description=description - }) - table.insert(SHOP_CALLBACKS[index], callback) - end - } -end - -function getPoints(player) - local points = 0 - local resultId = db.storeQuery("SELECT `premium_points` FROM `accounts` WHERE `id` = " .. player:getAccountId()) - if resultId ~= false then - points = result.getDataInt(resultId, "premium_points") - result.free(resultId) - end - return points -end - -function getStatus(player) - local status = { - ad = SHOP_AD, - points = getPoints(player), - buyUrl = SHOP_BUY_URL - } - return status -end - -function sendJSON(player, action, data, forceStatus) - local status = nil - if not player:getStorageValue(1150001) or player:getStorageValue(1150001) + 10 < os.time() or forceStatus then - status = getStatus(player) - end - player:setStorageValue(1150001, os.time()) - - - local buffer = json.encode({action = action, data = data, status = status}) - local s = {} - for i=1, #buffer, MAX_PACKET_SIZE do - s[#s+1] = buffer:sub(i,i+MAX_PACKET_SIZE - 1) - end - local msg = NetworkMessage() - if #s == 1 then - msg:addByte(50) - msg:addByte(SHOP_EXTENDED_OPCODE) - msg:addString(s[1]) - msg:sendToPlayer(player) - return - end - -- split message if too big - msg:addByte(50) - msg:addByte(SHOP_EXTENDED_OPCODE) - msg:addString("S" .. s[1]) - msg:sendToPlayer(player) - for i=2,#s - 1 do - msg = NetworkMessage() - msg:addByte(50) - msg:addByte(SHOP_EXTENDED_OPCODE) - msg:addString("P" .. s[i]) - msg:sendToPlayer(player) - end - msg = NetworkMessage() - msg:addByte(50) - msg:addByte(SHOP_EXTENDED_OPCODE) - msg:addString("E" .. s[#s]) - msg:sendToPlayer(player) -end - -function sendMessage(player, title, msg, forceStatus) - sendJSON(player, "message", {title=title, msg=msg}, forceStatus) -end - -function onExtendedOpcode(player, opcode, buffer) - if opcode ~= SHOP_EXTENDED_OPCODE then - return false - end - local status, json_data = pcall(function() return json.decode(buffer) end) - if not status then - return false - end - - local action = json_data['action'] - local data = json_data['data'] - if not action or not data then - return false - end - - if SHOP_CATEGORIES == nil then - init() - end - - if action == 'init' then - sendJSON(player, "categories", SHOP_CATEGORIES) - elseif action == 'buy' then - processBuy(player, data) - elseif action == "history" then - sendHistory(player) - end - return true -end - -function processBuy(player, data) - local categoryId = tonumber(data["category"]) - local offerId = tonumber(data["offer"]) - local offer = SHOP_CATEGORIES[categoryId]['offers'][offerId] - local callback = SHOP_CALLBACKS[categoryId][offerId] - if not offer or not callback or data["title"] ~= offer["title"] or data["cost"] ~= offer["cost"] then - sendJSON(player, "categories", SHOP_CATEGORIES) -- refresh categories, maybe invalid - return sendMessage(player, "Error!", "Invalid offer") - end - local points = getPoints(player) - if not offer['cost'] or offer['cost'] > points or points < 1 then - return sendMessage(player, "Error!", "You don't have enough points to buy " .. offer['title'] .."!", true) - end - local status = callback(player, offer) - if status == true then - db.query("UPDATE `accounts` set `premium_points` = `premium_points` - " .. offer['cost'] .. " WHERE `id` = " .. player:getAccountId()) - 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 sendMessage(player, "Success!", "You bought " .. offer['title'] .."!", true) - end - if status == nil or status == false then - status = "Unknown error while buying " .. offer['title'] - end - sendMessage(player, "Error!", status) -end - -function sendHistory(player) - if player:getStorageValue(1150002) and player:getStorageValue(1150002) + 10 > os.time() then - return -- min 10s delay - end - player:setStorageValue(1150002, os.time()) - - local history = {} - local resultId = db.storeQuery("SELECT * FROM `shop_history` WHERE `account` = " .. player:getAccountId() .. " order by `id` DESC") - - if resultId ~= false then - repeat - local details = result.getDataString(resultId, "details") - local status, json_data = pcall(function() return json.decode(details) end) - if not status then - json_data = { - type = "image", - title = result.getDataString(resultId, "title"), - cost = result.getDataInt(resultId, "cost") - } - end - table.insert(history, json_data) - history[#history]["description"] = "Bought on " .. result.getDataString(resultId, "date") .. " for " .. result.getDataInt(resultId, "cost") .. " points." - until not result.next(resultId) - result.free(resultId) - end - - sendJSON(player, "history", history) -end - --- BUY CALLBACKS --- May be useful: print(json.encode(offer)) - -function defaultItemBuyAction(player, offer) - -- todo: check if has capacity - if player:addItem(offer["itemId"], offer["count"], false) then - return true - end - return "Can't add item! Do you have enough space?" -end - -function defaultOutfitBuyAction(player, offer) - return "default outfit buy action is not implemented" -end - -function defaultImageBuyAction(player, offer) - return "default image buy action is not implemented" -end - -function customImageBuyAction(player, offer) - return "custom image buy action is not implemented. Offer: " .. offer['title'] -end \ No newline at end of file diff --git a/modules/game_shop/serverSIDE/data/scripts/game_shop.lua b/modules/game_shop/serverSIDE/data/scripts/game_shop.lua new file mode 100644 index 000000000..fd0756b86 --- /dev/null +++ b/modules/game_shop/serverSIDE/data/scripts/game_shop.lua @@ -0,0 +1,846 @@ +local DONATION_URL = "https://github.com/mehah/otclient" +local GAME_SHOP = nil +local SECOND_CURRENCY_ENABLED = false + +local LoginEvent = CreatureEvent("GameShopLogin") + +local chars = { + ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', + 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', + 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', + 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' +} + +local ExtendedOPCodes = { + CODE_GAMESHOP = 201 +} + +local forbiddenWords = { +'gm','adm','tutor','god','cm','admin','owner','g m','g o d','g0d','g 0 d','c m','administrator','senior','a d m', +'Trainer','Devil My Cry','Lavahole','Deaththrower','A Carved Stone Tile','Acolyte Of The Cult','Adept Of The Cult','Amazon','Ancient Scarab','Ashmunrah','Assassin','Azure Frog','Badger','Bandit','Banshee','Barbarian Bloodwalker','Barbarian Brutetamer','Barbarian Headsplitter','Barbarian Skullhunter','Bat','Bear','Behemoth','Beholder','Betrayed Wraith','Black Knight','Black Sheep','Blightwalker','Blood Crab','Blue Butterfly','Blue Djinn','Bonebeast','Braindeath','Bug','Carniphila','Carrion Worm','Cave Rat','Centipede','Chakoya Toolshaper','Chakoya Tribewarden','Chakoya Windcaller','Chicken','Cobra','Coral Frog','Crab','Crimson Frog','Crocodile','Crypt Shambler','Crystal Spider','Cyclops','Dark Magician','Dark Monk','Dark Torturer','Deathslicer','Deer','Defiler','Demon Skeleton','Demon','Destroyer','Diabolic Imp','Dipthrah','Dog','Dragon Lord','Dragon','Dwarf Geomancer','Dwarf Guard','Dwarf Soldier','Dwarf','Dworc Fleshhunter','Dworc Venomsniper','Dworc Voodoomaster','Efreet','Elder Beholder','Elephant','Elf Arcanist','Elf Scout','Elf','Enlightened Of The Cult','Eye Of The Seven','Fire Devil','Fire Elemental','Flamethrower','Flamingo','Frost Dragon','Frost Giant','Frost Giantess','Frost Troll','Fury','Gargoyle','Gazer','Ghost','Ghoul','Giant Spider','Goblin','Green Djinn','Green Frog','Hand Of Cursed Fate','Hell Hole','Hellfire Fighter','Hellhound','Hero','Hunter','Husky','Hyaena','Hydra','Ice Golem','Ice Witch','Juggernaut','Kongra','Larva','Lich','Lion','Lizard Noble','Lizard Sentinel','Lizard Snakecharmer','Lizard Templar','Lost Soul','Magic Pillar','Magicthrower','Mahrdis','Mammoth','Marid','Massive Fire Elemental','Massive Water Elemental','Merlkin','Minotaur Archer','Minotaur Guard','Minotaur Mage','Minotaur','Monk','Morguthis','Mummy','Necromancer','Nightmare','Nomad','Novice Of The Cult','Omruc','Orc Berserker','Orc Leader','Orc Rider','Orc Shaman','Orc Spearman','Orc Warlord','Orc Warrior','Orc','Orchid Frog','Panda','Parrot','Penguin','Phantasm Summon','Phantasm','Pig','Pillar','Pirate Buccaneer','Pirate Corsair','Pirate Cutthroat','Pirate Ghost','Pirate Marauder','Pirate Skeleton','Plaguesmith','Plaguethrower','Poison Spider','Polar Bear','Priestess','Purple Butterfly','Quara Constrictor Scout','Quara Constrictor','Quara Hydromancer Scout','Quara Hydromancer','Quara Mantassin Scout','Quara Mantassin','Quara Pincher Scout','Quara Pincher','Quara Predator Scout','Quara Predator','Rabbit','Rahemos','Rat','Red Butterfly','Rotworm','Scarab','Scorpion','Seagull','Serpent Spawn','Sheep','Shredderthrower','Sibang','Silver Rabbit','Skeleton','Skunk','Slime','Smuggler','Snake','Son Of Verminor','Spectre','Spider','Spit Nettle','Stalker','Stone Golem','Swamp Troll','Tarantula','Terror Bird','Thalas','Thornback Tortoise','Tiger','Toad','Tortoise','Troll','Undead Dragon','Valkyrie','Vampire','Vashresamun','War wolf','Warlock','Wasp','Wild Warrior','Winter Wolf','Witch','Wolf','Wyvern','Yellow Butterfly','Yeti','Annihilon','Apprentice Sheng','Barbaria','Bones','Brutus Bloodbeard','Countess Sorrow','Deadeye Devious','Demodras','Dharalion','Dire Penguin','Dracola','Fernfang','Ferumbras','Fluffy','Foreman Kneebiter','General Murius','Ghazbaran','Golgordan','Grorlam','Hairman The Huge', 'Hellgorak','Koshei The Deathless','Latrivan','Lethal Lissy','Mad Technomancer','Madareth','Man In The Cave','Massacre','Minishabaal','Morgaroth','Mr. Punish','Munster','Necropharus','Orshabaal', 'Ron the Ripper','The Abomination','The Evil Eye','The Handmaiden','The Horned Fox','The Imperor','The Old Widow','The Plasmother','Thul','Tiquandas Revenge','Undead Minion','Ungreez','Ushuriel','Xenia','Zugurosh' +} + +local maxWords = 5 +local maxLength = 20 +local minChars = 2 + +function LoginEvent.onLogin(player) + player:registerEvent("GameShopExtended") + return true +end + +local CATEGORY_NONE = -1 +local CATEGORY_PREMIUM = 0 +local CATEGORY_ITEM = 1 +local CATEGORY_BLESSING = 2 +local CATEGORY_OUTFIT = 3 +local CATEGORY_MOUNT = 4 +local CATEGORY_EXTRAS = 5 + +local HEALTH_POTION_DESCRIPTION = "Restores your character's hit points.\n\n- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded" +local MANA_POTION_DESCRIPTION = "Refills your character's mana.\n\n- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded" + +function gameShopInitialize() + GAME_SHOP = { + categories = {}, + categoriesId = {}, + offers = {} + } + + addCategory(nil, "Premium Time", 20, CATEGORY_PREMIUM, "Enhance your gaming experience by gaining additional abilities and advantages:\n\n* access to Premium areas\n* use Tibia's transport system (ships, carpet)\n* more spells\n* rent houses\n* found guilds\n* larger Depots\n* and many more\n\n- valid for all characters on this account\n- activated at purchase") + addItem("Premium Time", "30 Days of Premium Time", "30_days", 250, false, 30) + addItem("Premium Time", "90 Days of Premium Time", "90_days", 750, false, 90) + addItem("Premium Time", "180 Days of Premium Time", "180_days", 1500, false, 180) + addItem("Premium Time", "360 Days of Premium Time", "360_days", 3000, false, 360) + + addCategory(nil, "Consumables", 6, CATEGORY_NONE) + addCategory("Consumables", "Blessings", 8, CATEGORY_BLESSING, "Reduces your character's chance to lose any items as well as the amount of your character's experience and skill loss upon death:\n\n* 1 blessing = 8.00% less Skill / XP loss, 30% equipment protection\n* 2 blessing = 16.00% less Skill / XP loss, 55% equipment protection\n* 3 blessing = 24.00% less Skill / XP loss, 75% equipment protection\n* 4 blessing = 32.00% less Skill / XP loss, 90% equipment protection\n* 5 blessing = 40.00% less Skill / XP loss, 100% equipment protection\n* 6 blessing = 48.00% less Skill / XP loss, 100% equipment protection\n* 7 blessing = 56.00% less Skill / XP loss, 100% equipment protection\n\n- only usable by purchasing character\n- maximum amount that can be owned by character: 5\n- added directly to the Record of Blessings\n- characters with a red or black skull will always lose all equipment upon death") + addItem("Blessings", "All regular Blessings", "All_regular_Blessings", 130, false, -1) + addItem("Blessings", "The Spiritual Shielding", "The_Spiritual_Shielding", 25, false, 1) + addItem("Blessings", "The Embrace of Tibia", "The_Embrace_of_Tibia", 25, false, 2) + addItem("Blessings", "The Fire of the Suns", "The_Fire_of_the_Suns", 25, false, 3) + addItem("Blessings", "The Wisdom of Solitude", "The_Wisdom_of_Solitude", 25, false, 4) + addItem("Blessings", "The Spark of the Phoenix", "The_Spark_of_the_Phoenix", 25, false, 5) + + addCategory("Consumables", "Potions", 10, CATEGORY_ITEM) + addItem("Potions", "Mana Potion", 7620, 6, false, 125, MANA_POTION_DESCRIPTION) + addItem("Potions", "Mana Potion", 7620, 12, false, 300, MANA_POTION_DESCRIPTION) + addItem("Potions", "Strong Mana Potion", 7589, 7, false, 100, MANA_POTION_DESCRIPTION) + addItem("Potions", "Strong Mana Potion", 7589, 17, false, 250, MANA_POTION_DESCRIPTION) + addItem("Potions", "Great Mana Potion", 7590, 11, false, 100, MANA_POTION_DESCRIPTION) + addItem("Potions", "Great Mana Potion", 7590, 26, false, 250, MANA_POTION_DESCRIPTION) + addItem("Potions", "Health Potion", 7618, 6, false, 125, HEALTH_POTION_DESCRIPTION) + addItem("Potions", "Health Potion", 7618, 11, false, 300, HEALTH_POTION_DESCRIPTION) + addItem("Potions", "Strong Health Potion", 7588, 10, false, 100, HEALTH_POTION_DESCRIPTION) + addItem("Potions", "Strong Health Potion", 7588, 21, false, 250, HEALTH_POTION_DESCRIPTION) + addItem("Potions", "Great Health Potion", 7591, 18, false, 100, HEALTH_POTION_DESCRIPTION) + addItem("Potions", "Great Health Potion", 7591, 41, false, 250, HEALTH_POTION_DESCRIPTION) + + addCategory("Consumables", "Runes", 19, CATEGORY_ITEM) + addItem("Runes", "Animate Dead Rune", 2316, 75, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nAfter a long time of research, the magicians of Edron succeeded in storing some life energy in a rune. When this energy was unleashed onto a body it was found that an undead creature arose that could be mentally controlled by the user of the rune. This rune is useful to create allies in combat.") + addItem("Runes", "Avalanche Rune", 2274, 12, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThe ice damage which arises from this rune is a useful weapon in every battle but it comes in particularly handy if you fight against a horde of creatures dominated by the element fire.") + addItem("Runes", "Chameleon Rune", 2291, 42, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThe metamorphosis caused by this rune is only superficial, and while casters who are using the rune can take on the exterior form of nearly any inanimate object, they will always retain their original smell and mental abilities. So there is no real practical use for this rune, making this largely a fun rune.") + addItem("Runes", "Convince Creature Rune", 2290, 16, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nUsing this rune together with some mana, you can convince certain creatures. The needed amount of mana is determined by the power of the creature one wishes to convince, so the amount of mana to convince a rat is lower than that which is needed for an orc.") + addItem("Runes", "Cure Poison Rune", 2266, 13, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nIn the old days, many adventurers fell prey to poisonous creatures that were roaming the caves and forests. After many years of research druids finally succeeded in altering the cure poison spell so it could be bound to a rune. By using this rune it is possible to stop the effect of any known poison.") + addItem("Runes", "Disintegrate Rune", 2310, 5, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nNothing is worse than being cornered when fleeing from an enemy you just cannot beat, especially if the obstacles in your way are items you could easily remove if only you had the time! However, there is one reliable remedy: The Disintegrate rune will instantly destroy up to 500 movable items that are in your way, making room for a quick escape.") + addItem("Runes", "Energy Bomb Rune", 2262, 40, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nUsing the Energy Bomb rune will create a field of deadly energy that deals damage to all who carelessly step into it. Its area of effect is covering a full 9 square metres! Creatures that are caught in the middle of an Energy Bomb are frequently confused by the unexpected effect, and some may even stay in the field of deadly sparks for a while.") + addItem("Runes", "Energy Field Rune", 2277, 8, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis spell creates a limited barrier made up of crackling energy that will cause electrical damage to all those passing through. Since there are few creatures that are immune to the harmful effects of energy this spell is not to be underestimated.") + addItem("Runes", "Energy Wall Rune", 2279, 17, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nCasting this spell generates a solid wall made up of magical energy. Walls made this way surpass any other magically created obstacle in width, so it is always a good idea to have an Energy Wall rune or two in one's pocket when travelling through the wilderness.") + addItem("Runes", "Explosion Rune", 2313, 6, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis rune must be aimed at areas rather than at specific creatures, so it is possible for explosions to be unleashed even if no targets are close at all. These explosions cause a considerable physical damage within a substantial blast radius.") + addItem("Runes", "Fireball Rune", 2302, 6, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nWhen this rune is used a massive fiery ball is released which hits the aimed foe with immense power. It is especially effective against opponents of the element earth.") + addItem("Runes", "Fire Bomb Rune", 2305, 29, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis rune is a deadly weapon in the hands of the skilled user. On releasing it an area of 9 square metres is covered by searing flames that will scorch all those that are unfortunate enough to be caught in them. Worse, many monsters are confused by the unexpected blaze, and with a bit of luck a caster will even manage to trap his opponents by using the spell.") + addItem("Runes", "Fire Field Rune", 2301, 6, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nWhen this rune is used a field of one square metre is covered by searing fire that will last for some minutes, gradually diminishing as the blaze wears down. As with all field spells, Fire Field is quite useful to block narrow passageways or to create large, connected barriers.") + addItem("Runes", "Fire Wall Rune", 2303, 12, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis rune offers reliable protection against all creatures that are afraid of fire. The exceptionally long duration of the spell as well as the possibility to form massive barriers or even protective circles out of fire walls make this a versatile, practical spell.") + addItem("Runes", "Great Fireball Rune", 2304, 12, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nA shot of this rune affects a huge area - up to 37 square metres! It stands to reason that the Great Fireball is a favourite of most Tibians, as it is well suited both to hit whole crowds of monsters and individual targets that are difficult to hit because they are fast or hard to spot.") + addItem("Runes", "Icicle Rune", 2271, 6, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nParticularly creatures determined by the element fire are vulnerable against this ice-cold rune. Being hit by the magic stored in this rune, an ice arrow seems to pierce the heart of the struck victim. The damage done by this rune is quite impressive which makes this a quite popular rune among Tibian mages.") + addItem("Runes", "Intense Healing Rune", 2265, 19, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis rune is commonly used by young adventurers who are not skilled enough to use the rune's stronger version. Also, since the rune's effectiveness is determined by the user's magic skill, it is still popular among experienced spell casters who use it to get effective healing magic at a cheap price.") + addItem("Runes", "Magic Wall Rune", 2293, 23, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis spell causes all particles that are contained in the surrounding air to quickly gather and contract until a solid wall is formed that covers one full square metre. The wall that is formed that way is impenetrable to any missiles or to light and no creature or character can walk through it. However, the wall will only last for a couple of seconds.") + addItem("Runes", "Poison Bomb Rune", 2286, 19, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThis rune causes an area of 9 square metres to be contaminated with toxic gas that will poison anybody who is caught within it. Conceivable applications include the blocking of areas or the combat against fast-moving or invisible targets. Keep in mind, however, that there are a number of creatures that are immune to poison.") + addItem("Runes", "Poison Wall Rune", 2289, 10, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nWhen this rune is used a wall of concentrated toxic fumes is created which inflicts a moderate poison on all those who are foolish enough to enter it. The effect is usually impressive enough to discourage monsters from doing so, although few of the stronger ones will hesitate if there is nothing but a poison wall between them and their dinner.") + addItem("Runes", "Soulfire Rune", 2308, 9, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nSoulfire is an immensely evil spell as it directly targets a creature's very life essence. When the rune is used on a victim, its soul is temporarily moved out of its body, casting it down into the blazing fires of hell itself! Note that the experience and the mental strength of the caster influence the damage that is caused.") + addItem("Runes", "Stone Shower Rune", 2288, 9, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nParticularly creatures with an affection to energy will suffer greatly from this rune filled with powerful earth damage. As the name already says, a shower of stones drums on the opponents of the rune user in an area up to 37 squares.") + addItem("Runes", "Sudden Death Rune", 2268, 28, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nNearly no other spell can compare to Sudden Death when it comes to sheer damage. For this reason it is immensely popular despite the fact that only a single target is affected. However, since the damage caused by the rune is of deadly nature, it is less useful against most undead creatures.") + addItem("Runes", "Thunderstorm Rune", 2315, 9, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nFlashes filled with dangerous energy hit the rune user's opponent when this rune is being used. It is especially effective against ice dominated creatures. Covering up an area up to 37 squares, this rune is particularly useful when you meet a whole mob of opponents.") + addItem("Runes", "Ultimate Healing Rune", 2273, 35, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nThe coveted Ultimate Healing rune is an all-time favourite among all vocations. No other healing enchantments that are bound into runes can compare to its salutary effect.") + addItem("Runes", "Wild Growth Rune", 2269, 32, false, 250, "- only usable by purchasing character\n- will be sent to your backpack\n- cannot be purchased by characters with protection zone block or battle sign\n- cannot be purchased if capacity is exceeded\n\nBy unleashing this spell, all seeds that are lying dormant in the surrounding quickly sprout and grow into full-sized plants, thus forming an impenetrable thicket. Unfortunately, plant life created this way is short-lived and will collapse within minutes, so the magically created obstacle will not last long.") + + addCategory(nil, "Cosmetics", 21, CATEGORY_NONE) + addCategory("Cosmetics", "Mounts", 14, CATEGORY_MOUNT) + addItem("Mounts", "Arctic Unicorn", 1018, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Arctic Unicorn lives in a deep rivalry with its cousin the Blazing Unicorn. Even though they were born in completely different areas, they somehow share the same bloodline. The eternal battle between fire and ice continues. Who will win? Tangerine vs.crystal blue! The choice is yours!") + addItem("Mounts", "Armoured War Horse", 426, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Armoured War Horse is a dangerous black beauty! When you see its threatening, blood-red eyes coming towards you, you'll know trouble is on its way. Protected by its heavy armour plates, the warhorse is the perfect partner for dangerous hunting sessions and excessive enemy slaughtering.") + addItem("Mounts", "Batcat", 728, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nRumour has it that many years ago elder witches had gathered to hold a magical feast high up in the mountains. They had crossbred Batcat to easily conquer rocky canyons and deep valleys. Nobody knows what happened on their way up but only the mount has been seen ever since.") + addItem("Mounts", "Battle Badger", 1247, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBadgers have been a staple of the Tibian fauna for a long time, and finally some daring souls have braved the challenge to tame some exceptional specimens - and succeeded! While the common badger you can encounter during your travels might seem like a rather unassuming creature, the Battle Badger, the Ether Badger, and the Zaoan Badger are fierce and mighty beasts, which are at your beck and call.") + addItem("Mounts", "Black Stag", 686, 660, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nTreat your character to a new travelling companion with a gentle nature and an impressive antler: The noble Black Stag will carry you through the deepest snow.") + addItem("Mounts", "Blackpelt", 651, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Blackpelt is out searching for the best bamboo in Tibia. Its heavy armour allows it to visit even the most dangerous places. Treat it nicely with its favourite food from time to time and it will become a loyal partner.") + addItem("Mounts", "Blazing Unicorn", 1017, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Blazing Unicorn lives in a deep rivalry with its cousin the Arctic Unicorn. Even though they were born in completely different areas, they somehow share the same bloodline. The eternal battle between fire and ice continues. Who will win? Crystal blue vs. tangerine! The choice is yours!") + addItem("Mounts", "Bloodcurl", 869, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYou are fascinated by insectoid creatures and can picture yourself riding one during combat or just for travelling? The Bloodcurl will carry you through the Tibian wilderness with ease.") + addItem("Mounts", "Bog Tyrant", 1743, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThis monstrous creature lords over swamps, its body covered in toxic moss and grime.") + addItem("Mounts", "Bogwurm", 1447, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBurrowing from the depths of forgotten tunnels, this creature thrives in the shadows. The Bogwurm is as tough as steel and as fast as fear.") + addItem("Mounts", "Boisterous Bull", 1672, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA symbol of raw power and determination. The Boisterous Bull is as loud as it is loyal.") + addItem("Mounts", "Boreal Owl", 1106, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOwls have always been a symbol of mystery, magic and wisdom in Tibian myths and fairy tales. Having one of these enigmatic creatures of the night as a trustworthy companion provides you with a silent guide whose ever-watchful eyes will cut through the shadows, help you navigate the darkness and unravel great secrets.") + addItem("Mounts", "Brass Speckled Koi", 1609, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nElegant, serene, and ever-gliding — these koi mounts are symbols of balance and beauty.") + addItem("Mounts", "Bumblebee", 1778, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBuzzing with energy, the Bumblebee zips through the skies leaving a trail of pollen and sparks.") + addItem("Mounts", "Bunny Dray", 1180, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYour lower back worsens with every trip you spend on the back of your mount and you are looking for a more comfortable alternative to travel through the lands? Say no more! The Bunny Dray comes with two top-performing hares that never get tired thanks to the brand new and highly innovative propulsion technology. Just keep some back-up carrots in your pocket and you will be fine!") + addItem("Mounts", "Caped Snowman", 1169, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWhen the nights are getting longer and freezing wind brings driving snow into the land, snowmen rise and shine on every corner. Lately, a peaceful, arcane creature has found shelter in one of them and used its magical power to call the Caped Snowman into being. Wrap yourself up well and warmly and jump on the back of your new frosty companion.") + addItem("Mounts", "Cave Tarantula", 1026, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIt is said that the Cave Tarantula was born long before Banor walked the earth of Tibia. While its parents died in the war against the cruel hordes sent by Brog and Zathroth, their child survived by hiding in skulls of burned enemies. It never left its hiding spot and as it grew older, the skulls merged into its body. Now, it is fully-grown and thirsts for revenge.") + addItem("Mounts", "Cerberus Champion", 1209, 1250, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA fierce and grim guardian of the underworld has risen to fight side by side with the bravest warriors in order to send evil creatures into the realm of the dead. The three headed Cerberus Champion is constantly baying for blood and using its sharp fangs it easily rips apart even the strongest armour and shield.") + addItem("Mounts", "Cinderhoof", 851, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf you are more of an imp than an angel, you may prefer riding out on a Cinderhoof to scare fellow Tibians on their festive strolls. Its devilish mask, claw-like hands and sharp hooves makes it the perfect companion for any daring adventurer who likes to stand out.") + -- addItem("Mounts", "Cinnamon Ibex", 1528, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSurefooted and resilient, these ibexes were raised among mountain peaks. Their floral names are a nod to the patches of wildflowers found high above the clouds.") + -- addItem("Mounts", "Cony Cart", 1181, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYour lower back worsens with every trip you spend on the back of your mount and you are looking for a more comfortable alternative to travel through the lands? Say no more! The Cony Cart comes with two top-performing hares that never get tired thanks to the brand new and highly innovative propulsion technology. Just keep some back-up carrots in your pocket and you will be fine!") + -- addItem("Mounts", "Copper Fly", 671, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf you are more interested in the achievements of science, you may enjoy a ride on the Copper Fly, one of the new insect-like flying machines. Even if you do not move around, the wings of these unusual vehicles are always in motion.") + -- addItem("Mounts", "Coral Rhea", 1325, 500, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nDespite their inability to fly, these strong-legged birds are lightning-fast and utterly reliable when crossing large distances over dry terrain.") + -- addItem("Mounts", "Coralripper", 735, 570, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf the Coralripper moves its fins, it generates enough air pressure that it can even float over land. Its numerous eyes allow it to quickly detect dangers even in confusing situations and eliminate them with one powerful bite. If you watch your fingers, you are going to be good friends.") + -- addItem("Mounts", "Corpsefire Skull", 1687, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nForged from cursed bones and shadowed flame, this skull mount is only tamed by death itself.") + -- addItem("Mounts", "Cranium Spider", 1025, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIt is said that the Cranium Spider was born long before Banor walked the earth of Tibia. While its parents died in the war against the cruel hordes sent by Brog and Zathroth, their child survived by hiding in skulls of burned enemies. It never left its hiding spot and as it grew older, the skulls merged into its body. Now, it is fully-grown and thirsts for revenge.") + -- addItem("Mounts", "Crimson Fang", 1744, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBlood-red and battle-scarred, this predator obeys no one except its chosen rider.") + -- addItem("Mounts", "Crimson Ray", 521, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nHave you ever dreamed of gliding through the air on the back of a winged creature? With its deep red wings, the majestic Crimson Ray is a worthy mount for courageous heroes. Feel like a king on its back as you ride into your next adventure.") + -- addItem("Mounts", "Cunning Hyaena", 1334, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese rugged animals are fearsome in packs and cunning when left alone. Riding one gives you not only speed but a fearsome reputation.") + -- addItem("Mounts", "Dandelion", 1441, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese graceful mounts are named after the vibrant flowers they resemble. They are calm, enduring, and add a blooming touch to your journey.") + -- addItem("Mounts", "Darkfire Devourer", 1677, 1300, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nFrom the deepest rift beneath hell, the Darkfire Devourer hungers for conquest. Only the strongest may ride it.") + -- addItem("Mounts", "Dawn Strayer", 1286, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSome spirits are born from pure elements. The Dawn Strayer is a beacon of hope and a bringer of light. Ride it to greet the new day and strike fear into the hearts of nocturnal foes.") + -- addItem("Mounts", "Dawnbringer Pegasus", 1727, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA majestic celestial horse born of morning light, it shines with hope.") + -- addItem("Mounts", "Death Crawler", 624, 600, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Death Crawler is a scorpion that has surpassed the natural boundaries of its own kind. Way bigger, stronger and faster than ordinary scorpions, it makes a perfect companion for fearless heroes and explorers. Just be careful of his poisonous sting when you mount it.") + -- addItem("Mounts", "Desert King", 572, 450, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIts roaring is piercing marrow and bone and can be heard over ten miles away. The Desert King is the undisputed ruler of its territory and no one messes with this animal. Show no fear and prove yourself worthy of its trust and you will get yourself a valuable companion for your adventures.") + -- addItem("Mounts", "Doom Skull", 1685, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nForged from cursed bones and shadowed flame, this skull mount is only tamed by death itself.") + -- addItem("Mounts", "Doombringer", 644, 780, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce captured and held captive by a mad hunter, the Doombringer is the result of sick experiments. Fed only with demon dust and concentrated demonic blood it had to endure a dreadful transformation. The demonic blood that is now running through its veins, however, provides it with incredible strength and endurance.") + -- addItem("Mounts", "Dreadhare", 906, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nDo you like fluffy bunnies but think they are too small? Do you admire the majesty of stags and their antlers but are afraid of their untameable wilderness? Do not worry, the mystic creature Dreadhare consolidates the best qualities of both animals. Hop on its backs and enjoy the ride.") + -- addItem("Mounts", "Dusk Pryer", 1285, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSome spirits are born from pure elements. The Dusk Pryer embodies the essence of twilight, ever seeking knowledge hidden in the transition between light and darkness.") + -- addItem("Mounts", "Ebony Tiger", 1091, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIt is said that in ancient times, the sabre-tooth tiger was already used as a mount by elder warriors of Svargrond. As seafaring began to expand, this noble big cat was also transported to other regions in Tibia. Influenced by the new environment and climatic changes, the fur of the Ebony Tiger has developed its extraordinary colouring over several generations.") + -- addItem("Mounts", "Ember Saurian", 960, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThousands of years ago, its ancestors ruled the world. Only recently, it found its way into Tibia. The Ember Saurian has been spotted in a sea of flames and fire deep down in the depths of Kazordoon.") + -- addItem("Mounts", "Emerald Raven", 1453, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nGraceful and mysterious, ravens have long been symbols of magic. The Emerald Raven’s plumage glows faintly, enchanted by forest spirits.") + -- addItem("Mounts", "Emerald Sphinx", 951, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nRide an Emerald Sphinx on your way through ancient chambers and tombs and have a loyal friend by your side while fighting countless mummies and other creatures.") + -- addItem("Mounts", "Emerald Waccoon", 693, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWaccoons are cuddly creatures that love nothing more than to be petted and snuggled! Share a hug, ruffle the fur of the Emerald Waccoon and scratch it behind its ears to make it happy.") + -- addItem("Mounts", "Emperor Deer", 687, 660, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nTreat your character to a new travelling companion with a gentle nature and an impressive antler: The noble Emperor Deer will carry you through the deepest snow.") + -- addItem("Mounts", "Ether Badger", 1248, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBadgers have been a staple of the Tibian fauna for a long time, and finally some daring souls have braved the challenge to tame some exceptional specimens - and succeeded! While the common badger you can encounter during your travels might seem like a rather unassuming creature, the Battle Badger, the Ether Badger, and the Zaoan Badger are fierce and mighty beasts, which are at your beck and call.") + -- addItem("Mounts", "Eventide Nandu", 1326, 500, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nDespite their inability to fly, these strong-legged birds are lightning-fast and utterly reliable when crossing large distances over dry terrain.") + -- addItem("Mounts", "Feral Tiger", 1092, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nAs seafaring began to expand, this noble big cat was also transported to other regions in Tibia. Influenced by the new environment and climatic changes, the fur of the Feral Tiger has developed its extraordinary colouring over several generations.") + -- addItem("Mounts", "Festive Mammoth", 1381, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nNot all mammoths are grim and gruff. This one's festive nature and cheerful demeanor will lighten even the darkest dungeon.") + -- addItem("Mounts", "Festive Snowman", 1167, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWhen the nights are getting longer and freezing wind brings driving snow into the land, snowmen rise and shine on every corner. Lately, a peaceful, arcane creature has found shelter in one of them and used its magical power to call the Festive Snowman into being. Wrap yourself up well and warmly and jump on the back of your new frosty companion.") + -- addItem("Mounts", "Flamesteed", 626, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce a majestic and proud warhorse, the Flamesteed has fallen in a horrible battle many years ago. Driven by agony and pain, its spirit once again took possession of its rotten corpse to avenge its death. Stronger than ever, it seeks a master to join the battlefield, aiming for nothing but death and destruction.") + -- addItem("Mounts", "Flitterkatzen", 726, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nRumour has it that many years ago elder witches had gathered to hold a magical feast high up in the mountains. They had crossbred Flitterkatzen to easily conquer rocky canyons and deep valleys. Nobody knows what happened on their way up but only the mount has been seen ever since.") + -- addItem("Mounts", "Floating Augur", 1266, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese creatures are Floating Savants whose mind has been warped and bent to focus their extraordinary mental capabilities on one single goal: to do their master's bidding. Instead of being filled with an endless pursuit of knowledge, their live is now one of continuous thralldom and serfhood. The Floating Sage, the Floating Scholar and the Floating Augur are at your disposal.") + -- addItem("Mounts", "Floating Kashmir", 690, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Floating Kashmir is the perfect mount for those who are too busy to take care of an animal mount or simply like to travel on a beautiful, magic hand-woven carpet.") + -- addItem("Mounts", "Floating Sage", 1264, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese creatures are Floating Savants whose mind has been warped and bent to focus their extraordinary mental capabilities on one single goal: to do their master's bidding. Instead of being filled with an endless pursuit of knowledge, their live is now one of continuous thralldom and serfhood. The Floating Sage, the Floating Scholar and the Floating Augur are at your disposal.") + -- addItem("Mounts", "Floating Scholar", 1265, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese creatures are Floating Savants whose mind has been warped and bent to focus their extraordinary mental capabilities on one single goal: to do their master's bidding. Instead of being filled with an endless pursuit of knowledge, their live is now one of continuous thralldom and serfhood. The Floating Sage, the Floating Scholar and the Floating Augur are at your disposal.") + -- addItem("Mounts", "Flying Divan", 688, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Flying Divan is the perfect mount for those who are too busy to take care of an animal mount or simply like to travel on a beautiful, magic hand-woven carpet.") + -- addItem("Mounts", "Foxmouse", 1632, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nAn unusual crossbreed of cunning and curiosity, this mount’s playful energy is matched by its speed.") + -- addItem("Mounts", "Frostbringer", 1615, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThis mount was born of the first winter storm and embodies the fury and beauty of snow.") + -- addItem("Mounts", "Frostflare", 850, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf you are more of an imp than an angel, you may prefer riding out on a Frostflare to scare fellow Tibians on their festive strolls. Its devilish mask, claw-like hands and sharp hooves makes it the perfect companion for any daring adventurer who likes to stand out.") + -- addItem("Mounts", "Glacier Vagabond", 674, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWith its thick, shaggy hair, the Glacier Vagabond will keep you warm even in the chilly climate of the Ice Islands. Due to its calm and peaceful nature, it is not letting itself getting worked up easily.") + -- addItem("Mounts", "Glacier Wyrm", 1742, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nCold-blooded and ancient, the Glacier Wyrm coils through frostbitten mountains in silence.") + -- addItem("Mounts", "Gloom Widow", 1027, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIt is said that the Gloom Widow was born long before Banor walked the earth of Tibia. While its parents died in the war against the cruel hordes sent by Brog and Zathroth, their child survived by hiding in skulls of burned enemies. It never left its hiding spot and as it grew older, the skulls merged into its body. Now, it is fully-grown and thirsts for revenge.") + -- addItem("Mounts", "Gloomwurm", 1448, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBurrowing from the depths of forgotten tunnels, this creature thrives in the shadows. The Gloomwurm is as tough as steel and as fast as fear.") + -- addItem("Mounts", "Gold Sphinx", 950, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nRide a Gold Sphinx on your way through ancient chambers and tombs and have a loyal friend by your side while fighting countless mummies and other creatures.") + -- addItem("Mounts", "Golden Dragonfly", 669, 600, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf you are more interested in the achievements of science, you may enjoy a ride on the Golden Dragonfly, one of the new insect-like flying machines. Even if you do not move around, the wings of these unusual vehicles are always in motion.") + -- addItem("Mounts", "Gorgon Hydra", 1724, 1000, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nFew dare gaze into the many eyes of the Gorgon Hydra. This fearsome creature obeys no one — except you.") + -- addItem("Mounts", "Gorongra", 738, 720, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nGet yourself a mighty travelling companion with broad shoulders and a gentle heart. Gorongra is a physically imposing creature that is much more peaceful than its relatives, Tiquanda's wild kongras, and will carry you safely wherever you ask it to go.") + -- addItem("Mounts", "Hailstorm Fury", 648, 780, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce captured and held captive by a mad hunter, the Hailstorm Fury is the result of sick experiments. Fed only with demon dust and concentrated demonic blood it had to endure a dreadful transformation. The demonic blood that is now running through its veins, however, provides it with incredible strength and endurance.") + -- addItem("Mounts", "Highland Yak", 673, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWith its thick, shaggy hair, the Highland Yak will keep you warm even in the chilly climate of the Ice Islands. Due to its calm and peaceful nature, it is not letting itself getting worked up easily.") + -- addItem("Mounts", "Holiday Mammoth", 1380, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nNot all mammoths are grim and gruff. This one's festive nature and cheerful demeanor will lighten even the darkest dungeon.") + -- addItem("Mounts", "Hyacinth", 1439, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese graceful mounts are named after the vibrant flowers they resemble. They are calm, enduring, and add a blooming touch to your journey.") + -- addItem("Mounts", "Icebreacher", 1617, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThis mount was born of the first winter storm and embodies the fury and beauty of snow.") + -- addItem("Mounts", "Ink Spotted Koi", 1610, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nElegant, serene, and ever-gliding — these koi mounts are symbols of balance and beauty.") + -- addItem("Mounts", "Ivory Fang", 901, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIncredible strength and smartness, an irrepressible will to survive, passionately hunting in groups. If these attributes apply to your character, we have found the perfect partner for you. Have a proper look at Ivory Fang, which stands loyally by its master's side in every situation. It is time to become the leader of the wolf pack!") + -- addItem("Mounts", "Jackalope", 905, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nDo you like fluffy bunnies but think they are too small? Do you admire the majesty of stags and their antlers but are afraid of their untameable wilderness? Do not worry, the mystic creature Jackalope consolidates the best qualities of both animals. Hop on its backs and enjoy the ride.") + -- addItem("Mounts", "Jade Lion", 627, 450, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIts roaring is piercing marrow and bone and can be heard over ten miles away. The Jade Lion is the undisputed ruler of its territory and no one messes with this animal. Show no fear and prove yourself worthy of its trust and you will get yourself a valuable companion for your adventures.") + -- addItem("Mounts", "Jade Pincer", 628, 600, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Jade Pincer is a scorpion that has surpassed the natural boundaries of its own kind. Way bigger, stronger and faster than ordinary scorpions, it makes a perfect companion for fearless heroes and explorers. Just be careful of his poisonous sting when you mount it.") + -- addItem("Mounts", "Jade Shrine", 1492, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nImbued with ancient divine energy, this shrine floats effortlessly. The Jade Shrine blesses its rider with peace and clarity.") + -- addItem("Mounts", "Jousting Eagle", 1208, 800, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nHigh above the clouds far away from dry land, the training of giant eagles takes place. Only the cream of the crop is able to survive in such harsh environment long enough to call themselves Jousting Eagles while the weaklings find themselves at the bottom of the sea. The tough ones become noble and graceful mounts that are well known for their agility and endurance.") + -- addItem("Mounts", "Jousting Horse", 1579, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBred for ceremony and flair, this horse carries itself with grace and rhythm. Perfect for heroes who crave the spotlight.") + -- addItem("Mounts", "Jungle Saurian", 959, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThousands of years ago, its ancestors ruled the world. Only recently, it found its way into Tibia. The Jungle Saurian likes to hide in dense wood and overturned trees.") + -- addItem("Mounts", "Jungle Tiger", 1093, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nAs seafaring began to expand, this noble big cat was also transported to other regions in Tibia. Influenced by the new environment and climatic changes, the fur of the Jungle Tiger has developed its extraordinary colouring over several generations.") + -- addItem("Mounts", "Lagoon Saurian", 961, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThousands of years ago, its ancestors ruled the world. Only recently, it found its way into Tibia. The Lagoon Saurian feels most comfortable in torrential rivers and behind dangerous waterfalls.") + -- addItem("Mounts", "Leafscuttler", 870, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYou are fascinated by insectoid creatures and can picture yourself riding one during combat or just for travelling? The Leafscuttler will carry you through the Tibian wilderness with ease.") + -- addItem("Mounts", "Magic Carpet", 689, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Magic Carpet is the perfect mount for those who are too busy to take care of an animal mount or simply like to travel on a beautiful, magic hand-woven carpet.") + -- addItem("Mounts", "Magma Skull", 1686, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nForged from cursed bones and shadowed flame, this skull mount is only tamed by death itself.") + -- addItem("Mounts", "Marsh Toad", 1052, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Magic Carpet is the perfect mount for those who are too busy to take cFor centuries, humans and monsters have dumped their garbage in the swamps around Venore. The combination of old, rusty weapons, stale mana and broken runes have turned some of the swamp dwellers into gigantic frogs. Benefit from those mutations and make the Marsh Toad a faithful mount for your adventures even beyond the bounds of the swamp.") + -- addItem("Mounts", "Merry Mammoth", 1379, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nNot all mammoths are grim and gruff. This one's festive nature and cheerful demeanor will lighten even the darkest dungeon.") + -- addItem("Mounts", "Mint Ibex", 1527, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSurefooted and resilient, these ibexes were raised among mountain peaks. Their floral names are a nod to the patches of wildflowers found high above the clouds.") + -- addItem("Mounts", "Mould Shell", 887, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYou are intrigued by tortoises and would love to throne on a tortoise shell when travelling the Tibian wilderness? The Mould Shell might become your new trustworthy companion then, which will transport you safely and even carry you during combat.") + -- addItem("Mounts", "Mouldpincer", 868, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYou are fascinated by insectoid creatures and can picture yourself riding one during combat or just for travelling? The Mouldpincer will carry you through the Tibian wilderness with ease.") + -- addItem("Mounts", "Muffled Snowman", 1168, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWhen the nights are getting longer and freezing wind brings driving snow into the land, snowmen rise and shine on every corner. Lately, a peaceful, arcane creature has found shelter in one of them and used its magical power to call the Muffled Snowman into being. Wrap yourself up well and warmly and jump on the back of your new frosty companion.") + -- addItem("Mounts", "Mystic Raven", 1454, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nGraceful and mysterious, ravens have long been symbols of magic. The Mystic Raven’s plumage glows faintly, enchanted by forest spirits.") + -- addItem("Mounts", "Nethersteed", 629, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce a majestic and proud warhorse, the Nethersteed has fallen in a horrible battle many years ago. Driven by agony and pain, its spirit once again took possession of its rotten corpse to avenge its death. Stronger than ever, it seeks a master to join the battlefield, aiming for nothing but death and destruction.") + -- addItem("Mounts", "Night Waccoon", 692, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWaccoons are cuddly creatures that love nothing more than to be petted and snuggled! Share a hug, ruffle the fur of the Night Waccoon and scratch it behind its ears to make it happy.") + -- addItem("Mounts", "Nightdweller", 849, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf you are more of an imp than an angel, you may prefer riding out on a Nightdweller to scare fellow Tibians on their festive strolls. Its devilish mask, claw-like hands and sharp hooves makes it the perfect companion for any daring adventurer who likes to stand out.") + -- addItem("Mounts", "Nightmarish Crocovile", 1185, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nTo the keen observer, the crocovile is clearly a relative of the crocodile, albeit their look suggests an even more aggressive nature. While it is true that the power of its massive and muscular body can not only crush enemies dead but also break through any gate like a battering ram, a crocovile is, above all, a steadfast companion showing unwavering loyalty to its owner.") + -- addItem("Mounts", "Nightstinger", 762, 780, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Nightstinger has external characteristics of different breeds. It is assumed that his brain is also composed of many different species, which makes it completely unpredictable. Only few have managed to approach this creature unharmed and only the best could tame it.") + -- addItem("Mounts", "Noctungra", 739, 720, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nGet yourself a mighty travelling companion with broad shoulders and a gentle heart. Noctungra is a physically imposing creature that is much more peaceful than its relatives, Tiquanda's wild kongras, and will carry you safely wherever you ask it to go.") + -- addItem("Mounts", "Obsidian Shrine", 1493, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nImbued with ancient divine energy, this shrine floats effortlessly. The Obsidian Shrine blesses its rider with peace and clarity.") + -- addItem("Mounts", "Obstinate Ox", 1674, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA symbol of raw power and determination. The Obstinate Ox is as loud as it is loyal.") + -- addItem("Mounts", "Parade Horse", 1578, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBred for ceremony and flair, this horse carries itself with grace and rhythm. Perfect for heroes who crave the spotlight.") + -- addItem("Mounts", "Peony", 1440, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese graceful mounts are named after the vibrant flowers they resemble. They are calm, enduring, and add a blooming touch to your journey.") + -- addItem("Mounts", "Plumfish", 736, 570, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf the Plumfish moves its fins, it generates enough air pressure that it can even float over land. Its numerous eyes allow it to quickly detect dangers even in confusing situations and eliminate them with one powerful bite. If you watch your fingers, you are going to be good friends.") + -- addItem("Mounts", "Poisonbane", 650, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Poisonbane is out searching for the best bamboo in Tibia. Its heavy armour allows it to visit even the most dangerous places. Treat it nicely with its favourite food from time to time and it will become a loyal partner.") + -- addItem("Mounts", "Poppy Ibex", 1526, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSurefooted and resilient, these ibexes were raised among mountain peaks. Their floral names are a nod to the patches of wildflowers found high above the clouds.") + -- addItem("Mounts", "Prismatic Unicorn", 1019, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nLegend has it that a mare and a stallion once reached the end of a rainbow and decided to stay there. Influenced by the mystical power of the rainbow, the mare gave birth to an exceptional foal: Not only the big, strong horn on its forehead but the unusual colouring of its hair makes the Prismatic Unicorn a unique mount in every respect.") + -- addItem("Mounts", "Rabbit Rickshaw", 1179, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYour lower back worsens with every trip you spend on the back of your mount and you are looking for a more comfortable alternative to travel through the lands? Say no more! The Rabbit Rickshaw comes with two top-performing hares that never get tired thanks to the brand new and highly innovative propulsion technology. Just keep some back-up carrots in your pocket and you will be fine!") + -- addItem("Mounts", "Radiant Raven", 1455, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nGraceful and mysterious, ravens have long been symbols of magic. The Radiant Raven’s plumage glows faintly, enchanted by forest spirits.") + -- addItem("Mounts", "Razorcreep", 763, 780, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Razorcreep has external characteristics of different breeds. It is assumed that his brain is also composed of many different species, which makes it completely unpredictable. Only few have managed to approach this creature unharmed and only the best could tame it.") + -- addItem("Mounts", "Reed Lurker", 888, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYou are intrigued by tortoises and would love to throne on a tortoise shell when travelling the Tibian wilderness? The Reed Lurker might become your new trustworthy companion then, which will transport you safely and even carry you during combat.") + -- addItem("Mounts", "Rift Watcher", 1391, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSilent, patient and always on the lookout for rifts in reality, these beings are drawn to those who walk between worlds. The Rift Watcher will not falter.") + -- addItem("Mounts", "Ringtail Waccoon", 691, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWaccoons are cuddly creatures that love nothing more than to be petted and snuggled! Share a hug, ruffle the fur of the Ringtail Waccoon and scratch it behind its ears to make it happy.") + -- addItem("Mounts", "River Crocovile", 1183, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nTo the keen observer, the crocovile is clearly a relative of the crocodile, albeit their look suggests an even more aggressive nature. While it is true that the power of its massive and muscular body can not only crush enemies dead but also break through any gate like a battering ram, a crocovile is, above all, a steadfast companion showing unwavering loyalty to its owner.") + -- addItem("Mounts", "Rune Watcher", 1390, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSilent, patient and always on the lookout for rifts in reality, these beings are drawn to those who walk between worlds. The Rune Watcher will not falter.") + -- addItem("Mounts", "Rustwurm", 1446, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBurrowing from the depths of forgotten tunnels, this creature thrives in the shadows. The Rustwurm is as tough as steel and as fast as fear.") + -- addItem("Mounts", "Sanguine Frog", 1053, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nFor centuries, humans and monsters have dumped their garbage in the swamps around Venore. The combination of old, rusty weapons, stale mana and broken runes have turned some of the swamp dwellers into gigantic frogs. Benefit from those mutations and make the Sanguine Frog a faithful mount for your adventures even beyond the bounds of the swamp.") + -- addItem("Mounts", "Savanna Ostrich", 1324, 500, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nDespite their inability to fly, these strong-legged birds are lightning-fast and utterly reliable when crossing large distances over dry terrain.") + -- addItem("Mounts", "Scruffy Hyaena", 1335, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese rugged animals are fearsome in packs and cunning when left alone. Riding one gives you not only speed but a fearsome reputation.") + -- addItem("Mounts", "Sea Devil", 734, 570, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf the Sea Devil moves its fins, it generates enough air pressure that it can even float over land. Its numerous eyes allow it to quickly detect dangers even in confusing situations and eliminate them with one powerful bite. If you watch your fingers, you are going to be good friends.") + -- addItem("Mounts", "Shadow Claw", 902, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIncredible strength and smartness, an irrepressible will to survive, passionately hunting in groups. If these attributes apply to your character, we have found the perfect partner for you. Have a proper look at Shadow Claw, which stands loyally by its master's side in every situation. It is time to become the leader of the wolf pack!") + -- addItem("Mounts", "Shadow Draptor", 427, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA wild, ancient creature, which had been hiding in the depths of the shadows for a very long time, has been spotted in Tibia again! The almighty Shadow Draptor has returned and only the bravest Tibians can control such a beast!") + -- addItem("Mounts", "Shadow Hart", 685, 660, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nTreat your character to a new travelling companion with a gentle nature and an impressive antler: The noble Shadow Hart will carry you through the deepest snow.") + -- addItem("Mounts", "Shadow Sphinx", 952, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nRide a Shadow Sphinx on your way through ancient chambers and tombs and have a loyal friend by your side while fighting countless mummies and other creatures.") + -- addItem("Mounts", "Siegebreaker", 649, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Siegebreaker is out searching for the best bamboo in Tibia. Its heavy armour allows it to visit even the most dangerous places. Treat it nicely with its favourite food from time to time and it will become a loyal partner.") + -- addItem("Mounts", "Silverneck", 740, 720, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nGet yourself a mighty travelling companion with broad shoulders and a gentle heart. Silverneck is a physically imposing creature that is much more peaceful than its relatives, Tiquanda's wild kongras, and will carry you safely wherever you ask it to go.") + -- addItem("Mounts", "Skybreaker Pegasus", 1729, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA mount that rides thunderclouds and breaks the heavens. The storm is its domain.") + -- addItem("Mounts", "Slagsnare", 761, 780, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Slagsnare has external characteristics of different breeds. It is assumed that his brain is also composed of many different species, which makes it completely unpredictable. Only few have managed to approach this creature unharmed and only the best could tame it.") + -- addItem("Mounts", "Snow Pelt", 903, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIncredible strength and smartness, an irrepressible will to survive, passionately hunting in groups. If these attributes apply to your character, we have found the perfect partner for you. Have a proper look at Snow Pelt, which stands loyally by its master's side in every situation. It is time to become the leader of the wolf pack!") + -- addItem("Mounts", "Snow Strider", 1284, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSome spirits are born from pure elements. The Snow Strider came into being through a mix of pristine ice and eternal northern wind. With sharp hooves and sturdy legs, it glides effortlessly over snow and ice.") + -- addItem("Mounts", "Snowy Owl", 1105, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOwls have always been a symbol of mystery, magic and wisdom in Tibian myths and fairy tales. Having one of these enigmatic creatures of the night as a trustworthy companion provides you with a silent guide whose ever-watchful eyes will cut through the shadows, help you navigate the darkness and unravel great secrets.") + -- addItem("Mounts", "Spirit of Purity", 1682, 1000, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA radiant entity of light and truth, this mount protects those with noble hearts.") + -- addItem("Mounts", "Steel Bee", 670, 600, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIf you are more interested in the achievements of science, you may enjoy a ride on the Steel Bee, one of the new insect-like flying machines. Even if you do not move around, the wings of these unusual vehicles are always in motion.") + -- addItem("Mounts", "Steelbeak", 522, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nForged by only the highest skilled blacksmiths in the depths of Kazordoon's furnaces, a wild animal made out of the finest steel arose from glowing embers and blazing heat. Protected by its impenetrable armour, the Steelbeak is ready to accompany its master on every battleground.") + -- addItem("Mounts", "Surly Steer", 1673, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nA symbol of raw power and determination. The Surly Steer is as loud as it is loyal.") + -- addItem("Mounts", "Swamp Crocovile", 1184, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nTo the keen observer, the crocovile is clearly a relative of the crocodile, albeit their look suggests an even more aggressive nature. While it is true that the power of its massive and muscular body can not only crush enemies dead but also break through any gate like a battering ram, a crocovile is, above all, a steadfast companion showing unwavering loyalty to its owner.") + -- addItem("Mounts", "Swamp Snapper", 886, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nYou are intrigued by tortoises and would love to throne on a tortoise shell when travelling the Tibian wilderness? The Swamp Snapper might become your new trustworthy companion then, which will transport you safely and even carry you during combat.") + -- addItem("Mounts", "Tangerine Flecked Koi", 1608, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nElegant, serene, and ever-gliding — these koi mounts are symbols of balance and beauty.") + -- addItem("Mounts", "Tawny Owl", 1104, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nHaving one of these enigmatic creatures of the night as a trustworthy companion provides you with a silent guide whose ever-watchful eyes will cut through the shadows, help you navigate the darkness and unravel great secrets.") + -- addItem("Mounts", "Tempest", 630, 900, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce a majestic and proud warhorse, the Tempest has fallen in a horrible battle many years ago. Driven by agony and pain, its spirit once again took possession of its rotten corpse to avenge its death. Stronger than ever, it seeks a master to join the battlefield, aiming for nothing but death and destruction.") + -- addItem("Mounts", "Tombstinger", 546, 600, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThe Tombstinger is a scorpion that has surpassed the natural boundaries of its own kind. Way bigger, stronger and faster than ordinary scorpions, it makes a perfect companion for fearless heroes and explorers. Just be careful of his poisonous sting when you mount it.") + -- addItem("Mounts", "Topaz Shrine", 1491, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nImbued with ancient divine energy, this shrine floats effortlessly. The Topaz Shrine blesses its rider with peace and clarity.") + -- addItem("Mounts", "Tourney Horse", 1580, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBred for ceremony and flair, this horse carries itself with grace and rhythm. Perfect for heroes who crave the spotlight.") + -- addItem("Mounts", "Toxic Toad", 1054, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nFor centuries, humans and monsters have dumped their garbage in the swamps around Venore. The combination of old, rusty weapons, stale mana and broken runes have turned some of the swamp dwellers into gigantic frogs. Benefit from those mutations and make the Toxic Toad a faithful mount for your adventures even beyond the bounds of the swamp.") + -- addItem("Mounts", "Tundra Rambler", 672, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nWith its thick, shaggy hair, the Tundra Rambler will keep you warm even in the chilly climate of the Ice Islands. Due to its calm and peaceful nature, it is not letting itself getting worked up easily.") + -- addItem("Mounts", "Venompaw", 727, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nRumour has it that many years ago elder witches had gathered to hold a magical feast high up in the mountains. They had crossbred Venompaw to easily conquer rocky canyons and deep valleys. Nobody knows what happened on their way up but only the mount has been seen ever since.") + -- addItem("Mounts", "Void Watcher", 1389, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nSilent, patient and always on the lookout for rifts in reality, these beings are drawn to those who walk between worlds. The Void Watcher will not falter.") + -- addItem("Mounts", "Voracious Hyaena", 1333, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThese rugged animals are fearsome in packs and cunning when left alone. Riding one gives you not only speed but a fearsome reputation.") + -- addItem("Mounts", "Winter King", 631, 450, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nIts roaring is piercing marrow and bone and can be heard over ten miles away. The Winter King is the undisputed ruler of its territory and no one messes with this animal. Show no fear and prove yourself worthy of its trust and you will get yourself a valuable companion for your adventures.") + -- addItem("Mounts", "Winterstride", 1616, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThis mount was born of the first winter storm and embodies the fury and beauty of snow.") + -- addItem("Mounts", "Wolpertinger", 907, 870, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce captured and held captive by a mad hunter, the Woodland Prince is the result of sick experiments. Fed only with demon dust and concentrated demonic blood it had to endure a dreadful transformation. The demonic blood that is now running through its veins, however, provides it with incredible strength and endurance.") + -- addItem("Mounts", "Woodland Prince", 647, 780, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nOnce captured and held captive by a mad hunter, the Woodland Prince is the result of sick experiments. Fed only with demon dust and concentrated demonic blood it had to endure a dreadful transformation. The demonic blood that is now running through its veins, however, provides it with incredible strength and endurance.") + -- addItem("Mounts", "Wrathfire Pegasus", 1728, 750, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nThis pegasus was forged in wrath and fire. Ride it to war, and leave a trail of flame.") + -- addItem("Mounts", "Zaoan Badger", 1249, 690, false, 1, "- only usable by purchasing character\n- provides character with a speed boost\n\nBadgers have been a staple of the Tibian fauna for a long time, and finally some daring souls have braved the challenge to tame some exceptional specimens - and succeeded! While the common badger you can encounter during your travels might seem like a rather unassuming creature, the Battle Badger, the Ether Badger, and the Zaoan Badger are fierce and mighty beasts, which are at your beck and call.") + + addCategory("Cosmetics", "Outfits", 15, CATEGORY_OUTFIT) + addItem("Outfits", "Elementalist", 432, 450, false, 1, "The warm and cosy cloak of the Winter Warden outfit will keep you warm in every situation. Best thing, it is not only comfortable but fashionable as well. You will be the envy of any snow queen or king, guaranteed!") + addItem("Outfits", "Deepling", 463, 450, false, 1, "The Trailblazer is on a mission of enlightenment and carries the flame of wisdom near and far. The everlasting shine brightens the hearts and minds of all creatures its rays touch, bringing light even to the darkest corners of the world as a beacon of insight and knowledge.") + addItem("Outfits", "Insectoid", 465, 450, false, 1, "Do you worship warm temperatures and are opposed to the thought of long and dark winter nights? Do you refuse to spend countless evenings in front of your chimney while ice-cold wind whistles through the cracks and niches of your house? It is time to stop freezing and to become an honourable Sun Priest! With this stylish outfit, you can finally show the world your unconditional dedication and commitment to the sun!") + addItem("Outfits", "Entrepreneur", 472, 450, false, 1, "The mutated pumpkin is too weak for your mighty weapons? Time to show that evil vegetable how to scare the living daylight out of people! Put on a scary looking pumpkin on your head and spread terror and fear amongst the Tibian population.") + + addCategory(nil, "Extras", 9, CATEGORY_NONE) + addCategory("Extras", "Extra Services", 7, CATEGORY_EXTRAS) + addItem("Extra Services", "Name Change", "Name_Change", 250, false, 1, "Tired of your current character name? Purchase a new one!\n\n\n- only usable by purchasing character\n- relog required after purchase to finalise the name change") + addItem("Extra Services", "Sex Change", "Sex_Change", 120, false, 1, "Turns your female character into a male one - or vice versa.\n\n\n- only usable by purchasing character\n- activated at purchase\n- you will keep all outfits you have purchased or earned in quest") + + addCategory("Extras", "Useful Things", 24, CATEGORY_EXTRAS) + addItem("Useful Things", "Temple Teleport", "Temple_Teleport", 15, false, 1, "Teleports you instantly to your home temple.\n\n- only usable by purchasing character\n- use it to teleport you to your home temple\n- cannot be used while having a battle sign or a protection zone block") +end + +function addCategory(parent, title, iconId, categoryId, description) + GAME_SHOP.categoriesId[title] = categoryId + table.insert(GAME_SHOP.categories, { + title = title, + parent = parent, + iconId = iconId, + categoryId = categoryId, + description = description + }) +end + +function addItem(parent, name, id, price, isSecondPrice, count, description) + if not GAME_SHOP.offers[parent] then + GAME_SHOP.offers[parent] = {} + end + + local serverId = id + if type(id) == "number" and GAME_SHOP.categoriesId[parent] == CATEGORY_ITEM then + id = ItemType(id):getClientId() + end + + table.insert(GAME_SHOP.offers[parent], { + parent = parent, + name = name, + serverId = serverId, + id = id, + price = price, + isSecondPrice = isSecondPrice, + count = count, + description = description, + categoryId = GAME_SHOP.categoriesId[parent] + }) +end + +function gameShopPurchase(player, offer) + local offers = GAME_SHOP.offers[offer.parent] + if not offers then + return errorMsg(player, "Something went wrong, try again or contact server admin [#1]!") + end + + for i = 1, #offers do + if offers[i].name == offer.name and offers[i].price == offer.price and offers[i].count == offer.count then + local points = 0 + local query = "" + if offers[i].isSecondPrice then + points = getSecondCurrency(player) + query = "points_second" + else + points = getPoints(player) + query = "points" + end + + if offers[i].price > points then + return errorMsg(player, "You don't have enough points!") + end + + offer.serverId = offers[i].serverId + local status = finalizePurchase(player, offer) + if status then + return errorMsg(player, status) + end + + local aid = player:getAccountId() + local escapeName = db.escapeString(offers[i].name) + local escapePrice = db.escapeString(-offers[i].price) + local escapeIsSecondPrice = db.escapeString(offers[i].isSecondPrice and "1" or "0") + local escapeCount = offers[i].count and db.escapeString(offers[i].count) or 0 + if GAME_SHOP.categoriesId[offer.parent] == CATEGORY_PREMIUM then + escapeCount = 0 + end + + db.query("UPDATE `znote_accounts` set `" .. query .. "` = `" .. query .. "` - " .. offers[i].price .. " WHERE `id` = " .. aid) + db.asyncQuery("INSERT INTO `shop_history` VALUES (NULL, " .. aid .. ", " .. player:getGuid() .. ", NOW(), " .. escapeName .. ", " .. escapePrice .. ", " .. escapeIsSecondPrice .. ", " .. escapeCount .. ", NULL)") + addEvent(gameShopUpdateHistory, 1000, player:getId()) + addEvent(gameShopUpdatePoints, 1000, player:getId()) + return infoMsg(player, "You've bought " .. offers[i].name .. "!", true) + end + end + + return errorMsg(player, "Something went wrong, try again or contact server admin [#3]!") +end + +function finalizePurchase(player, offer) + local categoryId = GAME_SHOP.categoriesId[offer.parent] + if categoryId == CATEGORY_PREMIUM then + return defaultPremiumCallback(player, offer) + elseif categoryId == CATEGORY_ITEM then + return defaultItemCallback(player, offer) + elseif categoryId == CATEGORY_BLESSING then + return defaultBlessingCallback(player, offer) + elseif categoryId == CATEGORY_OUTFIT then + return defaultOutfitCallback(player, offer) + elseif categoryId == CATEGORY_MOUNT then + return defaultMountCallback(player, offer) + elseif categoryId == CATEGORY_EXTRAS then + return defaultExtrasCallback(player, offer) + end + + return "Something went wrong, try again or contact server admin [#2]!" +end + +function defaultPremiumCallback(player, offer) + player:addPremiumDays(offer.count) + return false +end + +function defaultItemCallback(player, offer) + local inPz = player:getTile():hasFlag(TILESTATE_PROTECTIONZONE) + local inFight = player:isPzLocked() or player:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT) + if not inPz or inFight then + return "Cannot be used while having a battle sign or a protection zone block." + end + + local weight = ItemType(offer.serverId):getWeight(offer.count) + if player:getFreeCapacity() < weight then + return "This item is too heavy for you!" + end + + local item = player:getSlotItem(CONST_SLOT_BACKPACK) + if not item then + return "You don't have enough space in backpack." + end + + local slots = item:getEmptySlots(true) + if slots <= 0 then + return "You don't have enough space in backpack." + end + + if player:addItem(offer.serverId, offer.count, false) then + return false + end + + return "Something went wrong, item couldn't be added." +end + +function defaultBlessingCallback(player, offer) + if offer.count == -1 then + for i = 1, 5 do + if not player:hasBlessing(i) then + for i = 1, 5 do + player:addBlessing(i) + end + + return false + end + end + + return "You already have all blessings." + elseif player:hasBlessing(offer.count) then + return "You already have this blessing." + end + + player:addBlessing(offer.count) + return false +end + +function defaultOutfitCallback(player, offer) + if player:hasOutfit(offer.id, offer.count) then + return "You already have this outfit." + end + + player:addOutfitAddon(offer.id, offer.count) + return false +end + +function defaultMountCallback(player, offer) + if player:hasMount(offer.id) then + return "You already have this mount." + end + + if not player:addMount(offer.id) then + return "Something went wrong, mount cannot be added." + end + + return false +end + +function defaultExtrasCallback(player, offer) + if offer.name == "Name Change" then + return defaultChangeNameCallback(player, offer) + elseif offer.name == "Sex Change" then + return defaultChangeSexCallback(player) + elseif offer.name == "Temple Teleport" then + return defaultTeleportCallback(player) + end + + return "Something went wrong, extra service couldn't be executed." +end + +function defaultChangeSexCallback(player) + local inPz = player:getTile():hasFlag(TILESTATE_PROTECTIONZONE) + local inFight = player:isPzLocked() or player:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT) + if not inPz or inFight then + return "Cannot be used while having a battle sign or a protection zone block." + end + + if not player:getGroup() then + return "You can't do this." + end + + player:setSex(player:getSex() == PLAYERSEX_FEMALE and PLAYERSEX_MALE or PLAYERSEX_FEMALE) + + local outfit = player:getOutfit() + if player:getSex(player) == PLAYERSEX_MALE then + outfit.lookType = 128 + else + outfit.lookType = 136 + end + + player:setOutfit(outfit) + return false +end + +function defaultChangeNameCallback(player, offer) + local inPz = player:getTile():hasFlag(TILESTATE_PROTECTIONZONE) + local inFight = player:isPzLocked() or player:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT) + if not inPz or inFight then + return "Cannot be used while having a battle sign or a protection zone block." + end + + if not player:getGroup() then + return "You can't do this." + end + + local characterName = offer.nick:trim() + local v = getValid(characterName:lower(), false) + if not validName(v) then + return "You can't use this character name." + end + + if getPlayerDatabaseInfo(v) then + return "Character name already taken." + end + + local lastName = player:getName() + db.query("UPDATE players SET name = "..db.escapeString(characterName).." WHERE name = "..db.escapeString(lastName)..";") + db.query("UPDATE player_deaths SET killed_by = "..db.escapeString(characterName)..", mostdamage_by = "..db.escapeString(characterName).." WHERE killed_by = "..db.escapeString(lastName).." OR mostdamage_by = "..db.escapeString(lastName)..";") + db.query("UPDATE player_deaths_backup SET killed_by = "..db.escapeString(characterName)..", mostdamage_by = "..db.escapeString(characterName).." WHERE killed_by = "..db.escapeString(lastName).." OR mostdamage_by = "..db.escapeString(lastName)..";") + db.query(string.format("INSERT INTO `change_name_history` (`player_id`, `last_name`, `current_name`, `changed_name_in`) VALUES (%d, %s, %s, %d)", player:getGuid(), db.escapeString(lastName), db.escapeString(characterName), os.time())) + return false +end + +function defaultTeleportCallback(player, offer) + local inFight = player:isPzLocked() or player:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT) + if inFight then + return "Cannot be used while having a battle sign or a protection zone block." + end + + player:teleportTo(player:getTown():getTemplePosition()) + player:getPosition():sendMagicEffect(CONST_ME_TELEPORT) + + return false +end + +function getValid(name, opt) + local function tchelper(first, rest) + return first:upper()..rest:lower() + end + + return opt and name:gsub("(%a)([%w_']*)", tchelper) or name:gsub("^%l", string.upper) +end + +function wordCount(str) + local count = 0 + for word in string.gmatch(str, "%a+") do + count = count + 1 + end + + return count +end + +function validName(name) + if not name then + return false + end + + if name:len() < minChars then + return false + end + + for i = 1, #forbiddenWords do + for word in string.gmatch(name, "%a+") do + if word:lower() == forbiddenWords[i] then + return false + end + end + end + + for i = 1, name:len() do + if not(isInArray(chars, name:sub(i,i))) or wordCount(name) > maxWords or name:len() > maxLength or string.find(name, " ") then + return false + end + end + + return true +end + +function gameShopUpdateHistory(player) + if type(player) == "number" then + player = Player(player) + end + + local history = {} + local resultId = db.storeQuery("SELECT * FROM `shop_history` WHERE `account` = " .. player:getAccountId() .. " order by `id` DESC") + if resultId ~= false then + repeat + table.insert(history, { + date = result.getDataString(resultId, "date"), + price = result.getDataInt(resultId, "price"), + isSecondPrice = result.getDataInt(resultId, "costSecond") == 1, + name = result.getDataString(resultId, "title"), + count = result.getDataInt(resultId, "count") + }) + until not result.next(resultId) + result.free(resultId) + end + + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "history", data = history})) +end + +local ExtendedEvent = CreatureEvent("GameShopExtended") + +function ExtendedEvent.onExtendedOpcode(player, opcode, buffer) + if opcode == ExtendedOPCodes.CODE_GAMESHOP then + if not GAME_SHOP then + gameShopInitialize() + addEvent(refreshPlayersPoints, 10 * 1000) + end + + local status, json_data = + pcall( + function() + return json.decode(buffer) + end + ) + if not status then + return + end + + local action = json_data.action + local data = json_data.data + if not action or not data then + return + end + + if action == "fetch" then + gameShopFetch(player) + elseif action == "purchase" then + gameShopPurchase(player, data) + elseif action == "transfer" then + gameShopTransferCoins(player, data) + elseif action == "changeName" then + gameShopChangeName(player, data) + end + end +end + +function gameShopFetch(player) + gameShopUpdatePoints(player) + gameShopUpdateHistory(player) + + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "fetchBase", data = {categories = GAME_SHOP.categories, url = DONATION_URL}})) + + for category, offersTable in pairs(GAME_SHOP.offers) do + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "fetchOffers", data = {category = category, offers = offersTable}})) + end +end + +function gameShopUpdatePoints(player) + if type(player) == "number" then + player = Player(player) + end + + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "points", data = { + points = getPoints(player), secondPoints = getSecondCurrency(player)}})) +end + +function gameShopUpdatePointsAndRemovePlayer(player) + if type(player) == "number" then + player = Player(player) + end + + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "points", data = { + points = getPoints(player), secondPoints = getSecondCurrency(player)}})) + player:remove() +end + +function gameShopChangeName(player, offer) + local offers = GAME_SHOP.offers[offer.category] + if not offers then + return errorMsg(player, "Something went wrong, try again or contact server admin [#1]!") + end + + if not offer.nick then + return errorMsg(player, "You need to choose a new nickname.") + end + + for i = 1, #offers do + if offers[i].title == offer.title and offers[i].price == offer.price then + local callback = offers[i].callback + if not callback then + return errorMsg(player, "Something went wrong, try again or contact server admin [#2]!") + end + + local points = getPoints(player) + if offers[i].price > points then + return errorMsg(player, "You don't have enough points!") + end + + if player:getName() == offer.nick then + return errorMsg(player, "Please choose a new nickname different from your previous one") + end + + local status = callback(player, offer) + if status ~= true then + return errorMsg(player, status) + end + + local aid = player:getAccountId() + local escapeTitle = db.escapeString(offers[i].title) + local escapePrice = db.escapeString(-offers[i].price) + local escapeIsSecondPrice = db.escapeString(-offers[i].isSecondPrice) + local escapeCount = offers[i].count and db.escapeString(offers[i].count) or 0 + db.query("UPDATE `znote_accounts` set `points` = `points` - " .. offers[i].price .. " WHERE `id` = " .. aid) + db.asyncQuery("INSERT INTO `shop_history` VALUES (NULL, '" .. aid .. "', '" .. player:getGuid() .. "', NOW(), " .. escapeTitle .. ", " .. escapePrice .. ", " .. escapeIsSecondPrice .. ", " .. escapeCount .. ", NULL)") + + addEvent(gameShopUpdateHistory, 1000, player:getId()) + addEvent(gameShopUpdatePointsAndRemovePlayer, 1000, player:getId()) + return infoMsg(player, "You've bought " .. offers[i].title .. "! Please log out of your account and join us with your new name already set.", true) + end + end + + return errorMsg(player, "Something went wrong, try again or contact server admin [#4]!") +end + +function gameShopTransferCoins(player, transfer) + local receiver = transfer.target + local amount = transfer.amount + local amountSecond = transfer.amountSecond + if not receiver then + return errorMsg(player, "Target player not found!") + end + + if amount > getPoints(player) then + return errorMsg(player, "You don't have enough points!") + end + + if SECOND_CURRENCY_ENABLED then + if amountSecond > getPoints(player) then + return errorMsg(player, "You don't have enough points!") + end + end + + if receiver:lower() == player:getName():lower() then + return errorMsg(player, "You can't transfer coins to yourself.") + end + + local accountId = 0 + local GUID = 0 + local resultId = db.storeQuery("SELECT `id`, `account_id` FROM `players` WHERE `name` = " .. db.escapeString(receiver)) + if resultId ~= false then + accountId = result.getDataInt(resultId, "account_id") + GUID = result.getDataInt(resultId, "id") + result.free(resultId) + end + + if accountId == 0 then + return errorMsg(player, "Target player not found!") + end + + if accountId == player:getAccountId() then + return errorMsg(player, "You can't transfer coins to yourself.") + end + + local aid = player:getAccountId() + local title = "Coin Transfer from " .. player:getName() .. " to " .. receiver:sub(1, 1):upper() .. receiver:sub(2, receiver:len()):lower() + local escapeTitle = db.escapeString(title) + if amount > 0 then + db.query("UPDATE `znote_accounts` set `points` = `points` - " .. amount .. " WHERE `id` = " .. aid) + db.query("UPDATE `znote_accounts` set `points` = `points` + " .. amount .. " WHERE `id` = " .. accountId) + + db.asyncQuery("INSERT INTO `shop_history` VALUES (NULL, '" .. aid .. "', '" .. player:getGuid() .. "', NOW(), " .. escapeTitle .. ", " .. db.escapeString(-amount) .. ", 0, 1, " .. db.escapeString(receiver) .. ")") + db.asyncQuery("INSERT INTO `shop_history` VALUES (NULL, '" .. accountId .. "', '" .. GUID .. "', NOW(), " .. escapeTitle .. ", " .. db.escapeString(amount) .. ", 0, 1, " .. db.escapeString(player:getName()) .. ")") + end + + if amountSecond > 0 then + db.query("UPDATE `znote_accounts` set `points_second` = `points_second` - " .. amountSecond .. " WHERE `id` = " .. aid) + db.query("UPDATE `znote_accounts` set `points_second` = `points_second` + " .. amountSecond .. " WHERE `id` = " .. accountId) + + db.asyncQuery("INSERT INTO `shop_history` VALUES (NULL, '" .. aid .. "', '" .. player:getGuid() .. "', NOW(), " .. escapeTitle .. ", " .. db.escapeString(-amountSecond) .. ", 1, 1, " .. db.escapeString(receiver) .. ")") + db.asyncQuery("INSERT INTO `shop_history` VALUES (NULL, '" .. accountId .. "', '" .. GUID .. "', NOW(), " .. escapeTitle .. ", " .. db.escapeString(amountSecond) .. ", 1, 1, " .. db.escapeString(player:getName()) .. ")") + end + + addEvent(gameShopUpdateHistory, 1000, player:getId()) + addEvent(gameShopUpdatePoints, 1000, player:getId()) + + local targetPlayer = Player(receiver) + if targetPlayer then + addEvent(gameShopUpdateHistory, 1000, targetPlayer:getId()) + addEvent(gameShopUpdatePoints, 1000, targetPlayer:getId()) + end + + local message = "You've sent " + if amount > 0 then + message = message .. amount .. " Tibia coins " + end + + if amountSecond > 0 then + message = message .. (amount > 0 and " and " or "") .. amountSecond .. " Task points " + end + + return infoMsg(player, message .. " to " .. receiver .. "!", true) +end + +function getPoints(player) + local points = 0 + local resultId = db.storeQuery("SELECT `points` FROM `znote_accounts` WHERE `id` = " .. player:getAccountId()) + if resultId ~= false then + points = result.getDataInt(resultId, "points") + result.free(resultId) + end + + return points +end + +function getSecondCurrency(player) + if not SECOND_CURRENCY_ENABLED then + return -1 + end + + local points = 0 + local resultId = db.storeQuery("SELECT `points_second` FROM `znote_accounts` WHERE `id` = " .. player:getAccountId()) + if resultId ~= false then + points = result.getDataInt(resultId, "points_second") + result.free(resultId) + end + + return points +end + +function errorMsg(player, msg) + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "msg", data = {type = "error", msg = msg}})) +end + +function infoMsg(player, msg, close) + if not close then + close = false + end + + player:sendExtendedOpcode(ExtendedOPCodes.CODE_GAMESHOP, json.encode({action = "msg", data = {type = "info", msg = msg, close = close}})) +end + +function refreshPlayersPoints() + for _, p in ipairs(Game.getPlayers()) do + if p:getIp() > 0 then + gameShopUpdatePoints(p) + end + end + addEvent(refreshPlayersPoints, 10 * 1000) +end + +LoginEvent:type("login") +LoginEvent:register() +ExtendedEvent:type("extendedopcode") +ExtendedEvent:register() \ No newline at end of file diff --git a/modules/game_shop/serverSIDE/server.txt b/modules/game_shop/serverSIDE/server.txt index 638611d97..376edf0f7 100644 --- a/modules/game_shop/serverSIDE/server.txt +++ b/modules/game_shop/serverSIDE/server.txt @@ -1,30 +1,61 @@ - -- Instruction: --- creaturescripts.xml --- and in login.lua player:registerEvent("Shop") --- create sql table shop_history --- set variables --- set up function init(), add there items and categories, follow examples --- set up callbacks at the bottom to add player item/outfit/whatever you want - -- add json lib dofile('data/lib/json.lua') in \data\lib\lib.lua +--[[ SQL TABLE - ZNOTE AAC ---[[ SQL TABLE - -CREATE TABLE `shop_history` ( +CREATE TABLE `znote_accounts` ( `id` int(11) NOT NULL, + `account_id` int(11) NOT NULL, + `ip` bigint(20) UNSIGNED NOT NULL, + `created` int(11) NOT NULL, + `points` int(11) DEFAULT 0, + `points_second` int(11) DEFAULT 0, + `cooldown` int(11) DEFAULT 0, + `active` tinyint(4) NOT NULL DEFAULT 0, + `active_email` tinyint(4) NOT NULL DEFAULT 0, + `activekey` int(11) NOT NULL DEFAULT 0, + `flag` varchar(20) NOT NULL, + `secret` char(16) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +CREATE TABLE IF NOT EXISTS `shop_history` ( + `id` int(11) NOT NULL AUTO_INCREMENT, `account` int(11) NOT NULL, `player` int(11) NOT NULL, `date` datetime NOT NULL, `title` varchar(100) NOT NULL, - `cost` int(11) NOT NULL, - `details` varchar(500) NOT NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + `price` int(11) NOT NULL, + `costSecond` int(11) NOT NULL, + `count` int(11) NOT NULL DEFAULT '0', + `target` varchar(255) DEFAULT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`account`) REFERENCES `accounts` (`id`) ON DELETE CASCADE, + FOREIGN KEY (`player`) REFERENCES `players` (`id`) ON DELETE CASCADE +); -ALTER TABLE `shop_history` - ADD PRIMARY KEY (`id`); -ALTER TABLE `shop_history` - MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; +CREATE TABLE IF NOT EXISTS `change_name_history` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `player_id` int(11) NOT NULL, + `last_name` varchar(30) NOT NULL, + `current_name` varchar(30) NOT NULL, + `changed_name_in` int(11) NOT NULL, + PRIMARY KEY (`id`), + FOREIGN KEY (`player_id`) REFERENCES `players` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +CREATE TABLE IF NOT EXISTS `player_deaths_backup` ( + `player_id` int NOT NULL, + `time` bigint unsigned NOT NULL DEFAULT '0', + `level` int NOT NULL DEFAULT '1', + `killed_by` varchar(255) NOT NULL, + `is_player` tinyint NOT NULL DEFAULT '1', + `mostdamage_by` varchar(100) NOT NULL, + `mostdamage_is_player` tinyint NOT NULL DEFAULT '0', + `unjustified` tinyint NOT NULL DEFAULT '0', + `mostdamage_unjustified` tinyint NOT NULL DEFAULT '0', + FOREIGN KEY (`player_id`) REFERENCES `players`(`id`) ON DELETE CASCADE, + KEY `killed_by` (`killed_by`), + KEY `mostdamage_by` (`mostdamage_by`) +) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8; ]]-- diff --git a/modules/game_shop/shop.lua b/modules/game_shop/shop.lua deleted file mode 100644 index 8c0e52249..000000000 --- a/modules/game_shop/shop.lua +++ /dev/null @@ -1,676 +0,0 @@ --- private variables -local SHOP_EXTENTED_OPCODE = 201 - -shop = nil -transferWindow = nil -local otcv8shop = false -local shopButton = nil -local msgWindow = nil -local browsingHistory = false -local transferValue = 0 - --- for classic store -local storeUrl = "" -local coinsPacketSize = 0 - -local CATEGORIES = {} -local HISTORY = {} -local STATUS = {} -local AD = {} - -local selectedOffer = {} - -local function sendAction(action, data) - - local protocolGame = g_game.getProtocolGame() - if data == nil then - data = {} - end - if protocolGame then - protocolGame:sendExtendedJSONOpcode(SHOP_EXTENTED_OPCODE, { - action = action, - data = data - }) - end -end - --- public functions -function init() - connect(g_game, { - onGameStart = check, - onGameEnd = hide - - }) - - ProtocolGame.registerExtendedJSONOpcode(SHOP_EXTENTED_OPCODE, onExtendedJSONOpcode) - - if g_game.isOnline() then - check() - end - createShop() - createTransferWindow() -end - -function terminate() - disconnect(g_game, { - onGameStart = check, - onGameEnd = hide - - }) - - ProtocolGame.unregisterExtendedJSONOpcode(SHOP_EXTENTED_OPCODE, onExtendedJSONOpcode) - - if shopButton then - shopButton:destroy() - shopButton = nil - end - if shop then - disconnect(shop.categories, { - onChildFocusChange = changeCategory - }) - shop:destroy() - shop = nil - end - if msgWindow then - msgWindow:destroy() - end -end - -function check() - otcv8shop = false - sendAction("init") -end - -function hide() - if not shop then - return - end - shop:hide() -end - -function show() - if not shop then - return - end - - shop:show() - shop:raise() - shop:focus() -end - -function softHide() - if not transferWindow then - return - end - - transferWindow:hide() - shop:show() -end - -function showTransfer() - if not shop or not transferWindow then - return - end - - hide() - transferWindow:show() - transferWindow:raise() - transferWindow:focus() -end - -function hideTransfer() - if not shop or not transferWindow then - return - end - - transferWindow:hide() - show() -end - -function toggle() - if not shop then - return - end - if shop:isVisible() then - return hide() - end - show() - check() -end - -function createShop() - if shop then - return - end - shop = g_ui.displayUI('shop') - shop:hide() - -- shopButton = modules.game_mainpanel.addStoreButton('store', tr('Shop'), '/images/options/store_large', toggle,false, 8) -- \game_mainpanel\mainpanel.lua - shopButton = nil - - connect(shop.categories, { - onChildFocusChange = changeCategory - }) - -end - -function createTransferWindow() - if transferWindow then - return - end - transferWindow = g_ui.displayUI('transfer') - transferWindow:hide() -end - -function onStoreInit(url, coins) - if otcv8shop then - return - end - storeUrl = url - if storeUrl:len() > 0 then - if storeUrl:sub(storeUrl:len(), storeUrl:len()) ~= "/" then - storeUrl = storeUrl .. "/" - end - storeUrl = storeUrl .. "64/" - if storeUrl:sub(1, 4):lower() ~= "http" then - storeUrl = "http://" .. storeUrl - end - end - coinsPacketSize = coins - createShop() - createTransferWindow() -end - -function onStoreCategories(categories) - if not shop or otcv8shop then - return - end - local correctCategories = {} - for i, category in ipairs(categories) do - local image = "" - if category.icon:len() > 0 then - image = storeUrl .. category.icon - end - table.insert(correctCategories, { - type = "image", - image = image, - name = category.name, - offers = {} - }) - end - processCategories(correctCategories) -end - -function onStoreOffers(categoryName, offers) - if not shop or otcv8shop then - return - end - local updated = false - - for i, category in ipairs(CATEGORIES) do - if category.name == categoryName then - if #category.offers ~= #offers then - updated = true - end - for i = 1, #category.offers do - if category.offers[i].title ~= offers[i].name or category.offers[i].id ~= offers[i].id or - category.offers[i].cost ~= offers[i].price then - updated = true - end - end - if updated then - for offer in pairs(category.offers) do - category.offers[offer] = nil - end - for i, offer in ipairs(offers) do - local image = "" - if offer.icon:len() > 0 then - image = storeUrl .. offer.icon - end - table.insert(category.offers, { - id = offer.id, - type = "image", - image = image, - cost = offer.price, - title = offer.name, - description = offer.description - }) - end - end - end - end - if not updated then - return - end - - local activeCategory = shop.categories:getFocusedChild() - changeCategory(activeCategory, activeCategory) -end - -function onStoreTransactionHistory(currentPage, hasNextPage, offers) - if not shop or otcv8shop then - return - end - HISTORY = {} - for i, offer in ipairs(offers) do - table.insert(HISTORY, { - id = offer.id, - type = "image", - image = storeUrl .. offer.icon, - cost = offer.price, - title = offer.name, - description = offer.description - }) - end - - if not browsingHistory then - return - end - clearOffers() - shop.categories:focusChild(nil) - for i, transaction in ipairs(HISTORY) do - addOffer(0, transaction) - end -end - -function onStorePurchase(message) - if not shop or otcv8shop then - return - end - if not transferWindow:isVisible() then - processMessage({ - title = "Successful shop purchase", - msg = message - }) - else - processMessage({ - title = "Successfuly gifted coins", - msg = message - }) - softHide() - end -end - -function onStoreError(errorType, message) - if not shop or otcv8shop then - return - end - if not transferWindow:isVisible() then - processMessage({ - title = "Shop Error", - msg = message - }) - else - processMessage({ - title = "Gift coins error", - msg = message - }) - end -end - -function onCoinBalance(coins, transferableCoins) - if not shop or otcv8shop then - return - end - shop.infoPanel.points:setText(tr("Points:") .. " " .. coins) - transferWindow.coinsBalance:setText(tr('Transferable Tibia Coins: ') .. coins) - transferWindow.coinsAmount:setMaximum(coins) - shop.infoPanel.buy:hide() - shop.infoPanel:setHeight(20) -end - -function transferCoins() - if not transferWindow then - return - end - local amount = 0 - amount = transferWindow.coinsAmount:getValue() - local recipient = transferWindow.recipient:getText() - - g_game.transferCoins(recipient, amount) - transferWindow.recipient:setText('') - transferWindow.coinsAmount:setValue(0) -end - -function onExtendedJSONOpcode(protocol, code, json_data) - createShop() - createTransferWindow() - - local action = json_data['action'] - local data = json_data['data'] - local status = json_data['status'] - if not action or not data then - return false - end - - otcv8shop = true - if action == 'categories' then - processCategories(data) - elseif action == 'history' then - processHistory(data) - elseif action == 'message' then - processMessage(data) - end - - if status then - processStatus(status) - end -end - -function clearOffers() - while shop.offers:getChildCount() > 0 do - local child = shop.offers:getLastChild() - shop.offers:destroyChildren(child) - end -end - -function clearCategories() - CATEGORIES = {} - clearOffers() - while shop.categories:getChildCount() > 0 do - local child = shop.categories:getLastChild() - shop.categories:destroyChildren(child) - end -end - -function clearHistory() - HISTORY = {} - if browsingHistory then - clearOffers() - end -end - -function processCategories(data) - if table.equal(CATEGORIES, data) then - return - end - clearCategories() - CATEGORIES = data - for i, category in ipairs(data) do - addCategory(category) - end - if not browsingHistory then - local firstCategory = shop.categories:getChildByIndex(1) - if firstCategory then - firstCategory:focus() - end - end -end - -function processHistory(data) - if table.equal(HISTORY, data) then - return - end - HISTORY = data - if browsingHistory then - showHistory(true) - end -end - -function processMessage(data) - if msgWindow then - msgWindow:destroy() - end - - local title = tr(data["title"]) - local msg = data["msg"] - msgWindow = displayInfoBox(title, msg) - msgWindow.onDestroy = function(widget) - if widget == msgWindow then - msgWindow = nil - end - end - msgWindow:show() - msgWindow:raise() - msgWindow:focus() -end -local function formatNumberWithCommas(value) - local formattedValue = string.format("%d", value) - -- Add commas to the formatted value - formattedValue = formattedValue:reverse():gsub("(%d%d%d)", "%1,") - return formattedValue:reverse():gsub("^,", "") -end - -function processStatus(data) - if table.equal(STATUS, data) then - return - end - STATUS = data - - if data['ad'] then - processAd(data['ad']) - end - if data['points'] then - shop.infoPanel.points:setText(tr("Points:") .. " " .. formatNumberWithCommas(data['points'])) - end - if data['buyUrl'] and data['buyUrl']:sub(1, 4):lower() == "http" then - shop.infoPanel.buy:show() - shop.infoPanel.buy.onMouseRelease = function() - scheduleEvent(function() - g_platform.openUrl(data['buyUrl']) - end, 50) - end - else - shop.infoPanel.buy:hide() - shop.infoPanel:setHeight(20) - end -end - -function processAd(data) - if table.equal(AD, data) then - return - end - AD = data - - if data['image'] then - - shop.adPanel:setHeight(shop.infoPanel:getHeight()) - shop.adPanel.ad:setText("") - shop.adPanel.ad:setImageSource(data['image']) - shop.adPanel.ad:setImageFixedRatio(true) - shop.adPanel.ad:setImageAutoResize(true) - shop.adPanel.ad:setHeight(shop.infoPanel:getHeight()) - - elseif data['text'] and data['text']:len() > 0 then - shop.adPanel:setHeight(shop.infoPanel:getHeight()) - shop.adPanel.ad:setText(data['text']) - shop.adPanel.ad:setHeight(shop.infoPanel:getHeight()) - else - shop.adPanel:setHeight(0) - end - if data['url'] and data['url']:sub(1, 4):lower() == "http" then - shop.adPanel.ad.onMouseRelease = function() - scheduleEvent(function() - g_platform.openUrl(data['url']) - end, 50) - end - else - shop.adPanel.ad.onMouseRelease = nil - end -end - -function addCategory(data) - - local category - if data["type"] == "item" then - category = g_ui.createWidget('ShopCategoryItem', shop.categories) - category.item:setItemId(data["item"]) - category.item:setItemCount(data["count"]) - -- category.item:setShowCount(false) - elseif data["type"] == "outfit" then - category = g_ui.createWidget('ShopCategoryCreature', shop.categories) - category.creature:setOutfit(data["outfit"]) - - elseif data["type"] == "shader" then - category = g_ui.createWidget('ShopCategoryCreature', shop.categories) - category.creature:setOutfit(g_game.getLocalPlayer():getOutfit()) - category.creature:getCreature():setShader(data["shader"]) - - elseif data["type"] == "image" then - category = g_ui.createWidget('ShopCategoryImage', shop.categories) - if data["image"] and data["image"]:sub(1, 4):lower() == "http" then - HTTP.downloadImage(data['image'], function(path, err) - if err then - g_logger.warning("HTTP error: " .. err .. " - " .. data["image"]) - return - end - category.image:setImageSource(path) - end) - else - category.image:setImageSource(data["image"]) - end - else - g_logger.error("Invalid shop category type: " .. tostring(data["type"])) - return - end - category:setId("category_" .. shop.categories:getChildCount()) - category.name:setText(data["name"]) -end - -function showHistory(force) - if browsingHistory and not force then - return - end - - sendAction("history") - - browsingHistory = true - clearOffers() - shop.categories:focusChild(nil) - for i, transaction in ipairs(HISTORY) do - addOffer(0, transaction) - end -end - -function addOffer(category, data) - local offer - if data["type"] == "item" then - offer = g_ui.createWidget('ShopOfferItem', shop.offers) - offer.item:setItemId(data["item"]) - offer.item:setItemCount(data["count"]) - -- offer.item:setShowCount(false) - - elseif data["type"] == "effect" then - - offer = g_ui.createWidget('ShopOfferCreature', shop.offers) - offer.creature:setOutfit(g_game.getLocalPlayer():getOutfit()) - offer.creature:getCreature():attachEffect(g_attachedEffects.getById(data["title"])) - - elseif data["type"] == "shader" then - - offer = g_ui.createWidget('ShopOfferCreature', shop.offers) - offer.creature:setOutfit(g_game.getLocalPlayer():getOutfit()) - offer.creature:getCreature():setShader(data["title"]) - - elseif data["type"] == "outfit" then - offer = g_ui.createWidget('ShopOfferCreature', shop.offers) - offer.creature:setOutfit(data["outfit"]) - if data["outfit"]["rotating"] then - -- offer.creature:setAutoRotating(true) - end - elseif data["type"] == "image" then - offer = g_ui.createWidget('ShopOfferImage', shop.offers) - if data["image"] and data["image"]:sub(1, 4):lower() == "http" then - HTTP.downloadImage(data['image'], function(path, err) - if err then - g_logger.warning("HTTP error: " .. err .. " - " .. data['image']) - return - end - if not offer.image then - return - end - offer.image:setImageSource(path) - end) - elseif data["image"] and data["image"]:len() > 1 then - offer.image:setImageSource(data["image"]) - end - else - g_logger.error("Invalid shop offer type: " .. tostring(data["type"])) - return - end - offer:setId("offer_" .. category .. "_" .. shop.offers:getChildCount()) - offer.title:setColoredText(data["title"] .. " {[" .. data["cost"] .. " points], #ff0000}") - offer.description:setText(data["description"]) - offer.offerId = data["id"] - if category ~= 0 then - offer.onDoubleClick = buyOffer - offer.buyButton.onClick = function() - buyOffer(offer) - end - else - offer.buyButton:hide() - end -end - -function changeCategory(widget, newCategory) - if not newCategory then - return - end - - browsingHistory = false - local id = tonumber(newCategory:getId():split("_")[2]) - clearOffers() - for i, offer in ipairs(CATEGORIES[id]["offers"]) do - addOffer(id, offer) - end -end - -function buyOffer(widget) - if not widget then - return - end - local split = widget:getId():split("_") - if #split ~= 3 then - return - end - local category = tonumber(split[2]) - local offer = tonumber(split[3]) - local item = CATEGORIES[category]["offers"][offer] - if not item then - return - end - - selectedOffer = { - category = category, - offer = offer, - title = item.title, - cost = item.cost, - id = widget.offerId - } - - scheduleEvent(function() - if msgWindow then - msgWindow:destroy() - end - - local title = tr("Buying from shop") - local msg = "Do you want to buy " .. item.title .. " for " .. item.cost .. " premium points?" - msgWindow = displayGeneralBox(title, msg, { - { - text = tr('Yes'), - callback = buyConfirmed - }, - { - text = tr('No'), - callback = buyCanceled - }, - anchor = AnchorHorizontalCenter - }, buyConfirmed, buyCanceled) - msgWindow:show() - msgWindow:raise() - msgWindow:focus() - msgWindow:raise() - end, 50) -end - -function buyConfirmed() - msgWindow:destroy() - msgWindow = nil - sendAction("buy", selectedOffer) - -end - -function buyCanceled() - msgWindow:destroy() - msgWindow = nil - selectedOffer = {} -end diff --git a/modules/game_shop/shop.otmod b/modules/game_shop/shop.otmod deleted file mode 100644 index eec111afb..000000000 --- a/modules/game_shop/shop.otmod +++ /dev/null @@ -1,10 +0,0 @@ -Module - name: game_shop - description: Game shop - author: otclient.ovh - website: http://otclient.ovh - sandboxed: true - scripts: [ shop ] - dependencies: [ client_topmenu ] - @onLoad: init() - @onUnload: terminate() diff --git a/modules/game_shop/shop.otui b/modules/game_shop/shop.otui deleted file mode 100644 index 67a0d1fff..000000000 --- a/modules/game_shop/shop.otui +++ /dev/null @@ -1,246 +0,0 @@ -ShopCategory < Panel - height: 36 - focusable: true - background: alpha - - $focus: - background: #99999999 - - Label - id: name - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - margin-left: 40 - text-align: left - color: white - font: verdana-11px-rounded - -ShopCategoryItem < ShopCategory - UIItem - id: item - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-top: 2 - margin-bottom: 2 - margin-left: 2 - virtual: true - size: 32 32 - -ShopCategoryCreature < ShopCategory - UICreature - id: creature - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-top: 2 - margin-bottom: 2 - margin-left: 2 - size: 32 32 - - -ShopCategoryImage < ShopCategory - Label - id: image - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-top: 2 - margin-bottom: 2 - margin-left: 2 - size: 32 32 - - - -ShopOffer < Panel - height: 56 - background: alpha - - $focus: - background: #99999999 - - Label - id: title - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - margin-top: 4 - margin-left: 55 - text-align: topleft - color: white - font: verdana-11px-rounded - - Label - id: description - anchors.top: prev.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - margin-left: 55 - margin-right: 55 - text-align: topleft - text-auto-resize: true - text-wrap: true - color: white - font: verdana-11px-rounded - - Button - id: buyButton - text: BUY - height: 25 - anchors.verticalCenter: parent.verticalCenter - anchors.left: prev.right - anchors.right: parent.right - margin-right: 15 - text-align: center - -ShopOfferItem < ShopOffer - UIItem - id: item - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-top: 4 - margin-bottom: 4 - margin-left: 2 - virtual: true - size: 48 48 - -ShopOfferCreature < ShopOffer - UICreature - id: creature - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-top: 4 - margin-bottom: 4 - margin-left: 2 - size: 48 48 - -ShopOfferImage < ShopOffer - Label - id: image - anchors.top: parent.top - anchors.left: parent.left - anchors.bottom: parent.bottom - margin-top: 4 - margin-bottom: 4 - margin-left: 2 - size: 48 48 - -MainWindow - id: shopWindow - !text: tr('Shop') - size: 750 500 - @onEscape: modules.game_shop.hide() - $mobile: - size: 500 360 - - Panel - id: infoPanel - anchors.top: parent.top - anchors.left: parent.left - width: 230 - height: 60 - - Label - id: points - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - margin-top: 10 - text: - - text-auto-resize: true - - Button - id: buy - anchors.horizontalCenter: parent.horizontalCenter - width: 150 - anchors.top: prev.bottom - margin-top: 10 - visible: false - !text: tr("Buy points2") - - Panel - id: adPanel - anchors.top: parent.top - anchors.left: infoPanel.right - anchors.right: parent.right - margin-left: 10 - height: 0 - - Label - id: ad - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.bottom: parent.bottom - text-auto-resize: true - text-wrap: true - text-align: center - font: sans-bold-16px - - TextList - id: categories - vertical-scrollbar: categoriesScrollBar - anchors.top: infoPanel.bottom - anchors.left: infoPanel.left - anchors.right: infoPanel.right - anchors.bottom: transactionHistory.top - margin-top: 10 - margin-bottom: 10 - padding: 1 - focusable: false - - VerticalScrollBar - id: categoriesScrollBar - anchors.top: categories.top - anchors.bottom: categories.bottom - anchors.right: categories.right - step: 50 - pixels-scroll: true - - TextList - id: offers - vertical-scrollbar: offersScrollBar - anchors.top: adPanel.bottom - anchors.left: adPanel.left - anchors.right: adPanel.right - anchors.bottom: transactionHistory.top - margin-top: 10 - margin-bottom: 10 - padding: 1 - focusable: false - - VerticalScrollBar - id: offersScrollBar - anchors.top: offers.top - anchors.bottom: offers.bottom - anchors.right: offers.right - step: 50 - pixels-scroll: true - - Button - id: transactionHistory - !text: tr('Transaction history') - width: 128 - anchors.left: parent.left - anchors.bottom: parent.bottom - @onClick: modules.game_shop.showHistory() - - Label - id: transferOpen - !text: tr('by kondra (otclient@otclient.ovh)') - width: 450 - anchors.left: prev. right - margin-left: 45 - anchors.verticalCenter: prev.verticalCenter - - - Button - id: buttonCancel - !text: tr('Close') - width: 64 - anchors.right: parent.right - anchors.bottom: parent.bottom - @onClick: modules.game_shop.hide() \ No newline at end of file diff --git a/modules/game_shop/transfer.otui b/modules/game_shop/transfer.otui deleted file mode 100644 index dbfefc499..000000000 --- a/modules/game_shop/transfer.otui +++ /dev/null @@ -1,80 +0,0 @@ -MainWindow - id: transferWindow - !text: tr('Gift Tibia Coins') - size: 280 240 - @onEscape: modules.game_shop.hideTransfer() - - Label - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - text-wrap: true - height: 56 - !text: tr('Please select the amount of Tibia Coins you would like to gift and enter the name of the character that should receive the Tibia Coins.') - - Label - anchors.top: prev.bottom - anchors.left: parent.left - margin-top: 20 - !text: tr('Reciepient:') - - TextEdit - id: recipient - anchors.verticalCenter: prev.verticalCenter - anchors.right: parent.right - width: 150 - text-align: left - - Label - id: coinsBalance - anchors.top: prev.bottom - anchors.left: parent.left - anchors.right: parent.right - margin-top: 10 - text-align: center - !text: tr('Transferable Tibia Coins:') - - Label - id: coinsAmountLabel - anchors.top: prev.bottom - anchors.left: parent.left - margin-top: 20 - !text: tr('Amount to gift: ') - - SpinBox - id: coinsAmount - anchors.right: parent.right - width: 100 - anchors.verticalCenter: prev.verticalCenter - text: 0 - minimum: 0 - maximum: 0 - focusable: true - editable: true - - HorizontalSeparator - anchors.right: parent.right - anchors.left: parent.left - anchors.bottom: cancelButton.top - margin-bottom: 8 - - Button - id: cancelButton - !text: tr('Cancel') - font: cipsoftFont - anchors.right: parent.right - anchors.bottom: parent.bottom - size: 45 21 - margin-top: 15 - margin-right: 5 - @onClick: modules.game_shop.hideTransfer() - - Button - id: giftButton - !text: tr('Gift') - font: cipsoftFont - size: 45 21 - anchors.verticalCenter: prev.verticalCenter - anchors.right: prev.left - margin-right: 5 - @onClick: modules.game_shop.transferCoins() \ No newline at end of file