// ==UserScript== // @name Miracle Scripts // @namespace Miracle Scripts // @version 5.7.0 // @description Best Agma.io script with tons of features // @author Samira, HutDude and others // @license MIT // @icon https://abload.de/img/mh3k8o.png // @match *://agma.io/* // @grant none // @downloadURL none // ==/UserScript== (function() { 'use strict'; window.miracleScripts = { // News icon: //news: 'Miracle Scripts Valentine\'s Day Giveaway with gold membership, coins and bots!', news: 'Update: Multi feed got repaired.', // Player profiles profiles: { 'LusualYT' : { nickNameColor: '#000000', nickNameStrokeColor: '#000000', nickNameStrokeWidth: 2, }, //'inaaa' : { // nickNameStrokeColor: 'deeppink', //}, }, banned: [], // Source: http://stackoverflow.com/questions/1772179/get-character-value-from-keycode-in-javascript-then-trim#answer-23377822 keyboardMap: [ '', // [0] '', // [1] '', // [2] 'CANCEL', // [3] '', // [4] '', // [5] 'HELP', // [6] '', // [7] 'BACK_SPACE', // [8] 'TAB', // [9] '', // [10] '', // [11] 'CLEAR', // [12] 'ENTER', // [13] 'ENTER_SPECIAL', // [14] '', // [15] 'SHIFT', // [16] 'CONTROL', // [17] 'ALT', // [18] 'PAUSE', // [19] 'CAPS_LOCK', // [20] 'KANA', // [21] 'EISU', // [22] 'JUNJA', // [23] 'FINAL', // [24] 'HANJA', // [25] '', // [26] 'ESCAPE', // [27] 'CONVERT', // [28] 'NONCONVERT', // [29] 'ACCEPT', // [30] 'MODECHANGE', // [31] 'SPACE', // [32] 'PAGE_UP', // [33] 'PAGE_DOWN', // [34] 'END', // [35] 'HOME', // [36] 'LEFT', // [37] 'UP', // [38] 'RIGHT', // [39] 'DOWN', // [40] 'SELECT', // [41] 'PRINT', // [42] 'EXECUTE', // [43] 'PRINTSCREEN', // [44] 'INSERT', // [45] 'DELETE', // [46] '', // [47] '0', // [48] '1', // [49] '2', // [50] '3', // [51] '4', // [52] '5', // [53] '6', // [54] '7', // [55] '8', // [56] '9', // [57] 'COLON', // [58] 'SEMICOLON', // [59] 'LESS_THAN', // [60] 'EQUALS', // [61] 'GREATER_THAN', // [62] 'QUESTION_MARK', // [63] 'AT', // [64] 'A', // [65] 'B', // [66] 'C', // [67] 'D', // [68] 'E', // [69] 'F', // [70] 'G', // [71] 'H', // [72] 'I', // [73] 'J', // [74] 'K', // [75] 'L', // [76] 'M', // [77] 'N', // [78] 'O', // [79] 'P', // [80] 'Q', // [81] 'R', // [82] 'S', // [83] 'T', // [84] 'U', // [85] 'V', // [86] 'W', // [87] 'X', // [88] 'Y', // [89] 'Z', // [90] 'OS_KEY', // [91] Windows Key (Windows) or Command Key (Mac) '', // [92] 'CONTEXT_MENU', // [93] '', // [94] 'SLEEP', // [95] 'NUMPAD0', // [96] 'NUMPAD1', // [97] 'NUMPAD2', // [98] 'NUMPAD3', // [99] 'NUMPAD4', // [100] 'NUMPAD5', // [101] 'NUMPAD6', // [102] 'NUMPAD7', // [103] 'NUMPAD8', // [104] 'NUMPAD9', // [105] 'MULTIPLY', // [106] 'ADD', // [107] 'SEPARATOR', // [108] 'SUBTRACT', // [109] 'DECIMAL', // [110] 'DIVIDE', // [111] 'F1', // [112] 'F2', // [113] 'F3', // [114] 'F4', // [115] 'F5', // [116] 'F6', // [117] 'F7', // [118] 'F8', // [119] 'F9', // [120] 'F10', // [121] 'F11', // [122] 'F12', // [123] 'F13', // [124] 'F14', // [125] 'F15', // [126] 'F16', // [127] 'F17', // [128] 'F18', // [129] 'F19', // [130] 'F20', // [131] 'F21', // [132] 'F22', // [133] 'F23', // [134] 'F24', // [135] '', // [136] '', // [137] '', // [138] '', // [139] '', // [140] '', // [141] '', // [142] '', // [143] 'NUM_LOCK', // [144] 'SCROLL_LOCK', // [145] 'WIN_OEM_FJ_JISHO', // [146] 'WIN_OEM_FJ_MASSHOU', // [147] 'WIN_OEM_FJ_TOUROKU', // [148] 'WIN_OEM_FJ_LOYA', // [149] 'WIN_OEM_FJ_ROYA', // [150] '', // [151] '', // [152] '', // [153] '', // [154] '', // [155] '', // [156] '', // [157] '', // [158] '', // [159] 'CIRCUMFLEX', // [160] 'EXCLAMATION', // [161] 'DOUBLE_QUOTE', // [162] 'HASH', // [163] 'DOLLAR', // [164] 'PERCENT', // [165] 'AMPERSAND', // [166] 'UNDERSCORE', // [167] 'OPEN_PAREN', // [168] 'CLOSE_PAREN', // [169] 'ASTERISK', // [170] 'PLUS', // [171] 'PIPE', // [172] 'HYPHEN_MINUS', // [173] 'OPEN_CURLY_BRACKET', // [174] 'CLOSE_CURLY_BRACKET', // [175] 'TILDE', // [176] '', // [177] '', // [178] '', // [179] '', // [180] 'VOLUME_MUTE', // [181] 'VOLUME_DOWN', // [182] 'VOLUME_UP', // [183] '', // [184] '', // [185] 'SEMICOLON', // [186] 'EQUALS', // [187] 'COMMA', // [188] 'MINUS', // [189] 'PERIOD', // [190] 'SLASH', // [191] 'BACK_QUOTE', // [192] '', // [193] '', // [194] '', // [195] '', // [196] '', // [197] '', // [198] '', // [199] '', // [200] '', // [201] '', // [202] '', // [203] '', // [204] '', // [205] '', // [206] '', // [207] '', // [208] '', // [209] '', // [210] '', // [211] '', // [212] '', // [213] '', // [214] '', // [215] '', // [216] '', // [217] '', // [218] 'OPEN_BRACKET', // [219] 'BACK_SLASH', // [220] 'CLOSE_BRACKET', // [221] 'QUOTE', // [222] '', // [223] 'META', // [224] 'ALTGR', // [225] '', // [226] 'WIN_ICO_HELP', // [227] 'WIN_ICO_00', // [228] '', // [229] 'WIN_ICO_CLEAR', // [230] '', // [231] '', // [232] 'WIN_OEM_RESET', // [233] 'WIN_OEM_JUMP', // [234] 'WIN_OEM_PA1', // [235] 'WIN_OEM_PA2', // [236] 'WIN_OEM_PA3', // [237] 'WIN_OEM_WSCTRL', // [238] 'WIN_OEM_CUSEL', // [239] 'WIN_OEM_ATTN', // [240] 'WIN_OEM_FINISH', // [241] 'WIN_OEM_COPY', // [242] 'WIN_OEM_AUTO', // [243] 'WIN_OEM_ENLW', // [244] 'WIN_OEM_BACKTAB', // [245] 'ATTN', // [246] 'CRSEL', // [247] 'EXSEL', // [248] 'EREOF', // [249] 'PLAY', // [250] 'ZOOM', // [251] '', // [252] 'PA1', // [253] 'WIN_OEM_CLEAR', // [254] '' // [255] ], // List of bad words / strings that will be removed from chat messages send with the /say command. // NOTE: Do not sort this list in alphabetical order! Some words have to be before others. badWords: [ 'https://', 'http://', 'www.', '. c o m', '.c o m', '.c0m', '.com', '.io', 'facebook', 'face book', 'cellcraft', 'cell craft', 'gay', 'ga\.y', 'cocksucker', 'sucker', 'sucka', 'suck my', 'blow job', 'blowjob', 'blow my', 'mofo', 'mother fucker', 'motherfucker', 'motherfucka', 'mothafucka', 'fucker', 'facker', 'fuck you', 'fuk you', 'fck you', 'fk you', 'fk u', 'fk of', 'fked', 'fucking', 'fucing', 'fuck', 'fรผck', 'fack', 'fukk', 'f\.uck', 'f u c k', 'fkin', 'smegma', 'semen', 'sperm', 'piece of shit', 'shitting', 'shite', 'shit', 'rectum', 'butthole', 'butt ', // butter... 'fatass', 'lardass', 'your ass', 'asshole', 'ass hole', 'ass-hole', 'arsehole', 'anal ', // analyze... 'pissing', 'pisser', 'piss', 'clitoris', 'clit', 'vulva', 'vagina', 'pussy', 'pu$$y', 'pussies', 'penis', 'dick', 'cock', 'scrotum', 'boobs', 'tits', 'titties', 'nipple', 'whore', 'prostitute', ' hoe', // shoes... 'stripper', 'bitch', 'biitch', 'biatch', 'bish ', // bishop... 'bich', 'slut', 'bastard', 'cunt', 'twat', 'suck', 'pornography', 'pornos', 'porn', 'por.n', 'p0rn', 'pron', 'had sex', 'sex with', 'sex ', // "sexy" is allowed 'blowjob', 'fisting', 'gangbang', 'masturbating', 'masturbate', 'deep throat', 'bdsm', 'dildo', 'pedo', 'retarded', 'retard', 'wanker', 'faggot', 'dumbo', 'loser', 'moron', 'idiota', // Spanish 'idiot', 'dimwit', 'stupid', 'dumb ass', 'dumb-ass', 'dumbass', 'massacre', 'nazi', 'adolf', 'hitler', 'get cancer', 'get aids', 'autistic', 'degenerated', 'punch you', 'slap you', 'kick you', 'nigger', 'nigg3r', 'n1gger', 'nigga', 'niga', 'viagra', 'weed', 'cocaine', 'puto', 'hijo de puta', 'puta', 'perra', 'zorra', 'culo', 'tonto', 'pendejo', 'maricon', 'mierda', 'merde', 'arschloch', 'arsch', 'wichser', 'hurensohn', 'huso', 'hure', 'fick', 'scheiรŸ', 'scheiss', 'nik mok', 'kurwa', 'kurva', 'cyka blyat', 'suka bljad' ], watermark: 'โ€‡', wearables: { 1: 'Santa Hat (Old)', 2: 'Wizard Hat', 3: 'Wooden Shield', 4: 'Red Partyhat (Big)', 5: 'Red Partyhat', 6: 'Blue Partyhat', 7: 'Green Partyhat', 8: 'Yellow Partyhat', 9: 'Green Eyes', 10: 'Minion Eyes', 11: 'Mustache & Glasses', 12: 'Cartoon Arms & Legs', 13: 'Evil Horns', 14: 'Hairs (Female)', 15: 'Red Hair', 16: 'Spikes', 17: 'Spine Ball', 18: 'Thug Life Glasses', 19: 'Thug Life Smoke', 20: 'Thug Life Cap', 21: 'Axe', 22: 'Sword', 23: 'Witch Hat (Purple)', 24: 'Viking Helmet', 25: 'Feather Hat', 26: 'Officer Hat', 27: 'Yellow Glasses', 28: 'Blue Fedora', 29: 'Red Cap', 30: 'Emperor Crown (Old)', 31: 'Emperor Crown', 32: 'Emperor Sceptre', 33: 'Steampunk', 34: 'Goggles', 35: 'Jester Hat', 36: 'Graduation Hat', 37: 'Angel Halo', 38: 'Angel Wings', 39: 'Pirate Eye Patch', 40: 'Pirate Hat', 41: 'Antlers', 42: 'Ring of Fire', 43: 'Sora\'s Hat', 44: 'Moderator Hat', 45: 'Admin Hat', 46: 'Witch Hat', 47: 'Scythe', 48: 'Bones', 49: 'Black Crown Friday', 50: 'Santa Hat', 51: 'Evil Wings', 52: 'Birthday Candles', 53: 'Barbed Wire', 54: 'Sheriff Star', 55: 'YouTuber Hat', 56: 'Admin Star', 57: 'Face Mask', 58: 'Cute Eyes', 59: 'Cute Eyes (With Tongue, Green)', 60: 'Cute Eyes (With Tongue)', 61: 'Leafy Hat', 62: 'Ears', 63: 'Elf hat', }, // Don't remove the spaces, they are used as separators! Source: https://emojiterra.com/de/liste/ emojis: '๐Ÿ˜€ ๐Ÿ˜ƒ ๐Ÿ˜„ ๐Ÿ˜ ๐Ÿ˜† ๐Ÿ˜… ๐Ÿ˜‚ ๐Ÿ˜‰ ๐Ÿ˜Š ๐Ÿ˜‡ ๐Ÿ˜ ๐Ÿ˜˜ ๐Ÿ˜— โ˜บ๏ธ ๐Ÿ˜š ๐Ÿ˜™ ๐Ÿ˜‹ ๐Ÿ˜› ๐Ÿ˜œ ๐Ÿ˜ ๐Ÿ˜ ๐Ÿ˜‘ ๐Ÿ˜ถ ๐Ÿ˜ ๐Ÿ˜’ ๐Ÿ˜ฌ ๐Ÿ˜Œ ๐Ÿ˜” ๐Ÿ˜ช ๐Ÿ˜ด ๐Ÿ˜ท ๐Ÿ˜ต ๐Ÿ˜Ž ๐Ÿ˜• ๐Ÿ˜Ÿ ๐Ÿ˜ฎ ๐Ÿ˜ฏ ๐Ÿ˜ฒ ๐Ÿ˜ณ ๐Ÿ˜ฆ ๐Ÿ˜ง ๐Ÿ˜จ ๐Ÿ˜ฐ ๐Ÿ˜ฅ ๐Ÿ˜ข ๐Ÿ˜ญ ๐Ÿ˜ฑ ๐Ÿ˜– ๐Ÿ˜ฃ ๐Ÿ˜ž ๐Ÿ˜“ ๐Ÿ˜ฉ ๐Ÿ˜ซ ๐Ÿ˜ค ๐Ÿ˜ก ๐Ÿ˜  ๐Ÿ˜ˆ ๐Ÿ‘ฟ ๐Ÿ’€ ๐Ÿ’ฉ ๐Ÿ‘น ๐Ÿ‘บ ๐Ÿ‘ป ๐Ÿ‘ฝ ๐Ÿ‘พ ๐Ÿ˜บ ๐Ÿ˜ธ ๐Ÿ˜น ๐Ÿ˜ป ๐Ÿ˜ผ ๐Ÿ˜ฝ ๐Ÿ™€ ๐Ÿ˜ฟ ๐Ÿ˜พ ๐Ÿ™ˆ ๐Ÿ™‰ ๐Ÿ™Š ๐Ÿ’‹ ๐Ÿ’Œ ๐Ÿ’˜ ๐Ÿ’ ๐Ÿ’– ๐Ÿ’— ๐Ÿ’“ ๐Ÿ’ž ๐Ÿ’• ๐Ÿ’Ÿ ๐Ÿ’” โค๏ธ ๐Ÿ’› ๐Ÿ’š ๐Ÿ’™ ๐Ÿ’œ ๐Ÿ’ฏ ๐Ÿ’ข ๐Ÿ’ฅ ๐Ÿ’ซ ๐Ÿ’ฆ ๐Ÿ’จ ๐Ÿ’ฃ ๐Ÿ’ฌ ๐Ÿ’ญ ๐Ÿ’ค ๐Ÿ‘‹ โœ‹ ๐Ÿ‘Œ โœŒ๏ธ ๐Ÿ‘ˆ ๐Ÿ‘‰ ๐Ÿ‘† ๐Ÿ‘‡ โ˜๏ธ ๐Ÿ‘ ๐Ÿ‘Ž โœŠ ๐Ÿ‘Š ๐Ÿ‘ ๐Ÿ™Œ ๐Ÿ‘ ๐Ÿ™ ๐Ÿ’… ๐Ÿ’ช ๐Ÿ‘‚ ๐Ÿ‘ƒ ๐Ÿ‘€ ๐Ÿ‘… ๐Ÿ‘„ ๐Ÿ‘ถ ๐Ÿ‘ฆ ๐Ÿ‘ง ๐Ÿ‘ฑ ๐Ÿ‘จ ๐Ÿ‘ฉ ๐Ÿ‘ด ๐Ÿ‘ต ๐Ÿ™ ๐Ÿ™Ž ๐Ÿ™… ๐Ÿ™† ๐Ÿ’ ๐Ÿ™‹ ๐Ÿ™‡ ๐Ÿ‘ฎ ๐Ÿ’‚ ๐Ÿ‘ท ๐Ÿ‘ธ ๐Ÿ‘ณ ๐Ÿ‘ฒ ๐Ÿ‘ฐ ๐Ÿ‘ผ ๐ŸŽ… ๐Ÿ’† ๐Ÿ’‡ ๐Ÿšถ ๐Ÿƒ ๐Ÿ’ƒ ๐Ÿ‘ฏ ๐Ÿ‡ ๐Ÿ‚ ๐Ÿ„ ๐Ÿšฃ ๐ŸŠ ๐Ÿšด ๐Ÿšต ๐Ÿ›€ ๐Ÿ‘ญ ๐Ÿ‘ซ ๐Ÿ‘ฌ ๐Ÿ’ ๐Ÿ’‘ ๐Ÿ‘ช ๐Ÿ‘ค ๐Ÿ‘ฅ ๐Ÿ‘ฃ ๐Ÿต ๐Ÿ’ ๐Ÿถ ๐Ÿ• ๐Ÿฉ ๐Ÿบ ๐Ÿฑ ๐Ÿˆ ๐Ÿฏ ๐Ÿ… ๐Ÿ† ๐Ÿด ๐ŸŽ ๐Ÿฎ ๐Ÿ‚ ๐Ÿƒ ๐Ÿ„ ๐Ÿท ๐Ÿ– ๐Ÿ— ๐Ÿฝ ๐Ÿ ๐Ÿ‘ ๐Ÿ ๐Ÿช ๐Ÿซ ๐Ÿ˜ ๐Ÿญ ๐Ÿ ๐Ÿ€ ๐Ÿน ๐Ÿฐ ๐Ÿ‡ ๐Ÿป ๐Ÿจ ๐Ÿผ ๐Ÿพ ๐Ÿ” ๐Ÿ“ ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿฆ ๐Ÿง ๐Ÿธ ๐ŸŠ ๐Ÿข ๐Ÿ ๐Ÿฒ ๐Ÿ‰ ๐Ÿณ ๐Ÿ‹ ๐Ÿฌ ๐ŸŸ ๐Ÿ  ๐Ÿก ๐Ÿ™ ๐Ÿš ๐ŸŒ ๐Ÿ› ๐Ÿœ ๐Ÿ ๐Ÿž ๐Ÿ’ ๐ŸŒธ ๐Ÿ’ฎ ๐ŸŒน ๐ŸŒบ ๐ŸŒป ๐ŸŒผ ๐ŸŒท ๐ŸŒฑ ๐ŸŒฒ ๐ŸŒณ ๐ŸŒด ๐ŸŒต ๐ŸŒพ ๐ŸŒฟ ๐Ÿ€ ๐Ÿ ๐Ÿ‚ ๐Ÿƒ ๐Ÿ‡ ๐Ÿˆ ๐Ÿ‰ ๐ŸŠ ๐Ÿ‹ ๐ŸŒ ๐Ÿ ๐ŸŽ ๐Ÿ ๐Ÿ ๐Ÿ‘ ๐Ÿ’ ๐Ÿ“ ๐Ÿ… ๐Ÿ† ๐ŸŒฝ ๐Ÿ„ ๐ŸŒฐ ๐Ÿž ๐Ÿ– ๐Ÿ— ๐Ÿ” ๐ŸŸ ๐Ÿ• ๐Ÿณ ๐Ÿฒ ๐Ÿฑ ๐Ÿ˜ ๐Ÿ™ ๐Ÿš ๐Ÿ› ๐Ÿœ ๐Ÿ ๐Ÿ  ๐Ÿข ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿก ๐Ÿฆ ๐Ÿง ๐Ÿจ ๐Ÿฉ ๐Ÿช ๐ŸŽ‚ ๐Ÿฐ ๐Ÿซ ๐Ÿฌ ๐Ÿญ ๐Ÿฎ ๐Ÿฏ ๐Ÿผ โ˜• ๐Ÿต ๐Ÿถ ๐Ÿท ๐Ÿธ ๐Ÿน ๐Ÿบ ๐Ÿป ๐Ÿด ๐Ÿ”ช ๐ŸŒ ๐ŸŒŽ ๐ŸŒ ๐ŸŒ ๐Ÿ—พ ๐ŸŒ‹ ๐Ÿ—ป ๐Ÿ  ๐Ÿก ๐Ÿข ๐Ÿฃ ๐Ÿค ๐Ÿฅ ๐Ÿฆ ๐Ÿจ ๐Ÿฉ ๐Ÿช ๐Ÿซ ๐Ÿฌ ๐Ÿญ ๐Ÿฏ ๐Ÿฐ ๐Ÿ’’ ๐Ÿ—ผ ๐Ÿ—ฝ โ›ช โ›ฒ โ›บ ๐ŸŒ ๐ŸŒƒ ๐ŸŒ„ ๐ŸŒ… ๐ŸŒ† ๐ŸŒ‡ ๐ŸŒ‰ โ™จ๏ธ ๐ŸŽ  ๐ŸŽก ๐ŸŽข ๐Ÿ’ˆ ๐ŸŽช ๐Ÿš‚ ๐Ÿšƒ ๐Ÿš„ ๐Ÿš… ๐Ÿš† ๐Ÿš‡ ๐Ÿšˆ ๐Ÿš‰ ๐ŸšŠ ๐Ÿš ๐Ÿšž ๐Ÿš‹ ๐ŸšŒ ๐Ÿš ๐ŸšŽ ๐Ÿš ๐Ÿš‘ ๐Ÿš’ ๐Ÿš“ ๐Ÿš” ๐Ÿš• ๐Ÿš– ๐Ÿš— ๐Ÿš˜ ๐Ÿš™ ๐Ÿšš ๐Ÿš› ๐Ÿšœ ๐Ÿšฒ ๐Ÿš โ›ฝ ๐Ÿšจ ๐Ÿšฅ ๐Ÿšฆ ๐Ÿšง โš“ โ›ต ๐Ÿšค ๐Ÿšข โœˆ๏ธ ๐Ÿ’บ ๐Ÿš ๐ŸšŸ ๐Ÿš  ๐Ÿšก ๐Ÿš€ โŒ› โณ โŒš โฐ ๐Ÿ•› ๐Ÿ•ง ๐Ÿ• ๐Ÿ•œ ๐Ÿ•‘ ๐Ÿ• ๐Ÿ•’ ๐Ÿ•ž ๐Ÿ•“ ๐Ÿ•Ÿ ๐Ÿ•” ๐Ÿ•  ๐Ÿ•• ๐Ÿ•ก ๐Ÿ•– ๐Ÿ•ข ๐Ÿ•— ๐Ÿ•ฃ ๐Ÿ•˜ ๐Ÿ•ค ๐Ÿ•™ ๐Ÿ•ฅ ๐Ÿ•š ๐Ÿ•ฆ ๐ŸŒ‘ ๐ŸŒ’ ๐ŸŒ“ ๐ŸŒ” ๐ŸŒ• ๐ŸŒ– ๐ŸŒ— ๐ŸŒ˜ ๐ŸŒ™ ๐ŸŒš ๐ŸŒ› ๐ŸŒœ โ˜€๏ธ ๐ŸŒ ๐ŸŒž โญ ๐ŸŒŸ ๐ŸŒ  ๐ŸŒŒ โ˜๏ธ โ›… ๐ŸŒ€ ๐ŸŒˆ ๐ŸŒ‚ โ˜” โšก โ„๏ธ โ›„ ๐Ÿ”ฅ ๐Ÿ’ง ๐ŸŒŠ ๐ŸŽƒ ๐ŸŽ„ ๐ŸŽ† ๐ŸŽ‡ โœจ ๐ŸŽˆ ๐ŸŽ‰ ๐ŸŽŠ ๐ŸŽ‹ ๐ŸŽ ๐ŸŽŽ ๐ŸŽ ๐ŸŽ ๐ŸŽ‘ ๐ŸŽ€ ๐ŸŽ ๐ŸŽซ ๐Ÿ† โšฝ โšพ ๐Ÿ€ ๐Ÿˆ ๐Ÿ‰ ๐ŸŽพ ๐ŸŽณ โ›ณ ๐ŸŽฃ ๐ŸŽฝ ๐ŸŽฟ ๐ŸŽฏ ๐ŸŽฑ ๐Ÿ”ฎ ๐ŸŽฎ ๐ŸŽฐ ๐ŸŽฒ โ™ ๏ธ โ™ฅ๏ธ โ™ฆ๏ธ โ™ฃ๏ธ ๐Ÿƒ ๐Ÿ€„ ๐ŸŽด ๐ŸŽญ ๐ŸŽจ ๐Ÿ‘“ ๐Ÿ‘” ๐Ÿ‘• ๐Ÿ‘– ๐Ÿ‘— ๐Ÿ‘˜ ๐Ÿ‘™ ๐Ÿ‘š ๐Ÿ‘› ๐Ÿ‘œ ๐Ÿ‘ ๐ŸŽ’ ๐Ÿ‘ž ๐Ÿ‘Ÿ ๐Ÿ‘  ๐Ÿ‘ก ๐Ÿ‘ข ๐Ÿ‘‘ ๐Ÿ‘’ ๐ŸŽฉ ๐ŸŽ“ ๐Ÿ’„ ๐Ÿ’ ๐Ÿ’Ž ๐Ÿ”‡ ๐Ÿ”ˆ ๐Ÿ”‰ ๐Ÿ”Š ๐Ÿ“ข ๐Ÿ“ฃ ๐Ÿ“ฏ ๐Ÿ”” ๐Ÿ”• ๐ŸŽผ ๐ŸŽต ๐ŸŽถ ๐ŸŽค ๐ŸŽง ๐Ÿ“ป ๐ŸŽท ๐ŸŽธ ๐ŸŽน ๐ŸŽบ ๐ŸŽป ๐Ÿ“ฑ ๐Ÿ“ฒ โ˜Ž๏ธ ๐Ÿ“ž ๐Ÿ“Ÿ ๐Ÿ“  ๐Ÿ”‹ ๐Ÿ”Œ ๐Ÿ’ป ๐Ÿ’ฝ ๐Ÿ’พ ๐Ÿ’ฟ ๐Ÿ“€ ๐ŸŽฅ ๐ŸŽฌ ๐Ÿ“บ ๐Ÿ“ท ๐Ÿ“น ๐Ÿ“ผ ๐Ÿ” ๐Ÿ”Ž ๐Ÿ’ก ๐Ÿ”ฆ ๐Ÿฎ ๐Ÿ“” ๐Ÿ“• ๐Ÿ“– ๐Ÿ“— ๐Ÿ“˜ ๐Ÿ“™ ๐Ÿ“š ๐Ÿ““ ๐Ÿ“’ ๐Ÿ“ƒ ๐Ÿ“œ ๐Ÿ“„ ๐Ÿ“ฐ ๐Ÿ“‘ ๐Ÿ”– ๐Ÿ’ฐ ๐Ÿ’ด ๐Ÿ’ต ๐Ÿ’ถ ๐Ÿ’ท ๐Ÿ’ธ ๐Ÿ’ณ ๐Ÿ’น ๐Ÿ’ฑ ๐Ÿ’ฒ โœ‰๏ธ ๐Ÿ“ง ๐Ÿ“จ ๐Ÿ“ฉ ๐Ÿ“ค ๐Ÿ“ฅ ๐Ÿ“ฆ ๐Ÿ“ซ ๐Ÿ“ช ๐Ÿ“ฌ ๐Ÿ“ญ ๐Ÿ“ฎ โœ๏ธ โœ’๏ธ ๐Ÿ“ ๐Ÿ’ผ ๐Ÿ“ ๐Ÿ“‚ ๐Ÿ“… ๐Ÿ“† ๐Ÿ“‡ ๐Ÿ“ˆ ๐Ÿ“‰ ๐Ÿ“Š ๐Ÿ“‹ ๐Ÿ“Œ ๐Ÿ“ ๐Ÿ“Ž ๐Ÿ“ ๐Ÿ“ โœ‚๏ธ ๐Ÿ”’ ๐Ÿ”“ ๐Ÿ” ๐Ÿ” ๐Ÿ”‘ ๐Ÿ”จ ๐Ÿ”ซ ๐Ÿ”ง ๐Ÿ”ฉ ๐Ÿ”— ๐Ÿ”ฌ ๐Ÿ”ญ ๐Ÿ“ก ๐Ÿ’‰ ๐Ÿ’Š ๐Ÿšช ๐Ÿšฝ ๐Ÿšฟ ๐Ÿ› ๐Ÿšฌ ๐Ÿ—ฟ ๐Ÿง ๐Ÿšฎ ๐Ÿšฐ โ™ฟ ๐Ÿšน ๐Ÿšบ ๐Ÿšป ๐Ÿšผ ๐Ÿšพ ๐Ÿ›‚ ๐Ÿ›ƒ ๐Ÿ›„ ๐Ÿ›… โš ๏ธ ๐Ÿšธ โ›” ๐Ÿšซ ๐Ÿšณ ๐Ÿšญ ๐Ÿšฏ ๐Ÿšฑ ๐Ÿšท ๐Ÿ“ต ๐Ÿ”ž โฌ†๏ธ โ†—๏ธ โžก๏ธ โ†˜๏ธ โฌ‡๏ธ โ†™๏ธ โฌ…๏ธ โ†–๏ธ โ†•๏ธ โ†”๏ธ ๐Ÿ”ƒ ๐Ÿ”„ ๐Ÿ”™ ๐Ÿ”š ๐Ÿ”› ๐Ÿ”œ ๐Ÿ” ๐Ÿ”ฏ โ™ˆ โ™‰ โ™Š โ™‹ โ™Œ โ™ โ™Ž โ™ โ™ โ™‘ โ™’ โ™“ โ›Ž ๐Ÿ”€ ๐Ÿ” ๐Ÿ”‚ โ–ถ๏ธ โ—€๏ธ ๐Ÿ”ผ ๐Ÿ”ฝ ๐ŸŽฆ ๐Ÿ“ถ ๐Ÿ“ณ ๐Ÿ“ด โ™ป๏ธ ๐Ÿ”ฑ ๐Ÿ“› ๐Ÿ”ฐ โญ• โœ… โ˜‘๏ธ โœ–๏ธ โŒ โŽ โž• โž– โž— โžฐ โžฟ ใ€ฝ๏ธ โœณ๏ธ โœด๏ธ โ‡๏ธ โ€ผ๏ธ โ‰๏ธ โ“ โ” โ• โ— ใ€ฐ๏ธ ยฉ๏ธ ยฎ๏ธ โ„ข๏ธ ๐Ÿ”  ๐Ÿ”ก ๐Ÿ”ข ๐Ÿ”ฃ ๐Ÿ”ค ๐Ÿ…ฐ๏ธ ๐Ÿ†Ž ๐Ÿ…ฑ๏ธ ๐Ÿ†‘ ๐Ÿ†’ ๐Ÿ†“ ๐Ÿ†” โ“‚๏ธ ๐Ÿ†• ๐Ÿ†– ๐Ÿ…พ๏ธ ๐Ÿ†— ๐Ÿ…ฟ๏ธ ๐Ÿ†˜ ๐Ÿ†™ ๐Ÿ†š ๐Ÿˆ ๐Ÿˆ‚๏ธ ๐Ÿˆท๏ธ ๐Ÿˆถ ๐Ÿˆฏ ๐Ÿ‰ ๐Ÿˆน ๐Ÿˆš ๐Ÿˆฒ ๐Ÿ‰‘ ๐Ÿˆธ ๐Ÿˆด ๐Ÿˆณ ใŠ—๏ธ ใŠ™๏ธ ๐Ÿˆบ ๐Ÿˆต ๐Ÿ”ด ๐Ÿ”ต โšซ โšช โฌ› โฌœ โ—ผ๏ธ โ—ป๏ธ โ—พ โ—ฝ โ–ช๏ธ โ–ซ๏ธ ๐Ÿ”ถ ๐Ÿ”ท ๐Ÿ”ธ ๐Ÿ”น ๐Ÿ”บ ๐Ÿ”ป ๐Ÿ’  ๐Ÿ”˜ ๐Ÿ”ณ ๐Ÿ”ฒ ๐Ÿ ๐Ÿšฉ ๐ŸŽŒ', settings: null, hotkeys: null, mass: 0, // Stores the current mass (Note: 0 is a valid value while being alive!! For example if the mass is 0.4, appaerently it is rounded to 0....) topMass: 0, mouse : { x: 0, y: 0, lastMovedAt: null, }, init: function() { var self = this; this.setupPolyfills(); this.hotkeys = JSON.parse(localStorage.getItem('hotkeys')); this.auth(); this.config(); this.originalDrawImage = CanvasRenderingContext2D.prototype.drawImage; CanvasRenderingContext2D.prototype.drawImage = this.drawImage; document.querySelector('body').addEventListener('mousemove', function(event) { self.mouse.x = event.clientX; self.mouse.y = event.clientY; self.mouse.lastMovedAt = Date.now(); }); this.moveRespawnBtn(); this.players(); this.animation(); this.chatLog(); this.halt(); this.dance(); this.favSkins(); this.paste(); this.replacements(); this.fpsPing(); this.timer(); this.alive(); this.skinChanger(); this.skinApplier(); this.nameCopier(); this.ultraSplit(); this.lineSplit(); this.waste(); this.guessing(); this.nameColor(); this.wearablesToggle(); this.keyboardLayout(); this.help(); this.commands(); console.log('๐Ÿ“œ Miracle Scripts successfully loaded!'); }, config: function() { var self = this; var settings = null; var loadSettings = function (stringifiedSettings) { var defaultSettings = { // To get keycodes: https://keycode.info bindings: { ultraSplit: 85, // U wearables: 36, // POS1 animation: 17, // CTRL paste: 33, // PAGE UP dance: 34, // PAGE DOWN, halt: 72, // H, lineSplit: null, // Undefined chatLog: 76, // L skin1: 49, // 1 skin2: 50, // 2 skin3: 51, // 3 skin4: 52, // 4 skin5: 53, // 5 skin6: 54, // 6 skin7: 55, // 7 skin8: 56, // 8 skin9: 57, // 9 }, replacements: ":D|:smile:\n:*(|:sob:\n:'D|:sweat_smile:\nxD|:joy:\n:shrug:|ยฏ\_(ใƒ„)_/ยฏ\n", primaryColor: '#f9138b', targetLanguage: 'en', favSkins: [], quickSkins: [], players: [], showClock: true, changeKeyboardLayout: false, showNewsFeed: true, overwriteHelp: true, useNickNameColor: false, nickNameColor: '#ffffff', useNickNameStrokeColor: false, nickNameStrokeColor: '#000000', useNickNameStrokeWidth: false, nickNameStrokeWidth: 2, playerChatFilter: true, coinsClaimedAt: null, }; if (stringifiedSettings == null || stringifiedSettings == undefined || stringifiedSettings === '') { settings = defaultSettings; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } else { settings = JSON.parse(stringifiedSettings); if (settings === null || Object.getOwnPropertyNames(settings).length == 0) { settings = defaultSettings; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } // Update for settings: if (typeof settings.primaryColor === 'undefined') { settings.primaryColor = defaultSettings.primaryColor; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.bindings.chatLog === 'undefined') { settings.bindings.chatLog = defaultSettings.bindings.chatLog; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.favSkins === 'undefined') { settings.favSkins = defaultSettings.favSkins; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.targetLanguage === 'undefined') { settings.targetLanguage = defaultSettings.targetLanguage; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.quickSkins === 'undefined') { settings.quickSkins = []; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.installedVersion === 'undefined') { settings.installedVersion = 1; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.players === 'undefined') { settings.players = []; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.bindings.skin1 === 'undefined') { settings.bindings.skin1 = defaultSettings.bindings.skin1; settings.bindings.skin2 = defaultSettings.bindings.skin2; settings.bindings.skin3 = defaultSettings.bindings.skin3; settings.bindings.skin4 = defaultSettings.bindings.skin4; settings.bindings.skin5 = defaultSettings.bindings.skin6; settings.bindings.skin6 = defaultSettings.bindings.skin6; settings.bindings.skin7 = defaultSettings.bindings.skin7; settings.bindings.skin8 = defaultSettings.bindings.skin8; settings.bindings.skin9 = defaultSettings.bindings.skin9; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.showClock === 'undefined') { settings.showClock = false; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.showKeyboardLayout === 'undefined') { settings.showKeyboardLayout = false; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.bindings.ultraSplit === 'undefined') { settings.bindings.ultraSplit = 85; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.bindings.wearables === 'undefined') { settings.bindings.wearables = 36; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.bindings.halt === 'undefined') { settings.bindings.halt = defaultSettings.bindings.halt; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.showNewsFeed === 'undefined') { settings.showNewsFeed = defaultSettings.showNewsFeed; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.overwriteHelp === 'undefined') { settings.overwriteHelp = defaultSettings.overwriteHelp; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.useNickNameStrokeWidth === 'undefined') { settings.useNickNameColor = defaultSettings.useNickNameColor; settings.nickNameColor = defaultSettings.nickNameColor; settings.useNickNameStrokeColor = defaultSettings.useNickNameStrokeColor; settings.nickNameStrokeColor = defaultSettings.nickNameStrokeColor; settings.useNickNameStrokeWidth = defaultSettings.useNickNameStrokeWidth; settings.nickNameStrokeWidth = defaultSettings.nickNameStrokeWidth; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.playerChatFilter === 'undefined') { settings.playerChatFilter = defaultSettings.playerChatFilter; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.coinsClaimed !== 'undefined') { delete settings.coinsClaimed; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.coinsClaimedAt === 'undefined') { settings.coinsClaimedAt = Date.now(); localStorage.setItem('miracleScripts', JSON.stringify(settings)); } if (typeof settings.bindings.lineSplit === 'undefined') { settings.bindings.lineSplit = defaultSettings.bindings.lineSplit; localStorage.setItem('miracleScripts', JSON.stringify(settings)); } } self.settings = settings; }; loadSettings(localStorage.getItem('miracleScripts')); if (settings.installedVersion < this.getVersionAsInt()) { if (settings.installedVersion > 1) { // We do not want to inform new scripts user of past updates if (settings.installedVersion < this.getVersionAsInt('2.4.3')) { window.alert('๐Ÿ“ข Miracle Scripts Update: \n\n' + 'As of version 2.4.3 the nickname color change feature has been removed ' + 'according to an official decision of the Agma team.\n\n' + 'To avoid trouble for its users Miracle Scripts respects this decision. ' + 'Therefore Miracle Scripts is a legit extension for Agma and using it is safe.' ); } if (settings.installedVersion < this.getVersionAsInt('2.5.6')) { self.swal( 'Miracle Scripts Update', 'You may now use 20 slots for skins (previously: 15). Type /skin16 - /skin20 in the chat box!'); } if (settings.installedVersion < this.getVersionAsInt('2.5.8')) { self.swal( 'Miracle Scripts Update', 'New: You may now assign aliases and notes to players. The alias will be displayed in the friends list. To add an alias right click on a player\'s name in the chat or a cell and then click on "Show profile".'); } if (settings.installedVersion < this.getVersionAsInt('2.6.0')) { self.swal( 'Miracle Scripts Update', 'New: You may now bind keys to skin slots. Per default the keys 1 - 9 are bound to /skin1 - /skin9.'); } if (settings.installedVersion < this.getVersionAsInt('2.6.1')) { self.swal( 'Miracle Scripts Update', 'New: Right click on a cell. Then click on Use Player\'s Wearables to use the same wearables as that player. (Of course you have to own the wearables.)'); } if (settings.installedVersion < this.getVersionAsInt('2.6.4')) { self.swal( 'Miracle Scripts Update', 'New: Want to see how late it is? Activate the clock in the settings!'); } if (settings.installedVersion < this.getVersionAsInt('3.0.0')) { self.swal( 'Miracle Scripts Update', 'ATTENTION! This script won\'t get any new features! The Agma staff keeps making new restrictions to this script, so there is no point to continue development. With this update, the /say command has been removed, as the Agma staff enforced this.'); } if (settings.installedVersion < this.getVersionAsInt('3.1.3')) { self.swal( 'Miracle Scripts Update', 'Just a friendly hint: Agma has a new powerup! It\'s called "Tactical Nuke" and can be found in the shop. Attention: It\'s the first of April ๐Ÿ˜œ'); } if (settings.installedVersion < this.getVersionAsInt('3.1.6')) { self.swal( 'Miracle Scripts Update', 'New: Type /players in the chat to see how many players are online in Agma!'); } if (settings.installedVersion < this.getVersionAsInt('3.3.0')) { self.swal( 'Miracle Scripts Update', 'New: You may now see your keyboard layout as an overlay! Go to the settings to activate it.'); } if (settings.installedVersion < this.getVersionAsInt('3.4.0')) { self.swal( 'Miracle Scripts Update', 'New: ULTRA split! Press U to make an ultra split, which can split 1 cell to 64!! (The server has to support that!)'); } if (settings.installedVersion < this.getVersionAsInt('3.6.0')) { self.swal( 'Miracle Scripts Update', 'New: Toggle "wearables on/off" with a key! Default is POS1!'); } if (settings.installedVersion < this.getVersionAsInt('4.0.0')) { self.swal( 'Miracle Scripts Update', 'New: Type /guess to start a little guessing game in the chat!

๐Ÿ’ก Note that it only works with browsers that can display emojis.'); } if (settings.installedVersion < this.getVersionAsInt('4.2.2')) { self.swal( 'Miracle Scripts Update', 'New: Right click on a player to copy the player\'s name to the chat! (PS: You cannot use the name as your own name though!)'); } if (settings.installedVersion < this.getVersionAsInt('4.3.2')) { self.swal( 'Miracle Scripts Announcement', 'Prepare for some insane new Miracle features! This time it will be mind-blowing.

To be released soon.'); } if (settings.installedVersion < this.getVersionAsInt('5.0.2')) { window.swal({ title: 'Miracle Scripts Update', text: 'Today we released a great new feature
to celebrate Miracle\'s 1 year anniversary:
Free self-freezing!

' + '' + '

Press H to use it!', html: true }); } if (settings.installedVersion < this.getVersionAsInt('5.0.6')) { self.swal( 'Miracle Scripts Update', 'New: Anti-AFK! Doubling the countdown time till you get disconnected for being AFK from 5 to 10 minutes!!!'); } if (settings.installedVersion < this.getVersionAsInt('5.1.0')) { self.swal( 'Miracle Scripts Update', 'Custom chat fonts are back - now with a cussing filter! Use /say1 message to send messages in custom font!!'); } if (settings.installedVersion < this.getVersionAsInt('5.1.5')) { self.swal( 'Miracle Scripts Update', '


5.000 Miracles!

Time to celebrate 1+ year of awesomeness, experienced by 5.000+ Agma players! ๐Ÿฅณ

'); } if (settings.installedVersion < this.getVersionAsInt('5.2.1')) { self.swal( 'Miracle Winter Giveaway!!!', '

Join our Discord server and win one of 5 amazing prices!


Participate in the huge winter giveaway (coins, minions, gold and power-ups!) and claim your custom nickname style!
' ); } if (settings.installedVersion < this.getVersionAsInt('5.2.3')) { self.swal( 'Miracle Scripts Update', 'New: Basic support for custom nickname styles! ๐Ÿฅณ

Go to the Miracle settings and change the look of your nickname.

Note: Only you can see that for now. More to come...'); } if (settings.installedVersion < this.getVersionAsInt('5.2.6')) { self.swal( 'Miracle Scripts Update', 'New Miracle setting: You may now turn this news feed on or off. Also you may decide if Agma\'s help should be overwritten by Miracles help.'); } if (settings.installedVersion < this.getVersionAsInt('5.3.0')) { self.swal( 'Miracle Scripts Update', 'New: Use the /wearable command to turn on/off your wearables!'); } if (settings.installedVersion < this.getVersionAsInt('5.4.0')) { self.swal( 'Miracle Scripts Update', 'New: Use the /mass and /topmass chat commands!'); } if (settings.installedVersion < this.getVersionAsInt('5.5.0')) { self.swal( 'Miracle Scripts Update', 'New: known toxic players get muted automatically.

You can disable this feature (useful for mods).'); } if (settings.installedVersion < this.getVersionAsInt('5.6.0')) { self.swal( 'Miracle Scripts Update', 'New: Miracle is reminding you to use the /claim command. Also megaphone messages can be seen in the Miracle chat log.'); } if (settings.installedVersion < this.getVersionAsInt('5.6.6')) { self.swal( 'Miracle Scripts Update', 'News: 10,000 Miracle installations!!! ๐Ÿฅณ๐Ÿฅณ๐Ÿฅณ'); } } settings.installedVersion = this.getVersionAsInt(); localStorage.setItem('miracleScripts', JSON.stringify(settings)); self.settings = settings; } if (settings.showNewsFeed) { var defaultNews = 'Agma Updates 22.Mar.2021'; var $newsElement = $('#cnt_panel .navbar p.text-center'); if ($newsElement.text().trim() === defaultNews) { $newsElement.css('margin-bottom', '20px'); $newsElement.css('padding', '10px'); $newsElement.css('background-color', 'rgba(0, 0, 0, 0.5)'); $newsElement.html(self.news); var $metaElement = $('
AGMA News
'); $newsElement.parent().prepend($metaElement); $metaElement.css('background-color', '#B5B9C0'); $metaElement.css('color', 'black'); } } var applyPrimaryColor = function () { var primaryColorCss = '.miracle-primary-color-font { color: ' + self.settings.primaryColor + ' !important } .miracle-primary-color-background { background-color: ' + self.settings.primaryColor + ' !important }; '; $('body').append(''); }; applyPrimaryColor(); // General fix for the size of the FontAwesome Icons in the context menu $('body').append(''); // We need to have a delay, because the menu is not loaded right away setTimeout(function () { var $playButton = $('#playBtn'); var $spectateButton = $('#spectateBtn'); $playButton.get(0).style.width = '40%'; $spectateButton.get(0).style.width = '40%'; var $settingsButton = $(''); $settingsButton.insertAfter($spectateButton); var changeKey = function (event) { var name = this.name.substr(4); $(this).val(self.keyboardMap[event.keyCode]); self.settings.bindings[name] = event.keyCode; localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var deleteKey = function () { var action = $(this).attr('data-action'); $('#miracle-settings input[name=key_' + action + ']').val('undefined'); self.settings.bindings[action] = null; localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; // Weird Agma scripting... press enter in the replacements textarea and the chat box gets focused! // Therefore catch the keydown event (that happens earlier) and insert the linebreak manually, // focus again (delayed) and go to the end of the text where the linebreak is. // We can improve this later on... var addReturn = function (event) { if (event.keyCode === 13) { var textarea = this; $(textarea).text($(this).text() + '\n').focus(); setTimeout(function () { $(textarea).focus(); textarea.setSelectionRange(textarea.value.length, textarea.value.length); }, 1); } }; var changeUseNickNameColor = function() { self.settings.useNickNameColor = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeUseNickNameStrokeColor = function() { self.settings.useNickNameStrokeColor = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeUseNickNameStrokeWidth = function() { self.settings.useNickNameStrokeWidth = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeNickNameColor = function() { self.settings.nickNameColor = $(this).val(); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeNickNameStrokeColor = function() { self.settings.nickNameStrokeColor = $(this).val(); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeNickNameStrokeWidth = function() { self.settings.nickNameStrokeWidth = parseInt($(this).val()) > -1 ? parseInt($(this).val()) : 2; localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeReplacements = function () { self.settings.replacements = $(this).val(); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changePrimaryColor = function () { self.settings.primaryColor = $(this).val(); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); applyPrimaryColor(); }; var changeTargetLanguage = function () { self.settings.targetLanguage = $(this).val(); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changePlayerChatFilter = function() { self.settings.playerChatFilter = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeOverwriteHelp = function() { self.settings.overwriteHelp = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeNewsFeed = function() { self.settings.showNewsFeed = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeClock = function() { self.settings.showClock = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var changeKeyboardLayout = function() { self.settings.showKeyboardLayout = $(this).is(':checked'); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }; var $modal = $(''); $modal.append('

Miracle Scripts Settings

'); if (GM_info) { $modal.append('Version ' + GM_info.script.version + ''); } var $firstRow = $(''); var $secRow = $(''); var $thirdRow = $(''); var $element = $('').keyup(changeKey); $firstRow.append('

Ultra-Split-Key:
', $element); $element = $('
โœ•').click(deleteKey); $firstRow.append($element); $element = $('').keyup(changeKey); $firstRow.append('

Animation-Key:
', $element); $element = $('โœ•').click(deleteKey); $firstRow.append($element); $element = $('').keyup(changeKey); $firstRow.append('

Paste-Key:
', $element); $element = $('โœ•').click(deleteKey); $firstRow.append($element); $element = $('').keyup(changeKey); $firstRow.append('

Dance-Key:
', $element); $element = $('โœ•').click(deleteKey); $firstRow.append($element); $element = $('').keyup(changeKey); $firstRow.append('

Halt-Key:
', $element); $element = $('โœ•').click(deleteKey); $firstRow.append($element); $element = $('').keyup(changeKey); $firstRow.append('

Chat-Log-Key:
', $element); $element = $('โœ•').click(deleteKey); $firstRow.append($element); $element = $('').keyup(changeKey); $secRow.append('

Use-First-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $secRow.append($element); $element = $('').keyup(changeKey); $secRow.append('

Use-Second-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $secRow.append($element); $element = $('').keyup(changeKey); $secRow.append('

Use-Third-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $secRow.append($element); $element = $('').keyup(changeKey); $secRow.append('

Use-Fourth-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $secRow.append($element); $element = $('').keyup(changeKey); $secRow.append('

Use-Fifth-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $secRow.append($element); $element = $('').keyup(changeKey); $secRow.append('

Line-Split-Key:
', $element); $element = $('โœ•').click(deleteKey); $secRow.append($element); $element = $('').keyup(changeKey); $thirdRow.append('

Use-Sixth-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $thirdRow.append($element); $element = $('').keyup(changeKey); $thirdRow.append('

Use-Seventh-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $thirdRow.append($element); $element = $('').keyup(changeKey); $thirdRow.append('

Use-Eighth-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $thirdRow.append($element); $element = $('').keyup(changeKey); $thirdRow.append('

Use-Ninth-Skin-Key:
', $element); $element = $('โœ•').click(deleteKey); $thirdRow.append($element); $element = $('').keyup(changeKey); $thirdRow.append('

Toggle-Wearables-Key:
', $element); $element = $('โœ•').click(deleteKey); $thirdRow.append($element); var $table = $('').append($('').append($('').append($firstRow).append($secRow).append($thirdRow))); $modal.append($table); $firstRow = $('
'); $element = $('').change(changeUseNickNameColor); $firstRow.append($element, ' Nickname Color:
'); $element = $('').change(changeNickNameColor); $firstRow.append($element); $secRow = $('
'); $element = $('').change(changeUseNickNameStrokeColor); $secRow.append($element, ' Nickname Stroke Color:
'); $element = $('').change(changeNickNameStrokeColor); $secRow.append($element); $thirdRow = $('
'); $element = $('').change(changeUseNickNameStrokeWidth); $thirdRow.append($element, ' Nickname Stroke Width:
'); $element = $('').change(changeNickNameStrokeWidth); $thirdRow.append($element); $table = $('').append($('').append($('').append($firstRow).append($secRow).append($thirdRow))); $modal.append($table); $element = $('').change(changeTargetLanguage); $modal.append('

Translate Chat Messages to:
', $element); $element.get(0).value = self.settings.targetLanguage; $element = $('').change(changePrimaryColor); $modal.append('

User Interface Color:
', $element); $element = $('').change(changePlayerChatFilter); $modal.append('

Automatically hide messages of toxic players:
', $element); $element = $('').change(changeOverwriteHelp); $modal.append('

Overwrite Agma Help (reload website to update):
', $element); $element = $('').change(changeNewsFeed); $modal.append('

Show News Feed (reload website to update):
', $element); $element = $('').change(changeClock); $modal.append('

Show Clock:
', $element); $element = $('').change(changeKeyboardLayout); $modal.append('

Show Keyboard Layout (reload website to update):
', $element); $element = $('').blur(function() { var note = $(this).val(); if (player) { player.note = note; } else { player = {name: accountName, note: note}; self.settings.players.push(player); } localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); }); if (player) { $noteField.val(player.note); } $editArea.append($noteField); $editArea.insertBefore('.sweet-alert .sa-button-container'); if ($('.sweet-overlay').attr('data-listening') != 1) { $('.sweet-overlay').attr('data-listening', 1); $('.sweet-overlay').click(function() { $('#miracle-player-settings').remove(); }); $('.sweet-alert .sa-button-container button').click(function() { $('#miracle-player-settings').remove(); }); } }, 300); }); }, auth: function() { var self = this; var value = localStorage.getItem('330145eb94127d7d99dd28af3ee8599d'); if (value) { throw 'Exception: Authentication failed. Code: 1000001'; } var check = function () { var accountName = self.getAccountName(); if (self.banned.indexOf(accountName) > -1) { console.log('Exception: Authentication failed. Code: 1000001'); localStorage.setItem('330145eb94127d7d99dd28af3ee8599d', '90f62eda082944015b3c794c65b7c0f0'); window.location.reload(); return; }; } setInterval(check, 10000); }, animation: function () { var self = this; var chatAnimate = function () { if ($('#chtbox').val().substr(0, 4) === '/pm ') { $('#chtbox').val(''); } // All available commands and combinations var items = ['wacky', 'spin', 'spinspin', 'spinspinspin', 'wackyspin', 'wackyspinspin', 'heartsspin', 'heartsspinspin', 'wavespinspin', 'wavespin', 'flip', 'flipflip', 'flipflipflip', 'wackyflip', 'wackyflipflip', 'heartsflip', 'heartsflipflip', 'waveflipflip', 'waveflip', 'shake', 'shakeshake', 'shakeshakeshake', 'wackyshake', 'wackyshakeshake', 'heartsshake', 'heartsshakeshake', 'waveshakeshake', 'waveshake', 'jump', 'jumpjump', 'jumpjumpjump', 'wackyjump', 'wackyjumpjump', 'heartsjump', 'heartsjumpjump', 'wavejumpjump', 'wavejump', ]; // Super-combinations!! if (self.getRandomInt(1, 3) === 1) { items = ['jumpspinflip', 'jumpflipshake', 'jumpspinshake', 'spinshakeflip']; } // Choose randomly an item of the items array // Source: https://stackoverflow.com/questions/5915096/get-random-item-from-javascript-array var item = items[Math.floor(Math.random() * items.length)]; // Attempt to avoid triggering spam protection - probably useless :-/ item += String.fromCharCode(8203).repeat(self.getRandomInt(1, 5)); // Add text into the chat box and focus it (Note: actually "/" is no longer necessary) $('#chtbox').val($('#chtbox').val() + item).focus(); // Stop the event so that the pressed key won't be written into the chat box! event.preventDefault(); }; window.addEventListener('keydown', function (event) { // Do nothing if a menu is open if (document.getElementById('overlays').style.display !== 'none' || document.getElementById('advert').style.display !== 'none') { return; } if (event.keyCode == self.settings.bindings.animation) { chatAnimate(); } }); }, paste: function () { var self = this; var emojiFontSize = (window.innerWidth * window.innerHeight > 2000000) ? 24 : 18; var css = '#miracle-emojis .miracle-emoji { display: inline-block; width: 40px; margin: 0 2px 2px 0; padding: 5px; border: 1px solid #333; font-size: ' + emojiFontSize + 'px; }\n' + '#miracle-emojis .miracle-emoji:hover { background-color: #FF69B4 }'; var emojis = this.emojis.split(' '); var emojiCode = ''; emojis.forEach(function (emoji) { emojiCode += '' + emoji + ''; }); var addEmoji = function () { setTimeout(function () { var $pasteInput = $(document).find('#miracle-emojis input[name=paste]'); // Add text into the chatbox and focus it $('#chtbox').val($('#chtbox').val() + $pasteInput.val()).focus(); }, 200); $modal.hide(); }; var $modal = $(''); $modal.append(''); $modal.append('

Insert text or emoji

'); var $pasteInput = $(''); $modal.append('

Insert:
', $pasteInput); $modal.html($modal.html() + '

' + emojiCode); $modal.append($('
Add').click(addEmoji)); $modal.append($('Cancel').click(function () { $modal.hide(); })); $modal.find('input[name=paste]').click(function () { var text = window.prompt('Please paste your text here!'); if (text !== null) { var $pasteInput = $modal.find('input[name=paste]'); // Add text into the paste input $pasteInput.val($pasteInput.val() + text); } }); $modal.click(function (event) { if (event.target.classList.contains('miracle-emoji')) { var $target = $(this).find('input[name=paste]'); $target.val($target.val() + $(event.target).text()); event.preventDefault(); } }); $modal.dblclick(function (event) { if (event.target.classList.contains('miracle-emoji')) { $('#chtbox').val($('#chtbox').val() + $(event.target).text()).focus(); $(this).hide(); event.preventDefault(); } }); $('body').append($modal); window.addEventListener('keydown', function (event) { // Do nothing if a menu is open if (document.getElementById('overlays').style.display !== 'none' || document.getElementById('advert').style.display !== 'none') { return; } if (event.keyCode == self.settings.bindings.paste) { $modal.find('input[name=paste]').val(''); $modal.toggle(); } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/paste') { $modal.find('input[name=paste]').val(''); $modal.toggle(); $('#chtbox').val(''); } }); }, replacements: function () { var self = this; $('#chtbox').keyup(function () { var lines = self.settings.replacements.split('\n'); var text = $('#chtbox').val(); lines.forEach(function (line) { var replacement = line.split('|'); if (replacement.length === 2) { text = text.replace(replacement[0], replacement[1]); $('#chtbox').val(text).focus(); } }); }); }, chatLog: function () { var self = this; // We escape the message before we print them, so no one can inject JS code! var htmlEntities = function (str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); }; var originalFillText = CanvasRenderingContext2D.prototype.fillText; var lastChatNickname = null; var lastChatNicknameColor = null; var chatLogCode = ''; var chatLog = []; CanvasRenderingContext2D.prototype.fillText = function () { var text = arguments[0]; if (this.canvas.id === '') { let match = text.toString().match(/^Mass: (\d+)$/); if (match !== null){ self.mass = parseInt(match[1]); if (self.mass > self.topMass) { self.topMass = self.mass; } } } // Canvas height is smaller when the screen is smaller than usual if (this.canvas.id !== 'leaderboard' && this.canvas.height > 13 && this.canvas.height <= 25 && typeof text !== 'number') { var xPos = arguments[1]; // Usually 3 for nicknames but bigger when a crown, donator icon etc. are displayed var lineSize = this.canvas.width; // ATTENTION: Not sure if that really is the total size (icons + nickname + message) // Sometimes also numbers (int) are printed (probably masses on cells) so we filter for strings if (typeof text === 'string' && (this.fillStyle !== '#f5f6ce' && this.fillStyle !== '#444444')) { // Dirty fix for the missing icon in the initial welcome messages if (text == '') { text = '๐Ÿ“ข'; } lastChatNickname = text; lastChatNicknameColor = this.fillStyle; } if (typeof text === 'string' && (this.fillStyle === '#f5f6ce' || this.fillStyle === '#444444')) { if (self.settings.playerChatFilter && lastChatNickname && lastChatNickname.indexOf('Angelica') !== -1) { let args = arguments; arguments[0] = '*****************************************************************************************************************'; return originalFillText.apply(this, args); } if (lastChatNickname === '๐“ขเธ„ษฑiษพเธ„') { this.fillStyle = '#FF0000'; } // Unfortunately chat messages will be printed more than just once and I don't know // how to identify them, so for now all messages will be stored and only new messages will be shown. // Of course this means messages won't be shown if they are sent more than once (by the same nickname). var found = false; for (var i = 0; i < chatLog.length; i++) { if (chatLog[i].nickname === lastChatNickname && chatLog[i].nicknameColor === lastChatNicknameColor && chatLog[i].message === text) { found = true; break; } } if (!found) { var legit = text.indexOf(self.watermark) > -1 ? 'class="legit" title="๐Ÿ›ก๏ธ This seems to be a legit Miracle Scripts message"' : ''; // NOTE: We might have to look for the coordinates of the text to find out the order of the messages (somehow) chatLogCode += '
' + (new Date().toLocaleTimeString()) + ' ' + htmlEntities(lastChatNickname) + ''; chatLogCode += '' + htmlEntities(text) + '
'; chatLog.push({nickname: lastChatNickname, nicknameColor: lastChatNicknameColor, message: text}); var messageEvent = new Event('miracleChatMessage'); messageEvent.nickname = lastChatNickname; messageEvent.nicknameColor = lastChatNicknameColor; messageEvent.message = text; window.dispatchEvent(messageEvent); } } } return originalFillText.apply(this, arguments); }; var performSearch = function (searchElement) { var subject = searchElement.value.toLowerCase(); $('#miracle-complete-chatlog div').each(function () { var $entry = $(this); if ($entry.text().toLowerCase().indexOf(subject) === -1 && subject != '') { $entry.hide(); } else { $entry.show(); } }); }; var $modal = $(''); $modal.append(''); $modal.append('

Complete Chat Log


'); $modal.append('
'); $modal.append($('').keyup(function () { performSearch(this); })); $modal.append($('
Close').click(function () { $modal.hide(); })); $('body').append($modal); $('#miracle-complete-chatlog').dblclick(function (event) { var $clickTarget; // Each chat message is a div with spans in it. Either the spans or the div might be clicked. if (event.target.tagName.toLowerCase() === 'span') { $clickTarget = $(event.target).parent(); } else { $clickTarget = $(event.target); } var message = $clickTarget.find('.message').text(); // Messages usually start with ': ' but we do not want to "translate" it, so we remove it if (message.substr(0, 2) === ': ') { message = message.substr(2); } window.open('https://www.deepl.com/translator#auto/' + self.settings.targetLanguage + '/' + message); }); const originalText = jQuery.prototype.text; jQuery.prototype.text = function (text) { if (this.get(0) && this.get(0).id === 'megaphone_text') { chatLogCode += '
' + (new Date().toLocaleTimeString()) + ' ๐Ÿ“ข Megaphone by ' + htmlEntities($('#megaphone_name').text()) + ': ' + htmlEntities(text) + '
'; } return originalText.apply(this, arguments); } var showChatlog = function() { $('#miracle-complete-chatlog').html(chatLogCode); $modal.toggle(); $modal.get(0).scrollTo(0, $modal.get(0).scrollHeight); }; window.addEventListener('keyup', function (event) { // Ignore text input field so typing in them is possible if (self.isWritingText()) { return; } if (event.keyCode == self.settings.bindings.chatLog) { showChatlog(); } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/chatlog') { showChatlog(); $('#chtbox').val(''); } }); }, favSkins: function () { var self = this; // We need to have a delay, because the menu is not loaded right away setTimeout(function () { var favIconClick = function () { var id = parseInt($(this).parent().parent().find('button').attr('onclick').substr(11)); if (self.settings.favSkins.includes(id)) { $(this).addClass('skin-not-fav'); $('#skinUseBtn' + id).parent().find('span').addClass('skin-not-fav'); var index = self.settings.favSkins.indexOf(id); self.settings.favSkins.splice(index, 1); } else { $(this).removeClass('skin-not-fav'); self.settings.favSkins.push(id); } localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); renderFavSkins(); }; var renderFavSkins = function () { var $skins = null; if ($('#fav-skins').length > 0) { $skins = $('#fav-skins'); $skins.html(''); } else { $skins = $('
'); $skins.insertAfter('#publicSkinsHeader'); $('#fav-skins').click(function (event) { if (event.target.tagName.toLowerCase() === 'span') { favIconClick.apply(event.target); } }); } self.settings.favSkins.forEach(function (id) { $skins.append('

โญ

'); }); $skins.append('
'); }; var addFavIcons = function () { var $skins = $('#publicSkinsPage'); $skins.append(''); $skins.find('h4').each(function () { var $favIcon = $('โญ'); var id = parseInt($(this).parent().find('button').attr('onclick').substr(11)); $favIcon.click(favIconClick); $(this).append($favIcon); if (! self.settings.favSkins.includes(id)) { $favIcon.addClass('skin-not-fav'); } }); }; var initialized = false; $('#skinsCustomTab, #skinExampleMenu').click(function () { if (!initialized) { var checkState = function () { if ($('#publicSkinsPage').html() !== '') { addFavIcons(); renderFavSkins(); } else { setTimeout(checkState, 30); } }; checkState(); initialized = true; } }); $('#phpSkins').click(function (event) { if (event.target.classList.contains('publicskins-nav-btn')) { addFavIcons(); } }); }, 500); }, skinChanger: function() { var self = this; // When the user changes the skin, display ID of the picked skin var originalToggleSkin = window.toggleSkin; window.toggleSkin = function () { self.message('Picked skin with ID ' + arguments[0]); return originalToggleSkin.apply(this, arguments); }; var useSkinFromSlot = function (skinSlot, skinId) { var skinUri = null; if (skinId) { if (skinId === 'this' || skinId === 'current' || skinId === 'my' || skinId === 'me' || skinId === 'now' || skinId === 'here') { skinUri = self.getSkinUrl(); skinId = parseInt(skinUri.substr(skinUri.indexOf('skins/') + 6)); self.message('Skin ' + skinId + ' saved in slot ' + skinSlot + ' โœ”๏ธ'); } skinId = parseInt(skinId); self.settings.quickSkins[skinSlot - 1] = skinId; localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); } else { skinId = self.settings.quickSkins[skinSlot - 1]; if (!skinId) { self.message('Skin not set yet, set with /skin' + skinSlot + ' id ๐Ÿ˜Š', true); $('#chtbox').val(''); return; } } if (skinUri === null) { self.useSkin(skinId); } $('#chtbox').val(''); }; window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === 'skin1' || commandEvent.command === '/skin1') { useSkinFromSlot(1, commandEvent.argument1); } if (commandEvent.command === 'skin2' || commandEvent.command === '/skin2') { useSkinFromSlot(2, commandEvent.argument1); } if (commandEvent.command === 'skin3' || commandEvent.command === '/skin3') { useSkinFromSlot(3, commandEvent.argument1); } if (commandEvent.command === 'skin4' || commandEvent.command === '/skin4') { useSkinFromSlot(4, commandEvent.argument1); } if (commandEvent.command === 'skin5' || commandEvent.command === '/skin5') { useSkinFromSlot(5, commandEvent.argument1); } if (commandEvent.command === 'skin6' || commandEvent.command === '/skin6') { useSkinFromSlot(6, commandEvent.argument1); } if (commandEvent.command === 'skin7' || commandEvent.command === '/skin7') { useSkinFromSlot(7, commandEvent.argument1); } if (commandEvent.command === 'skin8' || commandEvent.command === '/skin8') { useSkinFromSlot(8, commandEvent.argument1); } if (commandEvent.command === 'skin9' || commandEvent.command === '/skin9') { useSkinFromSlot(9, commandEvent.argument1); } if (commandEvent.command === 'skin10' || commandEvent.command === '/skin10') { useSkinFromSlot(10, commandEvent.argument1); } if (commandEvent.command === 'skin11' || commandEvent.command === '/skin11') { useSkinFromSlot(11, commandEvent.argument1); } if (commandEvent.command === 'skin12' || commandEvent.command === '/skin12') { useSkinFromSlot(12, commandEvent.argument1); } if (commandEvent.command === 'skin13' || commandEvent.command === '/skin13') { useSkinFromSlot(13, commandEvent.argument1); } if (commandEvent.command === 'skin14' || commandEvent.command === '/skin14') { useSkinFromSlot(14, commandEvent.argument1); } if (commandEvent.command === 'skin15' || commandEvent.command === '/skin15') { useSkinFromSlot(15, commandEvent.argument1); } if (commandEvent.command === 'skin16' || commandEvent.command === '/skin16') { useSkinFromSlot(16, commandEvent.argument1); } if (commandEvent.command === 'skin17' || commandEvent.command === '/skin17') { useSkinFromSlot(17, commandEvent.argument1); } if (commandEvent.command === 'skin18' || commandEvent.command === '/skin18') { useSkinFromSlot(18, commandEvent.argument1); } if (commandEvent.command === 'skin19' || commandEvent.command === '/skin19') { useSkinFromSlot(19, commandEvent.argument1); } if (commandEvent.command === 'skin20' || commandEvent.command === '/skin20') { useSkinFromSlot(20, commandEvent.argument1); } if (commandEvent.command === 'skin21' || commandEvent.command === '/skin21') { self.message('Only 20 skin slots are available โŒ', true); $('#chtbox').val('').focus(); } }); window.addEventListener('keyup', function (event) { // Ignore text input field so typing in them is possible if (self.isWritingText()) { return; } if (event.keyCode == self.settings.bindings.skin1) { useSkinFromSlot(1); } if (event.keyCode == self.settings.bindings.skin2) { useSkinFromSlot(2); } if (event.keyCode == self.settings.bindings.skin3) { useSkinFromSlot(3); } if (event.keyCode == self.settings.bindings.skin4) { useSkinFromSlot(4); } if (event.keyCode == self.settings.bindings.skin5) { useSkinFromSlot(5); } if (event.keyCode == self.settings.bindings.skin6) { useSkinFromSlot(6); } if (event.keyCode == self.settings.bindings.skin7) { useSkinFromSlot(7); } if (event.keyCode == self.settings.bindings.skin8) { useSkinFromSlot(8); } if (event.keyCode == self.settings.bindings.skin9) { useSkinFromSlot(9); } }); }, ultraSplit: function() { var self = this; window.addEventListener('keyup', function () { if (event.keyCode == self.settings.bindings.ultraSplit) { var tripleSplit = function() { window.onkeydown({keyCode: self.hotkeys.T.c}); window.onkeyup({keyCode: self.hotkeys.T.c}); } tripleSplit(); window.setTimeout(function() { tripleSplit(); window.setTimeout(function() { tripleSplit(); }, 150); }, 150); } }); }, lineSplit: function() { var self = this; let startLineSplit = function() { self.lineSplitAt = Date.now(); self.message('Linesplit โ€ขโ€ขโ€ขโ€ขโ€ข'); var doSplit = function() { if (Date.now() - self.lineSplitAt < 1000) { var factor = Math.min((Date.now() - self.lineSplitAt) / 700, 1); var x = window.innerWidth / 2; var y = factor * (window.innerHeight / 2); $('canvas').trigger($.Event('mousemove', {clientX: x, clientY: y})); window.requestAnimationFrame(doSplit); } else { if (Date.now() - self.lineSplitAt < 3000) { if (self.splitAt === undefined || Date.now() - self.splitAt > 200) { window.onkeydown({keyCode: self.hotkeys.T.c}); window.onkeyup({keyCode: self.hotkeys.T.c}); self.splitAt = Date.now(); } window.requestAnimationFrame(doSplit); } } }; doSplit(); } window.addEventListener('keyup', function () { if (event.keyCode == self.settings.bindings.lineSplit) { if (self.isWritingText()) { return; } startLineSplit(); } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/linesplit') { startLineSplit(); $('#chtbox').val(''); } }); }, halt: function() { var self = this; // Stop halt on respawn window.addEventListener('keydown', function (event) { if (self.hotkeys && event.keyCode == self.hotkeys.M.c && ! self.isWritingText()) { self.onHalt = false; } }); var initHalt = function() { // Do nothing if a menu is open if (document.getElementById('overlays').style.display !== 'none' || document.getElementById('advert').style.display !== 'none') { return; } self.onHalt = ! self.onHalt; if (self.onHalt) { self.performHalt.apply(self); } }; window.addEventListener('keyup', function () { if (event.keyCode == self.settings.bindings.halt) { if (self.isWritingText()) { return; } initHalt(); } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/halt') { initHalt(); $('#chtbox').val(''); } }); }, performHalt: function () { var self = this ? this : window.miracleScripts; if (self.haltMoveDirection === undefined) { self.haltMoveDirection = 1; } self.haltMoveDirection = -self.haltMoveDirection; var centerX = window.innerWidth / 2; var centerY = window.innerHeight / 2; var angle = self.getAngle(centerX, centerY, self.mouse.x, self.mouse.y); if (self.haltMoveDirection === 1) { angle = self.addAngle(angle, 180); // Invert angle } angle = self.addAngle(angle, 270); var distance = 1000000; var x = centerX + Math.cos(angle * Math.PI / 180) * distance; var y = centerY + Math.sin(angle * Math.PI / 180) * distance; $('canvas').trigger($.Event('mousemove', {clientX: x, clientY: y})); // Stop halt if dead ... to avoid continuing halt after next respawn if (document.getElementById('advert').style.display !== 'none') { self.onHalt = false; } if (self.onHalt) { window.requestAnimationFrame(self.performHalt); } }, dance: function () { var self = this; // Stop dancing on respawn window.addEventListener('keydown', function (event) { if (self.hotkeys && event.keyCode == self.hotkeys.M.c && ! self.isWritingText()) { self.dancing = false; } }); var initDance = function() { // Do nothing if a menu is open if (document.getElementById('overlays').style.display !== 'none' || document.getElementById('advert').style.display !== 'none') { return; } self.dancing = ! self.dancing; if (self.dancing) { self.performDance.apply(self); } }; window.addEventListener('keyup', function () { if (event.keyCode == self.settings.bindings.dance) { initDance(); } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/dance') { initDance(); $('#chtbox').val(''); } }); }, performDance: function () { var self = this ? this : window.miracleScripts; if (self.danceAngle === undefined) { self.danceAngle = 0; } self.danceAngle += 20; if (self.danceAngle > 360) { self.danceAngle = 0; } var distance = 1000000; var x = window.innerWidth / 2 + Math.sin(self.danceAngle * Math.PI / 180) * distance; var y = window.innerHeight / 2 + Math.cos(self.danceAngle * Math.PI / 180) * distance; $('canvas').trigger($.Event('mousemove', {clientX: x, clientY: y})); // Stop dancing if dead ... to avoid continuing dancing after next respawn if (document.getElementById('advert').style.display !== 'none') { self.dancing = false; } if (self.dancing) { window.requestAnimationFrame(self.performDance); } }, waste: function() { var self = this; window.addEventListener('keydown', function (event) { if (self.hotkeys && event.keyCode == self.hotkeys.M.c && ! self.isWritingText()) { self.wasting = false; } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/waste') { if (self.wasting) { self.wasting = false; self.message('Stopped wasting all mass.'); self.dancing = false; } else { self.wasting = true; self.message('Wasting all mass... ๐Ÿ’ฅ'); if (! self.dancing) { self.dancing = true; self.performDance.apply(self); } $('#chtbox').val('spinshakeflip').focus(); } var doWaste = function() { // Stop wasting mass if dead ... to avoid continuing wasting after next respawn if (document.getElementById('advert').style.display !== 'none') { self.wasting = false; } if (! self.wasting) { return; } $('body').trigger($.Event('keydown', { keyCode: self.hotkeys.W.c})); $('body').trigger($.Event('keyup', { keyCode: self.hotkeys.W.c})); window.requestAnimationFrame(doWaste); }; doWaste(); } }); }, fpsPing: function () { var self = this; window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === 'ping' || commandEvent.command === '/ping' || commandEvent.command === '/lag') { window.setFPS(1); var pingRating = 'Extremely bad! โŒ', ping = $('#ping').text(); if (parseInt(ping) > 0) { if (parseInt(ping) >= 0 && parseInt(ping) < 35) { pingRating = 'Perfect! โœ”๏ธ'; } if (parseInt(ping) >= 35 && parseInt(ping) < 70) { pingRating = 'Good! โœ”๏ธ'; } if (parseInt(ping) >= 70 && parseInt(ping) < 120) { pingRating = 'Acceptable! โœ”๏ธ'; } if (parseInt(ping) >= 120 && parseInt(ping) < 200) { pingRating = 'Bad! โŒ'; } if (parseInt(ping) >= 200 && parseInt(ping) < 990) { pingRating = 'Insanity! โŒ'; } if (parseInt(ping) >= 990 && parseInt(ping) < 4900) { pingRating = 'THIS IS MADNESS! โŒ'; } if (parseInt(ping) > 4900) { pingRating = 'M M M M M M M M M MONSTERPING! โŒ'; } } else { ping = 'โˆž (infinite) '; } $('#chtbox').val(self.pretty('has a ping of: ' + ping + '. ' + pingRating) + self.watermark).focus(); } if (commandEvent.command === 'fps' || commandEvent.command === '/fps') { window.setFPS(1); var fpsRating = 'Perfect! โœ”๏ธ', fps = $('#fps').text(); if (parseInt(fps) > 0) { if (fps >= 0 && fps < 10) { fpsRating = 'Extremely bad! โŒ'; } if (fps >= 10 && fps < 30) { fpsRating = 'Bad! โŒ'; } if (fps >= 30 && fps < 40) { fpsRating = 'Acceptable! โœ”๏ธ'; } if (fps >= 40 && fps < 57) { fpsRating = 'Good! โœ”๏ธ'; } if (fps > 73) { fpsRating = 'Outstanding! โœ”๏ธ'; } if (fps > 97) { fpsRating = 'Fantastic! โœ”๏ธ'; } if (fps > 117) { fpsRating = 'GODLIKE! โœ”๏ธ'; } } else { fpsRating = ''; } $('#chtbox').val(self.pretty('has ' + fps + 'fps. ' + fpsRating) + self.watermark).focus(); } }); }, timer: function() { var self = this; var timerStartedAt = null; var timerMinutes = null; var timeoutId = null; var updateId = null; // Note: The "settings" item is missing in the local storage until settings have been changed var agmaSettings = localStorage.getItem('settings') ? JSON.parse(localStorage.getItem('settings')) : { sDark : false }; var color = (agmaSettings.sDark) ? '#999' : '#3e3e3e'; var $timeUi = $('
'); $('body').append($timeUi); var updateUi = function () { var time = ''; if (self.settings.showClock) { var hours = (new Date).getHours(); var minutes = (new Date).getMinutes(); time = (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes); if (timeoutId) { time = ' - ' + time; } } var remaining = ''; if (timeoutId) { remaining = Math.ceil(((timerStartedAt + timerMinutes * 60 * 1000) - Date.now()) / 1000 / 60) + 'm'; } if (time || remaining) { $timeUi.text('๐Ÿ•’ ' + remaining + time); } else { $timeUi.text(''); } }; updateUi(); updateId = setInterval(updateUi, 2000); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === 'timer' || commandEvent.command === '/timer') { var argument1 = commandEvent.argument1; var argument2 = commandEvent.argument2; if (argument1) { timerMinutes = parseInt(argument1); if (argument2 === 'h' || argument2 === 'hour' || argument2 === 'hours') { timerMinutes *= 60; } if (timeoutId !== null) { clearTimeout(timeoutId); } if (argument1 === '0' || argument1 === 'reset' || argument1 === 'stop' || argument1 === 'clear' || argument1 === 'remove') { self.message('๐Ÿ—‘๏ธ Timer removed'); } else { timerStartedAt = Date.now(); timeoutId = setTimeout(function () { timeoutId = null; updateUi() var message = '๐Ÿ•’ Alert! Timer has expired after ' + timerMinutes + ' minutes.'; self.message(message); self.swal('Time has expired', '๐Ÿ•’ Alert! Timer has expired after ' + timerMinutes + ' minutes.'); }, timerMinutes * 60 * 1000); updateUi(); self.message('๐Ÿ•’ Timer set to ' + timerMinutes + ' minutes'); } } else { if (timeoutId === null) { self.message('๐Ÿ•’ No timer has been set. Set with: /timer minutes', true); } else { var remaining = ((timerStartedAt + timerMinutes * 60 * 1000) - Date.now()) / 1000 / 60; self.message('๐Ÿ•’ ' + Math.round(remaining * 10) / 10 + ' minutes remaining.'); } } $('#chtbox').val('').focus(); } }); }, alive: function() { var self = this; var element = document.getElementById('playBtn'); element.addEventListener('click', function() { if (! self.isAlive) { self.spawnedAt = Date.now(); self.isAlive = true; } }); element = document.querySelector('.bottom-dashboard-box img[title=Respawn]'); element.addEventListener('click', function() { self.spawnedAt = Date.now(); self.isAlive = true; }); element = document.getElementById('advertContinue'); element.addEventListener('click', function() { self.isAlive = false; }); window.addEventListener('keydown', function (event) { if (self.hotkeys && event.keyCode == self.hotkeys.M.c && ! self.isWritingText()) { self.spawnedAt = Date.now(); self.isAlive = true; } }); window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/alive' || commandEvent.command === 'alive') { var minutes = parseInt((Date.now() - self.spawnedAt) / 1000 / 60); if (minutes < 1) { minutes = parseInt((Date.now() - self.spawnedAt) / 1000) + ' Seconds & 0'; } if (minutes > 60) { minutes = parseInt(minutes / 60) + ' Hours & ' + (minutes % 60); } if (! self.isAlive || document.getElementById('advert').style.display !== 'none') { if (isNaN(minutes)) { self.prettyMsg('is not alive โ˜ ๏ธ'); } else { self.prettyMsg('is not alive but spawned ' + minutes + ' Minutes ago'); } } else { self.prettyMsg('has been alive for ' + minutes + ' Minutes'); } } }); }, guessing: function() { var self = this; var guessItem = null; var startedAt = null; var timeout = null; var roundLength = 60 * 1000; var library = [ // LMAO.... go away, no cheating please! ๐Ÿ™„ ['๐ŸŒž๐ŸŒผ', 'Sunflower', 1], ['๐ŸŒง๏ธ๐Ÿน', 'Rainbow', 1], ['๐ŸŒง๏ธ๐Ÿ“…', 'Rainy day', 3], ['โ„๏ธ๐Ÿ‘‘', 'Ice Queen', 3], ['๐Ÿฆถโšฝ', 'Football', 1], ['๐ŸŒ™๐Ÿ’ก', 'Moonlight', 2], ['๐ŸŒž๐Ÿ’ก', 'Sunlight', 2], ['๐Ÿ˜ฑ๐ŸŽฅ', 'Horror movie', 3], ['๐Ÿ‘จ๐Ÿบ', 'Werewolf', 2], ['๐Ÿฎ๐Ÿ‘ฆ', 'Cowboy', 1], ['๐ŸŒŒ๐Ÿšข', 'Spaceship', 2], ['๐Ÿ”ฅ๐Ÿ‘จ', 'Fireman', 2], ['๐Ÿ”ฅโš”๏ธ', 'Firefighter', 2], ['๐Ÿ”ต๐Ÿ“', 'Blueberry', 3], ['๐Ÿ”ฅ๐Ÿถ', 'Hotdog', 2], ['๐Ÿ“น๐ŸŽฎ', 'Video game', 4], ['โญ•๐Ÿ’บ', 'Wheelchair', 3], ['๐ŸŒš๐Ÿšถ', 'Moonwalk', 3], ['๐Ÿ”’๐Ÿ ', 'Secret room', 4], ['๐Ÿ”ด๐Ÿฆ ', 'Mothercell', 5], ['๐Ÿ“บ๐Ÿ‘จ', 'YouTuber', 3], ['๐Ÿšถ๐Ÿ’€', 'Walking Dead', 3], ['๐Ÿ”ฅ๐Ÿšง', 'Fireworks', 4], ['๐Ÿงบโšฝ', 'Basketball', 2], ['๐Ÿฏ๐ŸŒ™', 'Honeymoon', 2], ['๐Ÿค—๐Ÿšข', 'Friendship', 3], ['๐Ÿ‘ช๐Ÿ’ผ', 'Teamwork', 4], ['๐Ÿง€๐Ÿ”', 'Cheeseburger', 2], ['โ„๏ธโšฝ', 'Snowball', 1], ['๐Ÿ‘‘๐Ÿ‘จ', 'Gold member', 4], ['โ„๏ธโšช', 'Snow white', 4], ['โ›ฐ๏ธ๐Ÿ’ก', 'Highlight', 4], ['๐Ÿ’€๐ŸŒ', 'Unwerworld', 4], ['๐Ÿ”ตโ˜๏ธ', 'Blue sky', 3], ['โšก๐ŸŒง๏ธ', 'Thunderstorm', 3], ['๐Ÿ”ด๐Ÿ”ด๐Ÿ”ด๐Ÿ”ด๐Ÿ”ด', 'Line split', 2], ]; window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/guess') { if (startedAt !== null && Date.now() - startedAt < roundLength) { self.message('๐Ÿšซ Wait a little longer (' + Math.ceil((roundLength - (Date.now() - startedAt)) / 1000) + ' seconds)', true); $('#chtbox').val(''); return; } guessItem = library[self.getRandomInt(0, library.length - 1)]; var hint = ''; if (guessItem[2] !== null) { hint = guessItem[1]; hint = self.fonts['monospace'](hint.charCodeAt(0)) + hint.substr(1); for (var i = 1; i < guessItem[2]; i++) { var pos = self.getRandomInt(0, hint.length); hint = hint.substr(0, pos) + self.fonts['monospace'](hint.charCodeAt(pos)) + hint.substr(pos + 1); } hint = hint.replace(/(\w)/gi, '_ '); hint = ' โ†’ ' + hint; } $('#chtbox').val('๐˜Ž๐˜ถ๐˜ฆ๐˜ด๐˜ด ๐˜ธ๐˜ฉ๐˜ข๐˜ต ๐˜ต๐˜ฉ๐˜ช๐˜ด ๐˜ช๐˜ด: ' + guessItem[0] + hint); startedAt = Date.now(); timeout = setTimeout(function() { self.message('Guessing game ended without a winner. The word was: "' + guessItem[1] + '"'); self.swal('Miracle Guessing Game', 'Guessing game ended without a winner. The word was: "' + guessItem[1] + '"'); }, roundLength); } }); window.addEventListener('miracleChatMessage', function(messageEvent) { if (startedAt !== null && Date.now() - startedAt <= roundLength) { if (messageEvent.message.toLowerCase().trim().replace(/\s/g, '') === ':' + guessItem[1].toLowerCase()) { $('#chtbox').val('๐˜Ž๐˜ถ๐˜ฆ๐˜ด๐˜ด๐˜ช๐˜ฏ๐˜จ ๐˜จ๐˜ข๐˜ฎ๐˜ฆ ๐˜ธ๐˜ฐ๐˜ฏ ๐˜ฃ๐˜บ ๐˜ฑ๐˜ญ๐˜ข๐˜บ๐˜ฆ๐˜ณ ' + messageEvent.nickname); self.message('Guessing game won by player "' + messageEvent.nickname + '"!'); self.swal('Miracle Guessing Game', 'Guessing game won by "' + messageEvent.nickname + '"!'); startedAt = null; clearTimeout(timeout); } } }); }, nameColor: function() { var self = this; var nickname; var profile = null; var updateData = function() { nickname = ' ' + $('#nick').val() + ' '; var accountName = self.getAccountName(); if (accountName) { profile = self.profiles[accountName]; } } $('#playBtn').click(updateData); var originalStrokeText = CanvasRenderingContext2D.prototype.strokeText; CanvasRenderingContext2D.prototype.strokeText = function(text, x, y, maxWidth) { if (profile) { if (profile.nickNameStrokeColor && text === nickname) { this.strokeStyle = profile.nickNameStrokeColor; if (profile.nickNameStrokeWidth) { this.lineWidth = profile.nickNameStrokeWidth; } } } else { if (self.settings.useNickNameStrokeColor && text === nickname) { this.strokeStyle = self.settings.nickNameStrokeColor; if (self.settings.useNickNameStrokeWidth) { this.lineWidth = self.settings.nickNameStrokeWidth; } } } return originalStrokeText.apply(this, arguments); } var originalFillText = CanvasRenderingContext2D.prototype.fillText; CanvasRenderingContext2D.prototype.fillText = function(text, x, y, maxWidth) { if (profile) { if (profile && profile.nickNameColor && text === nickname) { this.fillStyle = profile.nickNameColor; } } else { if (self.settings.useNickNameColor && text === nickname) { this.fillStyle = self.settings.nickNameColor; } } return originalFillText.apply(this, arguments); } // Legacy info window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/namecolor' || commandEvent.command === '/colorname' || commandEvent.command === '/colorchange') { self.message('๐Ÿšซ Changing the name color is no longer possible as there is a server-side fix', true); $('#chtbox').val(''); } }); }, wearablesToggle: function() { var self = this; // Note: Doesn't get updated, so we can only use it to init var checked = document.getElementById('cWearables').checked; window.addEventListener('keydown', function () { // Ignore text input field so typing in them is possible if (self.isWritingText()) { return; } if (event.keyCode == self.settings.bindings.wearables) { checked = ! checked; window.setWearables(checked); } }); }, keyboardLayout: function() { if (this.settings.showKeyboardLayout && this.hotkeys) { var $element = $('
' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
Split:   ' + this.hotkeys.Space.d + '
Double Split: ' + this.hotkeys.D.d + '
Triple Split: ' + this.hotkeys.T.d + '
Macro Split: ' + this.hotkeys.Z.d + '
Ultra Split: ' + this.keyboardMap[this.settings.bindings.ultraSplit] + '
Feed: ' + this.hotkeys.W360.d + '
Respawn: ' + this.hotkeys.M.d + '
Recombine: ' + this.hotkeys.E.d + '
2x Speed: ' + this.hotkeys.S.d + '
Freeze Self: ' + this.hotkeys.F.d + '
Invisibility: ' + this.hotkeys.I.d + '
Toggle Camera: ' + this.hotkeys.Q.d + '
'); $element.insertAfter($('#leaderboard')); } }, nameCopier: function() { var $copyNameItem = $('
  • Copy Name To Chat

  • '); $copyNameItem.insertAfter('#contextSpectate'); var showNoPlayerSelectedMessage = function (message, isError) { var curser = document.querySelector('#curser'); curser.textContent = message; curser.style.display = 'block'; curser.style.color = isError ? 'rgb(255, 0, 0)' : 'rgb(255, 0, 0)'; window.setTimeout(function () { curser.style.display = 'none'; }, 5000); } $copyNameItem.click(function() { if ($('#contextPlayerName').text().trim() === '(no player selected)'){ showNoPlayerSelectedMessage('You didn\'t select a player!'); }else{ $('#chtbox').val($('#chtbox').val() + $('#contextPlayerName').text().trim()).focus(); $('#settingsBtn').click(); setTimeout(function(){$('#settingsBtn').click();},20);} }); }, skinApplier: function() { var self = this; var $useWearablesItem = $('
  • Use Player\'s Wearables

  • '); $useWearablesItem.insertAfter('#contextPlayer'); var $useSkinItem = $('
  • Use Player\'s Skin

  • '); $useSkinItem.insertAfter('#contextPlayer'); $useSkinItem.click(function() { var skinUrl = self.getSkinUrl('#contextPlayerSkin'); if (skinUrl === null) { self.message('This player does not use a skin or no player selected ๐Ÿšซ', true); } else { var skinId = parseInt(skinUrl.substr(22)); // Cut off "https://agma.io/skins/" self.useSkin(skinId); } }); $useWearablesItem.click(function() { var wearables = [ self.extractWearableId($('#contextPlayerWear1').attr('style')), self.extractWearableId($('#contextPlayerWear2').attr('style')), self.extractWearableId($('#contextPlayerWear3').attr('style')), self.extractWearableId($('#contextPlayerWear4').attr('style')), self.extractWearableId($('#contextPlayerWear5').attr('style')), ]; self.useWearables(wearables); }); }, useWearables: function(wearables, dropCurrent) { var self = this; if (dropCurrent === undefined) { dropCurrent = true; } window.azad(true); setTimeout(function () { $('#skinExampleMenu').click(); setTimeout(function () { $('#wearablesTab a').click() setTimeout(function () { // First remove all current wearables if (dropCurrent) { var oldWearables = [ self.extractWearableId($('#wearExampleShop1').attr('style')), self.extractWearableId($('#wearExampleShop2').attr('style')), self.extractWearableId($('#wearExampleShop3').attr('style')), self.extractWearableId($('#wearExampleShop4').attr('style')), self.extractWearableId($('#wearExampleShop5').attr('style')), ] oldWearables.forEach(function(id) { //toggleWearable(id, 0, 0, 0, false); $('#wearableUseBtn' + id).click(); }); } // Use new wearables wearables.forEach(function(id) { $('#wearableUseBtn' + id).click(); }); setTimeout(function () { $('#shopModalDialog button.close').click(); setTimeout(function () { window.setNick(document.getElementById('nick').value); }, 200); }, 200); }, 1000); }, 200); }, 200); }, extractWearableId: function(style) { if (style === undefined) { return null; } var pos = style.indexOf('background-image: url("wearables/'); if (pos === -1) { return null; } return parseInt(style.substr(pos + 33)); }, help: function() { $('body').append(''); var $modal = $(''); $modal.append('

    Miracle Scripts Help

    '); var helpText = '
    These chat commands are available. Click on a command to use it!

    ' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
    CommandDescription
    /commandsShow this command help
    /versionShow Miracle version info
    /miraclesShow the number of miracle installs
    /miraclesettingsShow the miracle settings page
    /playersDisplay how many players are online
    /skin<n>Change to skin <n> (1-20), e.g.: /skin1
    /skin<n> thisStore current skin as skin , e.g.: /skin1 this
    /skin<n> <id>Store skin with ID <id> as skin <n> (1-20)
    /skinidSend a chat message with your skin ID
    /useskin <id>Use skin with the given ID
    /chatlogShow the extended chat log
    /say <text>Send a chat message with a fancy font
    /say<n> <text>Send chat message with fancy font number <n> (1-7)
    /shout <text>Purchase a megaphone shout for 20000 coins
    /pasteShow the emojis and text paste page
    /timer <n>Set timer for <n> minutes
    /timer <n> hSet timer for <n> hours
    /timer stopStop the timer
    /massSend a chat message with your current mass
    /topmassSend a chat message with your top mass in this sesssion
    /xpSend a chat message with your level and next level\'s progress
    /powerupsSend a chat message with your powerup amounts
    /fpsSend a chat message with current fps
    /pingSend a chat message with current ping
    /onlineFor how long are you online in the current session?
    /aliveFor how long are you alive?
    /soloShow the solo server message
    /diceRoll a die with 6 sides
    /dice <n>Roll a die with <n> sides
    /guessStart a guessing chat game
    /linesplitLet your cell make a linesplit
    /wasteWaste all your mass
    /danceLet your cell dance
    /haltLet your cells stop moving
    ' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '' + '
    CommandDescription
    /helpGet help by the Agma support team
    /claimClaim your daily coins
    /coinsSend a chat message with your coins
    /levelSend a chat message with your account level
    /rankSend a chat message with your account rank
    /hoursSend a chat message with the time you played
    /shakeLet your cells shake!
    /flipLet your cells flip!
    /spinLet your cells spin!
    /jumpLet your cells jump!
    /wackyYour cells will be laughing faces!
    /statsShow your battle royale stats
    /party <message>Write a message to your party
    /pm <account>Write a message to a given account
    '; $modal.append(helpText); $modal.append($('
    Close').click(function () { $modal.hide(); })); $('body').append($modal); this.$helpModal = $modal; $('#miracle-help-table table tr').click(function() { var cmd = $(this).find('code').text(); $('#chtbox').val($('#chtbox').val() + cmd).focus(); $modal.hide(); }); var $helpButton = $('
    ').click(function() { $modal.show(); }); if (this.settings.overwriteHelp) { $('#commandsBtn').css('display', 'none'); // Hide Agma's vanilla help button $helpButton.insertAfter('#emojiBtn'); $('body').append(``); // Ensure help icon does not overlap powerups } window.addEventListener('miracleCommand', function(commandEvent) { if (commandEvent.command === '/cmds' || commandEvent.command === '/commands' || commandEvent.command === '/info' || commandEvent.command === '/miraclehelp') { $('#chtbox').val('').focus(); $modal.show(); } }); }, commands: function () { var self = this; var minutes, skinId; var sessionStartedAt = Date.now(); $('#chtbox').keydown(function (event) { if (event.keyCode === 13) { var message = $('#chtbox').val(); var command = message.split(' ')[0]; var argument1 = message.split(' ')[1]; var argument2 = message.split(' ')[2]; if (message === 'time' || command === '/time' || command === '/localtime') { var now = new Date(); $('#chtbox').val(self.pretty('Local time: ' + now.toLocaleString()) + self.watermark).focus(); } if (message === 'minutes' || command === '/minutes' || message === 'online' || command === '/online' || command === '/session') { if (message === 'minutes' || command === '/minutes') { self.message('โ›” The /minutes command is deprecated, please use /online instead.', true); } minutes = parseInt((Date.now() - sessionStartedAt) / 1000 / 60); if (minutes < 1) { minutes = parseInt((Date.now() - sessionStartedAt) / 1000) + ' Seconds & 0'; } if (minutes > 60) { minutes = parseInt(minutes / 60) + ' Hours & ' + (minutes % 60); } $('#chtbox').val(self.pretty('is online for: ' + minutes + ' Minutes in the session') + self.watermark).focus(); } if (command === '/claim') { // Player used claim command so store that so that Miracle doesnt suggest to use it during cool down // Use timeout to wait for curser rendering the message window.setTimeout(function() { // Check if the client got the success message to be sure they actually claimed coins: if ($('#curser').text().indexOf('free coins today, remember to /claim') !== -1) { self.settings.coinsClaimedAt = Date.now(); console.log('#3 coins claimed at: ' + self.settings.coinsClaimedAt); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); } // If the client got a fail message update the timer: if ($('#curser').text().indexOf('You have already claimed your reward today.') !== -1) { let regEx = /You can claim your reward again in (\d+) hour/; let matches = $('#curser').text().match(regEx); if (matches[1]) { // 25 instead of 24 because we ingore the remaining minutes, so we just add a complete hour instead self.settings.coinsClaimedAt = Date.now() - (25 - parseInt(matches[1])); console.log('#4 coins claimed at: ' + self.settings.coinsClaimedAt); localStorage.setItem('miracleScripts', JSON.stringify(self.settings)); } } }, 1000); // 1000 ms cuz of ping because the server needs to respond } if (command === '/solo' || command === '/noteam') { $('#chtbox').val(':warning: SOLO SERVER :warning: No teaming!! No hay equipo!! Pas d\'รฉquipe!! Kein Teaming!! ู„ุง ูุฑูŠู‚').focus(); } if (command === '/miracle' || command === '/version') { var miracleInfo = 'uses ๐˜”๐˜ช๐˜ณ๐˜ข๐˜ค๐˜ญ๐˜ฆ ๐˜š๐˜ค๐˜ณ๐˜ช๐˜ฑ๐˜ต๐˜ด'; if (GM_info) { miracleInfo += ' ' + GM_info.script.version; } var extra = 'Install for free!'; //if (self.getRandomInt(1, 2) === 1) { //extra = ''; //} $('#chtbox').val(miracleInfo + '. ' + extra + self.watermark).focus(); } if (command === '/samira') { $('#chtbox').val('Samira (inaaa) is the initiator of ๐˜”๐˜ช๐˜ณ๐˜ข๐˜ค๐˜ญ๐˜ฆ ๐˜š๐˜ค๐˜ณ๐˜ช๐˜ฑ๐˜ต๐˜ด' + self.watermark).focus(); } if (command === '/miracles') { $('#chtbox').val('๐˜”๐˜ช๐˜ณ๐˜ข๐˜ค๐˜ญ๐˜ฆ ๐˜š๐˜ค๐˜ณ๐˜ช๐˜ฑ๐˜ต๐˜ด has about 12,000 installs so far!' + self.watermark).focus(); } if (command === '/skinid' || command === '/sayskin') { var skinUri = self.getSkinUrl(); skinId = parseInt(skinUri.substr(skinUri.indexOf('skins/') + 6)); if (skinId > 0) { self.prettyMsg('uses the skin with the ID ' + skinId); } else { self.prettyMsg('does not use a skin'); } return; } if (command === '/useskin') { skinId = parseInt(argument1); if (! (skinId > 0)) { self.message('Invalid skin ID given. Example usage of command: /useskin 123', true); } else { self.useSkin(skinId); } $('#chtbox').val(''); } if (command.substr(0, 4) === '/say' || (command === '/party' && argument1.substr(0, 4) === '/say') || (command === '/pm' && argument2.substr(0, 4) === '/say')) { var prefix = ''; if (command === '/party' && argument1.substr(0, 4) === '/say') { prefix = '/party '; message = message.substr(7); } if (command === '/pm' && argument2.substr(0, 4) === '/say') { var spacePos = message.indexOf(' ', 5); prefix = message.substr(0, spacePos + 1); message = message.substr(spacePos + 1); } var fontIndex = message.charAt(4) - 1; if (Number.isNaN(fontIndex)|| fontIndex < 0 || fontIndex > Object.getOwnPropertyNames(self.fonts).length - 1) { fontIndex = 1; } var badWords = self.badWords.join('|'); var regExp = new RegExp(badWords, 'gi'); message = message.replace(regExp, '****'); $('#chtbox').val(prefix + self.useUnicodeFont(message.substr(message.indexOf(' ') + 1), Object.getOwnPropertyNames(self.fonts)[fontIndex])).focus(); } if (command === '/dice') { var max = (argument1 > 0) ? parseInt(argument1) : 6; var number = self.getRandomInt(1, max); self.prettyMsg('rolled a die with ' + max + ' sides. Result: ' + number); } if (command === '/powerups' || command === '/powers' || command === '/has') { var map = { invRecombine: 'recombine', invSpeed: 'speed', invGrowth: 'growth', invSpawnVirus: 'virus', invSpawnMothercell: 'red virus', invSpawnPortal: 'portal', invSpawnGoldOre: 'gold block', invFreeze: 'freeze', inv360Shot: 'push', invWall: 'wall', invAntiFreeze: 'nofreeze', invAntiRecombine: 'anti-rec', invFrozenVirus: 'frozen virus', invShield: 'shield', } var getPowerUps = function(map, shortNames) { var ids = Object.keys(map); var amount; var powerups = ''; var powerUpName; for (var i = 0; i < ids.length; i++) { // Note: If the amount of a power-ups is 1, no number will be displayed. amount = $('#' + ids[i] + ' p').text() || ($('#' + ids[i]).css('display') === 'none' ? 0 : 1); if (amount > 0) { if (powerups != '') { powerups += ', '; } powerUpName = map[ids[i]]; if (shortNames) { powerUpName = powerUpName.substr(0, 3); } powerups += amount + ' ' + powerUpName; } } return powerups; } var powerups = getPowerUps(map, false); if (powerups.length >= 95) { powerups = getPowerUps(map, true); } if (powerups === '') { powerups = 'no power-ups'; } $('#chtbox').val(self.watermark + self.pretty('has ') + powerups); // Note: Dont use unicode fotn on all because this uses more characters than usually! } if (command === '/mass') { self.prettyMsg('has this mass: ' + self.mass); } if (command === '/topmass') { self.prettyMsg('has this top mass: ' + self.topMass); } if (command === '/xp' || command === '/progress') { var xp = parseInt($('.xpBarTop span').text()); var text = 'โ–ˆ'.repeat(xp / 10) + 'โ–’'.repeat(10 - parseInt(xp / 10)) + ' ' + xp + '%'; self.prettyMsg('is currently level ' + $('#level2').text() + ' with ' + text + ' of the next level'); } if (command === '/megaphone' || command === '/megashout' || command === '/shout') { // Notes: 1-7 = colors. The shout message can have max 130 chars, but chat messages can be only 100(?) chars long so np self.warnBeforeMegaShout(message.substr(message.indexOf(' ') + 1), self.getRandomInt(1, 7)); $('#chtbox').val(''); } if (command === '/players') { var gameservers = JSON.parse(localStorage.getItem('gameservers')); var players = 0; var current = null; gameservers.forEach(function(gameserver) { players += gameserver.players; if (gameserver.isCurrent) { current = gameserver.players + '/' + gameserver.maxPlayers; } }); self.prettyMsg('Players online in Agma: ' + players); if (current !== null) { $('#chtbox').val($('#chtbox').val() + self.pretty(' - current server: ' + current)); } } if (command === '/wearable') { $('#chtbox').val(''); if (argument1) { argument1 = message.substr(10).toLowerCase().trim(); var wIds = Object.keys(self.wearables); var foundWearable = null; wIds.forEach(function(wId) { if (self.wearables[wId].toLowerCase() === argument1) { foundWearable = wId; } }); if (! foundWearable) { wIds.forEach(function(wId) { if (self.wearables[wId].toLowerCase().indexOf(argument1) !== -1) { foundWearable = wId; } }); } if (foundWearable) { self.useWearables([foundWearable], false); } else { var candidates = []; wIds.forEach(function(wId) { if (self.wearables[wId].toLowerCase().substr(0, 1) === argument1.substr(0, 1)) { candidates.push(self.wearables[wId]); } }); if (candidates.length > 0) { self.swal('Not found', 'Not found. Try one of these: "' + candidates.join('" , "') + '"'); } else { self.swal('Not found', 'Sorry, but I\'m lost. I cannot find this wearable.'); } } } else { self.swal('Missing Argument', 'You need to specify the name of a wearable.'); } } var commandEvent = new Event('miracleCommand'); commandEvent.message = message; commandEvent.command = command; commandEvent.argument1 = argument1; commandEvent.argument2 = argument2; window.dispatchEvent(commandEvent); } }); }, /** * This object is a container for functions that convert english letters and digits to fancy Unicode characters * @see https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols * @see https://en.wikipedia.org/wiki/Enclosed_Alphanumerics * @see https://en.wikipedia.org/wiki/Enclosed_Alphanumeric_Supplement */ fonts: { doubleStruck : function(charCode) { if (charCode === 67) { return String.fromCodePoint(0x2102); } // C if (charCode === 72) { return String.fromCodePoint(0x210D); } // H if (charCode === 78) { return String.fromCodePoint(0x2115); } // N if (charCode === 80) { return String.fromCodePoint(0x2119); } // P if (charCode === 81) { return String.fromCodePoint(0x211A); } // Q if (charCode === 82) { return String.fromCodePoint(0x211D); } // R if (charCode === 90) { return String.fromCodePoint(0x2124); } // Z if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x1D538 + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x1D552 + charCode - 97); } if (charCode >= 48 && charCode <= 57) { return String.fromCodePoint(0x1D7D8 + charCode - 48); } return String.fromCharCode(charCode); }, monospace : function(charCode) { if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x1D670 + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x1D68A + charCode - 97); } if (charCode >= 48 && charCode <= 57) { return String.fromCodePoint(0x1D7F6 + charCode - 48); } return String.fromCharCode(charCode); }, scriptBold : function(charCode) { if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x1D4D0 + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x1D4EA + charCode - 97); } if (charCode >= 48 && charCode <= 57) { return String.fromCodePoint(0x1D7CE + charCode - 48); } return String.fromCharCode(charCode); }, frakturBold : function(charCode) { if (charCode === 121) { return '๐ฒ'; } // y if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x1D56C + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x1D586 + charCode - 97); } if (charCode >= 48 && charCode <= 57) { return String.fromCodePoint(0x1D7CE + charCode - 48); } return String.fromCharCode(charCode); }, serifItalic: function(charCode) { if (charCode === 104) { return String.fromCodePoint(0x1D629); } // h if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x1D434 + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x1D44E + charCode - 97); } return String.fromCharCode(charCode); }, circled: function(charCode) { if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x24B6 + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x24D0 + charCode - 97); } if (charCode >= 49 && charCode <= 57) { return String.fromCodePoint(0x2460 + charCode - 49); } return String.fromCharCode(charCode); }, boxed: function(charCode) { if (charCode >= 65 && charCode <= 90) { return String.fromCodePoint(0x1F130 + charCode - 65); } if (charCode >= 97 && charCode <= 122) { return String.fromCodePoint(0x1F130 + charCode - 97); } if (charCode >= 49 && charCode <= 57) { return String.fromCodePoint(0x2460 + charCode - 49); } return String.fromCharCode(charCode); } }, pretty: function(text) { return this.useUnicodeFont(text, 'serifItalic'); }, prettyMsg: function(text) { $('#chtbox').val(this.pretty(text) + this.watermark); }, /** * Apply a unicode "font" on given text */ useUnicodeFont: function(text, font) { var regexResults, emojiPositions = [], emojiRegex = /:\w+:/g; while ((regexResults = emojiRegex.exec(text)) !== null) { emojiPositions.push(regexResults.index); } var converted = '', convert = true; for (var i = 0; i < text.length; i++) { if (! convert && text.charAt(i) === ':') { convert = true; } if (emojiPositions.indexOf(i) !== -1) { convert = false; } if (convert) { converted += this.fonts[font](text.charCodeAt(i)); } else { converted += text.charAt(i); } } return converted; }, /** * True if currently a HTML text element is focused */ isWritingText: function() { return document.activeElement.type === 'text' || document.activeElement.type === 'password' || document.activeElement.type === 'textarea'; }, /** * Let the browser download string data as a text file with a given filename. */ download: function (filename, text) { var element = document.createElement('a'); element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text)); element.setAttribute('download', filename); element.style.display = 'none'; document.body.appendChild(element); element.click(); document.body.removeChild(element); }, /** * Converts a version string (for example "1.5.7") to an integer (for example 1005007) * If no string version is given, the current version of the script will be used. */ getVersionAsInt: function(stringVersion) { if (stringVersion === undefined) { stringVersion = typeof GM_info !== 'undefined' ? GM_info.script.version : '0'; } var parts = stringVersion.split('.'); if (parts.length === 1) { parts.push('0'); } if (parts.length === 2) { parts.push('0'); } return parseInt(parts[0]) * 1000000 + parseInt(parts[1]) * 1000 + parseInt(parts[2]); }, /** * Returns a random number between min and max (both inclusive) * Source: MDN */ getRandomInt: function (min, max) { return Math.round(Math.random() * (max - min) + min); }, /** * Returns the 360-angle between two points 8coordinates), starting by the first point. * 0ยฐ means the second point is in the north of the first point. * The returned angle will always be >= 0 and < 360. */ getAngle: function(x1, y1, x2, y2) { var angle = Math.atan2(y2 - y1, x2 - x1); // range (-PI, PI] angle *= 180 / Math.PI; // rads to degs, range (-180, 180] angle += 90; if (angle < 0) angle = 360 + angle; // range [0, 360) if (angle >= 360) angle = 360 - angle; // range [0, 360) return angle; }, /** * Adds angle2 to angle1 and returns the resulting angle. */ addAngle: function(angle1, angle2) { var angle = angle1 + angle2; angle %= 360; if (angle < 0) angle += 360; return angle; }, /** * Use the curser div to display a message at the top of the screen. * * @param message * @param isError */ message: function (message, isError, fontSize) { var curser = document.querySelector('#curser'); curser.textContent = message; curser.style.display = 'block'; curser.style.color = isError ? 'rgb(255, 0, 0)' : 'rgb(0, 192, 0)'; if (fontSize > 0) { curser.style.fontSize = fontSize + 'px'; } window.setTimeout(function () { curser.style.display = 'none'; }, 5000); }, /** * Show a sweet alert (modal/popup) with a given title and message. */ swal: function (title, message, html) { if (html === undefined) { html = true; } window.swal({ title: '๐Ÿ“ข ' + title + '', text: message, html: html }); }, /** * Returns the URI of my skin or null if not skin has been set. * Use this.skinUrl() to get it. */ getSkinUrl: function(sourceSelector) { if (sourceSelector === undefined) { sourceSelector = '#skinExampleMenu'; } var skinUrlRaw = $(sourceSelector).css('background-image'); var parts = skinUrlRaw.split('"'); if (parts.length !== 3) { return null; } else { return parts[1]; } }, getAccountName: function() { // First make sure we are logged in if (document.getElementById('dashPanel').style.display !== 'none') { // We have to use trim() or else the name might contain new lines return document.querySelector('#dashPanel .username').innerText.trim(); } else { return null; } }, /** * Tries to pick a skin that is identified by its skin ID. * Opens the skin menu, chooses the skin, and closes the menu again. * The skin must be available for the current player (e.g. because it's a public one). */ useSkin: function(skinId) { window.azad(true); setTimeout(function () { $('#skinExampleMenu').click(); var checkLoaded = function () { var loaded = ($('#skinsFree tr').length > 1); if (loaded) { window.toggleSkin(skinId); setTimeout(function () { $('#shopModalDialog button.close').click(); setTimeout(function () { window.setNick(document.getElementById('nick').value); }, 200); }, 200); } else { setTimeout(checkLoaded, 300); } }; checkLoaded(); }, 200); }, /** * Legal Disclaimer: This is an original Agma function but the original is not accessible - so this is a copy. * Copyright (C) Agma.io - do only use together with Miracle on Agma.io. */ warnBeforeMegaShout: function(msg, color) { swal({ title: "Confirm", text: 'If you click "Buy", you will purchase the megaphone shout.', type: "warning", showCancelButton: true, confirmButtonColor: "#4CAF50", confirmButtonText: "Yes, confirm purchase", cancelButtonText: "No, cancel purchase" }, function() { purchaseMega(msg,color); }); }, setupPolyfills: function() { // Polyfill for old browser so they have String.fromCodePoint() if (!String.fromCodePoint) (function(stringFromCharCode) { var fromCodePoint = function(_) { var codeUnits = [], codeLen = 0, result = ""; for (var index=0, len = arguments.length; index !== len; ++index) { var codePoint = +arguments[index]; // correctly handles all cases including `NaN`, `-Infinity`, `+Infinity` // The surrounding `!(...)` is required to correctly handle `NaN` cases // The (codePoint>>>0) === codePoint clause handles decimals and negatives if (!(codePoint < 0x10FFFF && (codePoint>>>0) === codePoint)) throw RangeError("Invalid code point: " + codePoint); if (codePoint <= 0xFFFF) { // BMP code point codeLen = codeUnits.push(codePoint); } else { // Astral code point; split in surrogate halves // https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae codePoint -= 0x10000; codeLen = codeUnits.push( (codePoint >> 10) + 0xD800, // highSurrogate (codePoint % 0x400) + 0xDC00 // lowSurrogate ); } if (codeLen >= 0x3fff) { result += stringFromCharCode.apply(null, codeUnits); codeUnits.length = 0; } } return result + stringFromCharCode.apply(null, codeUnits); }; try { // IE 8 only supports `Object.defineProperty` on DOM elements Object.defineProperty(String, "fromCodePoint", { "value": fromCodePoint, "configurable": true, "writable": true }); } catch(e) { String.fromCodePoint = fromCodePoint; } }(String.fromCharCode)); }, }; window.miracleScripts.init(); })();