// ==UserScript==
// @name TagPro RL Chat
// @description Enhances the chat by mimicking Rocket League
// @author Ko
// @version 3.5
// @match *://*.koalabeast.com/*
// @match *://*.jukejuice.com/*
// @match *://*.newcompte.fr/*
// @icon https://github.com/wilcooo/TagPro-RL/raw/master/tprlc-256.png
// @supportURL https://www.reddit.com/message/compose/?to=Wilcooo
// @website https://redd.it/9le791
// @require https://cdnjs.cloudflare.com/ajax/libs/autolinker/1.6.2/Autolinker.min.js
// @license MIT
// @require https://greasyfork.org/scripts/371240/code/TagPro%20Userscript%20Library.js
// @grant GM_setValue
// @grant GM_getValue
// @namespace https://greasyfork.org/users/152992
// ==/UserScript==
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ### --- OPTIONS --- ### //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
// //
// Looking for options? They are on the homepage! Look for a green 'RL-chat' button. // //
// The only thing you can change here are what system messages will be replaced. // //
// null means the system message won't be shown at all, any other string will replace // //
// the message. The main goal is to reduce the space these messages take up, so that everything looks a bit neater. // //
// //
const system_messages = { // //
"Since you refreshed, you will have to wait 10 seconds to respawn.": "Wait 10 seconds after a refresh",
"Since there aren't many players in this game yet, you'll get a bonus": "There aren't many players in this game",
"5 rank points if you stick around and make it a real match.": null,
"10 rank points if you stick around and make it a real match.": null,
"15 rank points if you stick around and make it a real match.": null,
"20 rank points if you stick around and make it a real match.": null,
"Thanks, you're getting 5 bonus rank points for that.": null,
"Thanks, you're getting 10 bonus rank points for that.": null,
"Thanks, you're getting 15 bonus rank points for that.": null,
"Thanks, you're getting 20 bonus rank points for that.": null,
"THROWBACK MAP!": "This is a throwback map",
"TagPro Neomacro Plus Loaded!": null,
"You can't switch teams right now.": "You can't switch teams right now.",
"You've joined a game as a spectator. Once enough players come online, you'll": "You are spectating",
"be auto-joined to a game. Q/W=Rotate through players. A=Red's flag carrier.": null,
"S=Blue's flag carrier. +/- for zooming. C=Center map view. SPACE=Toggle auto-join.": null,
"S=Blue's flag carrier. +/- for zooming. C=Center map view.": null,
"Hi! You’re currently playing unregistered which means you can’t pick a": "You are not logged in",
"custom name and your chat is limited. To register, click the Log In": null,
"button on the homepage. Have fun!": null,
"Sorry, as an unregistered player, you’ve reached your chat limit. To": "Chat limit reached, log in",
"remove this limit, click the Log In button on the homepage and chat as": null,
"much as you like!": null,
"Thank you for testing! Winning 50 games while testing the world joiner": "Testing the SWJ. Win 50 to get the Compass",
"will result in bonus flair!": null,
"We are testing some adjustments to TagPro: Games are now 6 minutes long": "Test: 6 minute game, no limit, mercy and overtime",
"with no cap limit but there is a 3 cap mercy rule. There is also an": null,
"over time mode. Enjoy!": null,
"OVERTIME! Next cap wins. Respawn penalty increases. Grabbing the flag":"OVERTIME!",
"awards Juke Juice.":null,
"During over time, each death is +3 seconds of respawn. Currently: 3": "Current respawn time: 3",
"During over time, each death is +3 seconds of respawn. Currently: 6": "Current respawn time: 6",
"During over time, each death is +3 seconds of respawn. Currently: 9": "Current respawn time: 9",
"During over time, each death is +3 seconds of respawn. Currently: 12": "Current respawn time: 12",
"During over time, each death is +3 seconds of respawn. Currently: 15": "Current respawn time: 15",
"During over time, each death is +3 seconds of respawn. Currently: 18": "Current respawn time: 18",
"During over time, each death is +3 seconds of respawn. Currently: 21": "Current respawn time: 21",
"During over time, each death is +3 seconds of respawn. Currently: 24": "Current respawn time: 24",
"During over time, each death is +3 seconds of respawn. Currently: 27": "Current respawn time: 27",
"During over time, each death is +3 seconds of respawn. Currently: 30": "Current respawn time: 30",
}; // //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
// ### --- END OF OPTIONS --- ### //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ### --- SOUNDS --- ### //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
// //
var chat_sound = new Audio('https://raw.githubusercontent.com/wilcooo/TagPro-GroPro/master/audio/chat.wav'); // //
var left_sound = new Audio('https://raw.githubusercontent.com/wilcooo/TagPro-GroPro/master/audio/left.mp3'); // //
var join_sound = new Audio('https://raw.githubusercontent.com/wilcooo/TagPro-GroPro/master/audio/joined.mp3'); // //
// //
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //
// //
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////
// SCROLL FURTHER AT YOUR OWN RISK! //
//////////////////////////////////////
/* Structure: (for reference)
div#RLC-box
div.chats-wrapper // Necessary to define the exact height of the next div
// by placing n empty lines in it.
div.chats // inherits the height of the wrapper
div
span.name
span.message
div
span.name
span.message
//etc...
label // can show 'team', 'group', 'mod' or nothing
input#chat // Note: this is the original TP chatbox!
*/
// =====CONFIG SECTION=====
// DON'T CHANGE THE OPTIONS HERE, AS YOU CAN CHANGE THEM ON THE TAGPRO HOME PAGE!
var settings = tpul.settings.addSettings({
id: 'RL-Chat',
title: 'TagPro RL Chat Configuration',
tooltipText: 'RL Chat',
icon: 'https://github.com/wilcooo/TagPro-RL/raw/master/tprlc-256.png',
tabs: true,
fields:
{
position:
{
label: 'Position',
section: 'Appearance',
type: 'select',
options: ['top-left', 'top-right', 'bottom-left', 'bottom-right'],
default: 'top-left',
},
font_size:
{
label: 'Font size (pixels)',
type: 'int',
default: 12,
min: 0,
},
lines:
{
label: 'Height of the box (amount of lines)',
type: 'int',
default: 8,
min:0,
},
box_width:
{
label: 'Width of the box (pixels)',
type: 'int',
default: 300,
min: 0,
},
scrolling:
{
label: 'Enable scrolling to see older messages',
type: 'checkbox',
default: false,
},
hide_system:
{
label: 'Hide and/or shorten the most annoying system messages ("Since there aren\'t many players...")',
type: 'checkbox',
default: true,
},
bind_to_game:
{
label: 'Keep the chatbox inside the game viewport.',
type: 'checkbox',
default: true,
},
sound_on_chat: {
label: '"Bwep" whenever someone sends a message',
section: 'Sounds',
type: 'checkbox',
default: true,
},
sound_on_join: {
label: '"Dink" whenever someone joins',
type: 'checkbox',
default: true,
},
sound_on_left: {
label: '"Donk" whenever someone leaves',
type: 'checkbox',
default: true,
},
show_time:
{
label: 'Time to show RL-chat after recieving a message (seconds)',
section: ['Showing/Hiding the chat',
'By default, the chat is hidden. Once a message arrives, the chat (including past messages) will be shown for a few seconds.'],
type: 'int',
default: 6,
min:0,
},
permanent_end:
{
label: 'Permanently show RL-chat after the game has ended',
type: 'checkbox',
default: true,
},
permanent_always:
{
label: 'Permanently show RL-chat. Always',
type: 'checkbox',
default: false,
},
rollingchat:
{
label: 'Use the arrow keys to roll while typing',
type: 'checkbox',
default: true,
},
hide_default_chat:
{
label: 'Hide the default chat (Recommended)',
type: 'checkbox',
default: true,
},
},
events: { save: update_settings }
});
var position = settings.get('position'),
show_time = settings.get('show_time'),
box_width = settings.get('box_width'),
font_size = settings.get('font_size'),
lines = settings.get('lines'),
rollingchat = settings.get('rollingchat'),
permanent_end = settings.get('permanent_end'),
permanent_always = settings.get('permanent_always'),
hide_system = settings.get('hide_system'),
hide_default_chat = settings.get('hide_default_chat'),
scrolling = settings.get('scrolling'),
sound_on_chat = settings.get("sound_on_chat"),
sound_on_join = settings.get("sound_on_join"),
sound_on_left = settings.get("sound_on_left"),
bind_to_game = settings.get("bind_to_game");
function update_settings() {
if (tpul.playerLocation == 'game') {
position = settings.get('position');
show_time = settings.get('show_time');
box_width = settings.get('box_width');
font_size = settings.get('font_size');
lines = settings.get('lines');
//rollingchat = settings.get('rollingchat');
permanent_end = settings.get('permanent_end');
permanent_always = settings.get('permanent_always');
hide_system = settings.get('hide_system');
hide_default_chat = settings.get('hide_default_chat');
scrolling = settings.get('scrolling');
sound_on_chat = settings.get("sound_on_chat");
sound_on_join = settings.get("sound_on_join");
sound_on_left = settings.get("sound_on_left");
bind_to_game = settings.get("bind_to_game");
// Update the position
if (!tpul.noscript) tagpro.chat.resize();
// Update the width
box.style.width = box_width + 'px';
// Update the font size
box.style.fontSize = font_size + 'px';
// Update the amount of lines
spacer.innerHTML = Array(lines+1).join('<br>');
// Warn if rollingchat has been updated
if (rollingchat != settings.get('rollingchat')) {
setTimeout(tpul.notify, 1500,
'Rolling chat ' +
(settings.get('rollingchat') ? 'will be enabled after a refresh' :
'won\'t be enabled after a refresh / next game. (unless you have another script that enables it)'), 'warning');
}
// permanent
if (permanent_always) box.classList.add('permanent');
else if (permanent_end && !tpul.noscript && tagpro.state == 2) box.classList.add('permanent');
else box.classList.remove('permanent');
// (un)hide default chat
if (default_chat) default_chat.style.display = hide_default_chat ? 'none' : '';
// scrolling
if (scrolling) box.classList.add('scroll');
else box.classList.remove('scroll');
}
}
// =====NOITCES GIFNOC=====
// =====CSS SECTION=====
// Create our own stylesheet to define the styles in:
var style = document.createElement('style');
document.head.appendChild(style);
var styleSheet = style.sheet;
/* Remove the style rule for the input box from TagPro's stylesheet.
Doesn't work in firefox, lets override all css rules later on.
t:for (let sheet of document.styleSheets) if (sheet.href && sheet.href.endsWith('/stylesheets/style.css')) {
for (let r in sheet.rules) if (sheet.rules[r].selectorText == '.game input#chat') {
sheet.removeRule(r);
break t;
}
}*/
// The outer container (containing the chat history & text field)
// Define font-size here, to give the chat-wrapper as well as the chat
styleSheet.insertRule(` #RLC-box {
position:absolute;
transition: background 500ms;
width:`+box_width+`px;
border-radius: 10px;
font-size:`+font_size+`px;
margin: 10px;
}`);
// The container when it's shown (while composing a message)
styleSheet.insertRule(`#RLC-box:focus-within, #RLC-box.permanent {
background: rgba(0,0,0,.8);
}`);
// The wrapper around the .chats div
styleSheet.insertRule(`#RLC-box .chats-wrapper {
margin: 5px 0;
position:relative;
overflow: hidden;
}`);
// Add 8 empty lines in it to set the wanted height.
// Using em, or any other method, will result in non-pixel perfect
// heights while zooming (depending on the browser).
/* DEPRECATED: WE NOW USE A REAL SPACER DIV
styleSheet.insertRule(` #RLC-box .chats-wrapper:after {
content: "`+ '\\a'.repeat(lines) +`";
white-space: pre;
}`);*/
// The chat history, which will always contain ALL chats.
// Older chats will just be scrolled out of view
// Opacity set to 0 by default.
styleSheet.insertRule(`#RLC-box .chats {
opacity:0;
overflow:hidden;
transition: opacity 500ms;
transition-delay: 500ms;
position: absolute;
height: 100%;
width: 100%;
padding: 0 5px;
top: 0;
left: 0;
}`);
// SCROLLING
styleSheet.insertRule(`#RLC-box.scroll:focus-within .chats {
overflow-y: auto;
width: calc(100% + 17px);
padding-right: calc(5px + 17px);
scroll-snap-type: mandatory;
/* older spec implementation */
scroll-snap-destination: 0 100%;
}`);
styleSheet.insertRule(`#RLC-box .scrollbar {
position: absolute;
background: rgba(255,255,255,.4);
width: 7px;
border-radius: 5px;
right: 4px;
opacity: 0;
transition: opacity 500ms;
}`);
styleSheet.insertRule(`#RLC-box.scroll:hover:focus-within .scrollbar {
opacity: 1;
}`);
/*styleSheet.insertRule(`#RLC-box:focus-within .chats.scroll::-webkit-scrollbar { width: 17px; }`);
styleSheet.insertRule(`#RLC-box:focus-within:hover .chats.scroll::-webkit-scrollbar-thumb {
border-radius: 10px;
color: rgba(255,255,255,.5);
box-shadow: -17px 0 0 -5px;
}`);*/
// This same box, but when it's .shown
// Using opacity instead of display:none or visibility allows us to use CSS transistion
styleSheet.insertRule(`#RLC-box:focus-within .chats, #RLC-box.permanent .chats, #RLC-box .chats.shown {
opacity:1;
transition-delay: 0s;
}`);
// A single message. Combining these multiple shadows creates a hard 1px line around the text,
// combined with a softer 5px shadow.
// display:inline; to make sure the height doesn't deviate from the set line-height
// (we need this to make sure that exactly 8 lines fit in the box)
styleSheet.insertRule(` #RLC-box .chats div {
text-shadow: -1px -1px 5px #000, 1px -1px 5px #000, -1px 1px 5px #000, 1px 1px 5px #000, -1px -1px 1px #000, 1px -1px 1px #000, -1px 1px 1px #000, 1px 1px 1px #000;
width:inherit;
display: block;
text-overflow: ellipsis;
overflow: hidden;
scroll-snap-align: start;
/* older spec implementation */
scroll-snap-coordinate: 0 100%;
}`);
// The name of a chat message
styleSheet.insertRule(` #RLC-box .chats div .name {
text-transform: uppercase;
font-weight: bold;
margin-right: 3px;
}`);
// Authenticated name: add a green ✔
styleSheet.insertRule(` #RLC-box .chats div.auth .name::before {
content: "✔";
color: #BFFF00;
font-size: 8px;
}`);
// Changing the style of the .name, .message or full chat div depending on what kind of message it is.
styleSheet.insertRule(` #RLC-box .chats div.red .name { color:#FFB5BD; }`); // Red name
styleSheet.insertRule(` #RLC-box .chats div.red.team .message { color:#FFB5BD; }`); // Red team message
styleSheet.insertRule(` #RLC-box .chats div.blue .name { color:#CFCFFF; }`); // Blue name
styleSheet.insertRule(` #RLC-box .chats div.blue.team .message { color:#CFCFFF; }`); // Blue team message
styleSheet.insertRule(` #RLC-box .chats div.group { color:#E7E700; }`); // Group (name&message)
styleSheet.insertRule(` #RLC-box .chats div.mod .name { color:#00B900; }`); // Mod name
styleSheet.insertRule(` #RLC-box .chats div.system { color:#F0E68C; }`); // system message
styleSheet.insertRule(` #RLC-box .chats div.announcement { color:#FF88FF; }`); // announcement (server shutting down or something)
// Links. Same color as the message, but underlined.
styleSheet.insertRule(` #RLC-box a {
color: #8BC34A;
text-decoration: underline double;
}`);
// The label around the input field.
// This thing has the borders, because we want the
// label text to be inside the border too. ('team', 'group', 'mod'...)
// display:table; will make the input behave like a table-cell, which extends it to the end of the line.
styleSheet.insertRule(` #RLC-box label {
border-radius: 8px;
margin: 3px;
width: calc(100% - 6px);
padding: 3px;
border: 2px inset Gray;
transition: opacity 500ms;
opacity: 0;
display: table;
font-weight: normal;
background: rgba(255,255,255,.15);
cursor: text;
}`);
styleSheet.insertRule(` #RLC-box:focus-within label {
border: 2px outset CadetBlue;
}`);
// Same trick as before to hide/show it.
styleSheet.insertRule(` #RLC-box:focus-within label, #RLC-box.permanent label {
opacity: 1;
}`);
// The style of the label text ('team', 'group', 'mod')
// We have to add content: , because otherwise an empty
// input-box would have no height.
styleSheet.insertRule(` #RLC-box label:before {
display: table-cell;
font-weight: bold;
color: LightGrey;
content: '';
}`);
// Add text to the label, depending on the type of chat you're composing.
styleSheet.insertRule(` #RLC-box label.team:before {width:1px; padding-right:3px; content: 'team';}`);
styleSheet.insertRule(` #RLC-box label.group:before {width:1px; padding-right:3px; content: 'group';}`);
styleSheet.insertRule(` #RLC-box label.mod:before {width:1px; padding-right:3px; content: 'mod';}`);
// The input field
// note: this is the original TagPro element, it'll just be moved to the new location
// This way we don't have to bother with the logic behind opening the box, and sending a chat
// We are mainly overriding default parameters.
styleSheet.insertRule(` #RLC-box input#chat {
padding: 0;
position: static;
border: none;
background: none;
outline: none;
transition: all 500ms;
display: none;
width: 100%;
font-size: inherit;
}`);
// Change the text-color of the chat you're composing, based on the type
styleSheet.insertRule(` #RLC-box label.team.red input {color:#FFB5BD;}`); // Red text
styleSheet.insertRule(` #RLC-box label.team.blue input {color:#CFCFFF;}`); // Blue text
styleSheet.insertRule(` #RLC-box label.group input {color:#E7E700;}`); // Yellow text
styleSheet.insertRule(` #RLC-box label.mod input {color:#00B900;}`); // Green text
// =====NOITCES SSC=====
if (tpul.playerLocation == 'game' && !tpul.noscript) {
// =====DOM SECTION=====
// Some default DOM elements TagPro
var canvas = document.getElementById('viewport');
var game = document.getElementsByClassName('game')[0];
var default_chat = document.getElementById('chatHistory');
var input = document.getElementById('chat');
// Hide the default chat history
if (hide_default_chat && default_chat) default_chat.style.display = 'none';
// Create the RLC container
var box = document.createElement('div');
box.id = 'RLC-box';
game.appendChild( box );
if (permanent_always) box.classList.add('permanent');
// Add a wrapper for around the chats
var wrapper = document.createElement('div');
wrapper.className = 'chats-wrapper';
box.appendChild(wrapper);
// Add a "spacer" div to define the height of the wrapper based on some amount of lines
var spacer = document.createElement('div');
spacer.className = 'chats-spacer';
wrapper.appendChild( spacer );
spacer.innerHTML = Array(lines+1).join('<br>');
// Add the chat-log to that wrapper
var chats = document.createElement('div');
chats.className = 'chats';
wrapper.appendChild( chats );
// scrolling
if (scrolling) box.classList.add('scroll');
else box.classList.remove('scroll');
var scrollbar = document.createElement('div');
scrollbar.className = 'scrollbar';
wrapper.appendChild(scrollbar);
// Add a label around the input, shown in case of team or group chat
var label = document.createElement('label');
box.appendChild(label);
// Move the input inside RL chat
label.appendChild(input);
// =====NOITCES MOD=====
// =====LOGIC SECTION=====
/* global tagpro, $, Autolinker */
var autolinker = new Autolinker( {
urls : {
schemeMatches : true,
wwwMatches : true,
tldMatches : true
},
email : true,
phone : false,
mention : false,
hashtag : false,
stripPrefix : true,
stripTrailingSlash : true,
newWindow : true,
truncate : { length:25, location:'end' }
} );
tagpro.ready(function() {
if (rollingchat) enableRollingChat();
var timeout;
//Listen for messages, and add them to RLC:
function handleChat (chat) {
// Return disabled chat types
if (tagpro.settings.ui) {
if ( !tagpro.settings.ui.allChat && chat.to == "all" && chat.from ) return;
if ( !tagpro.settings.ui.teamChat && chat.to == "team" ) return;
if ( !tagpro.settings.ui.groupChat && chat.to == "group" ) return;
if ( chat.to == "all" && !chat.from ) {
if (!tagpro.settings.ui.systemChat) return;
if (hide_system && system_messages[chat.message] === null) return;
}
}
// Create the message div
var message = document.createElement('div');
var message_span = document.createElement('span');
message_span.className = 'message';
if (chat.from) {
var name_span = document.createElement('span');
name_span.className = 'name';
if ( typeof chat.from == "number" ) {
var player = tagpro.players[chat.from];
if (player.auth) message.classList.add('auth');
if (player.team == 1) message.classList.add('red');
else if (player.team == 2) message.classList.add('blue');
name_span.innerText = player.name;
} else name_span.innerText = chat.from;
message.appendChild(name_span);
} else {
message.classList.add('system');
}
if ( chat.to == "group" ) {
name_span.innerText = chat.from;
message.classList.add('group');
}
if ( chat.from == "ADMIN_GLOBAL_BROADCAST" ) {
message.classList.add('announcement');
name_span.innerText = "ANNOUNCEMENT";
}
if ( chat.mod ) {
message.classList.add('mod');
}
if( chat.to == "team") {
message.classList.add("team");
}
message_span.innerText = system_messages[chat.message] || chat.message;
message_span.innerHTML = autolinker.link( message_span.innerHTML );
// Linkify the message, and append it
message.appendChild(message_span);
if ( chat.c ) message_span.style.color = chat.c;
// Append the message and scroll the chat
chats.appendChild(message);
chats.scrollTop = chats.scrollHeight;
chats.classList.add('shown');
clearTimeout(timeout); // Remove any existing timeout
timeout = setTimeout(()=>chats.classList.remove('shown'),show_time*1e3); // Set a timeout to hide the chats
// Set volume according to the awesome Volume Slider®
chat_sound.volume = left_sound.volume = join_sound.volume = 1 * tagpro.volumeCoefficient || 1;
// Play a sound
if (chat.from && sound_on_chat) chat_sound.play();
else if (chat.message.includes(' has left ') && sound_on_left)
left_sound.play();
else if (chat.message.includes(' has joined ') && sound_on_join)
join_sound.play();
else if (sound_on_chat) chat_sound.play();
}
tagpro.socket.on('chat', handleChat);
if (tagpro.group.socket) tagpro.group.socket.on('chat', handleChat);
// Scrolling:
chats.onscroll = function(scroll){
// Update scrollbar
scrollbar.style.height = 100 * chats.offsetHeight / chats.scrollHeight + '%';
scrollbar.style.top = 100 * chats.scrollTop / chats.scrollHeight + '%';
};
// TODO: click on label opens all-chat (if not yet opened)
// Change the built-in jQuery function .show()
// to make it trigger an event.
// This function is used by TagPro to show the input-box.
$.fn.org_show = $.fn.show;
$.fn.show = function(speed, easing, callback) {
$(this).trigger('show');
return $(this).org_show(...arguments);
};
// Same for .hide()
$.fn.org_hide = $.fn.hide;
$.fn.hide = function(e, r, i) {
$(this).trigger('hide');
return $(this).org_hide(...arguments);
};
// Keep track of what is the last pressed key,
// so that we know what label to add.
var last_keyCode = null;
document.addEventListener('keydown', event => last_keyCode = event.keyCode);
// When the input is shown, add a label
$(input).on('show',function(){
// Scroll to bottom on opening chat
chats.scrollTop = chats.scrollHeight;
setTimeout(function(){
if ( tagpro.keys.chatToAll.indexOf(last_keyCode) > -1 )
label.classList.add('all');
else label.classList.remove('all');
if ( tagpro.keys.chatToTeam.indexOf(last_keyCode) > -1 ) {
label.classList.add('team');
label.classList.add(tagpro.players[tagpro.playerId].team == 1 ? 'red' : 'blue');
} else label.classList.remove('team');
if ( tagpro.keys.chatToGroup.indexOf(last_keyCode) > -1 )
label.classList.add('group');
else label.classList.remove('group');
if ( tagpro.keys.chatAsMod.indexOf(last_keyCode) > -1 )
label.classList.add('mod');
else label.classList.remove('mod');
});
});
// When the input is hidden, hide the label
$(input).on('hide',function(){
// Blur the input (not automatically done on firefox)
this.blur();
// hide chat on closing it
clearTimeout(timeout); // Remove any existing timeout
chats.classList.remove('shown'); // hide the chats
label.classList.remove('all');
label.classList.remove('team');
label.classList.remove('group');
label.classList.remove('mod');
});
// Permanently show the chat box after a game ends
if (permanent_end)
tagpro.socket.on('end', function(end) {
// Show the box
box.classList.add('permanent');
});
// When clicking the label, open the chat
// (this will only be used once a game has ended)
label.addEventListener('click', function(){
if (input.style.display == 'none') {
// Open the chat box:
var e = new Event("keydown");
e.keyCode = 'RL-Chat';
tagpro.keys.chatToAll.push('RL-Chat');
document.dispatchEvent(e);
tagpro.keys.chatToAll.pop();
}
});
// When the input looses focus, hide it
// (so that it can be reopened with Enter or T or whatever)
input.addEventListener('blur', function(){
if (input.style.display == 'inline-block') {
// Close the chat box:
var e = new Event("keydown");
e.keyCode = 'RL-Chat';
tagpro.keys.cancelChat.push('RL-Chat');
input.dispatchEvent(e);
tagpro.keys.cancelChat.pop();
}
});
// Modify TagPro's resize function, which is called whenever
// your window size changes. (going fullscreen, zooming, etc.)
tagpro.chat.org_resize = tagpro.chat.resize;
tagpro.chat.resize = function() {
canvas = document.getElementById('viewport');
switch (position) {
default: case 'top-left':
box.style.top = bind_to_game ? canvas.offsetTop + 'px' : 0;
box.style.left = bind_to_game ? canvas.offsetLeft + 'px' : 0;
box.style.bottom = '';
box.style.right = '';
// move 30 pixels down if you have FPS & ping enabled.
if (bind_to_game && tagpro.settings.ui.performanceInfo) box.style.top = canvas.offsetTop + 30 + 'px';
break;
case 'top-right':
box.style.top = bind_to_game ? canvas.offsetTop + 'px' : 0;
box.style.right = bind_to_game ? game.offsetWidth - canvas.offsetLeft - canvas.offsetWidth + 'px' : 0;
box.style.bottom = '';
box.style.left = '';
break;
case 'bottom-right':
box.style.bottom = bind_to_game ? window.innerHeight - canvas.offsetTop - canvas.offsetHeight + 'px' : 0;
box.style.right = bind_to_game ? game.offsetWidth - canvas.offsetLeft - canvas.offsetWidth + 'px' : 0;
box.style.top = '';
box.style.left = '';
break;
case 'bottom-left':
box.style.bottom = bind_to_game ? window.innerHeight - canvas.offsetTop - canvas.offsetHeight + 'px' : 0;
box.style.left = bind_to_game ? canvas.offsetLeft + 'px' : 0;
box.style.top = '';
box.style.right = '';
break;
}
chats.scrollTop = chats.scrollHeight;
if (!hide_default_chat) {
default_chat.style.left = canvas.offsetLeft + 10 + 'px';
default_chat.style.top = canvas.offsetTop + canvas.height - default_chat.offsetHeight - 50 + 'px';
}
return tagpro.chat.org_resize(...arguments);
};
// Call it once to make sure everyting is positioned correctly at the start.
tagpro.chat.resize();
});
function enableRollingChat(){
// It is perfectly fine to add this function (unchanged) to your own script.
// Multiple instances of "rollingchat" can run simultaniously without problems.
// intercept all key presses and releases:
document.addEventListener('keydown', keyUpOrDown);
document.addEventListener('keyup', keyUpOrDown);
function keyUpOrDown( event ) {
// The key that is pressed/released (undefined when it is any other key)
var arrow = ['left','up','right','down'][[37,38,39,40].indexOf(event.keyCode)];
// Only if the controls are disabled (usually while composing a message)
// AND the key is indeed an arrow (not undefined)
if (tagpro.disableControls && arrow) {
// Whether you are releasing instead of pressing the key:
var releasing = event.type == 'keyup';
// Prevent the 'default' thing to happen, which is the cursor moving through the message you are typing
event.preventDefault();
// Return if already pressed/released
if (tagpro.players[tagpro.playerId].pressing[arrow] != releasing) return;
// Send the key press/release to the server!
tagpro.sendKeyPress(arrow, releasing);
// Not necesarry, but useful for other scripts to 'hook onto'
if (!releasing && tagpro.events.keyDown) tagpro.events.keyDown.forEach(f => f.keyDown(arrow));
if (releasing && tagpro.events.keyUp) tagpro.events.keyUp.forEach(f => f.keyUp(arrow));
tagpro.ping.avg&&setTimeout(()=>(tagpro.players[tagpro.playerId][arrow]=!releasing),tagpro.ping.avg/2);
}
}
}
// =====NOITCES CIGOL=====
}