tibia-client/modules/game_minimap/minimap.lua

467 lines
13 KiB
Lua
Raw Normal View History

2013-01-21 00:17:56 +01:00
DEFAULT_ZOOM = 0
MAX_FLOOR_UP = 0
MAX_FLOOR_DOWN = 15
navigating = false
minimapWidget = nil
minimapButton = nil
minimapWindow = nil
otmm = false
flagsPanel = nil
flagWindow = nil
nextFlagId = 0
--[[
2012-07-12 21:16:23 +02:00
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')
2012-08-18 12:34:15 +02:00
connect(g_game, {
onGameStart = online,
onGameEnd = offline,
2013-01-29 21:36:27 +01:00
onAddAutomapFlag = addMapFlag,
onRemoveAutomapFlag = removeMapFlag,
2012-08-18 12:34:15 +02:00
})
connect(LocalPlayer, { onPositionChange = center })
2012-07-12 21:16:23 +02:00
g_keyboard.bindKeyDown('Ctrl+M', toggle)
minimapButton = modules.client_topmenu.addRightGameToggleButton('minimapButton', tr('Minimap') .. ' (Ctrl+M)', '/images/topbuttons/minimap', toggle)
minimapButton:setOn(true)
minimapWindow = g_ui.loadUI('minimap', modules.game_interface.getRightPanel())
2012-08-21 01:56:16 +02:00
minimapWindow:setContentMinimumHeight(64)
2013-01-21 00:17:56 +01:00
--minimapWindow:setContentMaximumHeight(256)
2012-06-22 07:26:22 +02:00
minimapWidget = minimapWindow:recursiveGetChildById('minimap')
g_mouse.bindAutoPress(minimapWidget, compassClick, nil, MouseLeftButton)
2013-01-21 00:17:56 +01:00
minimapWidget.onMouseRelease = onMinimapMouseRelease
minimapWidget.onMouseWheel = onMinimapMouseWheel
flagsPanel = minimapWindow:recursiveGetChildById('flagsPanel')
local gameRootPanel = modules.game_interface.getRootPanel()
g_keyboard.bindKeyPress('Alt+Left', function() move(-1,0) end, gameRootPanel)
g_keyboard.bindKeyPress('Alt+Right', function() move(1,0) end, gameRootPanel)
g_keyboard.bindKeyPress('Alt+Up', function() move(0,-1) end, gameRootPanel)
g_keyboard.bindKeyPress('Alt+Down', function() move(0,1) end, gameRootPanel)
2013-01-26 23:20:26 +01:00
reset()
2012-08-21 23:40:47 +02:00
minimapWindow:setup()
loadMapFlags()
useOTMM()
if g_game.isOnline() then
addEvent(function() updateMapFlags() end)
end
end
function terminate()
local gameRootPanel = modules.game_interface.getRootPanel()
g_keyboard.unbindKeyPress('Alt+Left', gameRootPanel)
g_keyboard.unbindKeyPress('Alt+Right', gameRootPanel)
g_keyboard.unbindKeyPress('Alt+Up', gameRootPanel)
g_keyboard.unbindKeyPress('Alt+Down', gameRootPanel)
2013-01-27 10:44:15 +01:00
2012-08-18 12:34:15 +02:00
disconnect(g_game, {
onGameStart = online,
onGameEnd = offline,
2013-01-29 21:36:27 +01:00
onAddAutomapFlag = addMapFlag,
onRemoveAutomapFlag = removeMapFlag,
2012-08-18 12:34:15 +02:00
})
disconnect(LocalPlayer, { onPositionChange = center })
2012-08-18 12:34:15 +02:00
destroyFlagWindow()
saveMapFlags()
2012-08-18 12:34:15 +02:00
if g_game.isOnline() then
saveMap()
end
2012-07-12 21:16:23 +02:00
2012-06-26 00:13:30 +02:00
g_keyboard.unbindKeyDown('Ctrl+M')
minimapButton:destroy()
2012-06-22 07:26:22 +02:00
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)
2013-01-29 21:36:27 +01:00
checkbox.icon = i - 1
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)
2013-01-29 21:36:27 +01:00
if not (icon >= 0 and icon <= 19) 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)
2013-01-29 21:36:27 +01:00
flagWidget:setIconClip(getFlagIconClip(icon))
flagWidget:setId('flag' .. flagId)
flagWidget.position = pos
flagWidget.icon = icon
flagWidget.description = message
if message and message:len() > 0 then
2013-01-25 20:26:51 +01:00
flagWidget:setTooltip(message)
end
flagWidget.id = flagId
flagWidget.version = version
updateMapFlag(flagId)
flagWidget.onMousePress = onFlagMousePress
end
2013-01-29 21:36:27 +01:00
function removeMapFlag(pos, icon, message)
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 flag.icon == icon and flag.description == message then
flag:destroy()
break
end
end
end
function getMapArea()
return minimapWidget:getPosition( { x = 1 + minimapWidget:getX(), y = 1 + minimapWidget:getY() } ),
2013-01-21 00:17:56 +01:00
minimapWidget:getPosition( { x = -2 + minimapWidget:getWidth() + minimapWidget:getX(), y = -2 + minimapWidget:getHeight() + minimapWidget:getY() } )
end
function isFlagVisible(flag, firstPosition, lastPosition)
2013-01-29 21:36:27 +01:00
return flag.version == g_game.getProtocolVersion() and (minimapWidget:getZoom() >= -2 and minimapWidget:getZoom() <= 4) 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)
2013-01-29 21:36:27 +01:00
flag:setMarginLeft(-5.5 + (minimapWidget:getWidth() / (lastPosition.x - firstPosition.x)) * (flag.position.x - firstPosition.x))
flag:setMarginTop(-5.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
2013-01-29 21:36:27 +01:00
for i=1, flagsPanel:getChildCount() do
local flag = flagsPanel:getChildByIndex(i)
if isFlagVisible(flag, firstPosition, lastPosition) then
flag:setVisible(true)
2013-01-29 21:36:27 +01:00
flag:setMarginLeft(-5.5 + (minimapWidget:getWidth() / (lastPosition.x - firstPosition.x)) * (flag.position.x - firstPosition.x))
flag:setMarginTop(-5.5 + (minimapWidget:getHeight() / (lastPosition.y - firstPosition.y)) * (flag.position.y - firstPosition.y))
else
flag:setVisible(false)
end
end
end
2012-08-18 12:34:15 +02:00
function online()
reset()
loadMap()
updateMapFlags()
2012-08-18 12:34:15 +02:00
end
function offline()
saveMap()
end
function loadMap()
local protocolVersion = g_game.getProtocolVersion()
g_map.clean()
g_minimap.clean()
if otmm then
local minimapFile = '/minimap.otmm'
if g_resources.fileExists(minimapFile) then
g_minimap.loadOtmm(minimapFile)
end
else
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
if g_resources.fileExists(minimapFile) then
g_map.loadOtcm(minimapFile)
end
end
2012-08-18 12:34:15 +02:00
end
function saveMap()
local protocolVersion = g_game.getProtocolVersion()
if otmm then
local minimapFile = '/minimap.otmm'
g_minimap.saveOtmm(minimapFile)
else
local minimapFile = '/minimap_' .. protocolVersion .. '.otcm'
g_map.saveOtcm(minimapFile)
end
2012-08-18 12:34:15 +02:00
end
function toggle()
2012-06-24 14:41:39 +02:00
if minimapButton:isOn() then
2012-06-22 07:26:22 +02:00
minimapWindow:close()
minimapButton:setOn(false)
2012-06-24 14:41:39 +02:00
else
minimapWindow:open()
minimapButton:setOn(true)
2012-06-22 07:26:22 +02:00
end
end
function useOTMM()
otmm = true
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)
2012-06-24 14:41:39 +02:00
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
2012-06-26 07:54:55 +02:00
end
2012-07-12 21:16:23 +02:00
function center()
reset(false)
updateMapFlags()
end
function compassClick(self, mousePos, mouseButton, elapsed)
if elapsed < 300 then return end
navigating = true
2012-07-12 21:16:23 +02:00
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
2012-07-12 21:16:23 +02:00
dx = dx/radius
dy = dy/radius
2013-01-21 00:17:56 +01:00
local speed = math.ceil((1.0 / minimapWidget:getScale()) * 3)
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()
2012-07-12 21:16:23 +02:00
local pos = {x = cameraPos.x + movex, y = cameraPos.y + movey, z = cameraPos.z}
minimapWidget:setCameraPosition(pos)
updateMapFlags()
2012-06-26 07:54:55 +02:00
end
2013-01-26 23:20:26 +01:00
function move(x,y)
local speed = math.ceil((1.0 / minimapWidget:getScale()) * 3)
local cameraPos = minimapWidget:getCameraPosition()
local pos = {x = cameraPos.x + x*speed, y = cameraPos.y + y*speed, z = cameraPos.z}
minimapWidget:setCameraPosition(pos)
updateMapFlags()
end
2013-01-21 00:17:56 +01:00
function miniMapZoomIn()
minimapWidget:zoomIn()
end
2013-01-21 00:17:56 +01:00
function miniMapZoomOut()
minimapWidget:zoomOut()
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
2013-01-29 14:50:24 +01:00
player.onAutoWalkFail = function() modules.game_textmessage.displayFailureMessage(tr('There is no way.')) end
return false
else
return true
end
end
function onButtonClick(id)
2012-06-26 07:54:55 +02:00
if id == "zoomIn" then
2013-01-21 00:17:56 +01:00
miniMapZoomIn()
2012-06-26 07:54:55 +02:00
elseif id == "zoomOut" then
2013-01-21 00:17:56 +01:00
miniMapZoomOut()
2012-07-12 19:29:44 +02:00
elseif id == "floorUp" then
minimapFloorUp(1)
2012-07-12 19:29:44 +02:00
elseif id == "floorDown" then
minimapFloorDown(1)
2012-06-26 07:54:55 +02:00
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
2012-08-22 04:10:56 +02:00
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()
elseif direction == MouseWheelDown and keyboardModifiers == KeyboardNoModifier then
miniMapZoomOut()
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