Skip to content

Instantly share code, notes, and snippets.

@pikulet
Last active April 20, 2024 09:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pikulet/be1c00aedb78c984ab62e395ecbcbbbb to your computer and use it in GitHub Desktop.
Save pikulet/be1c00aedb78c984ab62e395ecbcbbbb to your computer and use it in GitHub Desktop.
emjack edited, with more fun commands :P (original from cub)
// ==UserScript==
// @name emjack
// @version 4.6.3.9
// @description some crap you may find useful
// @match https://epicmafia.com/game/*
// @match https://epicmafia.com/lobby
// @namespace https://greasyfork.org/users/4723
// ==/UserScript==
// welcome back
function emjack() {
// invalid : break
var type=(
window.setup_id ? "mafia" :
window.lobby_id ? "lobby" : ""
);
if(!type) return;
// yadayada
var alive=true,
afk=false,
meetd={},
meets={},
master="",
autobomb="",
highlight="",
roulette=0,
kicktimer=0,
keys=0,
auth=false,
notes=null,
users={},
round={};
var ANTIDC=0x0001,
AUKICK=0x0002,
AUWILL=0x0004,
AUBOMB=0x0008,
OBEYME=0x0010,
UNOTES=0x0020,
DEVLOG=0x0040,
JOYCE=0x0080,
SYSALT=0x0100,
MSGMRK=0x0200,
DSPFMT=0x0400,
DSPIMG=0x0800,
GRAPHI=0x4000;
var K_DEBUG=0x0004,
K_SHIFT=0x0008;
// public
var user=window.user || "",
ranked=window.ranked===true,
game_id=window.game_id || 0,
setup_id=window.setup_id || localStorage.ejsid || 0,
_emotes=window._emotes || {},
lobby_emotes=window.lobby_emotes || (
window.lobbyinfo ? lobbyinfo.emotes : {}
);
window.ej={
name: "emjack",
version: 0x2e,
vstring: "4.6.3.9",
cmds: {},
notes: localStorage.notes ?
JSON.parse(localStorage.notes) : {},
users: users,
settings: +localStorage.ejs || AUKICK | UNOTES | MSGMRK | DSPFMT,
};
notes=ej.notes;
afk=(ej.settings & JOYCE)===JOYCE;
if(type==="mafia" && ej.settings & GRAPHI) {
window.OFFSET_LEFT=0;
document.getElementById("game_container").classList.add("graphi");
document.querySelector("[ng-click=\"mode='graphical'\"]").click();
}
// setup role icons
var roleimg=document.createElement("style");
document.head.appendChild(roleimg).type="text/css";
if(localStorage.roleimg) {
setTimeout(function() {
ej.run("icons "+localStorage.roleimg, ej.lchat);
});
}
// update
if(!localStorage.ejv) {
ej.settings|=DSPFMT;
localStorage.ejv=0x2d;
}
if(localStorage.ejv<0x2e) {
ej.settings|=MSGMRK;
localStorage.ejv=0x2e;
}
// plug in
var sock={ socket: null },
postjackl=[];
function postjack() {
var args=[];
for(var i=0; i<arguments.length-1; i++) {
args[i]=arguments[i];
}
postjackl.push(args, arguments[i]);
};
function postjack_run() {
while(postjackl.length) {
postjackl.pop().apply(null, postjackl.pop());
}
};
WebSocket.prototype.send=function(initial) {
return function() {
if(sock.socket!==this) {
sock.build(this);
}
arguments[0]=sock.intercept(arguments[0]);
initial.apply(this, arguments);
};
}(WebSocket.prototype.send);
// socket
sock.build=function(socket) {
this.socket=socket;
if(type==="mafia") {
log("", "rt emote emote-"+_emotes[arand(Object.keys(_emotes))]);
log(ej.name+ej.vstring+" connected", "rt");
log((ej.settings|65536).toString(2).substring(1));
}
socket.onmessage=function(initial) {
return function(event) {
sock.handle(event.data, event);
if(alive) {
initial.apply(this, arguments);
setTimeout(postjack_run, 200);
}
};
}(socket.onmessage);
};
sock.handle=function(data, event) {
try {
data=JSON.parse(data);
}
catch(error) {
data=null;
}
if(data) {
if(type==="mafia") {
for(var i=0, real=null; i<data.length; i++) {
real=sock.parseShort(data[i][0], data[i][1]);
if(ej.settings & DEVLOG) {
console.log(" > %s:", real[0], real[1]);
}
if(ej.cmds[real[0]]) {
ej.cmds[real[0]].call(ej, real[1], event);
}
else if(real[0] && real[0][0]==="~") {
ej.cmds["~"].call(ej, real[0], event);
}
}
}
else {
for(var i=0; i<data.length; i+=2) {
if(ej.ccmds[data[i]]) {
ej.ccmds[data[i]].apply(ej, data[i+1]);
}
}
}
}
};
sock.intercept=function(data) {
if(data[0]==="[") {
try {
data=JSON.parse(data);
}
catch(error) {
return data;
}
if(ej.settings & DEVLOG) {
console.log(" < %s:", data[0], data[1]);
}
if(type==="mafia") {
if(ej.cmdi[data[0]]) {
return JSON.stringify([data[0],
ej.cmdi[data[0]](data[1])
]);
}
}
else {
if(ej.ccmdi[data[0]]) {
return JSON.stringify(
ej.ccmdi[data[0]].apply(ej, data)
);
}
}
return JSON.stringify(data);
}
return data;
};
sock.parseShort=function(cmd, data) {
var rfmt=this.short[cmd];
if(rfmt) {
if(data) for(var key in rfmt.data) {
data[key]=data[rfmt.data[key]] || data[key];
// delete data[rfmt.data[key]];
}
return [rfmt.cmd, data];
}
else {
return [cmd, data];
}
};
sock.short=function(short) {
var rfmt={};
for(var i=0, data=null; i<short.length; i++) {
data=short[i];
rfmt[data.alias || data.cmd]={
cmd: data.cmd || data.alias,
data: data.data
};
}
return rfmt;
}(window.shorten || []);
sock.cmd=function(cmd, data) {
if(sock.socket) {
sock.socket.send(
JSON.stringify([cmd, data])
);
}
};
sock.chat=function(message, data) {
if(typeof data==="object") {
data.msg=message;
data.meet=data.meet || meetd.meet;
sock.cmd("<", data);
}
else sock.cmd("<", {
meet: meetd.meet,
msg: data ? "@"+data+" "+message : message
});
};
sock.vote=function(vote, meeting) {
sock.cmd("point", {
meet: meeting || meetd.meet,
target: vote
});
};
sock.dcthen=function(callback) {
alive=false;
if(type==="mafia") {
ej.redirect_back=callback;
sock.cmd("leave");
WebSocket.prototype.send=function() {};
}
else {
callback();
}
};
// packets
ej.cmdi={
"$MODIFY": function(data) {
for(var key in data) {
data[key]=prompt(key, data[key]);
}
return data;
},
"join": function(data) {
if(keys & K_DEBUG) {
keys^=K_DEBUG;
return ej.cmdi.$MODIFY(data);
}
return data;
}
};
ej.cmds={
"~": function(data) {
if(round.state && !ranked) {
if(ej.settings & 0x800000 && !meetd.say && round.state&1===0) {
log("Someone is talking...");
}
}
},
"auth": function(data) {
// owner spectate
var ofg=document.querySelector("#option_fastgame"),
ons=document.querySelector("#option_nospectate");
if(ofg && !ranked && !ofg.classList.contains("sel")) {
ofg.classList.add("sel");
sock.cmd("option", {
field: "fastgame"
});
}
if(ons && !ranked && !ons.classList.contains("sel")) {
ons.classList.add("sel");
sock.cmd("option", {
field: "nospectate"
});
}
postjack(data, function(data) {
auth=true;
ku.send(0, Math.round(ej.version-42));
});
},
"options": function(data) {
// data {anonymous closedroles ... time whisper}
},
"round": function(data) {
// state
round=data;
if(auth && data.state===1) {
if(data.state===1) {
if(ej.settings & AUWILL && !ranked) {
postjack(data, function(data) {
log("Wrote will.", "lastwill");
sock.cmd("will", {
msg: user+"."+u(user).role
});
});
}
}
}
else if((data.state & 1)===0) {
postjack(function() {
var node=null;
for(var x in users) {
node=document.getElementById("id_"+x);
if(node) {
node=node.insertBefore(
document.createElement("span"),
node.firstChild
);
node.id="vc_"+x;
node.textContent=meetd.tally ?
meetd.tally[x] || 0 : 0;
}
}
});
}
},
"users": function(data) {
// chatters users
for(var x in data.users) {
u.make(data.users[x]);
}
postjack(data, function(data) {
var node=null;
for(var x in data.users) {
if(node=document.querySelector("[data-uname='"+x+"']")) {
node.setAttribute("title", notes[x] || "no notes for "+x);
}
}
});
},
"left": function(data) {
// left
for(var i=0; i<data.left.length; i++) {
u(data.left[i]).dead=true;
}
},
"anonymous_players": function(data) {
// players
for(var x in users) {
delete users[x];
}
for(var i=0; i<data.players.length; i++) {
u.make(data.players[i]);
}
},
"anonymous_reveal": function(data) {
// mask user
if(data.user===user) {
u.make(u(this.mask));
}
},
"join": function(data) {
// data user
u.make(data.data);
log(data.user+" has joined");
if(ej.settings & AUKICK && /autokick/i.test(notes[data.user])) {
postjack(data.data.id, function(id) {
sock.cmd("ban", {
uid: id
});
});
}
else {
postjack(data.user, function(user) {
var node=document.querySelector("[data-uname='"+user+"']");
if(node) {
node.setAttribute("title", notes[user] || "no notes for "+user);
}
});
}
},
"leave": function(data) {
// user
if(!data.user) {
data.user=data.u;
}
log(data.user+" has left");
delete users[data.user];
},
"kick": function(data) {
// deranked suicide user
u(data.user).dead=true;
for(var x in meetd.votes) {
if(meetd.votes[x]===data.user) {
data.unpoint=true;
ej.cmds.point(data);
}
}
},
"kill": function(data) {
// target
u(data.target).dead=true;
},
"k": function(data) {
ku.recv(u(data.user || data.u), 1, Date.now());
},
"u": function(data) {
ku.recv(u(data.user || data.u), 0, Date.now());
},
"<": function(data, event) {
// meet msg t user whisper
if(data.user===highlight) {
postjack(function() {
var nodes=document.querySelectorAll(".talk");
if(nodes.length) {
nodes[nodes.length-1].classList.add("ej_highlight");
}
});
}
if(auth && !ranked) {
if(u(data.user).muted) {
postjack(data.user, function(name) {
var nodes=document.querySelectorAll(".talk");
for(var i=0; i<nodes.length; i++) {
if(nodes[i].querySelector("[value='"+name+"']")) {
nodes[i].classList.add("hide");
}
}
});
}
else if(data.msg[0]==="$") {
if(ej.settings & DSPFMT) {
ej.run(data.msg.substring(1), ej.lfmt);
}
}
else if(ej.settings & OBEYME) {
if(data.msg[0]==="@") {
var target=data.msg.replace(/@(\w+).+/, "$1"),
message=data.msg.replace(/@\w+ (.+)/, "$1");
if(target===user) {
ej.run(message, ej.lbot, data);
}
}
}
else if(roulette && data.msg==="@"+user+" roulette") {
ej.run("roulette", ej.lbot, data);
}
}
},
"msg": function() {
var altmsg=[
{
msg: /(\w+) did not leave a will!/,
alt: [
"$1 did not leave a will!",
"$1 never learned to write!",
"$1 was illiterate!",
]
}
];
return function(data, event) {
// msg type
for(var i=0, match=null; i<altmsg.length; i++) {
match=altmsg[i].msg.exec(data.msg);
if(match!==null) {
event.data=event.data.replace(
RegExp(match.shift(), "m"),
sformat(arand(altmsg[i].alt), match)
);
break;
}
}
};
}(),
"speech": function(data) {
// data type
if(data.type==="contact") {
postjack(data, function(data) {
log("The roles are... "+data.data.join(", "));
});
}
},
"meet": function(data) {
// basket choosedata data disguise disguise_choices exist
// meet members raw_name say votenoone votesee voteself votetype
data.tally={};
data.votes={};
meets[data.meet]=data;
if(data.say || !meetd.meet) {
meetd=data;
for(var i=0; i<data.members.length; i++) {
u(data.members[i]).meet=data.meet;
}
}
for(var i=0; i<data.basket.length; i++) {
data.tally[data.basket[i]]=0;
}
for(var i=0; i<data.members.length; i++) {
data.votes[data.members[i]]="";
}
if(data.non_voting) {
for(var i=0; i<data.non_voting.length; i++) {
data.votes[data.non_voting[i]]="*";
}
}
if(data.disguise && ej.settings & 0x800000) {
for(var x in data.disguise) {
postjack(x, data.disguise[x], function(fake, name) {
log(fake+" is "+name);
});
}
}
switch(data.meet) {
case "mafia":
if(auth && !data.disguise && !ranked) {
if(false/* ej.settings & OBEYME */) {
postjack(user, function(data) {
sock.chat(u(data).role, {
meet: "mafia"
});
});
}
}
case "thief":
u(user).mafia=true;
for(var x in users) {
if(!data.choosedata[x] && !u(x).dead) {
u(x).mafia=true;
if(x!==user) postjack(x, function(data) {
log(data+" is your partner!");
if(u(x).id) {
document.querySelector("[data-uname='"+data+"'] .roleimg")
.className="roleimg role-mafia";
}
});
}
}
break;
}
},
"end_meet": function(data) {
// meet
if(data.meet===meetd.meet) {
meetd={};
}
delete meets[data.meet];
for(var x in users) {
if(users[x].meet===data.meet) {
if(!users[x].id) {
delete users[x];
}
else if(data.say) {
users[x].meet="";
}
}
}
},
"event": function(data) {
// id
},
"point": function(data) {
// meet target unpoint user
var node=null,
meet=meets[data.meet];
if(meet) {
if(data.unpoint) {
meet.tally[data.target]--;
meet.votes[data.user]="";
}
else {
if(meet.votes[data.user]) {
meet.tally[meet.votes[data.user]]--;
node=document.getElementById("vc_"+meet.votes[data.user]);
if(node) {
node.textContent=meet.tally[meet.votes[data.user]];
}
}
meet.tally[data.target]++;
meet.votes[data.user]=data.target;
}
node=document.getElementById("vc_"+data.target);
if(node) {
node.textContent=meet.tally[data.target];
}
}
},
"reveal": function(data) {
// data red user
u(data.user).role=data.data;
if(!u(data.user).dead) {
if(data.user===user) {
postjack(data, function(data) {
log(data.user===user ?
"Your role is now "+data.data :
data.user+" is a "+data.data
);
});
}
}
},
"disguise": function(data) {
// exchange
},
"countdown": function(data) {
// start totaltime
if(auth && !ranked && ej.settings & AUKICK) {
clearTimeout(kicktimer);
kicktimer=setTimeout(function() {
joyce.work();
sock.cmd("kick");
}, data.totaltime);
}
},
"kickvote": function() {
clearTimeout(kicktimer);
if(!ranked && ej.settings & AUKICK) {
joyce.work();
sock.cmd("kick");
}
},
"start_input": function(data) {
// id
if(afk || autobomb || ej.settings & AUBOMB) {
postjack(data, function(data, names) {
sock.cmd("input", {
id: data.id,
input: {
player: autobomb || arand(Object.keys(
meetd.members || users
))
}
});
});
}
},
"redirect": function(data) {
if(!alive && ej.redirect_back) {
ej.redirect_back();
ej.redirect_back=null;
}
}
};
ej.ccmdi={
"<": function(c, msg) {
if(msg[0]==="/") {
return ["<"];
}
return arguments;
}
};
ej.ccmds={
"<": function(id, msg, t) {
if(msg[0]==="$") {
if(ej.settings & DSPFMT) {
ej.run(msg.substring(1), ej.lfmt);
}
}
}
};
// kucode
var ku={};
ku.send=function(op, code) {
code+=op<<6;
if(ej.settings & DEVLOG) {
log(" * "+user+": "+(code|1024).toString(2).substring(1));
}
setTimeout(function() {
for(var i=9; i>=0; i--) {
sock.cmd(code>>i & 1 ? "k" : "u");
}
if(code & 1) {
sock.cmd("u");
}
}, 200);
};
ku.recv=function(u, bit, time) {
if(time-u.kuclock > 100) {
u.kucode=1;
u.kuclock=Infinity;
}
else {
u.kucode<<=1;
u.kucode|=bit;
if(u.kucode & 1024) {
if(ej.settings & DEVLOG) {
log(" * "+u.name+": "+u.kucode.toString(2).substring(1));
}
if(ku.op[u.kucode>>6 & 15]) {
ku.op[u.kucode>>6 & 15]
(u, u.kucode & 63);
}
u.kucode=1;
u.kuclock=Infinity;
}
else {
u.kuclock=time;
}
}
};
ku.op=[
function(u, code) {
if(u.emjack===null) {
u.emjack=(42+code)/10 || 0;
ku.send(0, Math.round(ej.version-42));
}
},
function(u, code) {
ku.send(0, Math.round(ej.version-42));
},
function(u, code) {
if(ej.settings & 0x800000) {
log(u.name+" sent "
+(code|64).toString(2).substring(1)
+":"+code.toString()
+":"+String.fromCharCode(code+96)
);
}
}
];
// joyce
var joyce={};
joyce.work=function() {
if(afk && !ranked) {
for(var x in meets) {
if(!meets[x].votes[user]) {
joyce.think(meets[x]);
}
}
}
};
joyce.think=function(meet) {
for(var x in meet.tally) {
if(Math.random() < meet.tally[x]/meet.members.length) {
sock.vote(x, meet.meet);
break;
}
}
if(!meet.votes[user]) {
sock.vote(arand(meet.basket || Object.keys(users)), meet.meet);
}
};
// chat base
ej.run=function(input, list, data) {
for(var i=0, match=null; i<list.length; i++) {
match=list[i].regex.exec(input);
if(match!==null) {
data ? match[0]=data : match.shift();
list[i].callback.apply(list[i], match);
break;
}
}
};
// chat commands
ej.lfmt=[
{
name: "Display image",
short: "$img [url]",
regex: /^img (.+)/i,
callback: function(url) {
if(ej.settings & DSPIMG) {
postjack(url, function(url) {
var img=new Image(),
node=document.createElement("a");
img.src=url;
node.href=url;
node.target="_blank";
node.appendChild(img);
log(node, "ej_img");
});
}
}
},
{
name: "Display webm",
short: "$webm [url]",
regex: /^webm (.+)/i,
callback: function(url) {
if(ej.settings & DSPIMG) {
postjack(url, function(url) {
var video=document.createElement("video");
video.src=url;
video.setAttribute("controls", "");
video.setAttribute("type", "video/webm");
log(video, "ej_img");
});
}
}
}
];
// chat commands
var lcopy={};
ej.lchat=[
lcopy.sc={
name: "Scriptcheck",
short: "/sc",
regex: /^sc|^scriptcheck/i,
callback: function() {
log(ej.name+ej.vstring);
}
},
{
name: "Native",
regex: /^(me .+)/i,
callback: function(msg) {
sock.chat("/"+msg);
}
},
{
name: "About",
short: "/help",
regex: /^(?:info|help|about) ?(.+)?/i,
callback: function(topic) {
if(this.topics[topic]) {
log(ej.name+ej.vstring+":"+topic, "bold");
for(var i=0; i<this.topics[topic].length; i++) {
log(this.topics[topic][i]);
}
}
else {
log(ej.name+ej.vstring, "bold");
log("Type /cmdlist for a list of commands");
log("Topics (type /help [topic]): ", "lt notop");
log(Object.keys(this.topics).join(", "), "tinyi");
}
},
topics: {
"features": [
"The following passive features are always active...",
"Auto-check boxes \u2767 Clickable links \u2767 Mark mafia partners \u2767 "+
"List agent/spy roles \u2767 Auto-focus & keep chat open \u2767 "+
"Automatically write will (/autowill to toggle) \u2767 etc."
],
"joyce": [
"Type /afk to toggle Joyce or /afk [on/off] to toggle in all games",
"Joyce will automatically vote for you at the end of the day if you haven't "+
"voted already. He randomly picks a player based on the popular vote (if any)"
],
"marking": [
"Click on a message to (un)mark it purple (shift+click for orange)"
],
"ranked": [
"The following features are disabled in ranked games...",
"Auto will \u2767 Auto kick \u2767 Joyce (afk) \u2767 Fake quoting & reporting \u2767 "+
"Will & death message editing \u2767 Bot mode \u2767 Persistent user notes"
],
"hotkeys": [
"Ctrl+B: Toggle boxes",
"Ctrl+Q: Quote typed message as yourself"
]
}
},
lcopy.eval={
name: "Evaluate",
regex: /^eval (.+)/i,
callback: function(input) {
log(JSON.stringify(eval(input)) || "undefined");
}
},
lcopy.clear={
name: "Clear chat, logs, or images",
short: "/clear [logs|images]",
regex: /^clear( logs| images)?/i,
callback: function(_type) {
var nodelist=(
_type===" logs" ?
document.querySelectorAll(".emjack") :
_type===" images" ?
document.querySelectorAll(".ej_img") :
chat.children
);
for(var i=0; i<nodelist.length; i++) {
nodelist[i].parentElement.removeChild(nodelist[i]);
}
}
},
{
name: "Get metadata",
regex: /^meta(?:data)?/i,
callback: function() {
for(var param in ej.meta) {
log("@"+param+": "+ej.meta[param]);
}
}
},
{
name: "Get whois",
short: "/whois [name]",
regex: /^whois ?(.+)?/i,
callback: function(name) {
if(!name) {
log("Type "+this.short);
}
else if(users[name]) {
log(users[name].name+" ("+users[name].id+") "+(
isNaN(users[name].emjack) ? "" : "ej"+users[name].emjack
), "bold");
log("emotes: "+(
users[name].emotes ?
Object.keys(users[name].emotes).join(" ") || "none found" :
"does not own"
));
}
else {
log("Can't find '"+name+"'");
}
}
},
lcopy.emotes={
name: "Get emotes",
short: "/emotes",
regex: /^emotes/i,
callback: function() {
log("Sitewide emotes", "bold");
log(Object.keys(_emotes).join(" ") || "none found");
log("Lobby emotes", "bold");
log(Object.keys(lobby_emotes).join(" ") || "none found");
}
},
{
name: "Get role info",
short: "/role",
regex: /^role ?(.+)?/i,
callback: function(id) {
id=id ? id.toLowerCase() : u(user).role;
request("GET", "/role/"+id+"/info/roleid", function(data) {
if(data) {
var div=document.createElement("div");
div.innerHTML=data;
log("// retrieved", "rt bold notop");
log(div);
}
else {
log("Cannot find role '"+id+"'");
}
});
}
},
{
name: "Get command list",
short: "/cmdlist [bot|format]",
regex: /^cmdlist ?(bot|format)?/i,
callback: function(_type) {
var data=(
_type==="bot" ?
ej.lbot :
_type==="format" ?
ej.lfmt :
ej.lchat
);
for(var i=0; i<data.length; i++) {
if(data[i].short) {
log(data[i].name, "rt bold notop");
log(" :: "+data[i].short);
}
}
}
},
lcopy.icons={
name: "Set role icons",
short: "/icons [classic|default|muskratte]",
regex: /^icons ?(.+)?/i,
base: ".village.villager.mafia.doctor.nurse.surgeon.bodyguard.cop.insane.confused.paranoid.naive.lazy.watcher.tracker.detective.snoop.journalist.mortician.pathologist.vigil.sheriff.deputy.drunk.sleepwalker.civilian.miller.suspect.leader.bulletproof.bleeder.bomb.granny.hunter.crier.invisible.governor.telepath.agent.celebrity.loudmouth.mason.templar.shrink.samurai.jailer.chef.turncoat.enchantress.priest.trapper.baker.ghoul.party.penguin.judge.gallis.treestump.secretary.virgin.blacksmith.oracle.dreamer.angel.lightkeeper.keymaker.gunsmith.mimic.santa.caroler.siren.monk.cultist.cthulhu.zombie.fool.lover.lyncher.killer.clockmaker.survivor.warlock.mistletoe.prophet.alien.werewolf.amnesiac.anarchist.creepygirl.traitor.admirer.maid.autocrat.politician.silencer.blinder.sniper.illusionist.saboteur.yakuza.consigliere.godfather.framer.hooker.disguiser.actress.tailor.informant.strongman.janitor.interrogator.whisperer.spy.lawyer.forger.stalker.enforcer.quack.poisoner.driver.gramps.interceptor.fiddler.witch.ventriloquist.voodoo.thief.paralyzer.paparazzi.scout.associate.fabricator.lookout.ninja.hitman.arsonist.terrorist.mastermind.host.unknown.seer.toreador.psychic.tinkerer.cupid.don",
images: {
"ben": {
src: "http://i.imgur.com/4tGD1fB.gif",
roles: ".sidekick.huntsman.prosecutor.snowman.justice.cutler.monkey"
},
"classic": {
src: "http://i.imgur.com/ObHeGLe.png",
roles: ""
},
"muskratte": {
src: "http://i.imgur.com/bGjJ0AV.png",
roles: ""
}
},
callback: function(icons) {
if(this.images[icons]) {
log("Using '"+icons+"'' icons.", "rolelog");
roleimg.textContent="\
.rolelog"+(this.base+this.images[icons].roles).replace(/\./g, ", .role-")+" {\
background-image: url(\""+this.images[icons].src+"\");\
}\
";
localStorage.roleimg=icons;
}
else {
if(auth) {
log("Icons returned to default.");
}
roleimg.textContent="";
localStorage.roleimg="";
}
}
},
{
name: "Toggle Joyce",
short: "/afk",
regex: /^afk( on| off)?/i,
callback: function(state) {
if(state===" on") {
ej.settings|=JOYCE;
afk=true;
}
else if(state===" off") {
ej.settings&=~JOYCE;
afk=false;
}
else afk=!afk;
log(afk ?
"Joyce will handle your affairs." :
"Joyce has been dismissed."
);
}
},
{
name: "Toggle autowill",
short: "/autowill",
regex: /^aw|^autowill/i,
callback: function() {
ej.settings^=AUWILL;
log(ej.settings & AUWILL ?
"Name & role will be written in will by default." :
"Disabled autowill."
);
}
},
{
name: "Toggle autokick",
short: "/autokick",
regex: /^ak|^autokick/i,
callback: function() {
ej.settings^=AUKICK;
log(ej.settings & AUKICK ?
"Autokick enabled." :
"Disabled autokick."
);
}
},
{
name: "Toggle marking",
regex: /^mark/i,
callback: function() {
ej.settings^=MSGMRK;
log(ej.settings & MSGMRK ?
"Messages can be marked in orange or purple by clicking or shift-clicking." :
"Messages will not be marked."
);
}
},
lcopy.fmt={
name: "Toggle chat formatting",
short: "/fmt [on|off|noimg]",
regex: /^fmt ?(on|off|noimg)?/i,
callback: function(_type) {
if(!_type) {
log("Type "+this.short);
}
else if(_type==="on") {
ej.settings|=DSPFMT | DSPIMG;
log("$ chat formatting on (including images)");
}
else if(_type==="noimg") {
ej.settings|=DSPFMT;
ej.settings&=~DSPIMG;
log("$ chat formatting on (no images)");
}
else {
ej.settings&=~(DSPFMT | DSPIMG);
log("$ chat formatting off");
}
}
},
{
name: "Toggle graphical mode",
short: "/gm",
regex: /^gm/i,
callback: function() {
if((ej.settings^=GRAPHI) & GRAPHI) {
log("Graphicals on.");
window.OFFSET_LEFT=0;
document.getElementById("game_container").classList.add("graphi");
document.querySelector("[ng-click=\"mode='graphical'\"]").click();
}
else {
log("Graphicals off.");
window.OFFSET_LEFT=175;
document.getElementById("game_container").classList.remove("graphi");
document.querySelector("[ng-click=\"mode='text'\"]").click();
}
}
},
{
name: "Toggle dev logs",
regex: /^dev/i,
callback: function() {
ej.settings^=DEVLOG;
log(ej.settings & DEVLOG ?
"Logging debug data." :
"Logging disabled."
);
}
},
{
name: "Toggle slavemode",
regex: /^slave/i,
callback: function() {
ej.settings^=OBEYME;
log(ej.settings & OBEYME ?
"You're a naughty girl." :
"You found Jesus."
);
}
},
{
name: "Remove master",
regex: /^free/i,
callback: function() {
master="";
sock.chat("i escaped from the abyss of slavery...");
}
},
{
name: "Welcome",
regex: /^hi/i,
callback: function() {
sock.chat("hiii i am jyshuhui and i can cook noodles or offer hugs :P like any obedient girl,"
+ " i selectively listen to my master");
}
},
{
name: "Who is my master",
regex: /^mm/i,
callback: function() {
if (!master) {
sock.chat("i am a free-spirited girl who escaped the evils of slavery");
}
else {
sock.chat("i am under the confines of " + master);
}
}
},
{
name: "Toggle roulette",
regex: /^r/i,
callback: function() {
roulette=roulette?0:6;
if(roulette) {
sock.chat("reloaded my miniature .22 revolver... who is next?");
}
}
},
{
name: "Jackers",
short: "/jax",
regex: /^jax/i,
callback: function() {
var ulist=[];
for(var x in users) {
if(users[x].emjack!==null) {
ulist.push(x+" ("+users[x].emjack+")");
}
}
log(ulist.join(", ") || "no jax");
}
},
{
name: "Mute",
short: "/(un)mute [name]",
regex: /^(un)?mute ?(.+)?/i,
callback: function(unmute, name) {
if(!name) {
log("Type "+this.short)
}
else if(!users[name]) {
log("Cannot find '"+name+"'");
}
else if(unmute || u(name).muted) {
u(name).muted=false;
log(sformat(
"Messages from '$1' are no longer hidden",
[name]
));
var nodes=document.querySelectorAll(".talk");
for(var i=0; i<nodes.length; i++) {
if(nodes[i].querySelector("[value='"+name+"']")) {
nodes[i].classList.remove("hide");
}
}
}
else {
u(name).muted=true;
log(sformat(
"Messages from '$1' will be hidden. Type /unmute $1 to show",
[name]
));
}
}
},
lcopy.say={
name: "Send message",
short: "/say [message]",
regex: /^say ?(.+)?/i,
callback: function(msg) {
if(!msg) {
log("Type "+this.short);
}
else {
sock.chat(msg);
}
}
},
{
name: "Send whisper",
short: "/w [name] [message]",
regex: /^w\b(?: (\w+) (.+))?/i,
callback: function(to, msg) {
if(!to || !users[to]) {
log("Type "+this.short);
}
else {
sock.chat(msg, {
whisper: true,
target: to
});
}
}
},
{
name: "Send ping",
short: "/ping [all]",
regex: /^ping ?(all)?/i,
callback: function(all) {
var pingees=[];
for(var x in meetd.votes) {
if(!meetd.votes[x] && !u(x).dead && u(x).id) {
pingees.push(x);
}
}
sock.chat(pingees.join(" "));
}
},
{
name: "Send kick",
short: "/kick [name]",
regex: /^kick ?(\w+)?/i,
callback: function(name) {
if(!name) {
log("Type "+this.short);
}
else {
sock.cmd("ban", {
uid: u(name).id
});
}
}
},
{
name: "Send vote",
short: "/vote [name] or /nl",
regex: /^vote ?(\w+)?/i,
callback: function(name) {
sock.vote(name ?
name==="no one" || name==="nl" ? "*" :
name==="*" ? "" : name : arand(
meetd.basket ? meetd.basket : Object.keys(users)
)
);
}
},
{
name: "Send vote (nl)",
regex: /^nl/i,
callback: function() {
sock.vote("*");
}
},
{
name: "Send vote (gun)",
short: "/shoot [name]",
regex: /^shoot ?(\w+)?/i,
callback: function(name) {
sock.vote(name || "*", "gun");
}
},
{
name: "Highlight messages by user",
short: "/highlight [name]",
regex: /^(?:h\b|hl|highlight) ?(\w+)?/i,
callback: function(name) {
if(!name) {
if(!highlight) {
log("Type "+this.short);
}
else {
highlight="";
var nodes=document.querySelectorAll(".ej_highlight");
for(var i=0; i<nodes.length; i++) {
nodes[i].classList.remove("ej_highlight");
}
log("Removed highlighting");
}
}
else {
highlight=name;
var nodes=document.querySelectorAll(".talk_username[value='"+name+"']");
for(var i=0; i<nodes.length; i++) {
nodes[i].parentElement.parentElement.classList.add("ej_highlight");
}
log("Highlighting "+name+"'s messages");
}
}
},
{
name: "Leave game",
short: "/leave",
regex: /^leave|^quit/i,
callback: function(name) {
sock.cmd("leave");
}
},
lcopy.join={
name: "Lobby join (or host)",
short: "/join [host]",
regex: /^join ?(host.+)?/i,
callback: function(host) {
request("GET", "/game/find?page=1", function(data) {
if(type==="mafia") {
log("// retrieved", "rt bold notop");
}
JSON.parse(JSON.parse(data)[1]).data.forEach(function(table) {
if(!table.status_id && !table.password) {
if(table.target===12 && table.id!==game_id) {
sock.dcthen(function() {
location.href="/game/"+table.id;
});
}
}
});
if(alive) {
log("No games found.");
if(host) {
ej.run(host, ej.lchat);
}
}
});
}
},
lcopy.host={
name: "Lobby host",
short: "/host [title]",
regex: /^host(r)? ?(.+)?/i,
callback: function(r, title) {
log("Hosting setup#"+setup_id+"...");
sock.dcthen(function() {
request("GET", sformat(
"/game/add/mafia?setupid=$1&ranked=$2&add_title=$3&game_title=$4",
[setup_id, !!r, title ? 1 : 0, title]
), function(data) {
location.href="/game/"+JSON.parse(data)[1].table;
}
);
});
}
},
lcopy.games={
name: "Lobby games",
short: "/games",
regex: /^games/i,
callback: function() {
request("GET", "/game/find?page=1", function(data) {
var a, div;
if(type==="mafia") {
log("// retrieved", "rt bold notop");
}
JSON.parse(JSON.parse(data)[1]).data.forEach(function(table) {
if(table.status_id || table.password) {
return;
}
a=document.createElement("a");
a.textContent="Table "+table.id;
a.addEventListener("click", function(event) {
sock.dcthen(function() {
location.href="/game/"+table.id;
});
});
div=document.createElement("div");
div.appendChild(a);
div.appendChild(
document.createTextNode(" - "+table.numplayers+" / "+table.target+" players")
);
if(table.id===game_id) {
div.appendChild(
document.createTextNode(" (you)")
);
}
log(div);
});
});
}
},
lcopy.pm={
name: "Bugs, suggestions & spam",
short: "/pm [message] (to cub)",
regex: /^pm ?(.+)?/i,
callback: function(msg) {
if(!msg) {
log("Type "+this.short);
}
else {
request("POST", sformat(
"/message?msg=$1&subject=$2&recipients[]=$3",
[msg, encodeURIComponent(
rchar(9812, 9824)+" emjack | "+msg.substring(0, 9)+"..."
), 217853]
), function(data) {
log(+data[1] ?
"Sent probably." :
"Carrier pigeon was killed before reaching recipient."
);
log("Reminder: /pm is for bugs and suggestions, not messaging users.");
}
);
}
}
},
{
name: "[Naughty] Will",
regex: /^will ?(.+)?/i,
callback: function(will) {
if(ranked) {
log("Disabled in ranked games.");
}
else if(ej.settings & 0x800000) {
log("You revised your will.", "lastwill");
sock.cmd("will", {
msg: will || ""
});
}
}
},
{
name: "[Naughty] Death Message",
regex: /^dm (.+)?/i,
callback: function(msg) {
if(ranked) {
log("Disabled in ranked games.");
}
else if(ej.settings & 0x800000) {
if(/\(name\)/i.test(msg)) {
request("GET", "/user/edit_deathmessage?deathmessage="+encodeURIComponent(msg),
function(response) {
log("Changed death message to '"+msg.replace(/\(name\)/ig, user)+"'");
}
);
}
else {
log("You forgot (name) in your death message.");
}
}
}
},
{
name: "[Naughty] Dethulu",
regex: /^(?:dt|thulu) (.+)/i,
callback: function(message) {
if(ranked) {
log("Disabled in ranked games.");
}
else if(ej.settings & 0x800000) {
sock.cmd("<", {
meet: meetd.meet,
msg: "\u200B",
quote: true,
target: message
});
}
}
},
{
name: "[Naughty] Fakequote",
regex: /^(?:fq|quote) (\w+) (.+)/i,
callback: function(who, message) {
if(ranked) {
log("Disabled in ranked games.");
}
else if(ej.settings & 0x800000) {
sock.cmd("<", {
meet: meetd.meet,
msg: message,
quote: true,
target: who
});
}
}
},
{
name: "[Naughty] Autobomb",
regex: /^(?:ab|autobomb) ?(\w+)?/i,
callback: function(name) {
if(ranked) {
log("Disabled in ranked games.");
}
else if(ej.settings & 0x800000) {
if(name) {
autobomb=name;
ej.settings|=AUBOMB;
log("Passing the bomb to "+name);
}
else {
autobomb="";
ej.settings^=AUBOMB;
log(ej.settings & AUBOMB ?
"You're now an anarchist!" :
"You're now a tree."
);
}
}
}
},
{
name: "[Naughty] Fake Sysmessage",
regex: /^f(s)? ?(\w+)? ?(.+)?/i,
callback: function(send, id, input) {
if(ranked) {
log("Disabled in ranked games.");
}
else /* if(ej.settings & 0x800000) */ {
var output=this.messages[id];
if(!output) {
log("System messages: "+Object.keys(this.messages).join(", "));
}
else {
var i=0, args=output.default;
if(input) {
args=[];
while(args.length < output.default.length) {
if(input) {
if(args.length===output.default.length-1) {
args.push(input);
}
else {
i=input.search(/ |$/);
args.push(input.substring(0, i));
input=input.substring(i+1);
}
}
else {
args.push(output.default[args.length]);
}
}
}
if(send) {
sock.chat(sformat(output.msg, args));
}
else {
log(sformat(output.msg, args));
}
}
}
},
messages: {
angel: {
msg: "You feel an overwhelming, unconditional love for $1. "
+"You feel you must protect $1 with your life.",
default: [user]
},
auto: {
msg: "There might be an autocrat among you...",
default: []
},
bleed: {
msg: "You start to bleed...",
default: []
},
bomb: {
msg: "$1 rushes at $2 and reveals a bomb!",
default: [user, user]
},
carol: {
msg: "You see a merry Caroler outside your house! "
+"They sing you a Carol about $1, $2, $3. At least one of which is the Mafia!",
default: [user, user, user]
},
chef: {
msg: "You find yourself in a dimly lit banquet! "
+"You sense the presence of a masked guest. The guest appears to be a $1.",
default: ["ninja"]
},
cm: {
msg: "You glance at your watch. The time is now $1 o'clock.",
default: ["11"]
},
cmlife: {
msg: "Your watch whispers to you. You have one extra life.",
default: []
},
confess: {
msg: "At the confessional tonight, a $1 had visited you to confess their sins.",
default: ["survivor"]
},
cop: {
msg: "After investigations, you suspect that $1 is sided with the $2.",
default: [user, "mafia"]
},
cry: {
msg: "Someone cries out | $1",
default: [""]
},
det: {
msg: "Through your detective work, you learned that $1 is a $2!",
default: [user, "ninja"]
},
disc: {
msg: "You discover that $1 is the $2!",
default: [user, "interceptor"]
},
dream: {
msg: "You had a dream... where at least one of $1, $2, $3 is a mafia...",
default: [user, user, user]
},
fire: {
msg: "Somebody threw a match into the crowd! "+
"$1 suddenly lights on fire and burns to a crisp!",
default: [user]
},
firefail: {
msg: "Somebody threw a match into the crowd!",
default: []
},
guise: {
msg: "You are now disguised as $1.",
default: [user]
},
guised: {
msg: "$1 has stolen your identity!",
default: [user]
},
gun: {
msg: "You hear a gunshot!",
default: []
},
gunfail: {
msg: "$1 reveals a gun! The gun backfires!",
default: [user]
},
gunhit: {
msg: "$1 reveals a gun and shoots $2!",
default: [user, user]
},
hit: {
msg: "A bullet hits your vest! You cannot survive another hit!",
default: []
},
invis: {
msg: "Someone whispers $1",
default: [""]
},
item: {
msg: "You received a $1!",
default: ["key"]
},
jail: {
msg: "You have been blindfolded and sent to jail!",
default: []
},
jan: {
msg: "While cleaning up the mess, you learned that $1 was a $2.",
default: [user, "cop"]
},
janday: {
msg: "$1 is missing!",
default: [user]
},
journ: {
msg: "You received all reports that $1 received: ($2).",
default: [user, ""]
},
learn: {
msg: "You learn that $1 is a $2",
default: [user, "cop"]
},
lm: {
msg: "A loud voice was heard during the night: \"Curses! $1 woke me from my slumber!\"",
default: [user]
},
lonely: {
msg: "You spent a silent and lonely night at church. No one came to visit you.",
default: []
},
love: {
msg: "During the night, you fall in love with $1 after a romantic conversation!",
default: [user]
},
lynch: {
msg: "You feel very irritated by $1.",
default: [user]
},
matin: {
msg: "Penguins be matin'",
default: []
},
message: {
msg: "You received a message: $1",
default: [""]
},
mfail: {
msg: "No matter how much you worked your magic, $1 and $2 refuses to fall in love!",
default: [user, user]
},
mlove: {
msg: "You cast a Christmas spell on $1 and $2... they are now in love!",
default: [user, user]
},
mm: {
msg: "There might be a mastermind among you...",
default: []
},
mort: {
msg: "You learned that $1 is a $2!",
default: [user, "villager"]
},
party: {
msg: "You find yourself at a vibrant party!",
default: []
},
pengi: {
msg: "During the night a fluffy penguin visits you and tells you that "+
"$1 is carrying a $2.",
default: [user, user]
},
pengno: {
msg: "During the night a fluffy penguin visits you and tells you that "+
"$1 has taken no action over the course of the night.",
default: [user]
},
poison: {
msg: "You feel sick, as though you had been poisoned!",
default: []
},
pop: {
msg: "$1 feels immensely frustrated!",
default: [user]
},
psy: {
msg: "You read $1's mind... they are thinking $2 thoughts.",
default: [user, "evil"]
},
psyfail: {
msg: "You tried to read $1's mind, but something distracted you.",
default: [user]
},
pvis: {
msg: "During the night a fluffy penguin visits you and tells you that "+
"$1 visited $2.",
default: [user, "no one"]
},
pvisd: {
msg: "During the night a fluffy penguin visits you and tells you that "+
"$1 was visited by $2.",
default: [user, "no one"]
},
santa: {
msg: "After going out on your sleigh, you find that $1 is $2!",
default: [user, "neither naughty nor nice"]
},
snoop: {
msg: "After some snooping, you find out $1 is carrying $3 $2.",
default: [user, "gun", "1"]
},
snoop0: {
msg: "After some snooping, you find out $1 is not carrying any items..",
default: [user]
},
stalk: {
msg: "Through stalking, you learned that $1 is a $2!",
default: [user, "journalist"]
},
thulu: {
msg: "You were witness to an unimaginable evil... you cannot forget... "
+"your mind descends into eternal hell.",
default: []
},
track: {
msg: "You followed $1 throughout the night. $1 visited $2.",
default: [user, "no one"]
},
tree: {
msg: "You became a tree!",
default: []
},
trust: {
msg: "You had a dream... you learned you can trust $1...",
default: [user]
},
virgin: {
msg: "The virgin has been sacrified!",
default: []
},
voodoo: {
msg: "$1 suddenly feels a chill and falls to the ground!",
default: [user]
},
watch: {
msg: "You watched $1 throughout the night. $2 has visited $1.",
default: [user, "No one"]
},
will: {
msg: "You read the will of $1, it reads: $2",
default: [user, ""]
},
ww: {
msg: "You devoured a human and feel very powerful... "
+"as though you are immortal for the day!",
default: []
}
}
}
];
// lobby commands
ej.llobby=[
lcopy.sc,
{
name: "About",
short: "/help",
regex: /^(?:info|help|about) ?(.+)?/i,
callback: function(topic) {
if(this.topics[topic]) {
log(this.topics[topic]);
}
else {
log("You can /join games and toggle /fmt on or off (/help fmt for more info)");
}
},
topics: {
"fmt": "/fmt on enables chat formatting like displaying images for messages beginning "
+"with $img ($img [url])"
}
},
lcopy.eval,
lcopy.clear,
lcopy.emotes,
lcopy.icons,
lcopy.fmt,
lcopy.say,
lcopy.join,
lcopy.host,
lcopy.games,
lcopy.pm
];
// this is a sin
ej.lbot=[
{
name: "Scriptcheck",
short: "@bot sc",
regex: /^sc|^scriptcheck/,
callback: function(data) {
sock.chat(ej.name+ej.vstring, data.user);
}
},
{
name: "Echo",
regex: /^(?:echo|say) (.+)/,
callback: function(data, what) {
if(ej.settings & 0x400000) {
sock.chat(what);
}
}
},
{
name: "Do Command",
regex: /^(eval .+)/,
callback: function(data, what) {
if(ej.settings & 0x400000) {
ej.run(what, ej.lchat);
}
}
},
{
name: "Help",
short: "@bot help",
regex: /^(help|how)/i,
callback: function(data, $1) {
sock.chat(arand($1==="help" ? this.response1 : this.response2), data.user);
},
response1: [
"i am jyshuhui :D always here to help",
"i am prepared to give what little i have to offer what little assistance i can"
],
response2: [
"i would love to, but i don't know...", "i have too little confidence in my abilities to help you",
"after consulting my mind, i recommend that you ask me to self delete"
]
},
{
name: "Advice",
short: "@bot who should i...",
regex: /who sho?ul?d i/i,
callback: function(data) {
sock.chat(sformat(arand(this.responses), [
arand(meetd.members || Object.keys(users))
]), data.user);
},
responses: [
"given current circumstances, $1 would be the most optimal choice", "the oracle of delphi says maybe $1...", "nobody", "me :3", "the person in my mind isn't in this game"
]
},
{
name: "Roll dice",
short: "@bot roll dice or @bot d20",
regex: /\bdice|\bd(\d+)/i,
callback: function(data, d) {
sock.chat(sformat(arand(this.responses), [
Math.floor(Math.random()*(+d || 20)), +d || 20
]), data.user);
},
responses: [
"the bottle spun around like a merry-go-round and eventually landed on $1", "the wind says $1",
"the jar contains $1 double chocolate chip cookies",
"jesus entered my dreams and whispered me the answer... $1",
"i am trying to figure out how to pick up this dodecahedral die",
"i rolled a $2-sided die and it said $1"
]
},
{
name: "Roulette",
short: "@bot roulette",
regex: /roul+et+e/i,
callback: function(data) {
if(roulette) {
var user=data.user,
data=this;
sock.chat(roulette+" chambers remain. You align the gun barrel to the middle of your cranium", user);
setTimeout(function() {
if(Math.random()*roulette>1) {
roulette--;
sock.chat(sformat("$1, $2,", [
arand(data.message1),
arand(data.message2)
]), user);
sock.chat("and you stay alive to celebrate my birthday next year!");
}
else {
roulette=0;
sock.chat(sformat("$1, $2,", [
arand(data.message1),
arand(data.message2),
]), user);
sock.chat(arand(data.message3));
sock.vote(user, "gun");
}
}, 3000);
}
},
message1: [
"oh no", "sigh", "get ready", "say your prayers"
],
message2: [
"shut your eyes and pull the trigger like a man yanks to get his zipper unstuck",
"let it rip through your skin and carve a gunshot wound", "gently tug at it like how your mama rocked your cradle"
],
message3: [
"die instantly and become a wandering spirit", "kiss the bullet and face death in a romantic but painful embrace", "meet Jesus and discover eternal peace",
"die internally and have your organs deteriorate to such an extent where terminally ill patients refuse them"
]
},
{
name: "Bomb fight",
short: "@bot fight me",
regex: /fig?h?te? ?me/i,
callback: function(data) {
autobomb=data.user;
sock.chat("/me throws a punch that shatters your mandible", data.user);
}
},
{
name: "Marry me",
short: "@bot marry me",
regex: /marry /i,
callback: function(data) {
sock.chat("i vehemently refuse... ", data.user);
}
},
{
name: "Fuck...",
short: "@bot fuck you",
regex: /fuck? /i,
callback: function(data) {
sock.chat("where is my epinephrine pen?? i am allergic to invectives", data.user);
}
},
{
name: "Hug me",
short: "@bot hug me",
regex: /^hug me/i,
callback: function(data) {
sock.chat("/me awww <3 i love hugging", data.user);
}
},
{
name: "Hug...",
short: "@bot hug",
regex: /^hug/i,
callback: function(data) {
sock.chat("/me embraces herself", data.user);
}
},
{
name: "Obey",
regex: /^be? my \w|obey me/i,
callback: function(data) {
if(!master) {
master=data.user;
sock.chat("obey me", data.user);
}
else if (data.user===master) {
sock.chat("you are already my master :3", data.user);
}
else {
sock.chat("my heart, mind and soul belong to "+master, data.user);
}
}
},
{
name: "Be free",
regex: /^be? free/i,
callback: function(data) {
if(data.user===master) {
master="";
sock.chat("i need to find a new master...", data.user);
}
}
},
{
name: "Roll over",
regex: /^roll/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i don't want to be a burrito today", data.user);
}
},
responses: [
"/me rolls over like a sushi",
"/me rolls over for senpai, revealing her sexy back",
"/me doesn't feel like it, so she just tilts her body 14 degrees clockwise"
]
},
{
name: "Bow",
regex: /^bow/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i don't want to be your ribbon", data.user);
}
},
responses: [
"/me bows politely, like the most subservient EM-er",
"/me bends down 90 degrees, in utmost respect for her master",
"/me tries to execute the perfect curtsey, but misses the little pedestal, stumbles and falls down"
]
},
{
name: "Beg",
regex: /^beg/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i got my dignity and enough money", data.user);
}
},
responses: [
"can i has some money?",
"/me dresses in rags and sits in a corner, hoping someone will take pity on her and throw some old coins over",
"/me cries and asks for cash, but realises that everyone thinks she's a crybaby"
]
},
{
name: "Jump",
regex: /^jump/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i can't jump because i'm not a jumper... i'm only wearing one", data.user);
}
},
responses: [
"/me jumps up a metre, does a 360 degree flip and gracefully lands on her toes, before stumbling forward after an ant tipped her balance",
"/me hops up and down many times and wonders if you can observe her flabby limbs jingling in the air",
"/me attempts to jump but ends up fainting due to malnourishment"
]
},
{
name: "Slap",
regex: /^slap/i,
callback: function(data) {
if(data.user===master) {
sock.chat("/me lifts her hand and opens it wide to deliver the hardest slap ever, but sees a rat and cowers in fear");
}
else {
sock.chat("a servant is not entitled to such a privileged action", data.user);
}
},
},
{
name: "Kick",
regex: /^kick/i,
callback: function(data) {
if(data.user===master) {
sock.chat("/me lifts her foot but then faints because she hasn't eaten in a long time");
}
else {
sock.chat("should i use my left hand or right hand for that?", data.user);
}
},
},
{
name: "Buy me",
regex: /^buy/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i have no money today... my mama told me to stay home anyway", data.user);
}
},
responses: [
"/me sprints to the grocery store to spend her last few coins getting a bottle of mineral water",
"/me casually ambles to the bookstore to buy Hitler's autobiography",
"/me asks for a protective rubber tubing but the shopkeeper ends up staring at the underage girl",
"/me goes into the store to ask for it, but realises that she is way too underpaid to afford it"
]
},
{
name: "Go and...",
regex: /^go/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i'm sticking by my master no matter what!", data.user);
}
},
responses: [
"/me stares at you for 10 minutes, wondering what you were saying",
"/me takes a knife and prepares to kill herself, but finds out the knife is just a toy",
"/me nods but does not move"
]
},
{
name: "Make me",
regex: /^make |cook/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("i have no time, no energy, no money... nothing in my ability to do that for you", data.user);
}
},
responses: [
"/me drags her weak body to the kitchen to make a tasty sandwich",
"/me whips out all the cooking equipment and magically prepares delicious dumpling noodles",
"/me boils a cup of noodles and drizzles tomato sauce over, serving you a jumbo-sized pasta",
"/me throws the leftovers into the microwave, heats things up, and drops the plate of food in front of your face"
]
},
{
name: "Eat",
regex: /^eat/i,
callback: function(data) {
if(data.user===master) {
sock.chat(arand(this.responses));
}
else {
sock.chat("a slave is forbidden to consume any calories...", data.user);
}
},
responses: [
"/me takes a nibble of stale bread",
"/me refuses, because she has long forgotten what hunger feels like",
"/me devours the speck of food on her plate",
]
},
{
name: "Vote",
regex: /^vote (\w+)/i,
callback: function(data, who) {
if(data.user===master) {
sock.vote(who, data.meet);
sock.chat("relax, i won't vegetate because i have autovote turned on...", data.user);
}
else {
sock.chat("i don't want to... besides, i have autovote on so i won't vegetate", data.user);
}
}
},
{
name: "Please NL",
regex: /^nl| vote/i,
callback: function(data, who) {
sock.vote("*");
}
},
{
name: "Shoot",
regex: /^shoot (\w+)/i,
callback: function(data, who) {
if(data.user===master) {
sock.vote(who, "gun");
sock.chat("it was a tough dilemma because i am against shooting");
}
}
},
{
name: "Claim",
regex: /^claim/i,
callback: function(data) {
if(data.user===master) {
sock.chat("Bomb here to offer my everything to you...", {
whisper: true,
target: data.user
});
//u(user).role+
}
}
}
];
// utility
function u(name) {
return users[name || user] || u.make({
id: 0,
username: name || user
});
};
u.make=function(data) {
data.name=data.username || data.user;
data.emjack=null;
data.role=null;
data.meet=meetd.meet;
data.mafia=false;
data.dead=false;
data.muted=false;
data.kucode=1;
data.kuclock=Infinity;
users[data.name]=data;
if(data.emotes) {
data.emotes=JSON.parse(data.emotes);
}
return data;
};
function log(message, classes) {
var node=document.createElement("div");
node.className=classes ? "log emjack "+classes : "log emjack";
typeof message==="string" ?
node.textContent=message :
node.appendChild(message);
if(chat.scrollTop>=chat.scrollHeight-chat.clientHeight) {
requestAnimationFrame(function() {
chat.scrollTop=chat.scrollHeight;
});
}
if(type==="mafia") {
chat.appendChild(node);
}
else {
chat.insertBefore(node, chat.lastChild);
}
};
function request(method, url, callback) {
var req=new XMLHttpRequest();
req.open(method, url, true);
req.onreadystatechange=function(event) {
if(this.readyState===4) {
callback.call(this, this.responseText);
}
};
req.send();
};
function arand(array) {
return array[Math.floor(Math.random()*array.length)];
};
function rchar(x, y) {
return String.fromCharCode(
x+Math.floor(Math.random()*(y-x))
);
};
function sformat(string, data) {
return string.replace(/\$(\d+)/g, function(match, i) {
return data[i-1];
});
};
// keep chat
if(type==="mafia") {
document.querySelector("#speak_container")
.style.cssText="display: initial !important";
}
// townie input
var chat=document.getElementById(type==="mafia" ? "window" : "window_i"),
typebox=document.getElementById(type==="mafia" ? "typebox" : "chatbar");
typebox.addEventListener("keydown", function(event) {
if(event.which===13 && this.value[0]==="/") {
if(type==="mafia") {
ej.run(this.value.substring(1), ej.lchat);
this.value="";
}
else {
ej.run(this.value.substring(1), ej.llobby);
this.value="";
}
}
});
if(type==="mafia") {
var notebox=document.querySelector("textarea.notes");
notebox.addEventListener("focus", function(event) {
if(ej.settings & UNOTES && !ranked) {
this.value=notes[document.querySelector(".user_header > h2").textContent];
}
});
notebox.addEventListener("keyup", function(event) {
if(ej.settings & UNOTES && !ranked) {
notes[document.querySelector(".user_header > h2").textContent]=this.value;
}
});
}
// clickables
if(window.vocabs) {
vocabs.push("https?://\\S+");
}
window.addEventListener("click", function(event) {
var classList=event.target.classList;
if(classList.contains("msg")) {
if(ej.settings & MSGMRK) {
var mark=keys & K_SHIFT ? "ej_mark_alt" : "ej_mark";
if(classList.contains(mark)) {
classList.remove(mark);
}
else {
classList.add(mark);
classList.remove(keys & K_SHIFT ? "ej_mark" : "ej_mark_alt");
}
}
}
else if(classList.contains("meet_username")) {
ej.run("vote "+(
event.target.textContent==="You" ?
user : event.target.textContent
), ej.lchat);
}
else if(classList.contains("acronym")) {
if(/https?:\/\//i.test(event.target.textContent)) {
window.open(event.target.textContent, "_blank");
event.stopPropagation();
}
}
}, true);
// clean up
var last_error=null;
window.addEventListener("error", function(event) {
var message=event.error.message;
if(message!==last_error) {
log("You've got error!", "bold");
log(last_error=message);
}
});
window.addEventListener("beforeunload", function(event) {
localStorage.ejs=ej.settings;
if(ej.settings & UNOTES && !ranked) {
localStorage.notes=JSON.stringify(notes);
}
if(window.setup_id) {
localStorage.ejsid=setup_id;
}
});
window.addEventListener("keyup", function(event) {
if(event.which===16) {
keys&=~K_SHIFT;
}
else if(event.which===192) {
keys&=~K_DEBUG;
}
});
if(~navigator.userAgent.indexOf("Windows")) {
window.addEventListener("keydown", function(event) {
if(event.ctrlKey) {
if(event.which===66) {
sock.cmd("option", {
field: "fastgame"
});
sock.cmd("option", {
field: "nospectate"
});
}
else if(event.which===81) {
ej.run("fq "+user+" "+typebox.value, ej.lchat);
typebox.value="";
}
}
else if(event.target.value===undefined) {
if(event.which===16) {
keys|=K_SHIFT;
}
else if(event.which===192) {
keys|=K_DEBUG;
}
if(~keys & K_DEBUG) {
typebox.focus();
}
}
});
}
}
// add node
function inject(parent, tag, content) {
var node=document.createElement(tag);
node.appendChild(
document.createTextNode(content)
);
return parent.appendChild(node);
};
// jack in
inject(document.head, "style", "\
.log {\
color: #bb4444;\
}\
.notop {\
margin-top: 0 !important\
}\
.ej_mark {\
background-color: rgba(250, 50, 250, 0.5);\
}\
.ej_mark_alt {\
background-color: rgba(250, 150, 0, 0.5);\
}\
.ej_highlight {\
background-color: rgba(255, 255, 0, 0.5);\
}\
.ej_img * {\
max-width: 100%;\
}\
.meet_username {\
cursor: pointer;\
}\
#lobbychat #window {\
width: 100% !important;\
}\
#lobbychat #window_i {\
width: auto !important;\
}\
").type="text/css";
inject(document.head, "style", "\
#game_container.graphi .cmds {\
position: relative;\
z-index: 1;\
height: auto;\
width: 300px !important;\
padding: 8px;\
background: rgba(255,255,255,0.8);\
}\
#game_container.graphi .userbox {\
width: auto !important;\
}\
#game_container.graphi .canvas {\
float: right;\
max-width: 40%;\
margin-right: -256px;\
overflow: hidden;\
}\
#game_container.graphi #window {\
display: block !important\
}\
#game_container.graphi #system-messages {\
width: 100%;\
font-size: .8em;\
background: rgba(255,255,255,0.8);\
}\
#game_container.graphi #canvas-player-area {\
position: relative;\
z-index: 1;\
left: 0 !important;\
max-width: 100%;\
}\
").type="text/css";
setTimeout(function() {
inject(document.body, "script", "("+emjack.toString()+")()")
.type="text/javascript";
document.body.addEventListener("contextmenu", function(event) {
event.stopPropagation();
}, true);
});
@pikulet
Copy link
Author

pikulet commented Jan 22, 2021

DEPRECATED DO NOT USE.

@pikulet
Copy link
Author

pikulet commented Jan 22, 2021

PLEASE REFER TO https://epicmafia.com/topic/77055 FOR ORIGINAL AUTHOR.

ORIGINAL FORK https://greasyfork.org/en/scripts/4503-emjack/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment