options.lua

main 450 lines · 15 KB Raw
Alex Alex Commit Client Upload Part 2 19/10/2026 00:06
1local defaultOptions = {
2 layout = DEFAULT_LAYOUT, -- set in init.lua
3 vsync = true,
4 showFps = true,
5 showPing = true,
6 fullscreen = false,
7 classicView = false,--not g_app.isMobile(),
8 cacheMap = g_app.isMobile(),
9 classicControl = not g_app.isMobile(),
10 smartWalk = true,
11 autoChaseOverride = true,
12 showStatusMessagesInConsole = true,
13 showEventMessagesInConsole = true,
14 showInfoMessagesInConsole = true,
15 showTimestampsInConsole = true,
16 showLevelsInConsole = true,
17 showPrivateMessagesInConsole = true,
18 showPrivateMessagesOnScreen = true,
19 rightPanels = 4,
20 leftPanels = 0,
21 containerPanel = 8,
22 backgroundFrameRate = 60,
23 enableAudio = true,
24 enableMusicSound = true,
25 musicSoundVolume = 50,
26 botSoundVolume = 100,
27 enableLights = true,
28 floorFading = 500,
29 crosshair = 0,
30 ambientLight = 36,
31 optimizationLevel = 1,
32 displayNames = true,
33 displayShadows = true,
34 displayHealth = true,
35 displayMana = false,
36 displayHealthOnTop = false,
37 showHealthManaCircle = false,
38 hidePlayerBars = true,
39 highlightThingsUnderCursor = false,
40 topHealtManaBar = true,
41 displayText = true,
42 dontStretchShrink = false,
43 turnDelay = 30,
44 hotkeyDelay = 30,
45 animatedTextScale = 0,
46 missilesOpacity = 0,
47 effectsOpacity = 0,
48 wsadWalking = false,
49 walkFirstStepDelay = 200,
50 walkTurnDelay = 100,
51 walkStairsDelay = 50,
52 walkTeleportDelay = 200,
53 walkCtrlTurnDelay = 150,
54
55 actionBar = true
56}
57
58local optionsWindow
59--local optionsButton
60optionsTabBar = nil
61local options = {}
62local extraOptions = {}
63local generalPanel
64local interfacePanel
65local consolePanel
66local graphicsPanel
67local soundPanel
68extrasPanel = nil
69local audioButton
70
71function init()
72 -- Clear the retired Dash option, including values saved by older clients.
73 g_settings.set('dash', false)
74 g_game.setMaxPreWalkingSteps(1)
75 for k,v in pairs(defaultOptions) do
76 g_settings.setDefault(k, v)
77 options[k] = v
78 end
79 for _, v in ipairs(g_extras.getAll()) do
80 extraOptions[v] = g_extras.get(v)
81 g_settings.setDefault("extras_" .. v, extraOptions[v])
82 end
83
84
85 optionsWindow = g_ui.displayUI('options')
86 optionsWindow:hide()
87
88 optionsTabBar = optionsWindow:getChildById('optionsTabBar')
89 optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent'))
90
91 g_keyboard.bindKeyDown('Ctrl+Shift+F', function() toggleOption('fullscreen') end)
92 g_keyboard.bindKeyDown('Ctrl+N', toggleDisplays)
93
94 generalPanel = g_ui.loadUI('game')
95 optionsTabBar:addTab(tr('Game'), generalPanel, '/modules/client_options/settings/iconpanel')
96
97 interfacePanel = g_ui.loadUI('interface')
98 optionsTabBar:addTab(tr('Interface'), interfacePanel, '/modules/client_options/settings/iconpanel')
99
100 consolePanel = g_ui.loadUI('console')
101 optionsTabBar:addTab(tr('Console'), consolePanel, '/modules/client_options/settings/iconpanel')
102
103 graphicsPanel = g_ui.loadUI('graphics')
104 optionsTabBar:addTab(tr('Graphics'), graphicsPanel, '/modules/client_options/settings/iconpanel')
105
106 audioPanel = g_ui.loadUI('audio')
107 optionsTabBar:addTab(tr('Audio'), audioPanel, '/modules/client_options/settings/iconpanel')
108
109 extrasPanel = g_ui.createWidget('OptionPanel')
110 for _, v in ipairs(g_extras.getAll()) do
111 local extrasButton = g_ui.createWidget('OptionCheckBox')
112 extrasButton:setId(v)
113 extrasButton:setText(g_extras.getDescription(v))
114 extrasPanel:addChild(extrasButton)
115 end
116 --[[if not g_game.getFeature(GameNoDebug) and not g_app.isMobile() then
117 optionsTabBar:addTab(tr('Extras'), extrasPanel, '/images/optionstab/extras')
118 end]]--
119
120 --optionsButton = modules.client_topmenu.addLeftButton('optionsButton', tr('Options'), '/images/topbuttons/options', toggle)
121 audioButton = modules.client_topmenu.addLeftButton('audioButton', tr('Audio'), '/images/topbuttons/audio', function() toggleOption('enableAudio') end)
122 audioButton:hide()
123 if g_app.isMobile() then
124 audioButton:hide()
125 end
126
127 addEvent(function() setup() end)
128
129 connect(g_game, { onGameStart = online,
130 onGameEnd = offline })
131end
132
133function terminate()
134 disconnect(g_game, { onGameStart = online,
135 onGameEnd = offline })
136
137 g_keyboard.unbindKeyDown('Ctrl+Shift+F')
138 g_keyboard.unbindKeyDown('Ctrl+N')
139 optionsWindow:destroy()
140 --optionsButton:destroy()
141 audioButton:destroy()
142end
143
144function setup()
145 -- load options
146 for k,v in pairs(defaultOptions) do
147 if type(v) == 'boolean' then
148 setOption(k, g_settings.getBoolean(k), true)
149 elseif type(v) == 'number' then
150 setOption(k, g_settings.getNumber(k), true)
151 elseif type(v) == 'string' then
152 setOption(k, g_settings.getString(k), true)
153 end
154 end
155
156 for _, v in ipairs(g_extras.getAll()) do
157 g_extras.set(v, g_settings.getBoolean("extras_" .. v))
158 local widget = extrasPanel:recursiveGetChildById(v)
159 if widget then
160 widget:setChecked(g_extras.get(v))
161 end
162 end
163
164 if g_game.isOnline() then
165 online()
166 end
167end
168
169function toggle()
170 if optionsWindow:isVisible() then
171 hide()
172 else
173 show()
174 end
175end
176
177function show()
178 optionsWindow:show()
179 optionsWindow:raise()
180 optionsWindow:focus()
181 if modules.game_console then
182 modules.game_console.manageButton('settingsButton', true)
183 end
184end
185
186function hide()
187 optionsWindow:hide()
188 if modules.game_console then
189 modules.game_console.manageButton('settingsButton', false)
190 end
191end
192
193function toggleDisplays()
194 if options['displayNames'] and options['displayHealth'] and options['displayMana'] then
195 setOption('displayNames', false)
196 elseif options['displayHealth'] then
197 setOption('displayHealth', false)
198 setOption('displayMana', false)
199 else
200 if not options['displayNames'] and not options['displayHealth'] then
201 setOption('displayNames', true)
202 else
203 setOption('displayHealth', true)
204 setOption('displayMana', true)
205 end
206 end
207end
208
209function toggleOption(key)
210 setOption(key, not getOption(key))
211end
212
213function setOption(key, value, force)
214 if extraOptions[key] ~= nil then
215 g_extras.set(key, value)
216 g_settings.set("extras_" .. key, value)
217 if key == "debugProxy" and modules.game_proxy then
218 if value then
219 modules.game_proxy.show()
220 else
221 modules.game_proxy.hide()
222 end
223 end
224 return
225 end
226
227 if modules.game_interface == nil then
228 return
229 end
230
231 if not force and options[key] == value then return end
232 local gameMapPanel = modules.game_interface.getMapPanel()
233
234 if key == 'vsync' then
235 g_window.setVerticalSync(value)
236 elseif key == 'showFps' then
237 if g_game.isOnline() then
238 modules.client_topmenu.setFpsVisible(value)
239 if modules.game_stats and modules.game_stats.ui.fps then
240 modules.game_stats.ui.fps:setVisible(value)
241 end
242 end
243 elseif key == 'showPing' then
244 modules.client_topmenu.setPingVisible(value)
245 if modules.game_stats and modules.game_stats.ui.ping then
246 modules.game_stats.ui.ping:setVisible(value)
247 end
248 elseif key == 'fullscreen' then
249 g_window.setFullscreen(value)
250 elseif key == 'enableAudio' then
251 if g_sounds ~= nil then
252 g_sounds.setAudioEnabled(value)
253 end
254 if value then
255 audioButton:setIcon('/images/topbuttons/audio')
256 else
257 audioButton:setIcon('/images/topbuttons/audio_mute')
258 end
259 elseif key == 'enableMusicSound' then
260 if g_sounds ~= nil then
261 g_sounds.getChannel(SoundChannels.Music):setEnabled(value)
262 end
263 elseif key == 'musicSoundVolume' then
264 if g_sounds ~= nil then
265 g_sounds.getChannel(SoundChannels.Music):setGain(value/100)
266 end
267 audioPanel:getChildById('musicSoundVolumeBG'):getChildById('musicSoundVolumeLabelBG'):setText(tr('%d', value))
268 local valueScroll = ((value*200)/100)
269 audioPanel:getChildById('musicSoundVolumeBG'):getChildById('musicSoundVolume'):getChildById('activeScroll'):setWidth(valueScroll)
270 elseif key == 'botSoundVolume' then
271 if g_sounds ~= nil then
272 g_sounds.getChannel(SoundChannels.Bot):setGain(value/100)
273 end
274 audioPanel:getChildById('botSoundVolumeBG'):getChildById('botSoundVolumeLabelBG'):setText(tr('%d', value))
275 local valueScroll = ((value*200)/100)
276 audioPanel:getChildById('botSoundVolumeBG'):getChildById('botSoundVolume'):getChildById('activeScroll'):setWidth(valueScroll)
277 elseif key == 'showHealthManaCircle' then
278 if modules.game_healthinfo then
279 if modules.game_healthinfo.healthCircle then
280 modules.game_healthinfo.healthCircle:setVisible(value)
281 end
282 if modules.game_healthinfo.healthCircleFront then
283 modules.game_healthinfo.healthCircleFront:setVisible(value)
284 end
285 if modules.game_healthinfo.manaCircle then
286 modules.game_healthinfo.manaCircle:setVisible(value)
287 end
288 if modules.game_healthinfo.manaCircleFront then
289 modules.game_healthinfo.manaCircleFront:setVisible(value)
290 end
291 end
292 elseif key == 'backgroundFrameRate' then
293 local text, v = value, value
294 if value <= 0 or value >= 201 then text = 'max' v = 60 end -- Limitamos a 60 FPS máximo para proteger la GPU
295 graphicsPanel:getChildById('backgroundFrameRateBG'):getChildById('backgroundFrameRateLabelBG'):setText(tr('%s', text))
296 local valueScroll = ((value*200)/201)
297 graphicsPanel:getChildById('backgroundFrameRateBG'):getChildById('backgroundFrameRate'):getChildById('activeScroll'):setWidth(valueScroll)
298 g_app.setMaxFps(v)
299 elseif key == 'enableLights' then
300 gameMapPanel:setDrawLights(value and options['ambientLight'] < 100)
301 graphicsPanel:getChildById('ambientLightBG'):getChildById('ambientLight'):setEnabled(value)
302 elseif key == 'floorFading' then
303 gameMapPanel:setFloorFading(value)
304 interfacePanel:getChildById('floorFadingBG'):getChildById('floorFadingLabelBG'):setText(tr('%s ms', value))
305 local valueScroll = ((value*200)/2000)
306 interfacePanel:getChildById('floorFadingBG'):getChildById('floorFading'):getChildById('activeScroll'):setWidth(valueScroll)
307 elseif key == 'crosshair' then
308 if value == 1 then
309 gameMapPanel:setCrosshair("")
310 elseif value == 2 then
311 gameMapPanel:setCrosshair("/images/crosshair/default.png")
312 elseif value == 3 then
313 gameMapPanel:setCrosshair("/images/crosshair/full.png")
314 end
315 elseif key == 'ambientLight' then
316 graphicsPanel:getChildById('ambientLightBG'):getChildById('ambientLightLabelBG'):setText(tr('%s%%', value))
317 gameMapPanel:setMinimumAmbientLight(value/100)
318 gameMapPanel:setDrawLights(options['enableLights'] and value < 100)
319 local valueScroll = ((value*200)/100)
320 graphicsPanel:getChildById('ambientLightBG'):getChildById('ambientLight'):getChildById('activeScroll'):setWidth(valueScroll)
321 elseif key == 'missilesOpacity' then
322 graphicsPanel:getChildById('missilesOpacityBG'):getChildById('missilesOpacityLabelBG'):setText(tr('%s%%', value))
323 local valueScroll = ((value*200)/100)
324 graphicsPanel:getChildById('missilesOpacityBG'):getChildById('missilesOpacity'):getChildById('activeScroll'):setWidth(valueScroll)
325 setMissilesOpacity(1 - value / 100)
326 elseif key == 'effectsOpacity' then
327 graphicsPanel:getChildById('effectsOpacityBG'):getChildById('effectsOpacityLabelBG'):setText(tr('%s%%', value))
328 local valueScroll = ((value*200)/100)
329 graphicsPanel:getChildById('effectsOpacityBG'):getChildById('effectsOpacity'):getChildById('activeScroll'):setWidth(valueScroll)
330 if g_map and g_map.setEffectsOpacity then
331 g_map.setEffectsOpacity(1 - value / 100)
332 end
333 elseif key == 'optimizationLevel' then
334 g_adaptiveRenderer.setLevel(value - 2)
335 elseif key == 'displayNames' then
336 gameMapPanel:setDrawNames(value)
337 elseif key == 'displayShadows' then
338 if modules.game_creatureinfo and modules.game_creatureinfo.refreshShadows then
339 scheduleEvent(function() modules.game_creatureinfo.refreshShadows(value) end, 10)
340 end
341 elseif key == 'displayHealth' then
342 gameMapPanel:setDrawHealthBars(value)
343 elseif key == 'displayMana' then
344 gameMapPanel:setDrawManaBar(value)
345 elseif key == 'displayHealthOnTop' then
346 gameMapPanel:setDrawHealthBarsOnTop(value)
347 elseif key == 'hidePlayerBars' then
348 gameMapPanel:setDrawPlayerBars(value)
349 elseif key == 'topHealtManaBar' then
350 if modules.game_healthinfo then
351 if modules.game_healthinfo.topHealthBar then
352 modules.game_healthinfo.topHealthBar:setVisible(value)
353 end
354 if modules.game_healthinfo.topManaBar then
355 modules.game_healthinfo.topManaBar:setVisible(value)
356 end
357 end
358 elseif key == 'displayText' then
359 gameMapPanel:setDrawTexts(value)
360 elseif key == 'dontStretchShrink' then
361 addEvent(function()
362 modules.game_interface.updateStretchShrink()
363 end)
364 elseif key == 'wsadWalking' then
365 if modules.game_console then
366 modules.game_console.toggleChatByOptions(value)
367 end
368 end
369
370 -- change value for keybind updates
371 for _,panel in pairs(optionsTabBar:getTabsPanel()) do
372 local widget = panel:recursiveGetChildById(key)
373 if widget then
374 if widget:getStyle().__class == 'UICheckBox' then
375 widget:setChecked(value)
376 elseif widget:getStyle().__class == 'UIScrollBar' then
377 widget:setValue(value)
378 elseif widget:getStyle().__class == 'UIComboBox' then
379 if type(value) == "string" then
380 widget:setCurrentOption(value, true)
381 break
382 end
383 if value == nil or value < 1 then
384 value = 1
385 end
386 if widget.currentIndex ~= value then
387 widget:setCurrentIndex(value, true)
388 end
389 end
390 break
391 end
392 end
393
394 g_settings.set(key, value)
395 options[key] = value
396
397 if key == 'classicView' or key == 'rightPanels' or key == 'leftPanels' or key == 'cacheMap' then
398 modules.game_interface.refreshViewMode()
399 elseif key == 'actionBar' then
400 if modules.game_menu and modules.game_menu.setHudActionBarEnabled then
401 modules.game_menu.setHudActionBarEnabled(value)
402 end
403 if modules.game_spellbar and modules.game_spellbar.setBarEnabled then
404 modules.game_spellbar.setBarEnabled(value)
405 end
406 end
407end
408
409function getOption(key)
410 return options[key]
411end
412
413function addTab(name, panel, icon)
414 optionsTabBar:addTab(name, panel, icon)
415end
416
417function addButton(name, func, icon)
418 optionsTabBar:addButton(name, func, icon)
419end
420
421-- hide/show
422
423function online()
424 setLightOptionsVisibility(not g_game.getFeature(GameForceLight))
425 audioButton:show()
426end
427
428function offline()
429 setLightOptionsVisibility(true)
430 audioButton:hide()
431end
432
433-- classic view
434
435-- graphics
436function setLightOptionsVisibility(value)
437 graphicsPanel:getChildById('enableLights'):setEnabled(value)
438 graphicsPanel:getChildById('ambientLightBG'):getChildById('ambientLightLabelBG'):setEnabled(value)
439 graphicsPanel:getChildById('ambientLightBG'):getChildById('ambientLight'):setEnabled(value)
440 interfacePanel:getChildById('floorFadingBG'):getChildById('floorFading'):setEnabled(value)
441 interfacePanel:getChildById('floorFadingLabel'):setEnabled(value)
442 interfacePanel:getChildById('floorFadingLabel2'):setEnabled(value)
443end
444
445-- Definición de la función setMissilesOpacity
446function setMissilesOpacity(opacity)
447 -- Lógica para establecer la opacidad de los misiles
448 print("Opacidad de misiles establecida a " .. opacity)
449end
450
Top