New module and changes
* Implementing rule violation interface * New popup menu on console text messages * Terminal and Console will no longer history double command/messages
This commit is contained in:
parent
4f08a288ca
commit
69614da8cb
|
@ -211,10 +211,12 @@ function Terminal.executeCommand(command)
|
||||||
currentHistoryIndex = 0
|
currentHistoryIndex = 0
|
||||||
|
|
||||||
-- add new command to history
|
-- add new command to history
|
||||||
|
if #commandHistory == 0 or commandHistory[#commandHistory] ~= command then
|
||||||
table.insert(commandHistory, command)
|
table.insert(commandHistory, command)
|
||||||
if #commandHistory > MaxHistory then
|
if #commandHistory > MaxHistory then
|
||||||
table.remove(commandHistory, 1)
|
table.remove(commandHistory, 1)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- add command line
|
-- add command line
|
||||||
Terminal.addLine(">> " .. command, "#ffffff")
|
Terminal.addLine(">> " .. command, "#ffffff")
|
||||||
|
|
|
@ -26,6 +26,7 @@ Module
|
||||||
- game_textbooks
|
- game_textbooks
|
||||||
- game_playertrade
|
- game_playertrade
|
||||||
- game_questlog
|
- game_questlog
|
||||||
|
- game_ruleviolation
|
||||||
|
|
||||||
@onLoad: |
|
@onLoad: |
|
||||||
importStyle 'styles/items.otui'
|
importStyle 'styles/items.otui'
|
||||||
|
|
|
@ -266,6 +266,11 @@ function GameInterface.createThingMenu(menuPosition, lookThing, useThing, creatu
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if RuleViolation.hasWindowAccess() then
|
||||||
|
menu:addSeparator()
|
||||||
|
menu:addOption(tr('Rule Violation'), function() RuleViolation.show(creatureThing:getName()) end)
|
||||||
|
end
|
||||||
|
|
||||||
menu:addSeparator()
|
menu:addSeparator()
|
||||||
menu:addOption(tr('Copy Name'), function() g_window.setClipboardText(creatureThing:getName()) end)
|
menu:addOption(tr('Copy Name'), function() g_window.setClipboardText(creatureThing:getName()) end)
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ local function onCreatureSpeak(name, level, speaktype, message, channelId, creat
|
||||||
message = applyMessagePrefixies(name, level, message)
|
message = applyMessagePrefixies(name, level, message)
|
||||||
|
|
||||||
if speaktype.private then
|
if speaktype.private then
|
||||||
Console.addPrivateText(message, speaktype, name, false)
|
Console.addPrivateText(message, speaktype, name, false, name)
|
||||||
else
|
else
|
||||||
local channel = tr('Default')
|
local channel = tr('Default')
|
||||||
if not defaultMessage then
|
if not defaultMessage then
|
||||||
|
@ -97,7 +97,7 @@ local function onCreatureSpeak(name, level, speaktype, message, channelId, creat
|
||||||
end
|
end
|
||||||
|
|
||||||
if channel then
|
if channel then
|
||||||
Console.addText(message, speaktype, channel)
|
Console.addText(message, speaktype, channel, name)
|
||||||
elseif channelId ~= 0 then
|
elseif channelId ~= 0 then
|
||||||
-- server sent a message on a channel that is not open
|
-- server sent a message on a channel that is not open
|
||||||
warning('message in channel id ' .. channelId .. ' which is unknown, this is a server bug, relogin if you want to see messages in this channel')
|
warning('message in channel id ' .. channelId .. ' which is unknown, this is a server bug, relogin if you want to see messages in this channel')
|
||||||
|
@ -334,7 +334,7 @@ function Console.addChannel(name, id)
|
||||||
return tab
|
return tab
|
||||||
end
|
end
|
||||||
|
|
||||||
function Console.addPrivateText(text, speaktype, name, isPrivateCommand)
|
function Console.addPrivateText(text, speaktype, name, isPrivateCommand, creatureName)
|
||||||
local focus = false
|
local focus = false
|
||||||
if speaktype.speakType == SpeakPrivateNpcToPlayer then
|
if speaktype.speakType == SpeakPrivateNpcToPlayer then
|
||||||
name = 'NPCs'
|
name = 'NPCs'
|
||||||
|
@ -352,17 +352,17 @@ function Console.addPrivateText(text, speaktype, name, isPrivateCommand)
|
||||||
elseif focus then
|
elseif focus then
|
||||||
consoleTabBar:selectTab(privateTab)
|
consoleTabBar:selectTab(privateTab)
|
||||||
end
|
end
|
||||||
Console.addTabText(text, speaktype, privateTab)
|
Console.addTabText(text, speaktype, privateTab, creatureName)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Console.addText(text, speaktype, tabName)
|
function Console.addText(text, speaktype, tabName, creatureName)
|
||||||
local tab = Console.getTab(tabName)
|
local tab = Console.getTab(tabName)
|
||||||
if tab ~= nil then
|
if tab ~= nil then
|
||||||
Console.addTabText(text, speaktype, tab)
|
Console.addTabText(text, speaktype, tab, creatureName)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function Console.addTabText(text, speaktype, tab)
|
function Console.addTabText(text, speaktype, tab, creatureName)
|
||||||
if Options.getOption('showTimestampsInConsole') then
|
if Options.getOption('showTimestampsInConsole') then
|
||||||
text = os.date('%H:%M') .. ' ' .. text
|
text = os.date('%H:%M') .. ' ' .. text
|
||||||
end
|
end
|
||||||
|
@ -375,11 +375,41 @@ function Console.addTabText(text, speaktype, tab)
|
||||||
label:setColor(speaktype.color)
|
label:setColor(speaktype.color)
|
||||||
consoleTabBar:blinkTab(tab)
|
consoleTabBar:blinkTab(tab)
|
||||||
|
|
||||||
|
label.onMouseRelease = function (self, mousePos, mouseButton) Console.popupMenu(mousePos, mouseButton, creatureName, text) end
|
||||||
|
|
||||||
if consoleBuffer:getChildCount() > MAX_LINES then
|
if consoleBuffer:getChildCount() > MAX_LINES then
|
||||||
consoleBuffer:getFirstChild():destroy()
|
consoleBuffer:getFirstChild():destroy()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function Console.popupMenu(mousePos, mouseButton, creatureName, text)
|
||||||
|
if mouseButton == MouseRightButton then
|
||||||
|
local menu = createWidget('PopupMenu')
|
||||||
|
if creatureName then
|
||||||
|
if creatureName ~= g_game.getLocalPlayer():getName() then
|
||||||
|
menu:addOption(tr('Message to ' .. creatureName), function () g_game.openPrivateChannel(creatureName) end)
|
||||||
|
menu:addOption(tr('Add to VIP list'), function () g_game.addVip(creatureName) end) --TODO not show if creature already in vip
|
||||||
|
-- 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 Console.sendCurrentMessage()
|
function Console.sendCurrentMessage()
|
||||||
local message = consoleTextEdit:getText()
|
local message = consoleTextEdit:getText()
|
||||||
if #message == 0 then return end
|
if #message == 0 then return end
|
||||||
|
@ -419,10 +449,12 @@ function Console.sendCurrentMessage()
|
||||||
|
|
||||||
-- add new command to history
|
-- add new command to history
|
||||||
currentMessageIndex = 0
|
currentMessageIndex = 0
|
||||||
|
if #messageHistory == 0 or messageHistory[#messageHistory] ~= originalMessage then
|
||||||
table.insert(messageHistory, originalMessage)
|
table.insert(messageHistory, originalMessage)
|
||||||
if #messageHistory > MAX_HISTORY then
|
if #messageHistory > MAX_HISTORY then
|
||||||
table.remove(messageHistory, 1)
|
table.remove(messageHistory, 1)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- when talking on server log, the message goes to default channel
|
-- when talking on server log, the message goes to default channel
|
||||||
local name = tab:getText()
|
local name = tab:getText()
|
||||||
|
@ -460,7 +492,7 @@ function Console.sendCurrentMessage()
|
||||||
g_game.talkPrivate(speaktype.speakType, name, message)
|
g_game.talkPrivate(speaktype.speakType, name, message)
|
||||||
|
|
||||||
message = applyMessagePrefixies(player:getName(), player:getLevel(), message)
|
message = applyMessagePrefixies(player:getName(), player:getLevel(), message)
|
||||||
Console.addPrivateText(message, speaktype, name, isPrivateCommand)
|
Console.addPrivateText(message, speaktype, name, isPrivateCommand, g_game:getLocalPlayer():getName())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
RuleViolation = {}
|
||||||
|
|
||||||
|
-- private variables
|
||||||
|
local rvreasons = {}
|
||||||
|
rvreasons[0] = tr("1a) Offensive Name")
|
||||||
|
rvreasons[1] = tr("1b) Invalid Name Format")
|
||||||
|
rvreasons[2] = tr("1c) Unsuitable Name")
|
||||||
|
rvreasons[3] = tr("1d) Name Inciting Rule Violation")
|
||||||
|
rvreasons[4] = tr("2a) Offensive Statement")
|
||||||
|
rvreasons[5] = tr("2b) Spamming")
|
||||||
|
rvreasons[6] = tr("2c) Illegal Advertising")
|
||||||
|
rvreasons[7] = tr("2d) Off-Topic Public Statement")
|
||||||
|
rvreasons[8] = tr("2e) Non-English Public Statement")
|
||||||
|
rvreasons[9] = tr("2f) Inciting Rule Violation")
|
||||||
|
rvreasons[10] = tr("3a) Bug Abuse")
|
||||||
|
rvreasons[11] = tr("3b) Game Weakness Abuse")
|
||||||
|
rvreasons[12] = tr("3c) Using Unofficial Software to Play")
|
||||||
|
rvreasons[13] = tr("3d) Hacking")
|
||||||
|
rvreasons[14] = tr("3e) Multi-Clienting")
|
||||||
|
rvreasons[15] = tr("3f) Account Trading or Sharing")
|
||||||
|
rvreasons[16] = tr("4a) Threatening Gamemaster")
|
||||||
|
rvreasons[17] = tr("4b) Pretending to Have Influence on Rule Enforcement")
|
||||||
|
rvreasons[18] = tr("4c) False Report to Gamemaster")
|
||||||
|
rvreasons[19] = tr("Destructive Behaviour")
|
||||||
|
rvreasons[20] = tr("Excessive Unjustified Player Killing")
|
||||||
|
|
||||||
|
local rvactions = {}
|
||||||
|
rvactions[0] = tr("Notation")
|
||||||
|
rvactions[1] = tr("Name Report")
|
||||||
|
rvactions[2] = tr("Banishment")
|
||||||
|
rvactions[3] = tr("Name Report + Banishment")
|
||||||
|
rvactions[4] = tr("Banishment + Final Warning")
|
||||||
|
rvactions[5] = tr("Name Report + Banishment + Final Warning")
|
||||||
|
rvactions[6] = tr("Statement Report")
|
||||||
|
|
||||||
|
local ruleViolationWindow
|
||||||
|
local reasonsTextList
|
||||||
|
local actionsTextList
|
||||||
|
|
||||||
|
-- public functions
|
||||||
|
function RuleViolation.hasWindowAccess()
|
||||||
|
return reasonsTextList:getChildCount() > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.loadReasons()
|
||||||
|
reasonsTextList:destroyChildren()
|
||||||
|
|
||||||
|
local actions = g_game.getGMActions()
|
||||||
|
for reason, actionFlags in pairs(actions) do
|
||||||
|
local label = createWidget('RVListLabel', reasonsTextList)
|
||||||
|
label:setText(rvreasons[reason])
|
||||||
|
label.reasonId = reason
|
||||||
|
label.actionFlags = actionFlags
|
||||||
|
end
|
||||||
|
|
||||||
|
if not RuleViolation.hasWindowAccess() and ruleViolationWindow:isVisible() then RuleViolation.hide() end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.init()
|
||||||
|
connect(g_game, { onLogin = RuleViolation.loadReasons })
|
||||||
|
|
||||||
|
ruleViolationWindow = displayUI('ruleviolation.otui')
|
||||||
|
ruleViolationWindow:setVisible(false)
|
||||||
|
|
||||||
|
reasonsTextList = ruleViolationWindow:getChildById('reasonList')
|
||||||
|
actionsTextList = ruleViolationWindow:getChildById('actionList')
|
||||||
|
|
||||||
|
Keyboard.bindKeyDown('Ctrl+Y', RuleViolation.show)
|
||||||
|
|
||||||
|
if g_game.isOnline() then
|
||||||
|
RuleViolation.loadReasons()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.terminate()
|
||||||
|
disconnect(g_game, { onLogin = RuleViolation.loadReasons })
|
||||||
|
|
||||||
|
ruleViolationWindow:destroy()
|
||||||
|
ruleViolationWindow = nil
|
||||||
|
|
||||||
|
reasonsTextList = nil
|
||||||
|
actionsTextList = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.show(target, statement)
|
||||||
|
if g_game.isOnline() and RuleViolation.hasWindowAccess() then
|
||||||
|
if target then
|
||||||
|
ruleViolationWindow:getChildById('nameText'):setText(target)
|
||||||
|
end
|
||||||
|
|
||||||
|
if statement then
|
||||||
|
ruleViolationWindow:getChildById('statementText'):setText(statement)
|
||||||
|
end
|
||||||
|
|
||||||
|
ruleViolationWindow:show()
|
||||||
|
ruleViolationWindow:raise()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.hide()
|
||||||
|
ruleViolationWindow:hide()
|
||||||
|
RuleViolation.clearForm()
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.onSelectReason(reasonLabel, focused)
|
||||||
|
if reasonLabel.actionFlags and focused then
|
||||||
|
actionsTextList:destroyChildren()
|
||||||
|
for actionBaseFlag = 0, #rvactions do
|
||||||
|
actionFlagString = rvactions[actionBaseFlag]
|
||||||
|
if bit32.band(reasonLabel.actionFlags, math.pow(2, actionBaseFlag)) > 0 then
|
||||||
|
local label = createWidget('RVListLabel', actionsTextList)
|
||||||
|
label:setText(actionFlagString)
|
||||||
|
label.actionId = actionBaseFlag
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.report()
|
||||||
|
local target = ruleViolationWindow:getChildById('nameText'):getText()
|
||||||
|
local reason = reasonsTextList:getFocusedChild().reasonId
|
||||||
|
local action = actionsTextList:getFocusedChild().actionId
|
||||||
|
local comment = ruleViolationWindow:getChildById('commentText'):getText()
|
||||||
|
local statement = ruleViolationWindow:getChildById('statementText'):getText()
|
||||||
|
local statementId = 0 -- TODO: message unique id ?
|
||||||
|
local ipBanishment = ruleViolationWindow:getChildById('ipBanCheckBox'):isChecked()
|
||||||
|
if action == 6 and statement == "" then
|
||||||
|
displayErrorBox(tr("Error"), tr("No statement has been selected."))
|
||||||
|
elseif comment == "" then
|
||||||
|
displayErrorBox(tr("Error"), tr("You must enter a comment."))
|
||||||
|
else
|
||||||
|
g_game.reportRuleVilation(target, reason, action, comment, statement, statementId, ipBanishment)
|
||||||
|
RuleViolation.hide()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function RuleViolation.clearForm()
|
||||||
|
ruleViolationWindow:getChildById('nameText'):clearText()
|
||||||
|
ruleViolationWindow:getChildById('commentText'):clearText()
|
||||||
|
ruleViolationWindow:getChildById('statementText'):clearText()
|
||||||
|
ruleViolationWindow:getChildById('ipBanCheckBox'):setChecked(false)
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
Module
|
||||||
|
name: game_ruleviolation
|
||||||
|
description: Rule violation interface
|
||||||
|
author: OTClient team
|
||||||
|
website: https://github.com/edubart/otclient
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- game
|
||||||
|
|
||||||
|
@onLoad: |
|
||||||
|
dofile 'ruleviolation'
|
||||||
|
RuleViolation.init()
|
||||||
|
|
||||||
|
@onUnload: |
|
||||||
|
RuleViolation.terminate()
|
|
@ -0,0 +1,120 @@
|
||||||
|
RVListLabel < Label
|
||||||
|
background-color: alpha
|
||||||
|
text-offset: 2 0
|
||||||
|
focusable: true
|
||||||
|
@onFocusChange: function (self, focused) RuleViolation.onSelectReason(self, focused) end
|
||||||
|
|
||||||
|
$focus:
|
||||||
|
background-color: #ffffff22
|
||||||
|
color: #ffffff
|
||||||
|
|
||||||
|
RVLabel < Label
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
$first:
|
||||||
|
anchors.top: parent.top
|
||||||
|
|
||||||
|
$!first:
|
||||||
|
margin-top: 10
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
|
||||||
|
RVTextEdit < TextEdit
|
||||||
|
margin-top: 2
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
$first:
|
||||||
|
anchors.top: parent.top
|
||||||
|
|
||||||
|
$!first:
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
|
||||||
|
MainWindow
|
||||||
|
id: ruleViolationWindow
|
||||||
|
size: 400 445
|
||||||
|
text: Rule Violation
|
||||||
|
|
||||||
|
RVLabel
|
||||||
|
!text: tr('Name:')
|
||||||
|
|
||||||
|
RVTextEdit
|
||||||
|
id: nameText
|
||||||
|
|
||||||
|
RVLabel
|
||||||
|
!text: tr('Statement:')
|
||||||
|
|
||||||
|
RVTextEdit
|
||||||
|
id: statementText
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
RVLabel
|
||||||
|
!text: tr('Reason:')
|
||||||
|
|
||||||
|
TextList
|
||||||
|
id: reasonList
|
||||||
|
height: 100
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-top: 2
|
||||||
|
focusable: false
|
||||||
|
vertical-scrollbar: reasonListScrollBar
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: reasonListScrollBar
|
||||||
|
anchors.top: reasonList.top
|
||||||
|
anchors.bottom: reasonList.bottom
|
||||||
|
anchors.right: reasonList.right
|
||||||
|
step: 14
|
||||||
|
pixels-scroll: true
|
||||||
|
|
||||||
|
RVLabel
|
||||||
|
!text: tr('Action:')
|
||||||
|
|
||||||
|
TextList
|
||||||
|
id: actionList
|
||||||
|
height: 60
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
margin-top: 2
|
||||||
|
focusable: false
|
||||||
|
vertical-scrollbar: actionListScrollBar
|
||||||
|
|
||||||
|
VerticalScrollBar
|
||||||
|
id: actionListScrollBar
|
||||||
|
anchors.top: actionList.top
|
||||||
|
anchors.bottom: actionList.bottom
|
||||||
|
anchors.right: actionList.right
|
||||||
|
step: 14
|
||||||
|
pixels-scroll: true
|
||||||
|
|
||||||
|
CheckBox
|
||||||
|
id: ipBanCheckBox
|
||||||
|
!text: tr('IP Address Banishment')
|
||||||
|
margin-top: 10
|
||||||
|
anchors.top: prev.bottom
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
RVLabel
|
||||||
|
!text: tr('Comment:')
|
||||||
|
|
||||||
|
RVTextEdit
|
||||||
|
id: commentText
|
||||||
|
|
||||||
|
Button
|
||||||
|
!text: tr('Cancel')
|
||||||
|
width: 64
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
@onClick: RuleViolation.hide()
|
||||||
|
|
||||||
|
Button
|
||||||
|
!text: tr('Ok')
|
||||||
|
width: 64
|
||||||
|
margin-right: 5
|
||||||
|
anchors.right: prev.left
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
@onClick: RuleViolation.report()
|
Loading…
Reference in New Issue