Version 2.0 - preys, bot updates, ui improvements

This commit is contained in:
OTCv8 2020-01-31 18:01:42 +01:00
parent 48d7eb810d
commit 6bc4188d7a
40 changed files with 737 additions and 72 deletions

View File

@ -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

View File

@ -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";
?>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -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

View File

@ -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

View File

@ -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")

View File

@ -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
-- @}

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View 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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
--[[

View File

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

View File

@ -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
View 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

View 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
View 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()

View File

@ -320,7 +320,6 @@ function processMessage(data)
msgWindow:show()
msgWindow:raise()
msgWindow:focus()
msgWindow:raise()
end
function processStatus(data)

View File

@ -116,7 +116,7 @@ ShopOfferCreature < ShopOffer
margin-top: 4
margin-bottom: 4
margin-left: 2
size: 48 48
size: 64 64
ShopOfferImage < ShopOffer
Label

View File

@ -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)

View File

@ -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)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.