mirror of
https://github.com/OTCv8/otclientv8.git
synced 2025-04-29 18:59:20 +02:00
Version 2.0 - preys, bot updates, ui improvements
This commit is contained in:
parent
48d7eb810d
commit
6bc4188d7a
@ -22,7 +22,7 @@ It's based on https://github.com/edubart/otclient and it's not backward compatib
|
||||
- Refreshed interface
|
||||
- New crash and error handler
|
||||
- New HTTP login protocol
|
||||
- Ingame shop and news
|
||||
- Ingame shop
|
||||
- Updated hotkey manager
|
||||
- Updated and optimized battle list
|
||||
- Crosshair, floor fading, extra health/mana bars and panels
|
||||
@ -30,6 +30,7 @@ It's based on https://github.com/edubart/otclient and it's not backward compatib
|
||||
- Removed a lot of useless and outdated things
|
||||
- Advanced bot (https://github.com/OTCv8/otclientv8_bot)
|
||||
- Linux version
|
||||
- Tibia 11.00 support (preys)
|
||||
- Support for proxies to lower latency and protect against DDoS (extra paid option)
|
||||
- Bot protection (extra paid option)
|
||||
- [Soon] Mobile application for quick authorization
|
||||
|
@ -1,11 +1,14 @@
|
||||
<?php
|
||||
$data = file_get_contents("php://input");
|
||||
//$data = json_decode($data);
|
||||
if(empty($data)) {
|
||||
return http_response_code(400);
|
||||
}
|
||||
$json = json_decode($data);
|
||||
if(!$json) {
|
||||
return http_response_code(400);
|
||||
}
|
||||
|
||||
file_put_contents("feedback.txt", $data."\n\n\n", FILE_APPEND);
|
||||
file_put_contents("feedback.txt", ($json->player->name) .": ". ($json->text) ."\n".$data."\n\n\n", FILE_APPEND);
|
||||
|
||||
echo "OK";
|
||||
?>
|
BIN
data/images/topbuttons/prey.png
Normal file
BIN
data/images/topbuttons/prey.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -15,7 +15,7 @@ local serverSelector
|
||||
local clientVersionSelector
|
||||
local serverHostTextEdit
|
||||
local rememberPasswordBox
|
||||
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "961", "1077", "1090", "1096", "1098", "1099", "1100"}
|
||||
local protos = {"740", "760", "772", "792", "800", "810", "854", "860", "870", "961", "1077", "1090", "1096", "1098", "1099", "1100"}
|
||||
|
||||
-- private functions
|
||||
local function onProtocolError(protocol, message, errorCode)
|
||||
@ -289,7 +289,7 @@ end
|
||||
function EnterGame.clearAccountFields()
|
||||
enterGame:getChildById('accountNameTextEdit'):clearText()
|
||||
enterGame:getChildById('accountPasswordTextEdit'):clearText()
|
||||
--enterGame:getChildById('authenticatorTokenTextEdit'):clearText()
|
||||
enterGame:getChildById('accountTokenTextEdit'):clearText()
|
||||
enterGame:getChildById('accountNameTextEdit'):focus()
|
||||
g_settings.remove('account')
|
||||
g_settings.remove('password')
|
||||
@ -324,8 +324,7 @@ function EnterGame.doLogin()
|
||||
|
||||
G.account = enterGame:getChildById('accountNameTextEdit'):getText()
|
||||
G.password = enterGame:getChildById('accountPasswordTextEdit'):getText()
|
||||
--G.authenticatorToken = enterGame:getChildById('authenticatorTokenTextEdit'):getText()
|
||||
G.authenticatorToken = ""
|
||||
G.authenticatorToken = enterGame:getChildById('accountTokenTextEdit'):getText()
|
||||
G.stayLogged = true
|
||||
G.server = serverSelector:getText():trim()
|
||||
G.host = serverHostTextEdit:getText()
|
||||
@ -456,5 +455,7 @@ function EnterGame.onLoginError(err)
|
||||
end
|
||||
local errorBox = displayErrorBox(tr('Login Error'), err)
|
||||
errorBox.onOk = EnterGame.show
|
||||
EnterGame.clearAccountFields()
|
||||
if err:lower():find("invalid") or err:lower():find("not correct") or err:lower():find("or password") then
|
||||
EnterGame.clearAccountFields()
|
||||
end
|
||||
end
|
||||
|
@ -1,6 +1,6 @@
|
||||
EnterGameWindow < StaticMainWindow
|
||||
!text: tr('Enter Game')
|
||||
size: 240 310
|
||||
size: 260 354
|
||||
|
||||
EnterGameWindow
|
||||
id: enterGame
|
||||
@ -33,6 +33,20 @@ EnterGameWindow
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
|
||||
MenuLabel
|
||||
!text: tr('Token')
|
||||
anchors.left: prev.left
|
||||
anchors.top: prev.bottom
|
||||
text-auto-resize: true
|
||||
margin-top: 8
|
||||
|
||||
TextEdit
|
||||
id: accountTokenTextEdit
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
anchors.top: prev.bottom
|
||||
margin-top: 2
|
||||
|
||||
Panel
|
||||
id: serverSelectorPanel
|
||||
anchors.left: parent.left
|
||||
@ -114,7 +128,7 @@ EnterGameWindow
|
||||
anchors.left: parent.left
|
||||
anchors.top: serverLabel.bottom
|
||||
margin-top: 2
|
||||
width: 130
|
||||
width: 150
|
||||
|
||||
MenuLabel
|
||||
id: clientLabel
|
||||
|
@ -372,7 +372,19 @@ Characters < Panel
|
||||
!text: tr('Auto reconnect: Off')
|
||||
|
||||
Button
|
||||
id: createCharacter
|
||||
id: showOutfits
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.bottom: parent.bottom
|
||||
width: 140
|
||||
|
||||
$on:
|
||||
!text: tr("Show outfits")
|
||||
|
||||
$!on:
|
||||
!text: tr("Hide outfits")
|
||||
|
||||
Button
|
||||
id: connect
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
!text: tr("Connect")
|
||||
|
@ -362,4 +362,15 @@ function makesingleton(obj)
|
||||
return singleton
|
||||
end
|
||||
|
||||
function comma_value(amount)
|
||||
local formatted = amount
|
||||
while true do
|
||||
formatted, k = string.gsub(formatted, "^(-?%d+)(%d%d%d)", '%1,%2')
|
||||
if (k==0) then
|
||||
break
|
||||
end
|
||||
end
|
||||
return formatted
|
||||
end
|
||||
|
||||
-- @}
|
@ -9,16 +9,18 @@ ActionTypes = {
|
||||
USE = 0,
|
||||
USE_SELF = 1,
|
||||
USE_TARGET = 2,
|
||||
USE_WITH = 3
|
||||
USE_WITH = 3,
|
||||
EQUIP = 4
|
||||
}
|
||||
|
||||
ActionColors = {
|
||||
empty = '#00000022',
|
||||
text = '#88888844',
|
||||
itemUse = '#8888FF44',
|
||||
itemUseSelf = '#00FF0044',
|
||||
itemUseTarget = '#FF000044',
|
||||
itemUseWith = '#F5B32544'
|
||||
empty = '#00000033',
|
||||
text = '#88888866',
|
||||
itemUse = '#8888FF66',
|
||||
itemUseSelf = '#00FF0066',
|
||||
itemUseTarget = '#FF000066',
|
||||
itemUseWith = '#F5B32566',
|
||||
itemEquip = '#FFFFFF66'
|
||||
}
|
||||
|
||||
function init()
|
||||
@ -29,10 +31,7 @@ function init()
|
||||
bottomPanel:moveChildToIndex(actionPanel2, 1)
|
||||
|
||||
actionConfig = g_configs.create("/actionbar.otml")
|
||||
|
||||
setupActionPanel(1, actionPanel1)
|
||||
setupActionPanel(2, actionPanel2)
|
||||
|
||||
|
||||
connect(g_game, {
|
||||
onGameStart = online,
|
||||
onGameEnd = offline
|
||||
@ -66,6 +65,9 @@ function terminate()
|
||||
end
|
||||
|
||||
function show()
|
||||
if not g_game.isOnline() then return end
|
||||
setupActionPanel(1, actionPanel1)
|
||||
setupActionPanel(2, actionPanel2)
|
||||
actionPanel1:setOn(g_settings.getBoolean("actionBar1", false))
|
||||
actionPanel2:setOn(g_settings.getBoolean("actionBar2", false))
|
||||
end
|
||||
@ -104,6 +106,7 @@ function setupActionPanel(index, panel)
|
||||
for i, buttonConfig in pairs(rawConfig) do -- sorting, because key in rawConfig is string
|
||||
config[tonumber(i)] = buttonConfig
|
||||
end
|
||||
panel.tabBar:destroyChildren()
|
||||
for i=1,actionButtonsInPanel do
|
||||
local action = g_ui.createWidget('ActionButton', panel.tabBar)
|
||||
setupAction(index, action, config[i])
|
||||
@ -170,6 +173,8 @@ function setupActionType(action, actionType)
|
||||
action:setBorderColor(ActionColors.itemUseTarget)
|
||||
elseif action.actionType == ActionTypes.USE_WITH then
|
||||
action:setBorderColor(ActionColors.itemUseWith)
|
||||
elseif action.actionType == ActionTypes.EQUIP then
|
||||
action:setBorderColor(ActionColors.itemEquip)
|
||||
end
|
||||
end
|
||||
|
||||
@ -239,6 +244,12 @@ function executeAction(action, ticks)
|
||||
item = tmpItem
|
||||
end
|
||||
modules.game_interface.startUseWith(item, action.item:getItemSubType() or - 1)
|
||||
elseif action.actionType == ActionTypes.EQUIP then
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
local item = Item.create(action.item:getItemId())
|
||||
g_game.equipItem(item)
|
||||
action.actionDelayTo = g_clock.millis() + actionDelay
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -247,10 +258,18 @@ function actionOnMouseRelease(action, mousePosition, mouseButton)
|
||||
if mouseButton == MouseRightButton then
|
||||
local menu = g_ui.createWidget('PopupMenu')
|
||||
menu:setGameMenu(true)
|
||||
if action.item:getItemId() > 0 and action.item:getItem():isMultiUse() then
|
||||
menu:addOption(tr('Use on yourself'), function() return setupActionType(action, ActionTypes.USE_SELF) end)
|
||||
menu:addOption(tr('Use on target'), function() return setupActionType(action, ActionTypes.USE_TARGET) end)
|
||||
menu:addOption(tr('With crosshair'), function() return setupActionType(action, ActionTypes.USE_WITH) end)
|
||||
if action.item:getItemId() > 0 then
|
||||
if action.item:getItem():isMultiUse() then
|
||||
menu:addOption(tr('Use on yourself'), function() return setupActionType(action, ActionTypes.USE_SELF) end)
|
||||
menu:addOption(tr('Use on target'), function() return setupActionType(action, ActionTypes.USE_TARGET) end)
|
||||
menu:addOption(tr('With crosshair'), function() return setupActionType(action, ActionTypes.USE_WITH) end)
|
||||
end
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
if not action.item:getItem():isMultiUse() then
|
||||
menu:addOption(tr('Use'), function() return setupActionType(action, ActionTypes.USE) end)
|
||||
end
|
||||
menu:addOption(tr('Equip'), function() return setupActionType(action, ActionTypes.EQUIP) end)
|
||||
end
|
||||
end
|
||||
menu:addSeparator()
|
||||
menu:addOption(tr('Set text'), function()
|
||||
@ -324,7 +343,13 @@ function actionOnItemChange(widget)
|
||||
setupActionType(action, ActionTypes.USE_WITH)
|
||||
end
|
||||
else
|
||||
setupActionType(action, ActionTypes.USE)
|
||||
if g_game.getClientVersion() >= 910 then
|
||||
if not action.actionType or action.actionType <= ActionTypes.EQUIP then
|
||||
setupActionType(action, ActionTypes.USE)
|
||||
end
|
||||
else
|
||||
setupActionType(action, ActionTypes.USE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -16,7 +16,6 @@ ActionButton < Panel
|
||||
id: item
|
||||
anchors.fill: parent
|
||||
margin: 1 1 1 1
|
||||
item-id: 3307
|
||||
&selectable: true
|
||||
&editable: false
|
||||
virtual: true
|
||||
|
@ -128,11 +128,8 @@ function refresh()
|
||||
end
|
||||
|
||||
-- get list of configs
|
||||
createDefaultConfigs()
|
||||
local configs = g_resources.listDirectoryFiles("/bot", false, false)
|
||||
if #configs == 0 then
|
||||
createDefaultConfig()
|
||||
configs = g_resources.listDirectoryFiles("/bot", false, false)
|
||||
end
|
||||
|
||||
-- clean
|
||||
configList.onOptionChange = nil
|
||||
@ -272,22 +269,25 @@ function edit()
|
||||
editWindow:raise()
|
||||
end
|
||||
|
||||
function createDefaultConfig()
|
||||
if not g_resources.directoryExists("/bot/default_config") then
|
||||
g_resources.makeDir("/bot/default_config")
|
||||
if not g_resources.directoryExists("/bot/default_config") then
|
||||
return onError("Can't create default_config directory in " .. g_resources.getWriteDir())
|
||||
function createDefaultConfigs()
|
||||
local defaultConfigFiles = g_resources.listDirectoryFiles("default_configs", false, false)
|
||||
for i, config_name in ipairs(defaultConfigFiles) do
|
||||
if not g_resources.directoryExists("/bot/" .. config_name) then
|
||||
g_resources.makeDir("/bot/" .. config_name)
|
||||
if not g_resources.directoryExists("/bot/" .. config_name) then
|
||||
return onError("Can't create /bot/" .. config_name .. " directory in " .. g_resources.getWriteDir())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local defaultConfigFiles = g_resources.listDirectoryFiles("default_config", true, false)
|
||||
for i, file in ipairs(defaultConfigFiles) do
|
||||
local baseName = file:split("/")
|
||||
baseName = baseName[#baseName]
|
||||
local contents = g_resources.readFileContents(file)
|
||||
if contents:len() > 0 then
|
||||
g_resources.writeFileContents("/bot/default_config/" .. baseName, contents)
|
||||
end
|
||||
local defaultConfigFiles = g_resources.listDirectoryFiles("default_configs/" .. config_name, true, false)
|
||||
for i, file in ipairs(defaultConfigFiles) do
|
||||
local baseName = file:split("/")
|
||||
baseName = baseName[#baseName]
|
||||
local contents = g_resources.readFileContents(file)
|
||||
if contents:len() > 0 then
|
||||
g_resources.writeFileContents("/bot/" .. config_name .. "/" .. baseName, contents)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
4
modules/game_bot/default_configs/default/default.lua
Normal file
4
modules/game_bot/default_configs/default/default.lua
Normal file
@ -0,0 +1,4 @@
|
||||
-- to keep it up to date, config is loaded from remote server
|
||||
loadScript("http://otclient.ovh/bot/default.php?version=" .. getVersion())
|
||||
|
||||
-- if you want add custom scripts, just add them bellow or create new lua file
|
@ -1,8 +1,25 @@
|
||||
North = 0
|
||||
East = 1
|
||||
South = 2
|
||||
West = 3
|
||||
NorthEast = 4
|
||||
SouthEast = 5
|
||||
SouthWest = 6
|
||||
NorthWest = 7
|
||||
local context = G.botContext
|
||||
|
||||
context.North = 0
|
||||
context.East = 1
|
||||
context.South = 2
|
||||
context.West = 3
|
||||
context.NorthEast = 4
|
||||
context.SouthEast = 5
|
||||
context.SouthWest = 6
|
||||
context.NorthWest = 7
|
||||
|
||||
context.InventorySlotOther = 0
|
||||
context.InventorySlotHead = 1
|
||||
context.InventorySlotNeck = 2
|
||||
context.InventorySlotBack = 3
|
||||
context.InventorySlotBody = 4
|
||||
context.InventorySlotRight = 5
|
||||
context.InventorySlotLeft = 6
|
||||
context.InventorySlotLeg = 7
|
||||
context.InventorySlotFeet = 8
|
||||
context.InventorySlotFinger = 9
|
||||
context.InventorySlotAmmo = 10
|
||||
context.InventorySlotPurse = 11
|
||||
context.InventorySlotFirst = 1
|
||||
context.InventorySlotLast = 10
|
||||
|
@ -78,7 +78,7 @@ context.yell = function(text) g_game.talkChannel(3, 0, text) end
|
||||
context.talkChannel = function(channel, text) g_game.talkChannel(7, channel, text) end
|
||||
context.sayChannel = context.talkChannel
|
||||
context.talkPrivate = function(receiver, text) g_game.talkPrivate(5, receiver, text) end
|
||||
context.sayPrivate = g_game.talkPrivate
|
||||
context.sayPrivate = context.talkPrivate
|
||||
|
||||
context.talkNpc = function(text)
|
||||
if g_game.getClientVersion() >= 810 then
|
||||
|
59
modules/game_bot/functions/script_loader.lua
Normal file
59
modules/game_bot/functions/script_loader.lua
Normal file
@ -0,0 +1,59 @@
|
||||
local context = G.botContext
|
||||
|
||||
context.loadScript = function(path, onLoadCallback)
|
||||
if type(path) ~= 'string' then
|
||||
return context.error("Invalid path for loadScript: " .. tostring(path))
|
||||
end
|
||||
if path:lower():find("http") == 1 then
|
||||
return context.loadRemoteScript(path)
|
||||
end
|
||||
if not g_resources.fileExists(path) then
|
||||
return context.error("File " .. path .. " doesn't exist")
|
||||
end
|
||||
|
||||
local status, result = pcall(function()
|
||||
assert(load(g_resources.readFileContents(path), path, nil, context))()
|
||||
end)
|
||||
if not status then
|
||||
return context.error("Error while loading script from: " .. path .. ":\n" .. result)
|
||||
end
|
||||
if onLoadCallback then
|
||||
onLoadCallback()
|
||||
end
|
||||
end
|
||||
|
||||
context.loadRemoteScript = function(url, onLoadCallback)
|
||||
if type(url) ~= 'string' or url:lower():find("http") ~= 1 then
|
||||
return context.error("Invalid url for loadRemoteScript: " .. tostring(url))
|
||||
end
|
||||
|
||||
HTTP.get(url, function(data, err)
|
||||
if err or data:len() == 0 then
|
||||
-- try to load from cache
|
||||
if type(context.storage.scriptsCache) ~= 'table' then
|
||||
context.storage.scriptsCache = {}
|
||||
end
|
||||
local cache = context.storage.scriptsCache[url]
|
||||
if cache and type(cache) == 'string' and cache:len() > 0 then
|
||||
data = cache
|
||||
else
|
||||
return context.error("Can't load script from: " .. url .. ", error: " .. err)
|
||||
end
|
||||
end
|
||||
|
||||
local status, result = pcall(function()
|
||||
assert(load(data, url, nil, context))()
|
||||
end)
|
||||
if not status then
|
||||
return context.error("Error while loading script from: " .. url .. ":\n" .. result)
|
||||
end
|
||||
-- cache script
|
||||
if type(context.storage.scriptsCache) ~= 'table' then
|
||||
context.storage.scriptsCache = {}
|
||||
end
|
||||
context.storage.scriptsCache[url] = data
|
||||
if onLoadCallback then
|
||||
onLoadCallback()
|
||||
end
|
||||
end)
|
||||
end
|
@ -13,3 +13,7 @@ context.doScreenshot = function(filename)
|
||||
g_app.doScreenshot(filename)
|
||||
end
|
||||
context.screenshot = context.doScreenshot
|
||||
|
||||
context.getVersion = function()
|
||||
return g_app.getVersion()
|
||||
end
|
@ -9,6 +9,10 @@ context.setupUI = function(otml, parent)
|
||||
return widget
|
||||
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
|
||||
|
@ -148,11 +148,11 @@ function onHealthChange(localPlayer, health, maxHealth)
|
||||
maxHealth = health
|
||||
end
|
||||
|
||||
healthBar:setText(health .. ' / ' .. maxHealth)
|
||||
healthBar:setText(comma_value(health) .. ' / ' .. comma_value(maxHealth))
|
||||
healthBar:setTooltip(tr(healthTooltip, health, maxHealth))
|
||||
healthBar:setValue(health, 0, maxHealth)
|
||||
|
||||
topHealthBar:setText(health .. ' / ' .. maxHealth)
|
||||
topHealthBar:setText(comma_value(health) .. ' / ' .. comma_value(maxHealth))
|
||||
topHealthBar:setTooltip(tr(healthTooltip, health, maxHealth))
|
||||
topHealthBar:setValue(health, 0, maxHealth)
|
||||
|
||||
@ -182,11 +182,11 @@ function onManaChange(localPlayer, mana, maxMana)
|
||||
if mana > maxMana then
|
||||
maxMana = mana
|
||||
end
|
||||
manaBar:setText(mana .. ' / ' .. maxMana)
|
||||
manaBar:setText(comma_value(mana) .. ' / ' .. comma_value(maxMana))
|
||||
manaBar:setTooltip(tr(manaTooltip, mana, maxMana))
|
||||
manaBar:setValue(mana, 0, maxMana)
|
||||
|
||||
topManaBar:setText(mana .. ' / ' .. maxMana)
|
||||
topManaBar:setText(comma_value(mana) .. ' / ' .. comma_value(maxMana))
|
||||
topManaBar:setTooltip(tr(manaTooltip, mana, maxMana))
|
||||
topManaBar:setValue(mana, 0, maxMana)
|
||||
|
||||
@ -281,8 +281,7 @@ function onOverlayGeometryChange()
|
||||
|
||||
local height = overlay:getHeight()
|
||||
local width = overlay:getWidth()
|
||||
|
||||
|
||||
|
||||
topHealthBar:setMarginLeft(math.max(minMargin, (width - height + 50) / 2 + 2))
|
||||
topManaBar:setMarginRight(math.max(minMargin, (width - height + 50) / 2 + 2))
|
||||
end
|
@ -446,7 +446,11 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
|
||||
menu:addOption(tr('Dismount'), function() localPlayer:dismount() end)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if g_game.getFeature(GamePrey) and modules.game_prey then
|
||||
menu:addOption(tr('Open Prey Dialog'), function() modules.game_prey.show() end)
|
||||
end
|
||||
|
||||
if creatureThing:isPartyMember() then
|
||||
if creatureThing:isPartyLeader() then
|
||||
if creatureThing:isPartySharedExperienceActive() then
|
||||
@ -860,15 +864,19 @@ function refreshViewMode()
|
||||
gameLeftPanels:setMarginTop(0)
|
||||
gameMapPanel:setMarginLeft(0)
|
||||
gameMapPanel:setMarginRight(0)
|
||||
gameMapPanel:setMarginTop(0)
|
||||
if modules.game_textmessage then
|
||||
modules.game_textmessage.messagesPanel:setMarginTop(0)
|
||||
end
|
||||
else
|
||||
gameLeftPanels:setMarginTop(modules.client_topmenu.getTopMenu():getHeight() - gameLeftPanels:getPaddingTop())
|
||||
gameRightPanels:setMarginTop(modules.client_topmenu.getTopMenu():getHeight() - gameRightPanels:getPaddingTop())
|
||||
end
|
||||
|
||||
gameMapPanel:setVisibleDimension({ width = 15, height = 11 })
|
||||
gameMapPanel:setMarginTop(0)
|
||||
|
||||
if classic then
|
||||
g_game.changeMapAwareRange(19, 15)
|
||||
gameRootPanel:addAnchor(AnchorTop, 'topMenu', AnchorBottom)
|
||||
gameMapPanel:addAnchor(AnchorLeft, 'gameLeftPanels', AnchorRight)
|
||||
gameMapPanel:addAnchor(AnchorRight, 'gameRightPanels', AnchorLeft)
|
||||
@ -882,7 +890,6 @@ function refreshViewMode()
|
||||
|
||||
modules.client_topmenu.getTopMenu():setImageColor('white')
|
||||
gameBottomPanel:setImageColor('white')
|
||||
g_game.changeMapAwareRange(19, 15)
|
||||
|
||||
if modules.game_console then
|
||||
modules.game_console.switchMode(false)
|
||||
@ -921,6 +928,7 @@ function updateSize()
|
||||
local height = gameMapPanel:getHeight()
|
||||
local width = gameMapPanel:getWidth()
|
||||
|
||||
print("updatesize")
|
||||
if not classic then
|
||||
local rheight = gameRootPanel:getHeight()
|
||||
local rwidth = gameRootPanel:getWidth()
|
||||
@ -935,15 +943,20 @@ function updateSize()
|
||||
if g_game.getFeature(GameChangeMapAwareRange) then
|
||||
local maxWidth = tileSize * (awareRange.width - 1)
|
||||
end
|
||||
gameMapPanel:setMarginTop(-tileSize * 2)
|
||||
gameMapPanel:setMarginTop(-tileSize * 2)
|
||||
if g_settings.getBoolean("cacheMap") then
|
||||
gameMapPanel:setMarginLeft(0)
|
||||
gameMapPanel:setMarginRight(0)
|
||||
else
|
||||
local margin = math.max(0, math.floor((rwidth - maxWidth) / 2))
|
||||
local margin = math.max(0, math.floor((rwidth - maxWidth) / 2))
|
||||
gameMapPanel:setMarginLeft(margin)
|
||||
gameMapPanel:setMarginRight(margin)
|
||||
end
|
||||
|
||||
if modules.game_textmessage then
|
||||
modules.game_textmessage.messagesPanel:setMarginTop(-gameMapPanel:getMarginTop())
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[
|
||||
|
@ -35,6 +35,7 @@ Module
|
||||
- game_itemselector
|
||||
- game_textedit
|
||||
- game_actionbar
|
||||
- game_prey
|
||||
- game_bot
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
||||
|
@ -477,7 +477,7 @@ function onFreeCapacityChange(player, freeCapacity)
|
||||
freeCapacity = math.floor(freeCapacity)
|
||||
end
|
||||
if freeCapacity > 99999 then
|
||||
freeCapacity = 99999
|
||||
freeCapacity = math.min(9999, math.floor(freeCapacity/1000)) .. "k"
|
||||
end
|
||||
capLabel:setText(tr('Cap') .. ':\n' .. freeCapacity)
|
||||
end
|
||||
|
277
modules/game_prey/prey.lua
Normal file
277
modules/game_prey/prey.lua
Normal file
@ -0,0 +1,277 @@
|
||||
-- sponsored by kivera-global.com
|
||||
|
||||
local preyWindow
|
||||
local preyButton
|
||||
local msgWindow
|
||||
local bankGold = 0
|
||||
local inventoryGold = 0
|
||||
local rerollPrice = 0
|
||||
local bonusRerolls = 0
|
||||
|
||||
local PREY_BONUS_DAMAGE_BOOST = 0
|
||||
local PREY_BONUS_DAMAGE_REDUCTION = 1
|
||||
local PREY_BONUS_XP_BONUS = 2
|
||||
local PREY_BONUS_IMPROVED_LOOT = 3
|
||||
local PREY_BONUS_NONE = 4
|
||||
|
||||
local PREY_ACTION_LISTREROLL = 0
|
||||
local PREY_ACTION_BONUSREROLL = 1
|
||||
local PREY_ACTION_MONSTERSELECTION = 2
|
||||
local PREY_ACTION_REQUEST_ALL_MONSTERS = 3
|
||||
local PREY_ACTION_CHANGE_FROM_ALL = 4
|
||||
local PREY_ACTION_LOCK_PREY = 5
|
||||
|
||||
|
||||
function bonusDescription(bonusType, bonusValue, bonusGrade)
|
||||
if bonusType == PREY_BONUS_DAMAGE_BOOST then
|
||||
return "Damage bonus (" .. bonusGrade .. "/10)"
|
||||
elseif bonusType == PREY_BONUS_DAMAGE_REDUCTION then
|
||||
return "Damage reduction bonus (" .. bonusGrade .. "/10)"
|
||||
elseif bonusType == PREY_BONUS_XP_BONUS then
|
||||
return "XP bonus (" .. bonusGrade .. "/10)"
|
||||
elseif bonusType == PREY_BONUS_IMPROVED_LOOT then
|
||||
return "Loot bonus (" .. bonusGrade .. "/10)"
|
||||
elseif bonusType == PREY_BONUS_DAMAGE_BOOST then
|
||||
return "-"
|
||||
end
|
||||
return "Uknown bonus"
|
||||
end
|
||||
|
||||
function timeleftTranslation(timeleft, forPreyTimeleft) -- in seconds
|
||||
if timeleft == 0 then
|
||||
if forPreyTimeleft then
|
||||
return tr("infinite bonus")
|
||||
end
|
||||
return tr("Available now")
|
||||
end
|
||||
local minutes = math.ceil(timeleft / 60)
|
||||
local hours = math.floor(minutes / 60)
|
||||
minutes = minutes - hours * 60
|
||||
if hours > 0 then
|
||||
if forPreyTimeleft then
|
||||
return "" .. hours .. "h " .. minutes .. "m"
|
||||
end
|
||||
return tr("Available in") .. " " .. hours .. "h " .. minutes .. "m"
|
||||
end
|
||||
if forPreyTimeleft then
|
||||
return "" .. minutes .. "m"
|
||||
end
|
||||
return tr("Available in") .. " " .. minutes .. "m"
|
||||
end
|
||||
function init()
|
||||
connect(g_game, {
|
||||
onGameEnd = hide,
|
||||
onResourceBalance = onResourceBalance,
|
||||
onPreyFreeRolls = onPreyFreeRolls,
|
||||
onPreyTimeLeft = onPreyTimeLeft,
|
||||
onPreyPrice = onPreyPrice,
|
||||
onPreyLocked = onPreyLocked,
|
||||
onPreyInactive = onPreyInactive,
|
||||
onPreyActive = onPreyActive,
|
||||
onPreySelection = onPreySelection
|
||||
})
|
||||
|
||||
preyWindow = g_ui.displayUI('prey')
|
||||
preyWindow:hide()
|
||||
preyButton = modules.client_topmenu.addRightGameToggleButton('preyButton', tr('Preys'), '/images/topbuttons/prey', toggle)
|
||||
end
|
||||
|
||||
function terminate()
|
||||
disconnect(g_game, {
|
||||
onGameEnd = hide,
|
||||
onResourceBalance = onResourceBalance,
|
||||
onPreyFreeRolls = onPreyFreeRolls,
|
||||
onPreyTimeLeft = onPreyTimeLeft,
|
||||
onPreyPrice = onPreyPrice,
|
||||
onPreyLocked = onPreyLocked,
|
||||
onPreyInactive = onPreyInactive,
|
||||
onPreyActive = onPreyActive,
|
||||
onPreySelection = onPreySelection
|
||||
})
|
||||
|
||||
preyButton:destroy()
|
||||
preyWindow:destroy()
|
||||
if msgWindow then
|
||||
msgWindow:destroy()
|
||||
msgWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function hide()
|
||||
preyWindow:hide()
|
||||
if msgWindow then
|
||||
msgWindow:destroy()
|
||||
msgWindow = nil
|
||||
end
|
||||
end
|
||||
|
||||
function show()
|
||||
preyWindow:show()
|
||||
preyWindow:raise()
|
||||
preyWindow:focus()
|
||||
end
|
||||
|
||||
function toggle()
|
||||
if preyWindow:isVisible() then
|
||||
return hide()
|
||||
end
|
||||
show()
|
||||
end
|
||||
|
||||
function onPreyFreeRolls(slot, timeleft)
|
||||
local prey = preyWindow["slot" .. (slot + 1)]
|
||||
if not prey then return end
|
||||
if prey.state ~= "active" and prey.state ~= "selection" then
|
||||
return
|
||||
end
|
||||
prey.bottomLabel:setText(tr("Free list reroll") .. ": \n" .. timeleftTranslation(timeleft * 60))
|
||||
end
|
||||
|
||||
function onPreyTimeLeft(slot, timeleft)
|
||||
local prey = preyWindow["slot" .. (slot + 1)]
|
||||
if not prey then return end
|
||||
if prey.state ~= "active" then
|
||||
return
|
||||
end
|
||||
prey.description:setText(tr("Time left") .. ": " .. timeleftTranslation(timeleft, true))
|
||||
end
|
||||
|
||||
function onPreyPrice(price)
|
||||
rerollPrice = price
|
||||
preyWindow.rerollPrice:setText(tr("Reroll price") .. ":\n" .. price)
|
||||
end
|
||||
|
||||
function onPreyLocked(slot, unlockState, timeUntilFreeReroll)
|
||||
local prey = preyWindow["slot" .. (slot + 1)]
|
||||
if not prey then return end
|
||||
prey.state = "locked"
|
||||
prey.title:setText(tr("Prey Locked"))
|
||||
prey.list:hide()
|
||||
prey.listScrollbar:hide()
|
||||
prey.creature:hide()
|
||||
prey.description:hide()
|
||||
prey.bonuses:hide()
|
||||
prey.button:hide()
|
||||
prey.bottomLabel:show()
|
||||
if unlockState == 0 then
|
||||
prey.bottomLabel:setText(tr("You need to have premium account and buy this prey slot in the game store."))
|
||||
elseif unlockState == 1 then
|
||||
prey.bottomLabel:setText(tr("You need to buy this prey slot in the game store."))
|
||||
else
|
||||
prey.bottomLabel:setText(tr("You can't unlock it."))
|
||||
prey.bottomButton:hide()
|
||||
end
|
||||
if (unlockState == 0 or unlockState == 1) and modules.game_shop then
|
||||
prey.bottomButton:setText("Open game store")
|
||||
prey.bottomButton.onClick = function() hide() modules.game_shop.show() end
|
||||
prey.bottomButton:show()
|
||||
end
|
||||
end
|
||||
|
||||
function onPreyInactive(slot, timeUntilFreeReroll)
|
||||
local prey = preyWindow["slot" .. (slot + 1)]
|
||||
if not prey then return end
|
||||
prey.state = "inactive"
|
||||
prey.title:setText(tr("Prey Inactive"))
|
||||
prey.list:hide()
|
||||
prey.listScrollbar:hide()
|
||||
prey.creature:hide()
|
||||
prey.description:hide()
|
||||
prey.bonuses:hide()
|
||||
prey.button:hide()
|
||||
prey.bottomLabel:hide()
|
||||
prey.bottomButton:hide()
|
||||
end
|
||||
|
||||
function onPreyActive(slot, currentHolderName, currentHolderOutfit, bonusType, bonusValue, bonusGrade, timeLeft, timeUntilFreeReroll)
|
||||
local prey = preyWindow["slot" .. (slot + 1)]
|
||||
if not prey then return end
|
||||
prey.state = "active"
|
||||
prey.title:setText(currentHolderName)
|
||||
prey.list:hide()
|
||||
prey.listScrollbar:hide()
|
||||
prey.creature:show()
|
||||
prey.creature:setOutfit(currentHolderOutfit)
|
||||
prey.description:setText(tr("Time left") .. ": " .. timeleftTranslation(timeLeft, true))
|
||||
prey.description:show()
|
||||
prey.bonuses:setText(bonusDescription(bonusType, bonusValue, bonusGrade))
|
||||
prey.bonuses:show()
|
||||
prey.button:setText(tr("Bonus reroll"))
|
||||
prey.button:show()
|
||||
prey.bottomLabel:setText(tr("Free list reroll")..": \n" .. timeleftTranslation(timeUntilFreeReroll * 60))
|
||||
prey.bottomLabel:show()
|
||||
if timeUntilFreeReroll > 0 then
|
||||
prey.bottomButton:setText(tr("Buy list reroll"))
|
||||
else
|
||||
prey.bottomButton:setText(tr("Free list reroll"))
|
||||
end
|
||||
prey.bottomButton:show()
|
||||
|
||||
prey.button.onClick = function()
|
||||
if bonusRerolls == 0 then
|
||||
return showMessage(tr("Error"), tr("You don't have any bonus rerolls.\nYou can buy them in ingame store."))
|
||||
end
|
||||
g_game.preyAction(slot, PREY_ACTION_BONUSREROLL, 0)
|
||||
end
|
||||
|
||||
prey.bottomButton.onClick = function()
|
||||
g_game.preyAction(slot, PREY_ACTION_LISTREROLL, 0)
|
||||
end
|
||||
end
|
||||
|
||||
function onPreySelection(slot, bonusType, bonusValue, bonusGrade, names, outfits, timeUntilFreeReroll)
|
||||
local prey = preyWindow["slot" .. (slot + 1)]
|
||||
if not prey then return end
|
||||
prey.state = "selection"
|
||||
prey.title:setText(tr("Select monster"))
|
||||
prey.list:show()
|
||||
prey.listScrollbar:show()
|
||||
prey.creature:hide()
|
||||
prey.description:hide()
|
||||
prey.bonuses:hide()
|
||||
prey.button:setText(tr("Select"))
|
||||
prey.button:show()
|
||||
prey.bottomLabel:setText("Free list reroll: \n" .. timeleftTranslation(timeUntilFreeReroll * 60))
|
||||
prey.bottomLabel:show()
|
||||
prey.bottomButton:hide()
|
||||
prey.list:destroyChildren()
|
||||
for i, name in ipairs(names) do
|
||||
local label = g_ui.createWidget("PreySelectionLabel", prey.list)
|
||||
label:setText(name)
|
||||
label.creature:setOutfit(outfits[i])
|
||||
end
|
||||
prey.button.onClick = function()
|
||||
local child = prey.list:getFocusedChild()
|
||||
if not child then
|
||||
return showMessage(tr("Error"), tr("Select monster to proceed."))
|
||||
end
|
||||
local index = prey.list:getChildIndex(child)
|
||||
g_game.preyAction(slot, PREY_ACTION_MONSTERSELECTION, index - 1)
|
||||
end
|
||||
end
|
||||
|
||||
function onResourceBalance(type, balance)
|
||||
if type == 0 then -- bank gold
|
||||
bankGold = balance
|
||||
elseif type == 1 then -- inventory gold
|
||||
inventoryGold = balance
|
||||
elseif type == 10 then -- bonus rerolls
|
||||
bonusRerolls = balance
|
||||
preyWindow.bonusRerolls:setText(tr("Available bonus rerolls") .. ":\n" .. balance)
|
||||
end
|
||||
|
||||
if type == 0 or type == 1 then
|
||||
preyWindow.balance:setText(tr("Balance") .. ":\n" .. (bankGold + inventoryGold))
|
||||
end
|
||||
end
|
||||
|
||||
function showMessage(title, message)
|
||||
if msgWindow then
|
||||
msgWindow:destroy()
|
||||
end
|
||||
|
||||
msgWindow = displayInfoBox(title, message)
|
||||
msgWindow:show()
|
||||
msgWindow:raise()
|
||||
msgWindow:focus()
|
||||
end
|
10
modules/game_prey/prey.otmod
Normal file
10
modules/game_prey/prey.otmod
Normal file
@ -0,0 +1,10 @@
|
||||
Module
|
||||
name: game_prey
|
||||
description: Preys, sponsored by kivera-global.com
|
||||
author: otclient.ovh & kivera-global.com
|
||||
website: http://otclient.ovh
|
||||
sandboxed: true
|
||||
scripts: [ prey ]
|
||||
dependencies: [ client_topmenu ]
|
||||
@onLoad: init()
|
||||
@onUnload: terminate()
|
199
modules/game_prey/prey.otui
Normal file
199
modules/game_prey/prey.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()
|
@ -320,7 +320,6 @@ function processMessage(data)
|
||||
msgWindow:show()
|
||||
msgWindow:raise()
|
||||
msgWindow:focus()
|
||||
msgWindow:raise()
|
||||
end
|
||||
|
||||
function processStatus(data)
|
||||
|
@ -116,7 +116,7 @@ ShopOfferCreature < ShopOffer
|
||||
margin-top: 4
|
||||
margin-bottom: 4
|
||||
margin-left: 2
|
||||
size: 48 48
|
||||
size: 64 64
|
||||
|
||||
ShopOfferImage < ShopOffer
|
||||
Label
|
||||
|
@ -282,7 +282,18 @@ function onSkillButtonClick(button)
|
||||
end
|
||||
|
||||
function onExperienceChange(localPlayer, value)
|
||||
setSkillValue('experience', value)
|
||||
local postFix = ""
|
||||
if value > 1e15 then
|
||||
postFix = "B"
|
||||
value = math.floor(value / 1e9)
|
||||
elseif value > 1e12 then
|
||||
postFix = "M"
|
||||
value = math.floor(value / 1e6)
|
||||
elseif value > 1e9 then
|
||||
postFix = "K"
|
||||
value = math.floor(value / 1e3)
|
||||
end
|
||||
setSkillValue('experience', comma_value(value) .. postFix)
|
||||
end
|
||||
|
||||
function onLevelChange(localPlayer, value, percent)
|
||||
|
@ -117,7 +117,8 @@ MarketItemDescription = {
|
||||
Ability = 12,
|
||||
Charges = 13,
|
||||
WeaponName = 14,
|
||||
Weight = 15
|
||||
Weight = 15,
|
||||
Imbuements = 16
|
||||
}
|
||||
|
||||
MarketItemDescription.First = MarketItemDescription.Armor
|
||||
@ -138,7 +139,8 @@ MarketItemDescriptionStrings = {
|
||||
[12] = 'Ability',
|
||||
[13] = 'Charges',
|
||||
[14] = 'Weapon Type',
|
||||
[15] = 'Weight'
|
||||
[15] = 'Weight',
|
||||
[16] = 'Imbuements'
|
||||
}
|
||||
|
||||
function getMarketDescriptionName(id)
|
||||
|
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