420 lines
12 KiB
Lua
420 lines
12 KiB
Lua
DEFAULT_ZOOM = 60
|
|
MAX_FLOOR_UP = 0
|
|
MAX_FLOOR_DOWN = 15
|
|
|
|
navigating = false
|
|
minimapWidget = nil
|
|
minimapButton = nil
|
|
minimapWindow = nil
|
|
|
|
flagsPanel = nil
|
|
flagWindow = nil
|
|
nextFlagId = 0
|
|
--[[
|
|
Known Issue (TODO):
|
|
If you move the minimap compass directions and
|
|
you change floor it will not update the minimap.
|
|
]]
|
|
function init()
|
|
g_ui.importStyle('flagwindow.otui')
|
|
|
|
connect(g_game, {
|
|
onGameStart = online,
|
|
onGameEnd = offline,
|
|
onAutomapFlag = addMapFlag
|
|
})
|
|
connect(LocalPlayer, { onPositionChange = center })
|
|
|
|
g_keyboard.bindKeyDown('Ctrl+M', toggle)
|
|
|
|
minimapButton = TopMenu.addRightGameToggleButton('minimapButton', tr('Minimap') .. ' (Ctrl+M)', 'minimap.png', toggle)
|
|
minimapButton:setOn(true)
|
|
|
|
minimapWindow = g_ui.loadUI('minimap.otui', modules.game_interface.getRightPanel())
|
|
minimapWindow:setContentMinimumHeight(64)
|
|
minimapWindow:setContentMaximumHeight(256)
|
|
|
|
minimapWidget = minimapWindow:recursiveGetChildById('minimap')
|
|
g_mouse.bindAutoPress(minimapWidget, compassClick, nil, MouseLeftButton)
|
|
|
|
minimapWidget:setAutoViewMode(false)
|
|
minimapWidget:setViewMode(1) -- mid view
|
|
minimapWidget:setDrawMinimapColors(true)
|
|
minimapWidget:setMultifloor(false)
|
|
minimapWidget:setKeepAspectRatio(false)
|
|
minimapWidget.onMouseRelease = onMinimapMouseRelease
|
|
minimapWidget.onMouseWheel = onMinimapMouseWheel
|
|
flagsPanel = minimapWindow:recursiveGetChildById('flagsPanel')
|
|
|
|
reset()
|
|
minimapWindow:setup()
|
|
loadMapFlags()
|
|
|
|
if g_game.isOnline() then
|
|
addEvent(function() updateMapFlags() end)
|
|
end
|
|
end
|
|
|
|
function terminate()
|
|
disconnect(g_game, {
|
|
onGameStart = online,
|
|
onGameEnd = offline,
|
|
onAutomapFlag = addMapFlag
|
|
})
|
|
disconnect(LocalPlayer, { onPositionChange = center })
|
|
|
|
destroyFlagWindow()
|
|
saveMapFlags()
|
|
if g_game.isOnline() then
|
|
saveMap()
|
|
end
|
|
|
|
g_keyboard.unbindKeyDown('Ctrl+M')
|
|
|
|
minimapButton:destroy()
|
|
minimapWindow:destroy()
|
|
end
|
|
|
|
function onFlagMousePress(widget, mousePosition, mouseButton)
|
|
if mouseButton == MouseRightButton then
|
|
local menu = g_ui.createWidget('PopupMenu')
|
|
menu:addOption(tr('Delete mark'), function()
|
|
widget:destroy()
|
|
end)
|
|
menu:display(mousePosition)
|
|
elseif mouseButton == MouseLeftButton then
|
|
minimapAutoWalk(widget.position)
|
|
end
|
|
return true
|
|
end
|
|
|
|
function destroyFlagWindow()
|
|
if flagWindow then
|
|
flagWindow:destroy()
|
|
flagWindow = nil
|
|
end
|
|
end
|
|
|
|
function showFlagDialog(position)
|
|
if flagWindow then return end
|
|
if not position then return end
|
|
flagWindow = g_ui.createWidget('FlagWindow', rootWidget)
|
|
|
|
local positionLabel = flagWindow:getChildById('position')
|
|
local description = flagWindow:getChildById('description')
|
|
local okButton = flagWindow:getChildById('okButton')
|
|
local cancelButton = flagWindow:getChildById('cancelButton')
|
|
|
|
positionLabel:setText(tr('Position: %i %i %i', position.x, position.y, position.z))
|
|
|
|
flagRadioGroup = UIRadioGroup.create()
|
|
local flagCheckbox = {}
|
|
for i = 1, 20 do
|
|
local checkbox = flagWindow:getChildById('flag' .. i)
|
|
table.insert(flagCheckbox, checkbox)
|
|
checkbox.icon = i
|
|
flagRadioGroup:addWidget(checkbox)
|
|
end
|
|
|
|
flagRadioGroup:selectWidget(flagCheckbox[1])
|
|
|
|
cancelButton.onClick = function()
|
|
flagRadioGroup:destroy()
|
|
flagRadioGroup = nil
|
|
destroyFlagWindow()
|
|
end
|
|
okButton.onClick = function()
|
|
addMapFlag(position, flagRadioGroup:getSelectedWidget().icon, description:getText())
|
|
flagRadioGroup:destroy()
|
|
flagRadioGroup = nil
|
|
destroyFlagWindow()
|
|
end
|
|
end
|
|
|
|
function loadMapFlags()
|
|
mapFlags = {}
|
|
|
|
local flagSettings = g_settings.getNode('MapFlags')
|
|
if flagSettings then
|
|
for i = 1, #flagSettings do
|
|
local flag = flagSettings[i]
|
|
addMapFlag(flag.position, flag.icon, flag.description, flag.id, flag.version)
|
|
|
|
if i == #flagSettings then
|
|
nextFlagId = flag.id + 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function saveMapFlags()
|
|
local flagSettings = {}
|
|
|
|
for i = 1, flagsPanel:getChildCount() do
|
|
local child = flagsPanel:getChildByIndex(i)
|
|
|
|
table.insert(flagSettings, { position = child.position,
|
|
icon = child.icon,
|
|
description = child.description,
|
|
id = child.id,
|
|
version = child.version })
|
|
end
|
|
|
|
g_settings.setNode('MapFlags', flagSettings)
|
|
end
|
|
|
|
function getFlagIconClip(id)
|
|
return (((id)%10)*11) .. ' ' .. ((math.ceil(id/10+0.1)-1)*11) .. ' 11 11'
|
|
end
|
|
|
|
function addMapFlag(pos, icon, message, flagId, version)
|
|
if not(icon >= 1 and icon <= 20) or not pos then
|
|
return
|
|
end
|
|
|
|
version = version or g_game.getProtocolVersion()
|
|
-- Check if flag is set for that position
|
|
for i = 1, flagsPanel:getChildCount() do
|
|
local flag = flagsPanel:getChildByIndex(i)
|
|
if flag.position.x == pos.x and flag.position.y == pos.y and flag.position.z == pos.z
|
|
and version == flag.version then
|
|
return
|
|
end
|
|
end
|
|
|
|
if not flagId then
|
|
flagId = nextFlagId
|
|
nextFlagId = nextFlagId + 1
|
|
end
|
|
|
|
local flagWidget = g_ui.createWidget('FlagWidget', flagsPanel)
|
|
flagWidget:setIconClip(getFlagIconClip(icon - 1))
|
|
flagWidget:setId('flag' .. flagId)
|
|
flagWidget.position = pos
|
|
flagWidget.icon = icon
|
|
flagWidget.description = message
|
|
if message and message:len() > 0 then
|
|
flagWidget:setTooltip(tr(message))
|
|
end
|
|
flagWidget.id = flagId
|
|
flagWidget.version = version
|
|
updateMapFlag(flagId)
|
|
flagWidget.onMousePress = onFlagMousePress
|
|
end
|
|
|
|
function getMapArea()
|
|
return minimapWidget:getPosition( { x = 1 + minimapWidget:getX(), y = 1 + minimapWidget:getY() } ),
|
|
minimapWidget:getPosition( { x = -2 + minimapWidget:getWidth() + minimapWidget:getX(), y = -2 + minimapWidget:getHeight() + minimapWidget:getY() } )
|
|
end
|
|
|
|
function isFlagVisible(flag, firstPosition, lastPosition)
|
|
return flag.version == g_game.getProtocolVersion() and (minimapWidget:getZoom() >= 30 and minimapWidget:getZoom() <= 150) and flag.position.x >= firstPosition.x and flag.position.x <= lastPosition.x and flag.position.y >= firstPosition.y and flag.position.y <= lastPosition.y and flag.position.z == firstPosition.z
|
|
end
|
|
|
|
function updateMapFlag(id)
|
|
local firstPosition, lastPosition = getMapArea()
|
|
if not firstPosition or not lastPosition then
|
|
return
|
|
end
|
|
|
|
local flag = flagsPanel:getChildById('flag' .. id)
|
|
if isFlagVisible(flag, firstPosition, lastPosition) then
|
|
flag:setVisible(true)
|
|
flag:setMarginLeft( -5 + (minimapWidget:getWidth() / (lastPosition.x - firstPosition.x)) * (flag.position.x - firstPosition.x))
|
|
flag:setMarginTop( -5 + (minimapWidget:getHeight() / (lastPosition.y - firstPosition.y)) * (flag.position.y - firstPosition.y))
|
|
else
|
|
flag:setVisible(false)
|
|
end
|
|
end
|
|
|
|
function updateMapFlags()
|
|
local firstPosition, lastPosition = getMapArea()
|
|
if not firstPosition or not lastPosition then
|
|
return
|
|
end
|
|
|
|
for i = 1, flagsPanel:getChildCount() do
|
|
local flag = flagsPanel:getChildByIndex(i)
|
|
if isFlagVisible(flag, firstPosition, lastPosition) then
|
|
flag:setVisible(true)
|
|
flag:setMarginLeft( -5 + (minimapWidget:getWidth() / (lastPosition.x - firstPosition.x)) * (flag.position.x - firstPosition.x))
|
|
flag:setMarginTop( -5 + (minimapWidget:getHeight() / (lastPosition.y - firstPosition.y)) * (flag.position.y - firstPosition.y))
|
|
else
|
|
flag:setVisible(false)
|
|
end
|
|
end
|
|
end
|
|
|
|
function online()
|
|
reset()
|
|
loadMap()
|
|
|
|
updateMapFlags()
|
|
end
|
|
|
|
function offline()
|
|
saveMap()
|
|
end
|
|
|
|
function loadMap()
|
|
local protocolVersion = g_game.getProtocolVersion()
|
|
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
|
|
if g_resources.fileExists(minimapFile) then
|
|
g_map.clean()
|
|
g_map.loadOtcm(minimapFile)
|
|
end
|
|
end
|
|
|
|
function saveMap()
|
|
local protocolVersion = g_game.getProtocolVersion()
|
|
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
|
|
g_map.saveOtcm(minimapFile)
|
|
end
|
|
|
|
function toggle()
|
|
if minimapButton:isOn() then
|
|
minimapWindow:close()
|
|
minimapButton:setOn(false)
|
|
else
|
|
minimapWindow:open()
|
|
minimapButton:setOn(true)
|
|
end
|
|
end
|
|
|
|
function isClickInRange(position, fromPosition, toPosition)
|
|
return (position.x >= fromPosition.x and position.y >= fromPosition.y and position.x <= toPosition.x and position.y <= toPosition.y)
|
|
end
|
|
|
|
function reset(zoom)
|
|
if zoom == nil then zoom = true end
|
|
local player = g_game.getLocalPlayer()
|
|
if not player then return end
|
|
minimapWidget:followCreature(player)
|
|
if zoom then
|
|
minimapWidget:setZoom(DEFAULT_ZOOM)
|
|
end
|
|
end
|
|
|
|
function center()
|
|
reset(false)
|
|
updateMapFlags()
|
|
end
|
|
|
|
function compassClick(self, mousePos, mouseButton, elapsed)
|
|
if elapsed < 300 then return end
|
|
|
|
navigating = true
|
|
local px = mousePos.x - self:getX()
|
|
local py = mousePos.y - self:getY()
|
|
local dx = px - self:getWidth()/2
|
|
local dy = -(py - self:getHeight()/2)
|
|
local radius = math.sqrt(dx*dx+dy*dy)
|
|
local movex = 0
|
|
local movey = 0
|
|
dx = dx/radius
|
|
dy = dy/radius
|
|
|
|
local speed = math.ceil(minimapWidget:getZoom()/22)
|
|
if dx > 0.5 then movex = speed end
|
|
if dx < -0.5 then movex = -speed end
|
|
if dy > 0.5 then movey = -speed end
|
|
if dy < -0.5 then movey = speed end
|
|
|
|
local cameraPos = minimapWidget:getCameraPosition()
|
|
local pos = {x = cameraPos.x + movex, y = cameraPos.y + movey, z = cameraPos.z}
|
|
minimapWidget:setCameraPosition(pos)
|
|
|
|
updateMapFlags()
|
|
end
|
|
|
|
function miniMapZoomIn(zoom)
|
|
minimapWidget:setZoom(math.max(minimapWidget:getMaxZoomIn(), minimapWidget:getZoom()-zoom))
|
|
end
|
|
|
|
function miniMapZoomOut(zoom)
|
|
minimapWidget:setZoom(math.min(minimapWidget:getMaxZoomOut(), minimapWidget:getZoom()+zoom))
|
|
end
|
|
|
|
function minimapFloorUp(floors)
|
|
local pos = minimapWidget:getCameraPosition()
|
|
pos.z = pos.z - floors
|
|
if pos.z > MAX_FLOOR_UP then
|
|
minimapWidget:setCameraPosition(pos)
|
|
end
|
|
end
|
|
|
|
function minimapFloorDown(floors)
|
|
local pos = minimapWidget:getCameraPosition()
|
|
pos.z = pos.z + floors
|
|
if pos.z < MAX_FLOOR_DOWN then
|
|
minimapWidget:setCameraPosition(pos)
|
|
end
|
|
end
|
|
|
|
function minimapAutoWalk(pos)
|
|
local player = g_game.getLocalPlayer()
|
|
if not player:autoWalk(pos) then
|
|
modules.game_textmessage.displayStatusMessage(tr('There is no way.'))
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
function onButtonClick(id)
|
|
if id == "zoomIn" then
|
|
miniMapZoomIn(20)
|
|
elseif id == "zoomOut" then
|
|
miniMapZoomOut(20)
|
|
elseif id == "floorUp" then
|
|
minimapFloorUp(1)
|
|
elseif id == "floorDown" then
|
|
minimapFloorDown(1)
|
|
end
|
|
|
|
updateMapFlags()
|
|
end
|
|
|
|
function onMinimapMouseRelease(self, mousePosition, mouseButton)
|
|
-- Mapmark menu
|
|
local pos = self:getPosition(mousePosition)
|
|
if mouseButton == MouseRightButton then
|
|
local menu = g_ui.createWidget('PopupMenu')
|
|
menu:addOption(tr('Create mark'), function()
|
|
local pos = self:getPosition(mousePosition)
|
|
if pos then
|
|
showFlagDialog(pos)
|
|
end
|
|
end)
|
|
menu:display(mousePosition)
|
|
end
|
|
|
|
if navigating then
|
|
navigating = false
|
|
return
|
|
end
|
|
if pos and mouseButton == MouseLeftButton and self:isPressed() then
|
|
minimapAutoWalk(pos)
|
|
end
|
|
return false
|
|
end
|
|
|
|
function onMinimapMouseWheel(self, mousePos, direction)
|
|
local keyboardModifiers = g_keyboard.getModifiers()
|
|
|
|
if direction == MouseWheelUp and keyboardModifiers == KeyboardNoModifier then
|
|
miniMapZoomIn(10)
|
|
elseif direction == MouseWheelDown and keyboardModifiers == KeyboardNoModifier then
|
|
miniMapZoomOut(10)
|
|
elseif direction == MouseWheelDown and keyboardModifiers == KeyboardCtrlModifier then
|
|
minimapFloorUp(1)
|
|
elseif direction == MouseWheelUp and keyboardModifiers == KeyboardCtrlModifier then
|
|
minimapFloorDown(1)
|
|
end
|
|
updateMapFlags()
|
|
end
|
|
|
|
function onMiniWindowClose()
|
|
minimapButton:setOn(false)
|
|
end
|