mirror of
https://github.com/mehah/otclient
synced 2026-08-15 16:29:06 -04:00
* fix: mainpanel * Minor fixes * Removed dead code (Outfit) * Fixed type error SpellGroups vs game_cooldown * Fixed Keybind * And more * more fixes * ... * Changes in shop (store) * Added function addOutfit; * Fixed entries per page (history); * Fixed Extras Category * Added function Game.getMountIdByClientId
658 lines
20 KiB
Lua
658 lines
20 KiB
Lua
local options = dofile("data_options")
|
|
panels = {
|
|
generalPanel = nil,
|
|
graphicsPanel = nil,
|
|
soundPanel = nil,
|
|
gameMapPanel = nil,
|
|
graphicsEffectsPanel = nil,
|
|
interfaceHUD = nil,
|
|
interface = nil,
|
|
misc = nil,
|
|
miscHelp = nil,
|
|
keybindsPanel = nil
|
|
}
|
|
-- LuaFormatter off
|
|
local buttons = { {
|
|
|
|
text = "Controls",
|
|
icon = "/images/icons/icon_controls",
|
|
open = "generalPanel",
|
|
subCategories = { {
|
|
text = "General Hotkeys",
|
|
open = "keybindsPanel"
|
|
} }
|
|
}, {
|
|
text = "Interface",
|
|
icon = "/images/icons/icon_interface",
|
|
open = "interface",
|
|
subCategories = { {
|
|
text = "HUD",
|
|
open = "interfaceHUD"
|
|
}, {
|
|
text = "Console",
|
|
open = "interfaceConsole"
|
|
} }
|
|
}, {
|
|
text = "Graphics",
|
|
icon = "/images/icons/icon_graphics",
|
|
open = "graphicsPanel",
|
|
subCategories = { {
|
|
text = "Effects",
|
|
open = "graphicsEffectsPanel"
|
|
} }
|
|
}, {
|
|
text = "Sound",
|
|
icon = "/images/icons/icon_sound",
|
|
open = "soundPanel"
|
|
--[[ subCategories = {{
|
|
text = "Battle Sounds",
|
|
open = "Battle_Sounds"
|
|
}, {
|
|
text = "UI Sounds",
|
|
open = "UI_Sounds"
|
|
}} ]]
|
|
}, {
|
|
text = "Misc.",
|
|
icon = "/images/icons/icon_misc",
|
|
open = "misc",
|
|
subCategories = { --[[ {
|
|
text = "GamePlay",
|
|
open = "GamePlay"
|
|
}, {
|
|
text = "Screenshots",
|
|
open = "Screenshots"
|
|
}, ]] {
|
|
text = "Help",
|
|
open = "miscHelp"
|
|
} }
|
|
} }
|
|
|
|
-- LuaFormatter on
|
|
local extraWidgets = {
|
|
audioButton = nil,
|
|
optionsButton = nil,
|
|
logoutButton = nil,
|
|
optionsButtons = nil
|
|
}
|
|
|
|
local function toggleDisplays()
|
|
if options['displayNames'].value and options['displayHealth'].value and options['displayMana'].value then
|
|
setOption('displayNames', false)
|
|
elseif options['displayHealth'].value then
|
|
setOption('displayHealth', false)
|
|
setOption('displayMana', false)
|
|
else
|
|
if not options['displayNames'].value and not options['displayHealth'].value then
|
|
setOption('displayNames', true)
|
|
else
|
|
setOption('displayHealth', true)
|
|
setOption('displayMana', true)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function toggleOption(key)
|
|
setOption(key, not getOption(key))
|
|
end
|
|
|
|
local function setupComboBox()
|
|
local crosshairCombo = panels.interface:recursiveGetChildById('crosshair')
|
|
local antialiasingModeCombobox = panels.graphicsPanel:recursiveGetChildById('antialiasingMode')
|
|
local floorViewModeCombobox = panels.graphicsEffectsPanel:recursiveGetChildById('floorViewMode')
|
|
local framesRarityCombobox = panels.interface:recursiveGetChildById('frames')
|
|
local vocationPresetsCombobox = panels.keybindsPanel:recursiveGetChildById('list')
|
|
local listKeybindsPanel = panels.keybindsPanel:recursiveGetChildById('list')
|
|
|
|
for k, v in pairs({ { 'Disabled', 'disabled' }, { 'Default', 'default' }, { 'Full', 'full' } }) do
|
|
crosshairCombo:addOption(v[1], v[2])
|
|
end
|
|
|
|
crosshairCombo.onOptionChange = function(comboBox, option)
|
|
setOption('crosshair', comboBox:getCurrentOption().data)
|
|
end
|
|
|
|
|
|
for k, t in pairs({ 'None', 'Antialiasing', 'Smooth Retro' }) do
|
|
antialiasingModeCombobox:addOption(t, k - 1)
|
|
end
|
|
|
|
antialiasingModeCombobox.onOptionChange = function(comboBox, option)
|
|
setOption('antialiasingMode', comboBox:getCurrentOption().data)
|
|
end
|
|
|
|
|
|
for k, t in pairs({ 'Normal', 'Fade', 'Locked', 'Always', 'Always with transparency' }) do
|
|
floorViewModeCombobox:addOption(t, k - 1)
|
|
end
|
|
|
|
floorViewModeCombobox.onOptionChange = function(comboBox, option)
|
|
setOption('floorViewMode', comboBox:getCurrentOption().data)
|
|
end
|
|
|
|
for k, v in pairs({ { 'None', 'none' }, { 'Frames', 'frames' }, { 'Corners', 'corners' } }) do
|
|
framesRarityCombobox:addOption(v[1], v[2])
|
|
end
|
|
|
|
framesRarityCombobox.onOptionChange = function(comboBox, option)
|
|
setOption('framesRarity', comboBox:getCurrentOption().data)
|
|
end
|
|
|
|
local profileCombobox = panels.misc:recursiveGetChildById('profile')
|
|
|
|
for i = 1, 10 do
|
|
profileCombobox:addOption(tostring(i), i)
|
|
end
|
|
|
|
profileCombobox.onOptionChange = function(comboBox, option)
|
|
setOption('profile', comboBox:getCurrentOption().data)
|
|
end
|
|
|
|
for _, preset in ipairs(Keybind.presets) do
|
|
listKeybindsPanel:addOption(preset)
|
|
end
|
|
listKeybindsPanel.onOptionChange = function(comboBox, option)
|
|
setOption('listKeybindsPanel', option)
|
|
end
|
|
panels.keybindsPanel.presets.list:setCurrentOption(Keybind.currentPreset)
|
|
end
|
|
|
|
local function setup()
|
|
panels.gameMapPanel = modules.game_interface.getMapPanel()
|
|
|
|
setupComboBox()
|
|
|
|
-- load options
|
|
for k, obj in pairs(options) do
|
|
local v = obj.value
|
|
|
|
if type(v) == 'boolean' then
|
|
setOption(k, g_settings.getBoolean(k), true)
|
|
elseif type(v) == 'number' then
|
|
setOption(k, g_settings.getNumber(k), true)
|
|
elseif type(v) == 'string' then
|
|
setOption(k, g_settings.getString(k), true)
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
controller = Controller:new()
|
|
controller:setUI('options')
|
|
|
|
function controller:onInit()
|
|
for k, obj in pairs(options) do
|
|
if type(obj) ~= "table" then
|
|
obj = { value = obj }
|
|
options[k] = obj
|
|
end
|
|
g_settings.setDefault(k, obj.value)
|
|
end
|
|
|
|
extraWidgets.audioButton = modules.client_topmenu.addTopRightToggleButton('audioButton', tr('Audio'),
|
|
'/images/topbuttons/button_mute_up', function() toggleOption('enableAudio') end)
|
|
|
|
extraWidgets.optionsButton = modules.client_topmenu.addTopRightToggleButton('optionsButton', tr('Options'),
|
|
'/images/topbuttons/button_options', toggle)
|
|
|
|
extraWidgets.logoutButton = modules.client_topmenu.addTopRightToggleButton('logoutButton', tr('Exit'),
|
|
'/images/topbuttons/logout', toggle)
|
|
|
|
panels.generalPanel = g_ui.loadUI('styles/controls/general', controller.ui.optionsTabContent)
|
|
panels.keybindsPanel = g_ui.loadUI('styles/controls/keybinds', controller.ui.optionsTabContent)
|
|
|
|
panels.graphicsPanel = g_ui.loadUI('styles/graphics/graphics', controller.ui.optionsTabContent)
|
|
panels.graphicsEffectsPanel = g_ui.loadUI('styles/graphics/effects', controller.ui.optionsTabContent)
|
|
|
|
panels.interface = g_ui.loadUI('styles/interface/interface', controller.ui.optionsTabContent)
|
|
panels.interfaceConsole = g_ui.loadUI('styles/interface/console', controller.ui.optionsTabContent)
|
|
panels.interfaceHUD = g_ui.loadUI('styles/interface/HUD', controller.ui.optionsTabContent)
|
|
|
|
panels.soundPanel = g_ui.loadUI('styles/sound/audio', controller.ui.optionsTabContent)
|
|
|
|
panels.misc = g_ui.loadUI('styles/misc/misc', controller.ui.optionsTabContent)
|
|
panels.miscHelp = g_ui.loadUI('styles/misc/help', controller.ui.optionsTabContent)
|
|
|
|
self.ui:hide()
|
|
|
|
configureCharacterCategories()
|
|
addEvent(setup)
|
|
init_binds()
|
|
|
|
Keybind.new("UI", "Toggle Fullscreen", "Ctrl+Shift+F", "")
|
|
Keybind.bind("UI", "Toggle Fullscreen", {
|
|
{
|
|
type = KEY_DOWN,
|
|
callback = function() toggleOption('fullscreen') end,
|
|
}
|
|
})
|
|
Keybind.new("UI", "Show/hide FPS / lag indicator", "", "")
|
|
Keybind.bind("UI", "Show/hide FPS / lag indicator", { {
|
|
type = KEY_DOWN,
|
|
callback = function()
|
|
toggleOption('showPing')
|
|
toggleOption('showFps')
|
|
end
|
|
} })
|
|
|
|
Keybind.new("UI", "Show/hide Creature Names and Bars", "Ctrl+N", "")
|
|
Keybind.bind("UI", "Show/hide Creature Names and Bars", {
|
|
{
|
|
type = KEY_DOWN,
|
|
callback = toggleDisplays,
|
|
}
|
|
})
|
|
|
|
Keybind.new("Sound", "Mute/unmute", "", "")
|
|
Keybind.bind("Sound", "Mute/unmute", {
|
|
{
|
|
type = KEY_DOWN,
|
|
callback = function() toggleOption('enableAudio') end,
|
|
}
|
|
})
|
|
end
|
|
|
|
function controller:onTerminate()
|
|
extraWidgets.optionsButton:destroy()
|
|
extraWidgets.audioButton:destroy()
|
|
panels = {}
|
|
extraWidgets = {}
|
|
buttons = {}
|
|
Keybind.delete("UI", "Toggle Fullscreen")
|
|
Keybind.delete("UI", "Show/hide Creature Names and Bars")
|
|
Keybind.delete("UI", "Show/hide FPS / lag indicator")
|
|
Keybind.delete("Sound", "Mute/unmute")
|
|
|
|
terminate_binds()
|
|
end
|
|
|
|
function controller:onGameStart()
|
|
if g_settings.getBoolean("autoSwitchPreset") then
|
|
local name = g_game.getCharacterName()
|
|
if Keybind.selectPreset(name) then
|
|
panels.keybindsPanel.presets.list:setCurrentOption(name, true)
|
|
updateKeybinds()
|
|
end
|
|
end
|
|
end
|
|
|
|
function setOption(key, value, force)
|
|
if not modules.game_interface then
|
|
return
|
|
end
|
|
|
|
local option = options[key]
|
|
if option == nil or not force and option.value == value then
|
|
return
|
|
end
|
|
|
|
if option.action then
|
|
option.action(value, options, controller, panels, extraWidgets)
|
|
end
|
|
|
|
|
|
-- change value for keybind updates
|
|
for _, panel in pairs(panels) do
|
|
local widget = panel:recursiveGetChildById(key)
|
|
if widget then
|
|
if widget:getStyle().__class == 'UICheckBox' then
|
|
widget:setChecked(value)
|
|
elseif widget:getStyle().__class == 'UIScrollBar' then
|
|
widget:setValue(value)
|
|
elseif widget:recursiveGetChildById('valueBar') then
|
|
widget:recursiveGetChildById('valueBar'):setValue(value)
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
option.value = value
|
|
g_settings.set(key, value)
|
|
end
|
|
|
|
function setupOptionsMainButton()
|
|
if extraWidgets.optionsButtons then
|
|
return
|
|
end
|
|
|
|
extraWidgets.optionsButtons = modules.game_mainpanel.addSpecialToggleButton('optionsMainButton', tr('Options'),
|
|
'/images/options/button_options', toggle, true)
|
|
end
|
|
|
|
function getOption(key)
|
|
return options[key].value
|
|
end
|
|
|
|
function show()
|
|
controller.ui:show()
|
|
controller.ui:raise()
|
|
controller.ui:focus()
|
|
end
|
|
|
|
function hide()
|
|
controller.ui:hide()
|
|
end
|
|
|
|
function toggle()
|
|
if controller.ui:isVisible() then
|
|
hide()
|
|
return
|
|
end
|
|
if not controller.ui.openedCategory then
|
|
local firstCategory = controller.ui.optionsTabBar:getChildByIndex(1)
|
|
controller.ui.openedCategory = firstCategory
|
|
firstCategory.Button:onClick()
|
|
local panelToShow = panels[firstCategory.open]
|
|
if panelToShow then
|
|
panelToShow:show()
|
|
controller.ui.selectedOption = panelToShow
|
|
end
|
|
end
|
|
show()
|
|
updateKeybinds()
|
|
end
|
|
|
|
function addTab(name, panel, icon)
|
|
print("to prevent the error use Ex = g_ui.loadUI('option_healthcircle',modules.client_options:getPanel()) ")
|
|
end
|
|
|
|
function removeTab(v)
|
|
print("to prevent the error use Ex modules.client_options.addButton('Interface', 'HP/MP Circle', optionPanel)")
|
|
end
|
|
|
|
local function toggleSubCategories(parent, isOpen)
|
|
for subId, _ in ipairs(parent.subCategories) do
|
|
local subWidget = parent:getChildById(subId)
|
|
if subWidget then
|
|
subWidget:setVisible(isOpen)
|
|
end
|
|
end
|
|
parent:setHeight(isOpen and parent.openedSize or parent.closedSize)
|
|
parent.opened = isOpen
|
|
parent.Button.Arrow:setVisible(not isOpen)
|
|
end
|
|
|
|
local function close(parent)
|
|
if parent.subCategories then
|
|
toggleSubCategories(parent, false)
|
|
end
|
|
end
|
|
|
|
local function open(parent)
|
|
local oldOpen = controller.ui.openedCategory
|
|
if oldOpen and oldOpen ~= parent then
|
|
close(oldOpen)
|
|
end
|
|
toggleSubCategories(parent, true)
|
|
controller.ui.openedCategory = parent
|
|
end
|
|
|
|
function selectCharacterPage()
|
|
local selectedOption = controller.ui.selectedOption
|
|
if selectedOption then
|
|
selectedOption:hide()
|
|
end
|
|
if controller.ui.InfoBase then
|
|
controller.ui.InfoBase:setVisible(true)
|
|
controller.ui.InfoBase:show()
|
|
end
|
|
end
|
|
|
|
local function createSubWidget(parent, subId, subButton)
|
|
local subWidget = g_ui.createWidget("OptionsCategory", parent)
|
|
subWidget:setId(subId)
|
|
subWidget.Button.Icon:setIcon(subButton.icon)
|
|
subWidget.Button.Title:setText(subButton.text)
|
|
subWidget:setVisible(false)
|
|
subWidget.open = subButton.open
|
|
subWidget.callbackFunc = subButton.callbackFunc
|
|
|
|
function subWidget.Button.onClick()
|
|
local selectedOption = controller.ui.selectedOption
|
|
closeCharacterButtons()
|
|
parent.Button:setChecked(false)
|
|
parent.Button.Arrow:setVisible(true)
|
|
parent.Button.Arrow:setImageSource("")
|
|
subWidget.Button:setChecked(true)
|
|
subWidget.Button.Arrow:setVisible(true)
|
|
subWidget.Button.Arrow:setImageSource("/images/ui/icon-arrow7x7-right")
|
|
|
|
if selectedOption then
|
|
selectedOption:hide()
|
|
end
|
|
|
|
local panelToShow = panels[subWidget.open]
|
|
if panelToShow then
|
|
panelToShow:show()
|
|
panelToShow:setVisible(true)
|
|
controller.ui.selectedOption = panelToShow
|
|
else
|
|
print("Error: panelToShow is nil or does not exist in panels")
|
|
end
|
|
if subWidget.callbackFunc then
|
|
subWidget.callbackFunc()
|
|
end
|
|
end
|
|
|
|
subWidget:addAnchor(AnchorHorizontalCenter, "parent", AnchorHorizontalCenter)
|
|
if subId == 1 then
|
|
subWidget:addAnchor(AnchorTop, "parent", AnchorTop)
|
|
subWidget:setMarginTop(20)
|
|
else
|
|
subWidget:addAnchor(AnchorTop, "prev", AnchorBottom)
|
|
subWidget:setMarginTop(-1)
|
|
end
|
|
|
|
return subWidget
|
|
end
|
|
|
|
function configureCharacterCategories()
|
|
controller.ui.optionsTabBar:destroyChildren()
|
|
|
|
for id, button in ipairs(buttons) do
|
|
local widget = g_ui.createWidget("OptionsCategory", controller.ui.optionsTabBar)
|
|
widget:setId(id)
|
|
widget.Button.Icon:setIcon(button.icon)
|
|
widget.Button.Title:setText(button.text)
|
|
widget.open = button.open
|
|
|
|
if button.subCategories then
|
|
widget.subCategories = button.subCategories
|
|
widget.subCategoriesSize = #button.subCategories
|
|
widget.Button.Arrow:setVisible(true)
|
|
|
|
for subId, subButton in ipairs(button.subCategories) do
|
|
local subWidget = createSubWidget(widget, subId, subButton)
|
|
if button.text == "Controls" then
|
|
subWidget.Button.Title:setMarginLeft(-5)
|
|
end
|
|
end
|
|
end
|
|
|
|
widget:addAnchor(AnchorHorizontalCenter, "parent", AnchorHorizontalCenter)
|
|
if id == 1 then
|
|
widget:addAnchor(AnchorTop, "parent", AnchorTop)
|
|
widget:setMarginTop(10)
|
|
else
|
|
widget:addAnchor(AnchorTop, "prev", AnchorBottom)
|
|
widget:setMarginTop(10)
|
|
end
|
|
|
|
function widget.Button.onClick()
|
|
local parent = widget
|
|
local oldOpen = controller.ui.openedCategory
|
|
|
|
if oldOpen and oldOpen ~= parent then
|
|
if oldOpen.Button then
|
|
oldOpen.Button:setChecked(false)
|
|
oldOpen.Button.Arrow:setImageSource("/images/ui/icon-arrow7x7-down")
|
|
end
|
|
|
|
close(oldOpen)
|
|
end
|
|
|
|
if parent.subCategoriesSize then
|
|
parent.closedSize = parent.closedSize or parent:getHeight() / (parent.subCategoriesSize + 1) + 15
|
|
parent.openedSize = parent.openedSize or parent:getHeight() * (parent.subCategoriesSize + 1) - 6
|
|
|
|
if not parent.opened then
|
|
open(parent)
|
|
end
|
|
end
|
|
|
|
widget.Button:setChecked(true)
|
|
widget.Button.Arrow:setImageSource("/images/ui/icon-arrow7x7-right")
|
|
widget.Button.Arrow:setVisible(true)
|
|
|
|
if controller.ui.selectedOption then
|
|
controller.ui.selectedOption:hide()
|
|
end
|
|
|
|
local panelToShow = panels[parent.open]
|
|
if panelToShow then
|
|
closeCharacterButtons()
|
|
panelToShow:show()
|
|
panelToShow:setVisible(true)
|
|
controller.ui.selectedOption = panelToShow
|
|
else
|
|
print("Error: panelToShow is nil or does not exist in panels")
|
|
end
|
|
|
|
controller.ui.openedCategory = parent
|
|
end
|
|
end
|
|
end
|
|
|
|
function closeCharacterButtons()
|
|
for i = 1, controller.ui.optionsTabBar:getChildCount() do
|
|
local widget = controller.ui.optionsTabBar:getChildByIndex(i)
|
|
if widget and widget.subCategories then
|
|
for subId, _ in ipairs(widget.subCategories) do
|
|
local subWidget = widget:getChildById(subId)
|
|
if subWidget then
|
|
subWidget.Button:setChecked(false)
|
|
subWidget.Button.Arrow:setVisible(false)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function createCategory(text, icon, openPanel, subCategories)
|
|
local newCategory = {
|
|
text = text,
|
|
icon = icon,
|
|
open = type(openPanel) == "string" and openPanel or getPanelName(openPanel),
|
|
subCategories = subCategories
|
|
}
|
|
table.insert(buttons, newCategory)
|
|
if type(openPanel) ~= "string" then
|
|
panels[getPanelName(openPanel)] = openPanel
|
|
end
|
|
configureCharacterCategories()
|
|
end
|
|
|
|
function removeCategory(categoryText, subcategoryText)
|
|
for i, category in ipairs(buttons) do
|
|
if category.text == categoryText then
|
|
if subcategoryText then
|
|
if category.subCategories then
|
|
for j, subcategory in ipairs(category.subCategories) do
|
|
if subcategory.text == subcategoryText then
|
|
panels[subcategory.open] = nil
|
|
table.remove(category.subCategories, j)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
else
|
|
panels[category.open] = nil
|
|
if category.subCategories then
|
|
for _, subcategory in ipairs(category.subCategories) do
|
|
panels[subcategory.open] = nil
|
|
end
|
|
end
|
|
table.remove(buttons, i)
|
|
end
|
|
configureCharacterCategories()
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
function removeButton(categoryText, buttonText)
|
|
for _, category in ipairs(buttons) do
|
|
if category.text == categoryText then
|
|
if category.subCategories then
|
|
for i, subcategory in ipairs(category.subCategories) do
|
|
if subcategory.text == buttonText then
|
|
panels[subcategory.open] = nil
|
|
table.remove(category.subCategories, i)
|
|
configureCharacterCategories()
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function addButton(categoryText, buttonText, openPanel, callback)
|
|
for _, category in ipairs(buttons) do
|
|
if category.text == categoryText then
|
|
if not category.subCategories then
|
|
category.subCategories = {}
|
|
end
|
|
local panelName = type(openPanel) == "string" and openPanel or getPanelName(openPanel)
|
|
table.insert(category.subCategories, {
|
|
text = buttonText,
|
|
open = panelName,
|
|
callbackFunc = callback
|
|
})
|
|
if type(openPanel) ~= "string" then
|
|
panels[panelName] = openPanel
|
|
end
|
|
configureCharacterCategories()
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
function getPanelName(panel)
|
|
for name, p in pairs(panels) do
|
|
if p == panel then
|
|
return name
|
|
end
|
|
end
|
|
return "panel_" .. tostring(panel):match("userdata: 0x(%x+)")
|
|
end
|
|
|
|
function addSubcategoryToCategory(categoryText, newSubcategory)
|
|
addButtonToCategory(categoryText, newSubcategory)
|
|
end
|
|
|
|
function getPanel()
|
|
return controller.ui.optionsTabContent
|
|
end
|
|
|
|
function openOptionsCategory(category, subcategory)
|
|
if not controller.ui:isVisible() then
|
|
show()
|
|
end
|
|
for i = 1, controller.ui.optionsTabBar:getChildCount() do
|
|
local widget = controller.ui.optionsTabBar:getChildByIndex(i)
|
|
if widget and widget.Button.Title:getText() == category then
|
|
widget.Button:onClick()
|
|
if subcategory and widget.subCategories then
|
|
for subId, _ in ipairs(widget.subCategories) do
|
|
local subWidget = widget:getChildById(subId)
|
|
if subWidget and subWidget.Button.Title:getText() == subcategory then
|
|
subWidget.Button:onClick()
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|