From a1baafb65f66000b4acdc553f52a034afb4f4509 Mon Sep 17 00:00:00 2001 From: kokekanon <114332266+kokekanon@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:18:32 -0400 Subject: [PATCH] improve: client_options with tibia 13 styles (#821) --- data/images/ui/button-grey-down.png | Bin 0 -> 5883 bytes data/images/ui/button-grey-up.png | Bin 0 -> 6100 bytes data/images/ui/icon-arrow-disabled.png | Bin 0 -> 124 bytes data/images/ui/icon-arrow.png | Bin 0 -> 147 bytes data/images/ui/icon-arrow7x7-down.png | Bin 0 -> 102 bytes data/images/ui/icon-arrow7x7-right.png | Bin 0 -> 113 bytes data/images/ui/test/button-darkgrey-down.png | Bin 0 -> 4839 bytes data/images/ui/test/button-darkgrey-up.png | Bin 0 -> 5083 bytes .../ui/test/button-verydarkgrey-down.png | Bin 0 -> 2418 bytes .../images/ui/test/button-verydarkgrey-up.png | Bin 0 -> 2393 bytes modules/client_options/data_options.lua | 32 +- modules/client_options/options.lua | 398 ++++++++++++++++-- modules/client_options/options.otui | 89 +++- .../styles/controls/general.otui | 140 ++++++ .../styles/graphics/effects.otui | 129 ++++++ .../styles/graphics/graphics.otui | 113 +++++ .../client_options/styles/interface/HUD.otui | 77 ++++ .../styles/interface/console.otui | 90 ++++ .../styles/interface/interface.otui | 80 ++++ modules/client_options/styles/misc/help.otui | 44 ++ modules/client_options/styles/misc/misc.otui | 12 + .../client_options/styles/sound/audio.otui | 36 ++ modules/game_actionbar/game_actionbar.lua | 14 +- modules/game_cooldown/cooldown.lua | 5 + .../game_healthcircle/game_healthcircle.lua | 6 +- .../option_healthcircle.otui | 4 +- modules/game_screenshot/game_screenshot.lua | 34 +- modules/game_screenshot/game_screenshot.otui | 6 +- 28 files changed, 1217 insertions(+), 92 deletions(-) create mode 100644 data/images/ui/button-grey-down.png create mode 100644 data/images/ui/button-grey-up.png create mode 100644 data/images/ui/icon-arrow-disabled.png create mode 100644 data/images/ui/icon-arrow.png create mode 100644 data/images/ui/icon-arrow7x7-down.png create mode 100644 data/images/ui/icon-arrow7x7-right.png create mode 100644 data/images/ui/test/button-darkgrey-down.png create mode 100644 data/images/ui/test/button-darkgrey-up.png create mode 100644 data/images/ui/test/button-verydarkgrey-down.png create mode 100644 data/images/ui/test/button-verydarkgrey-up.png create mode 100644 modules/client_options/styles/controls/general.otui create mode 100644 modules/client_options/styles/graphics/effects.otui create mode 100644 modules/client_options/styles/graphics/graphics.otui create mode 100644 modules/client_options/styles/interface/HUD.otui create mode 100644 modules/client_options/styles/interface/console.otui create mode 100644 modules/client_options/styles/interface/interface.otui create mode 100644 modules/client_options/styles/misc/help.otui create mode 100644 modules/client_options/styles/misc/misc.otui create mode 100644 modules/client_options/styles/sound/audio.otui diff --git a/data/images/ui/button-grey-down.png b/data/images/ui/button-grey-down.png new file mode 100644 index 0000000000000000000000000000000000000000..b0935c59b9c8b9142f34718ef4af41656557ddf3 GIT binary patch literal 5883 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 G-TFUepy6x) literal 0 HcmV?d00001 diff --git a/data/images/ui/icon-arrow-disabled.png b/data/images/ui/icon-arrow-disabled.png new file mode 100644 index 0000000000000000000000000000000000000000..d581aebeedc06f2b2fbb8d157065e38e27a8996b GIT binary patch literal 124 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ(0U`xw#m)s%&YmugAr-eu&u`>qFyvr4*xF$< z;l+Lx6|0BFw-41Fn){%o#QeFd%WO%j#k-kvEFL#WGJX+dG%;SfDvzP!q11eh`uduh XMET3PD=umRjbre1^>bP0l+XkKbPXtg literal 0 HcmV?d00001 diff --git a/data/images/ui/icon-arrow.png b/data/images/ui/icon-arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..2b467e4fc2a1215da8bf4f86320934bca47316f2 GIT binary patch literal 147 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ(0U`xw#m)s%QJyZ2Ar-fB`wayTCbmIH|ms}7ug{ljmIZN{;bt{IZ?Nj+>2!X%v>LhltbH9)$81IIfknJDoekxMB4B9&Q`$u@ruSIqoNPbfVMDry85}Sb4q9e0J0-DQvd(} literal 0 HcmV?d00001 diff --git a/data/images/ui/icon-arrow7x7-down.png b/data/images/ui/icon-arrow7x7-down.png new file mode 100644 index 0000000000000000000000000000000000000000..859cec51756415f569ca649d39f65e89cf50db83 GIT binary patch literal 102 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 N002ovPDHLkV1g%YP+|Z8 literal 0 HcmV?d00001 diff --git a/data/images/ui/test/button-darkgrey-up.png b/data/images/ui/test/button-darkgrey-up.png new file mode 100644 index 0000000000000000000000000000000000000000..520166aee4c33bbbe0b63cb6795f58cbb077bad5 GIT binary patch literal 5083 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 literal 0 HcmV?d00001 diff --git a/data/images/ui/test/button-verydarkgrey-down.png b/data/images/ui/test/button-verydarkgrey-down.png new file mode 100644 index 0000000000000000000000000000000000000000..6ea33d15177f5e6459d6d218fb29c5b8bed952fb GIT binary patch literal 2418 zcmV-&361uNP)&=zk8sJD>l1xcC2e__D75yOn?Z_>t#%Ue=|Q z0s!KCErp28jG1bw-n%2ER@?cz^B6BViwGjr)>>;|;GAo%_1?`4006+uRJGR1B1CxY z@HcPX@ac4lQzWF;8X-C#0L;J)P(+;bU{FeFwT2MPjEJ6JUWf?*ge8PfYx(m`%*@P| zW!d)~5kv51cJ1(ohX;-^{_w*Os;a8Y+*&0j?W(;K@xJdjH#f(z6S0}a7@7HeK5N(B z`o8ZX;=BWZTC17WTFo@2yevyfiHT3^>DuA%KYZYMo)IyGkaI>v0AP_2LTjyjxyB*H zVdPTE+qSjVmSyR^6VbM9-uYqk%#4^2X~oZ|EI%iZ0b_C6dT0POq5%tVX`W|m87t&LL}r?D&x0=~RHdl#4q5zXvKNAN*J zy7u0?s$M(%{rmU4EVK7soS0flX_}^VBme+JVKGxxH83JFRU$$}L{wGp{c#*D?8N1g zLkOyBrl-@*w(TMKKWAP${PFRTM1+Yhmy7p)JaXqf037?yOd<{u)@1>*8B7Gv-hs|4giSw7l5lO-`?I%Q$)a8D*%}3x~%)YhY*hA81!*t zopYrYC$83th|99%oabeE{`7o*|2OB{&CN|pIfT$vb1A*G)9GZU*A9PteB|4^yVJTN zVM<9v44}96r>V<1Pt!EU32~n1l#__;`*x&sI-M?;ON?;@!P~Y?F_>BJJ%m6+$8pT_ zeC_Z*{`iBZ7)3aSh=>3qd@um;-ld#dZR1LN?@O(!8bd@v5x4JqYi*uqW*QN!b8bJ5 z-g^uY5ViMGG9q3({O#MfJkN9Q9g$+3QcCN(j*E(j!H2QCYL-%R&JlCYxz@U@>pV?k z5v?^5X|1J{PN%iEK32@k%)D*ewZq@O{e_6=#~=UAOt*bIpUWA%xZ&0E8Hs830pCy(*md5?&t=JCiy!i zfL3ek&3mV6LkW#BmR!7d1~$+0<#ItJGs`72F*6g7xJ5c9rmsv1JL zcKGLQnwPovZfZVwX0D|YF(3|EueCOGiIMC$?+G#I%q)lifNGtHy!XBLbzO-l<^0|G zd>jWehZwFM{_yZCAyKO}_<)G5Hs@T7vGefqSn>v0@^0XQP^6r-vkVer1SFOm&HtBr|A7&gyyYwb7=77^j0 z+LThdYVbbi?7Tz7Qp!BffH>T0&iQ;kKR>@*JN$F9az3A1ZA45&h(JWccdDw0AWTNWh(ZkWJm;K`bcl#*Z@mo_ z;y8|D-$i6U4kGHUA)^#xbOSr^;JaTG?koFI#NovH@Br^0C;`9`~~2jlNINj zbIyA&EX>kc6XyVM9LTaP`*AptVeN*>MMU#F6Z5*RFE1~qI;1b{3IN--|M2&}KY#kP zuFG+xYlpx28GE5 ze){x@i2A5ln~Jzn3z!XM_1fX@-@WJamta&)35gI*E$2)`%eoA^SV~#fQ>~@e=Dn}A zAYv_*Mbzy1`I9gsafm^CH-#AEvM%1aFU8dBhX3*V?>x^-2u_3v(F{iX8e&Yxp z5!K9z^R>etA0PSl z_7(uAX)=J;T5XMxiEwl!q?CsYXl6O*WuAxMbxy|NjPz1JS9pMsj^h}4Mv z@ac3ivu}+%Ux7b9K5~rl`|rR1*0}Q(_`A37c%EnP{kO)QufTu*{df8J@#D`w|J+(P z(BOjsfLUt|iI};TGDHbgWs#96j*(Gl9krU_Acl^SQtG`ANl-*aCiSJp-;rR5LCoBH zH!uW5!dBae_l7|oX=+MYgw22mz4rq(zCH%KDj1llnhMLm{1>Cu1OU`bm`C^S=Mhyz kWai=V01yC1ZKk&NU;bKG@dN)8MgRZ+07*qoM6N<$f|#1wMgRZ+ literal 0 HcmV?d00001 diff --git a/data/images/ui/test/button-verydarkgrey-up.png b/data/images/ui/test/button-verydarkgrey-up.png new file mode 100644 index 0000000000000000000000000000000000000000..15f9fee8237f801e2b31d28df7afcc4e2547124f GIT binary patch literal 2393 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 LNkvXXu0mjf(8{Xf literal 0 HcmV?d00001 diff --git a/modules/client_options/data_options.lua b/modules/client_options/data_options.lua index fadff65bd3..de7eae1d98 100644 --- a/modules/client_options/data_options.lua +++ b/modules/client_options/data_options.lua @@ -1,7 +1,7 @@ return { vsync = { value = true, - action = function(value, options, controller, panels, extraWidgets, extraWidgets) + action = function(value, options, controller, panels, extraWidgets) g_window.setVerticalSync(value) end }, @@ -96,7 +96,7 @@ return { value = true, action = function(value, options, controller, panels, extraWidgets) panels.gameMapPanel:setDrawLights(value and options.ambientLight.value < 100) - panels.graphicsPanel:recursiveGetChildById('ambientLight'):setEnabled(value) + panels.graphicsEffectsPanel:recursiveGetChildById('ambientLight'):setEnabled(value) end }, limitVisibleDimension = { @@ -114,7 +114,7 @@ return { ambientLight = { value = 0, action = function(value, options, controller, panels, extraWidgets) - panels.graphicsPanel:recursiveGetChildById('ambientLight'):setText(string.format('Ambient light: %s%%', value)) + panels.graphicsEffectsPanel:recursiveGetChildById('ambientLight'):setText(string.format('Ambient light: %s%%', value)) panels.gameMapPanel:setMinimumAmbientLight(value / 100) panels.gameMapPanel:setDrawLights(options.enableLights.value) end @@ -158,13 +158,13 @@ return { turnDelay = { value = 50, action = function(value, options, controller, panels, extraWidgets) - panels.controlPanel:recursiveGetChildById('turnDelay'):setText(string.format('Turn delay: %sms', value)) + panels.generalPanel:recursiveGetChildById('turnDelay'):setText(string.format('Turn delay: %sms', value)) end }, hotkeyDelay = { value = 70, action = function(value, options, controller, panels, extraWidgets) - panels.controlPanel:recursiveGetChildById('hotkeyDelay'):setText(string.format('Hotkey delay: %sms', value)) + panels.generalPanel:recursiveGetChildById('hotkeyDelay'):setText(string.format('Hotkey delay: %sms', value)) end }, crosshair = { @@ -177,7 +177,7 @@ return { end panels.gameMapPanel:setCrosshairTexture(newValue and crossPath .. newValue or nil) - panels.generalPanel:recursiveGetChildById('crosshair'):setCurrentOptionByData(newValue, true) + panels.interface:recursiveGetChildById('crosshair'):setCurrentOptionByData(newValue, true) end }, enableHighlightMouseTarget = { @@ -196,7 +196,7 @@ return { shadowFloorIntensity = { value = 30, action = function(value, options, controller, panels, extraWidgets) - panels.graphicsPanel:recursiveGetChildById('shadowFloorIntensity'):setText(string.format( + panels.graphicsEffectsPanel:recursiveGetChildById('shadowFloorIntensity'):setText(string.format( 'Shadow floor Intensity: %s%%', value)) panels.gameMapPanel:setShadowFloorIntensity(1 - (value / 100)) end @@ -223,16 +223,16 @@ return { value = 1, action = function(value, options, controller, panels, extraWidgets) panels.gameMapPanel:setFloorViewMode(value) - panels.graphicsPanel:recursiveGetChildById('floorViewMode'):setCurrentOptionByData(value, true) + panels.graphicsEffectsPanel:recursiveGetChildById('floorViewMode'):setCurrentOptionByData(value, true) local fadeMode = value == 1 - panels.graphicsPanel:recursiveGetChildById('floorFading'):setEnabled(fadeMode) + panels.graphicsEffectsPanel:recursiveGetChildById('floorFading'):setEnabled(fadeMode) end }, floorFading = { value = 500, action = function(value, options, controller, panels, extraWidgets) - panels.graphicsPanel:recursiveGetChildById('floorFading'):setText(string.format('Floor Fading: %s ms', value)) + panels.graphicsEffectsPanel:recursiveGetChildById('floorFading'):setText(string.format('Floor Fading: %s ms', value)) panels.gameMapPanel:setFloorFading(tonumber(value)) end }, @@ -242,7 +242,7 @@ return { if g_game.isUsingProtobuf() then value = true elseif g_app.isEncrypted() then - local asyncWidget = panels.generalPanel:recursiveGetChildById('asyncTxtLoading') + local asyncWidget = panels.graphicsPanel:recursiveGetChildById('asyncTxtLoading') asyncWidget:setEnabled(false) asyncWidget:setChecked(false) return @@ -260,7 +260,7 @@ return { value = value / 2 end g_app.setCreatureInformationScale(math.max(value + 0.5, 1)) - panels.consolePanel:recursiveGetChildById('creatureInformationScale'):setText(string.format( + panels.interfaceHUD:recursiveGetChildById('creatureInformationScale'):setText(string.format( 'Creature Information Scale: %sx', math.max(value + 0.5, 1))) end }, @@ -273,7 +273,7 @@ return { value = value / 2 end g_app.setStaticTextScale(math.max(value + 0.5, 1)) - panels.consolePanel:recursiveGetChildById('staticTextScale'):setText(string.format('Message Scale: %sx', + panels.interfaceHUD:recursiveGetChildById('staticTextScale'):setText(string.format('Message Scale: %sx', math.max(value + 0.5, 1))) end }, @@ -286,7 +286,7 @@ return { value = value / 2 end g_app.setAnimatedTextScale(math.max(value + 0.5, 1)) - panels.consolePanel:recursiveGetChildById('animatedTextScale'):setText( + panels.interfaceHUD:recursiveGetChildById('animatedTextScale'):setText( tr('Animated Message Scale: %sx', math.max(value + 0.5, 1))) end }, @@ -332,14 +332,14 @@ return { value = 100, action = function(value, options, controller, panels, extraWidgets) g_client.setEffectAlpha(value / 100) - panels.consolePanel:recursiveGetChildById('setEffectAlphaScroll'):setText(tr('Opacity Effect: %s%%', value)) + panels.graphicsEffectsPanel:recursiveGetChildById('setEffectAlphaScroll'):setText(tr('Opacity Effect: %s%%', value)) end }, setMissileAlphaScroll = { value = 100, action = function(value, options, controller, panels, extraWidgets) g_client.setMissileAlpha(value / 100) - panels.consolePanel:recursiveGetChildById('setMissileAlphaScroll'):setText(tr('Opacity Missile: %s%%', value)) + panels.graphicsEffectsPanel:recursiveGetChildById('setMissileAlphaScroll'):setText(tr('Opacity Missile: %s%%', value)) end }, distFromCenScrollbar = { diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index ac3859dab5..1d1b7a0030 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -2,13 +2,78 @@ local options = dofile("data_options") local panels = { generalPanel = nil, - controlPanel = nil, - consolePanel = nil, graphicsPanel = nil, soundPanel = nil, - gameMapPanel = nil + gameMapPanel = nil, + graphicsEffectsPanel = nil, + interfaceHUD = nil, + interface = nil, + misc = nil, + miscHelp = nil } - +-- LuaFormatter off +local buttons = {{ + + text = "Controls", + icon = "/images/icons/icon_controls", + open = "generalPanel" + --[[ subCategories = {{ + text = "General Hotkeys", + open = "generalPanel" + }, { + text = "Action Bar Hotkeys", + open = "Action_Bar_Hotkeys" + }, { + text = "Custom Hotkeys", + open = "Custom_Hotkeys" + }} ]] +}, { + 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, @@ -36,9 +101,9 @@ local function toggleOption(key) end local function setupComboBox() - local crosshairCombo = panels.generalPanel:recursiveGetChildById('crosshair') + local crosshairCombo = panels.interface:recursiveGetChildById('crosshair') local antialiasingModeCombobox = panels.graphicsPanel:recursiveGetChildById('antialiasingMode') - local floorViewModeCombobox = panels.graphicsPanel:recursiveGetChildById('floorViewMode') + local floorViewModeCombobox = panels.graphicsEffectsPanel:recursiveGetChildById('floorViewMode') for k, v in pairs({ { 'Disabled', 'disabled' }, { 'Default', 'default' }, { 'Full', 'full' } }) do crosshairCombo:addOption(v[1], v[2]) @@ -106,28 +171,32 @@ function controller:onInit() extraWidgets.audioButton = modules.client_topmenu.addTopRightToggleButton('audioButton', tr('Audio'), '/images/topbuttons/button_mute_up', function() toggleOption('enableAudio') end) - panels.generalPanel = g_ui.loadUI('general') - panels.controlPanel = g_ui.loadUI('control') - panels.consolePanel = g_ui.loadUI('console') - panels.graphicsPanel = g_ui.loadUI('graphics') - panels.soundPanel = g_ui.loadUI('audio') + panels.generalPanel = g_ui.loadUI('styles/controls/general',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() - self.ui.optionsTabBar:setContentWidget(self.ui.optionsTabContent) - self.ui.optionsTabBar:addTab(tr('Options'), panels.generalPanel, '/images/icons/icon_options') - self.ui.optionsTabBar:addTab(tr('Controls'), panels.controlPanel, '/images/icons/icon_controls') - self.ui.optionsTabBar:addTab(tr('Interface'), panels.consolePanel, '/images/icons/icon_interface') - self.ui.optionsTabBar:addTab(tr('Graphics'), panels.graphicsPanel, '/images/icons/icon_graphics') - self.ui.optionsTabBar:addTab(tr('Sound'), panels.soundPanel, '/images/icons/icon_sound') + configureCharacterCategories() addEvent(setup) end function controller:onTerminate() extraWidgets.optionsButton:destroy() extraWidgets.audioButton:destroy() - panels = nil - extraWidgets = nil + panels = {} + extraWidgets = {} + buttons = {} end function setOption(key, value, force) @@ -146,7 +215,7 @@ function setOption(key, value, force) -- change value for keybind updates - for _, panel in pairs(controller.ui.optionsTabBar:getTabsPanel()) do + for _, panel in pairs(panels) do local widget = panel:recursiveGetChildById(key) if widget then if widget:getStyle().__class == 'UICheckBox' then @@ -190,23 +259,296 @@ end function toggle() if controller.ui:isVisible() then hide() - else - show() + 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() end function addTab(name, panel, icon) - controller.ui.optionsTabBar:addTab(name, panel, icon) + print("to prevent the error use Ex = g_ui.loadUI('option_healthcircle',modules.client_options:getPanel()) ") end function removeTab(v) - if type(v) == 'string' then - v = controller.ui.optionsTabBar:getTab(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 + + 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 + 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) + 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 + }) + 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 - controller.ui.optionsTabBar:removeTab(v) +function addSubcategoryToCategory(categoryText, newSubcategory) + addButtonToCategory(categoryText, newSubcategory) end -function addButton(name, func, icon) - controller.ui.optionsTabBar:addButton(name, func, icon) +function getPanel() + return controller.ui.optionsTabContent end diff --git a/modules/client_options/options.otui b/modules/client_options/options.otui index 3cc7e01b8a..cf930b11a5 100644 --- a/modules/client_options/options.otui +++ b/modules/client_options/options.otui @@ -1,3 +1,58 @@ +OptionsCategory < UIWidget + size: 115 22 + image-source: /images/game/actionbar/1pixel-down-frame + image-border: 5 + UIWidget + id: Button + size: 115 20 + anchors.top: parent.top + anchors.left: parent.left + margin-left: 1 + margin-top: 1 + image-source: /images/ui/button-grey-up + image-border: 5 + opacity: 1.0 + $pressed: + image-source: /images/ui/button-grey-down + $checked: + image-source: /images/ui/button-grey-down + UIWidget + id: Icon + size: 13 13 + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + margin-left: 10 + phantom: true + $checked: + margin-left: 11 + margin-top: 1 + $!checked: + margin-left: 10 + margin-top: 0 + Label + id: Title + anchors.left: Icon.right + anchors.verticalCenter: Icon.verticalCenter + margin-left: 10 + text-align: center + text-auto-resize: true + !text: tr('General Stats') + color: #ffffff + font: cipsoftFont + $checked: + text-offset: 12 10 + $!checked: + text-offset: 0 0 + UIWidget + id: Arrow + size: 7 7 + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + margin-right: 5 + phantom: true + image-source: /images/ui/icon-arrow7x7-down + visible: false + OptionCheckBox < QtCheckBox anchors.left: parent.left anchors.right: parent.right @@ -56,33 +111,45 @@ OptionScaleScrollMarked < Label @onValueChange: | modules.client_options.setOption(self:getParent():getId(), self:getValue()) -MiniQtWindow +MainWindow id: optionsWindow - size: 685 530 + size: 686 534 anchors.centerIn: parent visible: false - draggable: false + draggable: true + icon-rect: 4 4 16 16 + + image-source: /images/ui/window_new + image-border: 4 + image-border-top: 16 + image-border-bottom: 4 + &minimizedHeight: 17 + draggable: true + $on: + image-border-bottom: 2 @onEnter: modules.client_options.hide() @onEscape: modules.client_options.hide() Label !text: tr('Options') font: verdana-11px-antialised - text-offset: 0 2 + margin-top: -35 text-align: top anchors.top: parent.top - anchors.bottom: parent.bottom + anchors.left: parent.left anchors.right: parent.right opacity: 0.5 - TabBarQtVertical + UIWidget id: optionsTabBar anchors.top: parent.top anchors.left: parent.left - margin-left: 16 - margin-top: 29 + margin-left: 1 + margin-top: -10 + image-border: 3 + image-source: /images/ui/2pixel_up_frame_borderimage_dark size: 128 453 QtPanel @@ -92,7 +159,7 @@ MiniQtWindow anchors.right: parent.right anchors.bottom: optionsTabBar.bottom margin-left: 10 - margin-right: 10 + HorizontalSeparator anchors.left: optionsTabBar.left @@ -106,7 +173,7 @@ MiniQtWindow !text: tr('Ok') size: 64 20 anchors.right: parent.right - anchors.bottom: parent.bottom - margin-bottom: 10 + anchors.top: prev.bottom + margin-top: 10 margin-right: 10 @onClick: modules.client_options.hide() diff --git a/modules/client_options/styles/controls/general.otui b/modules/client_options/styles/controls/general.otui new file mode 100644 index 0000000000..15fa6d23c0 --- /dev/null +++ b/modules/client_options/styles/controls/general.otui @@ -0,0 +1,140 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 22 + + OptionCheckBoxMarked + id: showPing + !text: tr('Show connection ping') + !tooltip: tr('Display connection speed to the server (milliseconds)') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + height: 22 + margin-top: 7 + OptionCheckBox + id: classicControl + !text: tr('Classic control') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: autoChaseOverride + !text: tr('Allow auto chase override') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: moveStack + !text: tr('Move stacks directly') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: smartWalk + !text: tr('Enable smart walking') + !tooltip: tr('Will detect when to use diagonal step based on the\nkeys you are pressing') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: preciseControl + !text: tr('Enable precise control') + !tooltip: tr('You will have more precision over the character walking,\nbut it can feel more abrupt or unnatural') + @onCheckChange: g_game.setScheduleLastWalk(not self:isChecked()) + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: openMaximized + !text: tr('Open containers maximized') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: displayText + !text: tr('Display text messages') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionScaleScroll + id: turnDelay + !text: tr('Turn delay: 30ms') + anchors.fill: parent + &minimumScrollValue: 30 + &maximumScrollValue: 250 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('turnDelay') + self:setText(tr('Turn delay: %dms', value)) + + SmallReversedQtPanel + id: hotkeyDelay_label + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionScaleScroll + id: hotkeyDelay + !text: tr('Hotkey delay: 30ms') + anchors.fill: parent + &minimumScrollValue: 30 + &maximumScrollValue: 250 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('hotkeyDelay') + self:setText(tr('Hotkey delay: %dms', value)) + + QtButton + id: hotkeysButton + !text: tr('Hotkeys Manager') + @onClick: modules.game_hotkeys.show() + anchors.top: prev.bottom + anchors.left: parent.left + margin-top: 12 + + size: 120 20 + diff --git a/modules/client_options/styles/graphics/effects.otui b/modules/client_options/styles/graphics/effects.otui new file mode 100644 index 0000000000..68cc881aec --- /dev/null +++ b/modules/client_options/styles/graphics/effects.otui @@ -0,0 +1,129 @@ +UIWidget + anchors.fill: parent + visible: false + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + + height: 60 + + OptionCheckBox + id: enableLights + !text: tr('Enable lights') + + OptionScaleScroll + id: ambientLight + anchors.top: prev.bottom + &minimumScrollValue: 0 + &maximumScrollValue: 100 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('ambientLight') + self:setText(string.format('Ambient light: %s%%', value)) + + OptionScaleScroll + id: shadowFloorIntensity + anchors.top: prev.bottom + &minimumScrollValue: 0 + &maximumScrollValue: 100 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('shadowFloorIntensity') + self:setText(string.format('Floor Shadowing Intensity: %s%%', value)) + + OptionScaleScroll + id: floorFading + anchors.top: prev.bottom + &minimumScrollValue: 0 + &maximumScrollValue: 1000 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('floorFading') + self:setText(tr('Floor Fading: %s ms', value)) + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 32 + + Label + !text: 'Floor View Mode:' + anchors.left: parent.left + margin-left: 18 + color: #c0c0c0ff + anchors.verticalCenter: parent.verticalCenter + + QtComboBox + id: floorViewMode + width: 180 + margin-left: 10 + anchors.verticalCenter: prev.verticalCenter + anchors.left: prev.right + mouse-scroll: false + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: drawEffectOnTop + !text: tr('Draw Effect On Top') + !tooltip: tr('Draw effect after drawing the entire floor.') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: limitVisibleDimension + !text: tr('Limit Visible Dimension') + !tooltip: tr('The limit is based on your maximum range.') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: floatingEffect + !text: 'Draw Floating Effects' + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionScaleScroll + id: setEffectAlphaScroll + anchors.fill: parent + &minimumScrollValue: 10 + &maximumScrollValue: 100 + &scrollSize: 21 + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionScaleScroll + id: setMissileAlphaScroll + anchors.fill: parent + &minimumScrollValue: 10 + &maximumScrollValue: 100 + &scrollSize: 21 diff --git a/modules/client_options/styles/graphics/graphics.otui b/modules/client_options/styles/graphics/graphics.otui new file mode 100644 index 0000000000..111f5c7ed2 --- /dev/null +++ b/modules/client_options/styles/graphics/graphics.otui @@ -0,0 +1,113 @@ +UIWidget + anchors.fill: parent + visible: false + + Label + !text: 'Antialiasing Mode:' + anchors.left: parent.left + margin-left: 18 + color: #c0c0c0ff + anchors.top: parent.top + + QtComboBox + id: antialiasingMode + width: 180 + margin-left: 10 + anchors.verticalCenter: prev.verticalCenter + anchors.left: prev.right + mouse-scroll: false + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: fullscreen + !text: 'Full Screen Mode' + !tooltip: 'Ctrl+Shift+F' + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 5 + height:55 + + OptionCheckBoxMarked + id: vsync + !text: tr('V-Sync') + !tooltip: tr('Limits your fps based on monitor refresh rate') + + + OptionCheckBoxMarked + id: showFps + !tooltip: tr('Show frame rate') + !text: tr('Show frame rate') + anchors.top: prev.bottom + + OptionScaleScroll + id: backgroundFrameRate + !text: tr('Game framerate limit: %s', 'max') + anchors.top: prev.bottom + margin-top: 5 + &minimumScrollValue: 10 + &maximumScrollValue: 201 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('backgroundFrameRate') + local text = value + if value <= 0 or value >= 201 then + text = 'max' + end + + self:setText(tr('Game framerate limit: %s', text)) + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: optimizeFps + !text: tr('Optimize FPS') + !tooltip: tr('Try to optimize when the frame rate is below 60. VISUAL PROBLEMS MAY OCCUR') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: forceEffectOptimization + !text: tr('Force Effect Optimization') + !tooltip: tr('Will avoid drawing effects on certain occasions.') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBoxMarked + id: asyncTxtLoading + !text: tr('Async texture loading') + !tooltip: tr('This option makes textures load asynchronously and uses less RAM.') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: dontStretchShrink + !text: 'Don\'t stretch/shrink Game Window' \ No newline at end of file diff --git a/modules/client_options/styles/interface/HUD.otui b/modules/client_options/styles/interface/HUD.otui new file mode 100644 index 0000000000..d66f90cbd8 --- /dev/null +++ b/modules/client_options/styles/interface/HUD.otui @@ -0,0 +1,77 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + + height: 22 + + OptionCheckBox + id: displayNames + !text: tr('Display creature names') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: displayHealth + !text: tr('Display creature health bars') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: displayMana + !text: tr('Display player mana bar') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + height: 22 + margin-top: 7 + OptionScaleScroll + id: creatureInformationScale + anchors.fill: parent + &minimumScrollValue: 1 + &maximumScrollValue: 9 + &scrollSize: 21 + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionScaleScroll + id: staticTextScale + anchors.fill: parent + &minimumScrollValue: 1 + &maximumScrollValue: 9 + &scrollSize: 21 + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionScaleScroll + id: animatedTextScale + anchors.fill: parent + &minimumScrollValue: 1 + &maximumScrollValue: 9 + &scrollSize: 21 + diff --git a/modules/client_options/styles/interface/console.otui b/modules/client_options/styles/interface/console.otui new file mode 100644 index 0000000000..4d5a634b5e --- /dev/null +++ b/modules/client_options/styles/interface/console.otui @@ -0,0 +1,90 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 22 + + OptionCheckBox + id: showInfoMessagesInConsole + !text: tr('Show info messages') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showEventMessagesInConsole + !text: tr('Show event messages') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showStatusMessagesInConsole + !text: tr('Show status messages') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showOthersStatusMessagesInConsole + !text: tr('Show others status messages in console') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showTimestampsInConsole + !text: tr('Show timestamps') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showLevelsInConsole + !text: tr('Show levels') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showPrivateMessagesInConsole + !text: tr('Show private messages') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showPrivateMessagesOnScreen + !text: tr('Show private messages on screen') + diff --git a/modules/client_options/styles/interface/interface.otui b/modules/client_options/styles/interface/interface.otui new file mode 100644 index 0000000000..bddc74b729 --- /dev/null +++ b/modules/client_options/styles/interface/interface.otui @@ -0,0 +1,80 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 22 + + OptionCheckBox + id: enableHighlightMouseTarget + !text: tr('Highlight mouse target') + + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showLeftPanel + !text: tr('Show left panel') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showRightExtraPanel + !text: tr('Show an extra right panel') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 22 + + OptionCheckBox + id: showActionbar + !text: tr('Show action bar') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + height: 22 + margin-top: 5 + + OptionCheckBoxMarked + id: showSpellGroupCooldowns + !text: tr('Show spell group cooldowns') + !tooltip: tr('Can be enabled only in version 8.7x or higher') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 32 + + Label + !text: 'Crosshair:' + anchors.left: parent.left + margin-left: 18 + color: #c0c0c0ff + anchors.verticalCenter: parent.verticalCenter + + QtComboBox + id: crosshair + width: 120 + margin-left: 10 + anchors.verticalCenter: prev.verticalCenter + anchors.left: prev.right + mouse-scroll: false \ No newline at end of file diff --git a/modules/client_options/styles/misc/help.otui b/modules/client_options/styles/misc/help.otui new file mode 100644 index 0000000000..784cefa5b3 --- /dev/null +++ b/modules/client_options/styles/misc/help.otui @@ -0,0 +1,44 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 60 + + QtButton + !text: tr('Wiki') + anchors.left: parent.left + anchors.top: parent.top + size: 130 20 + margin-bottom: 10 + margin-right: 10 + @onClick: g_platform.openUrl("https://github.com/mehah/otclient/wiki") + + QtButton + !text: tr('Info') + size: 130 20 + margin-top: 5 + + anchors.top: prev.bottom + anchors.left: parent.left + + @onClick: g_platform.openUrl("https://github.com/mehah/otclient/wiki") + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + height: 33 + margin-top: 5 + + QtButton + !text: tr('Clear Cache') + size: 130 20 + margin-bottom: 10 + margin-right: 10 + anchors.left: parent.left + anchors.top: parent.top + @onClick: g_platform.openUrl("https://github.com/mehah/otclient/wiki") + diff --git a/modules/client_options/styles/misc/misc.otui b/modules/client_options/styles/misc/misc.otui new file mode 100644 index 0000000000..a2144ce31c --- /dev/null +++ b/modules/client_options/styles/misc/misc.otui @@ -0,0 +1,12 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 22 + + OptionCheckBox + id: autoChaseOverride + !text: tr('Allow auto chase override') \ No newline at end of file diff --git a/modules/client_options/styles/sound/audio.otui b/modules/client_options/styles/sound/audio.otui new file mode 100644 index 0000000000..5af79771e1 --- /dev/null +++ b/modules/client_options/styles/sound/audio.otui @@ -0,0 +1,36 @@ +UIWidget + anchors.fill: parent + visible: false + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: parent.top + height: 22 + + OptionCheckBox + id: enableAudio + !text: tr('Enable audio') + + SmallReversedQtPanel + anchors.left: parent.left + anchors.right: parent.right + anchors.top: prev.bottom + margin-top: 7 + height: 44 + + OptionCheckBox + id: enableMusicSound + !text: tr('Enable music sound') + + OptionScaleScroll + id: musicSoundVolume + margin-top: 5 + anchors.top: prev.bottom + anchors.left: parent.left + anchors.right: parent.right + &minimumScrollValue: 1 + &maximumScrollValue: 100 + &scrollSize: 21 + @onSetup: | + local value = modules.client_options.getOption('musicSoundVolume') + self:setText(tr('Music volume: %d', value)) diff --git a/modules/game_actionbar/game_actionbar.lua b/modules/game_actionbar/game_actionbar.lua index d2b4dc4e21..2dbde86cfc 100644 --- a/modules/game_actionbar/game_actionbar.lua +++ b/modules/game_actionbar/game_actionbar.lua @@ -89,17 +89,9 @@ function terminate() end function online() - - if g_game.getFeature(GameSpellList) then - local console = modules.game_cooldown.cooldownWindow - if console then - console:addAnchor(AnchorTop, actionBar:getId(), AnchorBottom) - end - else - local console = modules.game_console.consolePanel - if console then - console:addAnchor(AnchorTop, actionBar:getId(), AnchorBottom) - end + local console = modules.game_cooldown.cooldownWindow + if console then + console:addAnchor(AnchorTop, actionBar:getId(), AnchorBottom) end actionBarPanel:destroyChildren() addEvent(function() diff --git a/modules/game_cooldown/cooldown.lua b/modules/game_cooldown/cooldown.lua index da3b42cfc6..b3fda07688 100644 --- a/modules/game_cooldown/cooldown.lua +++ b/modules/game_cooldown/cooldown.lua @@ -277,6 +277,11 @@ function onSpellGroupCooldown(groupId, duration) end function setSpellGroupCooldownsVisible(visible) + if not g_game.getFeature(GameSpellList) then + cooldownWindow:hide() + cooldownWindow:setHeight(10) + return + end if visible then cooldownWindow:setHeight(30) cooldownWindow:show() diff --git a/modules/game_healthcircle/game_healthcircle.lua b/modules/game_healthcircle/game_healthcircle.lua index 4bea172863..e0b4b2bacf 100644 --- a/modules/game_healthcircle/game_healthcircle.lua +++ b/modules/game_healthcircle/game_healthcircle.lua @@ -512,8 +512,7 @@ opacityScrollbar = nil function addToOptionsModule() -- Add to options module - optionPanel = g_ui.loadUI('option_healthcircle') - modules.client_options.addTab('HP/MP Circle', optionPanel, '/images/icons/icon_health') + optionPanel = g_ui.loadUI('option_healthcircle',modules.client_options:getPanel()) -- UI values healthCheckBox = optionPanel:recursiveGetChildById('healthCheckBox') @@ -563,6 +562,7 @@ function addToOptionsModule() distFromCenScrollbar:setValue(distanceFromCenter) opacityScrollbar:setText(tr('Opacity') .. ': ' .. opacityCircle) opacityScrollbar:setValue(opacityCircle * 100) + modules.client_options.addButton("Interface", "HP/MP Circle", optionPanel) end function updateStatsBar() @@ -595,6 +595,6 @@ function destroyOptionsModule() chooseStatsBarDimension = nil chooseStatsBarPlacement = nil - modules.client_options.removeTab('HP/MP Circle') + modules.client_options.removeButton("Interface", "HP/MP Circle") optionPanel = nil end diff --git a/modules/game_healthcircle/option_healthcircle.otui b/modules/game_healthcircle/option_healthcircle.otui index d4022c562b..511abfec3e 100644 --- a/modules/game_healthcircle/option_healthcircle.otui +++ b/modules/game_healthcircle/option_healthcircle.otui @@ -1,4 +1,6 @@ -Panel +UIWidget + anchors.fill: parent + visible: false SmallReversedQtPanel anchors.left: parent.left anchors.right: parent.right diff --git a/modules/game_screenshot/game_screenshot.lua b/modules/game_screenshot/game_screenshot.lua index 0007c141c9..09536df3ff 100644 --- a/modules/game_screenshot/game_screenshot.lua +++ b/modules/game_screenshot/game_screenshot.lua @@ -43,7 +43,6 @@ local AutoScreenshotEvents = { -- LuaFormatter on -- @ widget -local screenshotScheduleEvent = nil local optionPanel = nil -- @ -- @ variables @@ -61,18 +60,17 @@ end function screenshotController:onTerminate() destroyOptionsModule() - if screenshotScheduleEvent then - removeEvent(screenshotScheduleEvent) - screenshotScheduleEvent = nil - end + ScreenshotType = {} + checkboxes = {} + TypeScreenshots = {} + AutoScreenshotEvents = {} end function screenshotController:onGameStart() if g_game.getClientVersion() < 1180 then return end - optionPanel = g_ui.loadUI('game_screenshot') - modules.client_options.addTab('Screenshot', optionPanel, '/images/icons/icon_misc') + optionPanel = g_ui.loadUI('game_screenshot',modules.client_options:getPanel()) for _, screenshotEvent in ipairs(AutoScreenshotEvents) do local label = g_ui.createWidget("ScreenshotType", optionPanel.allCheckBox) @@ -84,6 +82,7 @@ function screenshotController:onGameStart() screenshotEvent.currentBoolean = settings end + optionPanel:recursiveGetChildById("enableScreenshots"):setChecked(g_settings.getBoolean("enableScreenshots")) optionPanel:recursiveGetChildById("onlyCaptureGameWindow"):setChecked(g_settings.getBoolean("onlyCaptureGameWindow")) if not g_resources.directoryExists(autoScreenshotDir) then @@ -94,18 +93,17 @@ function screenshotController:onGameStart() onTakeScreenshot = onScreenShot }) optionPanel:recursiveGetChildById("keepBlacklog"):disable() -- no compatibility 11/07/24 - + + modules.client_options.addButton("Misc.", "Screenshot", optionPanel) end function screenshotController:onGameEnd() if g_game.getClientVersion() >= 1180 then g_settings.set("onlyCaptureGameWindow",optionPanel:recursiveGetChildById("onlyCaptureGameWindow"):isChecked()) + g_settings.set("enableScreenshots",optionPanel:recursiveGetChildById("enableScreenshots"):isChecked()) destroyOptionsModule() end - if screenshotScheduleEvent then - removeEvent(screenshotScheduleEvent) - screenshotScheduleEvent = nil - end + for _, screenshotEvent in ipairs(AutoScreenshotEvents) do local labelScreenshotEvent = screenshotEvent.label:gsub("%s+", "") g_settings.set(labelScreenshotEvent, screenshotEvent.currentBoolean) @@ -150,7 +148,7 @@ end -- LuaFormatter on function destroyOptionsModule() - modules.client_options.removeTab('Screenshot') + modules.client_options.removeButton("Misc.","Screenshot") if optionPanel and not optionPanel:isDestroyed() then optionPanel:destroy() optionPanel = nil @@ -178,21 +176,17 @@ function takeScreenshot(name) return end - if screenshotScheduleEvent then - removeEvent(screenshotScheduleEvent) - screenshotScheduleEvent = nil - end - - screenshotScheduleEvent = scheduleEvent(function() + screenshotController:scheduleEvent(function() if optionPanel:recursiveGetChildById("onlyCaptureGameWindow"):isChecked() then g_app.doMapScreenshot(name) else g_app.doScreenshot(name) end - end, 50) + end, 50, 'screenshotScheduleEvent') end function OpenFolder() local directory = g_resources.getWriteDir():gsub("[/\\]+", "\\") .. autoScreenshotDirName g_platform.openDir(directory) end + diff --git a/modules/game_screenshot/game_screenshot.otui b/modules/game_screenshot/game_screenshot.otui index a71ef8387f..57a71a2c13 100644 --- a/modules/game_screenshot/game_screenshot.otui +++ b/modules/game_screenshot/game_screenshot.otui @@ -1,4 +1,6 @@ -Panel +UIWidget + anchors.fill: parent + visible: false SmallReversedQtPanel anchors.left: parent.left anchors.right: parent.right @@ -34,7 +36,7 @@ Panel id: enableScreenshots !text: tr('Enable Auto Screenshots') !tooltip: tr('Enable this option to save screenshots of the most important\nmoments of your Tibia career! Whenever one of the events you\nhave selected takes place, a screenshot will be taken\nautomatically.\n\nThe following events can be selected to trigger an auto screenshot:\n\n- Level Up: Your character has reached the next level\n- Skill Up: You advanced in one of your skills (e.g. Magic Level\nor Sword Fighting)\n- Achievement: You earned an achievement, either while\nplaying or upon login\n- Bestiary Entry Unlocked: You unlocked new information\nabout a creature in the Bestiary\n- Bestiary Entry Completed: You unlocked all information about\na creature in the Bestiary\n- Treasure Found: You received some reward from a container\nfor solving a quest or a riddle\n- Valuable Loot: You just found some loot which you have\nmarked in the Drop Tracker\n- Boss Defeated: You defeated a boss monster, either alone or\ntogether with other players, and are entitled to loot it\n- Death PvE: You were just killed by some creature (PvE)\n- Death PvP: You were just killed by another player (PvP)\n- Player Kill: You defeated another player\n- Player Killer Assist: You assisted the killing of another player\n- Player Attacking: Another player just started to attack you\n- Highest Damage Dealt: You dealt a new all-time high damage\non a foe. To see or reset your current all-time high, check\nthe Impact Analyser\n- Highest Healing Done: You healed someone with a new all-\ntime high healing value. To see or reset your current all-time\nhigh, check the Impact Analyser\n- Low Health: You have reached a threshold of deep red\nhealth Copy') - checked: true + checked: false Label !text: tr('Select all events that sould trigger auto Screenshots:')