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:
BeniS 2012-07-20 06:54:24 +12:00
parent 9dc88de6b0
commit 6293a49f8f
34 changed files with 744 additions and 99 deletions

View File

@ -146,7 +146,7 @@ function ModuleManager.unloadCurrentModule()
end
function ModuleManager.reloadAllModules()
g_modules.g_modules.reloadModules()
g_modules.reloadModules()
ModuleManager.refreshLoadedModules()
ModuleManager.show()
end

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>();

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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; }