More on Market (far from done), Minor Fixes, Edited Outfits Module, Some Cosmetics.
* Started building the market UI. * More work on the market functionality. * Fixes to the market protocol. (Known issue: if I use safeSend method from Market (like so: MarketProtocol.send~) is thinks it is a bot). * Fixes to the market offer class. * Outfit window will no longer display the mount box if you are using protocol < 870. * Added getFeature to playermount module. * Added isMarketable and getMarketData to the lua binding. * Added lua casts for MarketData. * Fixed typo in the module manager. * Added new 'light flat panel' for more variation (can change later) will require some graphics for market. * Added new functions to table lib. * Fixed some styling issues from previous commits.
This commit is contained in:
parent
9dc88de6b0
commit
6293a49f8f
|
@ -146,7 +146,7 @@ function ModuleManager.unloadCurrentModule()
|
|||
end
|
||||
|
||||
function ModuleManager.reloadAllModules()
|
||||
g_modules.g_modules.reloadModules()
|
||||
g_modules.reloadModules()
|
||||
ModuleManager.refreshLoadedModules()
|
||||
ModuleManager.show()
|
||||
end
|
||||
|
|
|
@ -74,6 +74,7 @@ function Options.init()
|
|||
optionsWindow = g_ui.displayUI('options.otui')
|
||||
optionsWindow:hide()
|
||||
optionsButton = TopMenu.addLeftButton('optionsButton', tr('Options') .. ' (Ctrl+D)', 'options.png', Options.toggle)
|
||||
|
||||
optionsTabBar = optionsWindow:getChildById('optionsTabBar')
|
||||
optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent'))
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
|
@ -15,3 +15,7 @@ ScrollableFlatPanel < ScrollablePanel
|
|||
ParticlesFlatPanel < Panel
|
||||
image-source: /images/panel_flat.png
|
||||
image-border: 1
|
||||
|
||||
LightFlatPanel < Panel
|
||||
image-source: /images/panel_lightflat.png
|
||||
image-border: 1
|
||||
|
|
|
@ -41,6 +41,18 @@ function table.find(t, value)
|
|||
end
|
||||
end
|
||||
|
||||
function table.findKey(t, key)
|
||||
if t and type(t) == 'table' then
|
||||
for k,v in pairs(t) do
|
||||
if k == key then return k end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function table.hasKey(t, key)
|
||||
return table.findKey(t, key) ~= nil
|
||||
end
|
||||
|
||||
function table.removevalue(t, value)
|
||||
for k,v in pairs(t) do
|
||||
if v == value then
|
||||
|
@ -59,7 +71,7 @@ function table.compare(t, other)
|
|||
end
|
||||
|
||||
function table.empty(t)
|
||||
if(t) then
|
||||
if t and type(t) == 'table' then
|
||||
return next(t) == nil
|
||||
end
|
||||
return true
|
||||
|
|
|
@ -5,8 +5,8 @@ ExitWindow < MainWindow
|
|||
|
||||
Label
|
||||
!text: tr('If you shut down the program, you character might stay in the game.\nClick on "Logout" to ensure that you character leaves the game property.\nClick on "Exit" if you want to exit the program without logging out your character.')
|
||||
width: 550
|
||||
height: 110
|
||||
width: 500
|
||||
height: 45
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-left: 10
|
||||
|
|
|
@ -5,7 +5,7 @@ LogoutWindow < MainWindow
|
|||
|
||||
Label
|
||||
!text: tr('Are you sure you want to logout?')
|
||||
width: 300
|
||||
width: 200
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
margin-left: 30
|
||||
|
|
|
@ -1,61 +1,262 @@
|
|||
Market = {}
|
||||
|
||||
g_ui.importStyle('market.otui')
|
||||
g_ui.importStyle('ui/general/markettabs.otui')
|
||||
g_ui.importStyle('ui/general/marketbuttons.otui')
|
||||
|
||||
local marketWindow
|
||||
local mainTabBar
|
||||
|
||||
local marketOffersPanel
|
||||
local selectionTabBar
|
||||
local browsePanel
|
||||
local searchPanel
|
||||
|
||||
local displaysTabBar
|
||||
local itemOffersPanel
|
||||
local itemDetailsPanel
|
||||
local itemStatsPanel
|
||||
|
||||
local myOffersPanel
|
||||
local offersTabBar
|
||||
local currentOffersPanel
|
||||
local offerHistoryPanel
|
||||
|
||||
local marketOffers = {}
|
||||
local depot = {}
|
||||
local information ={}
|
||||
local selectedItem
|
||||
local nameLabel
|
||||
|
||||
local itemsPanel
|
||||
local radioItems
|
||||
|
||||
local function clearSelectedItem()
|
||||
if selectedItem then
|
||||
nameLabel:clearText()
|
||||
radioItems:selectWidget(nil)
|
||||
selectedItem.setItem(nil)
|
||||
end
|
||||
end
|
||||
|
||||
local function loadMarketItems()
|
||||
itemsPanel = marketWindow:recursiveGetChildById('itemsPanel')
|
||||
|
||||
local layout = itemsPanel:getLayout()
|
||||
layout:disableUpdates()
|
||||
|
||||
clearSelectedItem()
|
||||
itemsPanel:destroyChildren()
|
||||
|
||||
if radioItemSet then
|
||||
radioItemSet:destroy()
|
||||
end
|
||||
radioItemSet = UIRadioGroup.create()
|
||||
|
||||
-- TODO: populate with dat items
|
||||
|
||||
|
||||
layout:enableUpdates()
|
||||
layout:update()
|
||||
end
|
||||
|
||||
local function loadDepotItems(depotItems)
|
||||
information.depotItems = {}
|
||||
for _, data in pairs(depotItems) do
|
||||
local item = Item.create(data[1])
|
||||
if not item then
|
||||
break
|
||||
end
|
||||
item:setCount(data[2])
|
||||
local marketData = item:getMarketData()
|
||||
|
||||
if not table.empty(marketData) then
|
||||
local newItem = {
|
||||
ptr = item,
|
||||
marketData = marketData
|
||||
}
|
||||
table.insert(information.depotItems, newItem)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Market.init()
|
||||
g_ui.importStyle('market.otui')
|
||||
marketWindow = g_ui.createWidget('MarketWindow', rootWidget)
|
||||
marketWindow:hide()
|
||||
|
||||
nameLabel = marketWindow:recursiveGetChildById('nameLabel')
|
||||
|
||||
-- TODO: clean this up into functions
|
||||
-- setup main tabs
|
||||
mainTabBar = marketWindow:getChildById('mainTabBar')
|
||||
mainTabBar:setContentWidget(marketWindow:getChildById('mainTabContent'))
|
||||
|
||||
-- setup 'Market Offer' section tabs
|
||||
marketOffersPanel = g_ui.loadUI('ui/marketoffers.otui')
|
||||
mainTabBar:addTab(tr('Market Offers'), marketOffersPanel)
|
||||
|
||||
selectionTabBar = marketOffersPanel:getChildById('leftTabBar')
|
||||
selectionTabBar:setContentWidget(marketOffersPanel:getChildById('leftTabContent'))
|
||||
|
||||
browsePanel = g_ui.loadUI('ui/marketoffers/browse.otui')
|
||||
selectionTabBar:addTab(tr('Browse'), browsePanel)
|
||||
|
||||
searchPanel = g_ui.loadUI('ui/marketoffers/search.otui')
|
||||
selectionTabBar:addTab(tr('Search'), searchPanel)
|
||||
|
||||
displaysTabBar = marketOffersPanel:getChildById('rightTabBar')
|
||||
displaysTabBar:setContentWidget(marketOffersPanel:getChildById('rightTabContent'))
|
||||
|
||||
itemOffersPanel = g_ui.loadUI('ui/marketoffers/itemoffers.otui')
|
||||
displaysTabBar:addTab(tr('Offers'), itemOffersPanel)
|
||||
|
||||
itemDetailsPanel = g_ui.loadUI('ui/marketoffers/itemdetails.otui')
|
||||
displaysTabBar:addTab(tr('Details'), itemDetailsPanel)
|
||||
|
||||
itemStatsPanel = g_ui.loadUI('ui/marketoffers/itemstats.otui')
|
||||
displaysTabBar:addTab(tr('Statistics'), itemStatsPanel)
|
||||
|
||||
-- setup 'My Offer' section tabs
|
||||
myOffersPanel = g_ui.loadUI('ui/myoffers.otui')
|
||||
mainTabBar:addTab(tr('My Offers'), myOffersPanel)
|
||||
|
||||
offersTabBar = myOffersPanel:getChildById('offersTabBar')
|
||||
offersTabBar:setContentWidget(myOffersPanel:getChildById('offersTabContent'))
|
||||
|
||||
currentOffersPanel = g_ui.loadUI('ui/myoffers/currentoffers.otui')
|
||||
offersTabBar:addTab(tr('Current Offers'), currentOffersPanel)
|
||||
|
||||
offerHistoryPanel = g_ui.loadUI('ui/myoffers/offerhistory.otui')
|
||||
offersTabBar:addTab(tr('Offer History'), offerHistoryPanel)
|
||||
end
|
||||
|
||||
function Market.terminate()
|
||||
marketWindow = nil
|
||||
if marketWindow then
|
||||
marketWindow:destroy()
|
||||
marketWindow = nil
|
||||
end
|
||||
|
||||
mainTabBar = nil
|
||||
marketOffersPanel = nil
|
||||
selectionTabBar = nil
|
||||
browsePanel = nil
|
||||
searchPanel = nil
|
||||
displaysTabBar = nil
|
||||
itemOffersPanel = nil
|
||||
itemDetailsPanel = nil
|
||||
itemStatsPanel = nil
|
||||
myOffersPanel = nil
|
||||
offersTabBar = nil
|
||||
currentOffersPanel = nil
|
||||
offerHistoryPanel = nil
|
||||
marketOffers = {}
|
||||
depotItems = {}
|
||||
information = {}
|
||||
itemsPanel = nil
|
||||
nameLabel = nil
|
||||
radioItems = nil
|
||||
selectedItem = nil
|
||||
|
||||
Market = nil
|
||||
end
|
||||
|
||||
function Market.onMarketEnter(depotItems, offers, balance)
|
||||
-- open market window
|
||||
-- populate market?
|
||||
print('onMarketEnter')
|
||||
print(offers)
|
||||
print(balance)
|
||||
print('depotItems:')
|
||||
for k, item in pairs(depotItems) do
|
||||
print('id- '..item[1])
|
||||
print('count- '..item[2])
|
||||
function Market.updateOffers(offers)
|
||||
for k, offer in pairs(offers) do
|
||||
if offer and offer:getAction() == MarketAction.Buy then
|
||||
table.insert(marketOffers[MarketAction.Buy], offer)
|
||||
else
|
||||
table.insert(marketOffers[MarketAction.Sell], offer)
|
||||
end
|
||||
end
|
||||
|
||||
for _, offers in pairs(marketOffers) do
|
||||
for _, offer in pairs(offers) do
|
||||
print(' counter: '..offer:getCounter()..' | timestamp: '..offer:getTimeStamp()..' | item: '..offer:getItem():getId()..' | action: '..offer:getAction()..' | amount: '..offer:getAmount()..' | price: '..offer:getPrice()..' | player: '..offer:getPlayer()..' | state: '..offer:getState())
|
||||
end
|
||||
end
|
||||
-- TODO: refresh all widget windows
|
||||
end
|
||||
|
||||
function Market.updateDetails(itemId, descriptions, purchaseStats, saleStats)
|
||||
-- TODO: refresh all widget windows
|
||||
|
||||
end
|
||||
|
||||
function Market.updateSelectedItem(newItem)
|
||||
local itemDisplay = marketWindow:recursiveGetChildById('selectedItem')
|
||||
local itemName = marketWindow:recursiveGetChildById('nameLabel')
|
||||
selectedItem = newItem
|
||||
if not table.empty(selectedItem) then
|
||||
if selectedItem.ptr then
|
||||
itemDisplay:setItem(selectedItem.ptr)
|
||||
itemName:setText(tr(selectedItem.name))
|
||||
MarketProtocol.sendMarketBrowse(selectedItem.ptr:getId()) -- send sprite id browsed
|
||||
end
|
||||
else
|
||||
itemDisplay:setItem(nil)
|
||||
itemName:setText(tr('No item selected.'))
|
||||
end
|
||||
end
|
||||
|
||||
function Market.onMarketEnter(depotItems, offers, balance)
|
||||
-- TODO: populate market?
|
||||
if marketWindow:isVisible() then
|
||||
return
|
||||
end
|
||||
marketOffers[MarketAction.Buy] = {}
|
||||
marketOffers[MarketAction.Sell] = {}
|
||||
|
||||
information.balance = balance
|
||||
information.totalOffers = offers
|
||||
|
||||
loadMarketItems()
|
||||
loadDepotItems(depotItems)
|
||||
|
||||
-- TODO: if you are already viewing an item on market enter it must recheck the current item
|
||||
if selectedItem and selectedItem:isChecked() then
|
||||
selectedItem:setChecked(false)
|
||||
selectedItem:setChecked(true)
|
||||
end
|
||||
--MarketProtocol.sendMarketBrowse(645)
|
||||
marketWindow:show()
|
||||
end
|
||||
|
||||
function Market.onMarketLeave()
|
||||
-- close market window?
|
||||
print('onMarketLeave')
|
||||
marketWindow:hide()
|
||||
end
|
||||
|
||||
function Market.onMarketDetail(itemId, descriptions, purchaseStats, saleStats)
|
||||
-- populate market widget
|
||||
print('onMarketDetail')
|
||||
print(itemId)
|
||||
Market.updateDetails(itemId, descriptions, purchaseStats, saleStats)
|
||||
|
||||
print('')
|
||||
print('[onMarketDetail]')
|
||||
print('itemId: '..itemId)
|
||||
print('descriptions:')
|
||||
for k, desc in pairs(descriptions) do
|
||||
print('type- '..desc[1])
|
||||
print('description- '..desc[2])
|
||||
print(' type: '..desc[1]..' | description: '..desc[2])
|
||||
end
|
||||
print('purchaseStats:')
|
||||
for k, stat in pairs(purchaseStats) do
|
||||
print('transactions- '..stat[1])
|
||||
print('total price- '..stat[2])
|
||||
print('highest price- '..stat[3])
|
||||
print('lowest price- '..stat[4])
|
||||
print(' transactions: '..stat[1])
|
||||
print(' total price: '..stat[2])
|
||||
print(' highest price: '..stat[3])
|
||||
print(' lowest price: '..stat[4])
|
||||
end
|
||||
print('saleStats:')
|
||||
for k, stat in pairs(saleStats) do
|
||||
print('transactions- '..stat[1])
|
||||
print('total price- '..stat[2])
|
||||
print('highest price- '..stat[3])
|
||||
print('lowest price- '..stat[4])
|
||||
print(' transactions: '..stat[1])
|
||||
print(' total price: '..stat[2])
|
||||
print(' highest price: '..stat[3])
|
||||
print(' lowest price: '..stat[4])
|
||||
end
|
||||
end
|
||||
|
||||
function Market.onMarketBrowse(offers)
|
||||
-- populate market widget
|
||||
print('onMarketBrowse')
|
||||
Market.updateOffers(offers)
|
||||
end
|
||||
|
||||
function Market.onItemBoxChecked(widget)
|
||||
if widget:isChecked() then
|
||||
Market.updateSelectedItem(widget.item)
|
||||
end
|
||||
end
|
|
@ -1,29 +1,26 @@
|
|||
MarketWindow < MainWindow
|
||||
id: marketWindow
|
||||
!text: tr('Market')
|
||||
size: 350 155
|
||||
size: 680 460
|
||||
|
||||
Label
|
||||
!text: tr('Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!')
|
||||
width: 550
|
||||
height: 140
|
||||
anchors.left: parent.left
|
||||
@onEnter: self:hide()
|
||||
@onEscape: self:hide()
|
||||
|
||||
// Main Panel Window
|
||||
|
||||
MarketTabBar
|
||||
id: mainTabBar
|
||||
width: 164
|
||||
height: 25
|
||||
anchors.top: parent.top
|
||||
margin-left: 10
|
||||
margin-top: 2
|
||||
|
||||
Button
|
||||
id: buttonOk
|
||||
!text: tr('Ok')
|
||||
width: 64
|
||||
anchors.left: parent.left
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 160
|
||||
|
||||
Button
|
||||
id: buttonCancel
|
||||
!text: tr('Cancel')
|
||||
width: 64
|
||||
anchors.left: prev.right
|
||||
Panel
|
||||
id: mainTabContent
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left: 5
|
||||
padding: 3
|
||||
border-width: 1
|
||||
border-color: #000000
|
||||
|
|
|
@ -4,7 +4,7 @@ MarketOffer.__index = MarketOffer
|
|||
local OFFER_TIMESTAMP = 1
|
||||
local OFFER_COUNTER = 2
|
||||
|
||||
MarketOffer.new = function(offerId, action, itemId, amount, price, playerName, state)
|
||||
MarketOffer.new = function(offerId, action, item, amount, price, playerName, state)
|
||||
local offer = {
|
||||
id = {},
|
||||
action = nil,
|
||||
|
@ -26,7 +26,11 @@ MarketOffer.new = function(offerId, action, itemId, amount, price, playerName, s
|
|||
end
|
||||
offer.action = action
|
||||
|
||||
offer.item = itemId
|
||||
if not item then
|
||||
g_logger.error('MarketOffer.new - invalid item provided.')
|
||||
end
|
||||
offer.item = item
|
||||
|
||||
offer.amount = amount
|
||||
offer.price = price
|
||||
offer.player = playerName
|
||||
|
@ -67,8 +71,19 @@ function MarketOffer:getId()
|
|||
return self.id
|
||||
end
|
||||
|
||||
function MarketOffer:setAction(action)
|
||||
if not action or type(action) ~= 'number' then
|
||||
g_logger.error('MarketOffer.setItem - invalid action id provided.')
|
||||
end
|
||||
self.action = action
|
||||
end
|
||||
|
||||
function MarketOffer:getAction()
|
||||
return self.action
|
||||
end
|
||||
|
||||
function MarketOffer:setItem(item)
|
||||
if not item or type(item) ~= 'number' then
|
||||
if not item or type(item) ~= 'userdata' then
|
||||
g_logger.error('MarketOffer.setItem - invalid item id provided.')
|
||||
end
|
||||
self.item = item
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
MarketProtocol = {}
|
||||
|
||||
local market
|
||||
|
||||
-- private functions
|
||||
|
||||
local protocol
|
||||
|
||||
local function send(msg)
|
||||
print(msg:getMessageSize())
|
||||
g_game.getProtocolGame():safeSend(msg)
|
||||
if protocol then
|
||||
print(msg:getMessageSize())
|
||||
--protocol:safeSend(msg)
|
||||
protocol:send(msg)
|
||||
end
|
||||
end
|
||||
|
||||
local function readMarketOffer(msg, action, var)
|
||||
|
@ -29,12 +33,15 @@ local function readMarketOffer(msg, action, var)
|
|||
playerName = msg:getString()
|
||||
end
|
||||
|
||||
return MarketOffer.new({timestamp, counter}, action, itemId, amount, price, playerName, state)
|
||||
return MarketOffer.new({timestamp, counter}, action, Item.create(itemId), amount, price, playerName, state)
|
||||
end
|
||||
|
||||
-- parsing protocols
|
||||
local function parseMarketEnter(msg)
|
||||
local balance = msg:getU32()
|
||||
if g_game.getProtocolVersion() < 950 then
|
||||
msg:getU8() -- get vocation id
|
||||
end
|
||||
local offers = msg:getU8()
|
||||
local depotItems = {}
|
||||
|
||||
|
@ -47,10 +54,12 @@ local function parseMarketEnter(msg)
|
|||
end
|
||||
|
||||
Market.onMarketEnter(depotItems, offers, balance)
|
||||
return true
|
||||
end
|
||||
|
||||
local function parseMarketLeave(msg)
|
||||
Market.onMarketLeave()
|
||||
return true
|
||||
end
|
||||
|
||||
local function parseMarketDetail(msg)
|
||||
|
@ -59,7 +68,7 @@ local function parseMarketDetail(msg)
|
|||
local descriptions = {}
|
||||
for i = MarketItemDescription.First, MarketItemDescription.Last do
|
||||
if msg:peekU16() ~= 0x00 then
|
||||
table.insert(descriptions, {i, msg:getString()})
|
||||
table.insert(descriptions, {i, msg:getString()}) -- item descriptions
|
||||
else
|
||||
msg:getU16()
|
||||
end
|
||||
|
@ -86,6 +95,7 @@ local function parseMarketDetail(msg)
|
|||
end
|
||||
|
||||
Market.onMarketDetail(itemId, descriptions, purchaseStats, saleStats)
|
||||
return true
|
||||
end
|
||||
|
||||
local function parseMarketBrowse(msg)
|
||||
|
@ -103,26 +113,55 @@ local function parseMarketBrowse(msg)
|
|||
end
|
||||
|
||||
Market.onMarketBrowse(offers)
|
||||
return true
|
||||
end
|
||||
|
||||
-- public functions
|
||||
function MarketProtocol.init()
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketEnter, parseMarketEnter)
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketLeave, parseMarketLeave)
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketDetail, parseMarketDetail)
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketBrowse, parseMarketBrowse)
|
||||
connect(g_game, { onGameStart = MarketProtocol.registerProtocol,
|
||||
onGameEnd = MarketProtocol.unregisterProtocol })
|
||||
|
||||
-- reloading module
|
||||
if g_game.isOnline() then
|
||||
MarketProtocol.updateProtocol(g_game.getProtocolGame())
|
||||
end
|
||||
end
|
||||
|
||||
function MarketProtocol.terminate()
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketEnter, parseMarketEnter)
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketLeave, parseMarketLeave)
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketDetail, parseMarketDetail)
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketBrowse, parseMarketBrowse)
|
||||
disconnect(g_game, { onGameStart = MarketProtocol.registerProtocol,
|
||||
onGameEnd = MarketProtocol.unregisterProtocol })
|
||||
|
||||
market = nil
|
||||
-- reloading module
|
||||
if not g_game.isOnline() then
|
||||
MarketProtocol.updateProtocol(nil)
|
||||
end
|
||||
MarketProtocol = nil
|
||||
end
|
||||
|
||||
function MarketProtocol.updateProtocol(_protocol)
|
||||
protocol = _protocol
|
||||
end
|
||||
|
||||
function MarketProtocol.registerProtocol()
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketEnter, parseMarketEnter)
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketLeave, parseMarketLeave)
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketDetail, parseMarketDetail)
|
||||
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerMarketBrowse, parseMarketBrowse)
|
||||
end
|
||||
MarketProtocol.updateProtocol(g_game.getProtocolGame())
|
||||
end
|
||||
|
||||
function MarketProtocol.unregisterProtocol()
|
||||
if g_game.getFeature(GamePlayerMarket) then
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketEnter, parseMarketEnter)
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketLeave, parseMarketLeave)
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketDetail, parseMarketDetail)
|
||||
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerMarketBrowse, parseMarketBrowse)
|
||||
end
|
||||
MarketProtocol.updateProtocol(nil)
|
||||
end
|
||||
|
||||
-- sending protocols
|
||||
|
||||
function MarketProtocol.sendMarketLeave()
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
MarketButtonBox < UICheckBox
|
||||
font: verdana-11px-antialised
|
||||
color: #ffffffff
|
||||
size: 106 22
|
||||
text-offset: 0 0
|
||||
text-align: center
|
||||
image-source: /images/tabbutton.png
|
||||
image-clip: 0 0 20 20
|
||||
image-border: 2
|
||||
|
||||
$hover !disabled:
|
||||
image-clip: 0 20 20 20
|
||||
|
||||
$checked:
|
||||
image-clip: 0 40 20 20
|
||||
color: white
|
||||
|
||||
$disabled:
|
||||
color: #666666ff
|
||||
image-color: #ffffff88
|
|
@ -0,0 +1,33 @@
|
|||
MarketTabBar < UITabBar
|
||||
size: 80 20
|
||||
MarketTabBarPanel < Panel
|
||||
MarketTabBarButton < UIButton
|
||||
size: 20 25
|
||||
image-source: /images/tabbutton.png
|
||||
image-clip: 0 0 20 20
|
||||
image-border: 2
|
||||
icon-color: white
|
||||
color: #aaaaaa
|
||||
anchors.top: parent.top
|
||||
padding: 5
|
||||
|
||||
$first:
|
||||
anchors.left: parent.left
|
||||
|
||||
$!first:
|
||||
anchors.left: prev.right
|
||||
|
||||
$hover !checked:
|
||||
image-clip: 0 20 20 20
|
||||
color: white
|
||||
|
||||
$disabled:
|
||||
image-color: #ffffff66
|
||||
icon-color: #888888
|
||||
|
||||
$checked:
|
||||
image-clip: 0 20 20 20
|
||||
color: #ffffff
|
||||
|
||||
$on !checked:
|
||||
color: #f55e5e
|
|
@ -0,0 +1,49 @@
|
|||
Panel
|
||||
|
||||
MarketTabBar
|
||||
id: leftTabBar
|
||||
width: 107
|
||||
height:25
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
|
||||
Panel
|
||||
id: leftTabContent
|
||||
width: 180
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
anchors.bottom: parent.bottom
|
||||
border-width: 1
|
||||
border-color: #000000
|
||||
|
||||
MarketTabBar
|
||||
id: rightTabBar
|
||||
width: 157
|
||||
height:25
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
|
||||
Panel
|
||||
id: rightTabContent
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: leftTabContent.right
|
||||
anchors.right: prev.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-left:3
|
||||
border-width: 1
|
||||
border-color: #000000
|
||||
|
||||
Item
|
||||
id: selectedItem
|
||||
phantom: true
|
||||
anchors.top: rightTabBar.bottom
|
||||
anchors.left: rightTabContent.left
|
||||
margin-top: 3
|
||||
margin-left: 3
|
||||
|
||||
Label
|
||||
id: nameLabel
|
||||
!text: tr('No item selected.')
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
margin-left: 5
|
|
@ -0,0 +1,125 @@
|
|||
MarketItemBox < UICheckBox
|
||||
border-width: 1
|
||||
border-color: #000000
|
||||
color: #aaaaaa
|
||||
text-align: center
|
||||
text-offset: 0 20
|
||||
@onCheckChange: Market.onItemBoxChecked(self)
|
||||
|
||||
Item
|
||||
id: item
|
||||
phantom: true
|
||||
anchors.top: parent.top
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
margin-top: 5
|
||||
|
||||
$checked:
|
||||
border-color: #ffffff
|
||||
|
||||
$hover !checked:
|
||||
border-color: #aaaaaa
|
||||
|
||||
$disabled:
|
||||
image-color: #ffffff88
|
||||
color: #aaaaaa88
|
||||
|
||||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
ComboBox
|
||||
id: filterComboBox
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
|
||||
ComboBox
|
||||
id: weaponComboBox
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
|
||||
MarketButtonBox
|
||||
id: filterMatchLevel
|
||||
checked: false
|
||||
!text: tr('Level')
|
||||
!tooltip: tr('Filter list to match your level')
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
margin-top: 3
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
width: 40
|
||||
height: 20
|
||||
//@onClick: Market.filterMatchLevel()
|
||||
|
||||
MarketButtonBox
|
||||
id: filterMatchVocation
|
||||
checked: false
|
||||
!text: tr('Vocation')
|
||||
!tooltip: tr('Filter list to match your vocation')
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
width: 60
|
||||
height: 20
|
||||
//@onClick: Market.filterMatchVocation()
|
||||
|
||||
ComboBox
|
||||
id: typeComboBox
|
||||
anchors.top: prev.top
|
||||
anchors.left: prev.right
|
||||
anchors.right: parent.right
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
|
||||
MarketButtonBox
|
||||
id: showDepotOnly
|
||||
checked: false
|
||||
!text: tr('Show Depot Only')
|
||||
!tooltip: tr('Show your depot items only')
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
margin-top: 3
|
||||
margin-right: 3
|
||||
margin-left: 3
|
||||
//@onClick: Market.setDisplayDepot()
|
||||
|
||||
Panel
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
margin-top: 10
|
||||
margin-left: 3
|
||||
margin-bottom: 10
|
||||
margin-right: 3
|
||||
|
||||
VerticalScrollBar
|
||||
id: itemsPanelListScrollBar
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.right: parent.right
|
||||
step: 16
|
||||
pixels-scroll: true
|
||||
|
||||
ScrollablePanel
|
||||
id: itemsPanel
|
||||
anchors.left: parent.left
|
||||
anchors.right: prev.left
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
vertical-scrollbar: itemsPanelListScrollBar
|
||||
layout:
|
||||
type: grid
|
||||
cell-size: 34 34
|
||||
flow: true
|
||||
auto-spacing: true
|
|
@ -0,0 +1,10 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Item Details')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 45
|
||||
margin-left: 3
|
|
@ -0,0 +1,10 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Item Offers')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 45
|
||||
margin-left: 3
|
|
@ -0,0 +1,10 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Item Stats')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-top: 45
|
||||
margin-left: 3
|
|
@ -0,0 +1,9 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Search')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
|
@ -0,0 +1,16 @@
|
|||
Panel
|
||||
|
||||
MarketTabBar
|
||||
id: offersTabBar
|
||||
width: 187
|
||||
height:25
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
|
||||
Panel
|
||||
id: offersTabContent
|
||||
anchors.top: prev.bottom
|
||||
anchors.left: prev.left
|
||||
anchors.right: prev.right
|
||||
anchors.bottom: parent.bottom
|
|
@ -0,0 +1,9 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Current Offers')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
|
@ -0,0 +1,9 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Item Offers')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
|
@ -0,0 +1,9 @@
|
|||
Panel
|
||||
background-color: #22283399
|
||||
margin: 1
|
||||
|
||||
Label
|
||||
!text: tr('Offer History')
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
margin-left: 10
|
|
@ -150,14 +150,35 @@ function Outfit.create(creatureOutfit, outfitList, creatureMount, mountList)
|
|||
mountCreature = creatureMount
|
||||
outfits = outfitList
|
||||
mounts = mountList
|
||||
Outfit.destroy()
|
||||
Outfit.destroy()
|
||||
|
||||
outfitWindow = g_ui.displayUI('outfitwindow.otui')
|
||||
outfit = outfitCreature:getOutfit()
|
||||
if mountCreature then
|
||||
local colorBoxPanel = outfitWindow:getChildById('colorBoxPanel')
|
||||
|
||||
-- setup outfit/mount display boxs
|
||||
local outfitCreatureBox = outfitWindow:getChildById('outfitCreatureBox')
|
||||
if outfitCreature then
|
||||
outfit = outfitCreature:getOutfit()
|
||||
outfitCreatureBox:setCreature(outfitCreature)
|
||||
else
|
||||
outfitCreatureBox:hide()
|
||||
outfitWindow:getChildById('outfitName'):hide()
|
||||
outfitWindow:getChildById('outfitNextButton'):hide()
|
||||
outfitWindow:getChildById('outfitPrevButton'):hide()
|
||||
end
|
||||
|
||||
local mountCreatureBox = outfitWindow:getChildById('mountCreatureBox')
|
||||
if mountCreature then
|
||||
mount = mountCreature:getOutfit()
|
||||
mountCreatureBox:setCreature(mountCreature)
|
||||
else
|
||||
mountCreatureBox:hide()
|
||||
outfitWindow:getChildById('mountName'):hide()
|
||||
outfitWindow:getChildById('mountNextButton'):hide()
|
||||
outfitWindow:getChildById('mountPrevButton'):hide()
|
||||
end
|
||||
|
||||
-- set addons
|
||||
addons = {
|
||||
[1] = {widget = outfitWindow:getChildById('addon1'), value = 1},
|
||||
[2] = {widget = outfitWindow:getChildById('addon2'), value = 2},
|
||||
|
@ -174,21 +195,14 @@ function Outfit.create(creatureOutfit, outfitList, creatureMount, mountList)
|
|||
end
|
||||
end
|
||||
|
||||
-- hook outfit sections
|
||||
currentClotheButtonBox = outfitWindow:getChildById('head')
|
||||
outfitWindow:getChildById('head').onCheckChange = onClotheCheckChange
|
||||
outfitWindow:getChildById('primary').onCheckChange = onClotheCheckChange
|
||||
outfitWindow:getChildById('secondary').onCheckChange = onClotheCheckChange
|
||||
outfitWindow:getChildById('detail').onCheckChange = onClotheCheckChange
|
||||
|
||||
local outfitCreatureBox = outfitWindow:getChildById('outfitCreatureBox')
|
||||
local colorBoxPanel = outfitWindow:getChildById('colorBoxPanel')
|
||||
outfitCreatureBox:setCreature(outfitCreature)
|
||||
|
||||
if mountCreature then
|
||||
local mountCreatureBox = outfitWindow:getChildById('mountCreatureBox')
|
||||
mountCreatureBox:setCreature(mountCreature)
|
||||
end
|
||||
|
||||
-- populate color panel
|
||||
for j=0,6 do
|
||||
for i=0,18 do
|
||||
local colorBox = g_ui.createWidget('ColorBox', colorBoxPanel)
|
||||
|
@ -206,9 +220,10 @@ function Outfit.create(creatureOutfit, outfitList, creatureMount, mountList)
|
|||
end
|
||||
end
|
||||
|
||||
-- set current outfit/mount
|
||||
currentOutfit = 1
|
||||
for i=1,#outfitList do
|
||||
if outfitList[i][1] == outfit.type then
|
||||
if outfit and outfitList[i][1] == outfit.type then
|
||||
currentOutfit = i
|
||||
break
|
||||
end
|
||||
|
|
|
@ -48,7 +48,7 @@ Window
|
|||
Label
|
||||
id: outfitName
|
||||
!text: tr('No Outfit')
|
||||
width: 100
|
||||
width: 115
|
||||
anchors.bottom: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-bottom: 2
|
||||
|
@ -81,7 +81,7 @@ Window
|
|||
Label
|
||||
id: mountName
|
||||
!text: tr('No Mount')
|
||||
width: 140
|
||||
width: 115
|
||||
anchors.bottom: prev.top
|
||||
anchors.left: prev.left
|
||||
margin-bottom: 2
|
||||
|
@ -95,7 +95,7 @@ Window
|
|||
@onClick: Outfit.nextMountType()
|
||||
|
||||
PrevMountButton
|
||||
id: mountPreviousButton
|
||||
id: mountPrevButton
|
||||
anchors.right: mountCreatureBox.left
|
||||
anchors.verticalCenter: mountCreatureBox.verticalCenter
|
||||
margin-right: 3
|
||||
|
@ -170,7 +170,7 @@ Window
|
|||
anchors.left: head.left
|
||||
margin-top: 3
|
||||
margin-right: 20
|
||||
width: 323
|
||||
width: 302
|
||||
height: 119
|
||||
layout:
|
||||
type: grid
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
PlayerMount = {}
|
||||
|
||||
function PlayerMount.init()
|
||||
g_keyboard.bindKeyDown('Ctrl+R', PlayerMount.toggleMount, gameRootPanel)
|
||||
if g_game.getFeature(GamePlayerMount) then
|
||||
g_keyboard.bindKeyDown('Ctrl+R', PlayerMount.toggleMount, gameRootPanel)
|
||||
end
|
||||
end
|
||||
|
||||
function PlayerMount.terminate()
|
||||
g_keyboard.unbindKeyDown('Ctrl+R', gameRootPanel)
|
||||
if g_game.getFeature(GamePlayerMount) then
|
||||
g_keyboard.unbindKeyDown('Ctrl+R', gameRootPanel)
|
||||
end
|
||||
|
||||
PlayerMount = nil
|
||||
end
|
||||
|
|
|
@ -31,8 +31,7 @@ MarketItemDescription = {
|
|||
Ability = 12,
|
||||
Charges = 13,
|
||||
WeaponName = 14,
|
||||
Weight = 15,
|
||||
|
||||
First = Armor,
|
||||
Last = Weight
|
||||
Weight = 15
|
||||
}
|
||||
MarketItemDescription.First = MarketItemDescription.Armor
|
||||
MarketItemDescription.Last = MarketItemDescription.Weight
|
||||
|
|
|
@ -1074,7 +1074,7 @@ bool Game::checkBotProtection()
|
|||
// accepts calls comming from a stacktrace containing only C++ functions,
|
||||
// if the stacktrace contains a lua function, then only accept if the engine is processing an input event
|
||||
if(m_denyBotCall && g_lua.isInCppCallback() && !g_app.isOnInputEvent()) {
|
||||
g_logger.error(g_lua.traceback("caught a lua call to a bot protected game function, the call was canceled"));
|
||||
g_logger.error(g_lua.traceback("caught a lua call to a bot protected game function, the call was cancelled"));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -274,7 +274,9 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.bindClassMemberFunction<Thing>("isHookSouth", &Thing::isHookSouth);
|
||||
g_lua.bindClassMemberFunction<Thing>("isTranslucent", &Thing::isTranslucent);
|
||||
g_lua.bindClassMemberFunction<Thing>("isFullGround", &Thing::isFullGround);
|
||||
g_lua.bindClassMemberFunction<Thing>("isMarketable", &Thing::isMarketable);
|
||||
g_lua.bindClassMemberFunction<Thing>("getParentContainer", &Thing::getParentContainer);
|
||||
g_lua.bindClassMemberFunction<Thing>("getMarketData", &Thing::getMarketData);
|
||||
|
||||
g_lua.registerClass<House>();
|
||||
g_lua.bindClassStaticFunction<House>("create", []{ return HousePtr(new House); });
|
||||
|
@ -334,6 +336,8 @@ void OTClient::registerLuaFunctions()
|
|||
g_lua.bindClassMemberFunction<Item>("getCount", &Item::getCount);
|
||||
g_lua.bindClassMemberFunction<Item>("getId", &Item::getId);
|
||||
g_lua.bindClassMemberFunction<Item>("isStackable", &Item::isStackable);
|
||||
g_lua.bindClassMemberFunction<Item>("isMarketable", &Item::isMarketable);
|
||||
g_lua.bindClassMemberFunction<Item>("getMarketData", &Item::isMarketable);
|
||||
|
||||
g_lua.registerClass<Effect, Thing>();
|
||||
g_lua.registerClass<Missile, Thing>();
|
||||
|
|
|
@ -97,3 +97,41 @@ bool luavalue_cast(int index, Position& pos)
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int push_luavalue(const MarketData& data)
|
||||
{
|
||||
g_lua.newTable();
|
||||
g_lua.pushInteger(data.category);
|
||||
g_lua.setField("category");
|
||||
g_lua.pushString(data.name);
|
||||
g_lua.setField("name");
|
||||
g_lua.pushInteger(data.requiredLevel);
|
||||
g_lua.setField("requiredLevel");
|
||||
g_lua.pushInteger(data.restrictProfession);
|
||||
g_lua.setField("restrictProfession");
|
||||
g_lua.pushInteger(data.showAs);
|
||||
g_lua.setField("showAs");
|
||||
g_lua.pushInteger(data.tradeAs);
|
||||
g_lua.setField("tradeAs");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool luavalue_cast(int index, MarketData& data)
|
||||
{
|
||||
if(g_lua.isTable(index)) {
|
||||
g_lua.getField("category", index);
|
||||
data.category = g_lua.popInteger();
|
||||
g_lua.getField("name", index);
|
||||
data.name = g_lua.popString();
|
||||
g_lua.getField("requiredLevel", index);
|
||||
data.requiredLevel = g_lua.popInteger();
|
||||
g_lua.getField("restrictProfession", index);
|
||||
data.restrictProfession = g_lua.popInteger();
|
||||
g_lua.getField("showAs", index);
|
||||
data.showAs = g_lua.popInteger();
|
||||
g_lua.getField("tradeAs", index);
|
||||
data.tradeAs = g_lua.popInteger();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,4 +36,8 @@ bool luavalue_cast(int index, Outfit& outfit);
|
|||
int push_luavalue(const Position& pos);
|
||||
bool luavalue_cast(int index, Position& pos);
|
||||
|
||||
// market
|
||||
int push_luavalue(const MarketData& data);
|
||||
bool luavalue_cast(int index, MarketData& data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -128,8 +128,10 @@ public:
|
|||
bool isFullGround() { return rawGetDatType()->isFullGround(); }
|
||||
bool isIgnoreLook() { return rawGetDatType()->isIgnoreLook(); }
|
||||
bool isCloth() { return rawGetDatType()->isCloth(); }
|
||||
bool isMarketable() { return rawGetDatType()->isMarketable(); }
|
||||
MarketData getMarketData() { return rawGetDatType()->getMarketData(); }
|
||||
|
||||
|
||||
protected:
|
||||
Position m_position;
|
||||
uint16 m_datId;
|
||||
|
|
|
@ -172,6 +172,7 @@ public:
|
|||
bool isFullGround() { return m_attribs.has(DatAttribFullGround); }
|
||||
bool isIgnoreLook() { return m_attribs.has(DatAttribIgnoreLook); }
|
||||
bool isCloth() { return m_attribs.has(DatAttribCloth); }
|
||||
bool isMarketable() { return m_attribs.has(DatAttribMarket); }
|
||||
|
||||
private:
|
||||
const TexturePtr& getTexture(int animationPhase);
|
||||
|
|
|
@ -48,8 +48,8 @@ public:
|
|||
|
||||
const ThingTypeDatPtr& getDatType(uint16 id, DatCategory category);
|
||||
const ThingTypeOtbPtr& getOtbType(uint16 id);
|
||||
ThingTypeDat *rawGetDatType(uint16 id, DatCategory category) { return m_datTypes[category][id].get(); }
|
||||
ThingTypeOtb *rawGetOtbType(uint16 id) { return m_otbTypes[id].get(); }
|
||||
ThingTypeDat* rawGetDatType(uint16 id, DatCategory category) { return m_datTypes[category][id].get(); }
|
||||
ThingTypeOtb* rawGetOtbType(uint16 id) { return m_otbTypes[id].get(); }
|
||||
|
||||
uint32 getDatSignature() { return m_datSignature; }
|
||||
uint32 getOtbMajorVersion() { return m_otbMajorVersion; }
|
||||
|
|
Loading…
Reference in New Issue