Added keypad, fixed one crash bug and few more features for mobile version

This commit is contained in:
OTCv8 2020-06-12 17:58:54 +02:00
parent 8391355c42
commit 82018bf3c9
23 changed files with 294 additions and 36 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -1,17 +1,33 @@
local overlay
local keypad
local touchStart = 0
local updateCursorEvent = nil
local updateCursorEvent
local zoomInButton
local zoomOutButton
local keypadButton
local keypadEvent
local keypadMousePos = {x=0.5, y=0.5}
local keypadTicks = 0
-- public functions
function init()
if not g_app.isMobile() then return end
overlay = g_ui.displayUI('mobile')
keypad = overlay.keypad
overlay:raise()
zoomInButton = modules.client_topmenu.addLeftButton('zoomInButton', 'Zoom In', '/images/topbuttons/zoomin', function() g_app.scaleUp() end)
zoomOutButton = modules.client_topmenu.addLeftButton('zoomOutButton', 'Zoom Out', '/images/topbuttons/zoomout', function() g_app.scaleDown() end)
keypadButton = modules.client_topmenu.addLeftGameToggleButton('keypadButton', 'Keypad', '/images/topbuttons/keypad', function()
keypadButton:setChecked(not keypadButton:isChecked())
if not g_game.isOnline() then
keypad:setVisible(false)
return
end
keypad:setVisible(keypadButton:isChecked())
end)
keypadButton:setChecked(true)
scheduleEvent(function()
g_app.scale(5.0)
end, 10)
@ -23,10 +39,25 @@ function init()
onTouchRelease = onMouseRelease,
onMouseMove = onMouseMove
})
connect(keypad, {
onTouchPress = onKeypadTouchPress,
onTouchRelease = onKeypadTouchRelease,
onMouseMove = onKeypadTouchMove
})
connect(g_game, {
onGameStart = online,
onGameEnd = offline
})
if g_game.isOnline() then
online()
end
end
function terminate()
if not g_app.isMobile() then return end
removeEvent(updateCursorEvent)
removeEvent(keypadEvent)
keypadEvent = nil
disconnect(overlay, {
onMousePress = onMousePress,
onMouseRelease = onMouseRelease,
@ -34,8 +65,18 @@ function terminate()
onTouchRelease = onMouseRelease,
onMouseMove = onMouseMove
})
disconnect(keypad, {
onTouchPress = onKeypadTouchPress,
onTouchRelease = onKeypadTouchRelease,
onMouseMove = onKeypadTouchMove
})
disconnect(g_game, {
onGameStart = online,
onGameEnd = offline
})
zoomInButton:destroy()
zoomOutButton:destroy()
keypadButton:destroy()
overlay:destroy()
overlay = nil
end
@ -48,13 +89,24 @@ function show()
overlay:show()
end
function online()
if keypadButton:isChecked() then
keypad:raise()
keypad:show()
end
end
function offline()
keypad:hide()
end
function onMouseMove(widget, pos, offset)
end
function onMousePress(widget, pos, button)
overlay:raise()
if button == 4 then -- touch
if button == MouseTouch then -- touch
overlay:raise()
overlay.cursor:show()
overlay.cursor:setPosition({x=pos.x - 32, y = pos.y - 32})
@ -67,12 +119,15 @@ function onMousePress(widget, pos, button)
end
function onMouseRelease(widget, pos, button)
overlay.cursor:hide()
removeEvent(updateCursorEvent)
if button == MouseTouch then
overlay.cursor:hide()
removeEvent(updateCursorEvent)
end
end
function updateCursor()
removeEvent(updateCursorEvent)
if not g_mouse.isPressed(MouseTouch) then return end
local percent = 100 - math.max(0, math.min(100, (g_clock.millis() - touchStart) / 5)) -- 500 ms
overlay.cursor:setPercent(percent)
if percent > 0 then
@ -81,4 +136,81 @@ function updateCursor()
else
overlay.cursor:setOpacity(0.8)
end
end
function onKeypadTouchMove(widget, pos, offset)
keypadMousePos = {x=(pos.x - widget:getPosition().x) / widget:getWidth(),
y=(pos.y - widget:getPosition().y) / widget:getHeight()}
return true
end
function onKeypadTouchPress(widget, pos, button)
if button ~= MouseTouch then return false end
keypadTicks = 0
keypadMousePos = {x=(pos.x - widget:getPosition().x) / widget:getWidth(),
y=(pos.y - widget:getPosition().y) / widget:getHeight()}
executeWalk()
return true
end
function onKeypadTouchRelease(widget, pos, button)
if button ~= MouseTouch then return false end
keypadMousePos = {x=(pos.x - widget:getPosition().x) / widget:getWidth(),
y=(pos.y - widget:getPosition().y) / widget:getHeight()}
executeWalk()
removeEvent(keypadEvent)
keypad.pointer:setMarginTop(0)
keypad.pointer:setMarginLeft(0)
return true
end
function executeWalk()
removeEvent(keypadEvent)
keypadEvent = nil
if not modules.game_walking or not g_mouse.isPressed(MouseTouch) then
keypad.pointer:setMarginTop(0)
keypad.pointer:setMarginLeft(0)
return
end
keypadEvent = scheduleEvent(executeWalk, 20)
keypadMousePos.x = math.min(1, math.max(0, keypadMousePos.x))
keypadMousePos.y = math.min(1, math.max(0, keypadMousePos.y))
local angle = math.atan2(keypadMousePos.x - 0.5, keypadMousePos.y - 0.5)
local maxTop = math.abs(math.cos(angle)) * 75
local marginTop = math.max(-maxTop, math.min(maxTop, (keypadMousePos.y - 0.5) * 150))
local maxLeft = math.abs(math.sin(angle)) * 75
local marginLeft = math.max(-maxLeft, math.min(maxLeft, (keypadMousePos.x - 0.5) * 150))
keypad.pointer:setMarginTop(marginTop)
keypad.pointer:setMarginLeft(marginLeft)
local dir
if keypadMousePos.y < 0.3 and keypadMousePos.x < 0.3 then
dir = Directions.NorthWest
elseif keypadMousePos.y < 0.3 and keypadMousePos.x > 0.7 then
dir = Directions.NorthEast
elseif keypadMousePos.y > 0.7 and keypadMousePos.x < 0.3 then
dir = Directions.SouthWest
elseif keypadMousePos.y > 0.7 and keypadMousePos.x > 0.7 then
dir = Directions.SouthEast
end
if not dir and (math.abs(keypadMousePos.y - 0.5) > 0.1 or math.abs(keypadMousePos.x - 0.5) > 0.1) then
if math.abs(keypadMousePos.y - 0.5) > math.abs(keypadMousePos.x - 0.5) then
if keypadMousePos.y < 0.5 then
dir = Directions.North
else
dir = Directions.South
end
else
if keypadMousePos.x < 0.5 then
dir = Directions.West
else
dir = Directions.East
end
end
end
if dir then
modules.game_walking.walk(dir, keypadTicks)
if keypadTicks == 0 then
keypadTicks = 100
end
end
end

View File

@ -13,3 +13,27 @@ UIWidget
y: 0
focusable: false
phantom: true
UIWidget
id: keypad
size: 200 150
anchors.bottom: parent.bottom
anchors.right: parent.right
phantom: false
focusable: false
visible: false
background: #00000044
image-source: /images/game/mobile/keypad
image-fixed-ratio: true
image-rect: 25 0 150 150
UIWidget
id: pointer
size: 49 49
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
image-source: /images/game/mobile/keypad_pointer
image-fixed-ratio: true
phantom: true
focusable: false

View File

@ -5,7 +5,7 @@ local defaultOptions = {
showPing = true,
fullscreen = false,
classicView = not g_app.isMobile(),
cacheMap = false,
cacheMap = g_app.isMobile(),
classicControl = not g_app.isMobile(),
smartWalk = false,
dash = false,

View File

@ -29,11 +29,12 @@ local function addButton(id, description, icon, callback, panel, toggle, front,
button:setTooltip(description)
button:setIcon(resolvepath(icon, 3))
button.onMouseRelease = function(widget, mousePos, mouseButton)
if widget:containsPoint(mousePos) and mouseButton ~= MouseMidButton then
if widget:containsPoint(mousePos) and mouseButton ~= MouseMidButton and mouseButton ~= MouseTouch then
callback()
return true
end
end
button.onTouchRelease = button.onMouseRelease
if not button.index and type(index) == 'number' then
button.index = index
end

View File

@ -36,6 +36,9 @@ MouseNoButton = 0
MouseLeftButton = 1
MouseRightButton = 2
MouseMidButton = 3
MouseTouch = 4
MouseTouch2 = 5 -- multitouch, 2nd finger
MouseTouch3 = 6 -- multitouch, 3th finger
MouseNoWheel = 0
MouseWheelUp = 1

View File

@ -15,12 +15,12 @@ ActionTypes = {
ActionColors = {
empty = '#00000033',
text = '#88888866',
itemUse = '#8888FF66',
itemUseSelf = '#00FF0066',
itemUseTarget = '#FF000066',
itemUseWith = '#F5B32566',
itemEquip = '#FFFFFF66'
text = '#00000033',
itemUse = '#8888FF88',
itemUseSelf = '#00FF0088',
itemUseTarget = '#FF000088',
itemUseWith = '#F5B32588',
itemEquip = '#FFFFFF88'
}
function init()
@ -142,6 +142,7 @@ function setupAction(action)
local config = action.config
action.item:setShowCount(false)
action.onMouseRelease = actionOnMouseRelease
action.onTouchRelease = actionOnMouseRelease
action.callback = function(k, c, ticks) executeAction(action, ticks) end
action.item.onItemChange = nil -- disable callbacks for setup
@ -165,7 +166,7 @@ function setupAction(action)
action.cooldownStart = 0
if type(config.text) == 'string' and config.text:len() > 0 then
action.text:setText(config.text)
action:setBorderColor(ActionColors.text)
action.item:setBorderColor(ActionColors.text)
action.item:setOn(true) -- removes background
action.item:setItemId(0)
if Spells then
@ -188,7 +189,7 @@ function setupAction(action)
else
action.item:setItemId(0)
action.item:setOn(false)
action:setBorderColor(ActionColors.empty)
action.item:setBorderColor(ActionColors.empty)
end
end
end
@ -212,15 +213,15 @@ function setupActionType(action, actionType)
action.config.actionType = actionType
if action.config.actionType == ActionTypes.USE then
action:setBorderColor(ActionColors.itemUse)
action.item:setBorderColor(ActionColors.itemUse)
elseif action.config.actionType == ActionTypes.USE_SELF then
action:setBorderColor(ActionColors.itemUseSelf)
action.item:setBorderColor(ActionColors.itemUseSelf)
elseif action.config.actionType == ActionTypes.USE_TARGET then
action:setBorderColor(ActionColors.itemUseTarget)
action.item:setBorderColor(ActionColors.itemUseTarget)
elseif action.config.actionType == ActionTypes.USE_WITH then
action:setBorderColor(ActionColors.itemUseWith)
action.item:setBorderColor(ActionColors.itemUseWith)
elseif action.config.actionType == ActionTypes.EQUIP then
action:setBorderColor(ActionColors.itemEquip)
action.item:setBorderColor(ActionColors.itemEquip)
end
end
@ -237,6 +238,7 @@ function updateAction(action, newConfig)
end
function actionOnMouseRelease(action, mousePosition, mouseButton)
if mouseButton == MouseTouch then return end
if mouseButton == MouseRightButton or not action.item:isOn() then
local menu = g_ui.createWidget('PopupMenu')
menu:setGameMenu(true)
@ -292,7 +294,7 @@ function actionOnMouseRelease(action, mousePosition, mouseButton)
end)
menu:display(mousePosition)
return true
elseif mouseButton == MouseLeftButton then
elseif mouseButton == MouseLeftButton or mouseButton == MouseTouch2 or mouseButton == MouseTouch3 then
action.callback()
return true
end

View File

@ -1,10 +1,10 @@
ActionButton < Panel
size: 36 36
font: cipsoftFont
anchors.top: parent.top
margin-left: 3
border-width: 1
border-color: #00000022
anchors.bottom: parent.bottom
width: 40
padding: 1 1 1 1
margin-left: 1
$first:
anchors.left: parent.left
@ -15,18 +15,19 @@ ActionButton < Panel
Item
id: item
anchors.fill: parent
margin: 1 1 1 1
&selectable: true
&editable: false
virtual: true
border-width: 1
border-color: #00000000
$!on:
image-source: /images/game/actionbarslot
Label
id: text
anchors.fill: parent
margin: 1 1 1 1
text-auto-resize: true
text-wrap: true
phantom: true
@ -85,7 +86,6 @@ Panel
anchors.left: prev.right
anchors.right: next.left
margin-right: 3
margin-top: 2
clipping: true
TabButton

View File

@ -126,7 +126,11 @@ end
function getSortType()
local settings = g_settings.getNode('BattleList')
if not settings then
return 'name'
if g_app.isMobile() then
return 'distance'
else
return 'name'
end
end
return settings['sortType']
end
@ -219,7 +223,7 @@ function updateBattleList()
end
function checkCreatures()
if not g_game.isOnline() then
if not battlePanel or not g_game.isOnline() then
return
end
@ -257,11 +261,17 @@ function checkCreatures()
local battleButton = battleButtons[i]
battleButton:creatureSetup(creature)
battleButton:show()
battleButton:setOn(true)
end
if g_app.isMobile() and #creatures > 0 then
onBattleButtonHoverChange(battleButtons[1], true)
end
for i=#creatures + 1,maxCreatures do
if battleButtons[i]:isHidden() then break end
battleButtons[i]:hide()
battleButton:setOn(false)
end
battlePanel:getLayout():enableUpdates()

View File

@ -66,11 +66,13 @@ MiniWindow
BattlePlayers
id: hidePlayers
!tooltip: tr('Hide players')
@onSetup: if g_app.isMobile() then self:setChecked(true) end
@onCheckChange: modules.game_battle.checkCreatures()
BattleNPCs
id: hideNPCs
!tooltip: tr('Hide Npcs')
@onSetup: if g_app.isMobile() then self:setChecked(true) end
@onCheckChange: modules.game_battle.checkCreatures()
BattleMonsters
@ -86,6 +88,7 @@ MiniWindow
BattleParty
id: hideParty
!tooltip: tr('Hide party members')
@onSetup: if g_app.isMobile() then self:setChecked(true) end
@onCheckChange: modules.game_battle.checkCreatures()
Panel

View File

@ -14,7 +14,7 @@ UI.Button("Discord", function()
end)
UI.Button("Forum", function()
g_platform.openUrl("http://otclient.net")
g_platform.openUrl("http://otclient.net/")
end)
UI.Button("Help & Tutorials", function()

View File

@ -25,7 +25,7 @@ function setupExtraHotkeys(combobox)
local nextChild = nil
local breakNext = false
for i, child in ipairs(battlePanel:getChildren()) do
if not child.creature or child:isDisabled() then
if not child.creature or not child:isOn() then
break
end
nextChild = child
@ -53,7 +53,7 @@ function setupExtraHotkeys(combobox)
local attackedCreature = g_game.getAttackingCreature()
local prevChild = nil
for i, child in ipairs(battlePanel:getChildren()) do
if not child.creature or child:isDisabled() or child:isHidden() then
if not child.creature or not child:isOn() then
break
end
if child.creature == attackedCreature then

View File

@ -40,6 +40,7 @@ function init()
mouseGrabberWidget = gameRootPanel:getChildById('mouseGrabber')
mouseGrabberWidget.onMouseRelease = onMouseGrabberRelease
mouseGrabberWidget.onTouchRelease = mouseGrabberWidget.onMouseRelease
bottomSplitter = gameRootPanel:getChildById('bottomSplitter')
gameMapPanel = gameRootPanel:getChildById('gameMapPanel')
@ -267,6 +268,7 @@ function updateStretchShrink()
end
function onMouseGrabberRelease(self, mousePosition, mouseButton)
if mouseButton == MouseTouch then return end
if selectedThing == nil then return false end
if mouseButton == MouseLeftButton then
local clickedWidget = gameRootPanel:recursiveGetChildByPos(mousePosition, false)
@ -575,7 +577,7 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
createThingMenu(menuPosition, lookThing, useThing, creatureThing)
return true
end
if mouseButton ~= MouseLeftButton then
if mouseButton ~= MouseLeftButton and mouseButton ~= MouseTouch2 and mouseButton ~= MouseTouch3 then
return false
end
local action = getLeftAction()
@ -707,7 +709,7 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
local player = g_game.getLocalPlayer()
player:stopAutoWalk()
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and (mouseButton == MouseLeftButton or mouseButton == MouseTouch2 or mouseButton == MouseTouch3) then
local autoWalkTile = g_map.getTile(autoWalkPos)
if autoWalkTile and not autoWalkTile:isWalkable(true) then
modules.game_textmessage.displayFailureMessage(tr('Sorry, not possible.'))
@ -1056,15 +1058,85 @@ function setupLeftActions()
if not g_app.isMobile() then return end
for _, widget in ipairs(gameLeftActions:getChildren()) do
widget.image:setChecked(false)
widget.lastClicked = 0
widget.onClick = function()
if widget.image:isChecked() then
widget.image:setChecked(false)
if widget.doubleClickAction and widget.lastClicked + 200 > g_clock.millis() then
widget.doubleClickAction()
end
return
end
resetLeftActions()
widget.image:setChecked(true)
widget.lastClicked = g_clock.millis()
end
end
if gameLeftActions.use then
gameLeftActions.use.doubleClickAction = function()
local player = g_game.getLocalPlayer()
local dir = player:getDirection()
local usePos = player:getPrewalkingPosition(true)
if dir == North then
usePos.y = usePos.y - 1
elseif dir == East then
usePos.x = usePos.x + 1
elseif dir == South then
usePos.y = usePos.y + 1
elseif dir == West then
usePos.x = usePos.x - 1
end
local tile = g_map.getTile(usePos)
if not tile then return end
local thing = tile:getTopUseThing()
if thing then
g_game.use(thing)
end
end
end
if gameLeftActions.attack then
gameLeftActions.attack.doubleClickAction = function()
local battlePanel = modules.game_battle.battlePanel
local attackedCreature = g_game.getAttackingCreature()
local child = battlePanel:getFirstChild()
if child and (not child.creature or not child:isOn()) then
child = nil
end
if child then
g_game.attack(child.creature)
else
g_game.attack(nil)
end
end
end
if gameLeftActions.follow then
gameLeftActions.follow.doubleClickAction = function()
local battlePanel = modules.game_battle.battlePanel
local attackedCreature = g_game.getAttackingCreature()
local child = battlePanel:getFirstChild()
if child and (not child.creature or not child:isOn()) then
child = nil
end
if child then
g_game.follow(child.creature)
else
g_game.follow(nil)
end
end
end
if gameLeftActions.look then
gameLeftActions.look.doubleClickAction = function()
local battlePanel = modules.game_battle.battlePanel
local attackedCreature = g_game.getAttackingCreature()
local child = battlePanel:getFirstChild()
if child and (not child.creature or child:isHidden()) then
child = nil
end
if child then
g_game.look(child.creature)
end
end
end
if not gameLeftActions.chat then return end
gameLeftActions.chat.onClick = function()
if gameBottomPanel:getHeight() <= 5 then
@ -1078,6 +1150,7 @@ end
function resetLeftActions()
for _, widget in ipairs(gameLeftActions:getChildren()) do
widget.image:setChecked(false)
widget.lastClicked = 0
end
end

View File

@ -172,6 +172,12 @@ function UIGameMap:onMouseRelease(mousePosition, mouseButton)
return ret
end
function UIGameMap:onTouchRelease(mousePosition, mouseButton)
if mouseButton ~= MouseTouch then
return self:onMouseRelease(mousePosition, mouseButton)
end
end
function UIGameMap:canAcceptDrop(widget, mousePos)
if not widget or not widget.currentDragThing then return false end

View File

@ -379,6 +379,9 @@ function walk(dir, ticks)
player:lockWalk(100) -- bug fix for missing stairs down on map
return
else
if g_app.isMobile() and dir <= Directions.West then
turn(dir, ticks > 0)
end
return -- not walkable tile
end
end

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
run_android.bat Normal file
View File

@ -0,0 +1 @@
adb uninstall com.otclientv8 && adb install otclientv8.apk && adb logcat -c && adb shell am start -n com.otclientv8/com.otclientv8.OTClientV8 && adb logcat | findstr /i otclient