mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-04-30 03:09:20 +02:00
Version 2.1 - imbuements, wrap/unwrap, 4 byte header, packet compression and other features
This commit is contained in:
parent
dbfad99ca4
commit
b58076a675
@ -1,26 +1,27 @@
|
|||||||
local entergameWindow
|
local entergameWindow
|
||||||
local characterGroup
|
local characterGroup
|
||||||
|
local outfitGroup
|
||||||
|
local protocol
|
||||||
|
local infoBox
|
||||||
|
local loadingBox
|
||||||
|
|
||||||
function init()
|
function init()
|
||||||
if not USE_NEW_ENERGAME then return end
|
if not USE_NEW_ENERGAME then return end
|
||||||
entergameWindow = g_ui.displayUI('entergamev2')
|
entergameWindow = g_ui.displayUI('entergamev2')
|
||||||
|
|
||||||
--entergameWindow.news:hide()
|
entergameWindow.news:hide()
|
||||||
--entergameWindow.quick:hide()
|
entergameWindow.quick:hide()
|
||||||
entergameWindow.registration:hide()
|
entergameWindow.registration:hide()
|
||||||
entergameWindow.characters:hide()
|
entergameWindow.characters:hide()
|
||||||
entergameWindow.createcharacter:hide()
|
entergameWindow.createcharacter:hide()
|
||||||
|
entergameWindow.settings:hide()
|
||||||
|
|
||||||
-- entergame
|
-- entergame
|
||||||
entergameWindow.entergame.register.onClick = function()
|
entergameWindow.entergame.register.onClick = function()
|
||||||
entergameWindow.registration:show()
|
entergameWindow.registration:show()
|
||||||
entergameWindow.entergame:hide()
|
entergameWindow.entergame:hide()
|
||||||
end
|
end
|
||||||
entergameWindow.entergame.mainPanel.button.onClick = function()
|
entergameWindow.entergame.mainPanel.button.onClick = login
|
||||||
entergameWindow.entergame:hide()
|
|
||||||
entergameWindow.characters:show()
|
|
||||||
g_game.setClientVersion(1099) -- for tests
|
|
||||||
end
|
|
||||||
|
|
||||||
-- registration
|
-- registration
|
||||||
entergameWindow.registration.back.onClick = function()
|
entergameWindow.registration.back.onClick = function()
|
||||||
@ -29,44 +30,455 @@ function init()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- characters
|
-- characters
|
||||||
|
--- outfits
|
||||||
|
entergameWindow.characters.mainPanel.showOutfits.onClick = function()
|
||||||
|
local status = not (entergameWindow.characters.mainPanel.showOutfits:isOn())
|
||||||
|
g_settings.set('showOutfits', status)
|
||||||
|
entergameWindow.characters.mainPanel.showOutfits:setOn(status)
|
||||||
|
if status then
|
||||||
|
entergameWindow.characters.mainPanel.outfitsPanel:show()
|
||||||
|
entergameWindow.characters.mainPanel.outfitsScroll:show()
|
||||||
|
entergameWindow.characters.mainPanel.charactersPanel:hide()
|
||||||
|
entergameWindow.characters.mainPanel.charactersScroll:hide()
|
||||||
|
else
|
||||||
|
entergameWindow.characters.mainPanel.outfitsPanel:hide()
|
||||||
|
entergameWindow.characters.mainPanel.outfitsScroll:hide()
|
||||||
|
entergameWindow.characters.mainPanel.charactersPanel:show()
|
||||||
|
entergameWindow.characters.mainPanel.charactersScroll:show()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local showOutfits = g_settings.getBoolean("showOutfits", false)
|
||||||
|
entergameWindow.characters.mainPanel.showOutfits:setOn(showOutfits)
|
||||||
|
if showOutfits then
|
||||||
|
entergameWindow.characters.mainPanel.charactersPanel:hide()
|
||||||
|
entergameWindow.characters.mainPanel.charactersScroll:hide()
|
||||||
|
else
|
||||||
|
entergameWindow.characters.mainPanel.outfitsPanel:hide()
|
||||||
|
entergameWindow.characters.mainPanel.outfitsScroll:hide()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- auto reconnect
|
||||||
|
entergameWindow.characters.mainPanel.autoReconnect.onClick = function()
|
||||||
|
local status = (not entergameWindow.characters.mainPanel.autoReconnect:isOn())
|
||||||
|
g_settings.set('autoReconnect', status)
|
||||||
|
entergameWindow.characters.mainPanel.autoReconnect:setOn(status)
|
||||||
|
end
|
||||||
|
local autoReconnect = g_settings.getBoolean("autoReconnect", true)
|
||||||
|
entergameWindow.characters.mainPanel.autoReconnect:setOn(autoReconnect)
|
||||||
|
|
||||||
|
--- buttons
|
||||||
entergameWindow.characters.logout.onClick = function()
|
entergameWindow.characters.logout.onClick = function()
|
||||||
|
protocol:logout()
|
||||||
entergameWindow.characters:hide()
|
entergameWindow.characters:hide()
|
||||||
entergameWindow.entergame:show()
|
entergameWindow.entergame:show()
|
||||||
|
entergameWindow.entergame.mainPanel.account:setText("")
|
||||||
|
entergameWindow.entergame.mainPanel.password:setText("")
|
||||||
end
|
end
|
||||||
entergameWindow.characters.createcharacter.onClick = function()
|
entergameWindow.characters.createcharacter.onClick = function()
|
||||||
entergameWindow.characters:hide()
|
entergameWindow.characters:hide()
|
||||||
entergameWindow.createcharacter:show()
|
entergameWindow.createcharacter:show()
|
||||||
|
entergameWindow.createcharacter.mainPanel.name:setText("")
|
||||||
end
|
end
|
||||||
entergameWindow.characters.mainPanel.autoReconnect.onClick = function()
|
entergameWindow.characters.settings.onClick = function()
|
||||||
entergameWindow.characters.mainPanel.autoReconnect:setOn(not entergameWindow.characters.mainPanel.autoReconnect:isOn())
|
entergameWindow.characters:hide()
|
||||||
end
|
entergameWindow.settings:show()
|
||||||
|
end
|
||||||
|
|
||||||
-- create character
|
-- create character
|
||||||
entergameWindow.createcharacter.back.onClick = function()
|
entergameWindow.createcharacter.back.onClick = function()
|
||||||
entergameWindow.createcharacter:hide()
|
entergameWindow.createcharacter:hide()
|
||||||
entergameWindow.characters:show()
|
entergameWindow.characters:show()
|
||||||
end
|
end
|
||||||
|
entergameWindow.createcharacter.mainPanel.createButton.onClick = createcharacter
|
||||||
-- tests
|
|
||||||
characterGroup = UIRadioGroup.create()
|
entergameWindow.settings.back.onClick = function()
|
||||||
for i=1,20 do
|
entergameWindow.settings:hide()
|
||||||
local character = g_ui.createWidget('EntergameCharacter', entergameWindow.characters.mainPanel.charactersPanel)
|
entergameWindow.characters:show()
|
||||||
characterGroup:addWidget(character)
|
|
||||||
character.outfit:setOutfit({feet=10,legs=10,body=176,type=129,auxType=0,addons=3,head=48})
|
|
||||||
end
|
end
|
||||||
characterGroup:selectWidget(entergameWindow.characters.mainPanel.charactersPanel:getFirstChild())
|
entergameWindow.settings.mainPanel.updateButton.onClick = updateSettings
|
||||||
characterGroup:getSelectedWidget()
|
|
||||||
|
|
||||||
for i=1,100 do
|
-- pick server
|
||||||
local l = g_ui.createWidget("NewsLabel", entergameWindow.news.content)
|
local server = nil
|
||||||
l:setText("test xxx ssss eeee uu u llel " .. i)
|
if type(Servers) == "table" then
|
||||||
|
for name, url in pairs(Servers) do
|
||||||
|
server = url
|
||||||
|
end
|
||||||
|
elseif type(Servers) == "string" then
|
||||||
|
server = Servers
|
||||||
|
elseif type(Server) == "string" then
|
||||||
|
server = Server
|
||||||
|
end
|
||||||
|
|
||||||
|
if not server then
|
||||||
|
message("Configuration error", "You must set server url in init.lua!\nExample:\nServer = \"ws://otclient.ovh:8000\"")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- init protocol
|
||||||
|
-- token is random string
|
||||||
|
local session = g_crypt.sha1Encode("" .. math.random() .. g_clock.realMicros() .. tostring(G.UUID) .. g_platform.getCPUName() .. g_platform.getProcessId())
|
||||||
|
protocol = EnterGameV2Protocol.new(session)
|
||||||
|
if not protocol:setUrl(server) then
|
||||||
|
return message("Configuration error", "Invalid url for entergamev2:\n" .. server)
|
||||||
|
end
|
||||||
|
|
||||||
|
protocol.onLogin = onLogin
|
||||||
|
protocol.onLogout = logout
|
||||||
|
protocol.onMessage = serverMessage
|
||||||
|
protocol.onLoading = showLoading
|
||||||
|
protocol.onQAuth = updateQAuth
|
||||||
|
protocol.onCharacters = updateCharacters
|
||||||
|
protocol.onNews = updateNews
|
||||||
|
protocol.onMotd = updateMotd
|
||||||
|
protocol.onCharacterCreate = onCharacterCreate
|
||||||
|
|
||||||
|
-- game stuff
|
||||||
|
connect(g_game, { onLoginError = onLoginError,
|
||||||
|
onLoginToken = onLoginToken ,
|
||||||
|
onUpdateNeeded = onUpdateNeeded,
|
||||||
|
onConnectionError = onConnectionError,
|
||||||
|
onGameStart = onGameStart,
|
||||||
|
onGameEnd = onGameEnd,
|
||||||
|
onLoginWait = onLoginWait,
|
||||||
|
onLogout = onLogout
|
||||||
|
})
|
||||||
|
|
||||||
|
if g_game.isOnline() then
|
||||||
|
onGameStart()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function terminate()
|
function terminate()
|
||||||
if not USE_NEW_ENERGAME then return end
|
if not USE_NEW_ENERGAME then return end
|
||||||
|
if protocol then
|
||||||
|
protocol:destroy()
|
||||||
|
protocol = nil
|
||||||
|
end
|
||||||
|
if infoBox then
|
||||||
|
infoBox:destroy()
|
||||||
|
infoBox = nil
|
||||||
|
end
|
||||||
|
if loadingBox then
|
||||||
|
loadingBox:destroy()
|
||||||
|
loadingBox = nil
|
||||||
|
end
|
||||||
|
if characterGroup then
|
||||||
|
characterGroup:destroy()
|
||||||
|
characterGroup = nil
|
||||||
|
end
|
||||||
|
if outfitGroup then
|
||||||
|
outfitGroup:destroy()
|
||||||
|
outfitGroup = nil
|
||||||
|
end
|
||||||
entergameWindow:destroy()
|
entergameWindow:destroy()
|
||||||
|
entergameWindow = nil
|
||||||
|
|
||||||
|
disconnect(g_game, { onLoginError = onLoginError,
|
||||||
|
onLoginToken = onLoginToken ,
|
||||||
|
onUpdateNeeded = onUpdateNeeded,
|
||||||
|
onConnectionError = onConnectionError,
|
||||||
|
onGameStart = onGameStart,
|
||||||
|
onGameEnd = onGameEnd,
|
||||||
|
onLoginWait = onLoginWait,
|
||||||
|
onLogout = onLogout
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function show()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function hide()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function message(title, text)
|
||||||
|
if infoBox then
|
||||||
|
infoBox:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
infoBox = displayInfoBox(title, text)
|
||||||
|
infoBox.onDestroy = function(widget)
|
||||||
|
if widget == infoBox then
|
||||||
|
infoBox = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
infoBox:show()
|
||||||
|
infoBox:raise()
|
||||||
|
infoBox:focus()
|
||||||
|
end
|
||||||
|
|
||||||
|
function showLoading(titie, text)
|
||||||
|
if loadingBox then
|
||||||
|
loadingBox:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
local callback = function() end -- do nothing
|
||||||
|
loadingBox = displayGeneralBox(titie, text, {}, callback, callback)
|
||||||
|
loadingBox.onDestroy = function(widget)
|
||||||
|
if widget == loadingBox then
|
||||||
|
loadingBox = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
loadingBox:show()
|
||||||
|
loadingBox:raise()
|
||||||
|
loadingBox:focus()
|
||||||
|
end
|
||||||
|
|
||||||
|
function serverMessage(title, text)
|
||||||
|
return message(title, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateCharacters(characters)
|
||||||
|
if outfitGroup then
|
||||||
|
outfitGroup:destroy()
|
||||||
|
end
|
||||||
if characterGroup then
|
if characterGroup then
|
||||||
characterGroup:destroy()
|
characterGroup:destroy()
|
||||||
end
|
end
|
||||||
|
entergameWindow.characters.mainPanel.charactersPanel:destroyChildren()
|
||||||
|
entergameWindow.characters.mainPanel.outfitsPanel:destroyChildren()
|
||||||
|
|
||||||
|
outfitGroup = UIRadioGroup.create()
|
||||||
|
characterGroup = UIRadioGroup.create()
|
||||||
|
for i, character in ipairs(characters) do
|
||||||
|
local characterWidget = g_ui.createWidget('EntergameCharacter', entergameWindow.characters.mainPanel.charactersPanel)
|
||||||
|
characterGroup:addWidget(characterWidget)
|
||||||
|
local outfitWidget = g_ui.createWidget('EntergameBigCharacter', entergameWindow.characters.mainPanel.outfitsPanel)
|
||||||
|
outfitGroup:addWidget(outfitWidget)
|
||||||
|
for i, widget in ipairs({characterWidget, outfitWidget}) do
|
||||||
|
widget.character = character
|
||||||
|
widget.outfit:setOutfit(character["outfit"])
|
||||||
|
widget.line1:setText(character["line1"])
|
||||||
|
widget.line2:setText(character["line2"])
|
||||||
|
widget.line3:setText(character["line3"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #characters > 1 then
|
||||||
|
characterGroup:selectWidget(entergameWindow.characters.mainPanel.charactersPanel:getFirstChild())
|
||||||
|
outfitGroup:selectWidget(entergameWindow.characters.mainPanel.outfitsPanel:getFirstChild())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateQAuth(token)
|
||||||
|
if not token or token:len() == 0 then
|
||||||
|
return entergameWindow.quick:hide()
|
||||||
|
end
|
||||||
|
entergameWindow.quick:show()
|
||||||
|
entergameWindow.quick.qrcode:setQRCode(token, 1)
|
||||||
|
entergameWindow.quick.qrcode.onClick = function()
|
||||||
|
g_platform.openUrl(token)
|
||||||
|
end
|
||||||
|
entergameWindow.quick.quathlogo.onClick = entergameWindow.quick.qrcode.onClick
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateNews(news)
|
||||||
|
if not news or #news == 0 then
|
||||||
|
return entergameWindow.news:hide()
|
||||||
|
end
|
||||||
|
entergameWindow.news:show()
|
||||||
|
entergameWindow.news.content:destroyChildren()
|
||||||
|
for i, entry in ipairs(news) do
|
||||||
|
local title = entry["title"]
|
||||||
|
local text = entry["text"]
|
||||||
|
local image = entry["image"]
|
||||||
|
if title then
|
||||||
|
local newsLabel = g_ui.createWidget('NewsLabel', entergameWindow.news.content)
|
||||||
|
newsLabel:setText(title)
|
||||||
|
end
|
||||||
|
if text ~= nil then
|
||||||
|
local newsText = g_ui.createWidget('NewsText', entergameWindow.news.content)
|
||||||
|
newsText:setText(text)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateMotd(text)
|
||||||
|
if not text or text:len() == 0 then
|
||||||
|
return entergameWindow.characters.mainPanel.motd:hide()
|
||||||
|
end
|
||||||
|
entergameWindow.characters.mainPanel.motd:show()
|
||||||
|
entergameWindow.characters.mainPanel.motd:setText(text)
|
||||||
|
end
|
||||||
|
|
||||||
|
function login()
|
||||||
|
local account = entergameWindow.entergame.mainPanel.account:getText()
|
||||||
|
local password = entergameWindow.entergame.mainPanel.password:getText()
|
||||||
|
entergameWindow.entergame:hide()
|
||||||
|
showLoading("Login", "Connecting to server...")
|
||||||
|
protocol:login(account, password, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
function onLogin(data)
|
||||||
|
if loadingBox then
|
||||||
|
loadingBox:destroy()
|
||||||
|
loadingBox = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if data["error"] and data["error"]:len() > 0 then
|
||||||
|
entergameWindow.entergame:show()
|
||||||
|
return message("Login error", data["error"])
|
||||||
|
end
|
||||||
|
|
||||||
|
local incorrectThings = validateThings(data["things"])
|
||||||
|
if incorrectThings:len() > 0 then
|
||||||
|
entergameWindow.entergame:show()
|
||||||
|
return message("Login error - missing things", incorrectThings)
|
||||||
|
end
|
||||||
|
|
||||||
|
if infoBox then
|
||||||
|
infoBox:destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
local version = data["version"]
|
||||||
|
G.clientVersion = version
|
||||||
|
g_game.setClientVersion(version)
|
||||||
|
g_game.setProtocolVersion(g_game.getClientProtocolVersion(version))
|
||||||
|
g_game.setCustomOs(-1) -- disable custom os
|
||||||
|
|
||||||
|
local customProtocol = data["customProtocol"]
|
||||||
|
g_game.setCustomProtocolVersion(0)
|
||||||
|
if type(customProtocol) == 'number' then
|
||||||
|
g_game.setCustomProtocolVersion(customProtocol)
|
||||||
|
end
|
||||||
|
|
||||||
|
local email = data["email"]
|
||||||
|
local security = data["security"]
|
||||||
|
entergameWindow.settings.mainPanel.email:setText(email)
|
||||||
|
entergameWindow.settings.mainPanel.security:setCurrentIndex(math.max(1, security))
|
||||||
|
|
||||||
|
entergameWindow.characters:show()
|
||||||
|
entergameWindow.entergame:hide()
|
||||||
|
end
|
||||||
|
|
||||||
|
function logout()
|
||||||
|
if not entergameWindow.characters:isVisible() and not entergameWindow.createcharacter:isVisible() then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
entergameWindow.characters:hide()
|
||||||
|
entergameWindow.createcharacter:hide()
|
||||||
|
entergameWindow.entergame:show()
|
||||||
|
message("Information", "Session expired, you has been logged out.")
|
||||||
|
end
|
||||||
|
|
||||||
|
function validateThings(things)
|
||||||
|
local incorrectThings = ""
|
||||||
|
local missingFiles = false
|
||||||
|
local versionForMissingFiles = 0
|
||||||
|
if things ~= nil then
|
||||||
|
local thingsNode = {}
|
||||||
|
for thingtype, thingdata in pairs(things) do
|
||||||
|
thingsNode[thingtype] = thingdata[1]
|
||||||
|
if not g_resources.fileExists("/data/things/" .. thingdata[1]) then
|
||||||
|
incorrectThings = incorrectThings .. "Missing file: " .. thingdata[1] .. "\n"
|
||||||
|
missingFiles = true
|
||||||
|
versionForMissingFiles = thingdata[1]:split("/")[1]
|
||||||
|
else
|
||||||
|
local localChecksum = g_resources.fileChecksum("/data/things/" .. thingdata[1]):lower()
|
||||||
|
if localChecksum ~= thingdata[2]:lower() and #thingdata[2] > 1 then
|
||||||
|
if g_resources.isLoadedFromArchive() then -- ignore checksum if it's test/debug version
|
||||||
|
incorrectThings = incorrectThings .. "Invalid checksum of file: " .. thingdata[1] .. " (is " .. localChecksum .. ", should be " .. thingdata[2]:lower() .. ")\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
g_settings.setNode("things", thingsNode)
|
||||||
|
else
|
||||||
|
g_settings.setNode("things", {})
|
||||||
|
end
|
||||||
|
if missingFiles then
|
||||||
|
incorrectThings = incorrectThings .. "\nYou should open data/things and create directory " .. versionForMissingFiles ..
|
||||||
|
".\nIn this directory (data/things/" .. versionForMissingFiles .. ") you should put missing\nfiles (Tibia.dat and Tibia.spr) " ..
|
||||||
|
"from correct Tibia version."
|
||||||
|
end
|
||||||
|
return incorrectThings
|
||||||
|
end
|
||||||
|
|
||||||
|
function doGameLogin()
|
||||||
|
local selected = nil
|
||||||
|
if entergameWindow.characters.mainPanel.charactersPanel:isVisible() then
|
||||||
|
selected = characterGroup:getSelectedWidget()
|
||||||
|
else
|
||||||
|
selected = outfitGroup:getSelectedWidget()
|
||||||
|
end
|
||||||
|
if not selected then
|
||||||
|
return message("Entergame error", "Please select character")
|
||||||
|
end
|
||||||
|
local character = selected.character
|
||||||
|
if not g_game.getFeature(GameSessionKey) then
|
||||||
|
g_game.enableFeature(GameSessionKey)
|
||||||
|
end
|
||||||
|
g_game.loginWorld("", "", character.worldName, character.worldHost, character.worldPort, character.name, "", protocol.session)
|
||||||
|
end
|
||||||
|
|
||||||
|
function onLoginError(err)
|
||||||
|
message("Login error", err)
|
||||||
|
end
|
||||||
|
|
||||||
|
function onLoginToken()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function onUpdateNeeded(signature)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function onConnectionError(message, code)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function onGameStart()
|
||||||
|
entergameWindow:hide()
|
||||||
|
end
|
||||||
|
|
||||||
|
function onGameEnd()
|
||||||
|
entergameWindow:show()
|
||||||
|
end
|
||||||
|
|
||||||
|
function onLoginWait(message, time)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function onLogout()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function createcharacter()
|
||||||
|
local name = entergameWindow.createcharacter.mainPanel.name:getText()
|
||||||
|
local gender = entergameWindow.createcharacter.mainPanel.gender:getCurrentOption().text
|
||||||
|
local vocation = entergameWindow.createcharacter.mainPanel.vocation:getCurrentOption().text
|
||||||
|
local town = entergameWindow.createcharacter.mainPanel.town:getCurrentOption().text
|
||||||
|
if name:len() < 3 or name:len() > 20 then
|
||||||
|
return message("Error", "Invalid character name")
|
||||||
|
end
|
||||||
|
protocol:createCharacter(name, gender, vocation, town)
|
||||||
|
showLoading("Creating character", "Creating new character...")
|
||||||
|
end
|
||||||
|
|
||||||
|
function onCharacterCreate(err, msg)
|
||||||
|
if loadingBox then
|
||||||
|
loadingBox:destroy()
|
||||||
|
loadingBox = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
if err then
|
||||||
|
return message("Error", err)
|
||||||
|
end
|
||||||
|
message("Success", msg)
|
||||||
|
entergameWindow.createcharacter:hide()
|
||||||
|
entergameWindow.characters:show()
|
||||||
|
end
|
||||||
|
|
||||||
|
function updateSettings()
|
||||||
|
local email = entergameWindow.settings.mainPanel.email:getText()
|
||||||
|
local security = entergameWindow.settings.mainPanel.security.currentIndex
|
||||||
|
|
||||||
|
protocol:updateSettings({
|
||||||
|
email=email,
|
||||||
|
security=security
|
||||||
|
})
|
||||||
|
|
||||||
|
entergameWindow.settings:hide()
|
||||||
|
entergameWindow.characters:show()
|
||||||
end
|
end
|
@ -4,7 +4,7 @@ Module
|
|||||||
author: otclient.ovh
|
author: otclient.ovh
|
||||||
website: http://otclient.ovh
|
website: http://otclient.ovh
|
||||||
sandboxed: true
|
sandboxed: true
|
||||||
scripts: [ entergamev2 ]
|
scripts: [ protocol, entergamev2 ]
|
||||||
@onLoad: init()
|
@onLoad: init()
|
||||||
@onUnload: terminate()
|
@onUnload: terminate()
|
||||||
|
|
@ -60,7 +60,7 @@ EnterGame < Panel
|
|||||||
id: mainPanel
|
id: mainPanel
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
size: 250 210
|
size: 230 210
|
||||||
!text: tr("Enter Game")
|
!text: tr("Enter Game")
|
||||||
padding-top: 36
|
padding-top: 36
|
||||||
padding-left: 16
|
padding-left: 16
|
||||||
@ -130,7 +130,7 @@ EnterGame < Panel
|
|||||||
anchors.horizontalCenter: prev.horizontalCenter
|
anchors.horizontalCenter: prev.horizontalCenter
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 20
|
margin-top: 20
|
||||||
size: 200 50
|
size: 290 50
|
||||||
image-source: /images/ui/window_headless
|
image-source: /images/ui/window_headless
|
||||||
image-border: 6
|
image-border: 6
|
||||||
padding-top: 8
|
padding-top: 8
|
||||||
@ -138,9 +138,18 @@ EnterGame < Panel
|
|||||||
Button
|
Button
|
||||||
id: register
|
id: register
|
||||||
anchors.verticalCenter: buttons.verticalCenter
|
anchors.verticalCenter: buttons.verticalCenter
|
||||||
anchors.horizontalCenter: buttons.horizontalCenter
|
anchors.left: buttons.left
|
||||||
|
margin-left: 10
|
||||||
!text: tr("Create account")
|
!text: tr("Create account")
|
||||||
size: 160 30
|
size: 130 30
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: register
|
||||||
|
anchors.verticalCenter: buttons.verticalCenter
|
||||||
|
anchors.right: buttons.right
|
||||||
|
margin-right: 10
|
||||||
|
!text: tr("Casts")
|
||||||
|
size: 130 30
|
||||||
|
|
||||||
Registration < Panel
|
Registration < Panel
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -226,7 +235,6 @@ Registration < Panel
|
|||||||
margin-top: 10
|
margin-top: 10
|
||||||
margin-left: 50
|
margin-left: 50
|
||||||
margin-right: 50
|
margin-right: 50
|
||||||
@onClick: EnterGame.doLogin()
|
|
||||||
|
|
||||||
EnterGamePanel
|
EnterGamePanel
|
||||||
id: buttons
|
id: buttons
|
||||||
@ -261,7 +269,6 @@ QuickLogin < EnterGamePanel
|
|||||||
image-fixed-ratio: true
|
image-fixed-ratio: true
|
||||||
image-smooth: false
|
image-smooth: false
|
||||||
margin-top: 5
|
margin-top: 5
|
||||||
qr: 123
|
|
||||||
|
|
||||||
UIButton
|
UIButton
|
||||||
id: quathlogo
|
id: quathlogo
|
||||||
@ -319,7 +326,6 @@ Characters < Panel
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
text-wrap: true
|
text-wrap: true
|
||||||
text: This is motd ;)
|
|
||||||
text-align: center
|
text-align: center
|
||||||
|
|
||||||
HorizontalSeparator
|
HorizontalSeparator
|
||||||
@ -328,22 +334,45 @@ Characters < Panel
|
|||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 5
|
margin-top: 5
|
||||||
height: 10
|
|
||||||
|
|
||||||
ScrollablePanel
|
ScrollablePanel
|
||||||
id: charactersPanel
|
id: outfitsPanel
|
||||||
layout:
|
layout:
|
||||||
type: grid
|
type: grid
|
||||||
cell-size: 100 100
|
cell-size: 125 125
|
||||||
cell-spacing: 1
|
cell-spacing: 1
|
||||||
flow: true
|
flow: true
|
||||||
vertical-scrollbar: charactersScroll
|
vertical-scrollbar: outfitsScroll
|
||||||
|
background-color: #444444
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
anchors.bottom: bottomSeparator.top
|
anchors.bottom: bottomSeparator.top
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
margin-bottom: 10
|
|
||||||
margin-right: 12
|
margin-right: 12
|
||||||
|
margin-bottom: 5
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: outfitsScroll
|
||||||
|
anchors.top: outfitsPanel.top
|
||||||
|
anchors.bottom: outfitsPanel.bottom
|
||||||
|
anchors.left: outfitsPanel.right
|
||||||
|
step: 14
|
||||||
|
pixels-scroll: true
|
||||||
|
|
||||||
|
ScrollablePanel
|
||||||
|
id: charactersPanel
|
||||||
|
layout:
|
||||||
|
type: verticalBox
|
||||||
|
vertical-scrollbar: charactersScroll
|
||||||
|
background-color: #444444
|
||||||
|
anchors.top: motdSeparator.bottom
|
||||||
|
anchors.bottom: bottomSeparator.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-right: 12
|
||||||
|
margin-bottom: 5
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
VerticalScrollBar
|
VerticalScrollBar
|
||||||
id: charactersScroll
|
id: charactersScroll
|
||||||
@ -351,14 +380,14 @@ Characters < Panel
|
|||||||
anchors.bottom: charactersPanel.bottom
|
anchors.bottom: charactersPanel.bottom
|
||||||
anchors.left: charactersPanel.right
|
anchors.left: charactersPanel.right
|
||||||
step: 14
|
step: 14
|
||||||
pixels-scroll: true
|
pixels-scroll: true
|
||||||
|
|
||||||
HorizontalSeparator
|
HorizontalSeparator
|
||||||
id: bottomSeparator
|
id: bottomSeparator
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
height: 35
|
margin-bottom: 30
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: autoReconnect
|
id: autoReconnect
|
||||||
@ -370,7 +399,7 @@ Characters < Panel
|
|||||||
$!on:
|
$!on:
|
||||||
image-color: red
|
image-color: red
|
||||||
!text: tr('Auto reconnect: Off')
|
!text: tr('Auto reconnect: Off')
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: showOutfits
|
id: showOutfits
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
@ -378,10 +407,10 @@ Characters < Panel
|
|||||||
width: 140
|
width: 140
|
||||||
|
|
||||||
$on:
|
$on:
|
||||||
!text: tr("Show outfits")
|
!text: tr("Hide big outfits")
|
||||||
|
|
||||||
$!on:
|
$!on:
|
||||||
!text: tr("Hide outfits")
|
!text: tr("Show big outfits")
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: connect
|
id: connect
|
||||||
@ -389,6 +418,7 @@ Characters < Panel
|
|||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
!text: tr("Connect")
|
!text: tr("Connect")
|
||||||
width: 140
|
width: 140
|
||||||
|
@onClick: modules.client_entergamev2.doGameLogin()
|
||||||
|
|
||||||
EnterGamePanel
|
EnterGamePanel
|
||||||
id: buttons
|
id: buttons
|
||||||
@ -409,10 +439,10 @@ Characters < Panel
|
|||||||
size: 140 30
|
size: 140 30
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: casts
|
id: settings
|
||||||
anchors.verticalCenter: buttons.verticalCenter
|
anchors.verticalCenter: buttons.verticalCenter
|
||||||
anchors.horizontalCenter: buttons.horizontalCenter
|
anchors.horizontalCenter: buttons.horizontalCenter
|
||||||
!text: tr("Casts")
|
!text: tr("Account settings")
|
||||||
size: 140 30
|
size: 140 30
|
||||||
|
|
||||||
Button
|
Button
|
||||||
@ -423,10 +453,11 @@ Characters < Panel
|
|||||||
!text: tr("Logout")
|
!text: tr("Logout")
|
||||||
size: 140 30
|
size: 140 30
|
||||||
|
|
||||||
EntergameCharacter < UIButton
|
EntergameBigCharacter < UIButton
|
||||||
border-width: 1
|
border-width: 1
|
||||||
padding: 1 1 1 1
|
padding: 1 1 1 1
|
||||||
@onClick: self:setChecked(true)
|
@onClick: self:setChecked(true)
|
||||||
|
@onDoubleClick: modules.client_entergamev2.doGameLogin()
|
||||||
|
|
||||||
$checked:
|
$checked:
|
||||||
border-color: #ffffff
|
border-color: #ffffff
|
||||||
@ -438,7 +469,7 @@ EntergameCharacter < UIButton
|
|||||||
id: outfit
|
id: outfit
|
||||||
anchors.bottom: parent.bottom
|
anchors.bottom: parent.bottom
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
size: 48 48
|
size: 70 70
|
||||||
margin-bottom: 3
|
margin-bottom: 3
|
||||||
phantom: true
|
phantom: true
|
||||||
|
|
||||||
@ -447,39 +478,99 @@ EntergameCharacter < UIButton
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
text: Dagusia Druid
|
|
||||||
text-align: center
|
text-align: center
|
||||||
text-wrap: false
|
text-wrap: false
|
||||||
height: 16
|
height: 16
|
||||||
font: terminus-10px
|
font: terminus-10px
|
||||||
border-width-bottom: 1
|
border-width-bottom: 1
|
||||||
border-color: #00000077
|
border-color: #00000077
|
||||||
|
phantom: true
|
||||||
|
|
||||||
Label
|
Label
|
||||||
id: line2
|
id: line2
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
text: Level: 666
|
|
||||||
text-align: center
|
text-align: center
|
||||||
text-wrap: false
|
text-wrap: false
|
||||||
height: 16
|
height: 16
|
||||||
font: terminus-10px
|
font: terminus-10px
|
||||||
border-width-bottom: 1
|
border-width-bottom: 1
|
||||||
border-color: #00000077
|
border-color: #00000077
|
||||||
|
phantom: true
|
||||||
|
|
||||||
Label
|
Label
|
||||||
id: line3
|
id: line3
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
text: World: nemezis
|
|
||||||
text-align: center
|
text-align: center
|
||||||
text-wrap: false
|
text-wrap: false
|
||||||
height: 16
|
height: 16
|
||||||
font: terminus-10px
|
font: terminus-10px
|
||||||
border-width-bottom: 1
|
border-width-bottom: 1
|
||||||
border-color: #00000077
|
border-color: #00000077
|
||||||
|
phantom: true
|
||||||
|
|
||||||
|
EntergameCharacter < UIButton
|
||||||
|
padding: 3 3 3 3
|
||||||
|
@onClick: self:setChecked(true)
|
||||||
|
@onDoubleClick: modules.client_entergamev2.doGameLogin()
|
||||||
|
height: 34
|
||||||
|
|
||||||
|
$checked:
|
||||||
|
background-color: #333333
|
||||||
|
|
||||||
|
$!checked:
|
||||||
|
background-color: #555555
|
||||||
|
|
||||||
|
UICreature
|
||||||
|
id: outfit
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
size: 32 32
|
||||||
|
margin-top: -2
|
||||||
|
margin-bottom: -2
|
||||||
|
phantom: true
|
||||||
|
|
||||||
|
UILabel
|
||||||
|
id: line1
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
margin-left: 6
|
||||||
|
width: 150
|
||||||
|
text-align: left
|
||||||
|
phantom: true
|
||||||
|
|
||||||
|
VerticalSeparator
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
UILabel
|
||||||
|
id: line2
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
width: 150
|
||||||
|
text-align: center
|
||||||
|
phantom: true
|
||||||
|
|
||||||
|
VerticalSeparator
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
|
||||||
|
UILabel
|
||||||
|
id: line3
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
text-align: center
|
||||||
|
phantom: true
|
||||||
|
|
||||||
CreateCharacter < Panel
|
CreateCharacter < Panel
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
@ -503,12 +594,32 @@ CreateCharacter < Panel
|
|||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
|
|
||||||
TextEdit
|
TextEdit
|
||||||
id: accountNameTextEdit
|
id: name
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 2
|
margin-top: 2
|
||||||
|
|
||||||
|
MenuLabel
|
||||||
|
!text: tr('Gender')
|
||||||
|
anchors.left: prev.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 8
|
||||||
|
text-auto-resize: true
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
id: gender
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
menu-scroll: true
|
||||||
|
menu-height: 125
|
||||||
|
menu-scroll-step: 25
|
||||||
|
margin-right: 3
|
||||||
|
@onSetup: |
|
||||||
|
self:addOption("Male")
|
||||||
|
self:addOption("Female")
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
!text: tr('Vocation')
|
!text: tr('Vocation')
|
||||||
anchors.left: prev.left
|
anchors.left: prev.left
|
||||||
@ -516,40 +627,42 @@ CreateCharacter < Panel
|
|||||||
margin-top: 8
|
margin-top: 8
|
||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
|
|
||||||
TextEdit
|
ComboBox
|
||||||
id: emailTextEdit
|
id: vocation
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 2
|
menu-scroll: true
|
||||||
|
menu-height: 125
|
||||||
MenuLabel
|
menu-scroll-step: 25
|
||||||
!text: tr('Password')
|
margin-right: 3
|
||||||
anchors.left: prev.left
|
@onSetup: |
|
||||||
anchors.top: prev.bottom
|
self:addOption("Sorcerer")
|
||||||
margin-top: 8
|
self:addOption("Druid")
|
||||||
text-auto-resize: true
|
self:addOption("Paladin")
|
||||||
|
self:addOption("Knight")
|
||||||
PasswordTextEdit
|
|
||||||
id: accountPasswordTextEdit
|
|
||||||
anchors.left: parent.left
|
|
||||||
anchors.right: parent.right
|
|
||||||
anchors.top: prev.bottom
|
|
||||||
margin-top: 2
|
|
||||||
|
|
||||||
MenuLabel
|
MenuLabel
|
||||||
!text: tr('Password confirmation')
|
!text: tr('Town')
|
||||||
anchors.left: prev.left
|
anchors.left: prev.left
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 8
|
margin-top: 8
|
||||||
text-auto-resize: true
|
text-auto-resize: true
|
||||||
|
|
||||||
PasswordTextEdit
|
ComboBox
|
||||||
id: accountPasswordTextEdit
|
id: town
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
margin-top: 2
|
menu-scroll: true
|
||||||
|
menu-height: 125
|
||||||
|
menu-scroll-step: 25
|
||||||
|
margin-right: 3
|
||||||
|
@onSetup: |
|
||||||
|
self:addOption("Carlin")
|
||||||
|
self:addOption("Edron")
|
||||||
|
self:addOption("Thais")
|
||||||
|
self:addOption("Venore")
|
||||||
|
|
||||||
HorizontalSeparator
|
HorizontalSeparator
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
@ -558,6 +671,7 @@ CreateCharacter < Panel
|
|||||||
margin-top: 9
|
margin-top: 9
|
||||||
|
|
||||||
Button
|
Button
|
||||||
|
id: createButton
|
||||||
!text: tr('Create character')
|
!text: tr('Create character')
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
@ -565,7 +679,89 @@ CreateCharacter < Panel
|
|||||||
margin-top: 10
|
margin-top: 10
|
||||||
margin-left: 50
|
margin-left: 50
|
||||||
margin-right: 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
|
||||||
|
|
||||||
|
|
||||||
|
AccountSettings < Panel
|
||||||
|
anchors.fill: parent
|
||||||
|
id: settings
|
||||||
|
|
||||||
|
EnterGamePanel
|
||||||
|
id: mainPanel
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
size: 250 173
|
||||||
|
!text: tr("Account settings")
|
||||||
|
padding-top: 36
|
||||||
|
padding-left: 16
|
||||||
|
padding-right: 16
|
||||||
|
padding-bottom: 16
|
||||||
|
|
||||||
|
MenuLabel
|
||||||
|
!text: tr('Email')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
text-auto-resize: true
|
||||||
|
|
||||||
|
TextEdit
|
||||||
|
id: email
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 2
|
||||||
|
|
||||||
|
MenuLabel
|
||||||
|
!text: tr('Security level')
|
||||||
|
anchors.left: prev.left
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 8
|
||||||
|
text-auto-resize: true
|
||||||
|
|
||||||
|
ComboBox
|
||||||
|
id: security
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
menu-scroll: true
|
||||||
|
menu-height: 125
|
||||||
|
menu-scroll-step: 25
|
||||||
|
margin-right: 3
|
||||||
|
@onSetup: |
|
||||||
|
self:addOption("Low")
|
||||||
|
self:addOption("Medium")
|
||||||
|
self:addOption("High")
|
||||||
|
|
||||||
|
HorizontalSeparator
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 9
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: updateButton
|
||||||
|
!text: tr('Update settings')
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
margin-top: 10
|
||||||
|
margin-left: 50
|
||||||
|
margin-right: 50
|
||||||
|
|
||||||
EnterGamePanel
|
EnterGamePanel
|
||||||
id: buttons
|
id: buttons
|
||||||
@ -597,3 +793,4 @@ Panel
|
|||||||
Registration
|
Registration
|
||||||
Characters
|
Characters
|
||||||
CreateCharacter
|
CreateCharacter
|
||||||
|
AccountSettings
|
||||||
|
228
modules/client_entergamev2/protocol.lua
Normal file
228
modules/client_entergamev2/protocol.lua
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
EnterGameV2Protocol = {}
|
||||||
|
EnterGameV2Protocol.__index = EnterGameV2Protocol
|
||||||
|
|
||||||
|
EnterGameV2Protocol.new = function(session)
|
||||||
|
if type(session) ~= 'string' then
|
||||||
|
return error("You need to specify string session for EnterGameV2Protocol")
|
||||||
|
end
|
||||||
|
local data = {}
|
||||||
|
data.socket = nil
|
||||||
|
data.terminated = false
|
||||||
|
data.reconnectEvent = nil
|
||||||
|
data.connected = false
|
||||||
|
data.session = session
|
||||||
|
data.sendQueue = {}
|
||||||
|
data.sendQueueMsgId = 1
|
||||||
|
data.loginTimeoutEvent = nil
|
||||||
|
setmetatable(data, EnterGameV2Protocol)
|
||||||
|
return data
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:destroy()
|
||||||
|
self.terminated = true
|
||||||
|
self.sendQueue = {}
|
||||||
|
|
||||||
|
if self.loginTimeoutEvent then
|
||||||
|
removeEvent(self.loginTimeoutEvent)
|
||||||
|
self.loginTimeoutEvent = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
self:reset()
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:reset()
|
||||||
|
self.connected = false
|
||||||
|
if self.reconnectEvent then
|
||||||
|
removeEvent(self.reconnectEvent)
|
||||||
|
self.reconnectEvent = nil
|
||||||
|
end
|
||||||
|
if self.socket then
|
||||||
|
self.socket.close()
|
||||||
|
self.socket = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:setUrl(url)
|
||||||
|
if self.terminated then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
self:reset()
|
||||||
|
if self.url ~= url then
|
||||||
|
self.sendQueue = {}
|
||||||
|
self.sendQueueMsgId = 1
|
||||||
|
if self.loginTimeoutEvent then
|
||||||
|
removeEvent(self.loginTimeoutEvent)
|
||||||
|
self.loginTimeoutEvent = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if type(url) ~= 'string' or not url:lower():find("ws") then
|
||||||
|
g_logger.error("Invalid url for EnterGameV2Protocol:\n" .. url)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
self.url = url
|
||||||
|
self.socket = HTTP.WebSocketJSON(url, {
|
||||||
|
onOpen = function(message, websocketId)
|
||||||
|
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
|
||||||
|
self.connected = true
|
||||||
|
self:sendFirstMessage()
|
||||||
|
end,
|
||||||
|
onMessage = function(message, websocketId)
|
||||||
|
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
|
||||||
|
self:onSocketMessage(message)
|
||||||
|
end,
|
||||||
|
onClose = function(message, websocketId)
|
||||||
|
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
|
||||||
|
self.connected = false
|
||||||
|
self:scheduleReconnect()
|
||||||
|
end,
|
||||||
|
onError = function(message, websocketId)
|
||||||
|
if self.terminated or not self.socket or self.socket.id ~= websocketId then return end
|
||||||
|
self.connected = false
|
||||||
|
self:scheduleReconnect()
|
||||||
|
end
|
||||||
|
})
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:isConnected()
|
||||||
|
return self.socket and self.connected
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:scheduleReconnect()
|
||||||
|
if self.socket then
|
||||||
|
self.connected = false
|
||||||
|
self.socket.close()
|
||||||
|
self.socket = nil
|
||||||
|
end
|
||||||
|
if self.terminated then return end
|
||||||
|
if self.reconnectEvent then return end
|
||||||
|
self.reconnectEvent = scheduleEvent(function() self:reconnect() end, 500)
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:login(account, password, token, callback)
|
||||||
|
self:send({
|
||||||
|
type="login",
|
||||||
|
account=account,
|
||||||
|
password=password,
|
||||||
|
token=token,
|
||||||
|
})
|
||||||
|
if self.loginTimeoutEvent then
|
||||||
|
removeEvent(self.loginTimeoutEvent)
|
||||||
|
end
|
||||||
|
self.loginTimeoutEvent = scheduleEvent(function()
|
||||||
|
self.loginTimeoutEvent = nil
|
||||||
|
self.onLogin({error="Connection timeout"})
|
||||||
|
end, 10000)
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:logout()
|
||||||
|
self:send({
|
||||||
|
type="logout"
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:register(name, email, password, callback)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:createCharacter(name, gender, vocation, town)
|
||||||
|
self:send({
|
||||||
|
type="createcharacter",
|
||||||
|
name=name,
|
||||||
|
gender=gender,
|
||||||
|
vocation=vocation,
|
||||||
|
town=town
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:updateSettings(settings)
|
||||||
|
self:send({
|
||||||
|
type="settings",
|
||||||
|
settings=settings
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
-- private functions
|
||||||
|
function EnterGameV2Protocol:reconnect()
|
||||||
|
if #self.sendQueue > 1 then
|
||||||
|
self.sendQueue = {} -- TEMPORARY
|
||||||
|
end
|
||||||
|
self.reconnectEvent = nil
|
||||||
|
if self.terminated then return end
|
||||||
|
self:setUrl(self.url)
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:send(data)
|
||||||
|
if type(data) ~= "table" then
|
||||||
|
return error("data should be table")
|
||||||
|
end
|
||||||
|
data["id"] = self.sendQueueMsgId
|
||||||
|
table.insert(self.sendQueue, {id=self.sendQueueMsgId, msg=json.encode(data)})
|
||||||
|
self.sendQueueMsgId = self.sendQueueMsgId + 1
|
||||||
|
if self.socket then
|
||||||
|
self.socket.send(self.sendQueue[#self.sendQueue].msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:sendFirstMessage()
|
||||||
|
self.socket.send({type="init", session=self.session})
|
||||||
|
for i, msg in ipairs(self.sendQueue) do
|
||||||
|
self.socket.send(msg.msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function EnterGameV2Protocol:onSocketMessage(message)
|
||||||
|
local lastId = message["lastId"]
|
||||||
|
if type(lastId) == 'number' then -- clear send queue
|
||||||
|
while #self.sendQueue > 0 do
|
||||||
|
local id = self.sendQueue[1].id
|
||||||
|
if id < lastId then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
table.remove(self.sendQueue, 1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if message["type"] == "ping" then
|
||||||
|
self.socket.send({type="ping"})
|
||||||
|
elseif message["type"] == "login" then
|
||||||
|
if self.loginTimeoutEvent then
|
||||||
|
removeEvent(self.loginTimeoutEvent)
|
||||||
|
self.loginTimeoutEvent = nil
|
||||||
|
end
|
||||||
|
if self.onLogin then
|
||||||
|
self.onLogin(message)
|
||||||
|
end
|
||||||
|
elseif message["type"] == "logout" then
|
||||||
|
if self.onLogout then
|
||||||
|
self.onLogout()
|
||||||
|
end
|
||||||
|
elseif message["type"] == "qauth" then
|
||||||
|
if self.onQAuth then
|
||||||
|
self.onQAuth(message["token"])
|
||||||
|
end
|
||||||
|
elseif message["type"] == "characters" then
|
||||||
|
if self.onCharacters then
|
||||||
|
self.onCharacters(message["characters"])
|
||||||
|
end
|
||||||
|
elseif message["type"] == "message" then
|
||||||
|
if self.onMessage then
|
||||||
|
self.onMessage(message["title"], message["text"])
|
||||||
|
end
|
||||||
|
elseif message["type"] == "loading" then
|
||||||
|
if self.onMessage then
|
||||||
|
self.onLoading(message["title"], message["text"])
|
||||||
|
end
|
||||||
|
elseif message["type"] == "news" then
|
||||||
|
if self.onNews then
|
||||||
|
self.onNews(message["news"])
|
||||||
|
end
|
||||||
|
elseif message["type"] == "motd" then
|
||||||
|
if self.onMotd then
|
||||||
|
self.onMotd(message["text"])
|
||||||
|
end
|
||||||
|
elseif message["type"] == "createcharacter" then
|
||||||
|
if self.onMessage then
|
||||||
|
self.onCharacterCreate(message["error"], message["message"])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -170,7 +170,7 @@ function update()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
statsWindow.debugPanel.sleepTime:setText("Sleep: " .. math.round(g_stats.getSleepTime() / math.max(1, g_clock.micros() - lastSleepTimeReset), 2) .. "%")
|
statsWindow.debugPanel.sleepTime:setText("Sleep: " .. math.round(g_stats.getSleepTime() / math.max(1, g_clock.micros() - lastSleepTimeReset), 2) .. "%, Packets: " .. g_game.getRecivedPacketsCount() .. " , " .. (g_game.getRecivedPacketsSize() / 1024) .. " KB")
|
||||||
statsWindow.debugPanel.luaRamUsage:setText("Ram usage by lua: " .. gcinfo() .. " kb")
|
statsWindow.debugPanel.luaRamUsage:setText("Ram usage by lua: " .. gcinfo() .. " kb")
|
||||||
local adaptive = "Adaptive: " .. g_adaptiveRenderer.getLevel() .. " | " .. g_adaptiveRenderer.getDebugInfo()
|
local adaptive = "Adaptive: " .. g_adaptiveRenderer.getLevel() .. " | " .. g_adaptiveRenderer.getDebugInfo()
|
||||||
adaptiveRender:setText(adaptive)
|
adaptiveRender:setText(adaptive)
|
||||||
|
@ -141,6 +141,7 @@ function init()
|
|||||||
terminalWindow.onDoubleClick = popWindow
|
terminalWindow.onDoubleClick = popWindow
|
||||||
|
|
||||||
terminalButton = modules.client_topmenu.addLeftButton('terminalButton', tr('Terminal') .. ' (Ctrl + T)', '/images/topbuttons/terminal', toggle)
|
terminalButton = modules.client_topmenu.addLeftButton('terminalButton', tr('Terminal') .. ' (Ctrl + T)', '/images/topbuttons/terminal', toggle)
|
||||||
|
terminalButton:setOn(false)
|
||||||
g_keyboard.bindKeyDown('Ctrl+T', toggle)
|
g_keyboard.bindKeyDown('Ctrl+T', toggle)
|
||||||
|
|
||||||
commandHistory = g_settings.getList('terminal-history')
|
commandHistory = g_settings.getList('terminal-history')
|
||||||
@ -197,7 +198,7 @@ function terminate()
|
|||||||
g_keyboard.unbindKeyDown('Ctrl+T')
|
g_keyboard.unbindKeyDown('Ctrl+T')
|
||||||
g_logger.setOnLog(nil)
|
g_logger.setOnLog(nil)
|
||||||
terminalWindow:destroy()
|
terminalWindow:destroy()
|
||||||
--terminalButton:destroy()
|
terminalButton:destroy()
|
||||||
commandEnv = nil
|
commandEnv = nil
|
||||||
_G.terminalLines = allLines
|
_G.terminalLines = allLines
|
||||||
end
|
end
|
||||||
|
@ -209,4 +209,79 @@ function table.equal(t1,t2,ignore_mt)
|
|||||||
if v1 == nil or not table.equal(v1,v2) then return false end
|
if v1 == nil or not table.equal(v1,v2) then return false end
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.isList(t)
|
||||||
|
local size = #t
|
||||||
|
return table.size(t) == size and size > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.isStringList(t)
|
||||||
|
if not table.isList(t) then return false end
|
||||||
|
for k,v in ipairs(t) do
|
||||||
|
if type(v) ~= 'string' then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.isStringPairList(t)
|
||||||
|
if not table.isList(t) then return false end
|
||||||
|
for k,v in ipairs(t) do
|
||||||
|
if type(v) ~= 'table' or #v ~= 2 or type(v[1]) ~= 'string' or type(v[2]) ~= 'string' then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
function table.encodeStringPairList(t)
|
||||||
|
local ret = ""
|
||||||
|
for k,v in ipairs(t) do
|
||||||
|
if v[2]:find("\n") then
|
||||||
|
ret = ret .. v[1] .. ":[[\n" .. v[2] .. "\n]]\n"
|
||||||
|
else
|
||||||
|
ret = ret .. v[1] .. ":" .. v[2] .. "\n"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
end
|
||||||
|
|
||||||
|
function table.decodeStringPairList(l)
|
||||||
|
local ret = {}
|
||||||
|
local r = regexMatch(l, "^([^:^\n]{1,20}):?(.*)$")
|
||||||
|
local multiline = ""
|
||||||
|
local multilineKey = ""
|
||||||
|
local multilineActive = false
|
||||||
|
for k,v in ipairs(r) do
|
||||||
|
if multilineActive then
|
||||||
|
local endPos = v[1]:find("%]%]")
|
||||||
|
if endPos then
|
||||||
|
if endPos > 1 then
|
||||||
|
table.insert(ret, {multilineKey, multiline .. "\n" .. v[1]:sub(1, endPos - 1)})
|
||||||
|
else
|
||||||
|
table.insert(ret, {multilineKey, multiline})
|
||||||
|
end
|
||||||
|
multilineActive = false
|
||||||
|
multiline = ""
|
||||||
|
multilineKey = ""
|
||||||
|
else
|
||||||
|
if multiline:len() == 0 then
|
||||||
|
multiline = v[1]
|
||||||
|
else
|
||||||
|
multiline = multiline .. "\n" .. v[1]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local bracketPos = v[3]:find("%[%[")
|
||||||
|
if bracketPos == 1 then -- multiline begin
|
||||||
|
multiline = v[3]:sub(bracketPos + 2)
|
||||||
|
multilineActive = true
|
||||||
|
multilineKey = v[2]
|
||||||
|
elseif v[2]:len() > 0 and v[3]:len() > 0 then
|
||||||
|
table.insert(ret, {v[2], v[3]})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return ret
|
||||||
end
|
end
|
@ -144,7 +144,7 @@ function setupAction(index, action, config)
|
|||||||
|
|
||||||
if config then
|
if config then
|
||||||
action.hotkey = config.hotkey
|
action.hotkey = config.hotkey
|
||||||
if action.hotkey then
|
if action.hotkey and action.hotkey:len() > 0 then
|
||||||
local gameRootPanel = modules.game_interface.getRootPanel()
|
local gameRootPanel = modules.game_interface.getRootPanel()
|
||||||
g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
||||||
end
|
end
|
||||||
@ -300,11 +300,11 @@ function actionOnMouseRelease(action, mousePosition, mouseButton)
|
|||||||
end
|
end
|
||||||
assignWindow.addButton.onClick = function()
|
assignWindow.addButton.onClick = function()
|
||||||
local gameRootPanel = modules.game_interface.getRootPanel()
|
local gameRootPanel = modules.game_interface.getRootPanel()
|
||||||
if action.hotkey then
|
if action.hotkey and action.hotkey:len() > 0 then
|
||||||
g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
||||||
end
|
end
|
||||||
action.hotkey = assignWindow.comboPreview.keyCombo
|
action.hotkey = assignWindow.comboPreview.keyCombo
|
||||||
if action.hotkey then
|
if action.hotkey and action.hotkey:len() > 0 then
|
||||||
g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
g_keyboard.bindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
||||||
end
|
end
|
||||||
action.hotkeyLabel:setText(action.hotkey or "")
|
action.hotkeyLabel:setText(action.hotkey or "")
|
||||||
@ -318,7 +318,7 @@ function actionOnMouseRelease(action, mousePosition, mouseButton)
|
|||||||
action.text:setText("")
|
action.text:setText("")
|
||||||
action.hotkeyLabel:setText("")
|
action.hotkeyLabel:setText("")
|
||||||
local gameRootPanel = modules.game_interface.getRootPanel()
|
local gameRootPanel = modules.game_interface.getRootPanel()
|
||||||
if action.hotkey then
|
if action.hotkey and action.hotkey:len() > 0 then
|
||||||
g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
g_keyboard.unbindKeyPress(action.hotkey, action.callback, gameRootPanel)
|
||||||
end
|
end
|
||||||
action.hotkey = nil
|
action.hotkey = nil
|
||||||
|
@ -24,6 +24,7 @@ function init()
|
|||||||
g_ui.importStyle("ui/panels.otui")
|
g_ui.importStyle("ui/panels.otui")
|
||||||
g_ui.importStyle("ui/config.otui")
|
g_ui.importStyle("ui/config.otui")
|
||||||
g_ui.importStyle("ui/icons.otui")
|
g_ui.importStyle("ui/icons.otui")
|
||||||
|
g_ui.importStyle("ui/container.otui")
|
||||||
|
|
||||||
connect(g_game, {
|
connect(g_game, {
|
||||||
onGameStart = online,
|
onGameStart = online,
|
||||||
@ -195,7 +196,7 @@ function refresh()
|
|||||||
|
|
||||||
-- run script
|
-- run script
|
||||||
local status, result = pcall(function()
|
local status, result = pcall(function()
|
||||||
return executeBot(configName, botStorage, botTabs, message, save, botWebSockets) end
|
return executeBot(configName, botStorage, botTabs, message, save, refresh, botWebSockets) end
|
||||||
)
|
)
|
||||||
if not status then
|
if not status then
|
||||||
return onError(result)
|
return onError(result)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, websockets)
|
function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, reloadCallback, websockets)
|
||||||
-- load lua and otui files
|
-- load lua and otui files
|
||||||
local configFiles = g_resources.listDirectoryFiles("/bot/" .. config, true, false)
|
local configFiles = g_resources.listDirectoryFiles("/bot/" .. config, true, false)
|
||||||
local luaFiles = {}
|
local luaFiles = {}
|
||||||
@ -21,16 +21,18 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
|
|||||||
local context = {}
|
local context = {}
|
||||||
context.configDir = "/bot/".. config
|
context.configDir = "/bot/".. config
|
||||||
context.tabs = tabs
|
context.tabs = tabs
|
||||||
context.panel = context.tabs:addTab("Main", g_ui.createWidget('BotPanel')).tabPanel.content
|
context.mainTab = context.tabs:addTab("Main", g_ui.createWidget('BotPanel')).tabPanel.content
|
||||||
|
context.panel = context.mainTab
|
||||||
context.saveConfig = saveConfigCallback
|
context.saveConfig = saveConfigCallback
|
||||||
context._websockets = websockets
|
context.reload = reloadCallback
|
||||||
|
|
||||||
context.storage = storage
|
context.storage = storage
|
||||||
if context.storage._macros == nil then
|
if context.storage._macros == nil then
|
||||||
context.storage._macros = {} -- active macros
|
context.storage._macros = {} -- active macros
|
||||||
end
|
end
|
||||||
|
|
||||||
-- macros, hotkeys, scheduler, icons, callbacks
|
-- websockets, macros, hotkeys, scheduler, icons, callbacks
|
||||||
|
context._websockets = websockets
|
||||||
context._macros = {}
|
context._macros = {}
|
||||||
context._hotkeys = {}
|
context._hotkeys = {}
|
||||||
context._scheduler = {}
|
context._scheduler = {}
|
||||||
@ -71,9 +73,10 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
|
|||||||
context.tonumber = tonumber
|
context.tonumber = tonumber
|
||||||
context.type = type
|
context.type = type
|
||||||
context.pcall = pcall
|
context.pcall = pcall
|
||||||
context.load = function(str) return load(str, nil, nil, context) end
|
context.load = function(str) return assert(load(str, nil, nil, context)) end
|
||||||
context.loadstring = context.load
|
context.loadstring = context.load
|
||||||
context.assert = assert
|
context.assert = assert
|
||||||
|
context.dofile = function(file) assert(load(g_resources.readFileContents("/bot/" .. config .. "/" .. file), file, nil, context))() end
|
||||||
context.gcinfo = gcinfo
|
context.gcinfo = gcinfo
|
||||||
context.tr = tr
|
context.tr = tr
|
||||||
context.json = json
|
context.json = json
|
||||||
@ -129,7 +132,8 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, webs
|
|||||||
|
|
||||||
-- run lua script
|
-- run lua script
|
||||||
for i, file in ipairs(luaFiles) do
|
for i, file in ipairs(luaFiles) do
|
||||||
assert(load(g_resources.readFileContents(file), file, nil, context))()
|
assert(load(g_resources.readFileContents(file), file, nil, context))()
|
||||||
|
context.panel = context.mainTab -- reset default tab
|
||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
--[[
|
--[[
|
||||||
Config. create. load and save config file (.json)
|
Config - create, load and save config file (.json / .cfg)
|
||||||
Used by cavebot and other things
|
Used by cavebot and other things
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
@ -22,7 +22,32 @@ Config.list = function(dir)
|
|||||||
return contex.error("Can't create config dir: " .. context.configDir .. "/" .. dir)
|
return contex.error("Can't create config dir: " .. context.configDir .. "/" .. dir)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return g_resources.listDirectoryFiles(context.configDir .. "/" .. dir)
|
local list = g_resources.listDirectoryFiles(context.configDir .. "/" .. dir)
|
||||||
|
local correctList = {}
|
||||||
|
for k,v in ipairs(list) do -- filter files
|
||||||
|
local nv = v:gsub(".json", ""):gsub(".cfg", "")
|
||||||
|
if nv ~= v then
|
||||||
|
table.insert(correctList, nv)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return correctList
|
||||||
|
end
|
||||||
|
|
||||||
|
-- load config from string insteaf of dile
|
||||||
|
Config.parse = function(data)
|
||||||
|
local status, result = pcall(function()
|
||||||
|
return json.decode(data)
|
||||||
|
end)
|
||||||
|
if status and type(result) == 'table' then
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
local status, result = pcall(function()
|
||||||
|
return table.decodeStringPairList(data)
|
||||||
|
end)
|
||||||
|
if status and type(result) == 'table' then
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
return context.error("Invalid config format")
|
||||||
end
|
end
|
||||||
|
|
||||||
Config.load = function(dir, name)
|
Config.load = function(dir, name)
|
||||||
@ -31,63 +56,154 @@ Config.load = function(dir, name)
|
|||||||
return json.decode(g_resources.readFileContents(file))
|
return json.decode(g_resources.readFileContents(file))
|
||||||
end
|
end
|
||||||
file = context.configDir .. "/" .. dir .. "/" .. name .. ".cfg"
|
file = context.configDir .. "/" .. dir .. "/" .. name .. ".cfg"
|
||||||
|
if g_resources.fileExists(file) then -- load cfg
|
||||||
|
return table.decodeStringPairList(g_resources.readFileContents(file))
|
||||||
|
end
|
||||||
|
return context.error("Config " .. file .. " doesn't exist")
|
||||||
|
end
|
||||||
|
|
||||||
|
Config.loadRaw = function(dir, name)
|
||||||
|
local file = context.configDir .. "/" .. dir .. "/" .. name .. ".json"
|
||||||
|
if g_resources.fileExists(file) then -- load json
|
||||||
|
return g_resources.readFileContents(file)
|
||||||
|
end
|
||||||
|
file = context.configDir .. "/" .. dir .. "/" .. name .. ".cfg"
|
||||||
if g_resources.fileExists(file) then -- load cfg
|
if g_resources.fileExists(file) then -- load cfg
|
||||||
return g_resources.readFileContents(file)
|
return g_resources.readFileContents(file)
|
||||||
end
|
end
|
||||||
return context.error("Config " .. file .. " doesn't exist")
|
return context.error("Config " .. file .. " doesn't exist")
|
||||||
end
|
end
|
||||||
|
|
||||||
Config.save = function(dir, name, value)
|
Config.save = function(dir, name, value, forcedExtension)
|
||||||
if not Config.exist(dir) then
|
if not Config.exist(dir) then
|
||||||
if not Config.create(dir) then
|
if not Config.create(dir) then
|
||||||
return contex.error("Can't create config dir: " .. context.configDir .. "/" .. dir)
|
return contex.error("Can't create config dir: " .. context.configDir .. "/" .. dir)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if type(value) ~= 'table' then
|
||||||
|
return context.error("Invalid config value type: " .. type(value) .. ", should be table")
|
||||||
|
end
|
||||||
local file = context.configDir .. "/" .. dir .. "/" .. name
|
local file = context.configDir .. "/" .. dir .. "/" .. name
|
||||||
if type(value) == 'string' then -- cfg
|
if (table.isStringPairList(value) and forcedExtension ~= "json") or forcedExtension == "cfg" then -- cfg
|
||||||
g_resources.writeFileContents(file .. ".cfg", value)
|
g_resources.writeFileContents(file .. ".cfg", table.encodeStringPairList(value))
|
||||||
elseif type(value) == 'table' then -- json
|
else
|
||||||
g_resources.writeFileContents(file .. ".json", json.encode(value))
|
g_resources.writeFileContents(file .. ".json", json.encode(value))
|
||||||
end
|
end
|
||||||
return context.error("Invalid config value type: " .. type(value))
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
Config.remove = function(dir, name)
|
Config.remove = function(dir, name)
|
||||||
local file = context.configDir .. "/" .. dir .. "/" .. name .. ".json"
|
local file = context.configDir .. "/" .. dir .. "/" .. name .. ".json"
|
||||||
|
local ret = false
|
||||||
if g_resources.fileExists(file) then
|
if g_resources.fileExists(file) then
|
||||||
return g_resources.deleteFile(file)
|
g_resources.deleteFile(file)
|
||||||
|
ret = true
|
||||||
end
|
end
|
||||||
file = context.configDir .. "/" .. dir .. "/" .. name .. ".cfg"
|
file = context.configDir .. "/" .. dir .. "/" .. name .. ".cfg"
|
||||||
if g_resources.fileExists(file) then
|
if g_resources.fileExists(file) then
|
||||||
return g_resources.deleteFile(file)
|
g_resources.deleteFile(file)
|
||||||
|
ret = true
|
||||||
end
|
end
|
||||||
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
-- setup is used for BotConfig widget
|
-- setup is used for BotConfig widget
|
||||||
-- not done yet
|
-- not done yet
|
||||||
Config.setup = function(dir, widget, callback)
|
Config.setup = function(dir, widget, configExtension, callback)
|
||||||
local refresh = function()
|
if type(dir) ~= 'string' or dir:len() == 0 then
|
||||||
--
|
return context.error("Invalid config dir")
|
||||||
end
|
end
|
||||||
|
if not Config.exist(dir) and not Config.create(dir) then
|
||||||
|
return context.error("Can't create config dir: " .. dir)
|
||||||
|
end
|
||||||
|
if type(context.storage._configs) ~= "table" then
|
||||||
|
context.storage._configs = {}
|
||||||
|
end
|
||||||
|
if type(context.storage._configs[dir]) ~= "table" then
|
||||||
|
context.storage._configs[dir] = {
|
||||||
|
enabled = false,
|
||||||
|
selected = ""
|
||||||
|
}
|
||||||
|
else
|
||||||
|
widget.switch:setOn(context.storage._configs[dir].enabled)
|
||||||
|
end
|
||||||
|
|
||||||
|
local isRefreshing = false
|
||||||
|
local refresh = function()
|
||||||
|
isRefreshing = true
|
||||||
|
local configs = Config.list(dir)
|
||||||
|
local configIndex = 1
|
||||||
|
widget.list:clear()
|
||||||
|
for v,k in ipairs(configs) do
|
||||||
|
widget.list:addOption(k)
|
||||||
|
if k == context.storage._configs[dir].selected then
|
||||||
|
configIndex = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local data = nil
|
||||||
|
if #configs > 0 then
|
||||||
|
widget.list:setCurrentIndex(configIndex)
|
||||||
|
context.storage._configs[dir].selected = widget.list:getCurrentOption().text
|
||||||
|
data = Config.load(dir, configs[configIndex])
|
||||||
|
else
|
||||||
|
context.storage._configs[dir].selected = nil
|
||||||
|
end
|
||||||
|
context.storage._configs[dir].enabled = widget.switch:isOn()
|
||||||
|
isRefreshing = false
|
||||||
|
callback(context.storage._configs[dir].selected, widget.switch:isOn(), data)
|
||||||
|
end
|
||||||
|
|
||||||
|
widget.list.onOptionChange = function(widget)
|
||||||
|
if not isRefreshing then
|
||||||
|
context.storage._configs[dir].selected = widget:getCurrentOption().text
|
||||||
|
refresh()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
widget.switch.onClick = function()
|
widget.switch.onClick = function()
|
||||||
widget.switch:setOn(not widget.switch:isOn())
|
widget.switch:setOn(not widget.switch:isOn())
|
||||||
|
refresh()
|
||||||
end
|
end
|
||||||
|
|
||||||
widget.add = function()
|
widget.add.onClick = function()
|
||||||
|
context.UI.SinglelineEditorWindow("config_name", function(name)
|
||||||
|
name = name:gsub("%s+", "_")
|
||||||
|
if name:len() == 0 or name:len() >= 30 or name:find("/") or name:find("\\") then
|
||||||
|
return context.error("Invalid config name")
|
||||||
|
end
|
||||||
|
local file = context.configDir .. "/" .. dir .. "/" .. name .. "." .. configExtension
|
||||||
|
if g_resources.fileExists(file) then
|
||||||
|
return context.error("Config " .. name .. " already exist")
|
||||||
|
end
|
||||||
|
g_resources.writeFileContents(file, "")
|
||||||
|
context.storage._configs[dir].selected = name
|
||||||
|
widget.switch:setOn(false)
|
||||||
|
refresh()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
widget.edit = function()
|
widget.edit.onClick = function()
|
||||||
|
local name = context.storage._configs[dir].selected
|
||||||
|
if not name then return end
|
||||||
|
context.UI.MultilineEditorWindow("Config editor - " .. name .. " in " .. dir,
|
||||||
|
Config.loadRaw(dir, name), function(newValue)
|
||||||
|
local data = Config.parse(newValue)
|
||||||
|
Config.save(dir, name, data, configExtension)
|
||||||
|
refresh()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
widget.remove = function()
|
widget.remove.onClick = function()
|
||||||
|
local name = context.storage._configs[dir].selected
|
||||||
|
if not name then return end
|
||||||
|
context.UI.ConfirmationWindow("Config removal", "Do you want to remove config " .. name .. " from " .. dir .. "?", function()
|
||||||
|
Config.remove(dir, name)
|
||||||
|
widget.switch:setOn(false)
|
||||||
|
refresh()
|
||||||
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--local configs = Config.list(dir)
|
refresh()
|
||||||
--widget.list.
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isOn = function()
|
isOn = function()
|
||||||
@ -96,18 +212,35 @@ Config.setup = function(dir, widget, callback)
|
|||||||
isOff = function()
|
isOff = function()
|
||||||
return not widget.switch:isOn()
|
return not widget.switch:isOn()
|
||||||
end,
|
end,
|
||||||
enable = function()
|
setOn = function(val)
|
||||||
|
if val == false then
|
||||||
|
if widget.switch:isOn() then
|
||||||
|
widget.switch:onClick()
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
if not widget.switch:isOn() then
|
if not widget.switch:isOn() then
|
||||||
widget.switch:onClick()
|
widget.switch:onClick()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
disable = function()
|
setOff = function(val)
|
||||||
|
if val == false then
|
||||||
|
if not widget.switch:isOn() then
|
||||||
|
widget.switch:onClick()
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
if widget.switch:isOn() then
|
if widget.switch:isOn() then
|
||||||
widget.switch:onClick()
|
widget.switch:onClick()
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
save = function()
|
save = function(data)
|
||||||
|
Config.save(dir, context.storage._configs[dir].selected, data, configExtension)
|
||||||
end
|
end,
|
||||||
|
refresh = refresh,
|
||||||
|
reload = refresh,
|
||||||
|
getActiveConfigName = function()
|
||||||
|
return context.storage._configs[dir].selected
|
||||||
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
@ -31,6 +31,7 @@ context.addIcon = function(id, options, callback)
|
|||||||
local config = context.storage._icons[id]
|
local config = context.storage._icons[id]
|
||||||
local widget = g_ui.createWidget("BotIcon", panel)
|
local widget = g_ui.createWidget("BotIcon", panel)
|
||||||
widget.botWidget = true
|
widget.botWidget = true
|
||||||
|
widget.botIcon = true
|
||||||
|
|
||||||
if type(config.x) ~= 'number' and type(config.y) ~= 'number' then
|
if type(config.x) ~= 'number' and type(config.y) ~= 'number' then
|
||||||
if type(options.x) == 'number' and type(options.y) == 'number' then
|
if type(options.x) == 'number' and type(options.y) == 'number' then
|
||||||
@ -138,22 +139,22 @@ context.addIcon = function(id, options, callback)
|
|||||||
|
|
||||||
config.x = math.min(1, math.max(0, x / width))
|
config.x = math.min(1, math.max(0, x / width))
|
||||||
config.y = math.min(1, math.max(0, y / height))
|
config.y = math.min(1, math.max(0, y / height))
|
||||||
|
|
||||||
widget:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter)
|
widget:addAnchor(AnchorHorizontalCenter, 'parent', AnchorHorizontalCenter)
|
||||||
widget:addAnchor(AnchorVerticalCenter, 'parent', AnchorVerticalCenter)
|
widget:addAnchor(AnchorVerticalCenter, 'parent', AnchorVerticalCenter)
|
||||||
|
widget:setMarginTop(math.max(height * (-0.5) - parent:getMarginTop(), height * (-0.5 + config.y)))
|
||||||
widget:setMarginTop(height * (-0.5 + config.y))
|
|
||||||
widget:setMarginLeft(width * (-0.5 + config.x))
|
widget:setMarginLeft(width * (-0.5 + config.x))
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
widget.onGeometryChange = function(widget, oldRect, newRect)
|
widget.onGeometryChange = function(widget)
|
||||||
if widget:isDragging() then return end
|
if widget:isDragging() then return end
|
||||||
local parent = widget:getParent()
|
local parent = widget:getParent()
|
||||||
local parentRect = parent:getRect()
|
local parentRect = parent:getRect()
|
||||||
local width = parentRect.width - widget:getWidth()
|
local width = parentRect.width - widget:getWidth()
|
||||||
local height = parentRect.height - widget:getHeight()
|
local height = parentRect.height - widget:getHeight()
|
||||||
widget:setMarginTop(-parent:getMarginTop() + height * (-0.5 + config.y))
|
widget:setMarginTop(math.max(height * (-0.5) - parent:getMarginTop(), height * (-0.5 + config.y)))
|
||||||
widget:setMarginLeft(width * (-0.5 + config.x))
|
widget:setMarginLeft(width * (-0.5 + config.x))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -183,7 +183,13 @@ context.findPath = function(startPos, destPos, maxDist, params)
|
|||||||
end
|
end
|
||||||
context.getPath = context.findPath
|
context.getPath = context.findPath
|
||||||
|
|
||||||
|
-- also works as autoWalk(dirs) where dirs is a list eg.: {1,2,3,0,1,1,2,}
|
||||||
context.autoWalk = function(destination, maxDist, params)
|
context.autoWalk = function(destination, maxDist, params)
|
||||||
|
if type(destination) == "table" and table.isList(destination) and not maxDist and not params then
|
||||||
|
g_game.autoWalk(destination, {x=0,y=0,z=0})
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- Available params same as for findPath
|
-- Available params same as for findPath
|
||||||
local path = context.findPath(context.player:getPosition(), destination, maxDist, params)
|
local path = context.findPath(context.player:getPosition(), destination, maxDist, params)
|
||||||
if not path then
|
if not path then
|
||||||
|
@ -1,114 +1,12 @@
|
|||||||
local context = G.botContext
|
local context = G.botContext
|
||||||
|
if type(context.UI) ~= "table" then
|
||||||
|
context.UI = {}
|
||||||
|
end
|
||||||
|
local UI = context.UI
|
||||||
|
|
||||||
context.setupUI = function(otml, parent)
|
UI.createWidget = function(name, parent)
|
||||||
if parent == nil then
|
if parent == nil then
|
||||||
parent = context.panel
|
parent = context.panel
|
||||||
end
|
end
|
||||||
local widget = g_ui.loadUIFromString(otml, parent)
|
return g_ui.createWidget(name, parent)
|
||||||
widget.botWidget = true
|
|
||||||
return widget
|
|
||||||
end
|
end
|
||||||
|
|
||||||
context.importStyle = function(otml)
|
|
||||||
return g_ui.importStyleFromString(otml)
|
|
||||||
end
|
|
||||||
|
|
||||||
context.addTab = function(name)
|
|
||||||
local tab = context.tabs:getTab(name)
|
|
||||||
if tab then -- return existing tab
|
|
||||||
return tab.tabPanel.content
|
|
||||||
end
|
|
||||||
|
|
||||||
context.tabs:setOn(true)
|
|
||||||
local newTab = context.tabs:addTab(name, g_ui.createWidget('BotPanel')).tabPanel.content
|
|
||||||
if #(context.tabs.tabs) > 5 then
|
|
||||||
for k,tab in pairs(context.tabs.tabs) do
|
|
||||||
tab:setPadding(3)
|
|
||||||
tab:setFont('small-9px')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return newTab
|
|
||||||
end
|
|
||||||
context.getTab = context.addTab
|
|
||||||
|
|
||||||
context.addSwitch = function(id, text, onClickCallback, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local switch = g_ui.createWidget('BotSwitch', parent)
|
|
||||||
switch:setId(id)
|
|
||||||
switch:setText(text)
|
|
||||||
switch.onClick = onClickCallback
|
|
||||||
return switch
|
|
||||||
end
|
|
||||||
|
|
||||||
context.addButton = function(id, text, onClickCallback, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local button = g_ui.createWidget('BotButton', parent)
|
|
||||||
button:setId(id)
|
|
||||||
button:setText(text)
|
|
||||||
button.onClick = onClickCallback
|
|
||||||
return button
|
|
||||||
end
|
|
||||||
|
|
||||||
context.addLabel = function(id, text, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local label = g_ui.createWidget('BotLabel', parent)
|
|
||||||
label:setId(id)
|
|
||||||
label:setText(text)
|
|
||||||
return label
|
|
||||||
end
|
|
||||||
|
|
||||||
context.addTextEdit = function(id, text, onTextChangeCallback, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local widget = g_ui.createWidget('BotTextEdit', parent)
|
|
||||||
widget:setId(id)
|
|
||||||
widget.onTextChange = onTextChangeCallback
|
|
||||||
widget:setText(text)
|
|
||||||
return widget
|
|
||||||
end
|
|
||||||
|
|
||||||
context.addSeparator = function(id, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local separator = g_ui.createWidget('BotSeparator', parent)
|
|
||||||
separator:setId(id)
|
|
||||||
return separator
|
|
||||||
end
|
|
||||||
|
|
||||||
context._addMacroSwitch = function(name, keys, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local text = name
|
|
||||||
if keys:len() > 0 then
|
|
||||||
text = name .. " [" .. keys .. "]"
|
|
||||||
end
|
|
||||||
local switch = context.addSwitch("macro_" .. #context._macros, text, function(widget)
|
|
||||||
context.storage._macros[name] = not context.storage._macros[name]
|
|
||||||
widget:setOn(context.storage._macros[name])
|
|
||||||
end, parent)
|
|
||||||
switch:setOn(context.storage._macros[name])
|
|
||||||
return switch
|
|
||||||
end
|
|
||||||
|
|
||||||
context._addHotkeySwitch = function(name, keys, parent)
|
|
||||||
if not parent then
|
|
||||||
parent = context.panel
|
|
||||||
end
|
|
||||||
local text = name
|
|
||||||
if keys:len() > 0 then
|
|
||||||
text = name .. " [" .. keys .. "]"
|
|
||||||
end
|
|
||||||
local switch = context.addSwitch("hotkey_" .. #context._hotkeys, text, nil, parent)
|
|
||||||
switch:setOn(false)
|
|
||||||
return switch
|
|
||||||
end
|
|
81
modules/game_bot/functions/ui_elements.lua
Normal file
81
modules/game_bot/functions/ui_elements.lua
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
local context = G.botContext
|
||||||
|
if type(context.UI) ~= "table" then
|
||||||
|
context.UI = {}
|
||||||
|
end
|
||||||
|
local UI = context.UI
|
||||||
|
|
||||||
|
UI.Config = function(parent)
|
||||||
|
return UI.createWidget("BotConfig", parent)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- call :setItems(table) to set items, call :getItems() to get them
|
||||||
|
-- unique if true, won't allow duplicates
|
||||||
|
-- callback (can be nil) gets table with new item list, eg: {{id=2160, count=1}, {id=268, count=100}, {id=269, count=20}}
|
||||||
|
UI.Container = function(callback, unique, parent)
|
||||||
|
local widget = UI.createWidget("BotContainer", parent)
|
||||||
|
local oldItems = {}
|
||||||
|
|
||||||
|
local updateItems = function()
|
||||||
|
local items = widget:getItems()
|
||||||
|
widget:setItems(items)
|
||||||
|
|
||||||
|
-- callback part
|
||||||
|
if not callback then return end
|
||||||
|
local somethingNew = false
|
||||||
|
for i, item in ipairs(items) do
|
||||||
|
if type(oldItems[i]) ~= "table" then
|
||||||
|
somethingNew = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if oldItems[i].id ~= item.id or oldItems[i].count ~= item.count then
|
||||||
|
somethingNew = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if somethingNew then
|
||||||
|
oldItems = items
|
||||||
|
callback(items)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
widget.setItems = function(self, items)
|
||||||
|
if type(self) == 'table' then
|
||||||
|
items = self
|
||||||
|
end
|
||||||
|
local itemsToShow = math.max(10, #items + 2)
|
||||||
|
if itemsToShow % 5 ~= 0 then
|
||||||
|
itemsToShow = itemsToShow + 5 - itemsToShow % 5
|
||||||
|
end
|
||||||
|
widget.items:destroyChildren()
|
||||||
|
for i = 1, itemsToShow do
|
||||||
|
local widget = g_ui.createWidget("BotItem", widget.items)
|
||||||
|
if type(items[i]) == 'number' then
|
||||||
|
items[i] = {id=items[i], count=1}
|
||||||
|
end
|
||||||
|
if type(items[i]) == 'table' then
|
||||||
|
widget:setItem(Item.create(items[i].id, items[i].count))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
oldItems = items
|
||||||
|
for i, child in ipairs(widget.items:getChildren()) do
|
||||||
|
child.onItemChange = updateItems
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
widget.getItems = function()
|
||||||
|
local items = {}
|
||||||
|
local duplicates = {}
|
||||||
|
for i, child in ipairs(widget.items:getChildren()) do
|
||||||
|
if child:getItemId() >= 100 then
|
||||||
|
if not duplicates[child:getItemId()] or not unique then
|
||||||
|
table.insert(items, {id=child:getItemId(), count=child:getItemCount()})
|
||||||
|
duplicates[child:getItemId()] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
|
return widget
|
||||||
|
end
|
||||||
|
|
132
modules/game_bot/functions/ui_legacy.lua
Normal file
132
modules/game_bot/functions/ui_legacy.lua
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
local context = G.botContext
|
||||||
|
|
||||||
|
context.createWidget = function(name, parent)
|
||||||
|
if parent == nil then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
g_ui.createWidget(name, parent)
|
||||||
|
end
|
||||||
|
|
||||||
|
context.setupUI = function(otml, parent)
|
||||||
|
if parent == nil then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local widget = g_ui.loadUIFromString(otml, parent)
|
||||||
|
widget.botWidget = true
|
||||||
|
return widget
|
||||||
|
end
|
||||||
|
|
||||||
|
context.importStyle = function(otml)
|
||||||
|
if type(otml) ~= "string" then
|
||||||
|
return error("Invalid parameter for importStyle, should be string")
|
||||||
|
end
|
||||||
|
if otml:find(".otui") and not otml:find("\n") then
|
||||||
|
return g_ui.importStyle(context.configDir .. "/" .. otml)
|
||||||
|
end
|
||||||
|
return g_ui.importStyleFromString(otml)
|
||||||
|
end
|
||||||
|
|
||||||
|
context.addTab = function(name)
|
||||||
|
local tab = context.tabs:getTab(name)
|
||||||
|
if tab then -- return existing tab
|
||||||
|
return tab.tabPanel.content
|
||||||
|
end
|
||||||
|
|
||||||
|
context.tabs:setOn(true)
|
||||||
|
local newTab = context.tabs:addTab(name, g_ui.createWidget('BotPanel')).tabPanel.content
|
||||||
|
if #(context.tabs.tabs) > 5 then
|
||||||
|
for k,tab in pairs(context.tabs.tabs) do
|
||||||
|
tab:setPadding(3)
|
||||||
|
tab:setFont('small-9px')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return newTab
|
||||||
|
end
|
||||||
|
context.getTab = context.addTab
|
||||||
|
|
||||||
|
context.setDefaultTab = function(name)
|
||||||
|
local tab = context.addTab(name)
|
||||||
|
context.panel = tab
|
||||||
|
end
|
||||||
|
|
||||||
|
context.addSwitch = function(id, text, onClickCallback, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local switch = g_ui.createWidget('BotSwitch', parent)
|
||||||
|
switch:setId(id)
|
||||||
|
switch:setText(text)
|
||||||
|
switch.onClick = onClickCallback
|
||||||
|
return switch
|
||||||
|
end
|
||||||
|
|
||||||
|
context.addButton = function(id, text, onClickCallback, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local button = g_ui.createWidget('BotButton', parent)
|
||||||
|
button:setId(id)
|
||||||
|
button:setText(text)
|
||||||
|
button.onClick = onClickCallback
|
||||||
|
return button
|
||||||
|
end
|
||||||
|
|
||||||
|
context.addLabel = function(id, text, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local label = g_ui.createWidget('BotLabel', parent)
|
||||||
|
label:setId(id)
|
||||||
|
label:setText(text)
|
||||||
|
return label
|
||||||
|
end
|
||||||
|
|
||||||
|
context.addTextEdit = function(id, text, onTextChangeCallback, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local widget = g_ui.createWidget('BotTextEdit', parent)
|
||||||
|
widget:setId(id)
|
||||||
|
widget.onTextChange = onTextChangeCallback
|
||||||
|
widget:setText(text)
|
||||||
|
return widget
|
||||||
|
end
|
||||||
|
|
||||||
|
context.addSeparator = function(id, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local separator = g_ui.createWidget('BotSeparator', parent)
|
||||||
|
separator:setId(id)
|
||||||
|
return separator
|
||||||
|
end
|
||||||
|
|
||||||
|
context._addMacroSwitch = function(name, keys, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local text = name
|
||||||
|
if keys:len() > 0 then
|
||||||
|
text = name .. " [" .. keys .. "]"
|
||||||
|
end
|
||||||
|
local switch = context.addSwitch("macro_" .. #context._macros, text, function(widget)
|
||||||
|
context.storage._macros[name] = not context.storage._macros[name]
|
||||||
|
widget:setOn(context.storage._macros[name])
|
||||||
|
end, parent)
|
||||||
|
switch:setOn(context.storage._macros[name])
|
||||||
|
return switch
|
||||||
|
end
|
||||||
|
|
||||||
|
context._addHotkeySwitch = function(name, keys, parent)
|
||||||
|
if not parent then
|
||||||
|
parent = context.panel
|
||||||
|
end
|
||||||
|
local text = name
|
||||||
|
if keys:len() > 0 then
|
||||||
|
text = name .. " [" .. keys .. "]"
|
||||||
|
end
|
||||||
|
local switch = context.addSwitch("hotkey_" .. #context._hotkeys, text, nil, parent)
|
||||||
|
switch:setOn(false)
|
||||||
|
return switch
|
||||||
|
end
|
30
modules/game_bot/functions/ui_windows.lua
Normal file
30
modules/game_bot/functions/ui_windows.lua
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
local context = G.botContext
|
||||||
|
if type(context.UI) ~= "table" then
|
||||||
|
context.UI = {}
|
||||||
|
end
|
||||||
|
local UI = context.UI
|
||||||
|
|
||||||
|
UI.SinglelineEditorWindow = function(text, callback)
|
||||||
|
return modules.game_textedit.singlelineEditor(text, callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.MultilineEditorWindow = function(description, test, callback)
|
||||||
|
return modules.game_textedit.multilineEditor(description, test, callback)
|
||||||
|
end
|
||||||
|
|
||||||
|
UI.ConfirmationWindow = function(title, question, callback)
|
||||||
|
local window = nil
|
||||||
|
local onConfirm = function()
|
||||||
|
window:destroy()
|
||||||
|
callback()
|
||||||
|
end
|
||||||
|
local closeWindow = function()
|
||||||
|
window:destroy()
|
||||||
|
end
|
||||||
|
window = context.displayGeneralBox(title, question, {
|
||||||
|
{ text=tr('Yes'), callback=onConfirm },
|
||||||
|
{ text=tr('No'), callback=closeWindow },
|
||||||
|
anchor=AnchorHorizontalCenter}, onConfirm, closeWindow)
|
||||||
|
window.botWidget = true
|
||||||
|
return window
|
||||||
|
end
|
@ -1,8 +1,6 @@
|
|||||||
BotConfig < Panel
|
BotConfig < Panel
|
||||||
anchors.top: parent.top
|
id: botConfig
|
||||||
anchors.left: parent.left
|
height: 45
|
||||||
anchors.right: parent.right
|
|
||||||
height: 40
|
|
||||||
|
|
||||||
ComboBox
|
ComboBox
|
||||||
id: list
|
id: list
|
||||||
@ -31,21 +29,21 @@ BotConfig < Panel
|
|||||||
anchors.top: prev.bottom
|
anchors.top: prev.bottom
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
text: Add
|
text: Add
|
||||||
width: 58
|
width: 59
|
||||||
height: 17
|
height: 20
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: edit
|
id: edit
|
||||||
anchors.top: prev.top
|
anchors.top: prev.top
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
text: Edit
|
text: Edit
|
||||||
width: 58
|
width: 59
|
||||||
height: 17
|
height: 20
|
||||||
|
|
||||||
Button
|
Button
|
||||||
id: remove
|
id: remove
|
||||||
anchors.top: prev.top
|
anchors.top: prev.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
text: Remove
|
text: Remove
|
||||||
width: 58
|
width: 59
|
||||||
height: 17
|
height: 20
|
19
modules/game_bot/ui/container.otui
Normal file
19
modules/game_bot/ui/container.otui
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
BotContainer < Panel
|
||||||
|
height: 68
|
||||||
|
|
||||||
|
ScrollablePanel
|
||||||
|
id: items
|
||||||
|
anchors.fill: parent
|
||||||
|
vertical-scrollbar: scroll
|
||||||
|
layout:
|
||||||
|
type: grid
|
||||||
|
cell-size: 34 34
|
||||||
|
flow: true
|
||||||
|
|
||||||
|
BotSmallScrollBar
|
||||||
|
id: scroll
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.bottom: prev.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
step: 10
|
||||||
|
pixels-scroll: true
|
@ -8,6 +8,9 @@ end
|
|||||||
|
|
||||||
function updateFeatures(version)
|
function updateFeatures(version)
|
||||||
g_game.resetFeatures()
|
g_game.resetFeatures()
|
||||||
|
if version <= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- you can add custom features here, list of them is in the modules\gamelib\const.lua
|
-- you can add custom features here, list of them is in the modules\gamelib\const.lua
|
||||||
g_game.enableFeature(GameBot)
|
g_game.enableFeature(GameBot)
|
||||||
|
39
modules/game_imbuement/imbuement.lua
Normal file
39
modules/game_imbuement/imbuement.lua
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
function init()
|
||||||
|
connect(g_game, {
|
||||||
|
onImbuementWindow = onImbuementWindow,
|
||||||
|
onCloseImbuementWindow = onCloseImbuementWindow
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function terminate()
|
||||||
|
disconnect(g_game, {
|
||||||
|
onImbuementWindow = onImbuementWindow,
|
||||||
|
onCloseImbuementWindow = onCloseImbuementWindow
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function onImbuementWindow(itemId, slots, activeSlots, imbuements, needItems)
|
||||||
|
print("window " .. slots)
|
||||||
|
for i, slot in pairs(activeSlots) do
|
||||||
|
local duration = slot.duration
|
||||||
|
local removalCost = slot.removalCost
|
||||||
|
local imbuement = slot.imbuement
|
||||||
|
for i, source in pairs(imbuement.sources) do
|
||||||
|
print(source.description, source.item:getId(), source.item:getCount())
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
for i, imbuement in ipairs(imbuements) do
|
||||||
|
for i, source in pairs(imbuement.sources) do
|
||||||
|
print(source.description, source.item:getId(), source.item:getCount())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i, item in ipairs(needItems) do
|
||||||
|
print(item:getId(), item:getCount())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function onCloseImbuementWindow()
|
||||||
|
print("close")
|
||||||
|
end
|
9
modules/game_imbuement/imbuement.otmod
Normal file
9
modules/game_imbuement/imbuement.otmod
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Module
|
||||||
|
name: game_imbuement
|
||||||
|
description: Imbuement
|
||||||
|
author: otclient.ovh
|
||||||
|
website: http://otclient.ovh
|
||||||
|
sandboxed: true
|
||||||
|
scripts: [ imbuement ]
|
||||||
|
@onLoad: init()
|
||||||
|
@onUnload: terminate()
|
199
modules/game_imbuement/imbuement.otui
Normal file
199
modules/game_imbuement/imbuement.otui
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
PreySelectionLabel < Label
|
||||||
|
font: verdana-11px-monochrome
|
||||||
|
background-color: alpha
|
||||||
|
text-offset: 34 0
|
||||||
|
margin-right: 5
|
||||||
|
text-align: center
|
||||||
|
text-wrap: true
|
||||||
|
focusable: true
|
||||||
|
height: 34
|
||||||
|
|
||||||
|
$focus:
|
||||||
|
background-color: #00000055
|
||||||
|
color: #ffffff
|
||||||
|
|
||||||
|
UICreature
|
||||||
|
id: creature
|
||||||
|
size: 32 32
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
margin-top: 1
|
||||||
|
|
||||||
|
PreySlot < Panel
|
||||||
|
width: 190
|
||||||
|
height: 280
|
||||||
|
border: 1 black
|
||||||
|
padding: 5
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: title
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
text-align: center
|
||||||
|
!text: tr("Prey Inactive")
|
||||||
|
|
||||||
|
TextList
|
||||||
|
id: list
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-top: 15
|
||||||
|
margin-right: 10
|
||||||
|
vertical-scrollbar: listScrollbar
|
||||||
|
height: 150
|
||||||
|
visible: false
|
||||||
|
focusable: false
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: listScrollbar
|
||||||
|
anchors.top: prev.top
|
||||||
|
anchors.bottom: prev.bottom
|
||||||
|
anchors.right: parent.right
|
||||||
|
pixels-scroll: true
|
||||||
|
visible: false
|
||||||
|
step: 10
|
||||||
|
|
||||||
|
UICreature
|
||||||
|
id: creature
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.horizontalCenter: parent.horizontalCenter
|
||||||
|
margin-top: 40
|
||||||
|
height: 64
|
||||||
|
width: 64
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: description
|
||||||
|
margin-top: 30
|
||||||
|
margin-left: 5
|
||||||
|
margin-right: 5
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
text-auto-resize: true
|
||||||
|
text-align: center
|
||||||
|
text-wrap: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: bonuses
|
||||||
|
margin-top: 5
|
||||||
|
margin-left: 5
|
||||||
|
margin-right: 5
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
text-auto-resize: true
|
||||||
|
text-align: center
|
||||||
|
text-wrap: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: button
|
||||||
|
margin-top: 5
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-left: 10
|
||||||
|
margin-right: 10
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: bottomLabel
|
||||||
|
margin-left: 5
|
||||||
|
margin-right: 5
|
||||||
|
margin-bottom: 5
|
||||||
|
anchors.bottom: next.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
text-auto-resize: true
|
||||||
|
text-align: center
|
||||||
|
text-wrap: true
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: bottomButton
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-left: 10
|
||||||
|
margin-right: 10
|
||||||
|
text: 11
|
||||||
|
visible: false
|
||||||
|
|
||||||
|
$hidden:
|
||||||
|
height: 0
|
||||||
|
|
||||||
|
$!hidden:
|
||||||
|
height: 22
|
||||||
|
|
||||||
|
MainWindow
|
||||||
|
id: preyWindow
|
||||||
|
!text: tr('Preys')
|
||||||
|
size: 600 405
|
||||||
|
background-color: #AAAAAA
|
||||||
|
@onEscape: modules.game_prey.hide()
|
||||||
|
|
||||||
|
PreySlot
|
||||||
|
id: slot1
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.top: parent.top
|
||||||
|
|
||||||
|
PreySlot
|
||||||
|
id: slot2
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.top: prev.top
|
||||||
|
|
||||||
|
PreySlot
|
||||||
|
id: slot3
|
||||||
|
anchors.left: prev.right
|
||||||
|
anchors.top: prev.top
|
||||||
|
|
||||||
|
HorizontalSeparator
|
||||||
|
id: mainSeparator
|
||||||
|
anchors.top: slot3.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-top: 5
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: rerollPrice
|
||||||
|
anchors.top: mainSeparator.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
margin-top: 5
|
||||||
|
width: 190
|
||||||
|
height: 30
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: balance
|
||||||
|
anchors.top: mainSeparator.bottom
|
||||||
|
anchors.left: prev.right
|
||||||
|
margin-top: 5
|
||||||
|
width: 190
|
||||||
|
height: 30
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
Label
|
||||||
|
id: bonusRerolls
|
||||||
|
anchors.top: mainSeparator.bottom
|
||||||
|
anchors.left: prev.right
|
||||||
|
margin-top: 5
|
||||||
|
width: 190
|
||||||
|
height: 30
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
HorizontalSeparator
|
||||||
|
anchors.bottom: buttonCancel.top
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-bottom: 5
|
||||||
|
|
||||||
|
Button
|
||||||
|
id: buttonCancel
|
||||||
|
!text: tr('Close')
|
||||||
|
width: 64
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
@onClick: modules.game_prey.hide()
|
@ -414,6 +414,12 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
|||||||
if useThing:isRotateable() then
|
if useThing:isRotateable() then
|
||||||
menu:addOption(tr('Rotate'), function() g_game.rotate(useThing) end)
|
menu:addOption(tr('Rotate'), function() g_game.rotate(useThing) end)
|
||||||
end
|
end
|
||||||
|
if useThing:isWrapable() then
|
||||||
|
menu:addOption(tr('Wrap'), function() g_game.wrap(useThing) end)
|
||||||
|
end
|
||||||
|
if useThing:isUnwrapable() then
|
||||||
|
menu:addOption(tr('Unwrap'), function() g_game.wrap(useThing) end)
|
||||||
|
end
|
||||||
|
|
||||||
if g_game.getFeature(GameBrowseField) and useThing:getPosition().x ~= 0xffff then
|
if g_game.getFeature(GameBrowseField) and useThing:getPosition().x ~= 0xffff then
|
||||||
menu:addOption(tr('Browse Field'), function() g_game.browseField(useThing:getPosition()) end)
|
menu:addOption(tr('Browse Field'), function() g_game.browseField(useThing:getPosition()) end)
|
||||||
@ -832,10 +838,7 @@ function refreshViewMode()
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local minimumWidth = (g_settings.getNumber("rightPanels") + g_settings.getNumber("leftPanels") - 1) * 200
|
local minimumWidth = (g_settings.getNumber("rightPanels") + g_settings.getNumber("leftPanels") - 1) * 200 + 300
|
||||||
if classic then
|
|
||||||
minimumWidth = minimumWidth + 400
|
|
||||||
end
|
|
||||||
minimumWidth = math.max(minimumWidth, 800)
|
minimumWidth = math.max(minimumWidth, 800)
|
||||||
g_window.setMinimumSize({ width = minimumWidth, height = 600 })
|
g_window.setMinimumSize({ width = minimumWidth, height = 600 })
|
||||||
if g_window.getWidth() < minimumWidth then
|
if g_window.getWidth() < minimumWidth then
|
||||||
@ -900,7 +903,7 @@ function refreshViewMode()
|
|||||||
gameRootPanel:fill('parent')
|
gameRootPanel:fill('parent')
|
||||||
gameMapPanel:setKeepAspectRatio(false)
|
gameMapPanel:setKeepAspectRatio(false)
|
||||||
gameMapPanel:setLimitVisibleRange(false)
|
gameMapPanel:setLimitVisibleRange(false)
|
||||||
gameMapPanel:setZoom(14)
|
gameMapPanel:setZoom(15)
|
||||||
|
|
||||||
modules.client_topmenu.getTopMenu():setImageColor('#ffffff66')
|
modules.client_topmenu.getTopMenu():setImageColor('#ffffff66')
|
||||||
|
|
||||||
@ -939,10 +942,10 @@ function updateSize()
|
|||||||
local dwidth = dimenstion.width
|
local dwidth = dimenstion.width
|
||||||
local tileSize = rheight / dheight
|
local tileSize = rheight / dheight
|
||||||
local maxWidth = tileSize * (awareRange.width + 1)
|
local maxWidth = tileSize * (awareRange.width + 1)
|
||||||
if g_game.getFeature(GameChangeMapAwareRange) then
|
if g_game.getFeature(GameChangeMapAwareRange) and g_game.getFeature(GameNewWalking) then
|
||||||
local maxWidth = tileSize * (awareRange.width - 1)
|
maxWidth = tileSize * (awareRange.width - 1)
|
||||||
end
|
end
|
||||||
gameMapPanel:setMarginTop(-tileSize * 2)
|
gameMapPanel:setMarginTop(-tileSize)
|
||||||
if g_settings.getBoolean("cacheMap") then
|
if g_settings.getBoolean("cacheMap") then
|
||||||
gameMapPanel:setMarginLeft(0)
|
gameMapPanel:setMarginLeft(0)
|
||||||
gameMapPanel:setMarginRight(0)
|
gameMapPanel:setMarginRight(0)
|
||||||
@ -956,6 +959,13 @@ function updateSize()
|
|||||||
modules.game_textmessage.messagesPanel:setMarginTop(-gameMapPanel:getMarginTop())
|
modules.game_textmessage.messagesPanel:setMarginTop(-gameMapPanel:getMarginTop())
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if modules.game_bot then
|
||||||
|
for i, child in ipairs(gameMapPanel:getChildren()) do
|
||||||
|
if child.botIcon and child.onGeometryChange then
|
||||||
|
child.onGeometryChange(child)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
|
@ -36,6 +36,7 @@ Module
|
|||||||
- game_textedit
|
- game_textedit
|
||||||
- game_actionbar
|
- game_actionbar
|
||||||
- game_prey
|
- game_prey
|
||||||
|
- game_imbuement
|
||||||
- game_bot
|
- game_bot
|
||||||
@onLoad: init()
|
@onLoad: init()
|
||||||
@onUnload: terminate()
|
@onUnload: terminate()
|
||||||
|
@ -35,8 +35,7 @@ function show(itemWidget)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local doneFunc = function()
|
local doneFunc = function()
|
||||||
itemWidget:setItemId(window.item:getItemId())
|
itemWidget:setItem(Item.create(window.item:getItemId(), window.item:getItemCount()))
|
||||||
itemWidget:setItemCount(window.item:getItemCount())
|
|
||||||
destroy()
|
destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -45,8 +44,7 @@ function show(itemWidget)
|
|||||||
window.onEnter = doneFunc
|
window.onEnter = doneFunc
|
||||||
window.onEscape = destroy
|
window.onEscape = destroy
|
||||||
|
|
||||||
window.item:setItemId(itemWidget:getItemId())
|
window.item:setItem(Item.create(itemWidget:getItemId(), itemWidget:getItemCount()))
|
||||||
window.item:setItemCount(itemWidget:getItemCount())
|
|
||||||
|
|
||||||
window.itemId:setValue(itemWidget:getItemId())
|
window.itemId:setValue(itemWidget:getItemId())
|
||||||
if itemWidget:getItemCount() > 1 then
|
if itemWidget:getItemCount() > 1 then
|
||||||
|
@ -18,6 +18,7 @@ MainWindow
|
|||||||
margin-top: 15
|
margin-top: 15
|
||||||
margin-left: 22
|
margin-left: 22
|
||||||
padding: 4 4 4 4
|
padding: 4 4 4 4
|
||||||
|
size: 96 96
|
||||||
fixed-creature-size: true
|
fixed-creature-size: true
|
||||||
|
|
||||||
Label
|
Label
|
||||||
@ -44,13 +45,14 @@ MainWindow
|
|||||||
enabled: true
|
enabled: true
|
||||||
@onClick: modules.game_outfit.previousOutfitType()
|
@onClick: modules.game_outfit.previousOutfitType()
|
||||||
|
|
||||||
Creature
|
Creature
|
||||||
id: mountCreatureBox
|
id: mountCreatureBox
|
||||||
anchors.top: parent.top
|
anchors.top: parent.top
|
||||||
anchors.right: parent.right
|
anchors.right: parent.right
|
||||||
margin-top: 15
|
margin-top: 15
|
||||||
margin-right: 22
|
margin-right: 22
|
||||||
padding: 4 4 4 4
|
padding: 4 4 4 4
|
||||||
|
size: 96 96
|
||||||
fixed-creature-size: true
|
fixed-creature-size: true
|
||||||
|
|
||||||
Label
|
Label
|
||||||
|
@ -317,6 +317,11 @@ function processMessage(data)
|
|||||||
local title = tr(data["title"])
|
local title = tr(data["title"])
|
||||||
local msg = data["msg"]
|
local msg = data["msg"]
|
||||||
msgWindow = displayInfoBox(title, msg)
|
msgWindow = displayInfoBox(title, msg)
|
||||||
|
msgWindow.onDestroy = function(widget)
|
||||||
|
if widget == msgWindow then
|
||||||
|
msgWindow = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
msgWindow:show()
|
msgWindow:show()
|
||||||
msgWindow:raise()
|
msgWindow:raise()
|
||||||
msgWindow:focus()
|
msgWindow:focus()
|
||||||
|
@ -165,6 +165,8 @@ GameMinimapLimitedToSingleFloor = 81
|
|||||||
GameDoubleLevel = 83
|
GameDoubleLevel = 83
|
||||||
GameDoubleSoul = 84
|
GameDoubleSoul = 84
|
||||||
GameDoublePlayerGoodsMoney = 85
|
GameDoublePlayerGoodsMoney = 85
|
||||||
|
GameCreatureWalkthrough = 86 -- add Walkthrough for versions less than 854, unpass = msg->getU8(); in protocolgameparse.cpp
|
||||||
|
GameDoubleTradeMoney = 87
|
||||||
|
|
||||||
GameNewWalking = 90
|
GameNewWalking = 90
|
||||||
GameSlowerManualWalking = 91
|
GameSlowerManualWalking = 91
|
||||||
@ -174,9 +176,14 @@ GameBiggerMapCache = 96
|
|||||||
GameForceLight = 97
|
GameForceLight = 97
|
||||||
GameNoDebug = 98
|
GameNoDebug = 98
|
||||||
GameBotProtection = 99
|
GameBotProtection = 99
|
||||||
GameFasterAnimations = 101
|
|
||||||
|
|
||||||
LastGameFeature = 110
|
GameFasterAnimations = 101
|
||||||
|
GameCenteredOutfits = 102
|
||||||
|
|
||||||
|
GamePacketSizeU32 = 110
|
||||||
|
GamePacketCompression = 111
|
||||||
|
|
||||||
|
LastGameFeature = 120
|
||||||
|
|
||||||
TextColors = {
|
TextColors = {
|
||||||
red = '#f55e5e', --'#c83200'
|
red = '#f55e5e', --'#c83200'
|
||||||
|
@ -131,6 +131,10 @@ function ProtocolLogin:sendLoginPacket()
|
|||||||
msg:encryptRsa()
|
msg:encryptRsa()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if g_game.getFeature(GamePacketSizeU32) then
|
||||||
|
self:enableBigPackets()
|
||||||
|
end
|
||||||
|
|
||||||
if g_game.getFeature(GameProtocolChecksum) then
|
if g_game.getFeature(GameProtocolChecksum) then
|
||||||
self:enableChecksum()
|
self:enableChecksum()
|
||||||
end
|
end
|
||||||
|
@ -26,11 +26,7 @@ function UIItem:onDrop(widget, mousePos, forced)
|
|||||||
if not item or not item:isItem() then return false end
|
if not item or not item:isItem() then return false end
|
||||||
|
|
||||||
if self.selectable then
|
if self.selectable then
|
||||||
self:setItemId(item:getId())
|
self:setItem(Item.create(item:getId(), item:getCount()))
|
||||||
self:setItemCount(item:getCount())
|
|
||||||
if item:getSubType() > 1 then
|
|
||||||
self:setItemSubType(item:getSubType())
|
|
||||||
end
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
BIN
otclient_dx.exe
BIN
otclient_dx.exe
Binary file not shown.
BIN
otclient_gl.exe
BIN
otclient_gl.exe
Binary file not shown.
BIN
otclient_linux
BIN
otclient_linux
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user