tibia-client/modules/game_console/console.lua

584 lines
19 KiB
Lua
Raw Normal View History

SpeakTypesSettings = {
2012-02-03 05:32:39 +01:00
say = { speakType = SpeakSay, color = '#FFFF00' },
whisper = { speakType = SpeakWhisper, color = '#FFFF00' },
yell = { speakType = SpeakYell, color = '#FFFF00' },
broadcast = { speakType = SpeakBroadcast, color = '#F55E5E' },
private = { speakType = SpeakPrivate, color = '#5FF7F7', private = true },
privateRed = { speakType = SpeakPrivateRed, color = '#F55E5E', private = true },
privatePlayerToPlayer = { speakType = SpeakPrivate, color = '#9F9DFD', private = true },
privatePlayerToNpc = { speakType = SpeakPrivatePlayerToNpc, color = '#9F9DFD', private = true, npcChat = true },
privateNpcToPlayer = { speakType = SpeakPrivateNpcToPlayer, color = '#5FF7F7', private = true, npcChat = true },
channelYellow = { speakType = SpeakChannelYellow, color = '#FFFF00' },
channelWhite = { speakType = SpeakChannelWhite, color = '#FFFFFF' },
channelRed = { speakType = SpeakChannelRed, color = '#F55E5E' },
channelOrange = { speakType = SpeakChannelOrange, color = '#FE6500' },
monsterSay = { speakType = SpeakMonsterSay, color = '#FE6500', hideInConsole = true},
monsterYell = { speakType = SpeakMonsterYell, color = '#FE6500', hideInConsole = true},
}
SpeakTypes = {
2012-02-03 06:24:45 +01:00
[SpeakSay] = SpeakTypesSettings.say,
[SpeakWhisper] = SpeakTypesSettings.whisper,
[SpeakYell] = SpeakTypesSettings.yell,
[SpeakBroadcast] = SpeakTypesSettings.broadcast,
[SpeakPrivate] = SpeakTypesSettings.private,
[SpeakPrivateRed] = SpeakTypesSettings.privateRed,
[SpeakPrivatePlayerToNpc] = SpeakTypesSettings.privatePlayerToNpc,
[SpeakPrivateNpcToPlayer] = SpeakTypesSettings.privateNpcToPlayer,
[SpeakChannelYellow] = SpeakTypesSettings.channelYellow,
[SpeakChannelWhite] = SpeakTypesSettings.channelWhite,
[SpeakChannelRed] = SpeakTypesSettings.channelRed,
[SpeakChannelOrange] = SpeakTypesSettings.channelOrange,
[SpeakMonsterSay] = SpeakTypesSettings.monsterSay,
[SpeakMonsterYell] = SpeakTypesSettings.monsterYell,
}
SayModes = {
2012-06-19 10:46:49 +02:00
[1] = { speakTypeDesc = 'whisper', icon = 'icons/whisper.png' },
[2] = { speakTypeDesc = 'say', icon = 'icons/say.png' },
[3] = { speakTypeDesc = 'yell', icon = 'icons/yell.png' }
}
MAX_HISTORY = 1000
MAX_LINES = 100
HELP_CHANNEL = 9
2012-04-08 06:13:52 +02:00
consolePanel = nil
consoleContentPanel = nil
consoleTabBar = nil
consoleTextEdit = nil
channels = nil
channelsWindow = nil
ownPrivateName = nil
messageHistory = {}
currentMessageIndex = 0
ignoreNpcMessages = false
function init()
connect(g_game, { onCreatureSpeak = onCreatureSpeak,
onChannelList = onChannelList,
onOpenChannel = onOpenChannel,
2012-04-24 13:39:45 +02:00
onOpenPrivateChannel = onOpenPrivateChannel,
onOpenOwnPrivateChannel = onOpenOwnPrivateChannel,
2012-04-08 06:13:52 +02:00
onCloseChannel = onCloseChannel,
onGameStart = onGameStart,
onGameEnd = clear })
consolePanel = g_ui.loadUI('console.otui', modules.game_interface.getBottomPanel())
consoleTextEdit = consolePanel:getChildById('consoleTextEdit')
consoleContentPanel = consolePanel:getChildById('consoleContentPanel')
consoleTabBar = consolePanel:getChildById('consoleTabBar')
consoleTabBar:setContentWidget(consoleContentPanel)
2012-01-14 02:37:15 +01:00
channels = {}
addTab(tr('Default'), true)
addTab(tr('Server Log'), false)
2012-02-04 03:11:18 +01:00
2012-06-26 00:13:30 +02:00
g_keyboard.bindKeyPress('Shift+Up', function() navigateMessageHistory(1) end, consolePanel)
g_keyboard.bindKeyPress('Shift+Down', function() navigateMessageHistory(-1) end, consolePanel)
g_keyboard.bindKeyPress('Tab', function() consoleTabBar:selectNextTab() end, consolePanel)
g_keyboard.bindKeyPress('Shift+Tab', function() consoleTabBar:selectPrevTab() end, consolePanel)
g_keyboard.bindKeyDown('Enter', sendCurrentMessage, consolePanel)
2012-06-26 00:13:30 +02:00
g_keyboard.bindKeyPress('Ctrl+A', function() consoleTextEdit:clearText() end, consolePanel)
2012-02-04 03:11:18 +01:00
2012-02-03 06:24:45 +01:00
-- apply buttom functions after loaded
consolePanel:getChildById('nextChannelButton').onClick = function() consoleTabBar:selectNextTab() end
consolePanel:getChildById('prevChannelButton').onClick = function() consoleTabBar:selectPrevTab() end
consoleTabBar.onTabChange = onTabChange
2012-02-04 03:11:18 +01:00
2012-02-03 06:24:45 +01:00
-- tibia like hotkeys
2012-06-26 00:13:30 +02:00
g_keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels)
g_keyboard.bindKeyDown('Ctrl+E', removeCurrentTab)
g_keyboard.bindKeyDown('Ctrl+H', openHelp)
end
function terminate()
disconnect(g_game, { onCreatureSpeak = onCreatureSpeak,
onChannelList = onChannelList,
onOpenChannel = onOpenChannel,
2012-04-24 13:39:45 +02:00
onOpenPrivateChannel = onOpenPrivateChannel,
onOpenOwnPrivateChannel = onOpenPrivateChannel,
2012-04-08 06:13:52 +02:00
onCloseChannel = onCloseChannel,
onGameStart = onGameStart,
onGameEnd = clear })
for channelid, channelname in pairs(channels) do
2012-06-04 00:55:26 +02:00
if tonumber(channelid) and tonumber(channelid) ~= 0 then
g_game.leaveChannel(channelid)
end
end
channels = {}
2012-06-26 00:13:30 +02:00
g_keyboard.unbindKeyDown('Ctrl+O')
g_keyboard.unbindKeyDown('Ctrl+E')
g_keyboard.unbindKeyDown('Ctrl+H')
if channelsWindow then
channelsWindow:destroy()
channelsWindow = nil
end
consolePanel:destroy()
consolePanel = nil
consoleTextEdit = nil
consoleContentPanel = nil
consoleTabBar = nil
ownPrivateName = nil
2012-04-27 06:54:14 +02:00
Console = nil
end
function onTabChange(tabBar, tab)
if tab:getText() == tr('Default') or tab:getText() == tr('Server Log') then
consolePanel:getChildById('closeChannelButton'):disable()
else
consolePanel:getChildById('closeChannelButton'):enable()
end
end
function clear()
local lastChannelsOpen = {}
local player = g_game.getLocalPlayer()
if(player) then
local char = player:getName()
lastChannelsOpen[char] = {}
for channelId, channelName in pairs(channels) do
table.insert(lastChannelsOpen[char], channelId)
end
end
-- save last open channels
g_settings.setNode('LastChannelsOpen', lastChannelsOpen)
for _, channelName in pairs(channels) do
local tab = consoleTabBar:getTab(channelName)
consoleTabBar:removeTab(tab)
end
channels = {}
consoleTabBar:getTab(tr('Default')).tabPanel:getChildById('consoleBuffer'):destroyChildren()
consoleTabBar:getTab(tr('Server Log')).tabPanel:getChildById('consoleBuffer'):destroyChildren()
local npcTab = consoleTabBar:getTab('NPCs')
if npcTab then
consoleTabBar:removeTab(npcTab)
end
consoleTextEdit:clearText()
if channelsWindow then
channelsWindow:destroy()
channelsWindow = nil
end
end
function setTextEditText(text)
consoleTextEdit:setText(text)
2012-02-07 06:52:48 +01:00
end
function openHelp()
2012-06-08 18:58:08 +02:00
g_game.joinChannel(HELP_CHANNEL)
end
function addTab(name, focus)
local tab = getTab(name)
if(tab) then -- is channel already open
if(not focus) then focus = true end
else
tab = consoleTabBar:addTab(name)
end
2012-02-03 05:32:39 +01:00
if focus then
consoleTabBar:selectTab(tab)
elseif name ~= tr('Server Log') then
consoleTabBar:blinkTab(tab)
2012-02-03 05:32:39 +01:00
end
2012-01-14 02:37:15 +01:00
return tab
end
function removeCurrentTab()
2012-02-03 05:32:39 +01:00
local tab = consoleTabBar:getCurrentTab()
if tab:getText() == tr('Default') or tab:getText() == tr('Server Log') then return end
2012-02-04 03:11:18 +01:00
-- notificate the server that we are leaving the channel
if tab.channelId then
2012-07-11 11:20:31 +02:00
for k, v in pairs(channels) do
if (k == tab.channelId) then channels[k] = nil end
end
2012-02-08 22:23:15 +01:00
g_game.leaveChannel(tab.channelId)
elseif tab:getText() == "NPCs" then
2012-02-08 22:23:15 +01:00
g_game.closeNpcChannel()
end
consoleTabBar:removeTab(tab)
2012-02-03 05:32:39 +01:00
end
function getTab(name)
2012-01-14 02:37:15 +01:00
return consoleTabBar:getTab(name)
end
function getCurrentTab()
2012-01-14 02:37:15 +01:00
return consoleTabBar:getCurrentTab()
end
function addChannel(name, id)
2012-01-14 02:37:15 +01:00
channels[id] = name
local tab = addTab(name, true)
2012-01-14 02:37:15 +01:00
tab.channelId = id
return tab
end
function addPrivateChannel(receiver)
channels[receiver] = receiver
return addTab(receiver, true)
end
function addPrivateText(text, speaktype, name, isPrivateCommand, creatureName)
local focus = false
if speaktype.speakType == SpeakPrivateNpcToPlayer then
name = 'NPCs'
focus = true
end
local privateTab = getTab(name)
2012-01-14 02:37:15 +01:00
if privateTab == nil then
if (Options.getOption('showPrivateMessagesInConsole') and not focus) or (isPrivateCommand and not privateTab) then
privateTab = getTab(tr('Default'))
2012-01-14 02:37:15 +01:00
else
privateTab = addTab(name, focus)
2012-06-10 02:12:28 +02:00
channels[name] = name
2012-01-14 02:37:15 +01:00
end
privateTab.npcChat = speaktype.npcChat
elseif focus then
consoleTabBar:selectTab(privateTab)
2012-01-14 02:37:15 +01:00
end
addTabText(text, speaktype, privateTab, creatureName)
2012-01-14 02:37:15 +01:00
end
function addText(text, speaktype, tabName, creatureName)
local tab = getTab(tabName)
if tab ~= nil then
addTabText(text, speaktype, tab, creatureName)
end
2012-01-14 02:37:15 +01:00
end
function addTabText(text, speaktype, tab, creatureName)
2012-03-23 23:02:58 +01:00
if Options.getOption('showTimestampsInConsole') then
2012-01-09 00:28:49 +01:00
text = os.date('%H:%M') .. ' ' .. text
end
2012-01-14 21:14:40 +01:00
local panel = consoleTabBar:getTabPanel(tab)
local consoleBuffer = panel:getChildById('consoleBuffer')
2012-06-26 00:13:30 +02:00
local label = g_ui.createWidget('ConsoleLabel', consoleBuffer)
label:setId('consoleLabel' .. panel:getChildCount())
label:setText(text)
2012-01-14 02:37:15 +01:00
label:setColor(speaktype.color)
consoleTabBar:blinkTab(tab)
2012-01-14 21:14:40 +01:00
label.onMouseRelease = function (self, mousePos, mouseButton) popupMenu(mousePos, mouseButton, creatureName, text) end
if consoleBuffer:getChildCount() > MAX_LINES then
consoleBuffer:getFirstChild():destroy()
2012-01-14 21:14:40 +01:00
end
end
function popupMenu(mousePos, mouseButton, creatureName, text)
if mouseButton == MouseRightButton then
2012-06-26 00:13:30 +02:00
local menu = g_ui.createWidget('PopupMenu')
if creatureName then
2012-06-04 02:28:19 +02:00
if creatureName ~= g_game.getCharacterName() then
menu:addOption(tr('Message to ' .. creatureName), function () g_game.openPrivateChannel(creatureName) end)
if (not Player:hasVip(creatureName)) then
menu:addOption(tr('Add to VIP list'), function () g_game.addVip(creatureName) end)
end
-- TODO ignore creatureName
menu:addSeparator()
end
--TODO select all
menu:addOption(tr('Copy message'), function () g_window.setClipboardText(text) end)
if RuleViolation.hasWindowAccess() then
menu:addSeparator()
menu:addOption(tr('Rule Violation'), function() RuleViolation.show(creatureName, text:match('.+%:%s(.+)')) end)
end
menu:addSeparator()
menu:addOption(tr('Copy name'), function () g_window.setClipboardText(creatureName) end)
else
--TODO select all
menu:addOption(tr('Copy message'), function () g_window.setClipboardText(text) end)
end
menu:display(mousePos)
end
end
function sendCurrentMessage()
local message = consoleTextEdit:getText()
2012-01-14 02:37:15 +01:00
if #message == 0 then return end
consoleTextEdit:clearText()
2012-01-14 02:37:15 +01:00
2012-01-14 06:54:20 +01:00
-- get current channel
local tab = getCurrentTab()
2012-01-14 02:37:15 +01:00
-- handling chat commands
local originalMessage = message
local chatCommandSayMode
local chatCommandPrivate
2012-02-03 22:37:42 +01:00
local chatCommandPrivateReady
2012-02-04 03:11:18 +01:00
local chatCommandMessage = message:match("^%#y (.*)")
if chatCommandMessage ~= nil then chatCommandSayMode = 'yell' end -- player used yell command
message = chatCommandMessage or message
2012-02-04 03:11:18 +01:00
local chatCommandMessage = message:match("^%#w (.*)")
if chatCommandMessage ~= nil then chatCommandSayMode = 'whisper' end -- player used whisper
message = chatCommandMessage or message
2012-02-04 03:11:18 +01:00
local findIni, findEnd, chatCommandInitial, chatCommandPrivate, chatCommandEnd, chatCommandMessage = message:find("([%*%@])(.+)([%*%@])(.*)")
if findIni ~= nil and findIni == 1 then -- player used private chat command
if chatCommandInitial == chatCommandEnd then
chatCommandPrivateRepeat = false
if chatCommandInitial == "*" then
consoleTextEdit:setText('*'.. chatCommandPrivate .. '* ')
2012-02-04 03:11:18 +01:00
end
message = chatCommandMessage:trim()
2012-02-03 22:37:42 +01:00
chatCommandPrivateReady = true
end
end
2012-02-04 03:11:18 +01:00
message = message:gsub("^(%s*)(.*)","%2") -- remove space characters from message init
if #message == 0 then return end
-- add new command to history
currentMessageIndex = 0
if #messageHistory == 0 or messageHistory[#messageHistory] ~= originalMessage then
table.insert(messageHistory, originalMessage)
if #messageHistory > MAX_HISTORY then
table.remove(messageHistory, 1)
end
end
2012-02-04 03:11:18 +01:00
2012-01-14 06:54:20 +01:00
-- when talking on server log, the message goes to default channel
local name = tab:getText()
if name == tr('Server Log') then
tab = getTab(tr('Default'))
name = tr('Default')
2012-01-14 02:37:15 +01:00
end
2012-01-14 06:54:20 +01:00
local speaktypedesc
if (tab.channelId or name == tr('Default')) and not chatCommandPrivateReady then
if name == tr('Default') then
speaktypedesc = chatCommandSayMode or SayModes[consolePanel:getChildById('sayModeButton').sayMode].speakTypeDesc
if speaktypedesc ~= 'say' then sayModeChange(2) end -- head back to say mode
2012-01-14 06:54:20 +01:00
else
2012-01-14 02:37:15 +01:00
speaktypedesc = 'channelYellow'
end
2012-02-08 22:23:15 +01:00
g_game.talkChannel(SpeakTypesSettings[speaktypedesc].speakType, tab.channelId, message)
2012-01-14 02:37:15 +01:00
return
else
local isPrivateCommand = false
2012-02-03 22:37:42 +01:00
if chatCommandPrivateReady then
speaktypedesc = 'privatePlayerToPlayer'
name = chatCommandPrivate
isPrivateCommand = true
elseif tab.npcChat then
2012-02-03 05:32:39 +01:00
speaktypedesc = 'privatePlayerToNpc'
2012-01-14 06:54:20 +01:00
else
2012-02-03 05:32:39 +01:00
speaktypedesc = 'privatePlayerToPlayer'
2012-01-14 06:54:20 +01:00
end
2012-02-04 03:11:18 +01:00
2012-01-14 06:54:20 +01:00
2012-02-03 05:32:39 +01:00
local speaktype = SpeakTypesSettings[speaktypedesc]
2012-02-08 22:23:15 +01:00
local player = g_game.getLocalPlayer()
g_game.talkPrivate(speaktype.speakType, name, message)
2012-01-14 06:54:20 +01:00
2012-01-14 02:37:15 +01:00
message = applyMessagePrefixies(player:getName(), player:getLevel(), message)
addPrivateText(message, speaktype, name, isPrivateCommand, g_game.getCharacterName())
end
end
function sayModeChange(sayMode)
local buttom = consolePanel:getChildById('sayModeButton')
if sayMode == nil then
sayMode = buttom.sayMode + 1
end
2012-02-04 03:11:18 +01:00
if sayMode > #SayModes then sayMode = 1 end
buttom:setIcon(SayModes[sayMode].icon)
2012-02-04 03:11:18 +01:00
buttom.sayMode = sayMode
end
function getOwnPrivateTab()
if not ownPrivateName then return end
return getTab(ownPrivateName)
end
2012-06-11 10:17:52 +02:00
function ignoreNpcMessages(ignore)
2012-06-11 10:25:04 +02:00
ignoreNpcMessages = ignore
end
function navigateMessageHistory(step)
local numCommands = #messageHistory
if numCommands > 0 then
currentMessageIndex = math.min(math.max(currentMessageIndex + step, 0), numCommands)
if currentMessageIndex > 0 then
local command = messageHistory[numCommands - currentMessageIndex + 1]
consoleTextEdit:setText(command)
else
consoleTextEdit:clearText()
end
end
end
function applyMessagePrefixies(name, level, message)
if name then
if Options.getOption('showLevelsInConsole') and level > 0 then
message = name .. ' [' .. level .. ']: ' .. message
else
message = name .. ': ' .. message
end
end
return message
end
function onCreatureSpeak(name, level, speaktype, message, channelId, creaturePos)
if ignoreNpcMessages and speaktype == SpeakPrivateNpcToPlayer then return end
local defaultMessage = speaktype < 3 and true or false
speaktype = SpeakTypes[speaktype]
if speaktype.hideInConsole then return end
local composedMessage = applyMessagePrefixies(name, level, message)
if speaktype.private then
addPrivateText(composedMessage, speaktype, name, false, name)
if Options.getOption('showPrivateMessagesOnScreen') then
if(speaktype.speakType ~= SpeakPrivateNpcToPlayer) then
TextMessage.displayPrivate(name .. ':\n' .. message)
end
end
else
local channel = tr('Default')
if not defaultMessage then
channel = channels[channelId]
end
if channel then
addText(composedMessage, speaktype, channel, name)
elseif channelId ~= 0 then
-- server sent a message on a channel that is not open
pwarning('message in channel id ' .. channelId .. ' which is unknown, this is a server bug, relogin if you want to see messages in this channel')
end
end
end
2012-07-24 07:41:59 +02:00
function onOpenChannel(channelId, channelName)
addChannel(channelName, channelId)
end
2012-07-24 07:41:59 +02:00
function onOpenPrivateChannel(receiver)
addPrivateChannel(receiver)
end
2012-07-24 07:41:59 +02:00
function onOpenOwnPrivateChannel(channelId, channelName)
local privateTab = getTab(channelName)
if privateTab == nil then
addChannel(channelName, channelId)
end
ownPrivateName = channelName
end
2012-07-24 07:41:59 +02:00
function onCloseChannel(channelId)
local channel = channels[channelId]
if channel then
local tab = getTab(channel)
if tab then
consoleTabBar:removeTab(tab)
end
for k, v in pairs(channels) do
if (k == tab.channelId) then channels[k] = nil end
end
end
end
2012-07-24 07:41:59 +02:00
function doChannelListSubmit()
local channelListPanel = channelsWindow:getChildById('channelList')
local openPrivateChannelWith = channelsWindow:getChildById('openPrivateChannelWith'):getText()
if openPrivateChannelWith ~= '' then
g_game.openPrivateChannel(openPrivateChannelWith)
else
local selectedChannelLabel = channelListPanel:getFocusedChild()
if not selectedChannelLabel then return end
if selectedChannelLabel.channelId == 0xFFFF then
g_game.openOwnChannel()
else
g_game.joinChannel(selectedChannelLabel.channelId)
end
end
channelsWindow:destroy()
end
2012-07-24 07:41:59 +02:00
function onChannelList(channelList)
if channelsWindow then channelsWindow:destroy() end
channelsWindow = g_ui.displayUI('channelswindow.otui')
local channelListPanel = channelsWindow:getChildById('channelList')
channelsWindow.onEnter = doChannelListSubmit
channelsWindow.onDestroy = function() channelsWindow = nil end
g_keyboard.bindKeyPress('Down', function() channelListPanel:focusNextChild(KeyboardFocusReason) end, channelsWindow)
g_keyboard.bindKeyPress('Up', function() channelListPanel:focusPreviousChild(KeyboardFocusReason) end, channelsWindow)
for k,v in pairs(channelList) do
local channelId = v[1]
local channelName = v[2]
if #channelName > 0 then
local label = g_ui.createWidget('ChannelListLabel', channelListPanel)
label.channelId = channelId
label:setText(channelName)
label:setPhantom(false)
label.onDoubleClick = doChannelListSubmit
end
end
end
2012-07-24 07:41:59 +02:00
function onGameStart()
-- open last channels
local player = g_game.getLocalPlayer()
if(player) then
local char = player:getName()
local lastChannelsOpen = g_settings.getNode('LastChannelsOpen')
if(not table.empty(lastChannelsOpen) and lastChannelsOpen[char]) then
for channelName, channelId in ipairs(lastChannelsOpen[char]) do
channelId = tonumber(channelId)
if channelId ~= 0 then
if not table.find(channels, channelId) then
g_game.joinChannel(channelId)
end
end
end
end
end
local tab = getTab(tr('Default'))
if tab then
--[[
Known Issue: The server is calling to open channels after
onGameStart is executed causing it to focus the last tab opened.
Fix: Don't save channels to the settings that are opened by the server.
]]
addEvent(function() consoleTabBar:selectTab(tab) end, true)
end
end