Version 2.2.1 - updated market, text editor, bot

This commit is contained in:
OTCv8 2020-04-02 06:47:02 +02:00
parent 932165111d
commit ed8162a9d5
20 changed files with 263 additions and 163 deletions

View File

@ -23,7 +23,7 @@ ComboBoxPopupMenuButton < UIButton
height: 23 height: 23
font: verdana-11px-antialised font: verdana-11px-antialised
text-align: left text-align: left
text-offset: 4 0 text-offset: 5 2
color: #dfdfdf color: #dfdfdf
background-color: alpha background-color: alpha
margin: 1 margin: 1
@ -44,7 +44,7 @@ ComboBox < UIComboBox
font: verdana-11px-antialised font: verdana-11px-antialised
color: #dfdfdf color: #dfdfdf
size: 91 23 size: 91 23
text-offset: 3 0 text-offset: 5 2
text-align: left text-align: left
image-source: /images/ui/combobox_square image-source: /images/ui/combobox_square
image-border: 3 image-border: 3
@ -65,7 +65,7 @@ ComboBoxRoundedPopupScrollMenuButton < UIButton
height: 23 height: 23
font: verdana-11px-antialised font: verdana-11px-antialised
text-align: left text-align: left
text-offset: 4 0 text-offset: 5 2
color: #dfdfdf color: #dfdfdf
background-color: alpha background-color: alpha
@ -85,7 +85,7 @@ ComboBoxRoundedPopupMenuButton < UIButton
height: 23 height: 23
font: verdana-11px-antialised font: verdana-11px-antialised
text-align: left text-align: left
text-offset: 4 0 text-offset: 5 2
color: #dfdfdf color: #dfdfdf
background-color: alpha background-color: alpha

View File

@ -2,7 +2,7 @@ Window < UIWindow
font: verdana-11px-antialised font: verdana-11px-antialised
size: 236 207 size: 236 207
opacity: 1 opacity: 1
color: #8F8F8F color: #AFAFAF
text-offset: 0 2 text-offset: 0 2
text-align: top text-align: top
image-source: /images/ui/window image-source: /images/ui/window

View File

@ -2,7 +2,7 @@ MiniWindow < UIMiniWindow
font: verdana-11px-antialised font: verdana-11px-antialised
icon-rect: 4 2 13 13 icon-rect: 4 2 13 13
icon-clip: 0 0 20 20 icon-clip: 0 0 20 20
color: #8F8F8F color: #9F9F9F
width: 190 width: 190
height: 200 height: 200
text-offset: 24 2 text-offset: 24 2

View File

@ -392,6 +392,7 @@ function EnterGame.doLogin()
g_game.setClientVersion(G.clientVersion) g_game.setClientVersion(G.clientVersion)
g_game.setProtocolVersion(g_game.getClientProtocolVersion(G.clientVersion)) g_game.setProtocolVersion(g_game.getClientProtocolVersion(G.clientVersion))
g_game.setCustomProtocolVersion(0) g_game.setCustomProtocolVersion(0)
g_game.setCustomOs(-1) -- disable
g_game.chooseRsa(G.host) g_game.chooseRsa(G.host)
if #server_params <= 3 and not g_game.getFeature(GameExtendedOpcode) then if #server_params <= 3 and not g_game.getFeature(GameExtendedOpcode) then
g_game.setCustomOs(2) -- set os to windows if opcodes are disabled g_game.setCustomOs(2) -- set os to windows if opcodes are disabled

View File

@ -1,2 +1,3 @@
BattleButton < CreatureButton BattleButton < CreatureButton
&isBattleButton: true &isBattleButton: true
optimized: true

View File

@ -366,7 +366,8 @@ function initCallbacks()
onAppear = botCreatureAppear, onAppear = botCreatureAppear,
onDisappear = botCreatureDisappear, onDisappear = botCreatureDisappear,
onPositionChange = botCreaturePositionChange, onPositionChange = botCreaturePositionChange,
onHealthPercentChange = botCraetureHealthPercentChange onHealthPercentChange = botCraetureHealthPercentChange,
onTurn = botCreatureTurn
}) })
connect(LocalPlayer, { connect(LocalPlayer, {
@ -414,7 +415,8 @@ function terminateCallbacks()
onAppear = botCreatureAppear, onAppear = botCreatureAppear,
onDisappear = botCreatureDisappear, onDisappear = botCreatureDisappear,
onPositionChange = botCreaturePositionChange, onPositionChange = botCreaturePositionChange,
onHealthPercentChange = botCraetureHealthPercentChange onHealthPercentChange = botCraetureHealthPercentChange,
onTurn = botCreatureTurn
}) })
disconnect(LocalPlayer, { disconnect(LocalPlayer, {
@ -559,3 +561,8 @@ function botChannelEvent(channelId, name, event)
if botExecutor == nil then return false end if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onChannelEvent(channelId, name, event) end) safeBotCall(function() botExecutor.callbacks.onChannelEvent(channelId, name, event) end)
end end
function botCreatureTurn(creature, direction)
if botExecutor == nil then return false end
safeBotCall(function() botExecutor.callbacks.onTurn(creature, direction) end)
end

View File

@ -59,7 +59,8 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, relo
onChannelList = {}, onChannelList = {},
onOpenChannel = {}, onOpenChannel = {},
onCloseChannel = {}, onCloseChannel = {},
onChannelEvent = {} onChannelEvent = {},
onTurn = {}
} }
-- basic functions & classes -- basic functions & classes
@ -311,6 +312,11 @@ function executeBot(config, storage, tabs, msgCallback, saveConfigCallback, relo
callback(channelId, name, event) callback(channelId, name, event)
end end
end, end,
onTurn = function(creature, direction)
for i, callback in ipairs(context._callbacks.onTurn) do
callback(creature, direction)
end
end,
} }
} }
end end

View File

@ -146,6 +146,10 @@ context.onChannelEvent = function(callback)
return context.callback("onChannelEvent", callback) return context.callback("onChannelEvent", callback)
end end
-- onTurn -- callback = function(creature, direction)
context.onTurn = function(callback)
return context.callback("onTurn", callback)
end
-- CUSTOM CALLBACKS -- CUSTOM CALLBACKS

View File

@ -166,7 +166,7 @@ Config.setup = function(dir, widget, configExtension, callback)
end end
widget.add.onClick = function() widget.add.onClick = function()
context.UI.SinglelineEditorWindow("config_name", function(name) context.UI.SinglelineEditorWindow("config_name", {title="Enter config name"}, function(name)
name = name:gsub("%s+", "_") name = name:gsub("%s+", "_")
if name:len() == 0 or name:len() >= 30 or name:find("/") or name:find("\\") then if name:len() == 0 or name:len() >= 30 or name:find("/") or name:find("\\") then
return context.error("Invalid config name") return context.error("Invalid config name")
@ -185,8 +185,7 @@ Config.setup = function(dir, widget, configExtension, callback)
widget.edit.onClick = function() widget.edit.onClick = function()
local name = context.storage._configs[dir].selected local name = context.storage._configs[dir].selected
if not name then return end if not name then return end
context.UI.MultilineEditorWindow("Config editor - " .. name .. " in " .. dir, context.UI.MultilineEditorWindow(Config.loadRaw(dir, name), {title="Config editor - " .. name .. " in " .. dir}, function(newValue)
Config.loadRaw(dir, name), function(newValue)
local data = Config.parse(newValue) local data = Config.parse(newValue)
Config.save(dir, name, data, configExtension) Config.save(dir, name, data, configExtension)
refresh() refresh()

View File

@ -4,12 +4,31 @@ if type(context.UI) ~= "table" then
end end
local UI = context.UI local UI = context.UI
UI.SinglelineEditorWindow = function(text, callback) UI.EditorWindow = function(text, options, callback)
return modules.game_textedit.singlelineEditor(text, callback) --[[
Available options:
title = text
description = text
multiline = true / false
width = number
validation = text (regex)
examples = {{name, text}, {name, text}}
]]--
local window = modules.game_textedit.edit(text, options, callback)
window.botWidget = true
return window
end end
UI.MultilineEditorWindow = function(description, test, callback) UI.SinglelineEditorWindow = function(text, options, callback)
return modules.game_textedit.multilineEditor(description, test, callback) options = options or {}
options.multiline = false
return UI.EditorWindow(text, options, callback)
end
UI.MultilineEditorWindow = function(text, options, callback)
options = options or {}
options.multiline = true
return UI.EditorWindow(text, options, callback)
end end
UI.ConfirmationWindow = function(title, question, callback) UI.ConfirmationWindow = function(title, question, callback)

View File

@ -29,7 +29,7 @@ BotConfig < Panel
anchors.top: prev.bottom anchors.top: prev.bottom
anchors.left: parent.left anchors.left: parent.left
text: Add text: Add
width: 59 width: 56
height: 20 height: 20
Button Button
@ -37,7 +37,7 @@ BotConfig < Panel
anchors.top: prev.top anchors.top: prev.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text: Edit text: Edit
width: 59 width: 56
height: 20 height: 20
Button Button
@ -45,5 +45,5 @@ BotConfig < Panel
anchors.top: prev.top anchors.top: prev.top
anchors.right: parent.right anchors.right: parent.right
text: Remove text: Remove
width: 59 width: 56
height: 20 height: 20

View File

@ -22,6 +22,7 @@ BotIcon < UIWidget
margin-top: 0 margin-top: 0
size: 48 48 size: 48 48
phantom: true phantom: true
optimized: true
UIWidget UIWidget
id: status id: status

View File

@ -78,6 +78,7 @@ currentItems = {}
lastCreatedOffer = 0 lastCreatedOffer = 0
fee = 0 fee = 0
averagePrice = 0 averagePrice = 0
tibiaCoins = 0
loaded = false loaded = false
@ -198,8 +199,8 @@ local function addOffer(offer, offerType)
if offer.var == MarketRequest.MyOffers then if offer.var == MarketRequest.MyOffers then
row = buyMyOfferTable:addRow({ row = buyMyOfferTable:addRow({
{text = itemName}, {text = itemName},
{text = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = price}, {text = comma_value(price), sortvalue = price},
{text = amount}, {text = amount},
{text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp} {text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp}
}) })
@ -207,8 +208,8 @@ local function addOffer(offer, offerType)
row = buyOfferTable:addRow({ row = buyOfferTable:addRow({
{text = player}, {text = player},
{text = amount}, {text = amount},
{text = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = price}, {text = comma_value(price), sortvalue = price},
{text = string.gsub(os.date('%c', timestamp), " ", " ")} {text = string.gsub(os.date('%c', timestamp), " ", " ")}
}) })
end end
@ -227,8 +228,8 @@ local function addOffer(offer, offerType)
if offer.var == MarketRequest.MyOffers then if offer.var == MarketRequest.MyOffers then
row = sellMyOfferTable:addRow({ row = sellMyOfferTable:addRow({
{text = itemName}, {text = itemName},
{text = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = price}, {text = comma_value(price), sortvalue = price},
{text = amount}, {text = amount},
{text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp} {text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp}
}) })
@ -236,8 +237,8 @@ local function addOffer(offer, offerType)
row = sellOfferTable:addRow({ row = sellOfferTable:addRow({
{text = player}, {text = player},
{text = amount}, {text = amount},
{text = price*amount}, {text = comma_value(price*amount), sortvalue = price*amount},
{text = price}, {text = comma_value(price), sortvalue = price},
{text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp} {text = string.gsub(os.date('%c', timestamp), " ", " "), sortvalue = timestamp}
}) })
end end
@ -462,7 +463,7 @@ local function updateBalance(balance)
if balance < 0 then balance = 0 end if balance < 0 then balance = 0 end
information.balance = balance information.balance = balance
balanceLabel:setText('Balance: '..balance..' gold') balanceLabel:setText('Balance: '.. comma_value(balance) ..' gold')
balanceLabel:resizeToText() balanceLabel:resizeToText()
end end
@ -473,7 +474,7 @@ local function updateFee(price, amount)
elseif fee > 1000 then elseif fee > 1000 then
fee = 1000 fee = 1000
end end
feeLabel:setText('Fee: '..fee) feeLabel:setText('Fee: '.. comma_value(fee))
feeLabel:resizeToText() feeLabel:resizeToText()
end end
@ -521,11 +522,11 @@ local function openAmountWindow(callback, actionType, actionText)
itembox:setItemId(item:getId()) itembox:setItemId(item:getId())
local scrollbar = amountWindow:getChildById('amountScrollBar') local scrollbar = amountWindow:getChildById('amountScrollBar')
scrollbar:setText(offer:getPrice()..'gp') scrollbar:setText(comma_value(offer:getPrice()) ..'gp')
scrollbar.onValueChange = function(widget, value) scrollbar.onValueChange = function(widget, value)
widget:setText((value*offer:getPrice())..'gp') widget:setText(comma_value(value*offer:getPrice())..'gp')
itembox:setText(value) itembox:setText(comma_value(value))
end end
scrollbar:setRange(1, maximum) scrollbar:setRange(1, maximum)
scrollbar:setValue(1) scrollbar:setValue(1)
@ -770,7 +771,7 @@ local function initInterface()
-- setup 'My Offer' section tabs -- setup 'My Offer' section tabs
myOffersPanel = g_ui.loadUI('ui/myoffers') myOffersPanel = g_ui.loadUI('ui/myoffers')
mainTabBar:addTab(tr('My Offers'), myOffersPanel) local myOffersTab = mainTabBar:addTab(tr('My Offers'), myOffersPanel)
offersTabBar = myOffersPanel:getChildById('offersTabBar') offersTabBar = myOffersPanel:getChildById('offersTabBar')
offersTabBar:setContentWidget(myOffersPanel:getChildById('offersTabContent')) offersTabBar:setContentWidget(myOffersPanel:getChildById('offersTabContent'))
@ -783,6 +784,12 @@ local function initInterface()
balanceLabel = marketWindow:getChildById('balanceLabel') balanceLabel = marketWindow:getChildById('balanceLabel')
mainTabBar.onTabChange = function(widget, tab)
if tab == myOffersTab then
Market.refreshMyOffers()
end
end
-- setup offers -- setup offers
buyButton = itemOffersPanel:getChildById('buyButton') buyButton = itemOffersPanel:getChildById('buyButton')
buyButton.onClick = function() openAmountWindow(Market.acceptMarketOffer, MarketAction.Buy, 'Buy') end buyButton.onClick = function() openAmountWindow(Market.acceptMarketOffer, MarketAction.Buy, 'Buy') end
@ -889,6 +896,8 @@ function init()
connect(g_game, { onGameEnd = Market.reset }) connect(g_game, { onGameEnd = Market.reset })
connect(g_game, { onGameEnd = Market.close }) connect(g_game, { onGameEnd = Market.close })
connect(g_game, { onGameStart = Market.updateCategories }) connect(g_game, { onGameStart = Market.updateCategories })
connect(g_game, { onCoinBalance = Market.onCoinBalance })
marketWindow = g_ui.createWidget('MarketWindow', rootWidget) marketWindow = g_ui.createWidget('MarketWindow', rootWidget)
marketWindow:hide() marketWindow:hide()
@ -904,6 +913,7 @@ function terminate()
disconnect(g_game, { onGameEnd = Market.reset }) disconnect(g_game, { onGameEnd = Market.reset })
disconnect(g_game, { onGameEnd = Market.close }) disconnect(g_game, { onGameEnd = Market.close })
disconnect(g_game, { onGameStart = Market.updateCategories }) disconnect(g_game, { onGameStart = Market.updateCategories })
disconnect(g_game, { onCoinBalance = Market.onCoinBalance })
destroyAmountWindow() destroyAmountWindow()
marketWindow:destroy() marketWindow:destroy()
@ -1076,7 +1086,7 @@ function Market.refreshItemsWidget(selectItem)
local amount = Market.getDepotCount(item.marketData.tradeAs) local amount = Market.getDepotCount(item.marketData.tradeAs)
if amount > 0 then if amount > 0 then
itemWidget:setText(amount) itemWidget:setText(comma_value(amount))
itemBox:setTooltip('You have '.. amount ..' in your depot.') itemBox:setTooltip('You have '.. amount ..' in your depot.')
end end
@ -1116,7 +1126,7 @@ function Market.loadMarketItems(category)
end end
end end
if not marketItems[category] then if not marketItems[category] and category ~= MarketCategory.All then
return return
end end
@ -1253,6 +1263,11 @@ function Market.onMarketEnter(depotItems, offers, balance, vocation)
-- set list of depot items -- set list of depot items
information.depotItems = depotItems information.depotItems = depotItems
for i = 1, #marketItems[MarketCategory.TibiaCoins] do
local item = marketItems[MarketCategory.TibiaCoins][i].displayItem
depotItems[item:getId()] = tibiaCoins
end
-- update the items widget to match depot items -- update the items widget to match depot items
if Market.isItemSelected() then if Market.isItemSelected() then
local spriteId = selectedItem.item.marketData.tradeAs local spriteId = selectedItem.item.marketData.tradeAs
@ -1284,3 +1299,12 @@ end
function Market.onMarketBrowse(offers) function Market.onMarketBrowse(offers)
updateOffers(offers) updateOffers(offers)
end end
function Market.onCoinBalance(coins, transferableCoins)
tibiaCoins = coins
if not marketItems[MarketCategory.TibiaCoins] then return end
for i = 1, #marketItems[MarketCategory.TibiaCoins] do
local item = marketItems[MarketCategory.TibiaCoins][i].displayItem
depotItems[item:getId()] = tibiaCoins
end
end

View File

@ -19,96 +19,135 @@ function destroyWindow()
end end
end end
function show(widget) -- also works as show(text, callback)
if not widget then function show(text, options, callback) -- callback = function(newText)
return --[[
Available options:
title = text
description = text
multiline = true / false
width = number
validation = text (regex)
examples = {{name, text}, {name, text}}
]]--
if type(text) == 'userdata' then
local widget = text
callback = function(newText)
widget:setText(newText)
end
text = widget:getText()
elseif type(text) == 'number' then
text = tostring(text)
elseif type(text) == 'nil' then
text = ''
elseif type(text) ~= 'string' then
return error("Invalid text type for game_textedit: " .. type(text))
end end
if type(options) == 'function' then
local tmp = callback
callback = options
options = callback
end
options = options or {}
if activeWindow then if activeWindow then
destroyWindow() destroyWindow()
end end
local window = g_ui.createWidget('TextEditWindow', rootWidget)
local window
if options.multiline then
window = g_ui.createWidget('MultilineTextEditWindow', rootWidget)
window.text = window.textPanel.text
else
window = g_ui.createWidget('SinglelineTextEditWindow', rootWidget)
end
-- functions
local validate = function(text)
if type(options.validation) ~= 'string' or options.validation:len() == 0 then
return true
end
return #regexMatch(text, options.validation) == 1
end
local destroy = function() local destroy = function()
window:destroy() window:destroy()
if window == activeWindow then
activeWindow = nil
end
end end
local doneFunc = function() local doneFunc = function()
widget:setText(window.text:getText()) local text = window.text:getText()
if not validate(text) then return end
destroy() destroy()
if callback then
callback(text)
end
end end
window.okButton.onClick = doneFunc window.buttons.ok.onClick = doneFunc
window.cancelButton.onClick = destroy window.buttons.cancel.onClick = destroy
window.onEnter = doneFunc if not options.multiline then
window.onEnter = doneFunc
end
window.onEscape = destroy window.onEscape = destroy
window.onDestroy = function()
window.text:setText(widget:getText())
activeWindow = window
activeWindow:raise()
activeWindow:focus()
end
function singlelineEditor(text, callback)
if activeWindow then
destroyWindow()
end
local window = g_ui.createWidget('TextEditWindow', rootWidget)
local destroy = function()
window:destroy()
if window == activeWindow then if window == activeWindow then
activeWindow = nil activeWindow = nil
end end
end end
window.okButton.onClick = function() if options.title then
local text = window.text:getText() window:setText(options.title)
destroy()
callback(text)
end end
window.cancelButton.onClick = destroy if options.description then
window.onEscape = destroy window.description:show()
window.onEnter = window.okButton.onClick window.description:setText(options.description)
window.text:setText(text)
activeWindow = window
activeWindow:raise()
activeWindow:focus()
end
function multilineEditor(description, text, callback)
if activeWindow then
destroyWindow()
end end
local window = g_ui.createWidget('TextEditMultilineWindow', rootWidget) if type(options.examples) == 'table' and #options.examples > 0 then
window.examples:show()
local destroy = function() for i, title_text in ipairs(options.examples) do
window:destroy() window.examples:addOption(title_text[1], title_text[2])
if window == activeWindow then end
activeWindow = nil window.examples.onOptionChange = function(widget, option, data)
window.text:setText(data)
window.text:setCursorPos(-1)
end
end
if type(options.validation) == 'string' and options.validation:len() > 0 then
window.buttons.ok:disable()
window.text.onTextChange = function(widget, text)
if validate(text) then
window.buttons.ok:enable()
else
window.buttons.ok:disable()
end
end end
end end
window.okButton.onClick = function()
local text = window.text:getText()
destroy()
callback(text)
end
window.cancelButton.onClick = destroy
window.onEscape = destroy
window.description:setText(description)
window.text:setText(text) window.text:setText(text)
window.text:setCursorPos(-1)
if type(options.width) == 'number' then
window:setWidth(options.width)
end
activeWindow = window activeWindow = window
activeWindow:raise() activeWindow:raise()
activeWindow:focus() activeWindow:focus()
return activeWindow
end end
function hide() function hide()
destroyWindow() destroyWindow()
end end
function edit(...)
return show(...)
end
-- legacy
function singlelineEditor(text, callback)
return show(text, {}, callback)
end
-- legacy
function multilineEditor(description, text, callback)
return show(text, {description=description, multiline=true}, callback)
end

View File

@ -1,16 +1,9 @@
TextEditWindow < MainWindow TextEditButtons < Panel
id: textedit id: buttons
size: 260 105 height: 30
!text: tr("Edit text")
TextEdit
id: text
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
Button Button
id: okButton id: ok
!text: tr('Ok') !text: tr('Ok')
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: next.left anchors.right: next.left
@ -18,56 +11,62 @@ TextEditWindow < MainWindow
width: 60 width: 60
Button Button
id: cancelButton id: cancel
!text: tr('Cancel') !text: tr('Cancel')
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.right: parent.right anchors.right: parent.right
width: 60 width: 60
TextEditMultilineWindow < MainWindow TextEditWindow < MainWindow
id: texteditmultiline id: textedit
size: 650 497
!text: tr("Edit text") !text: tr("Edit text")
layout:
type: verticalBox
fit-children: true
Label Label
id: description id: description
anchors.top: parent.top
anchors.left: parent.left
anchors.right: parent.right
text-auto-resize: true
text-align: center text-align: center
text: description
margin-bottom: 5
visible: false
text-wrap: true text-wrap: true
text-auto-resize: true
MultilineTextEdit ComboBox
id: examples
margin-bottom: 5
visible: false
SinglelineTextEditWindow < TextEditWindow
width: 250
TextEdit
id: text id: text
anchors.top: textScroll.top
anchors.left: parent.left
anchors.right: textScroll.left
anchors.bottom: textScroll.bottom
vertical-scrollbar: textScroll
text-wrap: true
VerticalScrollBar TextEditButtons
id: textScroll
anchors.top: description.bottom
anchors.bottom: okButton.top
anchors.right: parent.right
margin-bottom: 10
step: 16
pixels-scroll: true
Button MultilineTextEditWindow < TextEditWindow
id: okButton width: 600
!text: tr('Ok')
anchors.bottom: parent.bottom
anchors.right: next.left
margin-right: 10
width: 60
Button Panel
id: cancelButton id: textPanel
!text: tr('Cancel') height: 400
anchors.bottom: parent.bottom
anchors.right: parent.right MultilineTextEdit
width: 60 id: text
anchors.fill: parent
margin-right: 12
text-wrap: true
vertical-scrollbar: textScroll
VerticalScrollBar
id: textScroll
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
pixels-scroll: true
step: 10
TextEditButtons

View File

@ -350,7 +350,7 @@ function walk(dir, ticks)
return return
end end
if dash and lastWalkDir == dir and lastWalk + 30 > g_clock.millis() then if dash and lastWalkDir == dir and lastWalk + 50 > g_clock.millis() then
return return
end end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.