Multiprotocol 8.1-9.6 finally working

Still have many minor issues, tests are needed
No recompilation needed anymore
9.60 messages is not fully implemented
This commit is contained in:
Eduardo Bart 2012-07-26 06:12:20 -03:00
parent 98c279c10b
commit 36c029fc69
28 changed files with 575 additions and 511 deletions

View File

@ -5,7 +5,7 @@ function Client.reloadScripts()
dofile '/otclientrc' dofile '/otclientrc'
local message = tr('All modules and scripts were reloaded.') local message = tr('All modules and scripts were reloaded.')
modules.game_textmessage.displayEventAdvance(message) modules.game_textmessage.displayGameMessage(message)
print(message) print(message)
end end

View File

@ -171,28 +171,6 @@ KeyNumpad7 = 148
KeyNumpad8 = 149 KeyNumpad8 = 149
KeyNumpad9 = 150 KeyNumpad9 = 150
SpeakSay = 1
SpeakWhisper = 2
SpeakYell = 3
SpeakBroadcast = 4
SpeakPrivate = 5
SpeakPrivateRed = 6
SpeakPrivatePlayerToNpc = 7
SpeakPrivateNpcToPlayer = 8
SpeakChannelYellow = 9
SpeakChannelWhite = 10
SpeakChannelRed = 11
SpeakChannelOrange = 12
SpeakMonsterSay = 13
SpeakMonsterYell = 14
FightOffensive = 1
FightBalanced = 2
FightDefensive = 3
DontChase = 0
ChaseOpponent = 1
ExtendedActivate = 0 ExtendedActivate = 0
ExtendedLocales = 1 ExtendedLocales = 1
ExtendedParticles = 2 ExtendedParticles = 2

View File

@ -32,6 +32,7 @@ table.insert(LifeBarColors, {percentAbove = 3, color = '#3C0000' } )
table.insert(LifeBarColors, {percentAbove = -1, color = '#4F0000' } ) table.insert(LifeBarColors, {percentAbove = -1, color = '#4F0000' } )
function init() function init()
g_ui.importStyle('battlebutton.otui')
battleWindow = g_ui.loadUI('battle.otui', modules.game_interface.getRightPanel()) battleWindow = g_ui.loadUI('battle.otui', modules.game_interface.getRightPanel())
battleButton = TopMenu.addRightGameToggleButton('battleButton', tr('Battle') .. ' (Ctrl+B)', 'battle.png', toggle) battleButton = TopMenu.addRightGameToggleButton('battleButton', tr('Battle') .. ' (Ctrl+B)', 'battle.png', toggle)
battleButton:setOn(true) battleButton:setOn(true)
@ -173,10 +174,12 @@ function addCreature(creature)
local creatureId = creature:getId() local creatureId = creature:getId()
if battleButtonsByCreaturesList[creatureId] == nil then if battleButtonsByCreaturesList[creatureId] == nil then
local battleButton = g_ui.loadUI('battlebutton.otui', battlePanel) local battleButton = g_ui.createWidget('BattleButton', battlePanel)
local creatureWidget = battleButton:getChildById('creature') local creatureWidget = battleButton:getChildById('creature')
local labelWidget = battleButton:getChildById('label') local labelWidget = battleButton:getChildById('label')
local lifeBarWidget = battleButton:getChildById('lifeBar') local lifeBarWidget = battleButton:getChildById('lifeBar')
battleButton.onHoverChange = onbattleButtonHoverChange
battleButton.onMouseRelease = onMouseRelease
battleButton:setId('BattleButton_' .. creature:getName():gsub('%s','_')) battleButton:setId('BattleButton_' .. creature:getName():gsub('%s','_'))
battleButton.creatureId = creatureId battleButton.creatureId = creatureId

View File

@ -1,11 +1,7 @@
BattleButton < UIButton BattleButton < UIButton
BattleButton
height: 20 height: 20
margin-top: 5 margin-top: 5
fixed-size: true fixed-size: true
&onHoverChange: onbattleButtonHoverChange
&onMouseRelease: onMouseRelease
&isBattleButton: true &isBattleButton: true
UICreature UICreature

View File

@ -22,7 +22,7 @@ end
function doReport() function doReport()
g_game.reportBug(bugTextEdit:getText()) g_game.reportBug(bugTextEdit:getText())
bugReportWindow:hide() bugReportWindow:hide()
modules.game_textmessage.displayEventAdvance(tr('Bug report sent.')) modules.game_textmessage.displayGameMessage(tr('Bug report sent.'))
end end
function show() function show()

View File

@ -1,36 +1,36 @@
SpeakTypesSettings = { SpeakTypesSettings = {
say = { speakType = SpeakSay, color = '#FFFF00' }, say = { speakType = MessageModes.Say, color = '#FFFF00' },
whisper = { speakType = SpeakWhisper, color = '#FFFF00' }, whisper = { speakType = MessageModes.Whisper, color = '#FFFF00' },
yell = { speakType = SpeakYell, color = '#FFFF00' }, yell = { speakType = MessageModes.Yell, color = '#FFFF00' },
broadcast = { speakType = SpeakBroadcast, color = '#F55E5E' }, broadcast = { speakType = MessageModes.GamemasterPrivateFrom, color = '#F55E5E' },
private = { speakType = SpeakPrivate, color = '#5FF7F7', private = true }, private = { speakType = MessageModes.PrivateTo, color = '#5FF7F7', private = true },
privateRed = { speakType = SpeakPrivateRed, color = '#F55E5E', private = true }, privateRed = { speakType = MessageModes.GamemasterTo, color = '#F55E5E', private = true },
privatePlayerToPlayer = { speakType = SpeakPrivate, color = '#9F9DFD', private = true }, privatePlayerToPlayer = { speakType = MessageModes.PrivateTo, color = '#9F9DFD', private = true },
privatePlayerToNpc = { speakType = SpeakPrivatePlayerToNpc, color = '#9F9DFD', private = true, npcChat = true }, privatePlayerToNpc = { speakType = MessageModes.NpcTo, color = '#9F9DFD', private = true, npcChat = true },
privateNpcToPlayer = { speakType = SpeakPrivateNpcToPlayer, color = '#5FF7F7', private = true, npcChat = true }, privateNpcToPlayer = { speakType = MessageModes.NpcFrom, color = '#5FF7F7', private = true, npcChat = true },
channelYellow = { speakType = SpeakChannelYellow, color = '#FFFF00' }, channelYellow = { speakType = MessageModes.Channel, color = '#FFFF00' },
channelWhite = { speakType = SpeakChannelWhite, color = '#FFFFFF' }, channelWhite = { speakType = MessageModes.ChannelManagement, color = '#FFFFFF' },
channelRed = { speakType = SpeakChannelRed, color = '#F55E5E' }, channelRed = { speakType = MessageModes.GamemasterChannel, color = '#F55E5E' },
channelOrange = { speakType = SpeakChannelOrange, color = '#FE6500' }, channelOrange = { speakType = MessageModes.ChannelHighlight, color = '#FE6500' },
monsterSay = { speakType = SpeakMonsterSay, color = '#FE6500', hideInConsole = true}, monsterSay = { speakType = MessageModes.MonsterSay, color = '#FE6500', hideInConsole = true},
monsterYell = { speakType = SpeakMonsterYell, color = '#FE6500', hideInConsole = true}, monsterYell = { speakType = MessageModes.MonsterYell, color = '#FE6500', hideInConsole = true},
} }
SpeakTypes = { SpeakTypes = {
[SpeakSay] = SpeakTypesSettings.say, [MessageModes.Say] = SpeakTypesSettings.say,
[SpeakWhisper] = SpeakTypesSettings.whisper, [MessageModes.Whisper] = SpeakTypesSettings.whisper,
[SpeakYell] = SpeakTypesSettings.yell, [MessageModes.Yell] = SpeakTypesSettings.yell,
[SpeakBroadcast] = SpeakTypesSettings.broadcast, [MessageModes.GamemasterPrivateFrom] = SpeakTypesSettings.broadcast,
[SpeakPrivate] = SpeakTypesSettings.private, [MessageModes.PrivateFrom] = SpeakTypesSettings.private,
[SpeakPrivateRed] = SpeakTypesSettings.privateRed, [MessageModes.GamemasterPrivateFrom] = SpeakTypesSettings.privateRed,
[SpeakPrivatePlayerToNpc] = SpeakTypesSettings.privatePlayerToNpc, [MessageModes.NpcTo] = SpeakTypesSettings.privatePlayerToNpc,
[SpeakPrivateNpcToPlayer] = SpeakTypesSettings.privateNpcToPlayer, [MessageModes.NpcFrom] = SpeakTypesSettings.privateNpcToPlayer,
[SpeakChannelYellow] = SpeakTypesSettings.channelYellow, [MessageModes.Channel] = SpeakTypesSettings.channelYellow,
[SpeakChannelWhite] = SpeakTypesSettings.channelWhite, [MessageModes.ChannelManagement] = SpeakTypesSettings.channelWhite,
[SpeakChannelRed] = SpeakTypesSettings.channelRed, [MessageModes.GamemasterChannel] = SpeakTypesSettings.channelRed,
[SpeakChannelOrange] = SpeakTypesSettings.channelOrange, [MessageModes.ChannelHighlight] = SpeakTypesSettings.channelOrange,
[SpeakMonsterSay] = SpeakTypesSettings.monsterSay, [MessageModes.MonsterSay] = SpeakTypesSettings.monsterSay,
[SpeakMonsterYell] = SpeakTypesSettings.monsterYell, [MessageModes.MonsterYell] = SpeakTypesSettings.monsterYell,
} }
SayModes = { SayModes = {
@ -56,7 +56,7 @@ ignoreNpcMessages = false
function init() function init()
connect(g_game, { onCreatureSpeak = onCreatureSpeak, connect(g_game, { onTalk = onTalk,
onChannelList = onChannelList, onChannelList = onChannelList,
onOpenChannel = onOpenChannel, onOpenChannel = onOpenChannel,
onOpenPrivateChannel = onOpenPrivateChannel, onOpenPrivateChannel = onOpenPrivateChannel,
@ -94,7 +94,7 @@ function init()
end end
function terminate() function terminate()
disconnect(g_game, { onCreatureSpeak = onCreatureSpeak, disconnect(g_game, { onTalk = onTalk,
onChannelList = onChannelList, onChannelList = onChannelList,
onOpenChannel = onOpenChannel, onOpenChannel = onOpenChannel,
onOpenPrivateChannel = onOpenPrivateChannel, onOpenPrivateChannel = onOpenPrivateChannel,
@ -239,7 +239,7 @@ end
function addPrivateText(text, speaktype, name, isPrivateCommand, creatureName) function addPrivateText(text, speaktype, name, isPrivateCommand, creatureName)
local focus = false local focus = false
if speaktype.speakType == SpeakPrivateNpcToPlayer then if speaktype.speakType == SpeakNpcFrom then
name = 'NPCs' name = 'NPCs'
focus = true focus = true
end end
@ -301,9 +301,9 @@ function popupMenu(mousePos, mouseButton, creatureName, text)
--TODO select all --TODO select all
menu:addOption(tr('Copy message'), function () g_window.setClipboardText(text) end) menu:addOption(tr('Copy message'), function () g_window.setClipboardText(text) end)
if RuleViolation.hasWindowAccess() then if modules.game_ruleviolation.hasWindowAccess() then
menu:addSeparator() menu:addSeparator()
menu:addOption(tr('Rule Violation'), function() RuleViolation.show(creatureName, text:match('.+%:%s(.+)')) end) menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureName, text:match('.+%:%s(.+)')) end)
end end
menu:addSeparator() menu:addSeparator()
@ -448,8 +448,8 @@ function applyMessagePrefixies(name, level, message)
return message return message
end end
function onCreatureSpeak(name, level, speaktype, message, channelId, creaturePos) function onTalk(name, level, speaktype, message, channelId, creaturePos)
if ignoreNpcMessages and speaktype == SpeakPrivateNpcToPlayer then return end if ignoreNpcMessages and speaktype == SpeakNpcFrom then return end
local defaultMessage = speaktype < 3 and true or false local defaultMessage = speaktype < 3 and true or false
speaktype = SpeakTypes[speaktype] speaktype = SpeakTypes[speaktype]
if speaktype.hideInConsole then return end if speaktype.hideInConsole then return end
@ -458,11 +458,6 @@ function onCreatureSpeak(name, level, speaktype, message, channelId, creaturePos
if speaktype.private then if speaktype.private then
addPrivateText(composedMessage, speaktype, name, false, name) addPrivateText(composedMessage, speaktype, name, false, name)
if Options.getOption('showPrivateMessagesOnScreen') then
if(speaktype.speakType ~= SpeakPrivateNpcToPlayer) then
TextMessage.displayPrivate(name .. ':\n' .. message)
end
end
else else
local channel = tr('Default') local channel = tr('Default')
if not defaultMessage then if not defaultMessage then

View File

@ -347,9 +347,9 @@ function createThingMenu(menuPosition, lookThing, useThing, creatureThing)
end end
end end
if RuleViolation.hasWindowAccess() then if modules.game_ruleviolation.hasWindowAccess() then
menu:addSeparator() menu:addSeparator()
menu:addOption(tr('Rule Violation'), function() RuleViolation.show(creatureThing:getName()) end) menu:addOption(tr('Rule Violation'), function() modules.game_ruleviolation.show(creatureThing:getName()) end)
end end
menu:addSeparator() menu:addSeparator()
@ -430,7 +430,7 @@ function processMouseAction(menuPosition, mouseButton, autoWalkPos, lookThing, u
if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then if autoWalkPos and keyboardModifiers == KeyboardNoModifier and mouseButton == MouseLeftButton then
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), autoWalkPos, 127) local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), autoWalkPos, 127)
if #dirs == 0 then if #dirs == 0 then
modules.game_textmessage.displayStatus(tr('There is no way.')) modules.game_textmessage.displayStatusMessage(tr('There is no way.'))
return true return true
end end
g_game.autoWalk(dirs) g_game.autoWalk(dirs)

View File

@ -146,7 +146,7 @@ function onMinimapMouseRelease(self, mousePosition, mouseButton)
if tile and mouseButton == MouseLeftButton and self:isPressed() then if tile and mouseButton == MouseLeftButton and self:isPressed() then
local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), tile:getPosition(), 127) local dirs = g_map.findPath(g_game.getLocalPlayer():getPosition(), tile:getPosition(), 127)
if #dirs == 0 then if #dirs == 0 then
modules.game_textmessage.displayStatus(tr('There is no way.')) modules.game_textmessage.displayStatusMessage(tr('There is no way.'))
return true return true
end end
g_game.autoWalk(dirs) g_game.autoWalk(dirs)

View File

@ -32,7 +32,7 @@ function displayDeadMessage()
return return
end end
modules.game_textmessage.displayEventAdvance(tr('You are dead.')) modules.game_textmessage.displayGameMessage(tr('You are dead.'))
end end
function openWindow() function openWindow()

View File

@ -1,60 +0,0 @@
function getMessageTypes(version)
if version >= 960 then
perror("TODO: message types for 9.6")
return {}
elseif version >= 861 then
return {
[13] = 'ConsoleOrange',
[14] = 'ConsoleOrange',
[15] = 'Warning',
[16] = 'EventAdvance',
[17] = 'EventDefault',
[18] = 'StatusDefault',
[19] = 'Info',
[20] = 'StatusSmall',
[21] = 'ConsoleBlue',
[22] = 'ConsoleRed'
}
elseif version >= 854 then
return {
[18] = 'ConsoleRed',
[19] = 'ConsoleOrange',
[20] = 'ConsoleOrange',
[21] = 'Warning',
[22] = 'EventAdvance',
[23] = 'EventDefault',
[24] = 'StatusDefault',
[25] = 'Info',
[26] = 'StatusSmall',
[27] = 'ConsoleBlue'
}
else
return {
[18] = 'Warning',
[19] = 'EventAdvance',
[20] = 'EventDefault',
[21] = 'StatusDefault',
[22] = 'Info',
[23] = 'StatusSmall',
[24] = 'ConsoleBlue',
[25] = 'ConsoleRed',
[26] = 'ConsoleOrange',
[27] = 'ConsoleOrange',
}
end
end
function parseTextMessage(msg)
local msgtype = msg:getU8()
local text = msg:getString()
msgtype = getMessageTypes(g_game.getClientVersion())[msgtype]
signalcall(g_game.onTextMessage, msgtype, text)
end
function registerProtocol()
ProtocolGame.registerOpcode(GameServerOpcodes.GameServerTextMessage, parseTextMessage)
end
function unregisterProtocol()
ProtocolGame.unregisterOpcode(GameServerOpcodes.GameServerTextMessage)
end

View File

@ -1,115 +1,96 @@
MessageTypes = { MessageSettings = {
ConsoleRed = { color = '#F55E5E', consoleTab = tr('Default') }, consoleRed = { color = TextColors.red, consoleTab='Default' },
ConsoleOrange = { color = '#FE6500', consoleTab = tr('Default') }, consoleOrange = { color = TextColors.orange, consoleTab='Default' },
ConsoleBlue = { color = '#9F9DFD', consoleTab = tr('Default') }, consoleBlue = { color = TextColors.blue, consoleTab='Default' },
Warning = { color = '#F55E5E', consoleTab = tr('Server Log'), labelId = 'warningLabel' }, centerRed = { color = TextColors.red, consoleTab='Server Log', screenTarget='lowCenterLabel' },
Info = { color = '#00EB00', consoleTab = tr('Server Log'), labelId = 'infoLabel', consoleOption = 'showInfoMessagesInConsole' }, centerGreen = { color = TextColors.green, consoleTab='Server Log', screenTarget='highCenterLabel', consoleOption='showInfoMessagesInConsole' },
EventAdvance = { color = '#FFFFFF', consoleTab = tr('Server Log'), labelId = 'advanceLabel', consoleOption = 'showEventMessagesInConsole' }, centerWhite = { color = TextColors.white, consoleTab='Server Log', screenTarget='middleCenterLabel', consoleOption='showEventMessagesInConsole' },
EventDefault = { color = '#FFFFFF', consoleTab = tr('Server Log'), labelId = 'statusLabel', consoleOption = 'showEventMessagesInConsole' }, bottomWhite = { color = TextColors.white, consoleTab='Server Log', screenTarget='statusLabel', consoleOption='showEventMessagesInConsole' },
StatusDefault = { color = '#FFFFFF', consoleTab = tr('Server Log'), labelId = 'statusLabel', consoleOption = 'showStatusMessagesInConsole' }, status = { color = TextColors.white, consoleTab='Server Log', screenTarget='statusLabel', consoleOption='showStatusMessagesInConsole' },
StatusSmall = { color = '#FFFFFF', labelId = 'statusLabel' }, statusSmall = { color = TextColors.white, screenTarget='statusLabel' },
Private = { color = '#5FF7F7', labelId = 'privateLabel' } private = { color = TextColors.lightblue, screenTarget='privateLabel' }
} }
centerTextMessagePanel = nil MessageTypes = {
statusLabel = nil [MessageModes.MonsterSay] = MessageSettings.orange,
privateLabel = nil [MessageModes.MonsterYell] = MessageSettings.orange,
warningLabel = nil [MessageModes.Failure] = MessageSettings.statusSmall,
advanceLabel = nil [MessageModes.Login] = MessageSettings.bottomWhite,
infoLabel = nil [MessageModes.Game] = MessageSettings.centerWhite,
[MessageModes.Status] = MessageSettings.status,
[MessageModes.Warning] = MessageSettings.centerRed,
[MessageModes.Look] = MessageSettings.centerGreen,
[MessageModes.Loot] = MessageSettings.centerGreen,
[MessageModes.Red] = MessageSettings.consoleRed,
[MessageModes.Blue] = MessageSettings.consoleBlue,
[MessageModes.PrivateFrom] = MessageSettings.private
}
messagesPanel = nil
function init() function init()
connect(g_game, { connect(g_game, 'onTextMessage', displayMessage)
onTextMessage = displayMessage, connect(g_game, 'onPrivateTalk', onPrivateTalk)
onGameStart = clearMessages connect(g_game, 'onGameEnd', clearMessages)
}) messagesPanel = g_ui.loadUI('textmessage.otui', modules.game_interface.getRootPanel())
registerProtocol()
g_ui.importStyle('textmessage.otui')
centerTextMessagePanel = g_ui.createWidget('Panel', modules.game_interface.getMapPanel())
centerTextMessagePanel:setId('centerTextMessagePanel')
local layout = UIVerticalLayout.create(centerTextMessagePanel)
layout:setFitChildren(true)
centerTextMessagePanel:setLayout(layout)
centerTextMessagePanel:setWidth(360)
centerTextMessagePanel:centerIn('parent')
warningLabel = createTextMessageLabel('warningLabel', centerTextMessagePanel, 'CenterLabel')
advanceLabel = createTextMessageLabel('advanceLabel', centerTextMessagePanel, 'CenterLabel')
infoLabel = createTextMessageLabel('infoLabel', centerTextMessagePanel, 'CenterLabel')
privateLabel = createTextMessageLabel('privateLabel', modules.game_interface.getMapPanel(), 'TopCenterLabel')
statusLabel = createTextMessageLabel('statusLabel', modules.game_interface.getMapPanel(), 'BottomLabel')
end end
function terminate() function terminate()
disconnect(g_game, { disconnect(g_game, 'onTextMessage', displayMessage)
onTextMessage = display, disconnect(g_game, 'onPrivateTalk', onPrivateTalk)
onGameStart = clearMessages disconnect(g_game, 'onGameEnd',clearMessages)
}) clearMessages()
unregisterProtocol() messagesPanel:destroy()
end
removeEvent(warningLabel.hideEvent) function calculateVisibleTime(text)
removeEvent(advanceLabel.hideEvent) return math.max(#text * 100, 4000)
removeEvent(infoLabel.hideEvent) end
removeEvent(privateLabel.hideEvent)
removeEvent(statusLabel.hideEvent)
centerTextMessagePanel:destroy() function displayMessage(mode, text)
statusLabel:destroy() if not g_game.isOnline() then return end
privateLabel:destroy()
local msgtype = MessageTypes[mode]
if not msgtype then
perror('unhandled message mode ' .. mode)
return
end
if msgtype.consoleTab ~= nil and (msgtype.consoleOption == nil or Options.getOption(msgtype.consoleOption)) then
modules.game_console.addText(text, msgtype, tr(msgtype.consoleTab))
--TODO move to game_console
end
if msgtype.screenTarget then
local label = messagesPanel:recursiveGetChildById(msgtype.screenTarget)
label:setText(text)
label:setColor(msgtype.color)
label:setVisible(true)
removeEvent(label.hideEvent)
label.hideEvent = scheduleEvent(function() label:setVisible(false) end, calculateVisibleTime(text))
end
end
function displayStatusMessage(text)
displayMessage(MessageModes.Status, text)
end
function displayGameMessage(text)
displayMessage(MessageModes.Game, text)
end end
function clearMessages() function clearMessages()
warningLabel:hide() for _i,child in pairs(messagesPanel:recursiveGetChildren()) do
advanceLabel:hide() if child:getId():match('Label') then
infoLabel:hide() child:hide()
privateLabel:hide() removeEvent(child.hideEvent)
statusLabel:hide()
end
function createTextMessageLabel(id, parent, class)
local label = g_ui.createWidget(class, parent)
label:setFont('verdana-11px-rounded')
label:setId(id)
return label
end
function displayMessage(msgtype, msg, time)
if not g_game.isOnline() then return end
msgtype = MessageTypes[msgtype]
if msgtype.consoleTab ~= nil then
if msgtype.consoleOption == nil or Options.getOption(msgtype.consoleOption) then
modules.game_console.addText(msg, msgtype, msgtype.consoleTab)
end end
end end
end
if msgtype.labelId then function onPrivateTalk(code, text, speaker, speakerlevel, statmentid)
local label = modules.game_interface.getMapPanel():recursiveGetChildById(msgtype.labelId) if Options.getOption('showPrivateMessagesOnScreen') then
displayMessage(code, speaker .. ':\n' .. text)
label:setText(msg)
label:setColor(msgtype.color)
if not time then
time = math.max(#msg * 100, 4000)
else
time = time * 1000
end
removeEvent(label.hideEvent)
addEvent(function() label:setVisible(true) end)
label.hideEvent = scheduleEvent(function() label:setVisible(false) end, time)
end end
end end
function displayStatus(msg, time)
displayMessage('StatusSmall', msg)
end
function displayEventAdvance(msg, time)
displayMessage('EventAdvance', msg, time)
end
function displayPrivate(msg, time)
displayMessage('Private', time)
end

View File

@ -4,13 +4,6 @@ Module
author: edubart author: edubart
website: www.otclient.info website: www.otclient.info
sandboxed: true sandboxed: true
scripts: [ textmessage.lua ]
dependencies:
- game_interface
scripts:
- protocol.lua
- textmessage.lua
@onLoad: init() @onLoad: init()
@onUnload: terminate() @onUnload: terminate()

View File

@ -1,4 +1,4 @@
CenterLabel < UILabel TextMessageLabel < UILabel
font: verdana-11px-rounded font: verdana-11px-rounded
text-align: center text-align: center
text-wrap: true text-wrap: true
@ -6,17 +6,35 @@ CenterLabel < UILabel
margin-bottom: 2 margin-bottom: 2
visible: false visible: false
TopCenterLabel < UILabel Panel
font: verdana-11px-rounded anchors.fill: gameMapPanel
text-align: center focusable: false
text-wrap: true
visible: false Panel
id: centerTextMessagePanel
layout:
type: verticalBox
fit-children: true
width: 360
anchors.centerIn: parent
TextMessageLabel
id: highCenterLabel
TextMessageLabel
id: middleCenterLabel
TextMessageLabel
id: lowCenterLabel
TextMessageLabel
id: privateLabel
anchors.top: parent.top anchors.top: parent.top
anchors.bottom: centerTextMessagePanel.top anchors.bottom: centerTextMessagePanel.top
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
text-auto-resize: false
width: 275 width: 275
BottomLabel < CenterLabel TextMessageLabel
id: statusLabel
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right

View File

@ -34,6 +34,13 @@ SouthEast = 5
SouthWest = 6 SouthWest = 6
NorthWest = 7 NorthWest = 7
FightOffensive = 1
FightBalanced = 2
FightDefensive = 3
DontChase = 0
ChaseOpponent = 1
GameExtendedOpcode = 0 GameExtendedOpcode = 0
GameProtocolChecksum = 1 GameProtocolChecksum = 1
GameAccountNames = 2 GameAccountNames = 2
@ -59,6 +66,72 @@ GameReverseCreatureStack = 21
GameMagicEffectU16 = 22 GameMagicEffectU16 = 22
GamePlayerMarket = 23 GamePlayerMarket = 23
TextColors = {
red = '#f55e5e', --'#c83200'
orange = '#f36500', --'#c87832'
yellow = '#ffff00', --'#e6c832'
green = '#00EB00', --'#3fbe32'
lightblue = '#5ff7f7',
--blue1 = '#6e50dc',
--blue2 = '#3264c8',
--blue3 = '#0096c8',
white = '#ffffff' --'#bebebe'
}
MessageModes = {
None = 0,
Say = 1,
Whisper = 2,
Yell = 3,
PrivateFrom = 4,
PrivateTo = 5,
ChannelManagement = 6,
Channel = 7,
ChannelHighlight = 8,
Spell = 9,
NpcFrom = 10,
NpcTo = 11,
GamemasterBroadcast = 12,
GamemasterChannel = 13,
GamemasterPrivateFrom = 14,
GamemasterPrivateTo = 15,
Login = 16,
Warning = 17,
Game = 18,
Failure = 19,
Look = 20,
DamageDealed = 21,
DamageReceived = 22,
Heal = 23,
Exp = 24,
DamageOthers = 25,
HealOthers = 26,
ExpOthers = 27,
Status = 28,
Loot = 29,
TradeNpc = 30,
Guild = 31,
PartyManagement = 32,
Party = 33,
BarkLow = 34,
BarkLoud = 35,
Report = 36,
HotkeyUse = 37,
TutorialHint = 38,
Thankyou = 39,
Market = 40,
BeyondLast = 41,
MonsterYell = 42,
MonsterSay = 43,
Red = 44,
Blue = 45,
RVRChannel = 46,
RVRAnswer = 47,
RVRContinue = 48,
Last = 49,
Invalid = 255
}
OTSERV_RSA = "1091201329673994292788609605089955415282375029027981291234687579" .. OTSERV_RSA = "1091201329673994292788609605089955415282375029027981291234687579" ..
"3726629149257644633073969600111060390723088861007265581882535850" .. "3726629149257644633073969600111060390723088861007265581882535850" ..
"3429057592827629436413108566029093628212635953836686562675849720" .. "3429057592827629436413108566029093628212635953836686562675849720" ..

View File

@ -87,6 +87,7 @@ set(otclient_SOURCES ${otclient_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/luavaluecasts.h ${CMAKE_CURRENT_LIST_DIR}/luavaluecasts.h
# net # net
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolcodes.h ${CMAKE_CURRENT_LIST_DIR}/protocolcodes.h
${CMAKE_CURRENT_LIST_DIR}/protocolgame.cpp ${CMAKE_CURRENT_LIST_DIR}/protocolgame.cpp
${CMAKE_CURRENT_LIST_DIR}/protocolgame.h ${CMAKE_CURRENT_LIST_DIR}/protocolgame.h

View File

@ -255,21 +255,60 @@ namespace Otc
IconPz = 16384 IconPz = 16384
}; };
enum SpeakType { enum MessageMode {
SpeakSay = 1, MessageNone = 0,
SpeakWhisper, MessageSay = 1,
SpeakYell, MessageWhisper = 2,
SpeakBroadcast, MessageYell = 3,
SpeakPrivate, MessagePrivateFrom = 4,
SpeakPrivateRed, MessagePrivateTo = 5,
SpeakPrivatePlayerToNpc, MessageChannelManagement = 6,
SpeakPrivateNpcToPlayer, MessageChannel = 7,
SpeakChannelYellow, MessageChannelHighlight = 8,
SpeakChannelWhite, MessageSpell = 9,
SpeakChannelRed, MessageNpcFrom = 10,
SpeakChannelOrange, MessageNpcTo = 11,
SpeakMonsterSay, MessageGamemasterBroadcast = 12,
SpeakMonsterYell MessageGamemasterChannel = 13,
MessageGamemasterPrivateFrom = 14,
MessageGamemasterPrivateTo = 15,
MessageLogin = 16,
MessageWarning = 17,
MessageGame = 18,
MessageFailure = 19,
MessageLook = 20,
MessageDamageDealed = 21,
MessageDamageReceived = 22,
MessageHeal = 23,
MessageExp = 24,
MessageDamageOthers = 25,
MessageHealOthers = 26,
MessageExpOthers = 27,
MessageStatus = 28,
MessageLoot = 29,
MessageTradeNpc = 30,
MessageGuild = 31,
MessagePartyManagement = 32,
MessageParty = 33,
MessageBarkLow = 34,
MessageBarkLoud = 35,
MessageReport = 36,
MessageHotkeyUse = 37,
MessageTutorialHint = 38,
MessageThankyou = 39,
MessageMarket = 40,
MessageBeyondLast = 41,
// deprecated
MessageMonsterYell = 42,
MessageMonsterSay = 43,
MessageRed = 44,
MessageBlue = 45,
MessageRVRChannel = 46,
MessageRVRAnswer = 47,
MessageRVRContinue = 48,
LastMessage = 49,
MessageInvalid = 255,
}; };
enum GameFeature { enum GameFeature {

View File

@ -57,15 +57,6 @@ Creature::Creature() : Thing()
m_footStep = 0; m_footStep = 0;
} }
/*
PainterShaderProgramPtr outfitProgram;
int HEAD_COLOR_UNIFORM = 10;
int BODY_COLOR_UNIFORM = 11;
int LEGS_COLOR_UNIFORM = 12;
int FEET_COLOR_UNIFORM = 13;
int MASK_TEXTURE_UNIFORM = 14;
*/
void Creature::draw(const Point& dest, float scaleFactor, bool animate) void Creature::draw(const Point& dest, float scaleFactor, bool animate)
{ {
Point animationOffset = animate ? m_walkOffset : Point(0,0); Point animationOffset = animate ? m_walkOffset : Point(0,0);

View File

@ -32,6 +32,7 @@
#include <framework/core/application.h> #include <framework/core/application.h>
#include "luavaluecasts.h" #include "luavaluecasts.h"
#include "protocolgame.h" #include "protocolgame.h"
#include "protocolcodes.h"
Game g_game; Game g_game;
@ -151,22 +152,22 @@ void Game::processPing()
g_lua.callGlobalField("g_game", "onPing"); g_lua.callGlobalField("g_game", "onPing");
} }
void Game::processTextMessage(const std::string& type, const std::string& message) void Game::processTextMessage(Otc::MessageMode mode, const std::string& text)
{ {
g_lua.callGlobalField("g_game","onTextMessage", type, message); g_lua.callGlobalField("g_game", "onTextMessage", mode, text);
} }
void Game::processCreatureSpeak(const std::string& name, int level, Otc::SpeakType type, const std::string& message, int channelId, const Position& creaturePos) void Game::processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos)
{ {
if(creaturePos.isValid() && (type == Otc::SpeakSay || type == Otc::SpeakWhisper || type == Otc::SpeakYell if(pos.isValid() && (mode == Otc::MessageSay || mode == Otc::MessageWhisper || mode == Otc::MessageYell ||
|| type == Otc::SpeakMonsterSay || type == Otc::SpeakMonsterYell || type == Otc::SpeakPrivateNpcToPlayer)) mode == Otc::MessageMonsterSay || mode == Otc::MessageMonsterYell || mode == Otc::MessageNpcFrom))
{ {
StaticTextPtr staticText = StaticTextPtr(new StaticText); StaticTextPtr staticText = StaticTextPtr(new StaticText);
staticText->addMessage(name, type, message); staticText->addMessage(name, mode, text);
g_map.addThing(staticText, creaturePos); g_map.addThing(staticText, pos);
} }
g_lua.callGlobalField("g_game", "onCreatureSpeak", name, level, type, message, channelId, creaturePos); g_lua.callGlobalField("g_game", "onTalk", name, level, mode, text, channelId, pos);
} }
void Game::processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items) void Game::processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items)
@ -769,21 +770,21 @@ void Game::talk(const std::string& message)
{ {
if(!canPerformGameAction() || message.empty()) if(!canPerformGameAction() || message.empty())
return; return;
talkChannel(Otc::SpeakSay, 0, message); talkChannel(Otc::MessageSay, 0, message);
} }
void Game::talkChannel(Otc::SpeakType speakType, int channelId, const std::string& message) void Game::talkChannel(Otc::MessageMode mode, int channelId, const std::string& message)
{ {
if(!canPerformGameAction() || message.empty()) if(!canPerformGameAction() || message.empty())
return; return;
m_protocolGame->sendTalk(speakType, channelId, "", message); m_protocolGame->sendTalk(mode, channelId, "", message);
} }
void Game::talkPrivate(Otc::SpeakType speakType, const std::string& receiver, const std::string& message) void Game::talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message)
{ {
if(!canPerformGameAction() || receiver.empty() || message.empty()) if(!canPerformGameAction() || receiver.empty() || message.empty())
return; return;
m_protocolGame->sendTalk(speakType, 0, receiver, message); m_protocolGame->sendTalk(mode, 0, receiver, message);
} }
void Game::openPrivateChannel(const std::string& receiver) void Game::openPrivateChannel(const std::string& receiver)
@ -1145,6 +1146,8 @@ void Game::setClientVersion(int version)
m_protocolVersion = version; m_protocolVersion = version;
Proto::buildMessageModesMap(version);
g_lua.callGlobalField("g_game", "onClientVersionChange", version); g_lua.callGlobalField("g_game", "onClientVersionChange", version);
} }

View File

@ -60,8 +60,8 @@ protected:
void processWalkCancel(Otc::Direction direction); void processWalkCancel(Otc::Direction direction);
// message related // message related
void processTextMessage(const std::string& type, const std::string& message); // deprecated void processTextMessage(Otc::MessageMode mode, const std::string& text);
void processCreatureSpeak(const std::string& name, int level, Otc::SpeakType type, const std::string& message, int channelId, const Position& creaturePos); void processTalk(const std::string& name, int level, Otc::MessageMode mode, const std::string& text, int channelId, const Position& pos);
// container related // container related
void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items); void processOpenContainer(int containerId, const ItemPtr& containerItem, const std::string& name, int capacity, bool hasParent, const std::vector<ItemPtr>& items);
@ -155,8 +155,8 @@ public:
// talk related // talk related
void talk(const std::string& message); void talk(const std::string& message);
void talkChannel(Otc::SpeakType speakType, int channelId, const std::string& message); void talkChannel(Otc::MessageMode mode, int channelId, const std::string& message);
void talkPrivate(Otc::SpeakType speakType, const std::string& receiver, const std::string& message); void talkPrivate(Otc::MessageMode mode, const std::string& receiver, const std::string& message);
// channel related // channel related
void openPrivateChannel(const std::string& receiver); void openPrivateChannel(const std::string& receiver);

View File

@ -618,7 +618,7 @@ void Map::addThing(const ThingPtr& thing, const Position& pos, int stackPos)
StaticTextPtr cStaticText = *it; StaticTextPtr cStaticText = *it;
if(cStaticText->getPosition() == pos) { if(cStaticText->getPosition() == pos) {
// try to combine messages // try to combine messages
if(cStaticText->addMessage(staticText->getName(), staticText->getMessageType(), staticText->getFirstMessage())) { if(cStaticText->addMessage(staticText->getName(), staticText->getMessageMode(), staticText->getFirstMessage())) {
mustAdd = false; mustAdd = false;
break; break;
} else { } else {

View File

@ -0,0 +1,138 @@
/*
* Copyright (c) 2010-2012 OTClient <https://github.com/edubart/otclient>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "protocolcodes.h"
namespace Proto {
std::map<uint8, uint8> messageModesMap;
void buildMessageModesMap(int version) {
messageModesMap.clear();
if(version >= 900) {
for(int i=Otc::MessageNone;i<=Otc::MessageBeyondLast;++i)
messageModesMap[i] = i;
} else if(version >= 861) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessageNpcFrom] = 4;
messageModesMap[Otc::MessageNpcTo] = 5;
messageModesMap[Otc::MessagePrivateFrom] = 6;
messageModesMap[Otc::MessagePrivateTo] = 6;
messageModesMap[Otc::MessageChannelHighlight] = 7;
messageModesMap[Otc::MessageChannel] = 8;
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
messageModesMap[Otc::MessageGamemasterChannel] = 10;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
messageModesMap[Otc::MessageChannelManagement] = 12;
messageModesMap[Otc::MessageMonsterSay] = 13;
messageModesMap[Otc::MessageMonsterYell] = 14;
messageModesMap[Otc::MessageWarning] = 15;
messageModesMap[Otc::MessageGame] = 16;
messageModesMap[Otc::MessageLogin] = 17;
messageModesMap[Otc::MessageStatus] = 18;
messageModesMap[Otc::MessageLook] = 19;
messageModesMap[Otc::MessageFailure] = 20;
messageModesMap[Otc::MessageBlue] = 21;
messageModesMap[Otc::MessageRed] = 22;
} else if(version >= 854) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessageNpcFrom] = 4;
messageModesMap[Otc::MessageNpcTo] = 5;
messageModesMap[Otc::MessagePrivateFrom] = 6;
messageModesMap[Otc::MessagePrivateTo] = 6;
messageModesMap[Otc::MessageChannel] = 7;
messageModesMap[Otc::MessageChannelManagement] = 8;
messageModesMap[Otc::MessageRVRChannel] = 9;
messageModesMap[Otc::MessageRVRAnswer] = 10;
messageModesMap[Otc::MessageRVRContinue] = 11;
messageModesMap[Otc::MessageGamemasterBroadcast] = 12;
messageModesMap[Otc::MessageGamemasterChannel] = 13;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 14;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 14;
messageModesMap[Otc::MessageChannelHighlight] = 15;
// 16, 17, 18 ??
messageModesMap[Otc::MessageRed] = 18;
messageModesMap[Otc::MessageMonsterSay] = 19;
messageModesMap[Otc::MessageMonsterYell] = 20;
messageModesMap[Otc::MessageWarning] = 21;
messageModesMap[Otc::MessageGame] = 22;
messageModesMap[Otc::MessageLogin] = 23;
messageModesMap[Otc::MessageStatus] = 24;
messageModesMap[Otc::MessageLook] = 25;
messageModesMap[Otc::MessageFailure] = 26;
messageModesMap[Otc::MessageBlue] = 27;
} else if(version >= 810) {
messageModesMap[Otc::MessageNone] = 0;
messageModesMap[Otc::MessageSay] = 1;
messageModesMap[Otc::MessageWhisper] = 2;
messageModesMap[Otc::MessageYell] = 3;
messageModesMap[Otc::MessagePrivateFrom] = 4;
messageModesMap[Otc::MessagePrivateTo] = 4;
messageModesMap[Otc::MessageChannel] = 5;
messageModesMap[Otc::MessageRVRChannel] = 6;
messageModesMap[Otc::MessageRVRAnswer] = 7;
messageModesMap[Otc::MessageRVRContinue] = 8;
messageModesMap[Otc::MessageGamemasterBroadcast] = 9;
messageModesMap[Otc::MessageGamemasterChannel] = 10;
messageModesMap[Otc::MessageGamemasterPrivateFrom] = 11;
messageModesMap[Otc::MessageGamemasterPrivateTo] = 11;
messageModesMap[Otc::MessageChannelHighlight] = 12;
// 13, 14, 15 ??
messageModesMap[Otc::MessageMonsterSay] = 16;
messageModesMap[Otc::MessageMonsterYell] = 17;
messageModesMap[Otc::MessageWarning] = 18;
messageModesMap[Otc::MessageGame] = 19;
messageModesMap[Otc::MessageLogin] = 20;
messageModesMap[Otc::MessageStatus] = 21;
messageModesMap[Otc::MessageLook] = 22;
messageModesMap[Otc::MessageFailure] = 23;
messageModesMap[Otc::MessageBlue] = 24;
messageModesMap[Otc::MessageRed] = 25;
}
}
Otc::MessageMode translateMessageModeFromServer(uint8 mode)
{
auto it = std::find_if(messageModesMap.begin(), messageModesMap.end(), [=] (const std::pair<uint8, uint8>& p) { return p.second == mode; });
if(it != messageModesMap.end())
return (Otc::MessageMode)it->first;
return Otc::MessageInvalid;
}
uint8 translateMessageModeToServer(Otc::MessageMode mode)
{
if(mode < 0 || mode >= Otc::LastMessage)
return Otc::MessageInvalid;
auto it = messageModesMap.find(mode);
if(it != messageModesMap.end())
return it->second;
return Otc::MessageInvalid;
}
}

View File

@ -39,7 +39,8 @@ namespace Proto {
Creature = 99 Creature = 99
}; };
enum GameServerOpcodes { enum GameServerOpcodes : uint8
{
GameServerInitGame = 10, GameServerInitGame = 10,
GameServerGMActions = 11, GameServerGMActions = 11,
GameServerLoginError = 20, GameServerLoginError = 20,
@ -139,7 +140,8 @@ namespace Proto {
GameServerShowModalDialog = 250 // 960 GameServerShowModalDialog = 250 // 960
}; };
enum ClientOpcodes { enum ClientOpcodes : uint8
{
ClientEnterAccount = 1, ClientEnterAccount = 1,
ClientEnterGame = 10, ClientEnterGame = 10,
ClientLeaveGame = 20, ClientLeaveGame = 20,
@ -230,107 +232,6 @@ namespace Proto {
ClientAnswerModalDialog = 249 // 960 ClientAnswerModalDialog = 249 // 960
}; };
enum ServerSpeakType {
#if PROTOCOL>=910
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivateFrom, // new
ServerSpeakPrivateTo, // new
ServerSpeakChannelManagement, // new
ServerSpeakChannelYellow,
ServerSpeakChannelOrange,
ServerSpeakSpell, // new
ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedFrom, // new
ServerSpeakPrivateRedTo, // new
// 16 - 33
ServerSpeakMonsterSay = 34,
ServerSpeakMonsterYell,
// unsupported
ServerSpeakRVRChannel = 255,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakChannelRed2,
ServerSpeakChannelWhite
#elif PROTOCOL>=861
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow,
ServerSpeakChannelWhite,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange,
ServerSpeakMonsterSay,
ServerSpeakMonsterYell,
// unsupported
ServerSpeakRVRChannel = 255,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakChannelRed2
#elif PROTOCOL>=854
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivatePlayerToNpc,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow,
ServerSpeakChannelWhite,
ServerSpeakRVRChannel,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange,
// 16
ServerSpeakChannelRed2 = 17,
// 18
ServerSpeakMonsterSay = 19,
ServerSpeakMonsterYell
#elif PROTOCOL>=810
ServerSpeakSay = 1,
ServerSpeakWhisper,
ServerSpeakYell,
ServerSpeakPrivateTo,
ServerSpeakPrivateFrom = ServerSpeakPrivateTo,
ServerSpeakChannelYellow,
ServerSpeakRVRChannel,
ServerSpeakRVRAnswer,
ServerSpeakRVRContinue,
ServerSpeakBroadcast,
ServerSpeakChannelRed,
ServerSpeakPrivateRedTo,
ServerSpeakPrivateRedFrom = ServerSpeakPrivateRedTo,
ServerSpeakChannelOrange,
// 13
ServerSpeakChannelRed2 = 14,
// 15
ServerSpeakMonsterSay = 16,
ServerSpeakMonsterYell,
// unsupported
ServerSpeakPrivatePlayerToNpc = 255,
ServerSpeakPrivateNpcToPlayer,
ServerSpeakChannelWhite
#endif
};
enum CreatureType { enum CreatureType {
CreatureTypePlayer = 0, CreatureTypePlayer = 0,
CreatureTypeMonster, CreatureTypeMonster,
@ -346,50 +247,9 @@ namespace Proto {
NpcEndId = 0xffffffff NpcEndId = 0xffffffff
}; };
inline Otc::SpeakType translateSpeakTypeFromServer(int type) { void buildMessageModesMap(int version);
switch(type) { Otc::MessageMode translateMessageModeFromServer(uint8 mode);
case Proto::ServerSpeakSay: return Otc::SpeakSay; uint8 translateMessageModeToServer(Otc::MessageMode mode);
case Proto::ServerSpeakWhisper: return Otc::SpeakWhisper;
case Proto::ServerSpeakYell: return Otc::SpeakYell;
case Proto::ServerSpeakMonsterSay: return Otc::SpeakMonsterSay;
case Proto::ServerSpeakMonsterYell: return Otc::SpeakMonsterYell;
case Proto::ServerSpeakPrivateNpcToPlayer: return Otc::SpeakPrivateNpcToPlayer;
case Proto::ServerSpeakChannelYellow: return Otc::SpeakChannelYellow;
case Proto::ServerSpeakChannelWhite: return Otc::SpeakChannelWhite;
case Proto::ServerSpeakChannelRed: return Otc::SpeakChannelRed;
case Proto::ServerSpeakChannelRed2: return Otc::SpeakChannelRed;
case Proto::ServerSpeakChannelOrange: return Otc::SpeakChannelOrange;
case Proto::ServerSpeakPrivateTo: return Otc::SpeakPrivate;
case Proto::ServerSpeakPrivatePlayerToNpc: return Otc::SpeakPrivate;
case Proto::ServerSpeakBroadcast: return Otc::SpeakBroadcast;
case Proto::ServerSpeakPrivateRedTo: return Otc::SpeakPrivateRed;
default:
g_logger.error(stdext::format("unknown protocol speak type %d", type));
return Otc::SpeakSay;
}
}
inline Proto::ServerSpeakType translateSpeakTypeToServer(int type) {
switch(type) {
case Otc::SpeakSay: return Proto::ServerSpeakSay;
case Otc::SpeakWhisper: return Proto::ServerSpeakWhisper;
case Otc::SpeakYell: return Proto::ServerSpeakYell;
case Otc::SpeakBroadcast: return Proto::ServerSpeakBroadcast;
case Otc::SpeakPrivate: return Proto::ServerSpeakPrivateFrom;
case Otc::SpeakPrivateRed: return Proto::ServerSpeakPrivateRedFrom;
case Otc::SpeakPrivatePlayerToNpc: return Proto::ServerSpeakPrivatePlayerToNpc;
case Otc::SpeakPrivateNpcToPlayer: return Proto::ServerSpeakPrivateNpcToPlayer;
case Otc::SpeakChannelYellow: return Proto::ServerSpeakChannelYellow;
case Otc::SpeakChannelWhite: return Proto::ServerSpeakChannelWhite;
case Otc::SpeakChannelRed: return Proto::ServerSpeakChannelRed;
case Otc::SpeakChannelOrange: return Proto::ServerSpeakChannelOrange;
case Otc::SpeakMonsterSay: return Proto::ServerSpeakMonsterSay;
case Otc::SpeakMonsterYell: return Proto::ServerSpeakMonsterYell;
default:
g_logger.error(stdext::format("unknown protocol speak type desc %d", type));
return Proto::ServerSpeakSay;
}
}
} }
#endif #endif

View File

@ -72,7 +72,7 @@ public:
void sendEditText(uint id, const std::string& text); void sendEditText(uint id, const std::string& text);
void sendEditList(uint id, int doorId, const std::string& text); void sendEditList(uint id, int doorId, const std::string& text);
void sendLook(const Position& position, int thingId, int stackpos); void sendLook(const Position& position, int thingId, int stackpos);
void sendTalk(Otc::SpeakType speakType, int channelId, const std::string& receiver, const std::string& message); void sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message);
void sendRequestChannels(); void sendRequestChannels();
void sendJoinChannel(int channelId); void sendJoinChannel(int channelId);
void sendLeaveChannel(int channelId); void sendLeaveChannel(int channelId);
@ -169,7 +169,7 @@ private:
void parseSpellCooldown(const InputMessagePtr& msg); void parseSpellCooldown(const InputMessagePtr& msg);
void parseSpellGroupCooldown(const InputMessagePtr& msg); void parseSpellGroupCooldown(const InputMessagePtr& msg);
void parseMultiUseCooldown(const InputMessagePtr& msg); void parseMultiUseCooldown(const InputMessagePtr& msg);
void parseCreatureSpeak(const InputMessagePtr& msg); void parseTalk(const InputMessagePtr& msg);
void parseChannelList(const InputMessagePtr& msg); void parseChannelList(const InputMessagePtr& msg);
void parseOpenChannel(const InputMessagePtr& msg); void parseOpenChannel(const InputMessagePtr& msg);
void parseOpenPrivateChannel(const InputMessagePtr& msg); void parseOpenPrivateChannel(const InputMessagePtr& msg);

View File

@ -211,7 +211,7 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
parsePlayerCancelAttack(msg); parsePlayerCancelAttack(msg);
break; break;
case Proto::GameServerTalk: case Proto::GameServerTalk:
parseCreatureSpeak(msg); parseTalk(msg);
break; break;
case Proto::GameServerChannels: case Proto::GameServerChannels:
parseChannelList(msg); parseChannelList(msg);
@ -469,7 +469,6 @@ void ProtocolGame::parseTileTransformThing(const InputMessagePtr& msg)
Position pos = thing->getPosition(); Position pos = thing->getPosition();
int stackpos = thing->getStackpos(); int stackpos = thing->getStackpos();
assert(thing->getStackPriority() == newThing->getStackPriority());
if(!g_map.removeThing(thing)) { if(!g_map.removeThing(thing)) {
g_logger.traceError("unable to remove thing"); g_logger.traceError("unable to remove thing");
@ -938,51 +937,49 @@ void ProtocolGame::parseMultiUseCooldown(const InputMessagePtr& msg)
msg->getU32(); // cooldown msg->getU32(); // cooldown
} }
void ProtocolGame::parseCreatureSpeak(const InputMessagePtr& msg) void ProtocolGame::parseTalk(const InputMessagePtr& msg)
{ {
msg->getU32(); // channel statement guid msg->getU32(); // channel statement guid
std::string name = msg->getString(); std::string name = msg->getString();
int level = msg->getU16(); int level = msg->getU16();
int speakType = msg->getU8(); Otc::MessageMode mode = Proto::translateMessageModeFromServer(msg->getU8());
int channelId = 0; int channelId = 0;
Position creaturePos; Position pos;
switch(speakType) { switch(mode) {
case Proto::ServerSpeakSay: case Otc::MessageSay:
case Proto::ServerSpeakWhisper: case Otc::MessageWhisper:
case Proto::ServerSpeakYell: case Otc::MessageYell:
case Proto::ServerSpeakMonsterSay: case Otc::MessageMonsterSay:
case Proto::ServerSpeakMonsterYell: case Otc::MessageMonsterYell:
case Proto::ServerSpeakPrivateNpcToPlayer: case Otc::MessageNpcFrom:
creaturePos = getPosition(msg); case Otc::MessageBarkLow:
case Otc::MessageBarkLoud:
case Otc::MessageSpell:
pos = getPosition(msg);
break; break;
case Proto::ServerSpeakChannelYellow: case Otc::MessageChannel:
case Proto::ServerSpeakChannelWhite: case Otc::MessageChannelManagement:
case Proto::ServerSpeakChannelRed: case Otc::MessageChannelHighlight:
case Proto::ServerSpeakChannelRed2: case Otc::MessageGamemasterChannel:
case Proto::ServerSpeakChannelOrange:
channelId = msg->getU16(); channelId = msg->getU16();
break; break;
case Proto::ServerSpeakPrivateFrom: case Otc::MessagePrivateFrom:
case Proto::ServerSpeakPrivatePlayerToNpc: case Otc::MessageGamemasterBroadcast:
case Proto::ServerSpeakBroadcast: case Otc::MessageGamemasterPrivateFrom:
case Proto::ServerSpeakPrivateRedFrom:
break; break;
case Proto::ServerSpeakRVRChannel: case Otc::MessageRVRChannel:
msg->getU32(); msg->getU32();
break; break;
//case Proto::ServerSpeakChannelManagement:
//case Proto::ServerSpeakSpell:
default: default:
stdext::throw_exception(stdext::format("unknown speak type %d", speakType)); stdext::throw_exception(stdext::format("unknown message mode %d", mode));
break; break;
} }
std::string message = msg->getString(); std::string text = msg->getString();
Otc::SpeakType type = Proto::translateSpeakTypeFromServer(speakType);
g_game.processCreatureSpeak(name, level, type, message, channelId, creaturePos); g_game.processTalk(name, level, mode, text, channelId, pos);
} }
void ProtocolGame::parseChannelList(const InputMessagePtr& msg) void ProtocolGame::parseChannelList(const InputMessagePtr& msg)
@ -1066,9 +1063,58 @@ void ProtocolGame::parseRuleViolationLock(const InputMessagePtr& msg)
void ProtocolGame::parseTextMessage(const InputMessagePtr& msg) void ProtocolGame::parseTextMessage(const InputMessagePtr& msg)
{ {
msg->getU8(); // type int code = msg->getU8();
msg->getString(); // message Otc::MessageMode mode = Proto::translateMessageModeFromServer(code);
// this is now handled by game_textmessage module std::string text;
switch(mode) {
case Otc::MessageChannelManagement: {
int channel = msg->getU16();
text = msg->getString();
break;
}
case Otc::MessageDamageDealed:
case Otc::MessageDamageReceived:
case Otc::MessageDamageOthers: {
Position pos = getPosition(msg);
uint value = msg->getU32();
int color = msg->getU8();
msg->getU32(); // ??
msg->getU8(); // ??
text = msg->getString();
AnimatedTextPtr animatedText = AnimatedTextPtr(new AnimatedText);
animatedText->setColor(color);
animatedText->setText(stdext::to_string(value));
g_map.addThing(animatedText, pos);
break;
}
case Otc::MessageHeal:
case Otc::MessageExp:
case Otc::MessageHealOthers:
case Otc::MessageExpOthers: {
Position pos = getPosition(msg);
uint value = msg->getU32();
int color = msg->getU8();
msg->getU32(); // ??
msg->getU8(); // ??
text = msg->getString();
AnimatedTextPtr animatedText = AnimatedTextPtr(new AnimatedText);
animatedText->setColor(color);
animatedText->setText(stdext::to_string(value));
g_map.addThing(animatedText, pos);
break;
}
case Otc::MessageInvalid:
stdext::throw_exception(stdext::format("unknown message mode %d", mode));
break;
default:
text = msg->getString();
break;
}
g_game.processTextMessage(mode, text);
} }
void ProtocolGame::parseCancelWalk(const InputMessagePtr& msg) void ProtocolGame::parseCancelWalk(const InputMessagePtr& msg)

View File

@ -435,26 +435,33 @@ void ProtocolGame::sendLook(const Position& position, int thingId, int stackpos)
send(msg); send(msg);
} }
void ProtocolGame::sendTalk(Otc::SpeakType speakType, int channelId, const std::string& receiver, const std::string& message) void ProtocolGame::sendTalk(Otc::MessageMode mode, int channelId, const std::string& receiver, const std::string& message)
{ {
if(message.length() > 255 || message.length() <= 0) if(message.empty())
return; return;
int serverSpeakType = Proto::translateSpeakTypeToServer(speakType); if(message.length() > 255) {
g_logger.traceError("message too large");
return;
}
OutputMessagePtr msg(new OutputMessage); OutputMessagePtr msg(new OutputMessage);
msg->addU8(Proto::ClientTalk); msg->addU8(Proto::ClientTalk);
msg->addU8(serverSpeakType); msg->addU8(Proto::translateMessageModeToServer(mode));
switch(serverSpeakType) { switch(mode) {
case Proto::ServerSpeakPrivateFrom: case Otc::MessagePrivateTo:
case Proto::ServerSpeakPrivateRedFrom: case Otc::MessageGamemasterPrivateTo:
msg->addString(receiver); msg->addString(receiver);
break; break;
case Proto::ServerSpeakChannelYellow: case Otc::MessageChannel:
case Proto::ServerSpeakChannelRed: case Otc::MessageChannelHighlight:
case Otc::MessageChannelManagement:
case Otc::MessageGamemasterChannel:
msg->addU16(channelId); msg->addU16(channelId);
break; break;
default:
break;
} }
msg->addString(message); msg->addString(message);

View File

@ -47,16 +47,16 @@ void StaticText::drawText(const Point& dest, const Rect& parentRect)
//} //}
} }
bool StaticText::addMessage(const std::string& name, Otc::SpeakType type, const std::string& message) bool StaticText::addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text)
{ {
//TODO: this could be moved to lua //TODO: this could be moved to lua
// first message // first message
if(m_messages.size() == 0) { if(m_messages.size() == 0) {
m_name = name; m_name = name;
m_messageType = type; m_mode = mode;
} }
// check if we can really own the message // check if we can really own the message
else if(m_name != name || m_messageType != type) { else if(m_name != name || m_mode != mode) {
return false; return false;
} }
// too many messages // too many messages
@ -66,7 +66,7 @@ bool StaticText::addMessage(const std::string& name, Otc::SpeakType type, const
m_updateEvent = nullptr; m_updateEvent = nullptr;
} }
m_messages.push_back(message); m_messages.push_back(text);
compose(); compose();
if(!m_updateEvent) if(!m_updateEvent)
@ -105,26 +105,26 @@ void StaticText::compose()
//TODO: this could be moved to lua //TODO: this could be moved to lua
std::string text; std::string text;
if(m_messageType == Otc::SpeakSay) { if(m_mode == Otc::MessageSay) {
text += m_name; text += m_name;
text += " says:\n"; text += " says:\n";
m_color = Color(239, 239, 0); m_color = Color(239, 239, 0);
} else if(m_messageType == Otc::SpeakWhisper) { } else if(m_mode == Otc::MessageWhisper) {
text += m_name; text += m_name;
text += " whispers:\n"; text += " whispers:\n";
m_color = Color(239, 239, 0); m_color = Color(239, 239, 0);
} else if(m_messageType == Otc::SpeakYell) { } else if(m_mode == Otc::MessageYell) {
text += m_name; text += m_name;
text += " yells:\n"; text += " yells:\n";
m_color = Color(239, 239, 0); m_color = Color(239, 239, 0);
} else if(m_messageType == Otc::SpeakMonsterSay || m_messageType == Otc::SpeakMonsterYell) { } else if(m_mode == Otc::MessageMonsterSay || m_mode == Otc::MessageMonsterYell) {
m_color = Color(254, 101, 0); m_color = Color(254, 101, 0);
} else if(m_messageType == Otc::SpeakPrivateNpcToPlayer) { } else if(m_mode == Otc::MessageNpcFrom) {
text += m_name; text += m_name;
text += " says:\n"; text += " says:\n";
m_color = Color(95, 247, 247); m_color = Color(95, 247, 247);
} else { } else {
g_logger.warning(stdext::format("Unknown speak type: %d", m_messageType)); g_logger.warning(stdext::format("Unknown speak type: %d", m_mode));
} }
for(uint i = 0; i < m_messages.size(); ++i) { for(uint i = 0; i < m_messages.size(); ++i) {

View File

@ -36,12 +36,12 @@ public:
void drawText(const Point& dest, const Rect& parentRect); void drawText(const Point& dest, const Rect& parentRect);
std::string getName() { return m_name; } std::string getName() { return m_name; }
Otc::SpeakType getMessageType() { return m_messageType; } Otc::MessageMode getMessageMode() { return m_mode; }
std::string getFirstMessage() { return m_messages[0]; } std::string getFirstMessage() { return m_messages[0]; }
bool isYell() { return m_messageType == Otc::SpeakYell || m_messageType == Otc::SpeakMonsterYell; } bool isYell() { return m_mode == Otc::MessageYell || m_mode == Otc::MessageMonsterYell; }
bool addMessage(const std::string& name, Otc::SpeakType type, const std::string& message); bool addMessage(const std::string& name, Otc::MessageMode mode, const std::string& text);
StaticTextPtr asStaticText() { return std::static_pointer_cast<StaticText>(shared_from_this()); } StaticTextPtr asStaticText() { return std::static_pointer_cast<StaticText>(shared_from_this()); }
bool isStaticText() { return true; } bool isStaticText() { return true; }
@ -54,7 +54,7 @@ private:
Boolean<false> m_yell; Boolean<false> m_yell;
std::deque<std::string> m_messages; std::deque<std::string> m_messages;
std::string m_name; std::string m_name;
Otc::SpeakType m_messageType; Otc::MessageMode m_mode;
Color m_color; Color m_color;
CachedText m_cachedText; CachedText m_cachedText;
ScheduledEventPtr m_updateEvent; ScheduledEventPtr m_updateEvent;

View File

@ -192,6 +192,17 @@ ThingPtr Tile::addThing(const ThingPtr& thing, int stackPos)
if(m_things.size() > MAX_THINGS) if(m_things.size() > MAX_THINGS)
removeThing(m_things[MAX_THINGS]); removeThing(m_things[MAX_THINGS]);
/*
// check stack priorities
// this code exists to find stackpos bugs faster
int lastPriority = 0;
for(const ThingPtr& thing : m_things) {
int priority = thing->getStackPriority();
assert(lastPriority <= priority);
lastPriority = priority;
}
*/
update(); update();
return oldObject; return oldObject;
} }
@ -510,13 +521,4 @@ void Tile::update()
if(c != 0) if(c != 0)
m_minimapColorByte = c; m_minimapColorByte = c;
} }
// check stack priorities
// this code exists to find stackpos bugs faster
int lastPriority = 0;
for(const ThingPtr& thing : m_things) {
int priority = thing->getStackPriority();
assert(lastPriority <= priority);
lastPriority = priority;
}
} }