| @@ -0,0 +1,78 @@ | |||
| 1 | + | LoginLabel < Label | |
| 2 | + | anchors.left: parent.left | |
| 3 | + | anchors.right: parent.right | |
| 4 | + | font: verdana-11px-antialised | |
| 5 | + | color: #c8c8c8 | |
| 6 | + | ||
| 7 | + | LoginTextEdit < TextEdit | |
| 8 | + | anchors.left: parent.left | |
| 9 | + | anchors.right: parent.right | |
| 10 | + | height: 24 | |
| 11 | + | padding: 4 6 0 6 | |
| 12 | + | font: verdana-11px-antialised | |
| 13 | + | ||
| 14 | + | LoginPasswordEdit < PasswordTextEdit | |
| 15 | + | anchors.left: parent.left | |
| 16 | + | anchors.right: parent.right | |
| 17 | + | height: 24 | |
| 18 | + | padding: 4 6 0 6 | |
| 19 | + | font: verdana-11px-antialised | |
| 20 | + | ||
| 21 | + | StaticMainWindow | |
| 22 | + | id: enterGame | |
| 23 | + | !text: tr('Login') | |
| 24 | + | size: 300 250 | |
| 25 | + | @onEnter: EnterGame.doLogin() | |
| 26 | + | ||
| 27 | + | LoginLabel | |
| 28 | + | id: accountLabel | |
| 29 | + | !text: tr('Account') | |
| 30 | + | anchors.top: parent.top | |
| 31 | + | ||
| 32 | + | LoginTextEdit | |
| 33 | + | id: accountNameTextEdit | |
| 34 | + | anchors.top: accountLabel.bottom | |
| 35 | + | margin-top: 4 | |
| 36 | + | ||
| 37 | + | LoginLabel | |
| 38 | + | id: labelPassword | |
| 39 | + | !text: tr('Password') | |
| 40 | + | anchors.top: accountNameTextEdit.bottom | |
| 41 | + | margin-top: 12 | |
| 42 | + | ||
| 43 | + | LoginPasswordEdit | |
| 44 | + | id: accountPasswordTextEdit | |
| 45 | + | anchors.top: labelPassword.bottom | |
| 46 | + | margin-top: 4 | |
| 47 | + | ||
| 48 | + | CheckBox | |
| 49 | + | id: rememberPasswordBox | |
| 50 | + | !text: tr('Remember me') | |
| 51 | + | !tooltip: tr('Remember account and password when the client starts') | |
| 52 | + | anchors.left: parent.left | |
| 53 | + | anchors.right: parent.right | |
| 54 | + | anchors.top: accountPasswordTextEdit.bottom | |
| 55 | + | margin-top: 12 | |
| 56 | + | ||
| 57 | + | HorizontalSeparator | |
| 58 | + | id: separator | |
| 59 | + | anchors.left: parent.left | |
| 60 | + | anchors.right: parent.right | |
| 61 | + | anchors.bottom: enterGameButton.top | |
| 62 | + | margin-bottom: 10 | |
| 63 | + | ||
| 64 | + | Label | |
| 65 | + | id: serverInfoLabel | |
| 66 | + | anchors.left: parent.left | |
| 67 | + | anchors.verticalCenter: enterGameButton.verticalCenter | |
| 68 | + | font: verdana-11px-antialised | |
| 69 | + | color: #8f8f8f | |
| 70 | + | text-auto-resize: true | |
| 71 | + | ||
| 72 | + | Button | |
| 73 | + | id: enterGameButton | |
| 74 | + | !text: tr('Login') | |
| 75 | + | width: 90 | |
| 76 | + | anchors.right: parent.right | |
| 77 | + | anchors.bottom: parent.bottom | |
| 78 | + | @onClick: EnterGame.doLogin() |
| @@ -0,0 +1,17 @@ | |||
| 1 | + | Panel | |
| 2 | + | id: panelInfo | |
| 3 | + | size: 320 45 | |
| 4 | + | anchors.bottom: parent.bottom | |
| 5 | + | anchors.left: parent.left | |
| 6 | + | background-color: #00000099 | |
| 7 | + | margin-bottom: 16 | |
| 8 | + | margin-left: 40 | |
| 9 | + | ||
| 10 | + | UIWidget | |
| 11 | + | id: AccountText | |
| 12 | + | color: white | |
| 13 | + | anchors.verticalCenter: parent.verticalCenter | |
| 14 | + | anchors.left: parent.left | |
| 15 | + | margin-left: 15 | |
| 16 | + | text-auto-resize: true | |
| 17 | + | font: sono_bold_border_14 |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | UIWidget | |
| 2 | + | id: logpass | |
| 3 | + | size: 248 41 | |
| 4 | + | anchors.top: enterGame.bottom | |
| 5 | + | anchors.horizontalCenter: enterGame.horizontalCenter | |
| 6 | + | margin-top: 25 | |
| 7 | + | image-size: 248 41 | |
| 8 | + | image-source: /images/ui/continue_with_logpass.png | |
| 9 | + | @onClick: modules.logpass.show() |
| @@ -0,0 +1,44 @@ | |||
| 1 | + | MainWindow | |
| 2 | + | id: waitingWindow | |
| 3 | + | !text: tr('Waiting List') | |
| 4 | + | size: 260 180 | |
| 5 | + | @onEscape: CharacterList.cancelWait() | |
| 6 | + | ||
| 7 | + | Label | |
| 8 | + | id: infoLabel | |
| 9 | + | anchors.top: parent.top | |
| 10 | + | anchors.bottom: progressBar.top | |
| 11 | + | anchors.left: parent.left | |
| 12 | + | anchors.right: parent.right | |
| 13 | + | text-wrap: true | |
| 14 | + | ||
| 15 | + | ProgressBar | |
| 16 | + | id: progressBar | |
| 17 | + | height: 15 | |
| 18 | + | background-color: #4444ff | |
| 19 | + | anchors.bottom: timeLabel.top | |
| 20 | + | anchors.left: parent.left | |
| 21 | + | anchors.right: parent.right | |
| 22 | + | margin-bottom: 10 | |
| 23 | + | ||
| 24 | + | Label | |
| 25 | + | id: timeLabel | |
| 26 | + | anchors.bottom: separator.bottom | |
| 27 | + | anchors.left: parent.left | |
| 28 | + | anchors.right: parent.right | |
| 29 | + | margin-bottom: 10 | |
| 30 | + | ||
| 31 | + | HorizontalSeparator | |
| 32 | + | id: separator | |
| 33 | + | anchors.left: parent.left | |
| 34 | + | anchors.right: parent.right | |
| 35 | + | anchors.bottom: next.top | |
| 36 | + | margin-bottom: 10 | |
| 37 | + | ||
| 38 | + | Button | |
| 39 | + | id: buttonCancel | |
| 40 | + | !text: tr('Cancel') | |
| 41 | + | width: 64 | |
| 42 | + | anchors.right: parent.right | |
| 43 | + | anchors.bottom: parent.bottom | |
| 44 | + | @onClick: CharacterList.cancelWait() |
| @@ -0,0 +1,112 @@ | |||
| 1 | + | -- chunkname: @/modules/client_feedback/feedback.lua | |
| 2 | + | ||
| 3 | + | local feedbackWindow, textEdit, okButton, cancelButton | |
| 4 | + | local postId = 0 | |
| 5 | + | local tries = 0 | |
| 6 | + | local replyEvent | |
| 7 | + | ||
| 8 | + | function init() | |
| 9 | + | feedbackWindow = g_ui.displayUI("feedback") | |
| 10 | + | ||
| 11 | + | feedbackWindow:hide() | |
| 12 | + | ||
| 13 | + | textEdit = feedbackWindow:getChildById("text") | |
| 14 | + | okButton = feedbackWindow:getChildById("okButton") | |
| 15 | + | cancelButton = feedbackWindow:getChildById("cancelButton") | |
| 16 | + | okButton.onClick = send | |
| 17 | + | cancelButton.onClick = hide | |
| 18 | + | feedbackWindow.onEscape = hide | |
| 19 | + | end | |
| 20 | + | ||
| 21 | + | function terminate() | |
| 22 | + | feedbackWindow:destroy() | |
| 23 | + | removeEvent(replyEvent) | |
| 24 | + | end | |
| 25 | + | ||
| 26 | + | function show() | |
| 27 | + | if not Services or not Services.feedback or Services.feedback:len() < 4 then | |
| 28 | + | return | |
| 29 | + | end | |
| 30 | + | ||
| 31 | + | feedbackWindow:show() | |
| 32 | + | feedbackWindow:raise() | |
| 33 | + | feedbackWindow:focus() | |
| 34 | + | textEdit:setMaxLength(8192) | |
| 35 | + | textEdit:setText("") | |
| 36 | + | textEdit:setEditable(true) | |
| 37 | + | textEdit:setCursorVisible(true) | |
| 38 | + | feedbackWindow:focusChild(textEdit, KeyboardFocusReason) | |
| 39 | + | ||
| 40 | + | tries = 0 | |
| 41 | + | end | |
| 42 | + | ||
| 43 | + | function hide() | |
| 44 | + | feedbackWindow:hide() | |
| 45 | + | textEdit:setEditable(false) | |
| 46 | + | textEdit:setCursorVisible(false) | |
| 47 | + | end | |
| 48 | + | ||
| 49 | + | function send() | |
| 50 | + | local text = textEdit:getText() | |
| 51 | + | ||
| 52 | + | if text:len() > 1 then | |
| 53 | + | local localPlayer = g_game.getLocalPlayer() | |
| 54 | + | local playerData | |
| 55 | + | ||
| 56 | + | if localPlayer ~= nil then | |
| 57 | + | playerData = { | |
| 58 | + | name = localPlayer:getName(), | |
| 59 | + | position = localPlayer:getPosition() | |
| 60 | + | } | |
| 61 | + | end | |
| 62 | + | ||
| 63 | + | local details = { | |
| 64 | + | report_delay = sendInterval, | |
| 65 | + | os = g_app.getOs(), | |
| 66 | + | graphics_vendor = g_graphics.getVendor(), | |
| 67 | + | graphics_renderer = g_graphics.getRenderer(), | |
| 68 | + | graphics_version = g_graphics.getVersion(), | |
| 69 | + | fps = g_app.getFps(), | |
| 70 | + | maxFps = g_app.getMaxFps(), | |
| 71 | + | atlas = g_atlas.getStats(), | |
| 72 | + | classic = tostring(g_settings.getBoolean("classicView")), | |
| 73 | + | fullscreen = tostring(g_window.isFullscreen()), | |
| 74 | + | vsync = tostring(g_settings.getBoolean("vsync")), | |
| 75 | + | window_width = g_window.getWidth(), | |
| 76 | + | window_height = g_window.getHeight(), | |
| 77 | + | player_name = g_game.getCharacterName(), | |
| 78 | + | world_name = g_game.getWorldName(), | |
| 79 | + | otserv_host = G.host, | |
| 80 | + | otserv_protocol = g_game.getProtocolVersion(), | |
| 81 | + | otserv_client = g_game.getClientVersion(), | |
| 82 | + | build_version = g_app.getVersion(), | |
| 83 | + | build_revision = g_app.getBuildRevision(), | |
| 84 | + | build_commit = g_app.getBuildCommit(), | |
| 85 | + | build_date = g_app.getBuildDate(), | |
| 86 | + | display_width = g_window.getDisplayWidth(), | |
| 87 | + | display_height = g_window.getDisplayHeight(), | |
| 88 | + | cpu = g_platform.getCPUName(), | |
| 89 | + | mem = g_platform.getTotalSystemMemory(), | |
| 90 | + | os_name = g_platform.getOSName() | |
| 91 | + | } | |
| 92 | + | local data = json.encode({ | |
| 93 | + | text = text, | |
| 94 | + | version = g_app.getVersion(), | |
| 95 | + | host = g_settings.get("host"), | |
| 96 | + | player = playerData, | |
| 97 | + | details = details | |
| 98 | + | }) | |
| 99 | + | ||
| 100 | + | postId = HTTP.post(Services.feedback, data, function(ret, err) | |
| 101 | + | if err then | |
| 102 | + | tries = tries + 1 | |
| 103 | + | ||
| 104 | + | if tries < 3 then | |
| 105 | + | replyEvent = scheduleEvent(send, 1000) | |
| 106 | + | end | |
| 107 | + | end | |
| 108 | + | end) | |
| 109 | + | end | |
| 110 | + | ||
| 111 | + | hide() | |
| 112 | + | end |
| @@ -0,0 +1,10 @@ | |||
| 1 | + | Module | |
| 2 | + | name: client_feedback | |
| 3 | + | description: Allow to send feedback | |
| 4 | + | author: otclientv8 | |
| 5 | + | website: otclient.ovh | |
| 6 | + | sandboxed: true | |
| 7 | + | dependencies: [ game_interface ] | |
| 8 | + | scripts: [ feedback ] | |
| 9 | + | @onLoad: init() | |
| 10 | + | @onUnload: terminate() |
| @@ -0,0 +1,48 @@ | |||
| 1 | + | MainWindow | |
| 2 | + | id: feedbackWindow | |
| 3 | + | size: 400 280 | |
| 4 | + | !text: tr("Feedback/Bug report") | |
| 5 | + | ||
| 6 | + | Label | |
| 7 | + | id: description | |
| 8 | + | anchors.top: parent.top | |
| 9 | + | anchors.left: parent.left | |
| 10 | + | anchors.right: parent.right | |
| 11 | + | text-auto-resize: true | |
| 12 | + | text-align: left | |
| 13 | + | text-wrap: true | |
| 14 | + | !text: tr("Bellow enter your feedback or bug report. Please include as much details as possible. Thank you!") | |
| 15 | + | ||
| 16 | + | MultilineTextEdit | |
| 17 | + | id: text | |
| 18 | + | anchors.top: textScroll.top | |
| 19 | + | anchors.left: parent.left | |
| 20 | + | anchors.right: textScroll.left | |
| 21 | + | anchors.bottom: textScroll.bottom | |
| 22 | + | vertical-scrollbar: textScroll | |
| 23 | + | text-wrap: true | |
| 24 | + | ||
| 25 | + | VerticalScrollBar | |
| 26 | + | id: textScroll | |
| 27 | + | anchors.top: description.bottom | |
| 28 | + | anchors.bottom: okButton.top | |
| 29 | + | anchors.right: parent.right | |
| 30 | + | margin-top: 10 | |
| 31 | + | margin-bottom: 10 | |
| 32 | + | step: 16 | |
| 33 | + | pixels-scroll: true | |
| 34 | + | ||
| 35 | + | Button | |
| 36 | + | id: okButton | |
| 37 | + | !text: tr('Ok') | |
| 38 | + | anchors.bottom: parent.bottom | |
| 39 | + | anchors.right: next.left | |
| 40 | + | margin-right: 10 | |
| 41 | + | width: 60 | |
| 42 | + | ||
| 43 | + | Button | |
| 44 | + | id: cancelButton | |
| 45 | + | !text: tr('Cancel') | |
| 46 | + | anchors.bottom: parent.bottom | |
| 47 | + | anchors.right: parent.right | |
| 48 | + | width: 60 |
| @@ -0,0 +1,177 @@ | |||
| 1 | + | dofile 'neededtranslations' | |
| 2 | + | ||
| 3 | + | -- private variables | |
| 4 | + | local defaultLocaleName = 'pt' | |
| 5 | + | local installedLocales | |
| 6 | + | local currentLocale | |
| 7 | + | local missingTranslations = {} | |
| 8 | + | ||
| 9 | + | function createWindow() | |
| 10 | + | localesWindow = g_ui.displayUI('locales') | |
| 11 | + | local localesPanel = localesWindow:getChildById('localesPanel') | |
| 12 | + | local layout = localesPanel:getLayout() | |
| 13 | + | local spacing = layout:getCellSpacing() | |
| 14 | + | local size = layout:getCellSize() | |
| 15 | + | ||
| 16 | + | local count = 0 | |
| 17 | + | for name,locale in pairs(installedLocales) do | |
| 18 | + | local widget = g_ui.createWidget('LocalesButton', localesPanel) | |
| 19 | + | widget:setImageSource('/images/flags/' .. name .. '') | |
| 20 | + | widget:setText(locale.languageName) | |
| 21 | + | widget.onClick = function() selectFirstLocale(name) end | |
| 22 | + | count = count + 1 | |
| 23 | + | end | |
| 24 | + | ||
| 25 | + | count = math.max(1, math.min(count, 3)) | |
| 26 | + | localesPanel:setWidth(size.width*count + spacing*(count-1)) | |
| 27 | + | ||
| 28 | + | addEvent(function() addEvent(function() localesWindow:raise() localesWindow:focus() end) end) | |
| 29 | + | end | |
| 30 | + | ||
| 31 | + | function selectFirstLocale(name) | |
| 32 | + | if localesWindow then | |
| 33 | + | localesWindow:destroy() | |
| 34 | + | localesWindow = nil | |
| 35 | + | end | |
| 36 | + | if setLocale(name) then | |
| 37 | + | g_modules.reloadModules() | |
| 38 | + | end | |
| 39 | + | g_settings.save() | |
| 40 | + | end | |
| 41 | + | ||
| 42 | + | -- public functions | |
| 43 | + | function init() | |
| 44 | + | installedLocales = {} | |
| 45 | + | ||
| 46 | + | installLocales('/locales') | |
| 47 | + | ||
| 48 | + | local userLocaleName = g_settings.get('locale', 'false') | |
| 49 | + | if userLocaleName ~= 'false' and setLocale(userLocaleName) then | |
| 50 | + | pdebug('Using configured locale: ' .. userLocaleName) | |
| 51 | + | else | |
| 52 | + | setLocale(defaultLocaleName) | |
| 53 | + | --connect(g_app, { onRun = createWindow }) | |
| 54 | + | end | |
| 55 | + | end | |
| 56 | + | ||
| 57 | + | function terminate() | |
| 58 | + | installedLocales = nil | |
| 59 | + | currentLocale = nil | |
| 60 | + | ||
| 61 | + | --disconnect(g_app, { onRun = createWindow }) | |
| 62 | + | end | |
| 63 | + | ||
| 64 | + | function generateNewTranslationTable(localename) | |
| 65 | + | local locale = installedLocales[localename] | |
| 66 | + | for _i,k in pairs(neededTranslations) do | |
| 67 | + | local trans = locale.translation[k] | |
| 68 | + | k = k:gsub('\n','\\n') | |
| 69 | + | k = k:gsub('\t','\\t') | |
| 70 | + | k = k:gsub('\"','\\\"') | |
| 71 | + | if trans then | |
| 72 | + | trans = trans:gsub('\n','\\n') | |
| 73 | + | trans = trans:gsub('\t','\\t') | |
| 74 | + | trans = trans:gsub('\"','\\\"') | |
| 75 | + | end | |
| 76 | + | if not trans then | |
| 77 | + | print(' ["' .. k .. '"]' .. ' = false,') | |
| 78 | + | else | |
| 79 | + | print(' ["' .. k .. '"]' .. ' = "' .. trans .. '",') | |
| 80 | + | end | |
| 81 | + | end | |
| 82 | + | end | |
| 83 | + | ||
| 84 | + | function installLocale(locale) | |
| 85 | + | if not locale or not locale.name then | |
| 86 | + | error('Unable to install locale.') | |
| 87 | + | end | |
| 88 | + | ||
| 89 | + | if _G.allowedLocales and not _G.allowedLocales[locale.name] then return end | |
| 90 | + | ||
| 91 | + | if locale.name ~= defaultLocaleName then | |
| 92 | + | local updatesNamesMissing = {} | |
| 93 | + | for _,k in pairs(neededTranslations) do | |
| 94 | + | if locale.translation[k] == nil then | |
| 95 | + | updatesNamesMissing[#updatesNamesMissing + 1] = k | |
| 96 | + | end | |
| 97 | + | end | |
| 98 | + | ||
| 99 | + | if #updatesNamesMissing > 0 then | |
| 100 | + | pdebug('Locale \'' .. locale.name .. '\' is missing ' .. #updatesNamesMissing .. ' translations.') | |
| 101 | + | for _,name in pairs(updatesNamesMissing) do | |
| 102 | + | pdebug('["' .. name ..'"] = \"\",') | |
| 103 | + | end | |
| 104 | + | end | |
| 105 | + | end | |
| 106 | + | ||
| 107 | + | local installedLocale = installedLocales[locale.name] | |
| 108 | + | if installedLocale then | |
| 109 | + | for word,translation in pairs(locale.translation) do | |
| 110 | + | installedLocale.translation[word] = translation | |
| 111 | + | end | |
| 112 | + | else | |
| 113 | + | installedLocales[locale.name] = locale | |
| 114 | + | end | |
| 115 | + | end | |
| 116 | + | ||
| 117 | + | function installLocales(directory) | |
| 118 | + | dofiles(directory) | |
| 119 | + | end | |
| 120 | + | ||
| 121 | + | function setLocale(name) | |
| 122 | + | local locale = installedLocales[name] | |
| 123 | + | if locale == currentLocale then return end | |
| 124 | + | if not locale then | |
| 125 | + | pwarning("Locale " .. name .. ' does not exist.') | |
| 126 | + | return false | |
| 127 | + | end | |
| 128 | + | currentLocale = locale | |
| 129 | + | g_settings.set('locale', name) | |
| 130 | + | if onLocaleChanged then onLocaleChanged(name) end | |
| 131 | + | return true | |
| 132 | + | end | |
| 133 | + | ||
| 134 | + | function getInstalledLocales() | |
| 135 | + | return installedLocales | |
| 136 | + | end | |
| 137 | + | ||
| 138 | + | function getCurrentLocale() | |
| 139 | + | return currentLocale | |
| 140 | + | end | |
| 141 | + | ||
| 142 | + | -- global function used to translate texts | |
| 143 | + | function _G.tr(text, ...) | |
| 144 | + | if currentLocale then | |
| 145 | + | if tonumber(text) and currentLocale.formatNumbers then | |
| 146 | + | local number = tostring(text):split('.') | |
| 147 | + | local out = '' | |
| 148 | + | local reverseNumber = number[1]:reverse() | |
| 149 | + | for i=1,#reverseNumber do | |
| 150 | + | out = out .. reverseNumber:sub(i, i) | |
| 151 | + | if i % 3 == 0 and i ~= #number then | |
| 152 | + | out = out .. currentLocale.thousandsSeperator | |
| 153 | + | end | |
| 154 | + | end | |
| 155 | + | ||
| 156 | + | if number[2] then | |
| 157 | + | out = number[2] .. currentLocale.decimalSeperator .. out | |
| 158 | + | end | |
| 159 | + | return out:reverse() | |
| 160 | + | elseif tostring(text) then | |
| 161 | + | local translation = currentLocale.translation[text] | |
| 162 | + | if not translation then | |
| 163 | + | if translation == nil then | |
| 164 | + | if currentLocale.name ~= defaultLocaleName then | |
| 165 | + | if not missingTranslations[text] then | |
| 166 | + | pdebug('Unable to translate: \"' .. text .. '\"') | |
| 167 | + | missingTranslations[text] = true | |
| 168 | + | end | |
| 169 | + | end | |
| 170 | + | end | |
| 171 | + | translation = text | |
| 172 | + | end | |
| 173 | + | return string.format(translation, ...) | |
| 174 | + | end | |
| 175 | + | end | |
| 176 | + | return text | |
| 177 | + | end |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | Module | |
| 2 | + | name: client_locales | |
| 3 | + | description: Translates texts to selected language | |
| 4 | + | author: baxnie, edubart | |
| 5 | + | website: https://github.com/edubart/otclient | |
| 6 | + | sandboxed: true | |
| 7 | + | scripts: [ locales ] | |
| 8 | + | @onLoad: init() | |
| 9 | + | @onUnload: terminate() |
| @@ -0,0 +1,35 @@ | |||
| 1 | + | LocalesMainLabel < Label | |
| 2 | + | font: sans-bold-16px | |
| 3 | + | ||
| 4 | + | LocalesButton < UIWidget | |
| 5 | + | size: 96 96 | |
| 6 | + | image-size: 96 96 | |
| 7 | + | image-smooth: true | |
| 8 | + | text-offset: 0 96 | |
| 9 | + | font: verdana-11px-antialised | |
| 10 | + | ||
| 11 | + | UIWindow | |
| 12 | + | id: localesWindow | |
| 13 | + | background-color: #000000 | |
| 14 | + | opacity: 0.90 | |
| 15 | + | clipping: true | |
| 16 | + | anchors.fill: parent | |
| 17 | + | ||
| 18 | + | LocalesMainLabel | |
| 19 | + | !text: tr('Select your language') | |
| 20 | + | text-auto-resize: true | |
| 21 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 22 | + | anchors.verticalCenter: parent.verticalCenter | |
| 23 | + | margin-top: -100 | |
| 24 | + | ||
| 25 | + | Panel | |
| 26 | + | id: localesPanel | |
| 27 | + | margin-top: 50 | |
| 28 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 29 | + | anchors.top: prev.bottom | |
| 30 | + | anchors.bottom: parent.bottom | |
| 31 | + | layout: | |
| 32 | + | type: grid | |
| 33 | + | cell-size: 96 128 | |
| 34 | + | cell-spacing: 32 | |
| 35 | + | flow: true |
| @@ -0,0 +1,364 @@ | |||
| 1 | + | -- generated by ./tools/gen_needed_translations.sh | |
| 2 | + | neededTranslations = { | |
| 3 | + | "1a) Offensive Name", | |
| 4 | + | "1b) Invalid Name Format", | |
| 5 | + | "1c) Unsuitable Name", | |
| 6 | + | "1d) Name Inciting Rule Violation", | |
| 7 | + | "2a) Offensive Statement", | |
| 8 | + | "2b) Spamming", | |
| 9 | + | "2c) Illegal Advertising", | |
| 10 | + | "2d) Off-Topic Public Statement", | |
| 11 | + | "2e) Non-English Public Statement", | |
| 12 | + | "2f) Inciting Rule Violation", | |
| 13 | + | "3a) Bug Abuse", | |
| 14 | + | "3b) Game Weakness Abuse", | |
| 15 | + | "3c) Using Unofficial Software to Play", | |
| 16 | + | "3d) Hacking", | |
| 17 | + | "3e) Multi-Clienting", | |
| 18 | + | "3f) Account Trading or Sharing", | |
| 19 | + | "4a) Threatening Gamemaster", | |
| 20 | + | "4b) Pretending to Have Influence on Rule Enforcement", | |
| 21 | + | "4c) False Report to Gamemaster", | |
| 22 | + | "Accept", | |
| 23 | + | "Account name", | |
| 24 | + | "Account Status:", | |
| 25 | + | "Action:", | |
| 26 | + | "Add", | |
| 27 | + | "Add new VIP", | |
| 28 | + | "Addon 1", | |
| 29 | + | "Addon 2", | |
| 30 | + | "Addon 3", | |
| 31 | + | "Add to VIP list", | |
| 32 | + | "Adjust volume", | |
| 33 | + | "Alas! Brave adventurer, you have met a sad fate.\nBut do not despair, for the gods will bring you back\ninto this world in exchange for a small sacrifice\n\nSimply click on Ok to resume your journeys!", | |
| 34 | + | "All", | |
| 35 | + | "All modules and scripts were reloaded.", | |
| 36 | + | "Allow auto chase override", | |
| 37 | + | "Ambient light: %s%%", | |
| 38 | + | "Amount:", | |
| 39 | + | "Amount", | |
| 40 | + | "Anonymous", | |
| 41 | + | "Are you sure you want to logout?", | |
| 42 | + | "Attack", | |
| 43 | + | "Author", | |
| 44 | + | "Autoload", | |
| 45 | + | "Autoload priority", | |
| 46 | + | "Auto login", | |
| 47 | + | "Auto login selected character on next charlist load", | |
| 48 | + | "Axe Fighting", | |
| 49 | + | "Balance:", | |
| 50 | + | "Banishment", | |
| 51 | + | "Banishment + Final Warning", | |
| 52 | + | "Battle", | |
| 53 | + | "Browse", | |
| 54 | + | "Bug report sent.", | |
| 55 | + | "Button Assign", | |
| 56 | + | "Buy", | |
| 57 | + | "Buy Now", | |
| 58 | + | "Buy Offers", | |
| 59 | + | "Buy with backpack", | |
| 60 | + | "Cancel", | |
| 61 | + | "Cannot login while already in game.", | |
| 62 | + | "Cap", | |
| 63 | + | "Capacity", | |
| 64 | + | "Center", | |
| 65 | + | "Channels", | |
| 66 | + | "Character List", | |
| 67 | + | "Classic control", | |
| 68 | + | "Clear current message window", | |
| 69 | + | "Clear Messages", | |
| 70 | + | "Clear object", | |
| 71 | + | "Client needs update.", | |
| 72 | + | "Close", | |
| 73 | + | "Close this channel", | |
| 74 | + | "Club Fighting", | |
| 75 | + | "Combat Controls", | |
| 76 | + | "Comment:", | |
| 77 | + | "Connecting to game server...", | |
| 78 | + | "Connecting to login server...", | |
| 79 | + | "Console", | |
| 80 | + | "Cooldowns", | |
| 81 | + | "Copy message", | |
| 82 | + | "Copy name", | |
| 83 | + | "Copy Name", | |
| 84 | + | "Create Map Mark", | |
| 85 | + | "Create mark", | |
| 86 | + | "Create New Offer", | |
| 87 | + | "Create Offer", | |
| 88 | + | "Current hotkeys:", | |
| 89 | + | "Current hotkey to add: %s", | |
| 90 | + | "Current Offers", | |
| 91 | + | "Default", | |
| 92 | + | "Delete mark", | |
| 93 | + | "Description:", | |
| 94 | + | "Description", | |
| 95 | + | "Destructive Behaviour", | |
| 96 | + | "Detail", | |
| 97 | + | "Details", | |
| 98 | + | "Disable Shared Experience", | |
| 99 | + | "Dismount", | |
| 100 | + | "Display connection speed to the server (milliseconds)", | |
| 101 | + | "Distance Fighting", | |
| 102 | + | "Don\'t stretch/shrink Game Window", | |
| 103 | + | "Edit hotkey text:", | |
| 104 | + | "Edit List", | |
| 105 | + | "Edit Text", | |
| 106 | + | "Enable music", | |
| 107 | + | "Enable Shared Experience", | |
| 108 | + | "Enable smart walking", | |
| 109 | + | "Enable vertical synchronization", | |
| 110 | + | "Enable walk booster", | |
| 111 | + | "Enter Game", | |
| 112 | + | "Enter one name per line.", | |
| 113 | + | "Enter with your account again to update your client.", | |
| 114 | + | "Error", | |
| 115 | + | "Error", | |
| 116 | + | "Excessive Unjustified Player Killing", | |
| 117 | + | "Exclude from private chat", | |
| 118 | + | "Exit", | |
| 119 | + | "Experience", | |
| 120 | + | "Filter list to match your level", | |
| 121 | + | "Filter list to match your vocation", | |
| 122 | + | "Find:", | |
| 123 | + | "Fishing", | |
| 124 | + | "Fist Fighting", | |
| 125 | + | "Follow", | |
| 126 | + | "Force Exit", | |
| 127 | + | "For Your Information", | |
| 128 | + | "Free Account", | |
| 129 | + | "Fullscreen", | |
| 130 | + | "Game", | |
| 131 | + | "Game framerate limit: %s", | |
| 132 | + | "Graphics", | |
| 133 | + | "Graphics card driver not detected", | |
| 134 | + | "Graphics Engine:", | |
| 135 | + | "Head", | |
| 136 | + | "Healing", | |
| 137 | + | "Health Info", | |
| 138 | + | "Health Information", | |
| 139 | + | "Hide monsters", | |
| 140 | + | "Hide non-skull players", | |
| 141 | + | "Hide Npcs", | |
| 142 | + | "Hide Offline", | |
| 143 | + | "Hide party members", | |
| 144 | + | "Hide players", | |
| 145 | + | "Hide spells for higher exp. levels", | |
| 146 | + | "Hide spells for other vocations", | |
| 147 | + | "Hit Points", | |
| 148 | + | "Hold left mouse button to navigate\nScroll mouse middle button to zoom\nRight mouse button to create map marks", | |
| 149 | + | "Hotkeys", | |
| 150 | + | "If you shut down the program, your character might stay in the game.\nClick on 'Logout' to ensure that you character leaves the game properly.\nClick on 'Exit' if you want to exit the program without logging out your character.", | |
| 151 | + | "Ignore", | |
| 152 | + | "Ignore capacity", | |
| 153 | + | "Ignored players:", | |
| 154 | + | "Ignore equipped", | |
| 155 | + | "Ignore List", | |
| 156 | + | "Ignore players", | |
| 157 | + | "Ignore Private Messages", | |
| 158 | + | "Ignore Yelling", | |
| 159 | + | "Interface framerate limit: %s", | |
| 160 | + | "Inventory", | |
| 161 | + | "Invite to Party", | |
| 162 | + | "Invite to private chat", | |
| 163 | + | "IP Address Banishment", | |
| 164 | + | "Item Offers", | |
| 165 | + | "It is empty.", | |
| 166 | + | "Join %s\'s Party", | |
| 167 | + | "Leave Party", | |
| 168 | + | "Level", | |
| 169 | + | "Lifetime Premium Account", | |
| 170 | + | "Limits FPS to 60", | |
| 171 | + | "List of items that you're able to buy", | |
| 172 | + | "List of items that you're able to sell", | |
| 173 | + | "Load", | |
| 174 | + | "Logging out...", | |
| 175 | + | "Login", | |
| 176 | + | "Login Error", | |
| 177 | + | "Login Error", | |
| 178 | + | "Logout", | |
| 179 | + | "Look", | |
| 180 | + | "Magic Level", | |
| 181 | + | "Make sure that your client uses\nthe correct game protocol version", | |
| 182 | + | "Mana", | |
| 183 | + | "Manage hotkeys:", | |
| 184 | + | "Market", | |
| 185 | + | "Market Offers", | |
| 186 | + | "Message of the day", | |
| 187 | + | "Message to ", | |
| 188 | + | "Message to %s", | |
| 189 | + | "Minimap", | |
| 190 | + | "Module Manager", | |
| 191 | + | "Module name", | |
| 192 | + | "Mount", | |
| 193 | + | "Move Stackable Item", | |
| 194 | + | "Move up", | |
| 195 | + | "My Offers", | |
| 196 | + | "Name:", | |
| 197 | + | "Name Report", | |
| 198 | + | "Name Report + Banishment", | |
| 199 | + | "Name Report + Banishment + Final Warning", | |
| 200 | + | "No", | |
| 201 | + | "No graphics card detected, everything will be drawn using the CPU,\nthus the performance will be really bad.\nPlease update your graphics driver to have a better performance.", | |
| 202 | + | "No item selected.", | |
| 203 | + | "No Mount", | |
| 204 | + | "No Outfit", | |
| 205 | + | "No statement has been selected.", | |
| 206 | + | "Notation", | |
| 207 | + | "NPC Trade", | |
| 208 | + | "Offer History", | |
| 209 | + | "Offers", | |
| 210 | + | "Offer Type:", | |
| 211 | + | "Offline Training", | |
| 212 | + | "Ok", | |
| 213 | + | "on %s.\n", | |
| 214 | + | "Open", | |
| 215 | + | "Open a private message channel:", | |
| 216 | + | "Open charlist automatically when starting client", | |
| 217 | + | "Open in new window", | |
| 218 | + | "Open new channel", | |
| 219 | + | "Options", | |
| 220 | + | "Overview", | |
| 221 | + | "Pass Leadership to %s", | |
| 222 | + | "Password", | |
| 223 | + | "Piece Price:", | |
| 224 | + | "Please enter a character name:", | |
| 225 | + | "Please, press the key you wish to add onto your hotkeys manager", | |
| 226 | + | "Please Select", | |
| 227 | + | "Please use this dialog to only report bugs. Do not report rule violations here!", | |
| 228 | + | "Please wait", | |
| 229 | + | "Port", | |
| 230 | + | "Position:", | |
| 231 | + | "Position: %i %i %i", | |
| 232 | + | "Premium Account (%s) days left", | |
| 233 | + | "Price:", | |
| 234 | + | "Primary", | |
| 235 | + | "Protocol", | |
| 236 | + | "Quest Log", | |
| 237 | + | "Randomize", | |
| 238 | + | "Randomize characters outfit", | |
| 239 | + | "Reason:", | |
| 240 | + | "Refresh", | |
| 241 | + | "Refresh Offers", | |
| 242 | + | "Regeneration Time", | |
| 243 | + | "Reject", | |
| 244 | + | "Reload All", | |
| 245 | + | "Remember account and password when starts client", | |
| 246 | + | "Remember password", | |
| 247 | + | "Remove", | |
| 248 | + | "Remove %s", | |
| 249 | + | "Report Bug", | |
| 250 | + | "Reserved for more functionality later.", | |
| 251 | + | "Reset Market", | |
| 252 | + | "Revoke %s\'s Invitation", | |
| 253 | + | "Rotate", | |
| 254 | + | "Rule Violation", | |
| 255 | + | "Save", | |
| 256 | + | "Save Messages", | |
| 257 | + | "Search:", | |
| 258 | + | "Search all items", | |
| 259 | + | "Secondary", | |
| 260 | + | "Select object", | |
| 261 | + | "Select Outfit", | |
| 262 | + | "Select your language", | |
| 263 | + | "Sell", | |
| 264 | + | "Sell Now", | |
| 265 | + | "Sell Offers", | |
| 266 | + | "Send", | |
| 267 | + | "Send automatically", | |
| 268 | + | "Send Message", | |
| 269 | + | "Server", | |
| 270 | + | "Server Log", | |
| 271 | + | "Set Outfit", | |
| 272 | + | "Shielding", | |
| 273 | + | "Show all items", | |
| 274 | + | "Show connection ping", | |
| 275 | + | "Show Depot Only", | |
| 276 | + | "Show event messages in console", | |
| 277 | + | "Show frame rate", | |
| 278 | + | "Show info messages in console", | |
| 279 | + | "Show left panel", | |
| 280 | + | "Show levels in console", | |
| 281 | + | "Show Offline", | |
| 282 | + | "Show private messages in console", | |
| 283 | + | "Show private messages on screen", | |
| 284 | + | "Show Server Messages", | |
| 285 | + | "Show status messages in console", | |
| 286 | + | "Show Text", | |
| 287 | + | "Show timestamps in console", | |
| 288 | + | "Show your depot items only", | |
| 289 | + | "Skills", | |
| 290 | + | "Soul", | |
| 291 | + | "Soul Points", | |
| 292 | + | "Special", | |
| 293 | + | "Speed", | |
| 294 | + | "Spell Cooldowns", | |
| 295 | + | "Spell List", | |
| 296 | + | "Stamina", | |
| 297 | + | "Statement:", | |
| 298 | + | "Statement Report", | |
| 299 | + | "Statistics", | |
| 300 | + | "Stop Attack", | |
| 301 | + | "Stop Follow", | |
| 302 | + | "Support", | |
| 303 | + | "%s: (use object)", | |
| 304 | + | "%s: (use object on target)", | |
| 305 | + | "%s: (use object on yourself)", | |
| 306 | + | "%s: (use object with crosshair)", | |
| 307 | + | "Sword Fighting", | |
| 308 | + | "Terminal", | |
| 309 | + | "There is no way.", | |
| 310 | + | "Title", | |
| 311 | + | "Total Price:", | |
| 312 | + | "Trade", | |
| 313 | + | "Trade with ...", | |
| 314 | + | "Trying to reconnect in %s seconds.", | |
| 315 | + | "Unable to load dat file, please place a valid dat in '%s'", | |
| 316 | + | "Unable to load spr file, please place a valid spr in '%s'", | |
| 317 | + | "Unable to logout.", | |
| 318 | + | "Unignore", | |
| 319 | + | "Unload", | |
| 320 | + | "Update needed", | |
| 321 | + | "Use", | |
| 322 | + | "Use on target", | |
| 323 | + | "Use on yourself", | |
| 324 | + | "Use with ...", | |
| 325 | + | "Version", | |
| 326 | + | "VIP List", | |
| 327 | + | "Voc.", | |
| 328 | + | "Vocation", | |
| 329 | + | "Waiting List", | |
| 330 | + | "Website", | |
| 331 | + | "Weight:", | |
| 332 | + | "Will detect when to use diagonal step based on the\nkeys you are pressing", | |
| 333 | + | "With crosshair", | |
| 334 | + | "Yes", | |
| 335 | + | "You are bleeding", | |
| 336 | + | "You are burning", | |
| 337 | + | "You are cursed", | |
| 338 | + | "You are dazzled", | |
| 339 | + | "You are dead.", | |
| 340 | + | "You are dead", | |
| 341 | + | "You are drowning", | |
| 342 | + | "You are drunk", | |
| 343 | + | "You are electrified", | |
| 344 | + | "You are freezing", | |
| 345 | + | "You are hasted", | |
| 346 | + | "You are hungry", | |
| 347 | + | "You are paralysed", | |
| 348 | + | "You are poisoned", | |
| 349 | + | "You are protected by a magic shield", | |
| 350 | + | "You are strengthened", | |
| 351 | + | "You are within a protection zone", | |
| 352 | + | "You can enter new text.", | |
| 353 | + | "You have %s percent", | |
| 354 | + | "You have %s percent to go", | |
| 355 | + | "You may not logout during a fight", | |
| 356 | + | "You may not logout or enter a protection zone", | |
| 357 | + | "You must enter a comment.", | |
| 358 | + | "You must enter a valid server address and port.", | |
| 359 | + | "You must select a character to login!", | |
| 360 | + | "Your Capacity:", | |
| 361 | + | "You read the following, written by \n%s\n", | |
| 362 | + | "You read the following, written on \n%s.\n", | |
| 363 | + | "Your Money:", | |
| 364 | + | } |
| @@ -0,0 +1,449 @@ | |||
| 1 | + | local overlay | |
| 2 | + | local keypad | |
| 3 | + | local touchStart = 0 | |
| 4 | + | local updateCursorEvent | |
| 5 | + | local zoomInButton | |
| 6 | + | local zoomOutButton | |
| 7 | + | local keypadButton | |
| 8 | + | local keypadEvent | |
| 9 | + | local keypadMousePos = {x=0.5, y=0.5} | |
| 10 | + | local keypadTicks = 0 | |
| 11 | + | local delayMobileBt = 1000 | |
| 12 | + | ||
| 13 | + | -- public functions | |
| 14 | + | function init() | |
| 15 | + | if not g_app.isMobile() then return end | |
| 16 | + | overlay = g_ui.displayUI('mobile') | |
| 17 | + | attackerButton = overlay:recursiveGetChildById('attacker') | |
| 18 | + | menuButton = overlay:recursiveGetChildById('menu') | |
| 19 | + | optionsButton = overlay:recursiveGetChildById('options') | |
| 20 | + | exitButton = overlay:recursiveGetChildById('exitgame') | |
| 21 | + | mountButton = overlay:recursiveGetChildById('buttonMount') | |
| 22 | + | bugButton = overlay:recursiveGetChildById('buttonBug') | |
| 23 | + | keypad = overlay:recursiveGetChildById('keypad') | |
| 24 | + | ||
| 25 | + | buttonChat = overlay:recursiveGetChildById('buttonChat') | |
| 26 | + | buttonChat:hide() | |
| 27 | + | ||
| 28 | + | onlineMobile = overlay:recursiveGetChildById('onlineMobile') | |
| 29 | + | goldMobile = overlay:recursiveGetChildById('goldMobile') | |
| 30 | + | onlineMobile:hide() | |
| 31 | + | goldMobile:hide() | |
| 32 | + | ||
| 33 | + | mobileDGTime = overlay:recursiveGetChildById('mobileDGTime') | |
| 34 | + | mobileDGDesistir = overlay:recursiveGetChildById('mobileDGDesistir') | |
| 35 | + | mobileDGTime:hide() | |
| 36 | + | mobileDGDesistir:hide() | |
| 37 | + | ||
| 38 | + | skillBar = overlay:recursiveGetChildById('skillBar') | |
| 39 | + | skill1 = overlay:recursiveGetChildById('spell01') | |
| 40 | + | skill2 = overlay:recursiveGetChildById('spell02') | |
| 41 | + | skill3 = overlay:recursiveGetChildById('spell03') | |
| 42 | + | suporte1 = overlay:recursiveGetChildById('sup01') | |
| 43 | + | suporte2 = overlay:recursiveGetChildById('sup02') | |
| 44 | + | qntSkill = overlay:recursiveGetChildById('qntSkill') | |
| 45 | + | suporte3 = overlay:recursiveGetChildById('sup03') | |
| 46 | + | skillBar:hide() | |
| 47 | + | ||
| 48 | + | attackerButton:hide() | |
| 49 | + | menuButton:hide() | |
| 50 | + | exitButton:hide() | |
| 51 | + | optionsButton:hide() | |
| 52 | + | bugButton:hide() | |
| 53 | + | mountButton:hide() | |
| 54 | + | ||
| 55 | + | hpBar = overlay:recursiveGetChildById('hpBar') | |
| 56 | + | levelInfo = overlay:recursiveGetChildById('levelInfo') | |
| 57 | + | ammoInfo = overlay:recursiveGetChildById('ammoInfo') | |
| 58 | + | expBar = overlay:recursiveGetChildById('expBar') | |
| 59 | + | condMobile = overlay:recursiveGetChildById('conditionMobilePanel') | |
| 60 | + | hpBar:hide() | |
| 61 | + | levelInfo:hide() | |
| 62 | + | ammoInfo:hide() | |
| 63 | + | expBar:hide() | |
| 64 | + | ||
| 65 | + | menuButton:enable() | |
| 66 | + | ||
| 67 | + | menuButton.onClick = function() | |
| 68 | + | modules.game_menu.mobileMenuBar() | |
| 69 | + | menuButton:disable() | |
| 70 | + | scheduleEvent(function() | |
| 71 | + | menuButton:enable() | |
| 72 | + | end, delayMobileBt) | |
| 73 | + | end | |
| 74 | + | attackerButton.onClick = function() AttackMobile() scheduleEvent(function() attackerButton:enable() end, 1000) end | |
| 75 | + | keypad = overlay.keypad | |
| 76 | + | overlay:raise() | |
| 77 | + | ||
| 78 | + | zoomInButton = modules.client_topmenu.addLeftButton('zoomInButton', 'Zoom In', '/images/topbuttons/zoomin', function() g_app.scaleUp() end) | |
| 79 | + | zoomOutButton = modules.client_topmenu.addLeftButton('zoomOutButton', 'Zoom Out', '/images/topbuttons/zoomout', function() g_app.scaleDown() end) | |
| 80 | + | keypadButton = modules.client_topmenu.addLeftGameToggleButton('keypadButton', 'Keypad', '/images/topbuttons/keypad', function() | |
| 81 | + | keypadButton:setChecked(not keypadButton:isChecked()) | |
| 82 | + | if not g_game.isOnline() then | |
| 83 | + | keypad:setVisible(false) | |
| 84 | + | return | |
| 85 | + | end | |
| 86 | + | keypad:setVisible(keypadButton:isChecked()) | |
| 87 | + | end) | |
| 88 | + | keypadButton:setChecked(true) | |
| 89 | + | ||
| 90 | + | scheduleEvent(function() | |
| 91 | + | g_app.scale(5.0) | |
| 92 | + | end, 10) | |
| 93 | + | ||
| 94 | + | connect(overlay, { | |
| 95 | + | onMousePress = onMousePress, | |
| 96 | + | onMouseRelease = onMouseRelease, | |
| 97 | + | onTouchPress = onMousePress, | |
| 98 | + | onTouchRelease = onMouseRelease, | |
| 99 | + | onMouseMove = onMouseMove | |
| 100 | + | }) | |
| 101 | + | connect(keypad, { | |
| 102 | + | onTouchPress = onKeypadTouchPress, | |
| 103 | + | onTouchRelease = onKeypadTouchRelease, | |
| 104 | + | onMouseMove = onKeypadTouchMove | |
| 105 | + | }) | |
| 106 | + | connect(g_game, { | |
| 107 | + | onGameStart = online, | |
| 108 | + | onGameEnd = offline | |
| 109 | + | }) | |
| 110 | + | if g_game.isOnline() then | |
| 111 | + | online() | |
| 112 | + | end | |
| 113 | + | end | |
| 114 | + | ||
| 115 | + | function onMobileButton(id, type) | |
| 116 | + | if id == 01 then | |
| 117 | + | return hpBar | |
| 118 | + | elseif id == 02 then | |
| 119 | + | return expBar | |
| 120 | + | elseif id == 03 then | |
| 121 | + | return levelInfo | |
| 122 | + | elseif id == 04 then | |
| 123 | + | return ammoInfo | |
| 124 | + | elseif id == 05 then | |
| 125 | + | return attackerButton | |
| 126 | + | elseif id == 06 then | |
| 127 | + | return condMobile | |
| 128 | + | elseif id == 07 then | |
| 129 | + | return skillBar | |
| 130 | + | elseif id == 08 then | |
| 131 | + | return skill1 | |
| 132 | + | elseif id == 09 then | |
| 133 | + | return skill2 | |
| 134 | + | elseif id == 10 then | |
| 135 | + | return skill3 | |
| 136 | + | elseif id == 11 then | |
| 137 | + | return suporte1 | |
| 138 | + | elseif id == 12 then | |
| 139 | + | return suporte2 | |
| 140 | + | elseif id == 13 then | |
| 141 | + | return suporte3 | |
| 142 | + | elseif id == 14 then | |
| 143 | + | return qntSkill | |
| 144 | + | elseif id == 15 then | |
| 145 | + | return onlineMobile | |
| 146 | + | elseif id == 16 then | |
| 147 | + | return goldMobile | |
| 148 | + | elseif id == 17 then | |
| 149 | + | return mobileDGTime | |
| 150 | + | elseif id == 18 then | |
| 151 | + | return mobileDGDesistir | |
| 152 | + | end | |
| 153 | + | end | |
| 154 | + | function onHideUI(id) | |
| 155 | + | if id == 00 then | |
| 156 | + | condMobile:hide() | |
| 157 | + | mountButton:hide() | |
| 158 | + | bugButton:hide() | |
| 159 | + | attackerButton:hide() | |
| 160 | + | menuButton:hide() | |
| 161 | + | exitButton:hide() | |
| 162 | + | optionsButton:hide() | |
| 163 | + | hpBar:hide() | |
| 164 | + | levelInfo:hide() | |
| 165 | + | ammoInfo:hide() | |
| 166 | + | expBar:hide() | |
| 167 | + | skillBar:hide() | |
| 168 | + | onlineMobile:hide() | |
| 169 | + | goldMobile:hide() | |
| 170 | + | keypad:hide() | |
| 171 | + | buttonChat:hide() | |
| 172 | + | elseif id == 02 then | |
| 173 | + | attackerButton:hide() | |
| 174 | + | ammoInfo:hide() | |
| 175 | + | elseif id == 03 then | |
| 176 | + | attackerButton:show() | |
| 177 | + | ammoInfo:show() | |
| 178 | + | else | |
| 179 | + | mountButton:show() | |
| 180 | + | bugButton:show() | |
| 181 | + | condMobile:show() | |
| 182 | + | attackerButton:show() | |
| 183 | + | menuButton:show() | |
| 184 | + | exitButton:show() | |
| 185 | + | optionsButton:show() | |
| 186 | + | hpBar:show() | |
| 187 | + | levelInfo:show() | |
| 188 | + | ammoInfo:show() | |
| 189 | + | expBar:show() | |
| 190 | + | skillBar:show() | |
| 191 | + | onlineMobile:show() | |
| 192 | + | goldMobile:show() | |
| 193 | + | keypad:show() | |
| 194 | + | buttonChat:show() | |
| 195 | + | end | |
| 196 | + | end | |
| 197 | + | function AttackMobile() | |
| 198 | + | local battlePanel = modules.game_battle.battlePanel | |
| 199 | + | local child = battlePanel:getFirstChild() | |
| 200 | + | local nextChild = nil | |
| 201 | + | local attacking = g_game.getAttackingCreature() | |
| 202 | + | if child and (not child.creature or not child:isOn()) then | |
| 203 | + | child = nil | |
| 204 | + | end | |
| 205 | + | if child then | |
| 206 | + | if not attacking then | |
| 207 | + | g_game.attack(child.creature) | |
| 208 | + | else | |
| 209 | + | local battlePanel = modules.game_battle.battlePanel | |
| 210 | + | local attackedCreature = g_game.getAttackingCreature() | |
| 211 | + | local nextChild = nil | |
| 212 | + | local breakNext = false | |
| 213 | + | for i, child in ipairs(battlePanel:getChildren()) do | |
| 214 | + | if not child.creature or not child:isOn() then | |
| 215 | + | break | |
| 216 | + | end | |
| 217 | + | nextChild = child | |
| 218 | + | if breakNext then | |
| 219 | + | break | |
| 220 | + | end | |
| 221 | + | if child.creature == attackedCreature then | |
| 222 | + | breakNext = true | |
| 223 | + | nextChild = battlePanel:getFirstChild() | |
| 224 | + | end | |
| 225 | + | end | |
| 226 | + | if not breakNext then | |
| 227 | + | nextChild = battlePanel:getFirstChild() | |
| 228 | + | end | |
| 229 | + | if nextChild and nextChild.creature ~= attackedCreature then | |
| 230 | + | g_game.attack(nextChild.creature) | |
| 231 | + | end | |
| 232 | + | end | |
| 233 | + | else | |
| 234 | + | g_game.attack(nil) | |
| 235 | + | end | |
| 236 | + | end | |
| 237 | + | function terminate() | |
| 238 | + | if not g_app.isMobile() then return end | |
| 239 | + | removeEvent(updateCursorEvent) | |
| 240 | + | removeEvent(keypadEvent) | |
| 241 | + | keypadEvent = nil | |
| 242 | + | disconnect(overlay, { | |
| 243 | + | onMousePress = onMousePress, | |
| 244 | + | onMouseRelease = onMouseRelease, | |
| 245 | + | onTouchPress = onMousePress, | |
| 246 | + | onTouchRelease = onMouseRelease, | |
| 247 | + | onMouseMove = onMouseMove | |
| 248 | + | }) | |
| 249 | + | disconnect(keypad, { | |
| 250 | + | onTouchPress = onKeypadTouchPress, | |
| 251 | + | onTouchRelease = onKeypadTouchRelease, | |
| 252 | + | onMouseMove = onKeypadTouchMove | |
| 253 | + | }) | |
| 254 | + | disconnect(g_game, { | |
| 255 | + | onGameStart = online, | |
| 256 | + | onGameEnd = offline | |
| 257 | + | }) | |
| 258 | + | zoomInButton:destroy() | |
| 259 | + | zoomOutButton:destroy() | |
| 260 | + | keypadButton:destroy() | |
| 261 | + | overlay:destroy() | |
| 262 | + | overlay = nil | |
| 263 | + | end | |
| 264 | + | ||
| 265 | + | function hide() | |
| 266 | + | overlay:hide() | |
| 267 | + | attackerButton:hide() | |
| 268 | + | menuButton:hide() | |
| 269 | + | exitButton:hide() | |
| 270 | + | optionsButton:hide() | |
| 271 | + | hpBar:hide() | |
| 272 | + | levelInfo:hide() | |
| 273 | + | ammoInfo:hide() | |
| 274 | + | expBar:hide() | |
| 275 | + | skillBar:hide() | |
| 276 | + | onlineMobile:hide() | |
| 277 | + | goldMobile:hide() | |
| 278 | + | buttonChat:hide() | |
| 279 | + | bugButton:hide() | |
| 280 | + | mountButton:hide() | |
| 281 | + | end | |
| 282 | + | ||
| 283 | + | function show() | |
| 284 | + | overlay:show() | |
| 285 | + | attackerButton:show() | |
| 286 | + | menuButton:show() | |
| 287 | + | exitButton:show() | |
| 288 | + | optionsButton:show() | |
| 289 | + | hpBar:show() | |
| 290 | + | levelInfo:show() | |
| 291 | + | ammoInfo:show() | |
| 292 | + | expBar:show() | |
| 293 | + | skillBar:show() | |
| 294 | + | onlineMobile:show() | |
| 295 | + | goldMobile:show() | |
| 296 | + | buttonChat:show() | |
| 297 | + | end | |
| 298 | + | ||
| 299 | + | function online() | |
| 300 | + | if keypadButton:isChecked() then | |
| 301 | + | keypad:raise() | |
| 302 | + | keypad:show() | |
| 303 | + | end | |
| 304 | + | attackerButton:show() | |
| 305 | + | menuButton:show() | |
| 306 | + | exitButton:show() | |
| 307 | + | optionsButton:show() | |
| 308 | + | hpBar:show() | |
| 309 | + | levelInfo:show() | |
| 310 | + | ammoInfo:show() | |
| 311 | + | expBar:show() | |
| 312 | + | skillBar:show() | |
| 313 | + | onlineMobile:show() | |
| 314 | + | goldMobile:show() | |
| 315 | + | buttonChat:show() | |
| 316 | + | end | |
| 317 | + | ||
| 318 | + | function offline() | |
| 319 | + | keypad:hide() | |
| 320 | + | attackerButton:hide() | |
| 321 | + | menuButton:hide() | |
| 322 | + | exitButton:hide() | |
| 323 | + | optionsButton:hide() | |
| 324 | + | hpBar:hide() | |
| 325 | + | levelInfo:hide() | |
| 326 | + | ammoInfo:hide() | |
| 327 | + | expBar:hide() | |
| 328 | + | skillBar:hide() | |
| 329 | + | onlineMobile:hide() | |
| 330 | + | goldMobile:hide() | |
| 331 | + | buttonChat:hide() | |
| 332 | + | bugButton:hide() | |
| 333 | + | mountButton:hide() | |
| 334 | + | end | |
| 335 | + | ||
| 336 | + | function onMouseMove(widget, pos, offset) | |
| 337 | + | ||
| 338 | + | end | |
| 339 | + | ||
| 340 | + | function onMousePress(widget, pos, button) | |
| 341 | + | overlay:raise() | |
| 342 | + | if button == MouseTouch then -- touch | |
| 343 | + | overlay:raise() | |
| 344 | + | overlay.cursor:show() | |
| 345 | + | overlay.cursor:setPosition({x=pos.x - 32, y = pos.y - 32}) | |
| 346 | + | touchStart = g_clock.millis() | |
| 347 | + | updateCursor() | |
| 348 | + | else | |
| 349 | + | overlay.cursor:hide() | |
| 350 | + | removeEvent(updateCursorEvent) | |
| 351 | + | end | |
| 352 | + | end | |
| 353 | + | ||
| 354 | + | function onMouseRelease(widget, pos, button) | |
| 355 | + | if button == MouseTouch then | |
| 356 | + | overlay.cursor:hide() | |
| 357 | + | removeEvent(updateCursorEvent) | |
| 358 | + | end | |
| 359 | + | end | |
| 360 | + | ||
| 361 | + | function updateCursor() | |
| 362 | + | removeEvent(updateCursorEvent) | |
| 363 | + | if not g_mouse.isPressed(MouseTouch) then return end | |
| 364 | + | local percent = 100 - math.max(0, math.min(100, (g_clock.millis() - touchStart) / 5)) -- 500 ms | |
| 365 | + | overlay.cursor:setPercent(percent) | |
| 366 | + | if percent > 0 then | |
| 367 | + | overlay.cursor:setOpacity(0.5) | |
| 368 | + | updateCursorEvent = scheduleEvent(updateCursor, 10) | |
| 369 | + | else | |
| 370 | + | overlay.cursor:setOpacity(0.8) | |
| 371 | + | end | |
| 372 | + | end | |
| 373 | + | ||
| 374 | + | function onKeypadTouchMove(widget, pos, offset) | |
| 375 | + | keypadMousePos = {x=(pos.x - widget:getPosition().x) / widget:getWidth(), | |
| 376 | + | y=(pos.y - widget:getPosition().y) / widget:getHeight()} | |
| 377 | + | return true | |
| 378 | + | end | |
| 379 | + | ||
| 380 | + | function onKeypadTouchPress(widget, pos, button) | |
| 381 | + | if button ~= MouseTouch then return false end | |
| 382 | + | keypadTicks = 0 | |
| 383 | + | keypadMousePos = {x=(pos.x - widget:getPosition().x) / widget:getWidth(), | |
| 384 | + | y=(pos.y - widget:getPosition().y) / widget:getHeight()} | |
| 385 | + | executeWalk() | |
| 386 | + | return true | |
| 387 | + | end | |
| 388 | + | ||
| 389 | + | function onKeypadTouchRelease(widget, pos, button) | |
| 390 | + | if button ~= MouseTouch then return false end | |
| 391 | + | keypadMousePos = {x=(pos.x - widget:getPosition().x) / widget:getWidth(), | |
| 392 | + | y=(pos.y - widget:getPosition().y) / widget:getHeight()} | |
| 393 | + | executeWalk() | |
| 394 | + | removeEvent(keypadEvent) | |
| 395 | + | keypad.pointer:setMarginTop(0) | |
| 396 | + | keypad.pointer:setMarginLeft(0) | |
| 397 | + | return true | |
| 398 | + | end | |
| 399 | + | ||
| 400 | + | function executeWalk() | |
| 401 | + | removeEvent(keypadEvent) | |
| 402 | + | keypadEvent = nil | |
| 403 | + | if not modules.game_walking or not g_mouse.isPressed(MouseTouch) then | |
| 404 | + | keypad.pointer:setMarginTop(0) | |
| 405 | + | keypad.pointer:setMarginLeft(0) | |
| 406 | + | return | |
| 407 | + | end | |
| 408 | + | keypadEvent = scheduleEvent(executeWalk, 20) | |
| 409 | + | keypadMousePos.x = math.min(1, math.max(0, keypadMousePos.x)) | |
| 410 | + | keypadMousePos.y = math.min(1, math.max(0, keypadMousePos.y)) | |
| 411 | + | local angle = math.atan2(keypadMousePos.x - 0.5, keypadMousePos.y - 0.5) | |
| 412 | + | local maxTop = math.abs(math.cos(angle)) * 75 | |
| 413 | + | local marginTop = math.max(-maxTop, math.min(maxTop, (keypadMousePos.y - 0.5) * 150)) | |
| 414 | + | local maxLeft = math.abs(math.sin(angle)) * 75 | |
| 415 | + | local marginLeft = math.max(-maxLeft, math.min(maxLeft, (keypadMousePos.x - 0.5) * 150)) | |
| 416 | + | keypad.pointer:setMarginTop(marginTop) | |
| 417 | + | keypad.pointer:setMarginLeft(marginLeft) | |
| 418 | + | local dir | |
| 419 | + | if keypadMousePos.y < 0.3 and keypadMousePos.x < 0.3 then | |
| 420 | + | dir = Directions.NorthWest | |
| 421 | + | elseif keypadMousePos.y < 0.3 and keypadMousePos.x > 0.7 then | |
| 422 | + | dir = Directions.NorthEast | |
| 423 | + | elseif keypadMousePos.y > 0.7 and keypadMousePos.x < 0.3 then | |
| 424 | + | dir = Directions.SouthWest | |
| 425 | + | elseif keypadMousePos.y > 0.7 and keypadMousePos.x > 0.7 then | |
| 426 | + | dir = Directions.SouthEast | |
| 427 | + | end | |
| 428 | + | if not dir and (math.abs(keypadMousePos.y - 0.5) > 0.1 or math.abs(keypadMousePos.x - 0.5) > 0.1) then | |
| 429 | + | if math.abs(keypadMousePos.y - 0.5) > math.abs(keypadMousePos.x - 0.5) then | |
| 430 | + | if keypadMousePos.y < 0.5 then | |
| 431 | + | dir = Directions.North | |
| 432 | + | else | |
| 433 | + | dir = Directions.South | |
| 434 | + | end | |
| 435 | + | else | |
| 436 | + | if keypadMousePos.x < 0.5 then | |
| 437 | + | dir = Directions.West | |
| 438 | + | else | |
| 439 | + | dir = Directions.East | |
| 440 | + | end | |
| 441 | + | end | |
| 442 | + | end | |
| 443 | + | if dir then | |
| 444 | + | modules.game_walking.walk(dir, keypadTicks) | |
| 445 | + | if keypadTicks == 0 then | |
| 446 | + | keypadTicks = 100 | |
| 447 | + | end | |
| 448 | + | end | |
| 449 | + | end |
| @@ -0,0 +1,9 @@ | |||
| 1 | + | Module | |
| 2 | + | name: client_mobile | |
| 3 | + | description: Handles the mobile interface for smartphones | |
| 4 | + | author: otclient@otclient.ovh | |
| 5 | + | website: http://otclient.net | |
| 6 | + | sandboxed: true | |
| 7 | + | scripts: [ mobile ] | |
| 8 | + | @onLoad: init() | |
| 9 | + | @onUnload: terminate() |
| @@ -0,0 +1,326 @@ | |||
| 1 | + | UIWidget | |
| 2 | + | anchors.fill: parent | |
| 3 | + | focusable: false | |
| 4 | + | phantom: true | |
| 5 | + | ||
| 6 | + | UIProgressRect | |
| 7 | + | id: cursor | |
| 8 | + | size: 64 64 | |
| 9 | + | background: #FF5858 | |
| 10 | + | percent: 100 | |
| 11 | + | visible: false | |
| 12 | + | x: 0 | |
| 13 | + | y: 0 | |
| 14 | + | focusable: false | |
| 15 | + | phantom: true | |
| 16 | + | ||
| 17 | + | Panel | |
| 18 | + | id: skillBar | |
| 19 | + | focusable: false | |
| 20 | + | image-source: /images/custom/UI/back_menu | |
| 21 | + | anchors.top: parent.top | |
| 22 | + | anchors.bottom: parent.bottom | |
| 23 | + | anchors.right: parent.right | |
| 24 | + | visible: true | |
| 25 | + | width: 64 | |
| 26 | + | ||
| 27 | + | UIButton | |
| 28 | + | id: sup02 | |
| 29 | + | size: 52 52 | |
| 30 | + | image-source: /images/custom/Spells/atr_0 | |
| 31 | + | anchors.bottom: parent.bottom | |
| 32 | + | anchors.right: parent.right | |
| 33 | + | margin-right: 05 | |
| 34 | + | margin-bottom: 07 | |
| 35 | + | visible: true | |
| 36 | + | phantom: false | |
| 37 | + | ||
| 38 | + | UIButton | |
| 39 | + | id: sup01 | |
| 40 | + | size: 52 52 | |
| 41 | + | image-source: /images/custom/Spells/atr_0 | |
| 42 | + | anchors.bottom: sup02.top | |
| 43 | + | anchors.right: parent.right | |
| 44 | + | margin-right: 05 | |
| 45 | + | margin-bottom: 07 | |
| 46 | + | visible: true | |
| 47 | + | phantom: false | |
| 48 | + | ||
| 49 | + | UIButton | |
| 50 | + | id: qntSkill | |
| 51 | + | size: 55 15 | |
| 52 | + | text: 05 | |
| 53 | + | font: lucida-11px-rounded | |
| 54 | + | anchors.bottom: sup02.top | |
| 55 | + | anchors.right: parent.right | |
| 56 | + | margin-right: 03 | |
| 57 | + | margin-bottom: 08 | |
| 58 | + | visible: true | |
| 59 | + | phantom: true | |
| 60 | + | ||
| 61 | + | UIButton | |
| 62 | + | id: spell01 | |
| 63 | + | size: 52 52 | |
| 64 | + | image-source: /images/custom/Spells/atr_0 | |
| 65 | + | anchors.bottom: sup01.top | |
| 66 | + | anchors.right: parent.right | |
| 67 | + | margin-right: 05 | |
| 68 | + | margin-bottom: 07 | |
| 69 | + | visible: true | |
| 70 | + | phantom: false | |
| 71 | + | ||
| 72 | + | UIButton | |
| 73 | + | id: spell02 | |
| 74 | + | size: 52 52 | |
| 75 | + | image-source: /images/custom/Spells/atr_0 | |
| 76 | + | anchors.bottom: spell01.top | |
| 77 | + | anchors.right: parent.right | |
| 78 | + | margin-right: 05 | |
| 79 | + | margin-bottom: 07 | |
| 80 | + | visible: true | |
| 81 | + | phantom: false | |
| 82 | + | ||
| 83 | + | UIButton | |
| 84 | + | id: spell03 | |
| 85 | + | size: 52 52 | |
| 86 | + | image-source: /images/custom/Spells/atr_0 | |
| 87 | + | anchors.bottom: spell02.top | |
| 88 | + | anchors.right: parent.right | |
| 89 | + | margin-right: 05 | |
| 90 | + | margin-bottom: 07 | |
| 91 | + | visible: true | |
| 92 | + | phantom: false | |
| 93 | + | ||
| 94 | + | UIButton | |
| 95 | + | id: sup03 | |
| 96 | + | size: 52 52 | |
| 97 | + | image-source: /images/custom/Spells/maestria0 | |
| 98 | + | anchors.bottom: spell03.top | |
| 99 | + | anchors.right: parent.right | |
| 100 | + | margin-right: 05 | |
| 101 | + | margin-bottom: 07 | |
| 102 | + | visible: true | |
| 103 | + | phantom: false | |
| 104 | + | ||
| 105 | + | UIButton | |
| 106 | + | id: attacker | |
| 107 | + | size: 62 62 | |
| 108 | + | anchors.bottom: parent.bottom | |
| 109 | + | anchors.right: parent.right | |
| 110 | + | image-source: /images/custom/UI/atk_mobile | |
| 111 | + | image-fixed-ratio: true | |
| 112 | + | margin-bottom: 23 | |
| 113 | + | margin-right: 85 | |
| 114 | + | phantom: false | |
| 115 | + | focusable: false | |
| 116 | + | ||
| 117 | + | UIButton | |
| 118 | + | id: ammoInfo | |
| 119 | + | size: 75 18 | |
| 120 | + | image-source: /images/custom/UI/mobileAmmo | |
| 121 | + | anchors.bottom: parent.bottom | |
| 122 | + | anchors.right: parent.right | |
| 123 | + | margin-bottom: 05 | |
| 124 | + | margin-right: 78 | |
| 125 | + | phantom: false | |
| 126 | + | focusable: false | |
| 127 | + | ||
| 128 | + | UIButton | |
| 129 | + | id: levelInfo | |
| 130 | + | size: 40 15 | |
| 131 | + | font: terminus-10px | |
| 132 | + | image-source: /images/custom/UI/0 | |
| 133 | + | anchors.top: parent.top | |
| 134 | + | anchors.left: parent.left | |
| 135 | + | margin-top: 10 | |
| 136 | + | margin-left: 10 | |
| 137 | + | phantom: false | |
| 138 | + | focusable: false | |
| 139 | + | ||
| 140 | + | ProgressBar | |
| 141 | + | id: hpBar | |
| 142 | + | size: 150 15 | |
| 143 | + | font: terminus-10px | |
| 144 | + | image-source: /images/custom/UI/HP | |
| 145 | + | background-color: #00BC00FF | |
| 146 | + | anchors.top: parent.top | |
| 147 | + | anchors.left: levelInfo.right | |
| 148 | + | margin-top: 10 | |
| 149 | + | margin-left: 02 | |
| 150 | + | phantom: true | |
| 151 | + | focusable: false | |
| 152 | + | ||
| 153 | + | UIButton | |
| 154 | + | id: goldMobile | |
| 155 | + | size: 100 17 | |
| 156 | + | anchors.top: parent.top | |
| 157 | + | anchors.left: hpBar.right | |
| 158 | + | image-source: /images/custom/UI/mobileGold | |
| 159 | + | image-fixed-ratio: true | |
| 160 | + | margin-top: 09 | |
| 161 | + | margin-left: 05 | |
| 162 | + | phantom: true | |
| 163 | + | focusable: false | |
| 164 | + | ||
| 165 | + | UIButton | |
| 166 | + | id: onlineMobile | |
| 167 | + | size: 100 17 | |
| 168 | + | anchors.top: parent.top | |
| 169 | + | anchors.left: goldMobile.right | |
| 170 | + | image-source: /images/custom/UI/mobileOnline | |
| 171 | + | image-fixed-ratio: true | |
| 172 | + | margin-top: 09 | |
| 173 | + | margin-left: 05 | |
| 174 | + | phantom: true | |
| 175 | + | focusable: false | |
| 176 | + | ||
| 177 | + | UIButton | |
| 178 | + | id: mobileDGTime | |
| 179 | + | size: 100 17 | |
| 180 | + | anchors.top: parent.top | |
| 181 | + | anchors.left: hpBar.right | |
| 182 | + | image-source: /images/custom/UI/mobileDG | |
| 183 | + | image-fixed-ratio: true | |
| 184 | + | margin-top: 09 | |
| 185 | + | margin-left: 05 | |
| 186 | + | phantom: true | |
| 187 | + | visible: false | |
| 188 | + | focusable: false | |
| 189 | + | ||
| 190 | + | UIButton | |
| 191 | + | id: mobileDGDesistir | |
| 192 | + | size: 100 17 | |
| 193 | + | text: DESISTIR | |
| 194 | + | anchors.top: parent.top | |
| 195 | + | anchors.left: goldMobile.right | |
| 196 | + | image-source: /images/custom/UI/button | |
| 197 | + | image-fixed-ratio: true | |
| 198 | + | margin-top: 09 | |
| 199 | + | margin-left: 05 | |
| 200 | + | phantom: false | |
| 201 | + | visible: false | |
| 202 | + | focusable: false | |
| 203 | + | @onClick: modules.game_alert.onDGDesistir() | |
| 204 | + | ||
| 205 | + | Panel | |
| 206 | + | id: conditionMobilePanel | |
| 207 | + | phantom: true | |
| 208 | + | layout: | |
| 209 | + | type: horizontalBox | |
| 210 | + | size: 150 22 | |
| 211 | + | padding: 2 | |
| 212 | + | anchors.top: parent.top | |
| 213 | + | anchors.left: parent.left | |
| 214 | + | margin-top: 28 | |
| 215 | + | margin-left: 48 | |
| 216 | + | ||
| 217 | + | ProgressBar | |
| 218 | + | id: expBar | |
| 219 | + | width: 02 | |
| 220 | + | image-source: /images/custom/UI/0 | |
| 221 | + | anchors.bottom: parent.bottom | |
| 222 | + | anchors.right: parent.right | |
| 223 | + | anchors.left: parent.left | |
| 224 | + | background-color: white | |
| 225 | + | margin-bottom: -13 | |
| 226 | + | margin-right: 64 | |
| 227 | + | phantom: true | |
| 228 | + | focusable: false | |
| 229 | + | ||
| 230 | + | UIButton | |
| 231 | + | id: menu | |
| 232 | + | size: 85 40 | |
| 233 | + | anchors.bottom: parent.bottom | |
| 234 | + | anchors.left: parent.left | |
| 235 | + | image-source: /images/custom/UI/menu_mobile | |
| 236 | + | image-fixed-ratio: true | |
| 237 | + | margin-bottom: 165 | |
| 238 | + | margin-left: -20 | |
| 239 | + | phantom: false | |
| 240 | + | focusable: false | |
| 241 | + | ||
| 242 | + | UIButton | |
| 243 | + | id: buttonChat | |
| 244 | + | focusable: false | |
| 245 | + | image-source: /images/custom/UI/mobileChat | |
| 246 | + | anchors.bottom: parent.bottom | |
| 247 | + | anchors.left: parent.left | |
| 248 | + | margin-left: 70 | |
| 249 | + | margin-bottom: 165 | |
| 250 | + | visible: true | |
| 251 | + | size: 39 39 | |
| 252 | + | @onClick: modules.game_interface.onChatShow() | |
| 253 | + | ||
| 254 | + | UIButton | |
| 255 | + | id: buttonMount | |
| 256 | + | focusable: false | |
| 257 | + | image-source: /images/custom/UI/mobileMount | |
| 258 | + | anchors.bottom: parent.bottom | |
| 259 | + | anchors.left: parent.left | |
| 260 | + | margin-left: 70 | |
| 261 | + | margin-bottom: 210 | |
| 262 | + | visible: true | |
| 263 | + | size: 39 39 | |
| 264 | + | @onClick: modules.game_interface.onMobileMount() | |
| 265 | + | ||
| 266 | + | UIButton | |
| 267 | + | id: buttonBug | |
| 268 | + | focusable: false | |
| 269 | + | image-source: /images/custom/UI/mobileBug | |
| 270 | + | anchors.bottom: parent.bottom | |
| 271 | + | anchors.left: parent.left | |
| 272 | + | margin-left: 70 | |
| 273 | + | margin-bottom: 255 | |
| 274 | + | visible: true | |
| 275 | + | size: 39 39 | |
| 276 | + | @onClick: modules.game_bugreport.show() | |
| 277 | + | ||
| 278 | + | UIButton | |
| 279 | + | id: options | |
| 280 | + | size: 85 40 | |
| 281 | + | anchors.bottom: parent.bottom | |
| 282 | + | anchors.left: parent.left | |
| 283 | + | image-source: /images/custom/UI/options_mobile | |
| 284 | + | image-fixed-ratio: true | |
| 285 | + | margin-bottom: 210 | |
| 286 | + | margin-left: -20 | |
| 287 | + | phantom: false | |
| 288 | + | focusable: false | |
| 289 | + | @onClick: modules.client_options.show() | |
| 290 | + | ||
| 291 | + | UIButton | |
| 292 | + | id: exitgame | |
| 293 | + | size: 85 40 | |
| 294 | + | anchors.bottom: parent.bottom | |
| 295 | + | anchors.left: parent.left | |
| 296 | + | image-source: /images/custom/UI/exit_mobile | |
| 297 | + | image-fixed-ratio: true | |
| 298 | + | margin-bottom: 255 | |
| 299 | + | margin-left: -20 | |
| 300 | + | phantom: false | |
| 301 | + | focusable: false | |
| 302 | + | @onClick: modules.game_interface.tryLogout(true) | |
| 303 | + | ||
| 304 | + | UIWidget | |
| 305 | + | id: keypad | |
| 306 | + | size: 200 150 | |
| 307 | + | anchors.bottom: parent.bottom | |
| 308 | + | anchors.left: parent.left | |
| 309 | + | phantom: false | |
| 310 | + | focusable: false | |
| 311 | + | margin-bottom: 05 | |
| 312 | + | visible: false | |
| 313 | + | image-source: /images/game/mobile/keypad | |
| 314 | + | image-fixed-ratio: true | |
| 315 | + | image-rect: 25 0 150 150 | |
| 316 | + | ||
| 317 | + | UIWidget | |
| 318 | + | id: pointer | |
| 319 | + | size: 49 49 | |
| 320 | + | anchors.verticalCenter: parent.verticalCenter | |
| 321 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 322 | + | image-source: /images/game/mobile/keypad_pointer | |
| 323 | + | image-fixed-ratio: true | |
| 324 | + | phantom: true | |
| 325 | + | focusable: false | |
| 326 | + |
| @@ -0,0 +1,86 @@ | |||
| 1 | + | OptionPanel | |
| 2 | + | OptionCheckBox | |
| 3 | + | id: enableAudio | |
| 4 | + | margin: 0 0 0 8 | |
| 5 | + | ||
| 6 | + | UILabel | |
| 7 | + | id: label | |
| 8 | + | anchors.left: parent.left | |
| 9 | + | anchors.verticalCenter: parent.verticalCenter | |
| 10 | + | size: 275 30 | |
| 11 | + | !text: tr('Enable audio') | |
| 12 | + | text-offset: 0 5 | |
| 13 | + | font: poppins-14-px | |
| 14 | + | ||
| 15 | + | OptionCheckBox | |
| 16 | + | id: enableMusicSound | |
| 17 | + | margin: 27 0 0 8 | |
| 18 | + | ||
| 19 | + | UILabel | |
| 20 | + | id: label | |
| 21 | + | anchors.left: parent.left | |
| 22 | + | anchors.verticalCenter: parent.verticalCenter | |
| 23 | + | size: 275 30 | |
| 24 | + | !text: tr('Enable music sound') | |
| 25 | + | text-offset: 0 5 | |
| 26 | + | font: poppins-14-px | |
| 27 | + | ||
| 28 | + | UIWidget | |
| 29 | + | id: musicSoundVolumeBG | |
| 30 | + | margin: 27 0 0 2 | |
| 31 | + | height: 15 | |
| 32 | + | font: poppins-14-px | |
| 33 | + | text: Music volume | |
| 34 | + | text-align: left | |
| 35 | + | text-offset: 2 -2 | |
| 36 | + | ||
| 37 | + | OptionScrollbar | |
| 38 | + | id: musicSoundVolume | |
| 39 | + | anchors.verticalCenter: parent.verticalCenter | |
| 40 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 41 | + | margin: 0 0 0 105 | |
| 42 | + | width: 220 | |
| 43 | + | minimum: 0 | |
| 44 | + | maximum: 100 | |
| 45 | + | ||
| 46 | + | Label | |
| 47 | + | id: musicSoundVolumeLabelBG | |
| 48 | + | anchors.top: parent.top | |
| 49 | + | anchors.right: parent.right | |
| 50 | + | width: 35 | |
| 51 | + | margin: 0 29 0 0 | |
| 52 | + | font: poppins-14-px | |
| 53 | + | color: #77f558 | |
| 54 | + | @onSetup: | | |
| 55 | + | local value = modules.client_options.getOption('musicSoundVolume') | |
| 56 | + | self:setText(tr('%d', value)) | |
| 57 | + | ||
| 58 | + | UIWidget | |
| 59 | + | id: botSoundVolumeBG | |
| 60 | + | margin: 27 0 0 2 | |
| 61 | + | height: 15 | |
| 62 | + | font: poppins-14-px | |
| 63 | + | text: Bot sound volume | |
| 64 | + | text-align: left | |
| 65 | + | text-offset: 2 -2 | |
| 66 | + | ||
| 67 | + | OptionScrollbar | |
| 68 | + | id: botSoundVolume | |
| 69 | + | anchors.verticalCenter: parent.verticalCenter | |
| 70 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 71 | + | margin: 0 0 0 105 | |
| 72 | + | width: 220 | |
| 73 | + | minimum: 0 | |
| 74 | + | maximum: 100 | |
| 75 | + | ||
| 76 | + | Label | |
| 77 | + | id: botSoundVolumeLabelBG | |
| 78 | + | anchors.top: parent.top | |
| 79 | + | anchors.right: parent.right | |
| 80 | + | width: 35 | |
| 81 | + | margin: 0 29 0 0 | |
| 82 | + | font: poppins-14-px | |
| 83 | + | color: #77f558 | |
| 84 | + | @onSetup: | | |
| 85 | + | local value = modules.client_options.getOption('botSoundVolume') | |
| 86 | + | self:setText(tr('%d', value)) |
| @@ -0,0 +1,91 @@ | |||
| 1 | + | OptionPanel | |
| 2 | + | OptionCheckBox | |
| 3 | + | id: showInfoMessagesInConsole | |
| 4 | + | margin: 0 0 0 8 | |
| 5 | + | ||
| 6 | + | UILabel | |
| 7 | + | id: label | |
| 8 | + | anchors.left: parent.left | |
| 9 | + | anchors.verticalCenter: parent.verticalCenter | |
| 10 | + | size: 275 30 | |
| 11 | + | !text: tr('Show info messages in console') | |
| 12 | + | text-offset: 0 5 | |
| 13 | + | font: poppins-14-px | |
| 14 | + | ||
| 15 | + | OptionCheckBox | |
| 16 | + | id: showEventMessagesInConsole | |
| 17 | + | margin: 27 0 0 8 | |
| 18 | + | ||
| 19 | + | UILabel | |
| 20 | + | id: label | |
| 21 | + | anchors.left: parent.left | |
| 22 | + | anchors.verticalCenter: parent.verticalCenter | |
| 23 | + | size: 275 30 | |
| 24 | + | !text: tr('Show event messages in console') | |
| 25 | + | text-offset: 0 5 | |
| 26 | + | font: poppins-14-px | |
| 27 | + | ||
| 28 | + | OptionCheckBox | |
| 29 | + | id: showStatusMessagesInConsole | |
| 30 | + | margin: 27 0 0 8 | |
| 31 | + | ||
| 32 | + | UILabel | |
| 33 | + | id: label | |
| 34 | + | anchors.left: parent.left | |
| 35 | + | anchors.verticalCenter: parent.verticalCenter | |
| 36 | + | size: 275 30 | |
| 37 | + | !text: tr('Show status messages in console') | |
| 38 | + | text-offset: 0 5 | |
| 39 | + | font: poppins-14-px | |
| 40 | + | ||
| 41 | + | OptionCheckBox | |
| 42 | + | id: showTimestampsInConsole | |
| 43 | + | margin: 27 0 0 8 | |
| 44 | + | ||
| 45 | + | UILabel | |
| 46 | + | id: label | |
| 47 | + | anchors.left: parent.left | |
| 48 | + | anchors.verticalCenter: parent.verticalCenter | |
| 49 | + | size: 275 30 | |
| 50 | + | !text: tr('Show timestamps in console') | |
| 51 | + | text-offset: 0 5 | |
| 52 | + | font: poppins-14-px | |
| 53 | + | ||
| 54 | + | OptionCheckBox | |
| 55 | + | id: showLevelsInConsole | |
| 56 | + | margin: 27 0 0 8 | |
| 57 | + | ||
| 58 | + | UILabel | |
| 59 | + | id: label | |
| 60 | + | anchors.left: parent.left | |
| 61 | + | anchors.verticalCenter: parent.verticalCenter | |
| 62 | + | size: 275 30 | |
| 63 | + | !text: tr('Show levels in console') | |
| 64 | + | text-offset: 0 5 | |
| 65 | + | font: poppins-14-px | |
| 66 | + | ||
| 67 | + | OptionCheckBox | |
| 68 | + | id: showPrivateMessagesInConsole | |
| 69 | + | margin: 27 0 0 8 | |
| 70 | + | ||
| 71 | + | UILabel | |
| 72 | + | id: label | |
| 73 | + | anchors.left: parent.left | |
| 74 | + | anchors.verticalCenter: parent.verticalCenter | |
| 75 | + | size: 275 30 | |
| 76 | + | !text: tr('Show private messages in console') | |
| 77 | + | text-offset: 0 5 | |
| 78 | + | font: poppins-14-px | |
| 79 | + | ||
| 80 | + | OptionCheckBox | |
| 81 | + | id: showPrivateMessagesOnScreen | |
| 82 | + | margin: 27 0 0 8 | |
| 83 | + | ||
| 84 | + | UILabel | |
| 85 | + | id: label | |
| 86 | + | anchors.left: parent.left | |
| 87 | + | anchors.verticalCenter: parent.verticalCenter | |
| 88 | + | size: 275 30 | |
| 89 | + | !text: tr('Show private messages on screen') | |
| 90 | + | text-offset: 0 5 | |
| 91 | + | font: poppins-14-px |
| @@ -0,0 +1,88 @@ | |||
| 1 | + | OptionPanel | |
| 2 | + | ||
| 3 | + | OptionCheckBox | |
| 4 | + | id: classicControl | |
| 5 | + | margin: 0 0 0 8 | |
| 6 | + | ||
| 7 | + | $mobile: | |
| 8 | + | visible: false | |
| 9 | + | ||
| 10 | + | UILabel | |
| 11 | + | id: label | |
| 12 | + | anchors.left: parent.left | |
| 13 | + | anchors.verticalCenter: parent.verticalCenter | |
| 14 | + | size: 275 30 | |
| 15 | + | !text: tr('Classic control') | |
| 16 | + | text-offset: 0 5 | |
| 17 | + | font: poppins-14-px | |
| 18 | + | ||
| 19 | + | OptionCheckBox | |
| 20 | + | id: autoChaseOverride | |
| 21 | + | margin: 27 0 0 8 | |
| 22 | + | ||
| 23 | + | UILabel | |
| 24 | + | id: label | |
| 25 | + | anchors.left: parent.left | |
| 26 | + | anchors.verticalCenter: parent.verticalCenter | |
| 27 | + | size: 275 30 | |
| 28 | + | !text: tr('Allow auto chase override') | |
| 29 | + | text-offset: 0 5 | |
| 30 | + | font: poppins-14-px | |
| 31 | + | ||
| 32 | + | OptionCheckBox | |
| 33 | + | id: displayText | |
| 34 | + | margin: 27 0 0 8 | |
| 35 | + | ||
| 36 | + | UILabel | |
| 37 | + | id: label | |
| 38 | + | anchors.left: parent.left | |
| 39 | + | anchors.verticalCenter: parent.verticalCenter | |
| 40 | + | size: 275 30 | |
| 41 | + | !text: tr('Display text messages') | |
| 42 | + | text-offset: 0 5 | |
| 43 | + | font: poppins-14-px | |
| 44 | + | ||
| 45 | + | OptionCheckBox | |
| 46 | + | id: wsadWalking | |
| 47 | + | margin: 27 0 0 8 | |
| 48 | + | $mobile: | |
| 49 | + | visible: false | |
| 50 | + | ||
| 51 | + | UILabel | |
| 52 | + | id: label | |
| 53 | + | anchors.left: parent.left | |
| 54 | + | anchors.verticalCenter: parent.verticalCenter | |
| 55 | + | size: 275 30 | |
| 56 | + | !text: tr('Enable WSAD walking') | |
| 57 | + | text-offset: 0 5 | |
| 58 | + | !tooltip: tr('Disable chat and allow walk using WSAD keys') | |
| 59 | + | font: poppins-14-px | |
| 60 | + | ||
| 61 | + | OptionCheckBox | |
| 62 | + | id: smartWalk | |
| 63 | + | margin: 27 0 0 8 | |
| 64 | + | ||
| 65 | + | UILabel | |
| 66 | + | id: label | |
| 67 | + | anchors.left: parent.left | |
| 68 | + | anchors.verticalCenter: parent.verticalCenter | |
| 69 | + | size: 275 30 | |
| 70 | + | !text: tr('Enable smart walking') | |
| 71 | + | text-offset: 0 5 | |
| 72 | + | !tooltip: tr('Will detect when to use diagonal step based on the\nkeys you are pressing') | |
| 73 | + | font: poppins-14-px | |
| 74 | + | ||
| 75 | + | Panel | |
| 76 | + | margin: 27 0 0 4 | |
| 77 | + | height: 30 | |
| 78 | + | ||
| 79 | + | UIButton | |
| 80 | + | id: changeLocale | |
| 81 | + | !text: tr('Change language') | |
| 82 | + | font: poppins-14-px-semibold | |
| 83 | + | image-source: buttons/smallbutton | |
| 84 | + | @onClick: modules.client_locales.createWindow() | |
| 85 | + | anchors.left: parent.left | |
| 86 | + | anchors.top: parent.top | |
| 87 | + | size: 160 50 | |
| 88 | + | image-border: 11 |
| @@ -0,0 +1,258 @@ | |||
| 1 | + | OptionPanel | |
| 2 | + | Label | |
| 3 | + | text-wrap: false | |
| 4 | + | font: poppins-14-px | |
| 5 | + | @onSetup: | | |
| 6 | + | self:setText(tr("GPU: ") .. g_graphics.getRenderer()) | |
| 7 | + | ||
| 8 | + | Label | |
| 9 | + | text-wrap: false | |
| 10 | + | font: poppins-14-px | |
| 11 | + | @onSetup: | | |
| 12 | + | self:setText(tr("Version: ") .. g_graphics.getVersion()) | |
| 13 | + | ||
| 14 | + | HorizontalSeparator | |
| 15 | + | id: separator | |
| 16 | + | margin: 5 5 5 5 | |
| 17 | + | ||
| 18 | + | OptionCheckBox | |
| 19 | + | id: vsync | |
| 20 | + | margin: 27 0 0 8 | |
| 21 | + | ||
| 22 | + | UILabel | |
| 23 | + | id: label | |
| 24 | + | anchors.left: parent.left | |
| 25 | + | anchors.verticalCenter: parent.verticalCenter | |
| 26 | + | size: 275 30 | |
| 27 | + | !text: tr('Enable vertical synchronization') | |
| 28 | + | !tooltip: tr('Limits FPS (usually to 60)') | |
| 29 | + | text-offset: 0 5 | |
| 30 | + | font: poppins-14-px | |
| 31 | + | ||
| 32 | + | OptionCheckBox | |
| 33 | + | id: showFps | |
| 34 | + | margin: 27 0 0 8 | |
| 35 | + | ||
| 36 | + | UILabel | |
| 37 | + | id: label | |
| 38 | + | anchors.left: parent.left | |
| 39 | + | anchors.verticalCenter: parent.verticalCenter | |
| 40 | + | size: 275 30 | |
| 41 | + | !text: tr('Show frame rate') | |
| 42 | + | text-offset: 0 5 | |
| 43 | + | font: poppins-14-px | |
| 44 | + | ||
| 45 | + | OptionCheckBox | |
| 46 | + | id: enableLights | |
| 47 | + | margin: 27 0 0 8 | |
| 48 | + | ||
| 49 | + | UILabel | |
| 50 | + | id: label | |
| 51 | + | anchors.left: parent.left | |
| 52 | + | anchors.verticalCenter: parent.verticalCenter | |
| 53 | + | size: 275 30 | |
| 54 | + | !text: tr('Enable lights') | |
| 55 | + | text-offset: 0 5 | |
| 56 | + | font: poppins-14-px | |
| 57 | + | ||
| 58 | + | OptionCheckBox | |
| 59 | + | id: fullscreen | |
| 60 | + | margin: 27 0 0 8 | |
| 61 | + | tooltip: Ctrl+Shift+F | |
| 62 | + | ||
| 63 | + | UILabel | |
| 64 | + | id: label | |
| 65 | + | anchors.left: parent.left | |
| 66 | + | anchors.verticalCenter: parent.verticalCenter | |
| 67 | + | size: 275 30 | |
| 68 | + | !text: tr('Fullscreen') | |
| 69 | + | text-offset: 0 5 | |
| 70 | + | font: poppins-14-px | |
| 71 | + | ||
| 72 | + | Label | |
| 73 | + | margin: 27 0 0 6 | |
| 74 | + | id: optimizationLevelLabel | |
| 75 | + | font: poppins-14-px | |
| 76 | + | !text: tr("Optimization level") | |
| 77 | + | ||
| 78 | + | OptionComboBox | |
| 79 | + | id: optimizationLevel | |
| 80 | + | image-source: settings/combobox | |
| 81 | + | image-size: 200 40 | |
| 82 | + | font: poppins-14-px | |
| 83 | + | opacity: 0.5 | |
| 84 | + | @onMousePress: | | |
| 85 | + | addEvent(function() | |
| 86 | + | local menuStyle = self:getStyleName() | |
| 87 | + | if self:getStyleName() == 'OptionComboBox' then menuStyle = 'ComboBox' end | |
| 88 | + | local menu | |
| 89 | + | if self.menuScroll then | |
| 90 | + | menu = g_ui.createWidget(menuStyle .. 'PopupScrollMenu') | |
| 91 | + | menu:setHeight(self.menuHeight) | |
| 92 | + | if self.menuScrollStep > 0 then | |
| 93 | + | menu:setScrollbarStep(self.menuScrollStep) | |
| 94 | + | end | |
| 95 | + | else | |
| 96 | + | menu = g_ui.createWidget(menuStyle .. 'PopupMenu') | |
| 97 | + | end | |
| 98 | + | menu:setId(self:getId() .. 'PopupMenu') | |
| 99 | + | for i,v in ipairs(self.options) do | |
| 100 | + | menu:addOption(v.text, function() self:setCurrentOption(v.text) end) | |
| 101 | + | end | |
| 102 | + | menu:setWidth(self:getWidth()) | |
| 103 | + | menu:display({ x = self:getX(), y = self:getY() + self:getHeight() }) | |
| 104 | + | connect(menu, { onDestroy = function() self:setOn(false) end }) | |
| 105 | + | self:setOn(true) | |
| 106 | + | menu:setWidth(200) | |
| 107 | + | menu:setImageSource('settings/comboboxActive') | |
| 108 | + | end) | |
| 109 | + | @onOptionChange: modules.client_options.setOption(self:getId(), self.currentIndex) | |
| 110 | + | @onSetup: | | |
| 111 | + | self:addOption("Automatic") | |
| 112 | + | self:addOption("None") | |
| 113 | + | self:addOption("Low") | |
| 114 | + | self:addOption("Medium") | |
| 115 | + | self:addOption("High") | |
| 116 | + | self:addOption("Maximum") | |
| 117 | + | ||
| 118 | + | Label | |
| 119 | + | !text: tr('High/Maximum optimization level may cause visual defects.') | |
| 120 | + | margin: 5 0 0 4 | |
| 121 | + | height: 30 | |
| 122 | + | font: poppins-14-px | |
| 123 | + | ||
| 124 | + | UIWidget | |
| 125 | + | id: backgroundFrameRateBG | |
| 126 | + | margin: 10 0 0 0 | |
| 127 | + | height: 15 | |
| 128 | + | font: poppins-14-px | |
| 129 | + | text: Game framerate limit | |
| 130 | + | text-align: left | |
| 131 | + | text-offset: 2 -2 | |
| 132 | + | ||
| 133 | + | OptionScrollbar | |
| 134 | + | id: backgroundFrameRate | |
| 135 | + | anchors.verticalCenter: parent.verticalCenter | |
| 136 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 137 | + | margin: 0 0 0 105 | |
| 138 | + | width: 220 | |
| 139 | + | minimum: 10 | |
| 140 | + | maximum: 201 | |
| 141 | + | ||
| 142 | + | Label | |
| 143 | + | id: backgroundFrameRateLabelBG | |
| 144 | + | anchors.top: parent.top | |
| 145 | + | anchors.right: parent.right | |
| 146 | + | width: 35 | |
| 147 | + | margin: 0 35 0 0 | |
| 148 | + | font: poppins-14-px | |
| 149 | + | color: #77f558 | |
| 150 | + | @onSetup: | | |
| 151 | + | local value = modules.client_options.getOption('backgroundFrameRate') | |
| 152 | + | local text = value | |
| 153 | + | if value <= 0 or value >= 201 then | |
| 154 | + | text = 'max' | |
| 155 | + | end | |
| 156 | + | self:setText(tr('%s', text)) | |
| 157 | + | ||
| 158 | + | UIWidget | |
| 159 | + | id: ambientLightBG | |
| 160 | + | margin: 27 0 0 0 | |
| 161 | + | height: 15 | |
| 162 | + | font: poppins-14-px | |
| 163 | + | text: Ambient light | |
| 164 | + | text-align: left | |
| 165 | + | text-offset: 2 -8 | |
| 166 | + | ||
| 167 | + | OptionScrollbar | |
| 168 | + | id: ambientLight | |
| 169 | + | anchors.verticalCenter: parent.verticalCenter | |
| 170 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 171 | + | margin: 0 0 0 105 | |
| 172 | + | width: 220 | |
| 173 | + | minimum: 0 | |
| 174 | + | maximum: 100 | |
| 175 | + | ||
| 176 | + | Label | |
| 177 | + | id: ambientLightLabelBG | |
| 178 | + | anchors.top: parent.top | |
| 179 | + | anchors.right: parent.right | |
| 180 | + | width: 35 | |
| 181 | + | margin: 0 29 0 0 | |
| 182 | + | font: poppins-14-px | |
| 183 | + | color: #77f558 | |
| 184 | + | @onSetup: | | |
| 185 | + | local value = modules.client_options.getOption('ambientLight') | |
| 186 | + | self:setText(tr('%s%%', value)) | |
| 187 | + | ||
| 188 | + | UIWidget | |
| 189 | + | id: missilesOpacityBG | |
| 190 | + | margin: 27 0 0 0 | |
| 191 | + | height: 15 | |
| 192 | + | font: poppins-14-px | |
| 193 | + | text: Missiles opacity | |
| 194 | + | text-align: left | |
| 195 | + | text-offset: 2 -8 | |
| 196 | + | ||
| 197 | + | OptionScrollbar | |
| 198 | + | id: missilesOpacity | |
| 199 | + | anchors.verticalCenter: parent.verticalCenter | |
| 200 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 201 | + | margin: 0 0 0 105 | |
| 202 | + | width: 220 | |
| 203 | + | minimum: 1 | |
| 204 | + | maximum: 100 | |
| 205 | + | ||
| 206 | + | Label | |
| 207 | + | id: missilesOpacityLabelBG | |
| 208 | + | anchors.top: parent.top | |
| 209 | + | anchors.right: parent.right | |
| 210 | + | width: 35 | |
| 211 | + | margin: 0 29 0 0 | |
| 212 | + | font: poppins-14-px | |
| 213 | + | color: #77f558 | |
| 214 | + | @onSetup: | | |
| 215 | + | local value = modules.client_options.getOption('missilesOpacity') | |
| 216 | + | self:setText(tr('%s%%', value)) | |
| 217 | + | ||
| 218 | + | UIWidget | |
| 219 | + | id: effectsOpacityBG | |
| 220 | + | margin: 27 0 0 0 | |
| 221 | + | height: 15 | |
| 222 | + | font: poppins-14-px | |
| 223 | + | text: Effects opacity | |
| 224 | + | text-align: left | |
| 225 | + | text-offset: 2 -8 | |
| 226 | + | ||
| 227 | + | OptionScrollbar | |
| 228 | + | id: effectsOpacity | |
| 229 | + | anchors.verticalCenter: parent.verticalCenter | |
| 230 | + | anchors.horizontalCenter: parent.horizontalCenter | |
| 231 | + | margin: 0 0 0 105 | |
| 232 | + | width: 220 | |
| 233 | + | minimum: 1 | |
| 234 | + | maximum: 100 | |
| 235 | + | ||
| 236 | + | Label | |
| 237 | + | id: effectsOpacityLabelBG | |
| 238 | + | anchors.top: parent.top | |
| 239 | + | anchors.right: parent.right | |
| 240 | + | width: 35 | |
| 241 | + | margin: 0 29 0 0 | |
| 242 | + | font: poppins-14-px | |
| 243 | + | color: #77f558 | |
| 244 | + | @onSetup: | | |
| 245 | + | local value = modules.client_options.getOption('effectsOpacity') | |
| 246 | + | self:setText(tr('%s%%', value)) | |
| 247 | + | ||
| 248 | + | Label | |
| 249 | + | id: tips | |
| 250 | + | margin-top: 20 | |
| 251 | + | text-auto-resize: true | |
| 252 | + | text-align: left | |
| 253 | + | text-wrap: true | |
| 254 | + | !text: tr("If you have FPS issues:\n- Use OpenGL version (_gl)\n- Disable vertical synchronization\n- Set higher optimization level\n- Lower screen resolution\nOr report it on forum: http://otclient.net") | |
| 255 | + | font: poppins-14-px | |
| 256 | + | $mobile: | |
| 257 | + | visible: false | |
| 258 | + |