Skip to content

Instantly share code, notes, and snippets.

@panthar1
Last active August 29, 2015 14:06
Show Gist options
  • Save panthar1/d53edf48599a7557a419 to your computer and use it in GitHub Desktop.
Save panthar1/d53edf48599a7557a419 to your computer and use it in GitHub Desktop.
KDice Flag Enhancer
// ==UserScript==
// @name KDice Flag Enhancer
// @version 1.3.4
// @namespace panthar
// @run-at document-end
// @description KDice flag system enhancements.
// @include http://*kdice.com*
// @copyright 2014+, Bobby Kramer, http://www.panthar.net
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
// @downloadURL https://gist.github.com/panthar1/d53edf48599a7557a419/raw/KDiceFlagEnhancer.user.js
// @updateURL https://gist.github.com/panthar1/d53edf48599a7557a419/raw/KDiceFlagEnhancer.user.js
// @grant none
// ==/UserScript==
$(document).ready(function () {
var allPlayers = null;
//run the update on the table after 5 seconds from load. Just an approximation
setTimeout(updateNewTable, 5000);
setTimeout(showAutoTurn, 5000);
setTimeout(showSmartAutoEndTurn, 5000);
//go/cancel buttons, from kdice, when clicked, update our table.
//do this every 3 seconds, because it refreshes every time its your turn
$(document).delegate('.iogc-DialogOuter .iogc-NewButton, .iogc-GameWindow-commands .iogc-NewButton', 'click', function () {
setTimeout(updateNewTable, 3000);
setTimeout(showAutoTurn, 3000);
});
//smart auto end turn checkbox, need to update an attribute on it
$(document).delegate('.iogc-Controls .gwt-CheckBox input#kdice-flags-smart-end-turn', 'change', function () {
if ($(this).is(':checked')) {
$(this).attr('checked', true);
if (!$('.iogc-Controls .gwt-CheckBox input#gwt-uid-1').is(':checked')) {
$('.iogc-Controls .gwt-CheckBox input#gwt-uid-1').click();
}
} else {
$(this).attr('checked', false);
if($('.iogc-Controls .gwt-CheckBox input#gwt-uid-1').is(":checked")){
$('.iogc-Controls .gwt-CheckBox input#gwt-uid-1').click();
}
}
});
//just a change event on the auto end turn
$(document).delegate('.iogc-Controls .gwt-CheckBox input#gwt-uid-1', 'change', function () {
if ($(this).is(':checked')) {
$(this).attr('checked', true);
} else {
if ($('.iogc-Controls .gwt-CheckBox input#kdice-flags-smart-end-turn').is(':checked')) {
$(this).click();
}else{
$(this).attr('checked', false);
}
}
});
$(document).delegate('#kdice-flag-table input:checkbox', 'click', function () {
//if its not a kdice auto-checkbox checking mechanism, and it's the "current player's"
//row were looking at. If thats the case, then show a confirm dialog.
if (!$(this).hasClass('kdice-auto-check') && $(this).hasClass('kdice-flag-table-local')) {
if ($(this).is(':checked')) {
if (confirm('Are you sure you wish to flag ' + $(this).val() + '?')) {
$('.iogc-ChatPanel-input .gwt-TextBox').val('flag ' + $(this).val());
$('.iogc-ChatPanel-input .iogc-NewButton').click();
} else {
$(this).attr('checked', false);
}
} else {
$(this).attr('checked', false);
}
} else if ($(this).is(':checked')) {
$(this).attr('checked', true);
} else {
$(this).attr('checked', false);
}
$(this).removeClass('kdice-auto-check');
});
//Use non-jquery, to add event listenr.
//jquery seems to have some issues with chrome.
document.addEventListener('DOMNodeInserted', function (e) {
if (e.target != null && e.target != undefined) {
//if its a message panel message
if ($(e.target).is('.iogc-MessagePanel-messages .gwt-HTML')) {
var statusHtml = $(e.target).html();
if (statusHtml != null && statusHtml != undefined) {
//every time a player enters a new game, lets update player array
if (statusHtml.indexOf('takes a seat') > - 1) {
showAutoTurn();
//creates a new table until the total # of players are in game
updateNewTable();
} else if (statusHtml.indexOf('\'s turn') > - 1) {
//update the auto end turn, keep is visible
showAutoTurn();
} else {
autoLastTurnAttackCheck(e.target);
userLeavingCheck(e.target);
}
}
} else if ($(e.target).is('.iogc-ChatPanel-messages .gwt-HTML')) {
playerFlaggedCheck(e.target);
}
}
}, false);
//creates the "flag" table, that a user an click on
//flag table is only recreated when going to a different table,
//or when someone "sits in" on a table
function createFlagTable(players) {
var loggedInPlayer = $('.iogc-LoginPanel-nameHeading').html();
var tableStr = '';
var firstRowPlayerCount = 1;
var trBackgroundColor = '';
$('#kdice-flag-table-top').remove();
$('#kdice-flag-table').remove();
tableStr = '<p id="kdice-flag-table-top" style="font-size:20px;color:red;margin-left:40%;margin-bottom:5px;">Flagged To:</p>';
tableStr += '<table id="kdice-flag-table" ><thead>';
tableStr += '<th>Name</th>';
//create table head
for (var player in players) {
tableStr += '<th style="background-color:' + players[player].color + ';"' + ' class="' + players[player].colorName + '-header' + '">' + '</th>';
}
//create table body
for (var firstRowPlayer in players) {
if (firstRowPlayerCount % 2 == 1) {
trBackgroundColor = 'background-color:#EEEEEE;';
} else {
trBackgroundColor = '';
}
tableStr += '<tr style="' + trBackgroundColor + '">';
tableStr += '<td style="color:' + players[firstRowPlayer].color + ';font-size:11px;vertical-align: middle;">' + players[firstRowPlayer].name + '</td>';
for (var secondRowPlayer in players) {
//tableStr += '<td>';
if (players[firstRowPlayer].name == loggedInPlayer && players[secondRowPlayer].name != players[firstRowPlayer].name) {
tableStr += '<td style="background-color:' + players[firstRowPlayer].color + ';">';
tableStr += '<input type="checkbox" class="kdice-flag-table-local ' +
players[firstRowPlayer].colorName + '-flagger ' +
players[secondRowPlayer].colorName + '-flagged' +
'" value="' + players[secondRowPlayer].colorName + '" style="margin: 4px 1px 3px 1px;"/>';
} else if (players[firstRowPlayer].name == players[secondRowPlayer].name) {
tableStr += '<td style="background-color:#FFFFFF">';
} else {
tableStr += '<td style="background-color:' + players[firstRowPlayer].color + ';">';
tableStr += '<input type="checkbox" class="' +
players[firstRowPlayer].colorName + '-flagger ' +
players[secondRowPlayer].colorName + '-flagged' + '" style="margin: 4px 1px 3px 1px;"/>';
}
tableStr += '</td>';
}
tableStr += '<td class="kdice-flag-position ' + players[firstRowPlayer].colorName + '-flag-position" style="color:' + players[firstRowPlayer].color + ';font-size:11px;vertical-align: middle;">' + '</td>';
tableStr += '</tr>';
firstRowPlayerCount++;
}
tableStr += '</thead></table>';
$('#menu-out').append(tableStr);
}
//get list of all players and data from the game
function getPlayerArray() {
var gamePlayers = [
];
//look at the game window table
$('.iogc-GameWindow-table .gwt-HTML').each(function () {
var hidden = $(this).attr('aria-hidden');
var parentTable = $(this).closest('table');
var parentDiv = $(parentTable).closest('table').closest('div');
var playerData = $(parentTable).find('.iogc-PlayerPanel-name');
//get actual game statistics
var playerName = $(playerData).children('a').html();
//should we add game player?
var addGamePlayer = true;
var playerColor = $(playerData).css('borderTopColor');
var playerColorName = '';
if (playerName != undefined && $(parentDiv).css('display') != 'none') {
//some bug, where duplicate players can get added, so,
for (var player in gamePlayers) {
if (gamePlayers[player].name == playerName) {
addGamePlayer = false;
break;
}
}
//after removing duplicates,
if (addGamePlayer == true) {
//get color name from color values
switch (playerColor) {
case 'rgb(191, 48, 105)':
playerColorName = 'red';
break;
case 'rgb(48, 191, 86)':
playerColorName = 'green';
break;
case 'rgb(158, 48, 191)':
playerColorName = 'purple';
break;
case 'rgb(165, 180, 14)':
playerColorName = 'yellow';
break;
case 'rgb(48, 57, 191)':
playerColorName = 'blue';
break;
case 'rgb(191, 134, 48)':
playerColorName = 'brown';
break;
case 'rgb(48, 177, 191)':
playerColorName = 'teal';
break;
}
//push to our player array
gamePlayers.push({
name: playerName,
color: playerColor,
colorName: playerColorName
});
}
}
});
//special case, switch order of green/red, so the order of array makes sense for players
if (gamePlayers != null && gamePlayers.length > 1) {
if (gamePlayers[0].colorName == 'green' && gamePlayers[1].colorName == 'red') {
var tmpPlayer = gamePlayers[0];
gamePlayers[0] = gamePlayers[1];
gamePlayers[1] = tmpPlayer;
}
}
//return all the game players found.
return gamePlayers;
}
//just check a checkbox when flagged
function updateCheckboxForFlag(flaggerColor, flaggedColor) {
var flaggedCheckbox = $('#kdice-flag-table tr td input.' + flaggerColor + '-flagger.' + flaggedColor + '-flagged');
//update flag checkbox
if (!$(flaggedCheckbox).is(':checked')) {
$(flaggedCheckbox).addClass('kdice-auto-check');
$(flaggedCheckbox).click();
}
//find all people the flagged player has flagged to (if they have any)
//basically, we just update the "parent" flags, with the current flagger
$('#kdice-flag-table tr td input.' + flaggedColor + '-flagger:checked').each(function () {
var elementClasses = $(this).attr('class').split(/\s+/);
//search through all the CSS classes to see who they flagged to
for (var i = 0; i < elementClasses.length; i++) {
//look at the class element to see if it contains flags,
//if so, set the checkboxed on the original "flagger color"'s parent flags
var selectorStr = '';
switch (elementClasses[i]) {
case 'red-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.red-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
case 'green-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.green-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
case 'purple-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.purple-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
case 'yellow-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.yellow-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
case 'blue-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.blue-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
case 'brown-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.brown-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
case 'teal-flagged':
selectorStr = '#kdice-flag-table tr td input.' + flaggerColor + '-flagger.teal-flagged';
if (!$(selectorStr).is(':checked')) {
$(selectorStr).addClass('kdice-auto-check');
$(selectorStr).click();
}
break;
}
}
});
upddateRankCounts(flaggerColor);
}
//keeps the auto turn checkbox visible no matter what
function showAutoTurn() {
var autoEndTurnCheckbox = $('.iogc-Controls .gwt-CheckBox').css('display', 'block');
}
function showSmartAutoEndTurn() {
var closestTr = $('.iogc-Controls .gwt-CheckBox #gwt-uid-1').closest('tr');
$(closestTr).prepend('<td align="left" style="vertical-align: middle;"><span class="gwt-CheckBox"><input type="checkbox" id="kdice-flags-smart-end-turn"><label for="kdice-flags-smart-end-turn">Smart auto end turn</label></span></td>');
}
//just create a new flag table
function updateNewTable() {
allPlayers = getPlayerArray();
createFlagTable(allPlayers);
creatPlayedDesiredRank();
}
function creatPlayedDesiredRank() {
$('.kdice-flag-position').html('1');
}
//we don't want the "auto last turn" to work if we have been attacked
//so we check to see if the local-player has been attacked,
//if so, we uncheck the checkbox
function autoLastTurnAttackCheck(elementToCheck) {
//make sure auto end turn is checked before doing this
if ($('.iogc-Controls .gwt-CheckBox input#kdice-flags-smart-end-turn').prop('checked')) {
var loggedInPlayer = $('.iogc-LoginPanel-nameHeading').html().trim();
//only if we have a "current player"
if (loggedInPlayer != null && loggedInPlayer != undefined) {
//get the span, this is how we know its an "attack event"
var firstChild = $(elementToCheck).children('span').html();
//make sure we have a defined element
if (firstChild != undefined) {
//we have to trim it, because it has a space in it
if (loggedInPlayer == firstChild.trim()) {
//uncheck the auto end turn
$('.iogc-Controls .gwt-CheckBox input#gwt-uid-1').attr('checked', false);
$('.iogc-Controls .gwt-CheckBox input#gwt-uid-1').change();
$('.iogc-Controls .gwt-CheckBox input#kdice-flags-smart-end-turn').attr('checked', false);
$('.iogc-Controls .gwt-CheckBox input#kdice-flags-smart-end-turn').change();
}
}
}
}
}
//performs the check for when a users leaves
//it looks at the message window, and if a player actually left
//then remove them from the table.
function userLeavingCheck(elementToCheck) {
//check for users leaving
var userLeaving = $(elementToCheck).children('b').html();
var playerName = null;
//finishes has to be grater than 0, to assure the substring has a positive index
if (userLeaving != null && userLeaving != undefined) {
if (userLeaving.indexOf('finishes') > - 1 && userLeaving.indexOf('in round') > - 1) {
playerName = userLeaving.substring(0, userLeaving.indexOf('finishes') - 1).trim();
var playerWhoLeft = null;
for (var player in allPlayers) {
if (allPlayers[player].name == playerName) {
playerWhoLeft = allPlayers[player];
var checkboxLeavingPlayer = $('#kdice-flag-table tr td input.' + playerWhoLeft.colorName + '-flagger').first();
$(checkboxLeavingPlayer).closest('tr').remove();
$('#kdice-flag-table th.' + playerWhoLeft.colorName + '-header').remove();
$('#kdice-flag-table .' + playerWhoLeft.colorName + '-flagged').closest('td').remove();
//update all the players, our array is smaller
allPlayers = getPlayerArray();
break;
}
}
}
}
}
function playerFlaggedCheck(elementToCheck) {
var playerName = $(elementToCheck).children('b').html();
if (playerName != undefined) {
var playerToUpdate = null;
//find the player from the name
for (var player in allPlayers) {
if (allPlayers[player].name == playerName) {
playerToUpdate = allPlayers[player];
break;
}
}
//if we found the player who chatted in the game.
if (playerToUpdate != null) {
var playerText = $(elementToCheck).text();
var tmpPlayerText;
//important, we do toLowercase, so the regex does NOT need /gi
playerText = playerText.replace(playerName + ': ', '').toLowerCase();
//regex to check for string occurence
var flagPatt = /flag|flg|flga|falg|fagl|lagf|lafg|lfga|lfag/g;
//regex to get everything after the flag with a (.*) in it
var flagPattReplace = /^\bflag|\bflg|\bflga|\bfalg|\bfagl|\blagf|\blafg|\blfga|\blfag+(.*)/g;
//color pattern to match for players, includes "purp" and "yel" since those are common
var colorFullPatt = /\bred|\bgreen|\bpurple|\byellow|\bblue|\bbrown|\bteal(\w+)(?!\w)/g;
//if they did not spell the color name fully
var colorPartPatt = /\bred|\bgre|\bpur|\byel|\bblu|\bbro|\btea/g;
//number pattern
var numberPattern = /\d+/g;
//color matching variables
var colorMatch;
var colorMatchPlayer;
var numberMatchPlayer;
//for matching player names
var playerPatt;
var playerResult;
//have we found player(s)?
var hasFoundPlayer = false;
//var colorMatches = [];
//test the regex
var hasFlagged = flagPatt.test(playerText);
//only if they flagged, and it's not a question
if (hasFlagged == true) {
$(elementToCheck).css('background-color', '#DDDDDD');
//remove player flag text for regex checking, we want everything after the word flag
playerText = playerText.replace(flagPattReplace, '');
//STEP 1: See if the user typed out a full color name (no misspellings)
while (colorMatch = colorFullPatt.exec(playerText)) {
colorMatchPlayer = colorMatch[0];
updateCheckboxForFlag(playerToUpdate.colorName, colorMatchPlayer);
hasFoundPlayer = true;
}
//STEP 2: when players flag a number
if (hasFoundPlayer == false) {
while (colorMatch = numberPattern.exec(playerText)) {
numberMatchPlayer = colorMatch[0];
if (numberMatchPlayer > 0 && numberMatchPlayer < 7) {
updateFlagCountNumber(playerToUpdate.colorName, numberMatchPlayer);
hasFoundPlayer = true;
}
}
}
//STEP 3: Third best option, lets match player names
//by creating regex for each.
if (hasFoundPlayer == false) {
for (var player in allPlayers) {
if (allPlayers[player].name.length > 2) {
playerPatt = new RegExp('\\b' + allPlayers[player].name.substr(0, 2).toLowerCase() + '(\\w+)(?!\\w)', 'g');
playerResult = playerPatt.test(playerText);
if (playerResult == true) {
updateCheckboxForFlag(playerToUpdate.colorName, allPlayers[player].colorName);
hasFoundPlayer = true;
}
}
}
}
//STEP 4: third best option, try to find player from similar color words
//we only do this if none of the words matched before now.
if (hasFoundPlayer == false) {
while (colorMatch = colorPartPatt.exec(playerText)) {
colorMatchPlayer = colorMatch[0];
switch (colorMatchPlayer) {
case 'red':
updateCheckboxForFlag(playerToUpdate.colorName, 'red');
break;
case 'gre':
updateCheckboxForFlag(playerToUpdate.colorName, 'green');
break;
case 'pur':
updateCheckboxForFlag(playerToUpdate.colorName, 'purple');
break;
case 'yl':
case 'yel':
updateCheckboxForFlag(playerToUpdate.colorName, 'yellow');
break;
case 'blu':
updateCheckboxForFlag(playerToUpdate.colorName, 'blue');
break;
case 'bro':
updateCheckboxForFlag(playerToUpdate.colorName, 'brown');
break;
case 'tea':
updateCheckboxForFlag(playerToUpdate.colorName, 'teal');
break;
default:
//we don't know anything about the flag, highlight it
$(elementToCheck).css('background-color', '#660000');
break;
}
hasFoundPlayer = true;
}
}
if(hasFoundPlayer == false){
$(elementToCheck).css('background-color', '#660000');
}
}
}
}
}
//update the flag rank with a user specified count
function updateFlagCountNumber(flaggerColor, count) {
$('.' + flaggerColor + '-flag-position').html(count);
}
//update the desired rank with the # od checkboxes checked
function upddateRankCounts(flaggerColor) {
var count = $('#kdice-flag-table .' + flaggerColor + '-flagger:checked').size() + 1;
$('.' + flaggerColor + '-flag-position').html(count);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment