diff --git a/README.md b/README.md index bc341b5..719e4fc 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/api/feedback.php b/api/feedback.php index a63bdc4..a2c6ad1 100644 --- a/api/feedback.php +++ b/api/feedback.php @@ -1,11 +1,14 @@ player->name) .": ". ($json->text) ."\n".$data."\n\n\n", FILE_APPEND); echo "OK"; ?> \ No newline at end of file diff --git a/data/images/topbuttons/prey.png b/data/images/topbuttons/prey.png new file mode 100644 index 0000000..40346df Binary files /dev/null and b/data/images/topbuttons/prey.png differ diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index aa1a07e..19e8428 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -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 diff --git a/modules/client_entergame/entergame.otui b/modules/client_entergame/entergame.otui index 7721e71..68b1ff4 100644 --- a/modules/client_entergame/entergame.otui +++ b/modules/client_entergame/entergame.otui @@ -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 diff --git a/modules/client_entergamev2/entergamev2.otui b/modules/client_entergamev2/entergamev2.otui index 49ef9b4..b8942b9 100644 --- a/modules/client_entergamev2/entergamev2.otui +++ b/modules/client_entergamev2/entergamev2.otui @@ -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") diff --git a/modules/corelib/util.lua b/modules/corelib/util.lua index 157c28b..69213ed 100644 --- a/modules/corelib/util.lua +++ b/modules/corelib/util.lua @@ -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 + -- @} \ No newline at end of file diff --git a/modules/game_actionbar/actionbar.lua b/modules/game_actionbar/actionbar.lua index 82e649f..5a2d9aa 100644 --- a/modules/game_actionbar/actionbar.lua +++ b/modules/game_actionbar/actionbar.lua @@ -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 \ No newline at end of file diff --git a/modules/game_actionbar/actionbar.otui b/modules/game_actionbar/actionbar.otui index cd6495b..639ded1 100644 --- a/modules/game_actionbar/actionbar.otui +++ b/modules/game_actionbar/actionbar.otui @@ -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 diff --git a/modules/game_bot/bot.lua b/modules/game_bot/bot.lua index 833f648..bcc6373 100644 --- a/modules/game_bot/bot.lua +++ b/modules/game_bot/bot.lua @@ -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 diff --git a/modules/game_bot/default_configs/default/default.lua b/modules/game_bot/default_configs/default/default.lua new file mode 100644 index 0000000..53f9307 --- /dev/null +++ b/modules/game_bot/default_configs/default/default.lua @@ -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 diff --git a/modules/game_bot/default_config/battle.lua b/modules/game_bot/default_configs/examples/battle.lua similarity index 100% rename from modules/game_bot/default_config/battle.lua rename to modules/game_bot/default_configs/examples/battle.lua diff --git a/modules/game_bot/default_config/cavebot.lua b/modules/game_bot/default_configs/examples/cavebot.lua similarity index 100% rename from modules/game_bot/default_config/cavebot.lua rename to modules/game_bot/default_configs/examples/cavebot.lua diff --git a/modules/game_bot/default_config/example.otui b/modules/game_bot/default_configs/examples/example.otui similarity index 100% rename from modules/game_bot/default_config/example.otui rename to modules/game_bot/default_configs/examples/example.otui diff --git a/modules/game_bot/default_config/hp.lua b/modules/game_bot/default_configs/examples/hp.lua similarity index 100% rename from modules/game_bot/default_config/hp.lua rename to modules/game_bot/default_configs/examples/hp.lua diff --git a/modules/game_bot/default_config/icons.lua b/modules/game_bot/default_configs/examples/icons.lua similarity index 100% rename from modules/game_bot/default_config/icons.lua rename to modules/game_bot/default_configs/examples/icons.lua diff --git a/modules/game_bot/default_config/main.lua b/modules/game_bot/default_configs/examples/main.lua similarity index 100% rename from modules/game_bot/default_config/main.lua rename to modules/game_bot/default_configs/examples/main.lua diff --git a/modules/game_bot/default_config/npc.lua b/modules/game_bot/default_configs/examples/npc.lua similarity index 100% rename from modules/game_bot/default_config/npc.lua rename to modules/game_bot/default_configs/examples/npc.lua diff --git a/modules/game_bot/default_config/tools.lua b/modules/game_bot/default_configs/examples/tools.lua similarity index 100% rename from modules/game_bot/default_config/tools.lua rename to modules/game_bot/default_configs/examples/tools.lua diff --git a/modules/game_bot/functions/const.lua b/modules/game_bot/functions/const.lua index 149f3a8..637bb34 100644 --- a/modules/game_bot/functions/const.lua +++ b/modules/game_bot/functions/const.lua @@ -1,8 +1,25 @@ -North = 0 -East = 1 -South = 2 -West = 3 -NorthEast = 4 -SouthEast = 5 -SouthWest = 6 -NorthWest = 7 \ No newline at end of file +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 diff --git a/modules/game_bot/functions/player.lua b/modules/game_bot/functions/player.lua index f7a89f3..e4cb3cb 100644 --- a/modules/game_bot/functions/player.lua +++ b/modules/game_bot/functions/player.lua @@ -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 diff --git a/modules/game_bot/functions/script_loader.lua b/modules/game_bot/functions/script_loader.lua new file mode 100644 index 0000000..346b948 --- /dev/null +++ b/modules/game_bot/functions/script_loader.lua @@ -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 diff --git a/modules/game_bot/functions/tools.lua b/modules/game_bot/functions/tools.lua index 9c121b0..dda3cf4 100644 --- a/modules/game_bot/functions/tools.lua +++ b/modules/game_bot/functions/tools.lua @@ -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 \ No newline at end of file diff --git a/modules/game_bot/functions/ui.lua b/modules/game_bot/functions/ui.lua index 7b7c568..56f90d5 100644 --- a/modules/game_bot/functions/ui.lua +++ b/modules/game_bot/functions/ui.lua @@ -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 diff --git a/modules/game_healthinfo/healthinfo.lua b/modules/game_healthinfo/healthinfo.lua index 483d3a8..1590501 100644 --- a/modules/game_healthinfo/healthinfo.lua +++ b/modules/game_healthinfo/healthinfo.lua @@ -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 \ No newline at end of file diff --git a/modules/game_interface/gameinterface.lua b/modules/game_interface/gameinterface.lua index 6114ccd..7dde7a0 100644 --- a/modules/game_interface/gameinterface.lua +++ b/modules/game_interface/gameinterface.lua @@ -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 --[[ diff --git a/modules/game_interface/interface.otmod b/modules/game_interface/interface.otmod index a54f732..52b78b9 100644 --- a/modules/game_interface/interface.otmod +++ b/modules/game_interface/interface.otmod @@ -35,6 +35,7 @@ Module - game_itemselector - game_textedit - game_actionbar + - game_prey - game_bot @onLoad: init() @onUnload: terminate() diff --git a/modules/game_inventory/inventory.lua b/modules/game_inventory/inventory.lua index 79aa8dd..2db769c 100644 --- a/modules/game_inventory/inventory.lua +++ b/modules/game_inventory/inventory.lua @@ -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 diff --git a/modules/game_prey/prey.lua b/modules/game_prey/prey.lua new file mode 100644 index 0000000..dd90440 --- /dev/null +++ b/modules/game_prey/prey.lua @@ -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 \ No newline at end of file diff --git a/modules/game_prey/prey.otmod b/modules/game_prey/prey.otmod new file mode 100644 index 0000000..99808da --- /dev/null +++ b/modules/game_prey/prey.otmod @@ -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() diff --git a/modules/game_prey/prey.otui b/modules/game_prey/prey.otui new file mode 100644 index 0000000..ddd262d --- /dev/null +++ b/modules/game_prey/prey.otui @@ -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() \ No newline at end of file diff --git a/modules/game_shop/shop.lua b/modules/game_shop/shop.lua index 2b0dc83..a63e134 100644 --- a/modules/game_shop/shop.lua +++ b/modules/game_shop/shop.lua @@ -320,7 +320,6 @@ function processMessage(data) msgWindow:show() msgWindow:raise() msgWindow:focus() - msgWindow:raise() end function processStatus(data) diff --git a/modules/game_shop/shop.otui b/modules/game_shop/shop.otui index e70bd41..b6349f7 100644 --- a/modules/game_shop/shop.otui +++ b/modules/game_shop/shop.otui @@ -116,7 +116,7 @@ ShopOfferCreature < ShopOffer margin-top: 4 margin-bottom: 4 margin-left: 2 - size: 48 48 + size: 64 64 ShopOfferImage < ShopOffer Label diff --git a/modules/game_skills/skills.lua b/modules/game_skills/skills.lua index e09f59b..3c54cc0 100644 --- a/modules/game_skills/skills.lua +++ b/modules/game_skills/skills.lua @@ -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) diff --git a/modules/gamelib/market.lua b/modules/gamelib/market.lua index c1764b3..6c816f6 100644 --- a/modules/gamelib/market.lua +++ b/modules/gamelib/market.lua @@ -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) diff --git a/otclient_dx.exe b/otclient_dx.exe index 56e7d8b..99e9a56 100644 Binary files a/otclient_dx.exe and b/otclient_dx.exe differ diff --git a/otclient_gl.exe b/otclient_gl.exe index 1f0870f..9ffaf89 100644 Binary files a/otclient_gl.exe and b/otclient_gl.exe differ diff --git a/otclient_linux b/otclient_linux index cb50ef2..6deb95f 100644 Binary files a/otclient_linux and b/otclient_linux differ diff --git a/pdb/otclient_dx.zip b/pdb/otclient_dx.zip index 7862e17..bc401f8 100644 Binary files a/pdb/otclient_dx.zip and b/pdb/otclient_dx.zip differ diff --git a/pdb/otclient_gl.zip b/pdb/otclient_gl.zip index e5f59c1..eed2615 100644 Binary files a/pdb/otclient_gl.zip and b/pdb/otclient_gl.zip differ