// ==UserScript==
// @name emjack++
// @version 3.4.3
// @description The new emjack
// @match https://epicmafia.com/game/*
// @author Foxie, Croned
// @namespace https://greasyfork.org/en/users/9694-croned
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
unsafeWindow.GM_setValue = GM_setValue;
unsafeWindow.GM_getValue = GM_getValue;
unsafeWindow.notes = {};
inject = document.createElement("script");
inject.id = "emjack";
inject.textContent = "void " + String(function () {
//initiate
var scope = $(document.body).scope(),
dev = false,
settings = scope.settings;
function log(msg) {
scope.log(msg, "ejack");
}
var roleDisplay = false;
var voteTracker = { "length": 0, "users": {}, "voted": {} };
var query;
var showvotes = true;
var setWill = false;
window.voteList = {};
var lastActive = false;
//abort if not mafia
var gamemode = document.title.match(/([\w\s]+)\s-/)[1];
if (gamemode !== "Epicmafia" || scope.compete || scope.ranked || scope.record) {
return;
}
$("body").mousemove(function() {lastActive = new Date().getTime()});
$("body").keypress(function() {lastActive = new Date().getTime()});
//load config
if (localStorage.notes && !scope.ranked) {
notes = JSON.parse(localStorage.notes);
}
//intercept packets
scope.execute_cmds = function (initial) {
//console.log("Init:" + initial);
return function (pkg) {
initial.call(scope, pkg);
//console.log(pkg);
for (var i = 0, cmd, data; i < pkg.length; ++i) {
cmd = pkg[i][0];
//console.log("COMMAND:" + cmd);
data = pkg[i][1];
//console.log("DATA:" + data);
if (dev) {
console.log(cmd, data);
}
if (cmd === "a") {
if (!ranked) {
if (!options.fastgame) {
scope.set_option("fastgame");
}
if (!options.nospectate) {
scope.set_option("nospectate");
}
}
}
else if (cmd === "join") {
log(data.user + " has joined");
}
else if (cmd === "leave") {
log(data.user + " has left");
}
else if (cmd === "kill") {
scope.users[data.target].dead = true;
}
else if (cmd === "kk") {
scope.users[data.user].dead = true;
}
else if (cmd === "speech") {
if (data.type === "contact") {
log("The roles are... " + data.data.join(", "));
}
}
else if (cmd === "ms") {
if (data === "Zombie wins!") {
log("brraaaaaaiiinnnsss...");
}
}
else if (cmd === "m") {
if (data.meet === "mafia" && data.choosedata) {
for (var key in scope.users) {
if (!data.choosedata[key] && !scope.users[key].dead) {
if (!scope.users[key].revealed) {
scope.select_role(key, "mafia");
}
if (data.members.indexOf(key) === -1) {
log(key + " is your partner!");
}
}
}
}
}
else if (cmd == "p") {
if (data.meet == "village") {
var vote;
voteList = {};
$(".meet_entity[id*='target']").each(function () {
vote = $(this).text().replace(/votes/g, "");
vote = vote.replace(/vote/g, "");
vote = vote.replace(/ /g, "");
if (vote) {
if (voteList[vote]) {
voteList[vote]++;
}
else {
voteList[vote] = 1;
}
}
});
}
}
}
}
}(scope.execute_cmds);
//chat input
$(window).on("keydown", function (event) {
if (event.target.value === undefined && !event.ctrlKey && !event.metaKey) {
$("#typebox").focus();
}
});
scope.keypress = function (initial) {
return function (event) {
if (event.which === 13) {
var input = event.target.value;
if (input[0] === "/") {
var cmd = input.match(/\/(\w+)/)[1],
data = input.match(/\/\w+\s?(.+)?/)[1];
if (cmd === "dev") {
dev = !dev;
log(dev ? "Logging on" : "Logging off");
}
else if (cmd === "help") {
log("/me - action message");
log("/ping - ping living players");
log("/join - join first open game");
log("/host - host game with current setup");
log("/games - list open games");
}
else if (cmd === "clear") {
$(".ejack").remove();
}
else if (cmd === "ping") {
var ping = [];
for (var key in scope.users) {
if (!scope.users[key].dead) {
ping.push(key);
}
}
event.target.value = ping.join(" ");
initial.call(scope, event);
return;
}
else if (cmd === "kick") {
if (data) {
data = data.toLowerCase();
for (var key in scope.users) {
if (key.toLowerCase() === data) {
scope.ban(scope.users[key].id);
break;
}
}
}
}
else if (cmd === "emotes") {
log("global - " + Object.keys(_emotes).join(" "));
log("lobby - " + Object.keys(lobby_emotes).join(" "));
}
else if (cmd === "whois") {
if (data) {
data = data.toLowerCase();
for (var key in scope.users) {
if (data === "all" || key.toLowerCase() === data) {
log(key + " (" + scope.users[key].id + ")");
var emotes = scope.users[key].emotes;
log(" -- emotes: " + (
emotes ? Object.keys(emotes).join(" ") : "none"
));
if (data !== "all") {
break;
}
}
}
}
}
else if (cmd === "games") {
var a,
div,
chat = document.getElementById("window");
lobbyGames({
status_id: 0,
password: false
}, function (table) {
a = document.createElement("a");
a.textContent = "Table " + table.id;
a.addEventListener("click", function (event) {
leaveand(function () {
location.href = "/game/" + table.id;
});
});
div = document.createElement("div");
div.className = "log ejack";
div.appendChild(a);
div.appendChild(document.createTextNode(" - " + table.numplayers + " / " + table.target + " players"));
chat.appendChild(div);
chat.scrollTop = chat.scrollHeight;
});
}
else if (cmd === "join") {
lobbyGames({
status_id: 0,
target: 12,
password: false
}, function (table) {
leaveand(function () {
location.href = "/game/" + table.id;
});
return true;
}
);
}
else if (cmd === "host") {
leaveand(function () {
$.getJSON("/game/add/mafia", {
setupid: scope.setup_id,
ranked: false,
add_title: data === undefined ? 0 : 1,
game_title: data
}, function (json) {
if (json[1].table) {
location.href = "/game/" + json[1].table;
}
}
);
});
}
else if (cmd === "leave") {
scope.definite_leave();
}
else if (cmd === "me") {
if (data) {
initial.call(scope, event);
return;
}
else {
log("Add text!");
log("i.e.: /me slaps Foxie with a fish");
}
}
else if (cmd == "toggle") {
if (showvotes) {
showvotes = false;
$(".jackVote").hide();
showVotesSetting = false;
}
else {
showvotes = true;
$(".jackVote").show();
showVotesSetting = true;
}
}
else if (cmd == "role") {
if (data) {
data = data.toLowerCase();
}
else {
data = scope.users[scope.user].role;
}
var roleurl = "/role/" + data + "/info/roleid";
var roleInfo = $.ajax({ method: "GET", url: roleurl, async: false });
roleInfo = roleInfo.responseText;
var roleHTML = $(roleInfo);
var roleName = roleHTML.find("h4").text();
if (roleName.length > 0) {
var roleAttrs = roleHTML.find("li");
log(roleName + ":");
for (var i = 0; i < roleAttrs.length; i++) {
log("* " + roleAttrs[i].textContent);
}
}
else {
log("Role does not exist!");
}
}
else if (cmd == "afk") {
if (autoAfkSetting) {
autoAfkSetting = false;
errordisplay(".errordisplay", "AFK Mode Off!");
} else {
autoAfkSetting = true;
errordisplay(".errordisplay", "AFK Mode On!");
}
}
else if (cmd == "nl") {
$(".booth_noimg").click();
}
else if (cmd == "vote") {
$(".one_booth_choice:contains('" + data + "')").click();
}
else if (cmd == "bug") {
$.post("/message", {msg: data, subject: "emjack Bug Report", "recipients[]": 392447});
log("Bug report sent!");
}
else if (cmd == "suggest") {
$.post("/message", {msg: data, subject: "emjack Suggestion", "recipients[]": 392447});
log("Suggestion sent!");
}
event.target.value = "";
return;
}
}
initial.call(scope, event);
};
}(scope.keypress);
//anti-votespam
var votetimes = [];
$(document).on("click", ".one_booth_choice", function (event) {
var now = Date.now();
for (var i = votetimes.length; i--;) {
if (now - votetimes[i] > 5000) {
votetimes.splice(i, 1);
}
}
votetimes.push(now);
if (votetimes.length > 10) {
log("You're voting too fast!");
event.stopPropogation();
}
});
void function (eventlist) {
eventlist.unshift(eventlist[eventlist.length - 1]);
eventlist.pop();
}($._data(document).events.click);
//utility
function leaveand(callback) {
scope.redirect_back = callback;
scope.definite_leave();
};
function lobbyGames(criteria, callback) {
$.ajax({ url: "/game/find?page=1", method: "get" }).success(function (json) {
var criterion,
openGames = [],
games = JSON.parse(json[1]);
games.data.forEach(function (table) {
for (criterion in criteria) {
if (criteria[criterion] !== table[criterion]) {
return;
}
}
openGames.push(table);
})
if (openGames.length === 0) {
log("No open games available!");
}
else {
openGames.some(function (table) {
return callback(table);
});
}
});
};
//clickable links
vocabs.push("https?://.+");
$(document).delegate(".acronym", "click", function () {
if (/\bhttps?:\/\/.+\b/ig.test(this.textContent)) {
window.open(this.textContent, "_blank");
}
});
//manage notes
if (!scope.ranked) {
$(document).on("mouseenter", ".user_li", function (event) {
this.setAttribute("title", notes[this.dataset.uname] || "no notes for " + this.dataset.uname);
});
$(document).on("click", ".user_note", function (event) {
var user = scope.selected_user;
if (user.details.notes === undefined) {
user.details.notes = notes[user.username] || "";
$(".notes").val(user.details.notes);
}
});
$(".notes").on("keyup", function (event) {
notes[scope.selected_user.username] = this.value;
});
}
//Init Vote Tracker
var setVoteInt = setInterval(function () {
if (scope.user_list.length > 0 && $(".jackVote").length == 0 && scope.gamestate > 0) {
for (var i = 0; i < scope.user_list.length; i++) {
if (!scope.users[scope.user_list[i]].dead) {
query = "[data-uname*='" + scope.user_list[i] + "']";
$(query).prepend("<span class='jackVote'>0</span>");
}
}
$(".jackVote").hide();
clearInterval(setVoteInt);
}
}, 100);
//Role Info, voteTracker, and setWill
setInterval(function () {
//voteTracker
if (scope.is_day() && showvotes) {
$(".jackVote").show();
for (var i = 0; i < scope.user_list.length; i++) {
query = "[data-uname*='" + scope.user_list[i] + "']";
if (voteList[scope.user_list[i]]) {
$(query).find(".jackVote").text(voteList[scope.user_list[i]]);
}
else {
$(query).find(".jackVote").text("0");
}
}
}
else {
$(".jackVote").hide();
}
//Role Display
if (!roleDisplay && scope.gamestate > 0 && scope.users[scope.user].role) {
var role = scope.users[scope.user].role;
var alignment = scope.role_data[scope.users[scope.user].role];
$(".gamesetup").append("<li class='jackLi'>Role: <span id='jackRole' class='jackSpan'></span> Alignment: <span id='jackAlign' class='jackSpan'></span></li>");
$(".jackLi").css({
"color": "#b44",
"font-weight": "bold",
"margin-left": "10px"
});
$(".jackSpan").css({
"color": "black",
"margin-right": "5px"
});
$("#jackRole").text(role);
$("#jackAlign").text(alignment);
roleDisplay = true;
}
//setWill
if (scope.is_night() && scope.gamestate == 1 && !setWill && scope.role_data[scope.users[scope.user].role] != "mafia") {
scope.lastwill = scope.user + ", " + scope.users[scope.user].role;
scope.update_will();
setWill = true;
}
//Typebox always visible
$("#speak_container").removeClass("ng-hide");
}, 100);
//AFK Mode
var gamestates = {};
var chosenYet;
var choices;
function doVote() {
$(".booth_choices").each(function() {
chosenYet = false;
choices = $(this).find(".booth_inner");
choices.each(function(index) {
if ($(this).text() == "no one") {
$(this).click();
chosenYet = true;
}
else if (!chosenYet && (choices.length - 1) == index) {
$(this).first().click();
chosenYet = true;
}
});
});
$(".inputchoice").click();
gamestates[scope.gamestate] = true;
}
setInterval(function(){
var currentTime = new Date().getTime();
if (!gamestates[scope.gamestate] && autoAfkSetting) {
if (Math.round( (currentTime - lastActive) / 1000 ) >= 5 && !$("#id_" + scope.user).text().replace("You", "").replace(" ", "") && scope.kick_countdown == "Time is up!") {
doVote();
}
}
}, 5000);
//save settings
var emjackSettings = {
acronym: false,
emoticons: false,
fullscreen: false,
mutemusic: false,
muting: false,
timestamp: false,
voting: false
};
setTrue = function (setting) {
var selector = "#" + setting;
$(selector).click();
};
var showVotesSetting = false;
emjackSettings.acronym = GM_getValue("emjack_acronym");
emjackSettings.emoticons = GM_getValue("emjack_emoticons");
emjackSettings.fullscreen = GM_getValue("emjack_fullscreen");
emjackSettings.mutemusic = GM_getValue("emjack_mutemusic");
emjackSettings.muting = GM_getValue("emjack_muting");
emjackSettings.timestamp = GM_getValue("emjack_timestamp");
emjackSettings.voting = GM_getValue("emjack_voting");
showVotesSetting = GM_getValue("emjack_showvotes");
autoAfkSetting = GM_getValue("emjack_autoafk");
for (var set in emjackSettings) {
if (emjackSettings.hasOwnProperty(set)) {
if (emjackSettings[set] && !scope.settings[set]) {
setTrue(set);
}
}
}
if (!showVotesSetting) {
showvotes = false;
$(".jackVote").hide();
}
$(window).on("beforeunload", function (event) {
localStorage.notes = JSON.stringify(notes);
for (set in scope.settings) {
if (scope.settings.hasOwnProperty(set)) {
saveSettings(set, scope.settings);
}
}
GM_setValue("emjack_showvotes", showVotesSetting);
GM_setValue("emjack_autoafk", autoAfkSetting);
});
saveSettings = function (set, settings) {
GM_setValue("emjack_" + set, settings[set]);
}
console.log("emjack++ activated!");
} + "()");
window.addEventListener("load", function (event) {
document.body.appendChild(inject);
});