Version 1.9

This commit is contained in:
OTCv8
2020-01-21 23:45:52 +01:00
parent 11ad766308
commit be8704ee92
56 changed files with 3517 additions and 483 deletions

View File

@@ -19,6 +19,5 @@ Module
- client_entergamev2
- client_terminal
- client_stats
- client_news
- client_feedback
- client_updater

View File

@@ -15,7 +15,7 @@ local serverSelector
local clientVersionSelector
local serverHostTextEdit
local rememberPasswordBox
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "1077", "1090", "1096", "1098", "1099", "1100"}
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "961", "1077", "1090", "1096", "1098", "1099", "1100"}
-- private functions
local function onProtocolError(protocol, message, errorCode)
@@ -247,7 +247,7 @@ function EnterGame.init()
end
function EnterGame.terminate()
if USE_NEW_ENERGAME then return end
if not enterGame then return end
g_keyboard.unbindKeyDown('Ctrl+G')
enterGame:destroy()
@@ -263,6 +263,7 @@ function EnterGame.terminate()
end
function EnterGame.show()
if not enterGame then return end
if Updater and Updater.isVisible() or g_game.isOnline() then
return EnterGame.hide()
end
@@ -273,6 +274,7 @@ function EnterGame.show()
end
function EnterGame.hide()
if not enterGame then return end
enterGame:hide()
end

View File

@@ -1,5 +1,72 @@
local entergameWindow
local characterGroup
function init()
if not USE_NEW_ENERGAME then return end
entergameWindow = g_ui.displayUI('entergamev2')
--entergameWindow.news:hide()
--entergameWindow.quick:hide()
entergameWindow.registration:hide()
entergameWindow.characters:hide()
entergameWindow.createcharacter:hide()
-- entergame
entergameWindow.entergame.register.onClick = function()
entergameWindow.registration:show()
entergameWindow.entergame:hide()
end
entergameWindow.entergame.mainPanel.button.onClick = function()
entergameWindow.entergame:hide()
entergameWindow.characters:show()
g_game.setClientVersion(1099) -- for tests
end
-- registration
entergameWindow.registration.back.onClick = function()
entergameWindow.registration:hide()
entergameWindow.entergame:show()
end
-- characters
entergameWindow.characters.logout.onClick = function()
entergameWindow.characters:hide()
entergameWindow.entergame:show()
end
entergameWindow.characters.createcharacter.onClick = function()
entergameWindow.characters:hide()
entergameWindow.createcharacter:show()
end
entergameWindow.characters.mainPanel.autoReconnect.onClick = function()
entergameWindow.characters.mainPanel.autoReconnect:setOn(not entergameWindow.characters.mainPanel.autoReconnect:isOn())
end
-- create character
entergameWindow.createcharacter.back.onClick = function()
entergameWindow.createcharacter:hide()
entergameWindow.characters:show()
end
-- tests
characterGroup = UIRadioGroup.create()
for i=1,20 do
local character = g_ui.createWidget('EntergameCharacter', entergameWindow.characters.mainPanel.charactersPanel)
characterGroup:addWidget(character)
character.outfit:setOutfit({feet=10,legs=10,body=176,type=129,auxType=0,addons=3,head=48})
end
characterGroup:selectWidget(entergameWindow.characters.mainPanel.charactersPanel:getFirstChild())
characterGroup:getSelectedWidget()
for i=1,100 do
local l = g_ui.createWidget("NewsLabel", entergameWindow.news.content)
l:setText("test xxx ssss eeee uu u llel " .. i)
end
end
function terminate()
end
if not USE_NEW_ENERGAME then return end
entergameWindow:destroy()
if characterGroup then
characterGroup:destroy()
end
end

View File

@@ -0,0 +1,587 @@
EnterGamePanel < Panel
font: verdana-11px-antialised
color: #dfdfdf
text-offset: 0 6
text-align: top
image-source: /images/ui/window
image-border: 6
image-border-top: 27
padding-top: 28
padding-left: 8
padding-right: 8
padding-bottom: 8
News < EnterGamePanel
id: news
anchors.left: parent.left
anchors.top: parent.top
anchors.bottom: parent.bottom
width: 230
!text: tr("News")
ScrollablePanel
id: content
anchors.fill: parent
margin-right: 8
margin-left: 1
margin-bottom: 5
vertical-scrollbar: newsPanelScroll
layout:
type: verticalBox
SmallScrollBar
id: newsPanelScroll
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
NewsLabel < Label
text-wrap: true
text-auto-resize: true
text-align: center
font: terminus-14px-bold
NewsText < Label
text-wrap: true
text-auto-resize: true
text-align: left
margin-bottom: 10
NewsImage < Label
text-wrap: true
margin-bottom: 5
text-align: center
EnterGame < Panel
anchors.fill: parent
id: entergame
EnterGamePanel
id: mainPanel
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
size: 250 210
!text: tr("Enter Game")
padding-top: 36
padding-left: 16
padding-right: 16
padding-bottom: 16
MenuLabel
!text: tr('Account name')
anchors.left: parent.left
anchors.top: parent.top
text-auto-resize: true
TextEdit
id: account
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Password')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
PasswordTextEdit
id: password
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 10
CheckBox
id: rememberPasswordBox
!text: tr('Remember password')
!tooltip: tr('Remember account and password when starts client')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 9
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 9
Button
id: button
!text: tr('Login')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 10
margin-left: 50
margin-right: 50
EnterGamePanel
id: buttons
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 20
size: 200 50
image-source: /images/ui/window_headless
image-border: 6
padding-top: 8
Button
id: register
anchors.verticalCenter: buttons.verticalCenter
anchors.horizontalCenter: buttons.horizontalCenter
!text: tr("Create account")
size: 160 30
Registration < Panel
anchors.fill: parent
id: registration
EnterGamePanel
id: mainPanel
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
size: 250 262
!text: tr("Create Acoount")
padding-top: 36
padding-left: 16
padding-right: 16
padding-bottom: 16
MenuLabel
!text: tr('Account name')
anchors.left: parent.left
anchors.top: parent.top
text-auto-resize: true
TextEdit
id: accountNameTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Email')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
TextEdit
id: emailTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Password')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
PasswordTextEdit
id: accountPasswordTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Password confirmation')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
PasswordTextEdit
id: accountPasswordTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 9
Button
!text: tr('Create account')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 10
margin-left: 50
margin-right: 50
@onClick: EnterGame.doLogin()
EnterGamePanel
id: buttons
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 20
size: 200 50
image-source: /images/ui/window_headless
image-border: 6
padding-top: 8
Button
id: back
anchors.verticalCenter: buttons.verticalCenter
anchors.horizontalCenter: buttons.horizontalCenter
!text: tr("Back")
size: 160 30
QuickLogin < EnterGamePanel
id: quick
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
size: 230 312
!text: tr("Quick Login & Registration")
UIButton
id: qrcode
width: 200
height: 200
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
image-fixed-ratio: true
image-smooth: false
margin-top: 5
qr: 123
UIButton
id: quathlogo
width: 66
height: 40
anchors.verticalCenter: prev.verticalCenter
anchors.horizontalCenter: prev.horizontalCenter
image-fixed-ratio: true
image-smooth: false
image-source: /images/ui/qauth
Label
anchors.top: qrcode.bottom
anchors.left: qrcode.left
anchors.right: qrcode.right
text-align: center
text-auto-resize: true
!text: tr("Scan or click QR code\nto register or login")
height: 40
margin-top: 10
margin-bottom: 5
Button
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
text-align: center
!text: tr("Click to get PC/Android/iOS app")
height: 23
margin-top: 10
margin-left: 5
margin-right: 5
color: #FFFFFF
@onClick: g_platform.openUrl("http://qauth.co")
Characters < Panel
id: characters
anchors.fill: parent
EnterGamePanel
id: mainPanel
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
size: 550 350
!text: tr("Characters")
padding-top: 36
padding-left: 16
padding-right: 16
padding-bottom: 16
Label
id: motd
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text-auto-resize: true
text-wrap: true
text: This is motd ;)
text-align: center
HorizontalSeparator
id: motdSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 5
height: 10
ScrollablePanel
id: charactersPanel
layout:
type: grid
cell-size: 100 100
cell-spacing: 1
flow: true
vertical-scrollbar: charactersScroll
anchors.top: prev.bottom
anchors.bottom: bottomSeparator.top
anchors.left: parent.left
anchors.right: parent.right
margin-bottom: 10
margin-right: 12
VerticalScrollBar
id: charactersScroll
anchors.top: charactersPanel.top
anchors.bottom: charactersPanel.bottom
anchors.left: charactersPanel.right
step: 14
pixels-scroll: true
HorizontalSeparator
id: bottomSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: parent.bottom
height: 35
Button
id: autoReconnect
!text: tr('Auto reconnect: On')
width: 140
anchors.left: parent.left
anchors.bottom: parent.bottom
image-color: green
$!on:
image-color: red
!text: tr('Auto reconnect: Off')
Button
id: createCharacter
anchors.right: parent.right
anchors.bottom: parent.bottom
!text: tr("Connect")
width: 140
EnterGamePanel
id: buttons
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 20
size: 450 50
image-source: /images/ui/window_headless
image-border: 6
padding-top: 8
Button
id: createcharacter
anchors.verticalCenter: buttons.verticalCenter
anchors.left: buttons.left
!text: tr("Create character")
margin-left: 10
size: 140 30
Button
id: casts
anchors.verticalCenter: buttons.verticalCenter
anchors.horizontalCenter: buttons.horizontalCenter
!text: tr("Casts")
size: 140 30
Button
id: logout
anchors.verticalCenter: buttons.verticalCenter
anchors.right: buttons.right
margin-right: 10
!text: tr("Logout")
size: 140 30
EntergameCharacter < UIButton
border-width: 1
padding: 1 1 1 1
@onClick: self:setChecked(true)
$checked:
border-color: #ffffff
$!checked:
border-color: black
UICreature
id: outfit
anchors.bottom: parent.bottom
anchors.horizontalCenter: parent.horizontalCenter
size: 48 48
margin-bottom: 3
phantom: true
Label
id: line1
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
text: Dagusia Druid
text-align: center
text-wrap: false
height: 16
font: terminus-10px
border-width-bottom: 1
border-color: #00000077
Label
id: line2
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
text: Level: 666
text-align: center
text-wrap: false
height: 16
font: terminus-10px
border-width-bottom: 1
border-color: #00000077
Label
id: line3
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
text: World: nemezis
text-align: center
text-wrap: false
height: 16
font: terminus-10px
border-width-bottom: 1
border-color: #00000077
CreateCharacter < Panel
anchors.fill: parent
id: createcharacter
EnterGamePanel
id: mainPanel
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
size: 250 262
!text: tr("Create Character")
padding-top: 36
padding-left: 16
padding-right: 16
padding-bottom: 16
MenuLabel
!text: tr('Name')
anchors.left: parent.left
anchors.top: parent.top
text-auto-resize: true
TextEdit
id: accountNameTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Vocation')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
TextEdit
id: emailTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Password')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
PasswordTextEdit
id: accountPasswordTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
MenuLabel
!text: tr('Password confirmation')
anchors.left: prev.left
anchors.top: prev.bottom
margin-top: 8
text-auto-resize: true
PasswordTextEdit
id: accountPasswordTextEdit
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 2
HorizontalSeparator
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 9
Button
!text: tr('Create character')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom
margin-top: 10
margin-left: 50
margin-right: 50
@onClick: EnterGame.doLogin()
EnterGamePanel
id: buttons
anchors.horizontalCenter: prev.horizontalCenter
anchors.top: prev.bottom
margin-top: 20
size: 200 50
image-source: /images/ui/window_headless
image-border: 6
padding-top: 8
Button
id: back
anchors.verticalCenter: buttons.verticalCenter
anchors.horizontalCenter: buttons.horizontalCenter
!text: tr("Back")
size: 160 30
Panel
anchors.top: topMenu.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
margin: 10 10 10 10
News
QuickLogin
EnterGame
Registration
Characters
CreateCharacter

View File

@@ -1,119 +0,0 @@
-- private variables
local news
local newsPanel
local updateNewsEvent = nil
local ongoingNewsUpdate = false
local lastNewsUpdate = 0
local newsUpdateInterval = 30 -- seconds
-- public functions
function init()
news = g_ui.displayUI('news')
newsPanel = news:recursiveGetChildById('newsPanel')
connect(rootWidget, { onGeometryChange = updateSize })
connect(g_game, { onGameStart = hide, onGameEnd = show })
if g_game.isOnline() then
hide()
else
show()
end
end
function terminate()
disconnect(rootWidget, { onGeometryChange = updateSize })
disconnect(g_game, { onGameStart = hide, onGameEnd = show })
removeEvent(updateNewsEvent)
clearNews()
news:destroy()
news = nil
end
function hide()
news:hide()
end
function show()
news:show()
updateSize()
updateNews()
end
function updateSize()
if Services.news == nil or Services.news:len() < 4 or g_game.isOnline() then
return
end
if rootWidget:getWidth() < 790 and news:isVisible() then
hide()
elseif news:isHidden() then
show()
end
news:setWidth(math.min(math.max(250, rootWidget:getWidth() / 4), 300))
end
function updateNews()
if Services.news == nil or Services.news:len() < 4 then
hide()
return
end
if ongoingNewsUpdate or os.time() < lastNewsUpdate + newsUpdateInterval then
return
end
HTTP.getJSON(Services.news .. "?lang=" .. modules.client_locales.getCurrentLocale().name, onGotNews)
ongoingNewsUpdate = true
lastNewsUpdate = os.time()
end
function clearNews()
while newsPanel:getChildCount() > 0 do
local child = newsPanel:getLastChild()
newsPanel:destroyChildren(child)
end
end
function onGotNews(data, err)
ongoingNewsUpdate = false
if err then
return gotNewsError("Error:\n" .. err)
end
clearNews()
for i, news in pairs(data) do
local title = news["title"]
local text = news["text"]
local image = news["image"]
if title ~= nil then
newsLabel = g_ui.createWidget('NewsLabel', newsPanel)
newsLabel:setText(title)
end
if text ~= nil then
newsText = g_ui.createWidget('NewsText', newsPanel)
newsText:setText(text)
end
if image ~= nil then
newsImage = g_ui.createWidget('NewsImage', newsPanel)
newsImage:setId(imageName)
newsImage:setImageSourceBase64(image)
newsImage:setImageFixedRatio(true)
newsImage:setImageAutoResize(false)
newsImage:setHeight(200)
end
end
end
function gotNewsError(err)
updateNewsEvent = scheduleEvent(function()
updateNews()
end, 3000)
clearNews()
errorLabel = g_ui.createWidget('NewsLabel', newsPanel)
errorLabel:setText(tr("Error"))
errorInfo = g_ui.createWidget('NewsText', newsPanel)
errorInfo:setText(err)
ongoingNewsUpdate = true
end

View File

@@ -1,10 +0,0 @@
Module
name: client_news
description: News
author: otclient.ovh
website: http://otclient.ovh
sandboxed: true
scripts: [ news ]
dependencies: [ client_topmenu ]
@onLoad: init()
@onUnload: terminate()

View File

@@ -1,47 +0,0 @@
NewsLabel < Label
text-wrap: false
text-auto-resize: true
text-align: center
font: terminus-14px-bold
NewsText < Label
text-wrap: true
text-auto-resize: true
text-align: left
margin-bottom: 10
NewsImage < Label
text-wrap: true
margin-bottom: 5
text-align: center
StaticWindow
anchors.left: parent.left
anchors.top: topMenu.bottom
anchors.bottom: parent.bottom
margin-top: 10
margin-left: 20
margin-bottom: 10
id: newsPanelHolder
width: 300
!text: tr('News')
ScrollablePanel
id: newsPanel
layout:
type: verticalBox
vertical-scrollbar: newsScroll
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
anchors.bottom: parent.bottom
padding-right: 10
margin-right: 10
VerticalScrollBar
id: newsScroll
anchors.top: newsPanel.top
anchors.bottom: newsPanel.bottom
anchors.left: newsPanel.right
step: 14
pixels-scroll: true

View File

@@ -62,7 +62,7 @@ Panel
anchors.left: parent.left
anchors.right: parent.right
margin-top: 3
minimum: 0
minimum: 50
maximum: 300
Label

View File

@@ -3,6 +3,18 @@ Panel
id: classicView
!text: tr('Classic view')
OptionCheckBox
id: cacheMap
!text: tr('Cache map (for non-classic view)')
OptionCheckBox
id: actionBar1
!text: tr("Show first action bar")
OptionCheckBox
id: actionBar2
!text: tr("Show second action bar")
OptionCheckBox
id: showPing
!text: tr('Show connection ping')
@@ -41,7 +53,7 @@ Panel
!text: tr('Highlight things under cursor')
Label
margin-top: 12
margin-top: 5
width: 90
anchors.left: parent.left
anchors.top: prev.bottom
@@ -110,7 +122,7 @@ Panel
self:addOption("4th right panel")
Label
margin-top: 12
margin-top: 3
anchors.left: parent.left
anchors.right: parent.right
anchors.top: prev.bottom

View File

@@ -4,6 +4,7 @@ local defaultOptions = {
showPing = true,
fullscreen = false,
classicView = true,
cacheMap = false,
classicControl = true,
smartWalk = false,
dash = false,
@@ -49,7 +50,10 @@ local defaultOptions = {
walkTurnDelay = 100,
walkStairsDelay = 50,
walkTeleportDelay = 200,
walkCtrlTurnDelay = 150
walkCtrlTurnDelay = 150,
actionBar1 = true,
actionBar2 = false
}
local optionsWindow
@@ -343,8 +347,10 @@ function setOption(key, value, force)
g_settings.set(key, value)
options[key] = value
if key == 'classicView' or key == 'rightPanels' or key == 'leftPanels' then
if key == 'classicView' or key == 'rightPanels' or key == 'leftPanels' or key == 'cacheMap' then
modules.game_interface.refreshViewMode()
elseif key == 'actionBar1' or key == 'actionBar2' then
modules.game_actionbar.show()
end
end

View File

@@ -182,7 +182,9 @@ function HTTP.onDownload(operationId, url, err, path, checksum)
end
if operation.callback then
if operation["type"] == "image" then
HTTP.images[url] = path
if not err then
HTTP.images[url] = path
end
operation.callback('/downloads/' .. path, err)
else
operation.callback(path, checksum, err)

View File

@@ -0,0 +1,330 @@
actionPanel1 = nil
actionPanel2 = nil
local actionConfig
local hotkeyAssignWindow
local actionButtonsInPanel = 50
ActionTypes = {
USE = 0,
USE_SELF = 1,
USE_TARGET = 2,
USE_WITH = 3
}
ActionColors = {
empty = '#00000022',
text = '#88888844',
itemUse = '#8888FF44',
itemUseSelf = '#00FF0044',
itemUseTarget = '#FF000044',
itemUseWith = '#F5B32544'
}
function init()
local bottomPanel = modules.game_interface.getBottomPanel()
actionPanel1 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(actionPanel1, 1)
actionPanel2 = g_ui.loadUI('actionbar', bottomPanel)
bottomPanel:moveChildToIndex(actionPanel2, 1)
actionConfig = g_configs.create("/actionbar.otml")
setupActionPanel(1, actionPanel1)
setupActionPanel(2, actionPanel2)
connect(g_game, {
onGameStart = online,
onGameEnd = offline
})
if g_game.isOnline() then
show()
end
end
function terminate()
disconnect(g_game, {
onGameStart = online,
onGameEnd = offline
})
saveConfig()
-- remove hotkeys
for index, panel in ipairs({actionPanel1, actionPanel2}) do
for i, child in ipairs(panel.tabBar:getChildren()) do
local gameRootPanel = modules.game_interface.getRootPanel()
if child.hotkey then
g_keyboard.unbindKeyPress(child.hotkey, child.callback, gameRootPanel)
end
end
end
actionPanel1:destroy()
actionPanel2:destroy()
end
function show()
actionPanel1:setOn(g_settings.getBoolean("actionBar1", false))
actionPanel2:setOn(g_settings.getBoolean("actionBar2", false))
end
function hide()
actionPanel1:setOn(false)
actionPanel2:setOn(false)
end
function switchMode(newMode)
if newMode then
actionPanel1:setImageColor('#ffffff88')
actionPanel2:setImageColor('#ffffff88')
else
actionPanel1:setImageColor('white')
actionPanel2:setImageColor('white')
end
end
function online()
show()
end
function offline()
hide()
if hotkeyAssignWindow then
hotkeyAssignWindow:destroy()
hotkeyAssignWindow = nil
end
saveConfig()
end
function setupActionPanel(index, panel)
local rawConfig = actionConfig:getNode('actions_' .. index) or {}
local config = {}
for i, buttonConfig in pairs(rawConfig) do -- sorting, because key in rawConfig is string
config[tonumber(i)] = buttonConfig
end
for i=1,actionButtonsInPanel do
local action = g_ui.createWidget('ActionButton', panel.tabBar)
setupAction(index, action, config[i])
end
panel.nextButton.onClick = function()
panel.tabBar:moveChildToIndex(panel.tabBar:getLastChild(), 1)
end
panel.prevButton.onClick = function()
panel.tabBar:moveChildToIndex(panel.tabBar:getFirstChild(), panel.tabBar:getChildCount())
end
end
function saveConfig()
for index, panel in ipairs({actionPanel1, actionPanel2}) do
local config = {}
for i, child in ipairs(panel.tabBar:getChildren()) do
table.insert(config, {
text = child.text:getText(),
item = child.item:getItemId(),
count = child.item:getItemCount(),
action = child.actionType,
hotkey = child.hotkey
})
end
actionConfig:setNode('actions_' .. index, config)
end
actionConfig:save()
end
function setupAction(index, action, config)
action.item:setShowCount(false)
action.onMouseRelease = actionOnMouseRelease
action.callback = function(k, c, ticks) executeAction(action, ticks) end
if config then
action.hotkey = config.hotkey
if action.hotkey then
local gameRootPanel = modules.game_interface.getRootPanel()
g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel)
end
action.hotkeyLabel:setText(action.hotkey or "")
action.text:setText(config.text)
if action.text:getText():len() > 0 then
action:setBorderColor(ActionColors.text)
end
if config.item > 0 then
setupActionType(action, config.action)
end
action.item:setItemId(config.item)
action.item:setItemCount(config.count)
end
action.item.onItemChange = actionOnItemChange
end
function setupActionType(action, actionType)
action.actionType = actionType
if action.actionType == ActionTypes.USE then
action:setBorderColor(ActionColors.itemUse)
elseif action.actionType == ActionTypes.USE_SELF then
action:setBorderColor(ActionColors.itemUseSelf)
elseif action.actionType == ActionTypes.USE_TARGET then
action:setBorderColor(ActionColors.itemUseTarget)
elseif action.actionType == ActionTypes.USE_WITH then
action:setBorderColor(ActionColors.itemUseWith)
end
end
function executeAction(action, ticks)
if type(ticks) ~= 'number' then ticks = 0 end
local actionDelay = 100
if ticks == 0 then
actionDelay = 200 -- for first use
elseif action.actionDelayTo ~= nil and g_clock.millis() < action.actionDelayTo then
return
end
if action.text:getText():len() > 0 then
modules.game_console.sendMessage(action.text:getText())
action.actionDelayTo = g_clock.millis() + actionDelay
elseif action.item:getItemId() > 0 then
if action.actionType == ActionTypes.USE then
if g_game.getClientVersion() < 740 then
local item = g_game.findPlayerItem(action.item:getItemId(), hotKey.subType or -1)
if item then
g_game.use(item)
end
else
g_game.useInventoryItem(action.item:getItemId())
end
action.actionDelayTo = g_clock.millis() + actionDelay
elseif action.actionType == ActionTypes.USE_SELF then
if g_game.getClientVersion() < 740 then
local item = g_game.findPlayerItem(action.item:getItemId(), hotKey.subType or -1)
if item then
g_game.useWith(item, g_game.getLocalPlayer())
end
else
g_game.useInventoryItemWith(action.item:getItemId(), g_game.getLocalPlayer(), action.item:getItemSubType() or -1)
end
action.actionDelayTo = g_clock.millis() + actionDelay
elseif action.actionType == ActionTypes.USE_TARGET then
local attackingCreature = g_game.getAttackingCreature()
if not attackingCreature then
local item = Item.create(action.item:getItemId())
if g_game.getClientVersion() < 740 then
local tmpItem = g_game.findPlayerItem(action.item:getItemId(), action.item:getItemSubType() or -1)
if not tmpItem then return end
item = tmpItem
end
modules.game_interface.startUseWith(item, action.item:getItemSubType() or - 1)
return
end
if not attackingCreature:getTile() then return end
if g_game.getClientVersion() < 740 then
local item = g_game.findPlayerItem(action.item:getItemId(), action.item:getItemSubType() or -1)
if item then
g_game.useWith(item, attackingCreature, action.item:getItemSubType() or -1)
end
else
g_game.useInventoryItemWith(action.item:getItemId(), attackingCreature, action.item:getItemSubType() or -1)
end
action.actionDelayTo = g_clock.millis() + actionDelay
elseif action.actionType == ActionTypes.USE_WITH then
local item = Item.create(action.item:getItemId())
if g_game.getClientVersion() < 740 then
local tmpItem = g_game.findPlayerItem(action.item:getItemId(), action.item:getItemSubType() or -1)
if not tmpItem then return true end
item = tmpItem
end
modules.game_interface.startUseWith(item, action.item:getItemSubType() or - 1)
end
end
end
function actionOnMouseRelease(action, mousePosition, mouseButton)
if mouseButton == MouseRightButton then
local menu = g_ui.createWidget('PopupMenu')
menu:setGameMenu(true)
if action.item:getItemId() > 0 and action.item:getItem():isMultiUse() then
menu:addOption(tr('Use on yourself'), function() return setupActionType(action, ActionTypes.USE_SELF) end)
menu:addOption(tr('Use on target'), function() return setupActionType(action, ActionTypes.USE_TARGET) end)
menu:addOption(tr('With crosshair'), function() return setupActionType(action, ActionTypes.USE_WITH) end)
end
menu:addSeparator()
menu:addOption(tr('Set text'), function()
modules.game_textedit.singlelineEditor(action.text:getText(), function(newText)
action.item:setItemId(0)
action.text:setText(newText)
if action.text:getText():len() > 0 then
action:setBorderColor(ActionColors.text)
end
end)
end)
menu:addOption(tr('Set hotkey'), function()
if hotkeyAssignWindow then
hotkeyAssignWindow:destroy()
end
local assignWindow = g_ui.createWidget('ActionAssignWindow', rootWidget)
assignWindow:grabKeyboard()
assignWindow.comboPreview.keyCombo = ''
assignWindow.onKeyDown = function(assignWindow, keyCode, keyboardModifiers)
local keyCombo = determineKeyComboDesc(keyCode, keyboardModifiers)
assignWindow.comboPreview:setText(tr('Current action hotkey: %s', keyCombo))
assignWindow.comboPreview.keyCombo = keyCombo
assignWindow.comboPreview:resizeToText()
return true
end
assignWindow.onDestroy = function()
hotkeyAssignWindow = nil
end
assignWindow.addButton.onClick = function()
local gameRootPanel = modules.game_interface.getRootPanel()
if action.hotkey then
g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel)
end
action.hotkey = assignWindow.comboPreview.keyCombo
if action.hotkey then
g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel)
end
action.hotkeyLabel:setText(action.hotkey or "")
assignWindow:destroy()
end
hotkeyAssignWindow = assignWindow
end)
menu:addSeparator()
menu:addOption(tr('Clear'), function()
action.item:setItem(nil)
action.text:setText("")
action.hotkeyLabel:setText("")
local gameRootPanel = modules.game_interface.getRootPanel()
if action.hotkey then
g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel)
end
action.hotkey = nil
action.actionType = nil
action:setBorderColor(ActionColors.empty)
end)
menu:display(mousePosition)
return true
elseif mouseButton == MouseLeftButton then
action.callback()
return true
end
return false
end
function actionOnItemChange(widget)
local action = widget:getParent()
if action.item:getItemId() > 0 then
action.text:setText("")
if action.item:getItem():isMultiUse() then
if not action.actionType or action.actionType <= 1 then
setupActionType(action, ActionTypes.USE_WITH)
end
else
setupActionType(action, ActionTypes.USE)
end
end
end

View File

@@ -0,0 +1,9 @@
Module
name: game_actionbar
description: Action bar
author: otclient@otclient.ovh
website: otclient.ovh
sandboxed: true
scripts: [ actionbar ]
@onLoad: init()
@onUnload: terminate()

View File

@@ -0,0 +1,134 @@
ActionButton < Panel
size: 36 36
font: cipsoftFont
anchors.top: parent.top
margin-left: 3
border-width: 1
border-color: #00000022
$first:
anchors.left: parent.left
$!first:
anchors.left: prev.right
Item
id: item
anchors.fill: parent
margin: 1 1 1 1
item-id: 3307
&selectable: true
&editable: false
virtual: true
Label
id: text
anchors.fill: parent
margin: 3 3 3 3
text-auto-resize: true
text-wrap: true
text-align: center
font: verdana-9px
Label
id: hotkeyLabel
anchors.top: parent.top
anchors.left: parent.left
margin: 2 3 3 3
text-auto-resize: true
text-wrap: false
font: small-9px
color: #D3D3D3
Panel
id: actionBar
anchors.left: parent.left
anchors.right: parent.right
image-source: /images/ui/panel_bottom
image-border: 6
focusable: false
$first:
anchors.top: parent.top
$!first:
anchors.top: prev.bottom
$on:
height: 40
visible: true
$!on:
height: 0
visible: false
TabButton
id: prevButton
icon: /images/game/console/leftarrow
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
margin-left: 1
Panel
id: tabBar
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.left: prev.right
anchors.right: next.left
margin-right: 3
margin-top: 2
clipping: true
TabButton
id: nextButton
icon: /images/game/console/rightarrow
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
margin-right: 1
ActionAssignWindow < MainWindow
id: assignWindow
!text: tr('Button Assign')
size: 360 150
@onEscape: self:destroy()
Label
!text: tr('Please, press the key you wish to use for action')
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
text-auto-resize: true
text-align: left
Label
id: comboPreview
!text: tr('Current action hotkey: %s', 'none')
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: prev.bottom
margin-top: 10
text-auto-resize: true
HorizontalSeparator
id: separator
anchors.left: parent.left
anchors.right: parent.right
anchors.bottom: next.top
margin-bottom: 10
Button
id: addButton
!text: tr('Add')
width: 64
anchors.right: next.left
anchors.bottom: parent.bottom
margin-right: 10
Button
id: cancelButton
!text: tr('Cancel')
width: 64
anchors.right: parent.right
anchors.bottom: parent.bottom
@onClick: self:getParent():destroy()

View File

@@ -3,25 +3,16 @@ battleButton = nil
battlePanel = nil
filterPanel = nil
toggleFilterButton = nil
battleButtonsList = {}
mouseWidget = nil
sortTypeBox = nil
sortOrderBox = nil
hidePlayersButton = nil
hideNPCsButton = nil
hideMonstersButton = nil
hideSkullsButton = nil
hidePartyButton = nil
updateEvent = nil
hoveredCreature = nil
newHoveredCreature = nil
prevCreature = nil
local creatureAgeCounter = 1
battleButtons = {}
local ageNumber = 1
function init()
g_ui.importStyle('battlebutton')
@@ -43,13 +34,8 @@ function init()
hideFilterPanel()
end
sortTypeBox = battleWindow:recursiveGetChildById('sortTypeBox')
sortOrderBox = battleWindow:recursiveGetChildById('sortOrderBox')
hidePlayersButton = battleWindow:recursiveGetChildById('hidePlayers')
hideNPCsButton = battleWindow:recursiveGetChildById('hideNPCs')
hideMonstersButton = battleWindow:recursiveGetChildById('hideMonsters')
hideSkullsButton = battleWindow:recursiveGetChildById('hideSkulls')
hidePartyButton = battleWindow:recursiveGetChildById('hideParty')
local sortTypeBox = filterPanel.sortPanel.sortTypeBox
local sortOrderBox = filterPanel.sortPanel.sortOrderBox
mouseWidget = g_ui.createWidget('UIButton')
mouseWidget:setVisible(false)
@@ -70,11 +56,21 @@ function init()
sortOrderBox:setCurrentOptionByData(getSortOrder())
sortOrderBox.onOptionChange = onChangeSortOrder
updateBattleList()
battleWindow:setup()
for i=1,30 do
local battleButton = g_ui.createWidget('BattleButton', battlePanel)
battleButton:setup()
battleButton:hide()
battleButton.onHoverChange = onBattleButtonHoverChange
battleButton.onMouseRelease = onBattleButtonMouseRelease
table.insert(battleButtons, battleButton)
end
updateBattleList()
connect(LocalPlayer, {
onPositionChange = onCreaturePositionChange
onPositionChange = onPlayerPositionChange
})
connect(Creature, {
onAppear = updateSquare,
@@ -91,14 +87,15 @@ function terminate()
return
end
battleButtons = {}
g_keyboard.unbindKeyDown('Ctrl+B')
battleButtonsByCreaturesList = {}
battleButton:destroy()
battleWindow:destroy()
mouseWidget:destroy()
disconnect(LocalPlayer, {
onPositionChange = onCreaturePositionChange
onPositionChange = onPlayerPositionChange
})
disconnect(Creature, {
onAppear = onCreatureAppear,
@@ -216,7 +213,8 @@ end
-- functions
function updateBattleList()
updateEvent = scheduleEvent(updateBattleList, 200)
removeEvent(updateEvent)
updateEvent = scheduleEvent(updateBattleList, 100)
checkCreatures()
end
@@ -229,68 +227,54 @@ function checkCreatures()
if not player then
return
end
local dimension = modules.game_interface.getMapPanel():getVisibleDimension()
local spectators = g_map.getSpectatorsInRangeEx(player:getPosition(), false, math.floor(dimension.width / 2), math.floor(dimension.width / 2), math.floor(dimension.height / 2), math.floor(dimension.height / 2))
local maxCreatures = battlePanel:getChildCount()
local creatures = {}
for _, creature in ipairs(spectators) do
if doCreatureFitFilters(creature) then
if doCreatureFitFilters(creature) and #creatures < maxCreatures then
if not creature.age then
creature.age = ageNumber
ageNumber = ageNumber + 1
end
table.insert(creatures, creature)
end
end
updateSquare()
sortCreatures(creatures)
battlePanel:getLayout():disableUpdates()
-- sorting
local creature_i = 1
sortCreatures(creatures)
for i=1, #creatures do
if creature_i > 30 then
break
end
local ascOrder = isSortAsc()
for i=1,#creatures do
local creature = creatures[i]
if isSortAsc() then
if ascOrder then
creature = creatures[#creatures - i + 1]
end
if creature:getHealthPercent() > 0 then
local battleButton = battleButtonsList[creature_i]
if battleButton == nil then
battleButton = g_ui.createWidget('BattleButton')
battleButton.onHoverChange = onBattleButtonHoverChange
battleButton.onMouseRelease = onBattleButtonMouseRelease
battleButton:setup(creature, creature_i)
table.insert(battleButtonsList, battleButton)
battlePanel:addChild(battleButton)
end
battleButton:creatureSetup(creature)
battleButton:enable()
creature_i = creature_i + 1
end
local battleButton = battleButtons[i]
battleButton:creatureSetup(creature)
battleButton:show()
end
for i=#creatures + 1, 30 do
local battleButton = battleButtonsList[i]
if battleButton then
battleButton:disable()
end
for i=#creatures + 1,maxCreatures do
if battleButtons[i]:isHidden() then break end
battleButtons[i]:hide()
end
local height = 0
if creature_i > 1 then
height = 25 * (creature_i - 1)
end
if battlePanel:getHeight() ~= height then
battlePanel:setHeight(height)
end
battlePanel:getLayout():enableUpdates()
battlePanel:getLayout():update()
end
function doCreatureFitFilters(creature)
if creature:isLocalPlayer() then
return false
end
if creature:getHealthPercent() <= 0 then
return false
end
local pos = creature:getPosition()
if not pos then return false end
@@ -298,11 +282,11 @@ function doCreatureFitFilters(creature)
local localPlayer = g_game.getLocalPlayer()
if pos.z ~= localPlayer:getPosition().z or not creature:canBeSeen() then return false end
local hidePlayers = hidePlayersButton:isChecked()
local hideNPCs = hideNPCsButton:isChecked()
local hideMonsters = hideMonstersButton:isChecked()
local hideSkulls = hideSkullsButton:isChecked()
local hideParty = hidePartyButton:isChecked()
local hidePlayers = filterPanel.buttons.hidePlayers:isChecked()
local hideNPCs = filterPanel.buttons.hideNPCs:isChecked()
local hideMonsters = filterPanel.buttons.hideMonsters:isChecked()
local hideSkulls = filterPanel.buttons.hideSkulls:isChecked()
local hideParty = filterPanel.buttons.hideParty:isChecked()
if hidePlayers and creature:isPlayer() then
return false
@@ -327,26 +311,26 @@ function sortCreatures(creatures)
local player = g_game.getLocalPlayer()
if getSortType() == 'distance' then
local playerPos = player:getPosition()
local playerPos = player:getPosition()
table.sort(creatures, function(a, b)
if getDistanceBetween(playerPos, a:getPosition()) == getDistanceBetween(playerPos, b:getPosition()) then
return a:getAge() > b:getAge()
return a.age > b.age
end
return getDistanceBetween(playerPos, a:getPosition()) > getDistanceBetween(playerPos, b:getPosition())
end)
elseif getSortType() == 'health' then
table.sort(creatures, function(a, b)
if a:getHealthPercent() == b:getHealthPercent() then
return a:getAge() > b:getAge()
return a.age > b.age
end
return a:getHealthPercent() > b:getHealthPercent()
end)
elseif getSortType() == 'age' then
table.sort(creatures, function(a, b) return a:getAge() > b:getAge() end)
table.sort(creatures, function(a, b) return a.age > b.age end)
else -- name
table.sort(creatures, function(a, b)
if a:getName():lower() == b:getName():lower() then
return a:getAge() > b:getAge()
return a.age > b.age
end
return a:getName():lower() > b:getName():lower()
end)
@@ -397,12 +381,8 @@ function onBattleButtonHoverChange(battleButton, hovered)
updateSquare()
end
function onCreaturePositionChange(creature, newPos, oldPos)
if creature:isLocalPlayer() then
if oldPos and newPos and newPos.z ~= oldPos.z then
checkCreatures()
end
end
function onPlayerPositionChange(creature, newPos, oldPos)
addEvent(checkCreatures)
end
local CreatureButtonColors = {

View File

@@ -54,6 +54,7 @@ MiniWindow
height: 45
Panel
id: buttons
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
height: 20
@@ -88,6 +89,7 @@ MiniWindow
@onCheckChange: modules.game_battle.checkCreatures()
Panel
id: sortPanel
anchors.top: prev.bottom
anchors.left: parent.left
anchors.right: parent.right
@@ -147,3 +149,4 @@ MiniWindow
padding-right: 5
layout:
type: verticalBox
fit-children: true

View File

@@ -163,7 +163,6 @@ function refresh()
configList.onOptionChange = function(widget)
settings[index].config = widget:getCurrentOption().text
settings[index].enabled = false
g_settings.setNode('bot', settings)
g_settings.save()
refresh()
@@ -178,7 +177,7 @@ function refresh()
if not g_game.isOnline() or not settings[index].enabled then
statusLabel:setOn(true)
statusLabel:setText("Status: disabled")
statusLabel:setText("Status: disabled\nPress off button to enable")
return
end
@@ -381,7 +380,9 @@ function initCallbacks()
})
connect(g_map, {
onMissle = botOnMissle
onMissle = botOnMissle,
onAnimatedText = botOnAnimatedText,
onStaticText = botOnStaticText
})
end
@@ -427,7 +428,9 @@ function terminateCallbacks()
})
disconnect(g_map, {
onMissle = botOnMissle
onMissle = botOnMissle,
onAnimatedText = botOnAnimatedText,
onStaticText = botOnStaticText
})
end
@@ -526,6 +529,16 @@ function botOnMissle(missle)
safeBotCall(function() botExecutor.callbacks.onMissle(missle) end)
end
function botOnAnimatedText(thing, text)
if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onAnimatedText(thing, text) end)
end
function botOnStaticText(thing, text)
if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onStaticText(thing, text) end)
end
function botChannelList(channels)
if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onChannelList(channels) end)

View File

@@ -52,6 +52,8 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
onContainerClose = {},
onContainerUpdateItem = {},
onMissle = {},
onAnimatedText = {},
onStaticText = {},
onChannelList = {},
onOpenChannel = {},
onCloseChannel = {},
@@ -275,6 +277,16 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
callback(missle)
end
end,
onAnimatedText = function(thing, text)
for i, callback in ipairs(context._callbacks.onAnimatedText) do
callback(thing, text)
end
end,
onStaticText = function(thing, text)
for i, callback in ipairs(context._callbacks.onStaticText) do
callback(thing, text)
end
end,
onChannelList = function(channels)
for i, callback in ipairs(context._callbacks.onChannelList) do
callback(channels)

View File

@@ -116,6 +116,16 @@ context.onMissle = function(callback)
return context.callback("onMissle", callback)
end
-- onAnimatedText -- callback = function(thing, text)
context.onAnimatedText = function(callback)
return context.callback("onAnimatedText", callback)
end
-- onStaticText -- callback = function(thing, text)
context.onStaticText = function(callback)
return context.callback("onStaticText", callback)
end
-- onChannelList -- callback = function(channels)
context.onChannelList = function(callback)
return context.callback("onChannelList", callback)

View File

@@ -123,7 +123,7 @@ context.addIcon = function(id, options, callback)
widget.onDragMove = function(widget, mousePos, moved)
local parentRect = widget:getParent():getRect()
local x = math.min(math.max(parentRect.x, mousePos.x - widget.movingReference.x), parentRect.x + parentRect.width - widget:getWidth())
local y = math.min(math.max(parentRect.y, mousePos.y - widget.movingReference.y), parentRect.y + parentRect.height - widget:getHeight())
local y = math.min(math.max(parentRect.y - widget:getParent():getMarginTop(), mousePos.y - widget.movingReference.y), parentRect.y + parentRect.height - widget:getHeight())
widget:move(x, y)
return true
end
@@ -141,8 +141,8 @@ context.addIcon = function(id, options, callback)
widget:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter)
widget:addAnchor(AnchorVerticalCenter, 'parent', AnchorVerticalCenter)
widget:setMarginTop(height * (-0.5 + config.x))
widget:setMarginLeft(width * (-0.5 + config.y))
widget:setMarginTop(height * (-0.5 + config.y))
widget:setMarginLeft(width * (-0.5 + config.x))
return true
end
end
@@ -153,7 +153,7 @@ context.addIcon = function(id, options, callback)
local parentRect = parent:getRect()
local width = parentRect.width - widget:getWidth()
local height = parentRect.height - widget:getHeight()
widget:setMarginTop(height * (-0.5 + config.y))
widget:setMarginTop(-parent:getMarginTop() + height * (-0.5 + config.y))
widget:setMarginLeft(width * (-0.5 + config.x))
end

View File

@@ -7,4 +7,9 @@ context.displayGeneralBox = function(title, message, buttons, onEnterCallback, o
local box = displayGeneralBox(title, message, buttons, onEnterCallback, onEscapeCallback)
box.botWidget = true
return box
end
end
context.doScreenshot = function(filename)
g_app.doScreenshot(filename)
end
context.screenshot = context.doScreenshot

View File

@@ -26,6 +26,7 @@ BotLabel < Label
BotItem < Item
virtual: true
&selectable: true
&editable: true
BotTextEdit < TextEdit
@onClick: modules.game_textedit.show(self)
@@ -38,66 +39,7 @@ BotSeparator < HorizontalSeparator
margin-top: 5
margin-bottom: 3
BotSmallScrollBar < UIScrollBar
orientation: vertical
margin-bottom: 1
step: 20
width: 8
image-source: /images/ui/scrollbar
image-clip: 39 0 13 65
image-border: 1
pixels-scroll: true
UIButton
id: decrementButton
anchors.top: parent.top
anchors.left: parent.left
image-source: /images/ui/scrollbar
image-clip: 0 0 13 13
image-color: #ffffffff
size: 8 8
$hover:
image-clip: 13 0 13 13
$pressed:
image-clip: 26 0 13 13
$disabled:
image-color: #ffffff66
UIButton
id: incrementButton
anchors.bottom: parent.bottom
anchors.right: parent.right
size: 8 8
image-source: /images/ui/scrollbar
image-clip: 0 13 13 13
image-color: #ffffffff
$hover:
image-clip: 13 13 13 13
$pressed:
image-clip: 26 13 13 13
$disabled:
image-color: #ffffff66
UIButton
id: sliderButton
anchors.centerIn: parent
size: 8 11
image-source: /images/ui/scrollbar
image-clip: 0 26 13 13
image-border: 2
image-color: #ffffffff
$hover:
image-clip: 13 26 13 13
$pressed:
image-clip: 26 26 13 13
$disabled:
image-color: #ffffff66
Label
id: valueLabel
anchors.fill: parent
color: white
text-align: center
BotSmallScrollBar < SmallScrollBar
BotPanel < Panel
ScrollablePanel

View File

@@ -383,44 +383,15 @@ function clear()
end
end
function switchMode(floating)
if floating then
function switchMode(newView)
if newView then
consolePanel:setImageColor('#ffffff88')
consolePanel:removeAnchor(AnchorRight)
consolePanel:setWidth(600)
consolePanel:setDraggable(true)
consoleTabBar:setDraggable(true)
local bottomSplitter = modules.game_interface.bottomSplitter
if bottomSplitter then
bottomSplitter:removeAnchor(AnchorRight)
bottomSplitter:setWidth(600)
end
if not floatingMode then
local savedMargin = g_settings.get("consoleLeftMargin")
local newMargin = 150
if savedMargin and #savedMargin > 0 then
newMargin = tonumber(savedMargin)
end
newMargin = math.max(0, newMargin)
newMargin = math.min(consolePanel:getParent():getWidth() - consolePanel:getWidth(), newMargin)
consolePanel:setMarginLeft(newMargin)
if bottomSplitter then
bottomSplitter:setMarginLeft(newMargin)
end
end
else
consolePanel:setImageColor('white')
consolePanel:addAnchor(AnchorLeft, 'parent', AnchorLeft)
consolePanel:addAnchor(AnchorRight, 'parent', AnchorRight)
consolePanel:setDraggable(false)
consoleTabBar:setDraggable(false)
consolePanel:setMarginLeft(0)
end
floatingMode = floating
--consolePanel:setDraggable(floating)
--consoleTabBar:setDraggable(floating)
--floatingMode = floating
end
function onDragEnter(widget, pos)
@@ -431,15 +402,7 @@ function onDragMove(widget, pos, moved)
if not floatingMode then
return
end
local newMargin = consolePanel:getMarginLeft() + moved.x
newMargin = math.max(0, newMargin)
newMargin = math.min(consolePanel:getParent():getWidth() - consolePanel:getWidth(), newMargin)
consolePanel:setMarginLeft(newMargin)
local bottomSplitter = modules.game_interface.bottomSplitter
if bottomSplitter then
bottomSplitter:setMarginLeft(newMargin)
end
g_settings.set("consoleLeftMargin", newMargin)
-- update margin
return true
end

View File

@@ -57,10 +57,18 @@ ConsoleTabBarButton < MoveableTabBarButton
Panel
id: consolePanel
anchors.fill: parent
image-source: /images/ui/panel_bottom
image-border: 4
phantom: false
$first:
anchors.fill: parent
$!first:
anchors.top: prev.bottom
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
CheckBox
id: toggleChat

View File

@@ -274,8 +274,8 @@ function onOverlayGeometryChange()
topHealthBar:setMarginTop(15)
topManaBar:setMarginTop(15)
else
topHealthBar:setMarginTop(45)
topManaBar:setMarginTop(45)
topHealthBar:setMarginTop(45 - overlay:getParent():getMarginTop())
topManaBar:setMarginTop(45 - overlay:getParent():getMarginTop())
minMargin = 200
end
@@ -283,6 +283,6 @@ function onOverlayGeometryChange()
local width = overlay:getWidth()
topHealthBar:setMarginLeft(math.max(minMargin, (width - height) / 2 + 2))
topManaBar:setMarginRight(math.max(minMargin, (width - height) / 2 + 2))
topHealthBar:setMarginLeft(math.max(minMargin, (width - height + 50) / 2 + 2))
topManaBar:setMarginRight(math.max(minMargin, (width - height + 50) / 2 + 2))
end

View File

@@ -93,7 +93,7 @@ HealthOverlay < UIWidget
image-source: /images/game/circle/left_empty
margin-right: 169
margin-bottom: 16
opacity: 0.4
opacity: 0.5
phantom: true
UIProgressBar
@@ -103,7 +103,7 @@ HealthOverlay < UIWidget
image-source: /images/game/circle/left_full
margin-right: 169
margin-bottom: 16
opacity: 0.4
opacity: 0.5
phantom: true
UIProgressBar
@@ -113,7 +113,7 @@ HealthOverlay < UIWidget
image-source: /images/game/circle/right_empty
margin-left: 130
margin-bottom: 16
opacity: 0.4
opacity: 0.5
phantom: true
UIProgressBar
@@ -123,7 +123,7 @@ HealthOverlay < UIWidget
image-source: /images/game/circle/right_full
margin-left: 130
margin-bottom: 16
opacity: 0.3
opacity: 0.4
image-color: #0000FFFF
phantom: true

View File

@@ -545,7 +545,6 @@ function updateHotkeyLabel(hotkeyLabel)
end
function updateHotkeyForm(reset)
local hasCustomAction = hotkeysWindow.action and hotkeysWindow.action.currentIndex > 1
configValueChanged = true
if hotkeysWindow.action then
if currentHotkeyLabel then
@@ -560,6 +559,7 @@ function updateHotkeyForm(reset)
hotkeysWindow.action:setCurrentIndex(1, true)
end
end
local hasCustomAction = hotkeysWindow.action and hotkeysWindow.action.currentIndex > 1
if currentHotkeyLabel and not hasCustomAction then
removeHotkeyButton:enable()
if currentHotkeyLabel.itemId ~= nil then

View File

@@ -830,7 +830,7 @@ function refreshViewMode()
local minimumWidth = (g_settings.getNumber("rightPanels") + g_settings.getNumber("leftPanels") - 1) * 200
if classic then
minimumWidth = minimumWidth + 300
minimumWidth = minimumWidth + 400
end
minimumWidth = math.max(minimumWidth, 800)
g_window.setMinimumSize({ width = minimumWidth, height = 600 })
@@ -866,6 +866,7 @@ function refreshViewMode()
end
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
gameMapPanel:setMarginTop(0)
if classic then
gameRootPanel:addAnchor(AnchorTop, 'topMenu', AnchorBottom)
@@ -878,9 +879,6 @@ function refreshViewMode()
gameBottomPanel:addAnchor(AnchorLeft, 'gameLeftPanels', AnchorRight)
gameBottomPanel:addAnchor(AnchorRight, 'gameRightPanels', AnchorLeft)
bottomSplitter:addAnchor(AnchorLeft, 'gameLeftPanels', AnchorRight)
bottomSplitter:addAnchor(AnchorRight, 'gameRightPanels', AnchorLeft)
bottomSplitter:setMarginLeft(0)
modules.client_topmenu.getTopMenu():setImageColor('white')
gameBottomPanel:setImageColor('white')
@@ -890,28 +888,28 @@ function refreshViewMode()
modules.game_console.switchMode(false)
end
else
g_game.changeMapAwareRange(29, 19)
g_game.changeMapAwareRange(31, 21)
gameMapPanel:fill('parent')
gameRootPanel:fill('parent')
gameMapPanel:setKeepAspectRatio(false)
gameMapPanel:setLimitVisibleRange(false)
if g_game.getFeature(GameChangeMapAwareRange) then
gameMapPanel:setZoom(13)
else
gameMapPanel:setZoom(11)
end
gameBottomPanel:addAnchor(AnchorLeft, 'parent', AnchorLeft)
gameBottomPanel:addAnchor(AnchorRight, 'parent', AnchorRight)
bottomSplitter:addAnchor(AnchorLeft, 'parent', AnchorLeft)
bottomSplitter:addAnchor(AnchorRight, 'parent', AnchorRight)
gameMapPanel:setZoom(14)
modules.client_topmenu.getTopMenu():setImageColor('#ffffff66')
if modules.game_console then
modules.game_console.switchMode(true)
end
end
if modules.game_actionbar then
modules.game_actionbar.switchMode(not classic)
end
if g_settings.getBoolean("cacheMap") then
g_game.enableFeature(GameBiggerMapCache)
end
updateSize()
end
function limitZoom()
@@ -922,15 +920,6 @@ function updateSize()
local classic = g_settings.getBoolean("classicView")
local height = gameMapPanel:getHeight()
local width = gameMapPanel:getWidth()
if not classic and modules.game_console then
local newMargin = modules.game_console.consolePanel:getMarginLeft()
newMargin = math.max(0, newMargin)
newMargin = math.min(modules.game_console.consolePanel:getParent():getWidth() - modules.game_console.consolePanel:getWidth(), newMargin)
bottomSplitter:setMarginLeft(newMargin)
modules.game_console.consolePanel:setMarginLeft(newMargin)
bottomSplitter:setMarginLeft(newMargin)
end
if not classic then
local rheight = gameRootPanel:getHeight()
@@ -941,11 +930,20 @@ function updateSize()
local awareRange = g_map.getAwareRange()
local dheight = dimenstion.height
local dwidth = dimenstion.width
local tileSize = rheight / dheight
local maxWidth = tileSize * (awareRange.width - 4)
local margin = math.max(0, math.floor((rwidth - maxWidth) / 2))
gameMapPanel:setMarginLeft(margin)
gameMapPanel:setMarginRight(margin)
local tileSize = rheight / dheight
local maxWidth = tileSize * (awareRange.width + 1)
if g_game.getFeature(GameChangeMapAwareRange) then
local maxWidth = tileSize * (awareRange.width - 1)
end
gameMapPanel:setMarginTop(-tileSize * 2)
if g_settings.getBoolean("cacheMap") then
gameMapPanel:setMarginLeft(0)
gameMapPanel:setMarginRight(0)
else
local margin = math.max(0, math.floor((rwidth - maxWidth) / 2))
gameMapPanel:setMarginLeft(margin)
gameMapPanel:setMarginRight(margin)
end
end
--[[

View File

@@ -55,23 +55,24 @@ UIWidget
fit-children: true
spacing: -1
GameBottomPanel
id: gameBottomPanel
anchors.left: gameLeftPanels.right
anchors.right: gameRightPanels.left
anchors.top: bottomSplitter.top
anchors.bottom: parent.bottom
Splitter
id: bottomSplitter
anchors.left: gameLeftPanels.right
anchors.right: gameRightPanels.left
anchors.bottom: parent.bottom
relative-margin: bottom
margin-bottom: 172
@canUpdateMargin: function(self, newMargin) if modules.client_options.getOption('dontStretchShrink') then return self:getMarginBottom() end return math.max(math.min(newMargin, self:getParent():getHeight() - 300), 100) end
@onGeometryChange: function(self) self:setMarginBottom(math.min(math.max(self:getParent():getHeight() - 300, 100), self:getMarginBottom())) end
margin-bottom: 180
@canUpdateMargin: function(self, newMargin) if modules.client_options.getOption('dontStretchShrink') then return self:getMarginBottom() end return math.max(math.min(newMargin, self:getParent():getHeight() - 300), 80) end
@onGeometryChange: function(self) self:setMarginBottom(math.min(math.max(self:getParent():getHeight() - 300, 80), self:getMarginBottom())) end
GameBottomPanel
id: gameBottomPanel
anchors.left: bottomSplitter.left
anchors.right: bottomSplitter.right
anchors.top: bottomSplitter.top
anchors.bottom: parent.bottom
margin-top: 3
UIWidget
id: mouseGrabber
focusable: false

View File

@@ -34,6 +34,7 @@ Module
- game_shop
- game_itemselector
- game_textedit
- game_actionbar
- game_bot
@onLoad: init()
@onUnload: terminate()

View File

@@ -69,14 +69,19 @@ function init()
end
purseButton = inventoryWindow:recursiveGetChildById('purseButton')
marketButton = inventoryWindow:recursiveGetChildById('marketButton')
local function purseFunction()
purseButton.onClick = function()
local purse = g_game.getLocalPlayer():getInventoryItem(InventorySlotPurse)
if purse then
g_game.use(purse)
end
end
purseButton.onClick = purseFunction
marketButton = inventoryWindow:recursiveGetChildById('marketButton')
marketButton.onClick = function()
if modules.game_shop then
modules.game_shop.toggle()
end
end
-- controls
fightOffensiveBox = inventoryWindow:recursiveGetChildById('fightOffensiveBox')
@@ -206,7 +211,7 @@ function refresh()
end
purseButton:setVisible(g_game.getFeature(GamePurseSlot))
marketButton:setVisible(g_game.getFeature(GamePurseSlot))
marketButton:setVisible(g_game.getFeature(GameIngameStore))
end
function toggle()

View File

@@ -2,10 +2,15 @@
local SHOP_EXTENTED_OPCODE = 201
shop = nil
local otcv8shop = false
local shopButton = nil
local msgWindow = nil
local browsingHistory = false
-- for classic store
local storeUrl = ""
local coinsPacketSize = 0
local CATEGORIES = {}
local HISTORY = {}
local STATUS = {}
@@ -14,6 +19,10 @@ local AD = {}
local selectedOffer = {}
local function sendAction(action, data)
if not g_game.getFeature(GameExtendedOpcode) then
return
end
local protocolGame = g_game.getProtocolGame()
if data == nil then
data = {}
@@ -25,16 +34,37 @@ end
-- public functions
function init()
connect(g_game, { onGameStart = check, onGameEnd = hide })
ProtocolGame.registerExtendedJSONOpcode(SHOP_EXTENTED_OPCODE, onExtendedJSONOpcode)
connect(g_game, {
onGameStart = check,
onGameEnd = hide,
onStoreInit = onStoreInit,
onStoreCategories = onStoreCategories,
onStoreOffers = onStoreOffers,
onStoreTransactionHistory = onStoreTransactionHistory,
onStorePurchase = onStorePurchase,
onStoreError = onStoreError,
onCoinBalance = onCoinBalance
})
ProtocolGame.registerExtendedJSONOpcode(SHOP_EXTENTED_OPCODE, onExtendedJSONOpcode)
if g_game.isOnline() then
check()
end
end
function terminate()
disconnect(g_game, { onGameStart = check, onGameEnd = hide })
disconnect(g_game, {
onGameStart = check,
onGameEnd = hide,
onStoreInit = onStoreInit,
onStoreCategories = onStoreCategories,
onStoreOffers = onStoreOffers,
onStoreTransactionHistory = onStoreTransactionHistory,
onStorePurchase = onStorePurchase,
onStoreError = onStoreError,
onCoinBalance = onCoinBalance
})
ProtocolGame.unregisterExtendedJSONOpcode(SHOP_EXTENTED_OPCODE, onExtendedJSONOpcode)
@@ -53,9 +83,7 @@ function terminate()
end
function check()
if not g_game.getFeature(GameExtendedOpcode) then
return
end
otcv8shop = false
sendAction("init")
end
@@ -70,6 +98,10 @@ function show()
if not shop or not shopButton then
return
end
if g_game.getFeature(GameIngameStore) then
g_game.openStore(0)
end
shop:show()
shop:raise()
shop:focus()
@@ -86,14 +118,124 @@ function toggle()
check()
end
function onExtendedJSONOpcode(protocol, code, json_data)
if not shop then
shop = g_ui.displayUI('shop')
shop:hide()
shopButton = modules.client_topmenu.addRightGameToggleButton('shopButton', tr('Shop'), '/images/topbuttons/shop', toggle)
function createShop()
if shop then return end
shop = g_ui.displayUI('shop')
shop:hide()
shopButton = modules.client_topmenu.addRightGameToggleButton('shopButton', tr('Shop'), '/images/topbuttons/shop', toggle)
connect(shop.categories, { onChildFocusChange = changeCategory })
end
connect(shop.categories, { onChildFocusChange = changeCategory })
function onStoreInit(url, coins)
if otcv8shop then return end
storeUrl = url
if storeUrl:len() > 0 then
if storeUrl:sub(storeUrl:len(), storeUrl:len()) ~= "/" then
storeUrl = storeUrl .. "/"
end
storeUrl = storeUrl .. "64/"
if storeUrl:sub(1, 4):lower() ~= "http" then
storeUrl = "http://" .. storeUrl
end
end
coinsPacketSize = coins
createShop()
end
function onStoreCategories(categories)
if otcv8shop then return end
local correctCategories = {}
for i, category in ipairs(categories) do
table.insert(correctCategories, {
type = "image",
image = storeUrl .. category.icon,
name = category.name,
offers = {}
})
end
processCategories(correctCategories)
end
function onStoreOffers(categoryName, offers)
if otcv8shop then return end
local updated = false
for i, category in ipairs(CATEGORIES) do
if category.name == categoryName then
if #category.offers ~= #offers then
updated = true
end
for i=1,#category.offers do
if category.offers[i].title ~= offers[i].name or category.offers[i].id ~= offers[i].id or category.offers[i].cost ~= offers[i].price then
updated = true
end
end
if updated then
for offer in pairs(category.offers) do
category.offers[offer] = nil
end
for i, offer in ipairs(offers) do
table.insert(category.offers, {
id=offer.id,
type="image",
image=storeUrl .. offer.icon,
cost=offer.price,
title=offer.name,
description=offer.description
})
end
end
end
end
if not updated then
return
end
local activeCategory = shop.categories:getFocusedChild()
changeCategory(activeCategory, activeCategory)
end
function onStoreTransactionHistory(currentPage, hasNextPage, offers)
if otcv8shop then return end
HISTORY = {}
for i, offer in ipairs(offers) do
table.insert(HISTORY, {
id=offer.id,
type="image",
image=storeUrl .. offer.icon,
cost=offer.price,
title=offer.name,
description=offer.description
})
end
if not browsingHistory then return end
clearOffers()
shop.categories:focusChild(nil)
for i, transaction in ipairs(HISTORY) do
addOffer(0, transaction)
end
end
function onStorePurchase(message)
if otcv8shop then return end
processMessage({title="Successful shop purchase", msg=message})
end
function onStoreError(errorType, message)
if otcv8shop then return end
processMessage({title="Shop error", msg=message})
end
function onCoinBalance(coins, transferableCoins)
shop.infoPanel.points:setText(tr("Points:") .. " " .. coins)
shop.infoPanel.buy:hide()
shop.infoPanel:setHeight(20)
end
function onExtendedJSONOpcode(protocol, code, json_data)
createShop()
local action = json_data['action']
local data = json_data['data']
@@ -101,7 +243,8 @@ function onExtendedJSONOpcode(protocol, code, json_data)
if not action or not data then
return false
end
otcv8shop = true
if action == 'categories' then
processCategories(data)
elseif action == 'history' then
@@ -166,17 +309,17 @@ function processHistory(data)
end
function processMessage(data)
if msgWindow then
msgWindow:destroy()
end
local title = tr(data["title"])
local msg = data["msg"]
msgWindow = displayInfoBox(title, msg)
msgWindow:show()
msgWindow:raise()
msgWindow:focus()
msgWindow:raise()
if msgWindow then
msgWindow:destroy()
end
local title = tr(data["title"])
local msg = data["msg"]
msgWindow = displayInfoBox(title, msg)
msgWindow:show()
msgWindow:raise()
msgWindow:focus()
msgWindow:raise()
end
function processStatus(data)
@@ -198,6 +341,7 @@ function processStatus(data)
end
else
shop.infoPanel.buy:hide()
shop.infoPanel:setHeight(20)
end
end
@@ -268,7 +412,12 @@ function showHistory(force)
if browsingHistory and not force then
return
end
if g_game.getFeature(GameIngameStore) and not otcv8shop then
g_game.openTransactionHistory(100)
end
sendAction("history")
browsingHistory = true
clearOffers()
shop.categories:focusChild(nil)
@@ -295,6 +444,7 @@ function addOffer(category, data)
if data["image"]:sub(1, 4):lower() == "http" then
HTTP.downloadImage(data['image'], function(path, err)
if err then g_logger.warning("HTTP error: " .. err) return end
if not offer.image then return end
offer.image:setImageSource(path)
end)
elseif data["image"] and data["image"]:len() > 1 then
@@ -307,6 +457,7 @@ function addOffer(category, data)
offer:setId("offer_" .. category .. "_" .. shop.offers:getChildCount())
offer.title:setText(data["title"] .. " (" .. data["cost"] .. " points)")
offer.description:setText(data["description"])
offer.offerId = data["id"]
if category ~= 0 then
offer.onDoubleClick = buyOffer
offer.buyButton.onClick = function() buyOffer(offer) end
@@ -318,6 +469,11 @@ function changeCategory(widget, newCategory)
if not newCategory then
return
end
if g_game.getFeature(GameIngameStore) and widget ~= newCategory and not otcv8shop then
g_game.requestStoreOffers(newCategory.name:getText())
end
browsingHistory = false
local id = tonumber(newCategory:getId():split("_")[2])
clearOffers()
@@ -341,7 +497,7 @@ function buyOffer(widget)
return
end
selectedOffer = {category=category, offer=offer, title=item.title, cost=item.cost}
selectedOffer = {category=category, offer=offer, title=item.title, cost=item.cost, id=widget.offerId}
scheduleEvent(function()
if msgWindow then
@@ -365,6 +521,19 @@ function buyConfirmed()
msgWindow:destroy()
msgWindow = nil
sendAction("buy", selectedOffer)
if g_game.getFeature(GameIngameStore) and selectedOffer.id and not otcv8shop then
local offerName = selectedOffer.title:lower()
if string.find(offerName, "name") and string.find(offerName, "change") and modules.game_textedit then
modules.game_textedit.singlelineEditor("", function(newName)
if newName:len() == 0 then
return
end
g_game.buyStoreOffer(selectedOffer.id, 1, newName)
end)
else
g_game.buyStoreOffer(selectedOffer.id, 0, "")
end
end
end
function buyCanceled()

View File

@@ -14,7 +14,6 @@ ShopCategory < Panel
anchors.bottom: parent.bottom
margin-left: 40
text-align: left
text: UAHSbjaS ASDJHASD ASKJD
color: white
font: verdana-11px-rounded
@@ -69,7 +68,6 @@ ShopOffer < Panel
margin-top: 4
margin-left: 55
text-align: topleft
text: UAHSbjaS ASDJHASD ASKJD
color: white
font: verdana-11px-rounded

View File

@@ -73,7 +73,7 @@ function terminate()
end
function calculateVisibleTime(text)
return math.max(#text * 100, 4000)
return math.max(#text * 50, 3000)
end
function displayMessage(mode, text)

View File

@@ -141,7 +141,7 @@ function bindWalkKey(key, dir)
local gameRootPanel = modules.game_interface.getRootPanel()
g_keyboard.bindKeyDown(key, function() changeWalkDir(dir) end, gameRootPanel, true)
g_keyboard.bindKeyUp(key, function() changeWalkDir(dir, true) end, gameRootPanel, true)
g_keyboard.bindKeyPress(key, function() smartWalk(dir) end, gameRootPanel)
g_keyboard.bindKeyPress(key, function(c, k, ticks) smartWalk(dir, ticks) end, gameRootPanel)
end
function unbindWalkKey(key)
@@ -203,11 +203,11 @@ function changeWalkDir(dir, pop)
end
end
function smartWalk(dir)
function smartWalk(dir, ticks)
walkEvent = scheduleEvent(function()
if g_keyboard.getModifiers() == KeyboardNoModifier then
local direction = smartWalkDir or dir
walk(direction)
walk(direction, ticks)
return true
end
return false
@@ -252,7 +252,7 @@ function onWalkFinish(player)
lastFinishedStep = g_clock.millis()
if nextWalkDir ~= nil then
removeEvent(autoWalkEvent)
autoWalkEvent = addEvent(function() if nextWalkDir ~= nil then walk(nextWalkDir) end end, false)
autoWalkEvent = addEvent(function() if nextWalkDir ~= nil then walk(nextWalkDir, 0) end end, false)
end
end
@@ -260,13 +260,18 @@ function onCancelWalk(player)
player:lockWalk(50)
end
function walk(dir)
function walk(dir, ticks)
lastManualWalk = g_clock.millis()
local player = g_game.getLocalPlayer()
if not player or g_game.isDead() or player:isDead() then
return
end
if player:isWalkLocked() then
nextWalkDir = nil
return
end
if g_game.isFollowing() then
g_game.cancelFollow()
end
@@ -278,12 +283,7 @@ function walk(dir)
g_game.stop()
end
end
if player:isWalkLocked() then
nextWalkDir = nil
return
end
local dash = false
local ignoredCanWalk = false
if not g_game.getFeature(GameNewWalking) then
@@ -291,11 +291,11 @@ function walk(dir)
end
local ticksToNextWalk = player:getStepTicksLeft()
if not player:canWalk(dir) then -- canWalk return false when previous walk is not finished or not confirmed by server
if not player:canWalk(dir) then -- canWalk return false when previous walk is not finished or not confirmed by server
if dash then
ignoredCanWalk = true
else
if ticksToNextWalk < 500 and lastWalkDir ~= dir then
if ticksToNextWalk < 500 and (lastWalkDir ~= dir or ticks == 0) then
nextWalkDir = dir
end
if ticksToNextWalk < 30 and lastFinishedStep + 400 > g_clock.millis() and nextWalkDir == nil then -- clicked walk 20 ms too early, try to execute again as soon possible to keep smooth walking
@@ -349,11 +349,14 @@ function walk(dir)
end
if dash and lastWalkDir == dir and lastWalk + 30 > g_clock.millis() then
walkLock = lastWalk + g_settings.getNumber('walkFirstStepDelay')
return
end
firstStep = (not player:isWalking() and lastFinishedStep + 100 < g_clock.millis() and walkLock + 100 < g_clock.millis()) or (player:isServerWalking() and not dash)
firstStep = (not player:isWalking() and lastFinishedStep + 100 < g_clock.millis() and walkLock + 100 < g_clock.millis())
if player:isServerWalking() and not dash then
walkLock = walkLock + math.max(g_settings.getNumber('walkFirstStepDelay'), 100)
end
nextWalkDir = nil
removeEvent(autoWalkEvent)
autoWalkEvent = nil

View File

@@ -170,6 +170,7 @@ GameNewWalking = 90
GameSlowerManualWalking = 91
GameExtendedNewWalking = 92
GameBot = 95
GameBiggerMapCache = 96
GameForceLight = 97
GameNoDebug = 98
GameBotProtection = 99

View File

@@ -35,12 +35,7 @@ function UICreatureButton:getCreatureId()
return self.creature:getId()
end
function UICreatureButton:setup(creature, id)
if not id then
id = 0
end
self:setId('CreatureButton_' .. id)
function UICreatureButton:setup(id)
self.lifeBarWidget = self:getChildById('lifeBar')
self.creatureWidget = self:getChildById('creature')
self.labelWidget = self:getChildById('label')

View File

@@ -120,7 +120,7 @@ function UIItem:canAcceptDrop(widget, mousePos)
end
function UIItem:onClick(mousePos)
if not self.selectable then
if not self.selectable or not self.editable then
return
end