mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-10-20 14:43:27 +02:00
Version 0.95 BETA
This commit is contained in:
380
modules/game_shop/shop.lua
Normal file
380
modules/game_shop/shop.lua
Normal file
@@ -0,0 +1,380 @@
|
||||
-- private variables
|
||||
local SHOP_EXTENTED_OPCODE = 201
|
||||
|
||||
shop = nil
|
||||
local shopButton = nil
|
||||
local msgWindow = nil
|
||||
local browsingHistory = false
|
||||
|
||||
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:sendExtendedOpcode(SHOP_EXTENTED_OPCODE, json.encode({action = action, data = data}))
|
||||
end
|
||||
end
|
||||
|
||||
-- public functions
|
||||
function init()
|
||||
connect(g_game, { onGameStart = check, onGameEnd = hide })
|
||||
|
||||
ProtocolGame.registerExtendedOpcode(SHOP_EXTENTED_OPCODE, onExtendedOpcode)
|
||||
|
||||
if g_game.isOnline() then
|
||||
check()
|
||||
end
|
||||
end
|
||||
|
||||
function terminate()
|
||||
disconnect(g_game, { onGameEnd = hide })
|
||||
|
||||
ProtocolGame.unregisterExtendedOpcode(SHOP_EXTENTED_OPCODE, onExtendedOpcode)
|
||||
|
||||
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()
|
||||
if not g_game.getFeature(GameExtendedOpcode) then
|
||||
return
|
||||
end
|
||||
sendAction("init")
|
||||
end
|
||||
|
||||
function hide()
|
||||
if not shop then
|
||||
return
|
||||
end
|
||||
shop:hide()
|
||||
end
|
||||
|
||||
function show()
|
||||
if not shop or not shopButton then
|
||||
return
|
||||
end
|
||||
shop:show()
|
||||
shop:raise()
|
||||
shop:focus()
|
||||
end
|
||||
|
||||
function toggle()
|
||||
if not shop then
|
||||
return
|
||||
end
|
||||
if shop:isVisible() then
|
||||
return hide()
|
||||
end
|
||||
show()
|
||||
check()
|
||||
end
|
||||
|
||||
function onExtendedOpcode(protocol, code, buffer)
|
||||
if not shop then
|
||||
shop = g_ui.displayUI('shop')
|
||||
shop:hide()
|
||||
shopButton = modules.client_topmenu.addRightGameToggleButton('shopButton', tr('Shop'), '/images/topbuttons/shop', toggle)
|
||||
|
||||
connect(shop.categories, { onChildFocusChange = changeCategory })
|
||||
end
|
||||
|
||||
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']
|
||||
local status = json_data['status']
|
||||
if not action or not data then
|
||||
return false
|
||||
end
|
||||
|
||||
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:show()
|
||||
msgWindow:raise()
|
||||
msgWindow:focus()
|
||||
msgWindow:raise()
|
||||
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:") .. " " .. 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()
|
||||
end
|
||||
end
|
||||
|
||||
function processAd(data)
|
||||
if table.equal(AD,data) then
|
||||
return
|
||||
end
|
||||
AD = data
|
||||
|
||||
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) return end
|
||||
shop.adPanel:setHeight(shop.infoPanel:getHeight())
|
||||
shop.adPanel.ad:setText("")
|
||||
shop.adPanel.ad:setImageSource(path)
|
||||
shop.adPanel.ad:setImageFixedRatio(true)
|
||||
shop.adPanel.ad:setImageAutoResize(true)
|
||||
shop.adPanel.ad:setHeight(shop.infoPanel:getHeight())
|
||||
end)
|
||||
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"])
|
||||
if data["outfit"]["rotating"] then
|
||||
category.creature:setAutoRotating(true)
|
||||
end
|
||||
elseif data["type"] == "image" then
|
||||
category = g_ui.createWidget('ShopCategoryImage', shop.categories)
|
||||
if data["image"]:sub(1, 4):lower() == "http" then
|
||||
HTTP.downloadImage(data['image'], function(path, err)
|
||||
if err then g_logger.warning("HTTP error: " .. err) 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"] == "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"]:sub(1, 4):lower() == "http" then
|
||||
HTTP.downloadImage(data['image'], function(path, err)
|
||||
if err then g_logger.warning("HTTP error: " .. err) 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:setText(data["title"] .. " (" .. data["cost"] .. " points)")
|
||||
offer.description:setText(data["description"])
|
||||
if category ~= 0 then
|
||||
offer.onDoubleClick = buyOffer
|
||||
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}
|
||||
|
||||
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
|
Reference in New Issue
Block a user