modules changes

* speedup widget destruction checks
* rework outfit module using grid layout and the new design
* fixes in console, terminal, textmessage modules
This commit is contained in:
Eduardo Bart 2012-03-22 18:47:52 -03:00
parent 159eb98df2
commit 33458a3e39
41 changed files with 335 additions and 234 deletions

View File

@ -10,6 +10,7 @@ function Background.init()
local clientVersionLabel = background:getChildById('clientVersionLabel') local clientVersionLabel = background:getChildById('clientVersionLabel')
clientVersionLabel:setText('OTClient ' .. g_app.getVersion() .. '\n' .. clientVersionLabel:setText('OTClient ' .. g_app.getVersion() .. '\n' ..
'Rev ' .. g_app.getBuildRevision() .. '\n' ..
'Built on ' .. g_app.getBuildDate()) 'Built on ' .. g_app.getBuildDate())
if not g_game.isOnline() then if not g_game.isOnline() then

View File

@ -15,8 +15,8 @@ Panel
background-color: #00000099 background-color: #00000099
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
text-offset: 4 2 text-align: center
height: 32 height: 48
width: 120 width: 120
color: #ffffff color: #ffffff
font: verdana-11px-monochrome font: verdana-11px-monochrome

View File

@ -2,12 +2,11 @@ TerminalLabel < UILabel
font: terminus-14px-bold font: terminus-14px-bold
height: 16 height: 16
Panel UIWidget
id: terminalPanel id: terminalWidget
background-color: #000000 background-color: #000000
opacity: 0.85 opacity: 0.85
anchors.fill: parent anchors.fill: parent
@onEscape: Terminal.hide()
Panel Panel
id: terminalBuffer id: terminalBuffer

View File

@ -2,16 +2,16 @@ UIComboBox = extends(UIWidget)
function UIComboBox.create() function UIComboBox.create()
local combobox = UIComboBox.internalCreate() local combobox = UIComboBox.internalCreate()
combobox.m_options = {} combobox.options = {}
combobox.m_currentIndex = -1 combobox.currentIndex = -1
return combobox return combobox
end end
function UIComboBox:setCurrentOption(text) function UIComboBox:setCurrentOption(text)
if not self.m_options then return end if not self.options then return end
for i,v in ipairs(self.m_options) do for i,v in ipairs(self.options) do
if v.text == text and self.m_currentIndex ~= i then if v.text == text and self.currentIndex ~= i then
self.m_currentIndex = i self.currentIndex = i
self:setText(text) self:setText(text)
self:onOptionChange(text, v.data) self:onOptionChange(text, v.data)
return return
@ -20,24 +20,24 @@ function UIComboBox:setCurrentOption(text)
end end
function UIComboBox:setCurrentIndex(index) function UIComboBox:setCurrentIndex(index)
if index >= 1 and index <= #self.m_options then if index >= 1 and index <= #self.options then
local v = self.m_options[index] local v = self.options[index]
self.m_currentIndex = index self.currentIndex = index
self:setText(v.text) self:setText(v.text)
self:onOptionChange(v.text, v.data) self:onOptionChange(v.text, v.data)
end end
end end
function UIComboBox:addOption(text, data) function UIComboBox:addOption(text, data)
table.insert(self.m_options, { text = text, data = data }) table.insert(self.options, { text = text, data = data })
local index = #self.m_options local index = #self.options
if index == 1 then self:setCurrentOption(text) end if index == 1 then self:setCurrentOption(text) end
return index return index
end end
function UIComboBox:onMousePress(mousePos, mouseButton) function UIComboBox:onMousePress(mousePos, mouseButton)
local menu = createWidget(self:getStyleName() .. 'PopupMenu', self) local menu = createWidget(self:getStyleName() .. 'PopupMenu', self)
for i,v in ipairs(self.m_options) do for i,v in ipairs(self.options) do
menu:addOption(v.text, function() self:setCurrentOption(v.text) end) menu:addOption(v.text, function() self:setCurrentOption(v.text) end)
end end
menu:setWidth(self:getWidth()) menu:setWidth(self:getWidth())
@ -48,10 +48,10 @@ function UIComboBox:onMousePress(mousePos, mouseButton)
end end
function UIComboBox:onMouseWheel(mousePos, direction) function UIComboBox:onMouseWheel(mousePos, direction)
if direction == MouseWheelUp and self.m_currentIndex > 1 then if direction == MouseWheelUp and self.currentIndex > 1 then
self:setCurrentIndex(self.m_currentIndex - 1) self:setCurrentIndex(self.currentIndex - 1)
elseif direction == MouseWheelDown and self.m_currentIndex < #self.m_options then elseif direction == MouseWheelDown and self.currentIndex < #self.options then
self:setCurrentIndex(self.m_currentIndex + 1) self:setCurrentIndex(self.currentIndex + 1)
end end
return true return true
end end

View File

@ -4,23 +4,23 @@ function UIProgressBar.create()
local progressbar = UIProgressBar.internalCreate() local progressbar = UIProgressBar.internalCreate()
progressbar:setFocusable(false) progressbar:setFocusable(false)
progressbar:setPhantom(true) progressbar:setPhantom(true)
progressbar.m_percent = 0 progressbar.percent = 0
progressbar:updateBackground() progressbar:updateBackground()
return progressbar return progressbar
end end
function UIProgressBar:setPercent(percent) function UIProgressBar:setPercent(percent)
self.m_percent = math.max(math.min(percent, 100), 0) self.percent = math.max(math.min(percent, 100), 0)
self:updateBackground() self:updateBackground()
end end
function UIProgressBar:getPercent() function UIProgressBar:getPercent()
return self.m_percent return self.percent
end end
function UIProgressBar:updateBackground() function UIProgressBar:updateBackground()
local width = math.max((self.m_percent * self:getWidth())/100, 1) local width = math.max((self.percent * self:getWidth())/100, 1)
local height = self:getHeight() local height = self:getHeight()
self:setBackgroundSize({width=width, height=height}) self:setBackgroundSize({width=width, height=height})
end end

View File

@ -3,54 +3,54 @@ UISpinBox = extends(UILineEdit)
function UISpinBox.create() function UISpinBox.create()
local spinbox = UISpinBox.internalCreate() local spinbox = UISpinBox.internalCreate()
spinbox:setValidCharacters('0123456789') spinbox:setValidCharacters('0123456789')
spinbox.m_minimum = 0 spinbox.minimum = 0
spinbox.m_maximum = 0 spinbox.maximum = 0
spinbox:setCurrentIndex(0) spinbox:setCurrentIndex(0)
spinbox:setText("0") spinbox:setText("0")
return spinbox return spinbox
end end
function UISpinBox:setCurrentIndex(index) function UISpinBox:setCurrentIndex(index)
if index >= self.m_minimum and index <= self.m_maximum then if index >= self.minimum and index <= self.maximum then
if self:getText():len() > 0 then if self:getText():len() > 0 then
self:setText(index) self:setText(index)
end end
self.m_currentIndex = index self.currentIndex = index
self:onIndexChange(index) self:onIndexChange(index)
end end
end end
function UISpinBox:setMinimum(minimum) function UISpinBox:setMinimum(minimum)
if minimum > self.m_maximum then if minimum > self.maximum then
print("[UISpinBox:setMinimum]: minimum value cant be greater than maximum") print("[UISpinBox:setMinimum]: minimum value cant be greater than maximum")
return false return false
end end
if self.m_currentIndex < minimum then if self.currentIndex < minimum then
self:setCurrentIndex(minimum) self:setCurrentIndex(minimum)
end end
self.m_minimum = minimum self.minimum = minimum
end end
function UISpinBox:setMaximum(maximum) function UISpinBox:setMaximum(maximum)
if maximum < self.m_minimum then if maximum < self.minimum then
print("[UISpinBox:setMaximum]: maximum value cant be lower than minimum") print("[UISpinBox:setMaximum]: maximum value cant be lower than minimum")
return false return false
end end
if self.m_currentIndex > maximum then if self.currentIndex > maximum then
self:setCurrentIndex(maximum) self:setCurrentIndex(maximum)
end end
self.m_maximum = maximum self.maximum = maximum
end end
function UISpinBox:getCurrentIndex() function UISpinBox:getCurrentIndex()
return self.m_currentIndex return self.currentIndex
end end
function UISpinBox:onMouseWheel(mousePos, direction) function UISpinBox:onMouseWheel(mousePos, direction)
if direction == MouseWheelUp then if direction == MouseWheelUp then
self:setCurrentIndex(self.m_currentIndex + 1) self:setCurrentIndex(self.currentIndex + 1)
elseif direction == MouseWheelDown then elseif direction == MouseWheelDown then
self:setCurrentIndex(self.m_currentIndex - 1) self:setCurrentIndex(self.currentIndex - 1)
end end
return true return true
end end
@ -58,12 +58,12 @@ end
function UISpinBox:onTextChange(text, oldText) function UISpinBox:onTextChange(text, oldText)
if text:len() == 0 then if text:len() == 0 then
self:setCurrentIndex(self.m_minimum) self:setCurrentIndex(self.minimum)
return return
end end
local number = tonumber(text) local number = tonumber(text)
if not number or number > self.m_maximum or number < self.m_minimum then if not number or number > self.maximum or number < self.minimum then
self:setText(oldText) self:setText(oldText)
return return
end end

View File

@ -13,6 +13,13 @@ Module
load-later: load-later:
- game_textmessage - game_textmessage
- game_console - game_console
- game_outfit
//- game_healthbar
//- game_inventory
//- game_combatcontrols
//- game_skills
//- game_viplist
//- game_hotkeys
@onLoad: | @onLoad: |
importStyle 'styles/items.otui' importStyle 'styles/items.otui'

View File

@ -211,7 +211,7 @@ function GameInterface.processMouseAction(menuPosition, mouseButton, autoWalk, l
return true return true
end end
if not Options.classicControl then if not Options['classicControl'] then
if keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton then if keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton then
GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatureThing) GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatureThing)
return true return true

View File

@ -26,7 +26,7 @@ UIWidget
GameSidePanel GameSidePanel
id: gameLeftPanel id: gameLeftPanel
width: 190 width: 0
layout: verticalBox layout: verticalBox
anchors.left: parent.left anchors.left: parent.left
anchors.top: parent.top anchors.top: parent.top

View File

@ -36,7 +36,7 @@ table.insert(lifeBarColors, {percentAbove = -1, color = '#4F0000' } )
-- public functions -- public functions
function Battle.create() function Battle.create()
battleWindow = displayUI('battle.otui', g_game.gameRightPanel) battleWindow = displayUI('battle.otui', GameInterface.getRightPanel())
battleWindow:hide() battleWindow:hide()
battleButton = TopMenu.addGameButton('battleButton', 'Battle (Ctrl+B)', '/game_battle/battle.png', Battle.toggle) battleButton = TopMenu.addGameButton('battleButton', 'Battle (Ctrl+B)', '/game_battle/battle.png', Battle.toggle)
Keyboard.bindKeyDown('Ctrl+B', Battle.toggle) Keyboard.bindKeyDown('Ctrl+B', Battle.toggle)

View File

@ -3,5 +3,6 @@ Module
description: Manage battle window description: Manage battle window
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: |
@onLoad: |
dofile 'battle' dofile 'battle'

View File

@ -50,7 +50,7 @@ end
function CombatControls.init() function CombatControls.init()
combatControlsButton = TopMenu.addGameButton('combatControlsButton', 'Combat Controls', 'combatcontrols.png', CombatControls.toggle) combatControlsButton = TopMenu.addGameButton('combatControlsButton', 'Combat Controls', 'combatcontrols.png', CombatControls.toggle)
combatControlsButton:setOn(true) combatControlsButton:setOn(true)
combatControlsWindow = loadUI('combatcontrols.otui') combatControlsWindow = loadUI('combatcontrols.otui', GameInterface.getRightPanel())
fightOffensiveBox = combatControlsWindow:getChildById('fightOffensiveBox') fightOffensiveBox = combatControlsWindow:getChildById('fightOffensiveBox')
fightBalancedBox = combatControlsWindow:getChildById('fightBalancedBox') fightBalancedBox = combatControlsWindow:getChildById('fightBalancedBox')
@ -101,7 +101,6 @@ function CombatControls.terminate()
end end
function CombatControls.online() function CombatControls.online()
g_game.gameRightPanel:addChild(combatControlsWindow)
combatControlsWindow:setVisible(combatControlsButton:isOn()) combatControlsWindow:setVisible(combatControlsButton:isOn())
local fightMode = g_game.getFightMode() local fightMode = g_game.getFightMode()
@ -121,7 +120,6 @@ function CombatControls.online()
end end
function CombatControls.offline() function CombatControls.offline()
g_game.gameRightPanel:removeChild(combatControlsWindow)
end end
function CombatControls.toggle() function CombatControls.toggle()

View File

@ -4,9 +4,9 @@ Module
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: | @onLoad: |
dofile 'combatcontrols' dofile 'combatcontrols'
CombatControls.init() CombatControls.init()
onUnload: | @onUnload: |
CombatControls.terminate() CombatControls.terminate()

View File

@ -50,6 +50,7 @@ local channels
local messageHistory = { } local messageHistory = { }
local currentMessageIndex = 0 local currentMessageIndex = 0
local MaxHistory = 1000 local MaxHistory = 1000
local channelsWindow
-- private functions -- private functions
local function navigateMessageHistory(step) local function navigateMessageHistory(step)
@ -67,7 +68,7 @@ end
function applyMessagePrefixies(name, level, message) function applyMessagePrefixies(name, level, message)
if name then if name then
if Options.showLevelsInConsole and level > 0 then if Options.getOption('showLevelsInConsole') and level > 0 then
message = name .. ' [' .. level .. ']: ' .. message message = name .. ' [' .. level .. ']: ' .. message
else else
message = name .. ': ' .. message message = name .. ': ' .. message
@ -109,7 +110,7 @@ local function onOpenPrivateChannel(receiver)
end end
end end
local function doChannelListSubmit(channelsWindow) local function doChannelListSubmit()
local channelListPanel = channelsWindow:getChildById('channelList') local channelListPanel = channelsWindow:getChildById('channelList')
local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText() local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText()
if openPrivateChannelWith ~= '' then if openPrivateChannelWith ~= '' then
@ -119,13 +120,16 @@ local function doChannelListSubmit(channelsWindow)
if not selectedChannelLabel then return end if not selectedChannelLabel then return end
g_game.joinChannel(selectedChannelLabel.channelId) g_game.joinChannel(selectedChannelLabel.channelId)
end end
channelsWindow:destroy() channelsWindow:destroy()
end end
local function onChannelList(channelList) local function onChannelList(channelList)
local channelsWindow = displayUI('channelswindow.otui') if channelsWindow then channelsWindow:destroy() end
channelsWindow = displayUI('channelswindow.otui')
local channelListPanel = channelsWindow:getChildById('channelList') local channelListPanel = channelsWindow:getChildById('channelList')
channelsWindow.onEnter = function() doChannelListSubmit(channelsWindow) end channelsWindow.onEnter = doChannelListSubmit
channelsWindow.onDestroy = function() channelsWindow = nil end
Keyboard.bindKeyPress('Down', function() channelListPanel:focusNextChild(KeyboardFocusReason) end, channelsWindow) Keyboard.bindKeyPress('Down', function() channelListPanel:focusNextChild(KeyboardFocusReason) end, channelsWindow)
Keyboard.bindKeyPress('Up', function() channelListPanel:focusPreviousChild(KeyboardFocusReason) end, channelsWindow) Keyboard.bindKeyPress('Up', function() channelListPanel:focusPreviousChild(KeyboardFocusReason) end, channelsWindow)
@ -139,7 +143,7 @@ local function onChannelList(channelList)
label:setText(channelName) label:setText(channelName)
label:setPhantom(false) label:setPhantom(false)
label.onDoubleClick = function() doChannelListSubmit(channelsWindow) end label.onDoubleClick = doChannelListSubmit
end end
end end
end end
@ -150,7 +154,8 @@ function Console.init()
connect(g_game, { onCreatureSpeak = onCreatureSpeak, connect(g_game, { onCreatureSpeak = onCreatureSpeak,
onChannelList = onChannelList, onChannelList = onChannelList,
onOpenChannel = onOpenChannel, onOpenChannel = onOpenChannel,
onOpenPrivateChannel = onOpenPrivateChannel}) onOpenPrivateChannel = onOpenPrivateChannel,
onGameEnd = Console.clean })
consolePanel = displayUI('console.otui', GameInterface.getBottomPanel()) consolePanel = displayUI('console.otui', GameInterface.getBottomPanel())
consoleLineEdit = consolePanel:getChildById('consoleLineEdit') consoleLineEdit = consolePanel:getChildById('consoleLineEdit')
@ -182,15 +187,24 @@ function Console.terminate()
disconnect(g_game, { onCreatureSpeak = onCreatureSpeak, disconnect(g_game, { onCreatureSpeak = onCreatureSpeak,
onChannelList = onChannelList, onChannelList = onChannelList,
onOpenChannel = onOpenChannel, onOpenChannel = onOpenChannel,
onOpenPrivateChannel = onOpenPrivateChannel }) onOpenPrivateChannel = onOpenPrivateChannel,
onGameEnd = Console.clean })
for channelid, channelname in ipairs(channels) do for channelid, channelname in pairs(channels) do
if channelid ~= 0 then
g_game.leaveChannel(channelid) g_game.leaveChannel(channelid)
end end
end
channels = {}
Keyboard.unbindKeyDown('Ctrl+O') Keyboard.unbindKeyDown('Ctrl+O')
Keyboard.unbindKeyDown('Ctrl+E') Keyboard.unbindKeyDown('Ctrl+E')
if channelsWindow then
channelsWindow:destroy()
channelsWindow = nil
end
consolePanel:destroy() consolePanel:destroy()
consolePanel = nil consolePanel = nil
consoleLineEdit = nil consoleLineEdit = nil
@ -200,6 +214,28 @@ function Console.terminate()
Console = nil Console = nil
end end
function Console.debug()
print(#channels)
end
function Console.clean()
for channelid, channelname in pairs(channels) do
if channelid ~= 0 then
local tab = consoleTabBar:getTab(channelname)
consoleTabBar:removeTab(tab)
end
end
channels = {}
consoleTabBar:getTab('Default').tabPanel:destroyChildren()
consoleTabBar:getTab('Server Log').tabPanel:destroyChildren()
if channelsWindow then
channelsWindow:destroy()
channelsWindow = nil
end
end
function Console.setLineEditText(text) function Console.setLineEditText(text)
consoleLineEdit:setText(text) consoleLineEdit:setText(text)
end end
@ -260,7 +296,7 @@ function Console.addPrivateText(text, speaktype, name, isPrivateCommand)
local privateTab = Console.getTab(name) local privateTab = Console.getTab(name)
if privateTab == nil then if privateTab == nil then
if Options.showPrivateMessagesInConsole or (isPrivateCommand and not privateTab) then if Options['showPrivateMessagesInConsole'] or (isPrivateCommand and not privateTab) then
privateTab = Console.getTab('Default') privateTab = Console.getTab('Default')
else else
privateTab = Console.addTab(name, focus) privateTab = Console.addTab(name, focus)
@ -280,7 +316,7 @@ function Console.addText(text, speaktype, tabName)
end end
function Console.addTabText(text, speaktype, tab) function Console.addTabText(text, speaktype, tab)
if Options.showTimestampsInConsole then if Options['showTimestampsInConsole'] then
text = os.date('%H:%M') .. ' ' .. text text = os.date('%H:%M') .. ' ' .. text
end end

View File

@ -1,16 +1,16 @@
Containers = {} Containers = {}
-- private variables -- private variables
local m_containers = {} local containers = {}
-- public functions -- public functions
function Containers.clean() function Containers.clean()
m_containers = {} containers = {}
end end
function Containers.getFreeContainerId() function Containers.getFreeContainerId()
for i=0,15 do for i=0,15 do
if not m_containers[i] then if not containers[i] then
return i return i
end end
end end
@ -19,12 +19,12 @@ end
-- hooked events -- hooked events
function Containers.onOpenContainer(containerId, itemId, name, capacity, hasParent, items) function Containers.onOpenContainer(containerId, itemId, name, capacity, hasParent, items)
local container = m_containers[containerId] local container = containers[containerId]
if container then if container then
g_game.gameRightPanel:removeChild(container) GameInterface.getRightPanel():removeChild(container)
end end
container = displayUI('container.otui', g_game.gameRightPanel) container = displayUI('container.otui', GameInterface.getRightPanel())
name = name:sub(1,1):upper() .. name:sub(2) name = name:sub(1,1):upper() .. name:sub(2)
container:setText(name) container:setText(name)
@ -51,19 +51,19 @@ function Containers.onOpenContainer(containerId, itemId, name, capacity, hasPare
end end
end end
m_containers[containerId] = container containers[containerId] = container
end end
function Containers.onCloseContainer(containerId) function Containers.onCloseContainer(containerId)
local container = m_containers[containerId] local container = containers[containerId]
if container then if container then
g_game.gameRightPanel:removeChild(container) GameInterface.getRightPanel():removeChild(container)
end end
m_containers[containerId] = nil containers[containerId] = nil
end end
function Containers.onContainerAddItem(containerId, item) function Containers.onContainerAddItem(containerId, item)
local container = m_containers[containerId] local container = containers[containerId]
if not container or not item or container.itemCount >= container.capacity then return end if not container or not item or container.itemCount >= container.capacity then return end
local i = container.itemCount local i = container.itemCount
@ -92,7 +92,7 @@ function Containers.onContainerAddItem(containerId, item)
end end
function Containers.onContainerUpdateItem(containerId, slot, item) function Containers.onContainerUpdateItem(containerId, slot, item)
local container = m_containers[containerId] local container = containers[containerId]
if not container then return end if not container then return end
local itemWidget = container:getChildByIndex(slot + 1) local itemWidget = container:getChildByIndex(slot + 1)
@ -102,7 +102,7 @@ function Containers.onContainerUpdateItem(containerId, slot, item)
end end
function Containers.onContainerRemoveItem(containerId, slot) function Containers.onContainerRemoveItem(containerId, slot)
local container = m_containers[containerId] local container = containers[containerId]
if not container then return end if not container then return end
local itemWidget = container:getChildByIndex(slot+1) local itemWidget = container:getChildByIndex(slot+1)

View File

@ -3,5 +3,6 @@ Module
description: Manage containers description: Manage containers
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: |
@onLoad: |
dofile 'containers' dofile 'containers'

View File

@ -9,7 +9,7 @@ local manaLabel
-- public functions -- public functions
function HealthBar.create() function HealthBar.create()
healthBarWindow = displayUI('healthbar.otui', g_game.gameRightPanel) healthBarWindow = displayUI('healthbar.otui', GameInterface.getRightPanel())
healthBarButton = TopMenu.addGameButton('healthBarButton', 'Healh Bar', 'healthbar.png', HealthBar.toggle) healthBarButton = TopMenu.addGameButton('healthBarButton', 'Healh Bar', 'healthbar.png', HealthBar.toggle)
healthBarButton:setOn(true) healthBarButton:setOn(true)
healthBar = healthBarWindow:getChildById('healthBar') healthBar = healthBarWindow:getChildById('healthBar')

View File

@ -3,5 +3,6 @@ Module
description: Displays health and mana points description: Displays health and mana points
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: |
@onLoad: |
dofile 'healthbar' dofile 'healthbar'

View File

@ -37,7 +37,7 @@ function HotkeysManager.init()
hotkeysWindow = displayUI('hotkeys_manager.otui') hotkeysWindow = displayUI('hotkeys_manager.otui')
hotkeysWindow:setVisible(false) hotkeysWindow:setVisible(false)
hotkeysButton = TopMenu.addButton('hotkeysButton', 'Hotkeys (Ctrl+K)', '/game_hotkeys/icon.png', HotkeysManager.toggle) hotkeysButton = TopMenu.addLeftButton('hotkeysButton', 'Hotkeys (Ctrl+K)', '/game_hotkeys/icon.png', HotkeysManager.toggle)
Keyboard.bindKeyDown('Ctrl+K', HotkeysManager.toggle) Keyboard.bindKeyDown('Ctrl+K', HotkeysManager.toggle)
currentHotkeysList = hotkeysWindow:getChildById('currentHotkeys') currentHotkeysList = hotkeysWindow:getChildById('currentHotkeys')

View File

@ -5,11 +5,11 @@ Module
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
dependencies: dependencies:
- client_tibiafiles - game
onLoad: | @onLoad: |
dofile 'hotkeys_manager' dofile 'hotkeys_manager'
HotkeysManager.init() HotkeysManager.init()
onUnload: | @onUnload: |
HotkeysManager.terminate() HotkeysManager.terminate()

View File

@ -7,7 +7,7 @@ Module
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: | @onLoad: |
dofile 'uiminiwindow' dofile 'uiminiwindow'
dofile 'uiminiwindowcontainer' dofile 'uiminiwindowcontainer'
dofile 'uiitem' dofile 'uiitem'
@ -16,5 +16,5 @@ Module
GameInterface.init() GameInterface.init()
onUnload: | @onUnload: |
GameInterface.terminate() GameInterface.terminate()

View File

@ -6,7 +6,7 @@ local inventoryButton
-- public functions -- public functions
function Inventory.create() function Inventory.create()
inventoryWindow = displayUI('inventory.otui', g_game.gameRightPanel) inventoryWindow = displayUI('inventory.otui', GameInterface.getRightPanel())
inventoryButton = TopMenu.addGameButton('inventoryButton', 'Inventory (Ctrl+I)', 'inventory.png', Inventory.toggle) inventoryButton = TopMenu.addGameButton('inventoryButton', 'Inventory (Ctrl+I)', 'inventory.png', Inventory.toggle)
inventoryButton:setOn(true) inventoryButton:setOn(true)
Keyboard.bindKeyDown('Ctrl+I', Inventory.toggle) Keyboard.bindKeyDown('Ctrl+I', Inventory.toggle)

View File

@ -3,5 +3,6 @@ Module
description: View local player equipments window description: View local player equipments window
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: |
@onLoad: |
dofile 'inventory' dofile 'inventory'

View File

@ -1,84 +1,84 @@
Outfit = {} Outfit = {}
-- private variables -- private variables
local window = nil local outfitWindow
local m_creature = nil local outfitCreature
local m_outfit = nil local outfit
local m_outfits = nil local outfits
local m_currentOutfit = 1 local currentOutfit = 1
local m_currentColor = nil local currentColorBox
local m_currentClothe = nil local currentClotheButtonBox
-- private functions -- private functions
local function onAddonCheckChange(addon, value) local function onAddonCheckChange(addon, value)
if addon:isChecked() then if addon:isChecked() then
m_outfit.addons = m_outfit.addons + value outfit.addons = outfit.addons + value
else else
m_outfit.addons = m_outfit.addons - value outfit.addons = outfit.addons - value
end end
m_creature:setOutfit(m_outfit) outfitCreature:setOutfit(outfit)
end end
local function onColorCheckChange(color) local function onColorCheckChange(colorBox)
if color == m_currentColor then if colorBox == currentColorBox then
color.onCheckChange = nil colorBox.onCheckChange = nil
color:setChecked(true) colorBox:setChecked(true)
color.onCheckChange = onColorCheckChange colorBox.onCheckChange = onColorCheckChange
else else
m_currentColor.onCheckChange = nil currentColorBox.onCheckChange = nil
m_currentColor:setChecked(false) currentColorBox:setChecked(false)
m_currentColor.onCheckChange = onColorCheckChange currentColorBox.onCheckChange = onColorCheckChange
m_currentColor = color currentColorBox = colorBox
if m_currentClothe:getId() == 'head' then if currentClotheButtonBox:getId() == 'head' then
m_outfit.head = m_currentColor.colorId outfit.head = currentColorBox.colorId
elseif m_currentClothe:getId() == 'primary' then elseif currentClotheButtonBox:getId() == 'primary' then
m_outfit.body = m_currentColor.colorId outfit.body = currentColorBox.colorId
elseif m_currentClothe:getId() == 'secondary' then elseif currentClotheButtonBox:getId() == 'secondary' then
m_outfit.legs = m_currentColor.colorId outfit.legs = currentColorBox.colorId
elseif m_currentClothe:getId() == 'detail' then elseif currentClotheButtonBox:getId() == 'detail' then
m_outfit.feet = m_currentColor.colorId outfit.feet = currentColorBox.colorId
end end
m_creature:setOutfit(m_outfit) outfitCreature:setOutfit(outfit)
end end
end end
local function onClotheCheckChange(clothe) local function onClotheCheckChange(clotheButtonBox)
if clothe == m_currentClothe then if clotheButtonBox == currentClotheButtonBox then
clothe.onCheckChange = nil clotheButtonBox.onCheckChange = nil
clothe:setChecked(true) clotheButtonBox:setChecked(true)
clothe.onCheckChange = onClotheCheckChange clotheButtonBox.onCheckChange = onClotheCheckChange
else else
m_currentClothe.onCheckChange = nil currentClotheButtonBox.onCheckChange = nil
m_currentClothe:setChecked(false) currentClotheButtonBox:setChecked(false)
m_currentClothe.onCheckChange = onClotheCheckChange currentClotheButtonBox.onCheckChange = onClotheCheckChange
m_currentClothe = clothe currentClotheButtonBox = clotheButtonBox
local color = 0 local colorId = 0
if m_currentClothe:getId() == 'head' then if currentClotheButtonBox:getId() == 'head' then
color = m_outfit.head colorId = outfit.head
elseif m_currentClothe:getId() == 'primary' then elseif currentClotheButtonBox:getId() == 'primary' then
color = m_outfit.body colorId = outfit.body
elseif m_currentClothe:getId() == 'secondary' then elseif currentClotheButtonBox:getId() == 'secondary' then
color = m_outfit.legs colorId = outfit.legs
elseif m_currentClothe:getId() == 'detail' then elseif currentClotheButtonBox:getId() == 'detail' then
color = m_outfit.feet colorId = outfit.feet
end end
window:getChildById('color' .. color):setChecked(true) outfitWindow:recursiveGetChildById('colorBox' .. colorId):setChecked(true)
end end
end end
local function update() local function update()
local nameWidget = window:getChildById('name') local nameWidget = outfitWindow:getChildById('outfitName')
nameWidget:setText(m_outfits[m_currentOutfit][2]) nameWidget:setText(outfits[currentOutfit][2])
local availableAddons = m_outfits[m_currentOutfit][3] local availableAddons = outfits[currentOutfit][3]
local addon1 = window:getChildById('addon1') local addon1 = outfitWindow:getChildById('addon1')
local addon2 = window:getChildById('addon2') local addon2 = outfitWindow:getChildById('addon2')
local addon3 = window:getChildById('addon3') local addon3 = outfitWindow:getChildById('addon3')
addon1:setChecked(false) addon1:setChecked(false)
addon2:setChecked(false) addon2:setChecked(false)
addon3:setChecked(false) addon3:setChecked(false)
@ -111,55 +111,63 @@ local function update()
addon3:setEnabled(true) addon3:setEnabled(true)
end end
m_outfit.type = m_outfits[m_currentOutfit][1] outfit.type = outfits[currentOutfit][1]
m_outfit.addons = 0 outfit.addons = 0
m_creature:setOutfit(m_outfit) outfitCreature:setOutfit(outfit)
end end
-- public functions -- public functions
function Outfit.create(creature, outfitList) function Outfit.init()
connect(g_game, { onOpenOutfitWindow = Outfit.create,
onGameEnd = Outfit.destroy })
end
function Outfit.terminate()
disconnect(g_game, { onOpenOutfitWindow = Outfit.create,
onGameEnd = Outfit.destroy })
Outfit.destroy() Outfit.destroy()
window = displayUI('outfit.otui') end
window:lock()
m_outfit = creature:getOutfit() function Outfit.create(creature, outfitList)
outfitCreature = creature
outfits = outfitList
Outfit.destroy()
m_currentClothe = window:getChildById('head') outfitWindow = displayUI('outfit.otui')
window:getChildById('head').onCheckChange = onClotheCheckChange --outfitWindow:lock()
window:getChildById('primary').onCheckChange = onClotheCheckChange
window:getChildById('secondary').onCheckChange = onClotheCheckChange
window:getChildById('detail').onCheckChange = onClotheCheckChange
local creatureWidget = window:getChildById('creature') outfit = outfitCreature:getOutfit()
creatureWidget:setCreature(creature)
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)
for i=0,18 do
for j=0,6 do for j=0,6 do
local color = createWidget('Color', window) for i=0,18 do
local colorBox = createWidget('ColorBox', colorBoxPanel)
local outfitColor = getOufitColor(j*19 + i) local outfitColor = getOufitColor(j*19 + i)
color:setId('color' .. j*19+i) colorBox:setImageColor(outfitColor)
color.colorId = j*19 + i colorBox:setId('colorBox' .. j*19+i)
color:setImageColor(outfitColor) colorBox.colorId = j*19 + i
color:setMarginTop(j * 3 + j * 14)
color:setMarginLeft(10 + i * 3 + i * 14)
if j*19 + i == m_outfit.head then if j*19 + i == outfit.head then
m_currentColor = color currentColorBox = colorBox
color:setChecked(true) colorBox:setChecked(true)
end end
colorBox.onCheckChange = onColorCheckChange
color.onCheckChange = onColorCheckChange
end end
end end
m_creature = creature currentOutfit = 1
m_outfits = outfitList
m_currentOutfit = 1
for i=1,#outfitList do for i=1,#outfitList do
if outfitList[i][1] == m_outfit.type then if outfitList[i][1] == outfit.type then
m_currentOutfit = i currentOutfit = i
break break
end end
end end
@ -168,35 +176,33 @@ function Outfit.create(creature, outfitList)
end end
function Outfit.destroy() function Outfit.destroy()
if window ~= nil then if outfitWindow then
window:destroy() outfitWindow:destroy()
window = nil outfitWindow = nil
outfitCreature = nil
currentColorBox = nil
currentClotheButtonBox = nil
end end
end end
function Outfit.accept() function Outfit.accept()
g_game.changeOutfit(m_outfit) g_game.changeOutfit(outfit)
Outfit.destroy() Outfit.destroy()
end end
function Outfit.nextType() function Outfit.nextType()
m_currentOutfit = m_currentOutfit + 1 currentOutfit = currentOutfit + 1
if m_currentOutfit > #m_outfits then if currentOutfit > #outfits then
m_currentOutfit = 1 currentOutfit = 1
end end
update() update()
end end
function Outfit.previousType() function Outfit.previousType()
m_currentOutfit = m_currentOutfit - 1 currentOutfit = currentOutfit - 1
if m_currentOutfit <= 0 then if currentOutfit <= 0 then
m_currentOutfit = #m_outfits currentOutfit = #outfits
end end
update() update()
end end
-- hooked events
connect(g_game, { onOpenOutfitWindow = Outfit.create,
onGameEnd = Outfit.destroy })

View File

@ -3,5 +3,11 @@ Module
description: Change local player outfit description: Change local player outfit
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: | reloadable: true
@onLoad: |
dofile 'outfit' dofile 'outfit'
Outfit.init()
@onUnload: |
Outfit.terminate()

View File

@ -1,7 +1,3 @@
Color < ColorBox
anchors.top: head.top
anchors.left: head.right
Window Window
text: Select Outfit text: Select Outfit
size: 550 280 size: 550 280
@ -14,7 +10,7 @@ Window
@onEscape: Outfit.destroy() @onEscape: Outfit.destroy()
Label Label
id: name id: outfitName
text: Outfit Name text: Outfit Name
width: 100 width: 100
anchors.top: parent.top anchors.top: parent.top
@ -23,60 +19,81 @@ Window
margin-left: 20 margin-left: 20
Creature Creature
id: creature id: outfitCreatureBox
anchors.top: name.bottom anchors.top: outfitName.bottom
anchors.left: name.left anchors.left: outfitName.left
margin-top: 5 margin-top: 5
padding: 16 4 4 16 padding: 16 4 4 16
fixed-creature-size: true fixed-creature-size: true
Panel
id: colorBoxPanel
anchors.top: parent.top
anchors.right: parent.right
margin-top: 54
margin-right: 20
width: 323
height: 119
layout:
type: grid
cell-size: 16 16
cell-spacing: 2
num-columns: 19
num-lines: 7
ButtonBox ButtonBox
id: head id: head
text: Head text: Head
anchors.top: creature.top anchors.top: outfitCreatureBox.top
anchors.left: creature.right anchors.left: outfitCreatureBox.right
margin-left: 10 margin-left: 10
checked: true checked: true
width: 90
ButtonBox ButtonBox
id: primary id: primary
text: Primary text: Primary
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: prev.left
width: 90
ButtonBox ButtonBox
id: secondary id: secondary
text: Secondary text: Secondary
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: prev.left
width: 90
ButtonBox ButtonBox
id: detail id: detail
text: Detail text: Detail
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: prev.left
width: 90
Button Button
id: outfitNextButton
@onClick: Outfit.nextType() @onClick: Outfit.nextType()
text: >> text: >>
width: 32 width: 32
margin-top: 4 margin-top: 4
anchors.top: creature.bottom anchors.top: outfitCreatureBox.bottom
anchors.right: creature.right anchors.right: outfitCreatureBox.right
Button Button
id: outfitPreviousButton
@onClick: Outfit.previousType() @onClick: Outfit.previousType()
text: << text: <<
width: 32 width: 32
margin-top: 4 margin-top: 4
anchors.top: creature.bottom anchors.top: outfitCreatureBox.bottom
anchors.left: creature.left anchors.left: outfitCreatureBox.left
CheckBox CheckBox
id: addon1 id: addon1
text: Addon 1 text: Addon 1
enabled: false enabled: false
margin-top: 10 margin-top: 6
width: 100 width: 100
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: prev.left
@ -85,7 +102,7 @@ Window
id: addon2 id: addon2
text: Addon 2 text: Addon 2
enabled: false enabled: false
margin-top: 10 margin-top: 2
width: 100 width: 100
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: prev.left
@ -94,7 +111,7 @@ Window
id: addon3 id: addon3
text: Addon 3 text: Addon 3
enabled: false enabled: false
margin-top: 10 margin-top: 2
width: 100 width: 100
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: prev.left anchors.left: prev.left
@ -108,7 +125,7 @@ Window
margin-bottom: 10 margin-bottom: 10
Button Button
id: buttonOk id: outfitOkButton
text: Ok text: Ok
width: 64 width: 64
anchors.right: next.left anchors.right: next.left
@ -118,7 +135,7 @@ Window
@onClick: Outfit.accept() @onClick: Outfit.accept()
Button Button
id: buttonCancel id: outfitCancelButton
text: Cancel text: Cancel
width: 64 width: 64
anchors.right: parent.right anchors.right: parent.right

View File

@ -42,7 +42,7 @@ end
-- public functions -- public functions
function Skills.create() function Skills.create()
skillsWindow = displayUI('skills.otui', g_game.gameRightPanel) skillsWindow = displayUI('skills.otui', GameInterface.getRightPanel())
skillsWindow:hide() skillsWindow:hide()
skillsButton = TopMenu.addGameButton('skillsButton', 'Skills (Ctrl+S)', '/core_styles/icons/skills.png', Skills.toggle) skillsButton = TopMenu.addGameButton('skillsButton', 'Skills (Ctrl+S)', '/core_styles/icons/skills.png', Skills.toggle)
Keyboard.bindKeyDown('Ctrl+S', Skills.toggle) Keyboard.bindKeyDown('Ctrl+S', Skills.toggle)

View File

@ -3,5 +3,6 @@ Module
description: Manage skills window description: Manage skills window
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: |
@onLoad: |
dofile 'skills' dofile 'skills'

View File

@ -24,7 +24,7 @@ local function displayMessage(msgtype, msg, time)
if not g_game.isOnline() then return end if not g_game.isOnline() then return end
if msgtype.consoleTab ~= nil then if msgtype.consoleTab ~= nil then
if msgtype.consoleOption == nil or Options[msgtype.consoleOption] then if msgtype.consoleOption == nil or Options.getOption(msgtype.consoleOption) then
Console.addText(msg, msgtype, msgtype.consoleTab) Console.addText(msg, msgtype, msgtype.consoleTab)
end end
end end
@ -93,7 +93,7 @@ end
function TextMessage.terminate() function TextMessage.terminate()
disconnect(g_game, { onDeath = TextMessage.displayDeadMessage, disconnect(g_game, { onDeath = TextMessage.displayDeadMessage,
onTextMessage = TextMessage.display, onTextMessage = TextMessage.display,
onGameStart = TextMessage.clearMessages }) onGameEnd = TextMessage.clearMessages })
centerTextMessagePanel:destroy() centerTextMessagePanel:destroy()
centerTextMessagePanel = nil centerTextMessagePanel = nil
bottomStatusLabel:destroy() bottomStatusLabel:destroy()

1
modules/game_tibiafiles/.gitignore vendored Normal file
View File

@ -0,0 +1 @@

View File

@ -7,7 +7,7 @@ local addVipWindow
-- public functions -- public functions
function VipList.create() function VipList.create()
vipWindow = displayUI('viplist.otui', g_game.gameRightPanel) vipWindow = displayUI('viplist.otui', GameInterface.getRightPanel())
vipWindow:hide() vipWindow:hide()
vipButton = TopMenu.addGameButton('vipListButton', 'VIP list', 'viplist.png', VipList.toggle) vipButton = TopMenu.addGameButton('vipListButton', 'VIP list', 'viplist.png', VipList.toggle)
end end

View File

@ -3,5 +3,6 @@ Module
description: Manage vip list window description: Manage vip list window
author: OTClient team author: OTClient team
website: https://github.com/edubart/otclient website: https://github.com/edubart/otclient
onLoad: |
@onLoad: |
dofile 'viplist' dofile 'viplist'

View File

@ -1,5 +1,5 @@
-- private variables -- private variables
local m_mouseGrabberWidget local mouseGrabberWidget
-- private functions -- private functions
local function onGameKeyPress(self, keyCode, keyboardModifiers) local function onGameKeyPress(self, keyCode, keyboardModifiers)
@ -41,7 +41,7 @@ end
-- public functions -- public functions
function g_game.startUseWith(thing) function g_game.startUseWith(thing)
g_game.selectedThing = thing g_game.selectedThing = thing
m_mouseGrabberWidget:grabMouse() mouseGrabberWidget:grabMouse()
Mouse.setTargetCursor() Mouse.setTargetCursor()
end end
@ -49,11 +49,11 @@ function g_game.createInterface()
rootWidget:moveChildToIndex(g_game.gameUi, 1) rootWidget:moveChildToIndex(g_game.gameUi, 1)
g_game.gameMapPanel = g_game.gameUi:getChildById('gameMapPanel') g_game.gameMapPanel = g_game.gameUi:getChildById('gameMapPanel')
g_game.gameRightPanel = g_game.gameUi:getChildById('gameRightPanel') GameInterface.getRightPanel() = g_game.gameUi:getChildById('gameRightPanel')
g_game.gameBottomPanel = g_game.gameUi:getChildById('gameBottomPanel') g_game.gameBottomPanel = g_game.gameUi:getChildById('gameBottomPanel')
m_mouseGrabberWidget = g_game.gameUi:getChildById('mouseGrabber') mouseGrabberWidget = g_game.gameUi:getChildById('mouseGrabber')
connect(g_game.gameUi, { onKeyPress = onGameKeyPress }) connect(g_game.gameUi, { onKeyPress = onGameKeyPress })
connect(m_mouseGrabberWidget, { onMouseRelease = onUseWithMouseRelease }) connect(mouseGrabberWidget, { onMouseRelease = onUseWithMouseRelease })
end end
function g_game.destroyInterface() function g_game.destroyInterface()

View File

@ -19,7 +19,7 @@ function g_game.processMouseAction(menuPosition, mouseButton, autoWalk, lookThin
return true return true
end end
if not Options.classicControl then if not Options.getOption('classicControl') then
if keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton then if keyboardModifiers == KeyboardNoModifier and mouseButton == MouseRightButton then
g_game.createThingMenu(menuPosition, lookThing, useThing, creatureThing) g_game.createThingMenu(menuPosition, lookThing, useThing, creatureThing)
return true return true

View File

@ -44,6 +44,8 @@ void Logger::log(Fw::LogLevel level, const std::string& message)
std::size_t now = std::time(NULL); std::size_t now = std::time(NULL);
m_logMessages.push_back(LogMessage(level, outmsg, now)); m_logMessages.push_back(LogMessage(level, outmsg, now));
if(m_logMessages.size() > MAX_LOG_HISTORY)
m_logMessages.pop_front();
if(m_onLog) if(m_onLog)
m_onLog(level, outmsg, now); m_onLog(level, outmsg, now);

View File

@ -34,6 +34,10 @@ struct LogMessage {
class Logger class Logger
{ {
enum {
MAX_LOG_HISTORY = 1000
};
typedef std::function<void(Fw::LogLevel, std::string, std::size_t)> OnLogCallback; typedef std::function<void(Fw::LogLevel, std::string, std::size_t)> OnLogCallback;
public: public:

View File

@ -171,7 +171,6 @@ void Texture::generateSoftwareMipmaps(std::vector<uint8> inPixels)
Size outSize = inSize / 2; Size outSize = inSize / 2;
std::vector<uint8> outPixels(outSize.area()*4); std::vector<uint8> outPixels(outSize.area()*4);
dump << "yeah";
int mipmap = 1; int mipmap = 1;
while(true) { while(true) {
// this is a simple bilinear filtering algorithm, it combines every 4 pixels in one pixel // this is a simple bilinear filtering algorithm, it combines every 4 pixels in one pixel

View File

@ -225,6 +225,31 @@ void UIManager::onWidgetDestroy(const UIWidgetPtr& widget)
updateDraggingWidget(nullptr); updateDraggingWidget(nullptr);
} }
void UIManager::addDestroyedWidget(const UIWidgetPtr& widget)
{
static UIWidgetList destroyedWidgets;
static ScheduledEventPtr checkEvent;
if(widget == m_rootWidget)
return;
destroyedWidgets.push_back(widget);
if(checkEvent && !checkEvent->isExecuted())
return;
checkEvent = g_eventDispatcher.scheduleEvent([] {
g_lua.collectGarbage();
g_eventDispatcher.addEvent([] {
g_lua.collectGarbage();
for(const UIWidgetPtr& widget : destroyedWidgets) {
if(widget->getUseCount() != 1)
logWarning("widget '", widget->getId(), "' destroyed but still have ", widget->getUseCount()-1, " reference(s) left");
}
});
}, 1000);
}
bool UIManager::importStyle(const std::string& file) bool UIManager::importStyle(const std::string& file)
{ {
try { try {

View File

@ -68,6 +68,7 @@ protected:
void onWidgetAppear(const UIWidgetPtr& widget); void onWidgetAppear(const UIWidgetPtr& widget);
void onWidgetDisappear(const UIWidgetPtr& widget); void onWidgetDisappear(const UIWidgetPtr& widget);
void onWidgetDestroy(const UIWidgetPtr& widget); void onWidgetDestroy(const UIWidgetPtr& widget);
void addDestroyedWidget(const UIWidgetPtr& widget);
friend class UIWidget; friend class UIWidget;

View File

@ -636,10 +636,8 @@ void UIWidget::destroy()
g_ui.onWidgetDestroy(asUIWidget()); g_ui.onWidgetDestroy(asUIWidget());
// remove itself from parent // remove itself from parent
if(UIWidgetPtr parent = getParent()) { if(UIWidgetPtr parent = getParent())
assert(parent->hasChild(asUIWidget()));
parent->removeChild(asUIWidget()); parent->removeChild(asUIWidget());
}
destroyChildren(); destroyChildren();
m_focusedChild = nullptr; m_focusedChild = nullptr;
@ -649,15 +647,7 @@ void UIWidget::destroy()
releaseLuaFieldsTable(); releaseLuaFieldsTable();
#ifdef DEBUG #ifdef DEBUG
auto self = asUIWidget(); g_ui.addDestroyedWidget(asUIWidget());
g_lua.collectGarbage();
if(self != g_ui.getRootWidget()) {
g_eventDispatcher.scheduleEvent([self] {
g_lua.collectGarbage();
if(self->getUseCount() != 1)
logWarning("widget '", self->getId(), "' destroyed but still have ", self->getUseCount()-1, " reference(s) left");
}, 500);
}
#endif #endif
} }

View File

@ -207,6 +207,7 @@ void OTClient::registerLuaFunctions()
g_lua.bindClassMemberFunction<Creature>("setEmblemTexture", &Creature::setEmblemTexture); g_lua.bindClassMemberFunction<Creature>("setEmblemTexture", &Creature::setEmblemTexture);
g_lua.bindClassMemberFunction<Creature>("showStaticSquare", &Creature::showStaticSquare); g_lua.bindClassMemberFunction<Creature>("showStaticSquare", &Creature::showStaticSquare);
g_lua.bindClassMemberFunction<Creature>("hideStaticSquare", &Creature::hideStaticSquare); g_lua.bindClassMemberFunction<Creature>("hideStaticSquare", &Creature::hideStaticSquare);
g_lua.bindClassMemberFunction<Creature>("isWalking", &Creature::isWalking);
g_lua.bindClassMemberFunction<Creature>("asMonster", &Creature::asMonster); g_lua.bindClassMemberFunction<Creature>("asMonster", &Creature::asMonster);
g_lua.bindClassMemberFunction<Creature>("asNpc", &Creature::asNpc); g_lua.bindClassMemberFunction<Creature>("asNpc", &Creature::asNpc);
@ -220,7 +221,9 @@ void OTClient::registerLuaFunctions()
g_lua.registerClass<AnimatedText, Thing>(); g_lua.registerClass<AnimatedText, Thing>();
g_lua.registerClass<Player, Creature>(); g_lua.registerClass<Player, Creature>();
g_lua.bindClassMemberFunction<Creature>("isWalking", &Creature::isWalking); g_lua.bindClassMemberFunction<Player>("isPartyMember", &LocalPlayer::isPartyMember);
g_lua.bindClassMemberFunction<Player>("isPartyLeader", &LocalPlayer::isPartyLeader);
g_lua.bindClassMemberFunction<Player>("isPartySharedExperienceActive", &LocalPlayer::isPartySharedExperienceActive);
g_lua.registerClass<Npc, Creature>(); g_lua.registerClass<Npc, Creature>();
g_lua.registerClass<Monster, Creature>(); g_lua.registerClass<Monster, Creature>();