// ==UserScript== // @name fsfb script // @namespace http://tampermonkey.net/ // @homepage https://greasyfork.org/scripts/446564/ // @version 1.6.2 // @description An agma.io script, which includes fastsplit, secret bot packs, linesplit lock, and many other amazing features! // @author fishy & firebone // @match *://agma.io/* // @icon data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c3ZnIGlkPSJhIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgNTE1IDUxNSI+PGRlZnM+PHJhZGlhbEdyYWRpZW50IGlkPSJiIiBjeD0iMjg2LjgiIGN5PSIxMDYiIGZ4PSIyODYuOCIgZnk9IjEwNiIgcj0iMTEzLjI4NCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2VmNDYzMCIvPjxzdG9wIG9mZnNldD0iLjEyNSIgc3RvcC1jb2xvcj0iI2VjNGUzMSIvPjxzdG9wIG9mZnNldD0iLjI1IiBzdG9wLWNvbG9yPSIjZTk1ZDM1Ii8+PHN0b3Agb2Zmc2V0PSIuNTIxIiBzdG9wLWNvbG9yPSIjZTk4MjM2Ii8+PHN0b3Agb2Zmc2V0PSIuOSIgc3RvcC1jb2xvcj0iI2ZjYzczOSIvPjxzdG9wIG9mZnNldD0iLjk4MSIgc3RvcC1jb2xvcj0iI2YxZDIzNSIvPjwvcmFkaWFsR3JhZGllbnQ+PHJhZGlhbEdyYWRpZW50IGlkPSJjIiBjeD0iMzIxLjIiIGN5PSIxMzMuMiIgZng9IjMyMS4yIiBmeT0iMTMzLjIiIHI9IjM5LjUyNSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2U3NDQyZSIvPjxzdG9wIG9mZnNldD0iLjEyNSIgc3RvcC1jb2xvcj0iI2U1NGMyZiIvPjxzdG9wIG9mZnNldD0iLjI1IiBzdG9wLWNvbG9yPSIjZTM1YjMzIi8+PHN0b3Agb2Zmc2V0PSIuNTIxIiBzdG9wLWNvbG9yPSIjZTk4MjM2Ii8+PHN0b3Agb2Zmc2V0PSIuOSIgc3RvcC1jb2xvcj0iI2ZjYzczOSIvPjxzdG9wIG9mZnNldD0iLjk4MSIgc3RvcC1jb2xvcj0iI2ZjYzg0OSIvPjwvcmFkaWFsR3JhZGllbnQ+PGxpbmVhckdyYWRpZW50IGlkPSJkIiB4MT0iMTg4LjE0NiIgeTE9IjIzMi41NDYiIHgyPSIxNTMuNDc5IiB5Mj0iMjU3LjA3OSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iI2UzNDIyZSIvPjxzdG9wIG9mZnNldD0iLjExNyIgc3RvcC1jb2xvcj0iI2UyNGEyZiIvPjxzdG9wIG9mZnNldD0iLjI1IiBzdG9wLWNvbG9yPSIjZTI1YjMzIi8+PHN0b3Agb2Zmc2V0PSIuNTIxIiBzdG9wLWNvbG9yPSIjZTk4MjM2Ii8+PHN0b3Agb2Zmc2V0PSIuOSIgc3RvcC1jb2xvcj0iI2ZjYzczOSIvPjxzdG9wIG9mZnNldD0iLjk4MSIgc3RvcC1jb2xvcj0iI2ZjYzg0OSIvPjwvbGluZWFyR3JhZGllbnQ+PHJhZGlhbEdyYWRpZW50IGlkPSJlIiBjeD0iMTA1LjMzMyIgY3k9IjI2Ni42NjciIGZ4PSIxMDUuMzMzIiBmeT0iMjY2LjY2NyIgcj0iMjcwLjMwNCIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjExIiBzdG9wLWNvbG9yPSIjZmNjODQ5Ii8+PHN0b3Agb2Zmc2V0PSIuMTE0IiBzdG9wLWNvbG9yPSIjZmNjNzQ3Ii8+PHN0b3Agb2Zmc2V0PSIuMTczIiBzdG9wLWNvbG9yPSIjZmNjNzNjIi8+PHN0b3Agb2Zmc2V0PSIuMjM2IiBzdG9wLWNvbG9yPSIjZmNjNzM5Ii8+PHN0b3Agb2Zmc2V0PSIuNjEyIiBzdG9wLWNvbG9yPSIjZTk4MjM2Ii8+PHN0b3Agb2Zmc2V0PSIuNzgzIiBzdG9wLWNvbG9yPSIjZTk1ZDM1Ii8+PHN0b3Agb2Zmc2V0PSIuODgyIiBzdG9wLWNvbG9yPSIjZWU1NzM0Ii8+PHN0b3Agb2Zmc2V0PSIuODg2IiBzdG9wLWNvbG9yPSIjZWM1NjMzIi8+PHN0b3Agb2Zmc2V0PSIuOTE2IiBzdG9wLWNvbG9yPSIjZTU1MjJmIi8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZTQ1MTJlIi8+PC9yYWRpYWxHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9ImYiIGN4PSIzNzAiIGN5PSIzMTIuMTMzIiBmeD0iMzcwIiBmeT0iMzEyLjEzMyIgcj0iMzguOTQyIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZDk0MDJiIi8+PHN0b3Agb2Zmc2V0PSIuMTE3IiBzdG9wLWNvbG9yPSIjZGE0ODJkIi8+PHN0b3Agb2Zmc2V0PSIuMjUiIHN0b3AtY29sb3I9IiNkZDU5MzIiLz48c3RvcCBvZmZzZXQ9Ii41MjEiIHN0b3AtY29sb3I9IiNlOTgyMzYiLz48c3RvcCBvZmZzZXQ9Ii45IiBzdG9wLWNvbG9yPSIjZmNjNzM5Ii8+PHN0b3Agb2Zmc2V0PSIuOTgxIiBzdG9wLWNvbG9yPSIjZmNjODQ5Ii8+PC9yYWRpYWxHcmFkaWVudD48cmFkaWFsR3JhZGllbnQgaWQ9ImciIGN4PSIzODEuMiIgY3k9IjI1OCIgZng9IjM4MS4yIiBmeT0iMjU4IiByPSIxMTMuNjAzIiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZWY0NjMwIi8+PHN0b3Agb2Zmc2V0PSIuMTI1IiBzdG9wLWNvbG9yPSIjZWM0ZTMxIi8+PHN0b3Agb2Zmc2V0PSIuMjUiIHN0b3AtY29sb3I9IiNlOTVkMzUiLz48c3RvcCBvZmZzZXQ9Ii40IiBzdG9wLWNvbG9yPSIjZTk4MjM2Ii8+PHN0b3Agb2Zmc2V0PSIuNDExIiBzdG9wLWNvbG9yPSIjZTk4NDM2Ii8+PHN0b3Agb2Zmc2V0PSIuNTM2IiBzdG9wLWNvbG9yPSIjZjFhMTM3Ii8+PHN0b3Agb2Zmc2V0PSIuNjYiIHN0b3AtY29sb3I9IiNmN2I2MzgiLz48c3RvcCBvZmZzZXQ9Ii43ODIiIHN0b3AtY29sb3I9IiNmYWMyMzgiLz48c3RvcCBvZmZzZXQ9Ii45IiBzdG9wLWNvbG9yPSIjZmNjNzM5Ii8+PHN0b3Agb2Zmc2V0PSIuOTgxIiBzdG9wLWNvbG9yPSIjZmNjODQ5Ii8+PC9yYWRpYWxHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImgiIHgxPSIyNjkuOTQ0IiB5MT0iMjg3LjM0NSIgeDI9IjI2MC41MzciIHkyPSIyODkuMTE1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjN2U0NzBjIi8+PHN0b3Agb2Zmc2V0PSIuOTk2IiBzdG9wLWNvbG9yPSIjNWYyZjAwIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImkiIHgxPSIzMzkuNTU2IiB5MT0iMjMzLjgwMSIgeDI9IjMyMi4yMjIiIHkyPSIxNzEuNDY4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIwIiBzdG9wLWNvbG9yPSIjZTlhZTM1Ii8+PHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjZmVkNTczIi8+PC9saW5lYXJHcmFkaWVudD48bGluZWFyR3JhZGllbnQgaWQ9ImoiIHgxPSIyNTQuNDk3IiB5MT0iMTExLjkzNiIgeDI9IjIwMC4xNjQiIHkyPSIxODYuNjAzIiB4bGluazpocmVmPSIjaSIvPjwvZGVmcz48cmVjdCB3aWR0aD0iNTE1IiBoZWlnaHQ9IjUxNSIgcng9IjEwMCIgcnk9IjEwMCIgc3R5bGU9ImZpbGw6Izc1MmIxNjsiLz48cGF0aCBkPSJNMTUwLjYyMiw0NTkuOTU2YzAsOC41MzMsMjEyLjI2NywxMS4yLDIxMi4yNjcsMHMtMjEyLjI2Ny0xMi44LTIxMi4yNjcsMFoiIHN0eWxlPSJmaWxsOiM0ZTFmMTQ7IG9wYWNpdHk6Ljk7Ii8+PHBhdGggZD0iTTI2NS44NjcsNDYuOTMzczMzLjgwMSwxOS4zMzMsMzMuODAxLDQ1LjczM2MwLDMzLjYtMzIuMzM0LDQxLjQ2Ny01MC42MDEsNTYuNzM0LDAsMC00OS43MzMsMzkuNDY3LTM3LjczMyw5My42LDAsMC00MC4yNjctMzcuOTc5LTE1LjkxMS05MS40OSwxMi44LTM5LjY0NCw3Ni45NzgtNjMuNjQ0LDc2Ljk3OC04OC44ODksMCwwLDEuMTU2LTIuNC02LjUzMy0xNS42ODlaIiBzdHlsZT0iZmlsbDp1cmwoI2IpOyIvPjxwYXRoIGQ9Ik0zMjAuOCwxMjUuMmMxNS40LDE1LjQsMzAuMjY3LTEzLjMzMywyNy40NjctMTkuNDY3LTguNjY3LTMuMzMzLTI2LjgtNi4xMzMtMjcuNDY3LDE5LjQ2N1oiIHN0eWxlPSJmaWxsOnVybCgjYyk7Ii8+PHBhdGggZD0iTTE5Mi4zMzQsMjQ5LjczM2MtNy45MzQsMTEuODY3LTM4LjczNCwxOS4zMzMtNDYuNjAxLTguNTMzLDQuNDkxLTQuMzUsMTYuOTU3LTkuNjYxLDI3Ljg2OC05LjQxMiw5LjgyMywuMjI0LDE4LjM4NSwzLjk1MywxOC43MzMsMTcuOTQ1WiIgc3R5bGU9ImZpbGw6dXJsKCNkKTsiLz48cGF0aCBkPSJNMjI3LjcxNSwyNTMuNjhjLTEyLTczLjM3OCw1Ni4zODQtMTA2LjI1OCw5MC44MjgtMTEwLjQ4LDAsMC0zMy41MTEsMjYuNDg5LTMzLjUxMSw2My4wMjJzMzcuNiw2OC44LDM3LjYsNjguOGMwLDAsNDUuMzMzLDMzLjg2Nyw0NS4zMzMsODYuOTMzcy00Mi4zMTEsOTguMjIyLTExMS40MzMsOTguMjIyLTk2LjAzMy01MC44NDQtMTAwLjMtNjAuOTc4Yy00LjI2Ny0xMC4xMzMtMzguNzU2LTE2LTM4Ljc1Ni0xNiwwLDAsMy43MzMtMzQuMzExLDMzLjQyMi01Ni41MzMsMTcuNTExLTUwLjU1NSw1MS43MTgtNjcuOTg3LDc2LjgxNi03Mi45ODYsNi40OTktMS4yOTQsMTIuNDAyLTEuNjgsMTcuMjI4LTEuNjgsMTUuNjQ0LDMuOTExLDE4Ljg0NCw2NS44OSwxOC44NDQsNjUuODksMCwwLTMyLjcxMSwzLjc5OS00NS4zMzMtMi40MjMsOS43NzgsMTEuOTExLDQwLjg4OSwxNC43NTYsNDAuODg5LDE0Ljc1Ni0uNTMzLDIzLjExMS00MS42LDM5LjQ2Ny0zNS4yLDkzLjY4OSw2LjA0NCw5LjI0NCwzNS4wMjIsNy40NjcsMzUuMDIyLDcuNDY3LDQ0LjQ0OS03LjY1Myw0NS4zMzMtNjUuMTMzLDQuNjIyLTExMy40ODhtLTQwLjg4OS00NS4yNjdjLTUuNDQ5LDAtOS44NjcsNC40MTctOS44NjcsOS44NjdzNC40MTcsOS44NjcsOS44NjcsOS44NjcsOS44NjctNC40MTcsOS44NjctOS44NjctNC40MTctOS44NjctOS44NjctOS44NjdaIiBzdHlsZT0iZmlsbDp1cmwoI2UpOyIvPjxwYXRoIGQ9Ik0zNjUuMzMzLDMwNy4wNjdjLjEzMy0xOC44LDEzLjczMy0yNy4zMzMsMjcuNzMzLTE5LjQ2NywxLjMzMywxNi41MzMtMTguMjgxLDMyLjkzMy0yNy43MzMsMTkuNDY3WiIgc3R5bGU9ImZpbGw6dXJsKCNmKTsiLz48cGF0aCBkPSJNMzU2Ljg2NywyNzguNDY3czE2Ljk5OS04Ljg2NywxNi45OTktMjguMDY3LTE4LTM1LjItMTgtMzUuMmMwLDAtMTcuODY3LTE5LjYtMTcuODY3LTM4LjhzOC44LTMyLjgsOC44LTMyLjhjMCwwLTM5LjEyNCwxOC4wMDctMzkuODY3LDU2LjgsMCwwLTEuNiwyNS42LDE0LjUzMyw0NC4xMzMsMCwwLDI4LjEzNSwzMy45MzQsMzUuNDAxLDMzLjkzNFoiIHN0eWxlPSJmaWxsOnVybCgjZyk7Ii8+PHBhdGggZD0iTTI2My43ODgsMzE3Ljg5Yy0xLjQxNi0xNC40MDMtNC41MS01NS41NTYtMTYuNTUtNjUuMDc4LDMxLjkyOSwxMi4zNTUsMjMuMDAzLDczLjI4NCwyMy4wMDMsNzMuMjg0bC02LjQ1My04LjIwNloiIHN0eWxlPSJmaWxsOnVybCgjaCk7IG9wYWNpdHk6LjY7Ii8+PHBhdGggZD0iTTMyMi4xNjcsMzMxLjgzM2MxMi41LDI5LjgzMywxOC4zNTMsODMuODExLTM0LDEwNC44MzMsNDMuODMzLTI3Ljc3OCw0MC43NzgtODQuMjc4LDM0LTEwNC44MzNaIiBzdHlsZT0iZmlsbDojZjU4NjYzOyIvPjxwYXRoIGQ9Ik0yNzUuMjA4LDI2OS4zNjdjLTM1LjkzNC00MS4xNjYtMjQuMTExLTk1LjI3OCw0My4xNjctMTI2LjE2Ny01Ni4xNjcsMzUuNTU2LTcwLjE2Nyw2OC4zMzMtNDMuMTY3LDEyNi4xNjdaIiBzdHlsZT0iZmlsbDojZjlhMzVkOyIvPjxwYXRoIGQ9Ik0yMjQuMjA0LDQyMy44NjRsLS43MDItOC40MTlzLTM3LTE2LjY2Ny0zNy0zOGMwLDMyLjY2NywzNy43MDIsNDYuNDE5LDM3LjcwMiw0Ni40MTlaIiBzdHlsZT0iZmlsbDojZjhhYzVlOyIvPjxwYXRoIGQ9Ik0zNDMuMjIyLDIzMS42NjdjLTguNjA4LTEwLjI3Mi0zMS40NzItMzQuOTE3LTE1LjU1Ni02My40NDQtMy41ODMsMjQuOTQ0LDIuNjY3LDM5LjI3OCwxNS41NTYsNjMuNDQ0WiIgc3R5bGU9ImZpbGw6dXJsKCNpKTsiLz48cGF0aCBkPSJNMjA0LDE5MS44MzNjLTUuNS0xOC42NjcsMjYuMjUtNjIuNTgzLDQ5LjgzMy03Ny00NSw1NS41LTM5LjE2Nyw1MS4zMzMtNDkuODMzLDc3WiIgc3R5bGU9ImZpbGw6dXJsKCNqKTsiLz48L3N2Zz4= // @run-at document-start // @require https://greasyfork.org/scripts/459346-fsfb-facts/code/fsfb%20facts.js?version=1145073 // @license GPL-3.0-or-later // @connect translate.google.com // @connect greasyfork.org // @grant unsafeWindow // @grant GM_setValue // @grant GM_getValue // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant GM_unregisterMenuCommand // @downloadURL https://update.greasyfork.icu/scripts/446564/fsfb%20script.user.js // @updateURL https://update.greasyfork.icu/scripts/446564/fsfb%20script.meta.js // ==/UserScript== // ~~~~~~~~~ Don't change anything below this unless you know what you are doing ~~~~~~~~~ const version = typeof GM_info != 'undefined' && GM_info?.script?.version || '1.6.2'; let settings = { hotkeys: [ {title: "Shoot 7 Ejected", id: "fsfb-key7Feed", key: 0, active: false}, // 0 {title: "Linesplit Lock", id: "fsfb-linesplit", key: 0, active: false}, // 1 {title: "Macro Split Bots", id: "fsfb-MacroSplitBots", key: 0, active: false}, // 2 {title: "Hide UI", id: "fsfb-hideUI", key: 0, active: false}, // 3 {title: "Toggle Cursor", id: "fsfb-togglecursor", key: 0, active: false}, // 4 {title: "Check Profile", id: "fsfb-checkprofile", key: 0, active: false} // 5 ], fastsplit_hotkeys: [ {title: "Fast Onesplit", id: "fsfb-fsOne", keyName: "", keyCode: 0, active: false}, // 0 {title: "1st Delay (ms)", id: "fsfb-firstdelay", val: 60, active: false}, // 1 {title: "2nd Delay (ms)", id: "fsfb-secdelay", val: 60, active: false}, // 2 {title: "Fast Doublesplit", id: "fsfb-fsTwo", keyName: "", keyCode: 0, active: false}, // 3 {title: "1st Delay (ms)", id: "fsfb-dubfirstdelay", val: 60, active: false}, // 4 {title: "2nd Delay (ms)", id: "fsfb-dubsecdelay", val: 60, active: false}, // 5 {title: "Fast Triplesplit", id: "fsfb-fsThree", keyName: "", keyCode: 0, active: false}, // 6 {title: "1st Delay (ms)", id: "fsfb-threefirstdelay", val: 120, active: false}, // 7 {title: "2nd Delay (ms)", id: "fsfb-threesecdelay", val: 60, active: false} // 8 ], frozenvirus: [ {title: "Frozen Virus", id: "fsfb-frzvs", key: 0, active: false}, {title: "Press Delay (ms)", id: "fsfb-fvsdelay", val: 100, active: false} ], checkboxes: [ {title: "Chat Copy/Cut/Paste", id: "fsfb-copycutpaste", active: false}, // 0 {title: "Anti-AFK", id: "fsfb-antiAFK", active: false}, // 1 {title: "Anti-Invis", id: "fsfb-anticloak", active: false}, // 2 {title: "Linesplit Toggle", id: "fsfb-linetoggle", active: false}, // 3 {title: "Change Page Title", id: "fsfb-changetitle", active: false}, // 4 {title: "Hide Shouts", id: "fsfb-hideshouts", active: false}, // 5 {title: "Hold To Spam Rec/Spd", id: "fsfb-recospeed", active: false}, // 6 {title: "Show Portal Mass", id: "fsfb-portalmass", active: false}, // 7 {title: "Pow Spawns Overlay", id: "fsfb-powsoverlay", active: false}, // 8 {title: "Mothercell Mass", id: "fsfb-mtchmass", active: false}, // 9 {title: "Inventory One Row", id: "fsfb-pwsonerow", active: false}, // 10 {title: "Quick Buy", id: "fsfb-qBuy", active: false} // 11- ], slowFeed: [ {title: "Toggle Feed", id: "fsfb-slowFeed", key: 0, active: false}, {title: "Feed Delay (ms)", id: "fsfb-slowfeedtime", val: 100, active: false} ], quickSettings: [ {id: "fsfb-quick-hotkey1", id1: "fsfb-quick-select1", set: "cSkins", key: 0, active: false}, {id: "fsfb-quick-hotkey2", id1: "fsfb-quick-select2", set: "cWearables", key: 0, active: false}, {id: "fsfb-quick-hotkey3", id1: "fsfb-quick-select3", set: "cFood", key: 0, active: false}, {id: "fsfb-quick-hotkey4", id1: "fsfb-quick-select4", set: "cBubbleCells", key: 0, active: false}, {id: "fsfb-quick-hotkey5", id1: "fsfb-quick-select5", set: "cNames", key: 0, active: false}, {id: "fsfb-quick-hotkey6", id1: "fsfb-quick-select6", set: "cNameOutlines", key: 0, active: false} ], uiScaling: [ // {title: "Chat Size", id: "fsfb-chatSize", level: 5}, {title: "Inventory Size", id: "fsfb-invSize", level: 5}, // 0 {title: "Food Size", id: "fsfb-foodSize", level: 1}, // 1 {title: "Statsbox Size", id: "fsfb-statsSize", level: 5} // 2 ], theme: [ {title: "Food Color", id: "fsfb-check-foodcolor", id1: "fsfb-color-foodcolor", color: "#FFFFFF", active: false}, // 0 {title: "Virus Color", id: "fsfb-check-viruscolor", id1: "fsfb-color-viruscolor", color: "#00ff00", active: false}, // 1 {title: "Virus Stroke", id: "fsfb-check-virusstroke", id1: "fsfb-color-virusstroke", color: "#00ff00", active: false}, // 2 {title: "Mothercell Color", id: "fsfb-check-msColor", id1: "fsfb-color-msColor", color: "#cd5564", active: false}, // 3 {title: "Mothercell Stroke", id: "fsfb-check-msStroke", id1: "fsfb-color-msStroke", color: "#cd5564", active: false}, // 4 {title: "Border Color", id: "fsfb-check-border", id1: "fsfb-color-border", color: "#CC3030", active: false}, // 5 {title: "BR Hazard Zone", id: "fsfb-check-Hazard", id1: "fsfb-color-hazard", color: "#cc3030", active: false} // 6 ], theme_boxes: [ {title: "Fancy Bubble Cells", id: "fsfb-bublecell", active: false}, // 0 {title: "Show Player Mass", id: "fsfb-showmass", active: false}, // 1 {title: "Only My Skin", id: "fsfb-myskins", active: false}, // 2 {title: "Only Party Skins", id: "fsfb-partyskins", active: false}, // 3 {title: "Only My Nick", id: "fsfb-mynick", active: false}, // 4 {title: "Only Party Nicks", id: "fsfb-partynicks", active: false}, // 5 {title: "Spiked Cells", id: "fsfb-spikedcells", active: false}, // 6 {title: "Reverse Cell Order", id: "fsfb-revcell", active: false}, // 7 {title: "Render Portals Top", id: "fsfb-portalstop", active: false}, // 8 ], name_color: [ {title: "Public Name Color", id: "fsfb-nc-public", active: true}, // 0 // start with a (somewhat) random color so not everyone has the same color {title: "Name Color", id: "fsfb-box-nc", id1: "fsfb-nc-color", color: ["#22FF22", "#2299FF", "#FF9922", "#FF2222", "#000000", "#800080", "#0086b9"][~~(new Date().getHours() % 7)], active: false}, // 1 {title: "Name Stroke", id: "fsfb-box-ncs", id1: "fsfb-nc-stroke", color: ["#000000", "#000000", "#000000", "#000000", "#777777", "#f5e666", "#06ffda"][~~(new Date().getHours() % 7)], active: false} // 2 ], anti_lag: [ {title: "Hide Small Minions", id: "fsfb-hideminions", active: false}, // 0 {title: "No Minion Skins", id: "fsfb-nominionskins", active: false}, // 1 {title: "Hide All Ejected", id: "fsfb-hideejected", active: false}, // 2 {title: "Hide Static Ejected", id: "fsfb-hidestaticej", active: false}, // 3 {title: "No Eat Anims", id: "fsfb-nodeathanims", active: false} // 4 ], chat_translate: [ {title: "Translate Chat", id: "fsfb-tranchat", active: false}, // 0 {title: "Translate Server", id: "fsfb-tranplyr", active: false}, // 1 {title: "Show Original", id: "fsfb-tranorig", active: false}, // 2 {title: "Translate From:", id: "fsfb-tran1", set: "auto"}, // 3 {title: "Translate To:", id: "fsfb-tran2", set: "auto"} // 4 ], export_import: [ {title: "Game Settings", id: "fsfb-game-settings", active: false}, {title: "Game Controls", id: "fsfb-game-controls", active: false}, {title: "Custom Background", id: "fsfb-custom-bg", active: false}, {title: "Script Settings", id: "fsfb-script-settings", active: false}, {title: "Script Theme", id: "fsfb-theme-settings", active: false} ] }, misc_settings = { abil: {}, bots: {}, statsPos: null, statsSettings: { xp: { lvlcomp: true, rem: true, projhr: true, lasthr: true, lastmin: true, lastsec: true, mean: true, median: true, sd: true, sesh: true, seshlength: true, lifetime: true }, coins: { rem: true, projhr: true, lasthr: true, lastmin: true, mean: true, median: true, sd: true, sesh: true, seshlength: true } } } // Don't edit these settings directly (changing code) unless you aren't using tampermonkey or can't access the settings via the menu commands let userPreferences = { hideAds: true, improvedShop: true, extraBotPacks: true, rightClickCopyChat: true, rightClickCopyInfo: true, showRemainingAbilityTime: true, unlockFreeSkins: true, hoverShowSkinID: true, coinXPstats: true, saveStatsBoxPosition: true, showXPdecimals: true, whiteBorder4BlackCells: true, sortWearablesByOwned: true, linesplitClosestSide: false, // friendDeclineAll: true, rainbowMapBorder: false, rainbowBorderSpeed: 5, rainbowBrHazard: false, rainbowBrHazardSpeed: 5, extraChatCommands: true, chatPrefix: '/f ', bypassConfirmChatRules: true, publicSkinSearch: true, extraOneFastSplitDelay: false, notifyNewUpdates: true, preventAutoLowGraphics: true, stylizeActiveSettings: true, removeMultiFeedPopup: true, level1kFix: true, messageBanWarning: true, removeModMessages: false, removeColorTagsInChat: true, tripleFastSplitSetting: false, rainbowNameColor: false, rainbowNameSpeed: 3, clickToCursorLock: false, removeLvlRewardPopup: false } const keyCodeMappings = { 0: "", 8: "BACKSPACE", 9: "TAB", 12: "CLEAR", 13: "ENTER", 16: "SHIFT", 17: "CTRL", 18: "ALT", 19: "PAUSE", 20: "CAPSLOCK", 27: "ESC", 32: "SPACE", 33: "PAGEUP", 34: "PAGEDOWN", 35: "END", 36: "HOME", 37: "LEFT", 38: "UP", 39: "RIGHT", 40: "DOWN", 44: "PRTSCN", 45: "INS", 46: "DEL", 91: "WIN", 92: "WIN", 93: "CONTEXTMENU", 96: "NUM 0", 97: "NUM 1", 98: "NUM 2", 99: "NUM 3", 100: "NUM 4", 101: "NUM 5", 102: "NUM 6", 103: "NUM 7", 104: "NUM 8", 105: "NUM 9", 106: "NUM *", 107: "NUM +", 109: "NUM -", 110: "NUM .", 111: "NUM /", 112: "F1", 113: "F2", 114: "F3", 115: "F4", 116: "F5", 117: "F6", 118: "F7", 119: "F8", 120: "F9", 121: "F10", 122: "F11", 123: "F12", 124: "F13", 125: "F14", 126: "F15", 127: "F16", 128: "F17", 129: "F18", 130: "F19", 131: "F20", 132: "F21", 133: "F22", 134: "F23", 135: "F24", 144: "NUMLOCK", 145: "SCROLLLOCK", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", 221: "]", 222: "'"}, cmap = { a: "а", e: "е", i: "і", o: "ο", u: "υ", y: "у", A: "А", E: "Е", I: "Ӏ", O: "Ο", U: "𝗨", Y: "Υ"}; const invisUnicodeIds = [9, 32, 160, 847, 1564, 4448, 6068, 6069, 8192, 8193, 8194, 8195, 8196, 8197, 8198, 8199, 8200, 8201, 8232, 8239, 8287, 8289, 8290, 8291, 8292, 8298, 8299, 8300, 8301, 8302, 8303, 12288, 12644, 65440]; const setStorage = (name, obj) => typeof GM_setValue != "function" ? localStorage.setItem(name, JSON.stringify(obj)) : GM_setValue(name, obj), getStorage = (name, default_obj) => typeof GM_getValue != "function" ? localStorage.getItem(name) != null ? JSON.parse(localStorage.getItem(name)) : setStorage(name, default_obj) : GM_getValue(name, default_obj); if(typeof unsafeWindow === 'undefined') unsafeWindow = window; const saveSettings = () => setStorage("fsfb-scripts", settings); const getSettings = () => { let settingsPrev = getStorage("fsfb-scripts", settings); for(let i in settingsPrev) { for(let j in settingsPrev[i]) { for(let x in settings){ for(let y in settings[x]){ if(settingsPrev[i][j].id == settings[x][y].id) settings[x][y] = settingsPrev[i][j]; } } } } } let prevPreferences = getStorage('fsfb-user-settings', userPreferences); for(let prevSetting in prevPreferences) { for(let currSetting in userPreferences){ if(prevSetting == currSetting) userPreferences[currSetting] = prevPreferences[prevSetting]; //settings[x][y] = settingsPrev[i][j]; } } const getMiscSettings = () => { let prevSettings = getStorage("fsfb-misc", misc_settings); misc_settings = {...misc_settings, ... prevSettings}; } getSettings(); getMiscSettings(); const getName = key => key ? keyCodeMappings[key] ?? String.fromCharCode(key) : ''; const levelSum = lvl => lvl * --lvl / 2, range = arr => Math.max(...arr) - Math.min(...arr), sigma = arr => arr.reduce((a, b) => a + b), mean = arr => sigma(arr) / arr.length, variance = arr => arr.reduce((a, b) => a + (b - mean(arr)) ** 2, 0) / arr.length, standardDeviation = arr => Math.sqrt(variance(arr)), ascending = arr => arr.sort((a, b) => a - b), getIQR = arr => quartile(arr, .75) - quartile(arr, .25), round = (num, places = 0) => Math.round(num * +("1e" + places)) / +("1e" + places); const median = arr => { const mid = ~~(arr.length / 2), asc = ascending(arr); return arr.length % 2 !== 0 ? asc[mid] : (asc[mid - 1] + asc[mid]) / 2; } const getProperty = (arr, property) => { let newArr = []; for (let i of arr) newArr.push(i[property]); return newArr; } const quartile = (arr, q) => { const sorted = ascending(arr), pos = (sorted.length - 1) * q, base = ~~pos, rest = pos - base; return sorted[base + 1] !== null ? sorted[base] + rest * (sorted[base + 1] - sorted[base]) : sorted[base] } const checkOutliers = (arr, returnOutliers) => { let nonOutliers = [], outliers = []; const IQR = getIQR(arr), Q1 = quartile(arr, .25), Q3 = quartile(arr, .75); for (let i of arr) i < Q1 - 1.5 * IQR || i > Q3 + 1.5 * IQR ? outliers.push(i) : nonOutliers.push(i); return returnOutliers ? outliers : nonOutliers; } const msToTime = ms => { const pad = num => num < 10 ? '0' + ~~num : ~~num; return `${pad(ms / 36e5)}:${pad(ms / 6e4 % 60)}:${pad(ms / 1e3 % 60)}`; // hrs:mins:secs } const changeTitle = title => { if(document.title != title) document.title = title; }; if(settings.checkboxes[4].active && document.title == 'Agma.io - A free multiplayer MMO game') changeTitle('Agma.io'); if(userPreferences.unlockFreeSkins){ ["", 56, 1657, 2281, 2282, 2297, 2331, 2529, 2626, 2683, 2816, 2832].forEach(id => localStorage.setItem('ytSkin' + id, '1')); localStorage.setItem('fbSkin', '1'); } const softSanitize = str => { const map = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', "/": '/', }; return str.replace(/[&<>"'/]/ig, match => map[match]); } const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); ['paste', 'copy', 'cut'].forEach(a => { unsafeWindow.addEventListener(a, e => { if(document.querySelector('#fsfb-copycutpaste')?.checked) e.stopImmediatePropagation(); }, true) }); let agmaHotkeys = JSON.parse(localStorage.getItem('hotkeys')); let agmaSettings = JSON.parse(localStorage.getItem('settings')); Object.defineProperty(unsafeWindow, 'localStorage', { value: new Proxy(localStorage, { set: function (ls, prop, val) { if(prop === 'hotkeys') agmaHotkeys = JSON.parse(val); else if(prop === 'settings'){ let prevNick = agmaSettings?.nickName; agmaSettings = JSON.parse(val); if(settings.name_color[0].active && !!document.querySelector('#nick') && prevNick && prevNick != agmaSettings.nickName) val = JSON.stringify((agmaSettings.nickName = document.querySelector('#nick').value, agmaSettings)); } return !void(ls[prop] = val); }, get: function(ls, prop) { return prop === 'setItem' || typeof ls[prop] === 'function' ? ls[prop].bind(ls) : ls[prop]; } }), configurable: true, enumerable: true }); const hotkeysMap = { 360: "W360", Split: "Space", DoubleSplit: "D", TripleSplit: "T", MacroSplit: "Z", MacroFeed: "W", FixedMouse: "C", Respawn: "M", MultiFeed: "V", Recombine: "E", Speed: "S", FreezeSelf: "F", Invisibility: "I", DropWall: "DW", ToggleCamera: "Q", FreezeCamera: "F", ToggleControlBots: "Q", SplitBots: "A", FeedBots: "X" } const getKey = id => agmaHotkeys && agmaHotkeys[hotkeysMap?.[id.replace(/^key/gm, '')]]?.c; unsafeWindow.getKey = getKey; if(userPreferences.bypassConfirmChatRules) localStorage.setItem('crc', 'true'); const insertCustomjQuery = $ => { // const { $ } = unsafeWindow; if(userPreferences.extraBotPacks){ const newBots = [ {title: "100 Bots", time: "24 HOURS", price: "700,000", id: 9}, {title: "125 Bots", time: "48 HOURS", price: "900,000", id: 10}, {title: "300 Bots", time: "24 HOURS", price: "900,000", id: 7}, {title: "100 MASS Bots", time: "1 HOURS", price: "800,000", id: 8}, {title: "300 Bots", time: "72 HOURS", price: "2,000,000", id: 11}, {title: "100 MASS Bots", time: "24 HOURS", price: "2,600,000", id: 12}, {title: "500 MASS Bots", time: "2 HOURS", price: "20,000,000", id: 17}, {title: "500 MASS Bots", time: "12 HOURS", price: "30,000,000", id: 16} ] if(document.getElementsByClassName('tab-container-section minion scroll')?.[0]?.children?.[0].children.length){ // check if minions page has already been loaded $('.confirm-minion[item=7], .confirm-minion[item=8]').parent().hide(); for(let i of newBots) createEl(i); document.getElementById('extraTab').childNodes[0].setAttribute('onclick', ''); $('.confirm-minion.extra-min').click(function(e) { e.preventDefault(); // Prevent the href from redirecting directly const { setMinionUi, purchaseMinion } = unsafeWindow; let linkURL = $(this).attr("href"), priceK = $(this).attr("price"), itemId = $(this).attr("item"); setMinionUi(true); unsafeWindow.swal({ title: "Confirm", text: 'If you click "Buy", you will purchase these minions. They cost ' + priceK, type: "warning", showCancelButton: true, confirmButtonColor: "#4CAF50", confirmButtonText: "Yes, confirm purchase", cancelButtonText: "No, cancel purchase" }, function() { purchaseMinion(itemId); }); }); } else { const _$click = $.prototype.click; $.prototype.click = function(){ if(this.selector === ".confirm-minion" && typeof arguments[0] === 'function'){ $('.confirm-minion[item=7], .confirm-minion[item=8]').parent().hide(); for(let i of newBots) createEl(i); document.getElementById('extraTab').childNodes[0].setAttribute('onclick', ''); return _$click.apply($('.confirm-minion'), arguments); } return _$click.apply(this, arguments); } } function createEl(i) { const botEl = document.createElement('li'); botEl.setAttribute('class', 'masterTooltip extra-min'); botEl.setAttribute('title', 'Spawns bots/minions which suicide into your playercell to make you big in no time! Minions follow your mouse and split upon your command! Minions start immediately after you buy them.'); document.getElementsByClassName('tab-container-section minion scroll')[0].children[0].children[0].appendChild(botEl); botEl.innerHTML = `

${i.title}

${i.time}

${i.price}
Buy`; } } } if(typeof unsafeWindow.$ === 'function'){ insertCustomjQuery(unsafeWindow.$); } else { let setjQueryVal; Object.defineProperty(unsafeWindow, '$', { // intercept immediately after jQuery is defined on window set: function(val) { setjQueryVal = val; insertCustomjQuery(val); }, get: function() { return setjQueryVal; }, configurable: true }); } const afterLoaded = () => { unsafeWindow.fsfbStartedLoading = true; const { $, swal, purchaseItem, hotkeySetDefaults, setDefaults, uisdoa } = unsafeWindow; // attempt to prevent the script from being active on subpages of agma.io if($ == null || $('#friendResizer').length < 1 || $('#megaholder').length < 1 || $('#preroll').length < 1) return; if(!agmaHotkeys) hotkeySetDefaults(); if(!agmaSettings) setDefaults(); if(typeof GM_registerMenuCommand === 'function' && typeof GM_unregisterMenuCommand === 'function'){ const addMenuCmd = (name, callback, accessKey) => GM_registerMenuCommand(name, callback, accessKey); const remMenuCmd = command_id => GM_unregisterMenuCommand(command_id); let expandedUserPref = { hideAds: { title: 'Hide Ads', type: 'bool' }, improvedShop: { title: 'Improved Shop', type: 'bool' }, extraBotPacks: { title: 'Better Shop', type: 'bool' }, rightClickCopyChat: { title: 'Right-Click Copy Chat', type: 'bool' }, rightClickCopyInfo: { title: 'Right-Click Copy Info', type: 'bool' }, showRemainingAbilityTime: { title: 'Show Remaining Abilities', type: 'bool' }, unlockFreeSkins: { title: 'Unlock Free Skins', type: 'bool' }, hoverShowSkinID: { title: 'Hover Show Skin ID', type: 'bool' }, coinXPstats: { title: 'Coin/XP Statistics', type: 'bool' }, saveStatsBoxPosition: { title: 'Save Stats-Box Position', type: 'bool' }, showXPdecimals: { title: 'Show Decimals in % XP', type: 'bool' }, whiteBorder4BlackCells: { title: 'White Border For Black Cells', type: 'bool' }, sortWearablesByOwned: { title: 'Sort Owned Wearables', type: 'bool' }, linesplitClosestSide: { title: 'Linesplit Closest Side', type: 'bool' }, // friendDeclineAll: { title: 'Friend Decline All', type: 'bool' }, rainbowMapBorder: { title: 'Rainbow Map Border', type: 'bool' }, rainbowBorderSpeed: { title: 'Rainbow Border Speed', type: 'num' }, rainbowBrHazard: { title: 'Rainbow BR Hazard', type: 'bool' }, rainbowBrHazardSpeed: { title: 'Rainbow Hazard Speed', type: 'num' }, extraChatCommands: { title: 'FSFB Chat Commands', type: 'bool' }, chatPrefix: { title: 'Chat Command Prefix', type: 'str' }, bypassConfirmChatRules: { title: 'Bypass Chat Confirm', type: 'bool' }, publicSkinSearch: { title: 'Public Skin Search', type: 'bool' }, extraOneFastSplitDelay: { title: 'Extra Fastsplit Delay', type: 'bool' }, notifyNewUpdates: { title: 'Notify New Updates', type: 'bool' }, preventAutoLowGraphics: { title: 'Disable Auto-Low Graphics', type: 'bool' }, stylizeActiveSettings: { title: 'Stylize Active Settings', type: 'bool' }, removeMultiFeedPopup: { title: 'Remove MultiFeed Warning', type: 'bool' }, level1kFix: { title: 'Fix Level 1000 Bug', type: 'bool'}, messageBanWarning: { title: 'Censor Message To Mitigate Ban', type: 'bool' }, removeModMessages: { title: 'Remove Server Mod Messages', type: 'bool' }, removeColorTagsInChat: { title: 'Remove Custom Name Tags In Chat', type: 'bool' }, tripleFastSplitSetting: { title: 'Triple Fastsplit Setting', type: 'bool'}, rainbowNameColor: { title: 'Rainbow Name Color (Client Only)', type: 'bool'}, rainbowNameSpeed: { title: 'Rainbow Name Speed (Client Only)', type: 'num'}, clickToCursorLock: { title: 'Left Click To Cursor Lock', type: 'bool'}, removeLvlRewardPopup: { title: 'Hide Level Reward Popup', type: 'bool'} } function updateShownSettings(){ for(let keyName in expandedUserPref){ const expObj = expandedUserPref[keyName]; if('menu' in expObj){ remMenuCmd(expObj.menu); } let value = userPreferences[keyName], typeIndicator = expObj.type == 'bool' ? `[ ${value ? '✅' : '❌'} ] ` : `[ "${value}" ] `; expObj.menu = addMenuCmd(typeIndicator + expObj.title, function(e){ let newVal; if(expObj.type === 'bool'){ newVal = !value; userPreferences[keyName] = newVal; } else { newVal = prompt('Please input the value you want to set:', value); if(expObj.type === 'num' && !/^[0-9]+$/.test(newVal)){ updateShownSettings(); return alert('Please only enter numbers'); } userPreferences[keyName] = expObj.type === 'num' ? Number(newVal) : newVal; } updateShownSettings(); setStorage('fsfb-user-settings', userPreferences); alert(`Setting: "${expObj.title}" value changed to: ${expObj.type === 'bool' ? `[ ${newVal ? '✅' : '❌'} ] ` : `[ "${newVal}" ] `}.\nNote that some (not all) settings require a browser reload to take full effect.`); }) } addHideAll(); } function addHideAll(){ let hideAllBtn = addMenuCmd('Hide all settings', function(){ for(let keyName in expandedUserPref){ const expObj = expandedUserPref[keyName]; if('menu' in expObj){ remMenuCmd(expObj.menu); } } remMenuCmd(hideAllBtn); addShowMore(); }); } function addShowMore(){ let showMoreBtn = addMenuCmd('Show all settings', function(){ remMenuCmd(showMoreBtn); updateShownSettings(); }) } addShowMore(); } const _slideDown = $.prototype.slideDown; $.prototype.slideDown = function () { if(this.selector === '#curser'){ let content = this[0].textContent; if(content?.includes("Your FPS seems to be low")) return; if(content?.includes("Connected to server")){ playerAlive = false; svSwitch = true; try{ currentServerId = 0; for(let { isCurrent, id } of JSON.parse(localStorage.gameservers)){ if(isCurrent) currentServerId = id; } } catch { console.warn("FSFB: Failed to grab server id from localStorage") currentServerId = parseInt($(".server-tabmenu").find(".active")[0]?.id.slice(9)); } } } return _slideDown.apply(this, arguments); } const _$text = $.prototype.text; $.prototype.text = function(){ if(this.selector === '.exp-bar' && userPreferences.showXPdecimals){ arguments[0] = (~~(+this[0].parentElement.style.width.slice(0, -1) * 100) / 100) + '%'; } if(this.selector === '#userCoins2' && typeof arguments[0] === 'string') currentUser = arguments[0]; // if(this.selector === '#megaphone_text' && typeof arguments[0] === 'string' && addChatMsg !== null){ // let name = document.querySelector('#megaphone_name').textContent, // [message] = arguments, // id = unsafeWindow.md5(Math.round(Math.random())); // addChatMsg({ // R: !1, // v: 0, // i: 0, // P: id, // z: id, // name, // G: "", // color: "#FF0A0A", // message, // category: 0, // goldMember: 0, // L: 0, // Y: 0, // j: 0, // q: 0, // J: 1, // time: Date.now(), // cache: null // }); // } return _$text.apply(this, arguments); } let swalUserColor = '#FF00D8', swalRoleTitle = 'Fsfb Developer', swalRoleColor = '#FF78EA'; unsafeWindow.swal = function() { // console.log(arguments); // console.log(arguments[0]); if(typeof arguments[0] === 'object' && 'title' in arguments[0] && userPreferences.removeLvlRewardPopup && arguments[0].type === "" && arguments[0].title === "Level Rewards" && arguments[0].html){ return void(curserMsg(arguments[0].text.replace(/\n(?=G)/gm, '').replace(/\n\. /gm, '').replace(/Wall disappears on logout!<\/span>/gm, ''), 'yellow', 0, true)); } if(typeof arguments[0] === 'object' && 'title' in arguments[0] && userPreferences.removeMultiFeedPopup && arguments[0].type === "error" && arguments[0].text === "Eject multiple cells (Multi Feed) is only available for users who purchased the Custom Skins Sale"){ return void(curserMsg(arguments[0].text, 'red', 1e4)); } if(typeof arguments[0] === 'object' && 'title' in arguments[0] && userPreferences.removeModMessages && arguments[0].title.includes("Mod Message") && arguments[0]?.customClass === "swal-title-green"){ return void(curserMsg(`${arguments[0].title}:\n${arguments[0].text}`, 'purple', 0, true)); } if (typeof arguments[0] === 'object' && 'title' in arguments[0] && /

(Fishyyyy|firebonee|kidmaletteo)<\/span>/gm.test(arguments[0].title)) { arguments[0].title = arguments[0].title .replace(/(?<=(Fishyyyy|firebonee|kidmaletteo))/gm, 'color: ' + swalUserColor) .replace(/(?<=(?:
)|(?: style="padding:2px 5px; font-size:10px; background:#999; color:#000; border-radius:10px;">Hidden<\/span>

))(?=Hidden<\/span>

)))/gm, `☆☆ ${swalRoleTitle} ☆☆
`); } return swal.apply(this, arguments); } $('.setting-tablink').css({'width' : '30%'}); $('#settingTab2').after(``); $('#settingPage3').after(`
`); $('.container').eq(0).css("max-width", "1250px"); $('#fsfb-sect-checkbox').append(`

Script Features

`); // add checkbox HTML for(let i of settings.checkboxes){ $('#fsfb-sect-checkbox').append(``); $( "#" + i.id).change(function(e) { changeSettings(this.id, $(this).is(':checked'), e); }); } // add import/export HTML $('#fsfb-sect-imexport').append(`

Import/Export

`); for(let i of settings.export_import){ $('#fsfb-sect-imexport').append(``); $( "#" + i.id).change(function() { changeSettings(this.id, $(this).is(':checked')); }); } $('#fsfb-sect-imexport').append(`
Export
Import
`); $('#fsfb-sect-theme').append(`

Game Theme

`); for(let i of settings.theme){ $('#fsfb-sect-theme').append(``); $( "#" + i.id).change(function() { changeSettings(this.id, $(this).is(':checked')); }); $( "#" + i.id1).on('input', function() { changeSettings(this.id, this.value); $(this).parent().css('background-color', this.value); // bcs the regular [input="color"] looks rly shit, change color of overlayed div instead }); } for(let i of settings.theme_boxes){ $('#fsfb-sect-theme').append(``); $( "#" + i.id).change(function(e) { changeSettings(this.id, $(this).is(':checked'), e); }); } // namecolor $('#fsfb-sect-namecolor').append(`

Colored Name

`); for(let i of settings.name_color){ if("color" in i){ $('#fsfb-sect-namecolor').append(``); $( "#" + i.id).change(function() { changeSettings(this.id, $(this).is(':checked')); }); $( "#" + i.id1).on('input', function() { changeSettings(this.id, this.value); $(this).parent().css('background-color', this.value); // bcs the regular [input="color"] looks rly shit, change color of overlayed div instead }); } else { $('#fsfb-sect-namecolor').append(``); $( "#" + i.id).change(function(e) { changeSettings(this.id, $(this).is(':checked'), e); }); } } // antilag $('#fsfb-sect-antilag').append(`

Anti-Lag

`); for(let i of settings.anti_lag){ $('#fsfb-sect-antilag').append(``); $( "#" + i.id).change(function(e) { changeSettings(this.id, $(this).is(':checked'), e); }); } $('#fsfb-sect-translate').append(`

Chat Translate

`); for(let i of settings.chat_translate){ if(!('set' in i)){ //checkboxes $('#fsfb-sect-translate').append(``); $( "#" + i.id).change(function(e) { changeSettings(this.id, $(this).is(':checked'), e); }); } else { $('#fsfb-sect-translate').append(`

${i.title}

`); } }; $('.fsfb-changelang').on("change", function(){ for(let i = 0; i < settings.chat_translate.length; i++){ if(settings.chat_translate[i].id == this.id) settings.chat_translate[i].set = this.value; } saveSettings(); }); $('#fsfb-sect-hotkeys').append(`

Script Hotkeys

`); const checkHotkeyClicked = (e, thing) => { if (e.target.id == thing.id && !thing.active){ $('#' + thing.id).addClass('selected'); thing.active = true; keysChanging = true; // prevent features from triggering when setting hotkey } else { thing.active = false; $('#' + thing.id).removeClass('selected'); } } const checkNewHotkey = (e, thing) => { if (!thing.active) return; thing.key = e.keyCode; $('#' + thing.id).text(getName(e.keyCode)).removeClass('selected'); thing.active = false; saveSettings(); styleActiveSettings(); e.preventDefault(); } const checkFsHotkey = (e, thing) => { if (!thing.active) return; thing.key = e.keyCode; thing.keyName = e.key; $('#' + thing.id).text(getName(e.keyCode)).removeClass('selected'); thing.active = false; saveSettings(); styleActiveSettings(); e.preventDefault(); } const checkPowerupClicked = e => { if(!quickBuying || !e?.originalEvent?.isTrusted || $(e.target).attr('class') == 'purchase-btn confirmation' || $(e.target).attr('class') == 'megaphone-btn') return; let id = e.target.id; if (id == 'fsfb-quickbuy-img' || id == 'fsfb-quickbuy') return void(quickBuying = true); const map = { Wall: 33, AntiFreeze: 35, AntiRecombine: 34, Shield: 38, FrozenVirus: 36, Recombine: 1, Speed: 2, Growth: 6, SpawnVirus: 7, SpawnMothercell: 8, SpawnPortal: 9, SpawnGoldOre: 10, Freeze: 5, '360Shot': 30, minion_nuker: 39, megaphone_shout: 14, freeze_yourself: 18, 'ripple-virus': 42 } let pwID = map[id.replace(/^(inv|fsfb-)/gm, '')] ?? (() => { quickBuying = false; $('.inventory-box').removeClass('fsfb-shown').find('p').show(); $('#fsfb-quickbuy').removeClass('activatedInv') curserMsg('Quick buy deactivated.', 'red'); })(); if (!quickBuying || !pwID) return; $('.confirm').attr('disabled', 'true'); // disable so user doesn't buy early - swal is slow to load text const waitUntil1 = (condition) => new Promise(resolve => { let interval = setInterval(() => { if($('.sweet-alert h2').text() == ' Confirm ') return; $('.confirm')[0].click(); condition() && (clearInterval(interval), resolve()); }, 25); setTimeout(() => { (clearInterval(interval), resolve()) }, 1e4); }); setTimeout(() => { if(pwID == 14) return; $('.confirm')[0].addEventListener('click', async e => { if(!e.isTrusted || $('.confirm').text() == 'OK') return; $('.sweet-alert, .sweet-overlay').addClass('fsfb-hidden'); setTimeout(async() => { await waitUntil1(() => !$('.sweet-alert').hasClass('visible')); if($('.sweet-alert').hasClass('visible')) return; await sleep(100); $('.sweet-alert, .sweet-overlay').removeClass('fsfb-hidden'); }, 1e3); }) }, 500); setTimeout(() => $('.confirm').removeAttr('disabled'), 600); if(pwID == 14) $('.megaphone-btn')[0].click(); else $(`.purchase-btn.confirmation[item="${pwID}"]`)[0].click(); $('.inventory-box').removeClass('fsfb-shown').find('p').show(); $('#fsfb-quickbuy').removeClass('activatedInv') quickBuying = false; } for(let i of settings.hotkeys){ $('#fsfb-sect-hotkeys').append(`

${i.title}

`); $('#' + i.id).on('contextmenu', e => { $('#' + i.id).text('').removeClass('selected'); i.active = false; i.key = 0; saveSettings(); styleActiveSettings(); e.preventDefault(); }); } // const typing = () => $('input, textarea').is(':focus'); const typing = () => { const focused = document.querySelector(":focus"); return focused === document.activeElement && ['TEXTAREA', 'INPUT'].includes(focused?.tagName) && (!document.hasFocus || document.hasFocus()) && !!(focused.type || focused.href || ~focused.tabIndex); }; const sleep = ms => new Promise(r => setTimeout(r, ms)); const press = key => ['down', 'up'].forEach(i => unsafeWindow[`onkey${i}`]({ keyCode: key })); let fsWaiting = false; const fastSplit = async(a) => { // a = true: was fast onesplit; a = false: was fast doublesplit if(fsWaiting) return; fsWaiting = true; setTimeout(() => void(fsWaiting = false), settings.fastsplit_hotkeys[a ? a === 1 ? 4 : 7 : 1].val + settings.fastsplit_hotkeys[a ? a === 1 ? 5 : 8 : 2].val); if([39, 37, 2, 4, 6].includes(currentServerId) || a || userPreferences.extraOneFastSplitDelay) await sleep(settings.fastsplit_hotkeys[a ? a === 1 ? 4 : 7 : 1].val); press(getKey("FreezeSelf")); await sleep(settings.fastsplit_hotkeys[a ? a === 1 ? 5 : 8 : 2].val); press(getKey("FreezeSelf")); } let cursorLockActivated = false, holdAutoFeed = false, _onblur; const waitForBlur = () => { if(unsafeWindow.onblur != null){ const oldBlur = unsafeWindow.onblur; unsafeWindow.onblur = function(){ spamRec = spamSpeed = splittingbots = false; keys = {}; if(!settings.checkboxes[3].active){ $("#linesplit-markers div").hide(); linesplitting = false; } return oldBlur.apply(this, arguments); } _onblur = unsafeWindow.onblur; } else { setTimeout(waitForBlur, 400); } }; waitForBlur(); // hook for typing in chat w/ cursor lock const waitForKeyup = () => { if(unsafeWindow.onkeyup != null){ const _keydown = unsafeWindow.onkeyup; unsafeWindow.onkeyup = function(){ const keyCode = arguments[0]?.keyCode; if(arguments[0]?.target?.id === 'chtbox' && arguments[0]?.isTrusted && cursorLockActivated && keyCode === getKey('FixedMouse')) return; if(arguments[0]?.isTrusted && holdAutoFeed && [getKey('MacroFeed'), getKey('MultiFeed')].includes(keyCode)) return; return _keydown.apply(this, arguments); } } else { setTimeout(waitForKeyup, 400); } }; waitForKeyup(); const waitForSetGraphics = () => { if(unsafeWindow.onkeyup != null){ const _setGraphics = unsafeWindow.setGraphics; unsafeWindow.setGraphics = (a, b) => userPreferences.preventAutoLowGraphics && b ? $("#curser").hide() : _setGraphics(a, b); } else { setTimeout(waitForSetGraphics, 400); } }; waitForSetGraphics(); const fsfbCustomBlur = function(){ ['MacroSplit', ...(holdAutoFeed ? [] : ['MacroFeed', 'MultiFeed']), ...(cursorLockActivated ? [] : ['FixedMouse'])].forEach(id => unsafeWindow.onkeyup({keyCode: getKey(id)})); spamRec = spamSpeed = splittingbots = false; keys = {}; if(!settings.checkboxes[3].active){ $("#linesplit-markers div").hide(); linesplitting = false; } } const toggleHoldFeed = active => { holdAutoFeed = active ?? !holdAutoFeed; unsafeWindow.onblur = holdAutoFeed || cursorLockActivated ? fsfbCustomBlur : _onblur; unsafeWindow[`onkey${holdAutoFeed ? 'down' : 'up'}`]({ keyCode: getKey('MacroFeed') }); } const toggleCursorLock = active => { cursorLockActivated = active ?? !cursorLockActivated; unsafeWindow.onblur = holdAutoFeed || cursorLockActivated ? fsfbCustomBlur : _onblur; unsafeWindow[`onkey${cursorLockActivated ? 'down' : 'up'}`]({ keyCode: getKey('FixedMouse') }); } unsafeWindow.fsfbCursorLock = toggleCursorLock; const toggleSetting = index => { let el = $('#' + settings.quickSettings[index].set); if($('#fsfb-settings-main')[0].contains(el[0])) el.prop('checked', !el.prop('checked')).trigger('change'); else el.unbind().click(); } Object.defineProperty(KeyboardEvent.prototype, 'keyCode', { get: function() { switch (this.key.toLowerCase()) { case settings.fastsplit_hotkeys[0]?.keyName.toLowerCase(): return getKey("Split"); case settings.fastsplit_hotkeys[3]?.keyName.toLowerCase(): return getKey("DoubleSplit"); case settings.fastsplit_hotkeys[6]?.keyName.toLowerCase(): return userPreferences.tripleFastSplitSetting ? getKey("TripleSplit") : this.which; default: return this.which; } } }); let slowfeeding = !1, linesplitting = !1, hiddenUI = !1, splittingbots = !1, spamRec = !1, spamSpeed = !1; const pressed = e => { const key = e.which ? e.which : e.keyCode; if(document.activeElement.type === 'textarea') e.stopImmediatePropagation(); if(typing() || keysChanging || e.key == undefined || e.keyCode == undefined) return; if(key === 27 && quickBuying){ // esc pressed quickBuying = false; $('#fsfb-quickbuy').removeClass('activatedInv'); curserMsg('Quick buy deactivated.', 'red'); $('.inventory-box').removeClass('fsfb-shown').find('p').show(); e.preventDefault(); e.stopImmediatePropagation(); } if(key === settings.hotkeys[0].key){ // 7 feed let i = 1; let interval = setInterval(() => { press(getKey("MacroFeed")); if(++i > 7) clearInterval(interval); }, 85); e.preventDefault(); } if(key === settings.hotkeys[1].key && !settings.checkboxes[3].active){ // linesplit lock linesplitting = true; linesplit(); $("#linesplit-markers div").show(); e.preventDefault(); } if(key === settings.hotkeys[1].key && settings.checkboxes[3].active){ // linesplit lock linesplitting = !linesplitting; if(linesplitting){ $("#linesplit-markers div").show(); linesplit(); } else { $("#linesplit-markers div").hide(); $('#canvas').trigger($.Event('mousemove', {clientX: mosX, clientY: mosY})); // return mouse to where the cursor is } e.preventDefault(); } if(key === settings.hotkeys[2].key){ // macro split bots splittingbots = true; const splittingBots = () => { if(!splittingbots) return; press(getKey("SplitBots")); setTimeout(splittingBots, 50); } splittingBots(); e.preventDefault(); } if(key === settings.hotkeys[3].key){ // hide ui _replaceCSS('hideUI-css', (hiddenUI = !hiddenUI) ? '.hideUI{ display: none !important; }' : ''); e.preventDefault(); } if(key === settings.hotkeys[4].key){ // toggle cursor lock toggleCursorLock(); e.preventDefault(); } if(key === settings.hotkeys[5].key){ // check profile const swal = $('.sweet-alert'), swalText = swal.text(); if((swalText.includes('Level: ') || swalText.includes('The selected player is not logged in or is playing in invisible mode.')) && swalText.includes('Not valid!')) $('button.confirm').click(); if(mouseHoveringChat) $('#chtCanvas')[0].ondblclick({clientX: mosX, clientY: mosY, preventDefault: function(){}}); else { let contextmenuShown = $('#contextMenu').css('display') == 'block'; let evt = new MouseEvent("contextmenu", { bubbles: true, cancelable: true, view: unsafeWindow, clientX: mosX, clientY: mosY }); document.body.dispatchEvent(evt); if($('#contextPlayerSkin').css('background-color') == 'rgb(51, 51, 51)') curserMsg('Unable to show profile; no player was clicked on.', 'red'); if(!contextmenuShown) $('#contextMenu').hide(); $('#contextUserProfile').addClass('hover'); $('#contextMenu')[0].onclick({stopPropagation: function(){}}); } e.preventDefault(); } if(key === getKey("FixedMouse")){ // real cursor lock key is pressed cursorLockActivated = false; unsafeWindow.onblur = _onblur; } if(e.keyCode != 0 && e.key.toLowerCase() === settings.fastsplit_hotkeys[0]?.keyName.toLowerCase()){ // fast onesplit fastSplit(0); e.preventDefault(); } if(e.keyCode != 0 && e.key.toLowerCase() === settings.fastsplit_hotkeys[3]?.keyName.toLowerCase()){ // fast doublesplit fastSplit(1); e.preventDefault(); } if(e.keyCode != 0 && e.key.toLowerCase() === settings.fastsplit_hotkeys[6]?.keyName.toLowerCase() && userPreferences.tripleFastSplitSetting){ // fast triplesplit fastSplit(2); e.preventDefault(); } if(key === settings.slowFeed[0].key){ // toggle feed slowfeeding = !slowfeeding; const feeding = () => { if(!slowfeeding) return void(holdAutoFeed && toggleHoldFeed(false)); unsafeWindow?.uisdoa?.foprw?.() || settings.slowFeed[1].val === 0 || press(getKey("MacroFeed")); settings.slowFeed[1].val === 0 ? toggleHoldFeed(slowfeeding) : setTimeout(feeding, settings.slowFeed[1].val); } feeding(); e.preventDefault(); } if(key === settings.frozenvirus[0].key){ let fvEl = $('#invFrozenVirus'), wasActive = fvEl.hasClass('activatedInv'); if(fvEl.css('display') === 'none') return void(curserMsg(`FSFB script can't click on the frozen virus powerup! Frozen viruses are needed before using this hotkey`, 'red')); curserMsg(); wasActive || fvEl[0].onmousedown({ button: 0 }); press(getKey("MacroFeed")); wasActive || setTimeout(() => fvEl[0].onmousedown({ button: 0 }), settings.frozenvirus[1].val); } if(key === settings.quickSettings[0].key){ // quick settings 1 toggleSetting(0); e.preventDefault(); } if(key === settings.quickSettings[1].key){ // quick settings 2 toggleSetting(1); e.preventDefault(); } if(key === settings.quickSettings[2].key){ // quick settings 3 toggleSetting(2); e.preventDefault(); } if(key === settings.quickSettings[3].key){ // quick settings 4 toggleSetting(3); e.preventDefault(); } if(key === settings.quickSettings[4].key){ // quick settings 5 toggleSetting(4); e.preventDefault(); } if(key === settings.quickSettings[5].key){ // quick settings 6 toggleSetting(5); e.preventDefault(); } if(!spamRec && uisdoa && settings.checkboxes[6].active && key === getKey("Recombine")){ spamRec = true; const spammingRec = () => { if(!spamRec) return; // press(getKey("keyRecombine")); if(unsafeWindow?.uisdoa?.foprc) uisdoa.foprc(1); setTimeout(spammingRec, 10); } spammingRec(); e.preventDefault(); } if(!spamSpeed && uisdoa && settings.checkboxes[6].active && key === getKey("Speed")){ spamSpeed = true; const spammingSpeed = () => { if(!spamSpeed) return; // press(getKey("keySpeed")); if(unsafeWindow?.uisdoa?.foprc) uisdoa.foprc(0); setTimeout(spammingSpeed, 10); } spammingSpeed(); e.preventDefault(); } } const released = key => { if(typing() || keysChanging) return; if(key == settings.hotkeys[2].key) splittingbots = false; // macro split bots if(key == settings.hotkeys[1].key && !settings.checkboxes[3].active){ // linesplit lock linesplitting = false; $('#canvas').trigger($.Event('mousemove', {clientX: mosX, clientY: mosY})); // return mouse to where the cursor is $("#linesplit-markers div").hide(); } if(spamRec && key === getKey("Recombine")) spamRec = false; if(spamSpeed && key === getKey("Speed")) spamSpeed = false; } const slowfeedhotkey = settings.slowFeed[0]; // add slowfeed HTML $('#fsfb-sect-slowfeed').append(`

Auto-Feed

`) .append(`

${slowfeedhotkey.title}

`) .append(`

${settings.slowFeed[1].title}

`); $('#' + slowfeedhotkey.id).on('contextmenu', e => { $('#' + slowfeedhotkey.id).text('').removeClass('selected'); slowfeedhotkey.active = false; slowfeedhotkey.key = 0; saveSettings(); styleActiveSettings(); e.preventDefault(); }); document.getElementById(settings.slowFeed[1].id).addEventListener("keypress", function(e){ setTimeout(() => { // goes too fast or smth settings.slowFeed[1].val = +$('#' + settings.slowFeed[1].id).val(); saveSettings(); }, 5); }); // add fastsplit HTML $('#fsfb-sect-fastsplit').append(`

Fast-Split

`); // for(let i of settings.fastsplit_hotkeys){ for(let j = 0; j < settings.fastsplit_hotkeys.length; j++){ let i = settings.fastsplit_hotkeys[j]; $('#fsfb-sect-fastsplit').append('val' in i ? `

${i.title}

` : `

${i.title}

`); if('val' in i){ document.getElementById(i.id).addEventListener("keypress", function(e){ setTimeout(() => { // goes too fast or smth settings.fastsplit_hotkeys[j].val = +$('#' + i.id).val(); if($('#' + i.id).val() == "") settings.fastsplit_hotkeys[j].val = 0; saveSettings(); }, 5); }); } else { $('#' + i.id).on('contextmenu', e => { $('#' + i.id).text('').removeClass('selected'); i.active = false; i.key = 0; i.keyName = ''; saveSettings(); styleActiveSettings(); e.preventDefault(); }); } } $('#fsfb-sect-frzvrs').append(`

Frozen-Virus

`) .append(`

${settings.frozenvirus[0].title}

`) .append(`

${settings.frozenvirus[1].title}

`); $('#' + settings.frozenvirus[0].id).on('contextmenu', e => { $('#' + settings.frozenvirus[0].id).text('').removeClass('selected'); settings.frozenvirus[0].active = false; settings.frozenvirus[0].key = 0; saveSettings(); styleActiveSettings(); e.preventDefault(); }); document.getElementById(settings.frozenvirus[1].id).addEventListener("keypress", function(e){ setTimeout(() => { // goes too fast or smth settings.frozenvirus[1].val = +$('#' + settings.frozenvirus[1].id).val(); saveSettings(); }, 5); }); // add quick settings HTML $('#fsfb-sect-quickSettings').append(`

Quick Settings

`); for(let i of settings.quickSettings){ $('#fsfb-sect-quickSettings').append(`
`); $('#' + i.id).on('contextmenu', e => { $('#' + i.id).text('').removeClass('selected'); i.active = false; i.key = 0; saveSettings(); styleActiveSettings(); e.preventDefault(); }); }; $('.fsfb-quickchange').on("change", function(){ settings.quickSettings[+this.id.replace('fsfb-quick-select', '') - 1].set = this.value; saveSettings(); }); // add UI scaling $('#fsfb-sect-uiScale').append(`

Game Scaling

`); for(let i of settings.uiScaling){ $('#fsfb-sect-uiScale').append(`

${i.title}

`); // $('#fsfb-sect-uiScale').append(`

${i.title}

`); $( "#" + i.id).on('input', function() { changeSettings(this.id, $(this).val()); }); }; let quickBuying = false; ['megaphone_shout', 'minion_nuker', 'freeze_yourself', 'ripple-virus'].forEach(elId => $('#invCloak').after(``)); $(settings.checkboxes[10] ? '#fsfb-megaphone_shout' : '#inv360Shot').after(``); $('#fsfb-quickbuy').on('click', function(){ quickBuying = !quickBuying; if (quickBuying){ $(this).addClass('activatedInv'); curserMsg('Quick buy activated, click the powerup you would like to buy.', 'green'); $('.inventory-box').addClass('fsfb-shown').find('p').hide(); $('#invCloak').removeClass('fsfb-shown'); $('#fsfb-quickbuy').removeClass('fsfb-shown'); } else { $(this).removeClass('activatedInv'); curserMsg('Quick buy deactivated.', 'red'); $('.inventory-box').removeClass('fsfb-shown').find('p').show(); } }); const styleActiveSettings = () => { // css selector :has() isn't fully supported at the moment, so gotta use jquery for the time being :( // #fsfb-settings-main p:has(+.fsfb-hotkey:not(:empty)) { // color:#df901c; // } // #fsfb-settings-main .fsfb-hotkey:not(:empty) ~ p:has(+input.fsfb-hotkey):not(div.fsfb-hotkey:empty + * + p):not(div.fsfb-hotkey:empty + * + p + * + * + p) { // color: #df901c; // } if(!userPreferences.stylizeActiveSettings) return; $('#fsfb-settings-main p:has(+div.fsfb-hotkey), #fsfb-settings-main select:has(+div.fsfb-hotkey)').each(function(){ $(this)[$(this).is(':has(+.fsfb-hotkey:empty)') ? 'removeClass' : 'addClass']('fsfb-active-setting'); }) $('#fsfb-settings-main .fsfb-hotkey~ p:has(+input.fsfb-hotkey)').each(function(){ $(this)[$(this).is('div.fsfb-hotkey:empty + * + p') || $(this).is('div.fsfb-hotkey:empty + * + p + * + * + p') ? 'removeClass' : 'addClass']('fsfb-active-setting'); }); $('input[type="range"].fsfb-slider').each(function(){ $(this).prev()[this.value == this.getAttribute('value') ? 'removeClass': 'addClass']('fsfb-active-setting'); }) } // add lag detection settings to things let customCells = false; $("#fsfb-sect-theme>label>input").addClass('fsfb-ncustom'); $('#fsfb-powsoverlay, #fsfb-mtchmass').addClass('fsfb-ncustom'); $('#fsfb-check-Hazard, #fsfb-check-border').removeClass('fsfb-ncustom'); $("#fsfb-revcell, #fsfb-portalstop, #fsfb-bublecell").removeClass('fsfb-ncustom'); $('#fsfb-foodSize').prev().addClass('fsfb-lag'); let antilagCells = false; let fillCells = false; $('#fsfb-bublecell, #fsfb-showmass, #fsfb-spikedcells, #fsfb-mtchmass, #fsfb-powsoverlay, #fsfb-anticloak, #fsfb-portalmass, #fsfb-nc-public').addClass('fsfb-lag'); $('#fsfb-powsoverlay, #fsfb-bublecell, #fsfb-anticloak').addClass('fsfb-nfill'); let onlyCells = false; let strokeCells = false; $('#fsfb-bublecell, #fsfb-powsoverlay').addClass('fsfb-nstroke'); let foodSizeOn = false; // let drawCells = false; // $('#fsfb-powsoverlay, #fsfb-portalmass').addClass('fsfb-ndraw'); let customCellsChanged = false; let translateChanged = false, pwOverlayChanged = false; const changeSettings = (ID, active, e) => { // a = active, e = event (optional) for(let i of settings.uiScaling) if(i.id == ID) i.level = active; for(let i of settings.checkboxes) if(i.id == ID) i.active = active; for(let i of settings.export_import) if(i.id == ID) i.active = active; for(let i of settings.theme_boxes) if(i.id == ID) i.active = active; for(let i of settings.anti_lag) if(i.id == ID) i.active = active; for(let i of settings.chat_translate){ if(i.id == ID){ if(ID == "fsfb-tranchat" && (typeof GM_xmlhttpRequest != 'function') && e?.originalEvent?.isTrusted){ curserMsg('Fsfb script is unable to access the GM_xmlhttpRequest function. Chat translate won\'t work without this. This is often caused by not using the tampermonkey extension (or not the latest version).', 'red', 1e4); $('#' + ID).prop('checked', false); return; } translateChanged = true; i.active = active; } } for(let i of settings.theme){ if(i.id == ID) i.active = active; if(i.id1 == ID) i.color = active; } for(let i of settings.name_color){ if(i.id == ID) i.active = active; if(i.id1 == ID) i.color = active; } if(ID == "fsfb-hideshouts") $('#megaholder')[`${active ? 'add' : 'remove'}Class`]('hideMegaphone'); if(ID == "fsfb-qBuy") $('#fsfb-quickbuy')[active ? 'show' : 'hide'](); //.css('display', a ? 'flex' : 'hide'); if(ID == "fsfb-pwsonerow"){ $('#fsfb-quickbuy').detach().appendTo(`#inventory${active ? 2 : 1}`); [1, 2].forEach((i) => $("#inventory" + i).addClass("fsfb-inventories").css("order", active ? i : -i)); _replaceCSS("css-invsingleline", active ? `#inventory{ display: flex; position: absolute; left: 50%; bottom: 8px; transform: translateX(-50%); } .fsfb-inventories { position: initial !important; transform: initial !important; }` : ''); } let maxlen = $('#fsfb-nc-public').is(':checked') ? ($('#fsfb-box-ncs').is(':checked') ? 16 : 19) : 24; $('#nick').attr('maxlength', maxlen); if(ID == "fsfb-nc-public"){ if(!active) pubNameSwitch = true; setTimeout(() => (pubNameSwitch = false), 25); // def nonoptimal, 2 lazy 2 fix } // client side colored name if(["fsfb-box-nc", "fsfb-box-ncs", "fsfb-nc-color", "fsfb-nc-stroke", "fsfb-nc-public"].includes(ID) && nameColors?.set){ if(settings.name_color[0].active || ID === "fsfb-nc-public"){ if(active && ID === "fsfb-nc-public" && !settings.name_color[1].active){ nameColors.set(defaultColorsAmnt, "#FFFFFF"); nameStrokes.set(defaultColorsAmnt, "#000000"); } else { nameColors.set(defaultColorsAmnt, settings.name_color[1].color); nameStrokes.set(defaultColorsAmnt, settings.name_color[2].active ? settings.name_color[2].color : contrastColor(settings.name_color[1].color)); } // warnings if(playerIsAlive()){ if(ID == "fsfb-nc-public" && !active){ curserMsg("Respawn to deactivate FSFB public custom name.", "red", 4e3, false); } else { curserMsg(`Respawn to update your name color!\nNote: FSFB Public Colored Name is ONLY visible to other FSFB script users!`, 'orange', 8e3, true); } } else if(maxlen < 24 && ID == "fsfb-nc-public") { curserMsg(`FSFB script's public custom name feature encodes the color in your clan tag; therefore, clan tags won't work with this feature enabled. The max nick length with the current settings is ${maxlen}${settings.name_color[2].active ? `, deactivate Name Stroke to increase this to 19.` : '.'}\nPlease note: FSFB Public Colored Name is ONLY visible to other FSFB script users!`, "purple", 20e3, true); } } else { if((ID === "fsfb-nc-color" && !active) || !settings.name_color[1].active){ nameColors.set(defaultColorsAmnt, "#FFFFFF"); nameStrokes.set(defaultColorsAmnt, "#000000"); // again won't revert bc lazy } else { nameColors.set(defaultColorsAmnt, settings.name_color[1].color); nameStrokes.set(defaultColorsAmnt, settings.name_color[2].active ? settings.name_color[2].color : contrastColor(settings.name_color[1].color)); } } } if(ID == "fsfb-bublecell" && $("#cBubbleCells").is(":checked") != active && e?.originalEvent?.isTrusted) $('#cBubbleCells').unbind().click(); if(ID == "fsfb-showmass" && $("#cMass").is(":checked") != active && e?.originalEvent?.isTrusted) $('#cMass').unbind().click(); if((ID == "fsfb-myskins" || ID == "fsfb-partyskins") && !$("#cSkins").is(":checked") && active) $('#cSkins').unbind().click(); if((ID == "fsfb-mynick" || ID == "fsfb-partynicks") && !$("#cNames").is(":checked") && active) $('#cNames').unbind().click(); if(ID == "fsfb-myskins" && active) $('#fsfb-partyskins').prop('checked', false).trigger('change'); if(ID == "fsfb-partyskins" && active) $('#fsfb-myskins').prop('checked', false).trigger('change'); if(ID == "fsfb-mynick" && active) $('#fsfb-partynicks').prop('checked', false).trigger('change'); if(ID == "fsfb-partynicks" && active) $('#fsfb-mynick').prop('checked', false).trigger('change'); if(ID == "fsfb-hideejected" && active) $('#fsfb-hidestaticej').prop('checked', false).trigger('change'); if(ID == "fsfb-hidestaticej" && active) $('#fsfb-hideejected').prop('checked', false).trigger('change'); if(ID == "fsfb-box-nc" && !active) $('#fsfb-box-ncs').prop('checked', false).trigger('change'); if(ID == "fsfb-powsoverlay") svSwitch = true; let zoomLvl = "100%"; let map = { 1: 50, 2: 70, 3: 80, 4: 90, 5: 100, 6: 110, 7: 125, 8: 150, 9: 200 } if(ID == "fsfb-invSize") $('#inventory').css('zoom', (map[+active] ?? 100)+ '%'); if(ID == "fsfb-statsSize") $('#stats-container').css('zoom', (map[+active] ?? 100) + '%'); let prevCustomCells = customCells; // lag settings customCells = $(".fsfb-ncustom, #fsfb-nc-public").is(":checked") || $('#fsfb-foodSize').val() != '1'; // || userPreferences.whiteBorder4BlackCells; fillCells = $('.fsfb-nfill').is(':checked'); strokeCells = $('.fsfb-nstroke').is(':checked') || settings.checkboxes[2].active;; onlyCells = $('#fsfb-myskins, #fsfb-partyskins, #fsfb-mynick, #fsfb-partynicks').is(':checked') || ($('#fsfb-box-nc').is(':checked') && !$('#fsfb-nc-public').is(':checked')) || userPreferences.rainbowNameColor; antilagCells = $("#fsfb-sect-antilag>label>input").not('#fsfb-nodeathanim').is(':checked'); foodSizeOn = $('#fsfb-foodSize').val() != '1'; if(prevCustomCells != customCells && e?.originalEvent?.isTrusted) customCellsChanged = true; // if(customCellsChanged && e?.originalEvent?.isTrusted) setTimeout(() => (customCellsChanged = false), 25); if(customCellsChanged && e?.originalEvent?.isTrusted) setTimeout(() => (customCellsChanged = false), 25); styleActiveSettings(); saveSettings(); } // add event listeners let mosX, mosY, keys = {}, keysChanging = false, mouseHoveringChat = false; $(document).on('click', e => { if(e.target.id.includes('fsfb')){ for(let i = 0; i < settings.hotkeys.length; i++) checkHotkeyClicked(e, settings.hotkeys[i]); for(let i = 0; i < settings.fastsplit_hotkeys.length; i++) settings.fastsplit_hotkeys[i].val == null && checkHotkeyClicked(e, settings.fastsplit_hotkeys[i]); for(let i = 0; i < settings.quickSettings.length; i++) checkHotkeyClicked(e, settings.quickSettings[i]); checkHotkeyClicked(e, settings.slowFeed[0]); // slow feed checkHotkeyClicked(e, settings.frozenvirus[0]); } checkPowerupClicked(e); }) .on('mousemove', e => { if(e.originalEvent == null || !e.originalEvent.isTrusted) return; mouseHoveringChat = e.target.id == 'chtCanvas'; ({clientX: mosX, clientY: mosY} = e); if (linesplitting) linesplit(); }) .on("keydown", e => { // if(e.originalEvent == null || !e.originalEvent.isTrusted) return; if(keysChanging){ for(let i = 0; i < settings.hotkeys.length; i++) checkNewHotkey(e, settings.hotkeys[i]); for(let i = 0; i < settings.fastsplit_hotkeys.length; i++) checkFsHotkey(e, settings.fastsplit_hotkeys[i]); for(let i = 0; i < settings.quickSettings.length; i++) checkNewHotkey(e, settings.quickSettings[i]); checkNewHotkey(e, settings.slowFeed[0]); // slow feed checkNewHotkey(e, settings.frozenvirus[0]); } if (!(e.keyCode in keys)){ keys[e.keyCode] = !0; pressed(e); } keysChanging = false; }) .on("keyup", e => { if(e.originalEvent == null || !e.originalEvent.isTrusted) return; delete keys[e.keyCode]; released(e.keyCode); if(cursorLockActivated && e.keyCode == getKey("FixedMouse")){ e.stopImmediatePropagation(); e.preventDefault(); } }) .on('mouseup', e => { if(e.which !== 1 || !e?.originalEvent?.isTrusted || !userPreferences.clickToCursorLock || cursorLockActivated) return; unsafeWindow.onkeyup({keyCode: getKey('FixedMouse')}); }); $('#canvas').on('mousedown', e => { // for mouse cursorlock if(e.which !== 1 || !e?.originalEvent?.isTrusted || !userPreferences.clickToCursorLock) return; if(cursorLockActivated){ cursorLockActivated = false; unsafeWindow.onblur = _onblur; } unsafeWindow.onkeydown({keyCode: getKey('FixedMouse')}) }); let factsArr = typeof facts_list == 'undefined' ? null : facts_list.replace(/^\n|\n$/gm, '').split(/\n/gm); const randomFact = index => factsArr && (factsArr[index] ?? factsArr[~~(Math.random() * factsArr.length)]); const hashCode = (str, shift) => { let hash = 0; for (let i = 0; i < str.length; i++) hash = (hash << shift) - hash + str.charCodeAt(i), hash |= 0; return str.length == 0 ? 0 : hash; }; const RNG = (min, max) => Math.random() * (max - min) + min; // chat cmds if(userPreferences.extraChatCommands){ const $chtbox = $('#chtbox'); $chtbox.on('keydown', e => { if(e.keyCode != 13) return; if(userPreferences.messageBanWarning && /a\s*g\s*a\s*r\s*p\s*o\s*w\s*e\s*r/gmi.test($chtbox.val())){ curserMsg("FSFB WARNING: FSFB script has censored your message as it has detected that your message may've contained a word/phrase that agma.io gives a 24 hour IP ban for. This FSFB feature can be disabled in the tampermonkey script settings.", 'red', 1e4); $chtbox.val($chtbox.val().replace(/a\s*g\s*a\s*r\s*p\s*o\s*w\s*e\s*r/gmi, match => '*'.repeat(match.length))); } let newMsg = '', cmdVerif, customCmd = false, firstMatch = $chtbox.val().match(new RegExp(`(?<=((^|(^\/party +)|(^\/pm +\\S+ ))${escapeRegExp(userPreferences.chatPrefix || "/f ")}))\\S+(\\s+\\S+)*(?=($|\\s+))`, 'gmi')); if(firstMatch == null) return; let[command, ...params] = firstMatch[0].split(/\s+/g); const originalMsg = $chtbox.val().replace(new RegExp(`(?<=((^|(^\/party +)|(^\/pm +\\S+ ))))${escapeRegExp(userPreferences.chatPrefix || "/f ")}${escapeRegExp(firstMatch[0])}(?=($|\\s+))`, 'gmi'), ''), isolatedMsg = firstMatch[0].replace(new RegExp(command + '\\s', 'gi'), ''); coinsInfo(); xpInfo(); /* ~~~ example of external chat cmds (can be used by other scripts) ~~~ */ /* externalChatCmds = [ { commands: ['test1', 'test2', 'test3'], callback: (command, isolatedMsg, params) => { let newMsg = ''; return newMsg; } }, { commands: ['eg1', 'eg2'], callback: (cmd, isoMsg, params) => { console.log(cmd, isoMsg, params); alert('bru') return ''; } } ] */ let { externalChatCmds } = unsafeWindow; if(externalChatCmds?.length){ for(let i of externalChatCmds){ if(i.commands.includes(command.toLowerCase())){ customCmd = true; newMsg = i.callback(command.toLowerCase(), isolatedMsg, params); } } } if(!customCmd && (cmdVerif ??= true)){ switch(command.toLowerCase()){ case 'help': $('#fsfb-extra-info')[0].click(); setTimeout(() => $('.fsfb-modal-body').scrollTop(1850), 200); newMsg = ''; break; case 'bots': case 'bot': case 'min': case 'mins': case 'minion': case 'minions': { let minInfo = misc_settings.bots?.[currentUser], minsAmt, minsTimeRem; $('#infoContent').children().each(function(){ if($(this).text().includes('Minion Time:')) minsTimeRem = $(this).find('span').text(); if($(this).text().includes('Minions:')) minsAmt = $(this).find('span').text(); }); if((minsChatAmt[currentUser] != null && minsChatAmt[currentUser]?.amt && !minsChatAmt[currentUser]?.started) && (minInfo == null || (minInfo && Date.now() > minInfo.currMs + minInfo.rem))){ /* || (minInfo && Date.now() > minInfo.currMs + minInfo.rem) */ newMsg = `Minion Pack Unstarted: ${minsChatAmt[currentUser].amt}`; } else if(minsChatAmt[currentUser] != null && minsChatAmt[currentUser]?.started && minsChatAmt[currentUser]?.amt && minInfo == null ){ newMsg = `Minion Pack Activated: ${minsChatAmt[currentUser].amt}`; } else if(!(minsAmt == '0' && minsTimeRem == '00:00:00') && minsChatAmt[currentUser] != null && minsChatAmt[currentUser].amt && minInfo != null && (minInfo.active || minsChatAmt[currentUser].started) && minInfo.rem - (Date.now() - minInfo.currMs) > 0){ newMsg = `Minion Pack Activated: ${minsChatAmt[currentUser].amt}, with ${msToTime(minInfo.rem - (Date.now() - minInfo.currMs))} remaining`; } else if(!(minsAmt == '0' && minsTimeRem == '00:00:00') && minsAmt != null && minsTimeRem != null){ let timeArr = minsTimeRem.split(':'), msBotsTime = (3.6e6 * +timeArr[0]) + (6e4 * +timeArr[1]) + (1e3 * +timeArr[2]); newMsg = `Minion Pack Activated: ${minsAmt}, with ${msToTime(msBotsTime)} remaining`; } else { newMsg = `Minion Pack Activated: none`; } break; } case 'pws': case 'pw': case 'powers': case 'power': case 'inv': case 'inventory': case 'pows': case 'powerups': { curserMsg(`It's recommended to use ${userPreferences.chatPrefix + command}1, ${userPreferences.chatPrefix + command}2, and ${userPreferences.chatPrefix + command}3 instead, so your chat messages aren't cut-off by the chat maxlength`, 'red', 8e3); updatePwCount(); newMsg = 'Inv: '; for (let i = 0; i < 6; i++) { newMsg = 'Inv: '; for (let pw in pws) { const check = index => i < index ? ' ' : ''; if (pws[pw] != '') newMsg += `${pws[pw]}${check(1)}${(i > 2 ? pw.slice(0, 6 - i) : pw)},${check(2)}`; } newMsg = newMsg.replace(/,[^,]*$/g, ''); if (newMsg.length <= 100) i = 6; } if (newMsg == 'Inv: ') newMsg = 'Inv: no powers'; break; } case 'totalpws': case 'totalpw': case 'totalpowers': case 'totalpower': case 'total': case 'totpw': case 'totalpows': case 'totalpowerups': newMsg = `Total Powerups: ${$('.inventory-box>p').toArray().map(x => +x.innerText).reduce((a, b) => a + b).toLocaleString('en-US')}` break; case 'xplevel': case 'levelxp': case 'lvlxp': case 'xpcompleted': case 'xp': newMsg = `XP Completed: ${currentPercent ? String(Math.round(currentPercent * currentLevel * 1e3, 1)).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "/" + (currentLevel * 1e3).toLocaleString('en-US') : "0/0"}` break; case 'level': case 'levels': case 'lvls': case 'lvl': case 'lvlcompleted': case 'lvlscompleted': newMsg = `Level ${currentLevel}, with ${round(currentPercent * 100, 3)}% completed` break; case 'coin': case 'coins': newMsg = `Coins: ${String(currentCoins).replace(/\B(?=(\d{3})+(?!\d))/g, ",")}` break; case 'hours': case 'hrs': case 'hour': case 'hr': case 'timeplayed': newMsg = (isLogged() ? $('.timePlayed>span').text().replace(/\B(?=(\d{3})+(?!\d))/g, ",") : 'Time Played: 0, not logged in'); break; case 'rank': case 'lvlrank': newMsg = `My Rank: ${isLogged() ? $('.ranking.text-left>span').text().match(/(?<=^Your rank: )\d+$/gm)?.[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",") : '∞, not logged in'}`; break; case 'ping': case 'delay': case 'ms': newMsg = `My Ping: ${$('#ping').text().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}` break; case 'fps': case 'frames': newMsg = `My FPS: ${$('#fps').text().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}` break; case 'topmass': case 'highscore': case 'highmass': case 'highestmass': newMsg = `My Top Mass: ${$('#topMass').text()}` break; case 'cells': case 'cellcount': case 'cell': newMsg = `My Cell Count: ${$('#cellsAmount').text()}` break; case 'pw1': case 'pws1': case 'power1': case 'powers1': case 'inv1': case 'inventory1': newMsg = getPowerMessage(1); break; case 'pw2': case 'pws2': case 'power2': case 'powers2': case 'inv2': case 'inventory2': newMsg = getPowerMessage(2); break; case 'pw3': case 'pws3': case 'power3': case 'powers3': case 'inv3': case 'inventory3': newMsg = getPowerMessage(3); break; case 'friends': case 'friend': case 'friendsonline': case 'friendonline': newMsg = `Friends Online: ${$('#friendsLoggedInAmt').text() + $('#friendsTotalAmt').text()}`; break; case 'request': case 'requests': case 'friendrequest': case 'friendrequests': case 'friendreq': case 'req': newMsg = `Friend Requests: ${$('#friendsRequestsAmt').text() === '' ? 'none' : $('#friendsRequestsAmt').text()}`; break; case 'gold': case 'goldmem': case 'goldmember': case 'golddays': case 'gm': { const obj = accGoldMem[currentUser]; if(obj?.has == null){ newMsg = `Days of Goldmember Remaining: none`; break; } newMsg = `Days Of Goldmember Remaining: ${obj.has || obj.days != null ? (obj.days + (obj.days == 1 ? ' Day' : ' Days')) : 'none'}`; break; } case 'alive': case 'alivetime': case 'timealive': newMsg = `Time Alive: ${playerIsAlive() ? msToTime(Date.now() - timeAlive) : 'not alive'}`; break; case 'mass': case 'currentmass': newMsg = `Current Mass: ${playerIsAlive() ? currentMass.toLocaleString('en-US') : 'none, not alive'}`; break; case 'user': case 'username': case 'usr': case 'account': case 'acc': newMsg = `My Username: ${currentUser == "Please Login First" ? "logged out" : currentUser}` break; case 'custom': case 'customs': case 'customskins': case 'totalcustoms': if($('#publicSkinsPage').children().length == 0){ curserMsg(`Please load your custom skins before using this command`, 'red', 6e3); newMsg = ''; break; } newMsg = `My Total Custom Skins: ${$('[id^="skinCustomImg"').length}, worth ${($('[id^="skinCustomImg"').length * 1e6).toLocaleString('en-US')}` break; case 'skins': case 'boughtskins': case 'ownedskins': case 'totalskins': { if($('#skinsBuy [id^="skinContainer"]').length == 0){ curserMsg(`Please load your owned skins from the agma.io skin store`, 'red', 6e3); newMsg = ''; break; } let ownedSkinsArr = [], edSkins = 0, totalValue = 0; $('#skinsBuy [id^="skinUseBtn"]').each(function(){ ownedSkinsArr.push(+$(this)[0].id.match(/\d+$/gm)[0]); }) for(let i of skinsArr){ if(ownedSkinsArr.includes(i.id)){ i.price > 2e6 ? ++edSkins : totalValue += i.price; } } newMsg = `My Total Bought Skins: ${$('#skinsBuy [id^="skinUseBtn"').length}, worth ${totalValue.toLocaleString('en-US')} coins (${edSkins} lim. ed.)`; break; } case 'ownedwearables': case 'wearables': case 'wears': case 'totalwearables': case 'totalwears': { if(!$('#fsfb-wearsloaded').length){ curserMsg(`Please load your wearables before using this command`, 'red', 6e3); newMsg = ''; // aft break; } let wearsPrice = [0], edSkins = 0; $('[id^="wearableUseBtn"]').each(function(){ if ($(this).parents().eq(0).siblings('p').text() == '(Limited Edition)') edSkins++; wearsPrice.push(+$(this).parents().eq(0).siblings('span.win-price').text().replace(/,/g, '')); }); newMsg = `My Total Wearables: ${$('[id^="wearableUseBtn"]').length}, worth ${sigma(wearsPrice).toLocaleString('en-US')} coins (${edSkins} lim. ed.)`; break; } case 'cloak': case 'invis': case 'invisibility': { let status, time; $('#infoContent>p').each(function(){ if($(this).text().includes('Cloaked: ')) status = $(this).text().match(/(?<=Cloaked: ).+/gm); if($(this).text().includes('Cloak Time: ')) time = $(this).text().match(/(?<=Cloak Time: ).+/gm); }) newMsg = status == null || time == null ? `Cloak: inactive` : `Cloak ${status}, with ${time} remaining`; break; } case 'addfriend': case 'add': if(params?.length == 0){ curserMsg(`Please add a username after the command, such as: ${userPreferences.chatPrefix}${command} Fishyyy`, 'red', 6e3); newMsg = ''; break; } unsafeWindow.friendAdd(params[0]); break; case 'partymembers': case 'partymember': case 'party': newMsg = $('#partyContent').children().length - 1 > 0 ? `In a party, with ${$('#partyContent').children().length - 1} members` : `Party members: not in a party`; break; case 'players': case 'ply': case 'plyrs': case 'serverplayers': case 'totalplayers':{ let plyr_max = [0, 0]; // players[0] | maxplayers[1] $('[id^="serverPlayers"]').each(function(){ plyr_max = plyr_max.map((n, i) => n + +this.innerText.split('/')[i]); }); let serverBots = getServerValue('bots') ?? 0, totalbots = 0; for(let server in svInfo){ totalbots += (svInfo[server].bots ?? 0); } newMsg = `Server Players: ${$('[id^="serverRow"].active>[id^="serverPlayers"]').text()}${serverBots ? ` (${serverBots} bots)` : ''}, Total Players: ${plyr_max[0].toLocaleString('en-US') + '/' + plyr_max[1].toLocaleString('en-US')} ${totalbots ? `(${totalbots} bots)` : ''}`; break; } case 'server': newMsg = `Currently playing in ${$('[id^="serverRow"].active>*').first().text()}`; break; case 'abil': case 'abils': case 'ability': case 'abilities': { // not finished let arr = [], newStr = ''; $('.checkmark').each(function(){ if($(this).css('display') == 'block') arr.push($(this).siblings().eq(1).attr('item')); }) if(misc_settings.abil?.[currentUser] != null || arr.length){ const abil = misc_settings.abil?.[currentUser], map = { 18: 'Freeze', 22: 'Invis Cloak', 20: '2x Spawn', 23: '2x Exp' } if(currentUser == "Please Login First"){ newMsg = `Active Abilities: none`; break; } for(let i of arr) newStr += map[i] + (abil?.[i] != null && 8.64e7 - (Date.now() - abil[i]) > 0 ? (' with ' + msToTime(8.64e7 - (Date.now() - abil[i])) + ' left, ') : ', '); newMsg = `Active Abilities: ${newStr == '' ? 'none' : newStr}`; newMsg = newMsg.replace(/,[^,]*$/g, ''); } else { newMsg = `Active Abilities: none`; } break; } case 'xpproj': case 'xpprojected': case 'projectedxp': case 'projxp': case 'levelprojected': case 'lvlproj': case 'lvlprojected': { const projectedHr = lastHrXP.length > 0 ? sigma(getProperty(lastHrXP.slice(-5), "gained")) * 12 : 0; newMsg = `Next Hour Projected XP: ${xpStatsInPercentages ? round(convertToPerc(projectedHr, currentLevel) * 100, 2) + '%' : round(projectedHr).toLocaleString('en-US')}`; break; } case 'projcoins': case 'projcoin': case 'projectedcoin': case 'projectedcoins': case 'coinsproj': case 'coinproj': case 'coinprojected': case 'coinsprojected': { const projectedHr = lastHrCoins.length > 5 ? Math.round(sigma(getProperty(lastHrCoins.slice(-5), "gained")) * 12) : 0; newMsg = `Next Hour Projected Coins: ${projectedHr.toLocaleString('en-US')}`; break; } case 'xpremaining': case 'xprem': case 'remainingxp': case 'remxp': { const xpRemaining = currentLevel ? currentLevel * 1e3 - currentPercent * currentLevel * 1e3 : 0, newMsg = `XP Remanining: ${xpStatsInPercentages ? round(convertToPerc(xpRemaining, currentLevel) * 100, 2) + '%' : round(xpRemaining).toLocaleString('en-US')}`; break; } case 'coinsremaining': case 'coinsrem': case 'remainingcoins': case 'remcoins': { const coinsRemaining = currentCoins ? 25e4 - currentCoins % 25e4 : 0; newMsg = `Coins Remanining: ${coinsRemaining.toLocaleString('en-US')}`; break; } case 'xplasthour': case 'lasthourxp': case 'hrxp': case 'xphr': case 'hourxp': case 'xphour': { const lastHr = lastHrXP.length > 0 ? sigma(getProperty(lastHrXP, "gained")) : 0; newMsg = `XP Last Hour: ${xpStatsInPercentages ? round(convertToPerc(lastHr, currentLevel) * 100, 2) + '%' : round(lastHr).toLocaleString('en-US')}`; break; } case 'coinslasthour': case 'lasthourcoins': case 'hrcoins': case 'coinshr': case 'hourcoins': case 'coinshour': { const lastHr = lastHrCoins.length > 0 ? Math.round(sigma(getProperty(lastHrCoins, "gained"))) : 0 newMsg = `Coins Last Hour: ${lastHr.toLocaleString('en-US')}`; break; } case 'xplastmin': case 'xplastminute': case 'lastminxp': case 'lastminutexp': case 'minxp': case 'minutexp': case 'xpmin': { const lastMin = lastMinXP.length > 0 ? sigma(getProperty(lastMinXP, "gained")) : 0; newMsg = `XP Last Minute: ${xpStatsInPercentages ? round(convertToPerc(lastMin, currentLevel) * 100, 2) + '%' : round(lastMin).toLocaleString('en-US')}`; break; } case 'coinslastmin': case 'coinslastminute': case 'lastmincoins': case 'lastminutecoins': case 'coinsxp': case 'minutecoins': case 'coinsmin': { const lastMin = lastMinCoins.length > 0 ? Math.round(sigma(getProperty(lastMinCoins, "gained"))) : 0; newMsg = `Coins Last Minute: ${lastMin.toLocaleString('en-US')}`; break; } case 'xplast12s': case 'xplast12sec': case 'xplast12seconds': case 'last12secondsxp': case 'lastminutexp': case 'xp12s': case '12sxp': case 'xp12sec': { const last12sec = lastMinXP.length > 0 ? lastMinXP[lastMinXP.length - 1].gained : 0; newMsg = `XP Last 12 Seconds: ${xpStatsInPercentages ? round(convertToPerc(last12sec, currentLevel) * 100, 2) + '%' : round(last12sec).toLocaleString('en-US')}`; break; } case 'xpsession': case 'sessionxp': case 'xpsesh': case 'sesh': case 'seshxp': case 'online': { const sessionXP = currentXP && accounts[currentUser] ? currentXP - accounts[currentUser].xp : 0; newMsg = `Session XP: ${xpStatsInPercentages ? round(currentLevel && accounts[currentUser] ? ((round(currentPercent, 3) + currentLevel) - accounts[currentUser].lvl) * 100 : 0, 2) + '%' : round(sessionXP).toLocaleString('en-US')}, Session Length: ${msToTime(Date.now() - scriptStartXP)}`; break; } case 'lifetimexp': case 'xplifetime': newMsg = `Lifetime XP: ${round(currentXP ?? 0).toLocaleString('en-US')}`; break; case 'coinssession': case 'sessioncoins': case 'coinssesh': case 'seshcoins': { const sessionCoins = currentCoins && accounts[currentUser] ? Math.round(currentCoins - accounts[currentUser].coins): 0; newMsg = `Session Coins: ${sessionCoins.toLocaleString('en-US')}, Session Length: ${msToTime(Date.now() - scriptStartCoins)}`; break; } case 'ratewaifu': case 'waifu': case 'waifurating': case 'waifurate': case 'howwaifu': cmdVerif = false; if(params?.length == 0){ if(currentUser == "Please Login First"){ newMsg = `My Waifu Rating: 0 / 10`; break; } newMsg = `My Waifu Rating: ${Math.round(+String(Math.round(hashCode(currentUser, 5) * 102.2)).slice(-3, -1) / 10)} / 10`; break; } newMsg = `${params[0]}'s Waifu Rating: ${Math.round(+String(Math.round(hashCode(params[0], 5) * 102.2)).slice(-3, -1) / 10)} / 10`; break; case 'ratepro': case 'pro': case 'prorating': case 'prorate': case 'howpro': cmdVerif = false; if(params?.length == 0){ if(currentUser == "Please Login First"){ newMsg = `I am 0% pro`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 5) * 194.3)).slice(-4, -1) / 10)}% pro`; break; } newMsg = `${params[0]} is ${Math.round(+String(Math.round(hashCode(params[0], 5) * 194.3)).slice(-4, -1) / 10)}% pro`; break; case 'ratedog': case 'dog': case 'dograting': case 'dograte': case 'howdog': cmdVerif = false; if(params?.length == 0){ if(currentUser == "Please Login First"){ newMsg = `I am 0% dog`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 6) * 189.3)).slice(-4, -1) / 10)}% dog`; break; } newMsg = `${params[0]} is ${Math.round(+String(Math.round(hashCode(params[0], 6) * 189.3)).slice(-4, -1) / 10)}% dog`; break; case 'rateking': case 'king': case 'kingrating': case 'kingrate': case 'howking': cmdVerif = false; if(params?.length == 0){ if(currentUser == "Please Login First"){ newMsg = `I am 0% king`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 5) * 389.3)).slice(-4, -1) / 10)}% king`; break; } newMsg = `${params[0]} is ${Math.round(+String(Math.round(hashCode(params[0], 5) * 389.3)).slice(-4, -1) / 10)}% king`; break; case 'dice': case 'die': case 'roll': case 'rolldice': { const sides = params?.length == 0 || isNaN(+params[0]) ? 6 : +params[0]; newMsg = `Rolled a dice with ${sides.toLocaleString('en-US')} sides, landed on ${Math.round(RNG(1, sides)).toLocaleString('en-US')}`; break; } case 'rng': case 'random': case 'randomnumber': case 'number': case 'num': { const min = params?.length < 1 || isNaN(+params[0]) ? 0 : +params[0]; const max = params?.length < 2 || isNaN(+params[1]) ? min + 10 : +params[1]; if(min > max){ curserMsg(`Please make sure your minimum (${min}) is less than your maximum (${max})`, 'red', 5e3); newMsg = ''; break; } newMsg = `Generated a random number between ${min.toLocaleString('en-US')} and ${max.toLocaleString('en-US')}, chose: ${Math.round(RNG(min, max)).toLocaleString('en-US')}`; break; } case 'ratefriends': case 'friendsrating': case 'friendsrate': case 'howfriends': cmdVerif = false; if(params?.length == 0){ if(currentUser == "Please Login First"){ newMsg = `I am 0% friends with a frog`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 4) * 283.7)).slice(-4, -1) / 10)}% friends with a frog`; break; } if(params?.length == 1){ if(currentUser == "Please Login First"){ newMsg = `I am 0% friends with a ${params[0]}`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 4) * 283.7) + Math.round((hashCode(params[0], 5) * 405.2))).slice(-4, -1) / 10)}% friends with a ${params[0]}`; break; } else { newMsg = `${params[0]} is ${Math.round(+String(Math.round(hashCode(params[0], 4) * 283.7) + Math.round((hashCode(params[0], 5) * 405.2))).slice(-4, -1) / 10)}% friends with ${params[1]}`; break; } case 'rateenemies': case 'enemiesrating': case 'enemiesrate': case 'howenemies': case 'enemies': cmdVerif = false; if(params?.length == 0){ if(currentUser == "Please Login First"){ newMsg = `I am 0% enemies with a frog`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 4) * 164.45)).slice(-5, -2) / 10)}% enemies with a frog`; break; } if(params?.length == 1){ if(currentUser == "Please Login First"){ newMsg = `I am 0% enemies with a ${params[0]}`; break; } newMsg = `I am ${Math.round(+String(Math.round(hashCode(currentUser, 4) * 164.45) + Math.round((hashCode(params[0], 5) * 405.2))).slice(-5, -2) / 10)}% enemies with a ${params[0]}`; break; } else { newMsg = `${params[0]} is ${Math.round(+String(Math.round(hashCode(params[0], 4) * 164.45) + Math.round((hashCode(params[0], 5) * 405.2))).slice(-5, -2) / 10)}% enemies with ${params[1]}`; break; } case 'flip': case 'coinflip': case 'heads': case 'tails': case 'flipcoin': { newMsg = `Coin flipped! Landed on ${Math.round(RNG(0, 1)) ? 'heads' : 'tails'}`; break; } case 'script': case 'version': case 'fsfb': case 'v': newMsg = `Using fsfb script! Version ${version}` break; case 'time': case 'localtime': case 'localetime': case 'date': newMsg = `My Time: ${new Date().toLocaleString()}` break; case 'leaderboard': case 'leader': case 'lb': newMsg = `My leaderboard position: ${!playerIsAlive() || leaderboardPos == null ? 'none, not alive' : leaderboardPos}`; break; case 'altcaps': case 'altcap': case 'altscaps': case 'altscap': newMsg = isolatedMsg.toLowerCase().split('').map((v, i) => i % 2 == 0 ? v : v.toUpperCase()).join(''); cmdVerif = false; break; case 'sparkles': case 'sprk': newMsg = '✨' + isolatedMsg + '✨'; cmdVerif = false; break; case 'cfix': case 'canvasfix': { document.querySelectorAll('canvas').forEach(canvas => ({ innerWidth: canvas.width, innerHeight: canvas.height } = unsafeWindow)); // const canvas = document.querySelector('#canvas'); // ({ innerWidth: canvas.width, innerHeight: canvas.height } = unsafeWindow); curserMsg('Canvas was reset.', 'green', 5e3); newMsg = ''; break; } case 'solo': case 'soloserver': // message from Miracle Scripts (another great agma script) - https://greasyfork.org/scripts/391142 newMsg = ':warning: SOLO SERVER :warning: No teaming!! No hay equipo!! Pas d\'équipe!! Kein Teaming!! لا فريق'; cmdVerif = false; break; case 'facts': case 'fact': case 'funfact': { const fact = randomFact(); newMsg = fact ? randomFact() : ''; fact ?? curserMsg(`Fsfb is unable to access the list of facts. Possible cause: not using tampermonkey or not using the latest version of tampermonkey.`, 'red', 6e3); break; } case 'fastsplit': case 'fs': case 'fastsplits': case 'fastsplitdelay': case 'delay': { const fs = settings.fastsplit_hotkeys; newMsg = `My fast onesplit delays: ${fs[1].val}, ${fs[2].val}; fast double: ${fs[4].val}, ${fs[5].val}; fast triple: ${fs[7].val}, ${fs[8].val}`; break; } case "dailyprogress": case "dailychallenge": case "progress": case "challengeprogress": case "challenge": case "challenges": { let progress = +$("#challengeProgress").text(); let goal = +$("#challengeGoal").text(); let percent = ((progress / goal) * 100).toFixed(1); newMsg = `Daily Challenge Progress: ${progress.toLocaleString('en-US')} / ${goal.toLocaleString('en-US')} (${percent}% completed)`; break; } case "sp": case "sorapoint": case "sorapoints": case "sps": { let soraPoints = +$('.sora-points-inv.chall-mythic').text(); newMsg = `Sora Points: ${soraPoints.toLocaleString('en-US')}`; break; } case "keys": case "key": case "challengekeys": case "challengekey": { let challengeKeys = +$('.mystery-keys.chall-mythic').text(); newMsg = `Challenge Keys: ${challengeKeys.toLocaleString('en-US')}`; break; } case "stars": case "challengestars": case "challengestar": case "star": { let challengeStars = +$('.challenge-stars.chall-mythic').text(); newMsg = `Challenge Stars: ${challengeStars.toLocaleString('en-US')}`; break; } case "lastshout": case "lshout": $chtbox.blur(); if(shouts.length == 0){ swal({ title: "No shouts detected.", type: "error" }); } else { let shout = shouts[shouts.length-1]; let wasRemoved = false; if(shout.isModerator == true && shouts.length >= 2){ shout = shout[shouts.length-2]; wasRemoved = true; } swal({ title: "Last shout info:", text: ` Nickname: ${shout.name} \n Message: ${shout.message} \n Translated: ${shout.messageTranslated} \n Time: ${(new Date(shout.time)).toString()} \n Was Removed: ${wasRemoved ? "Yes" : "No"} `, type: "info" }); newMsg = ""; } $chtbox.blur(); break; case "allshouts": case "dumpshouts": { $chtbox.blur(); console.log("Collected shouts:"); for(let shout of shouts){ console.log(` Nickname: ${shout.name} Message: ${shout.message} Translated: ${shout.messageTranslated} Time: ${(new Date(shout.time)).toString()} `); newMsg = ""; } console.log("Total: ", shouts.length , "shouts"); swal({ title: "Dumped " + shouts.length + " shouts into console.", type: "info" }); break; } default: newMsg = $chtbox.val(); return; } } // (unsafeWindow.kfjsdafl != null) ? $chtbox.val(newMsg) : $chtbox.val(''), console.log(newMsg);; $chtbox.val(newMsg == '' ? '' : originalMsg + (newMsg?.[cmdVerif ? 'replace' : '']?.(/[youaie](?!.: )/gmi, m => cmap[m]) || newMsg)); }) } // check if player is alive let playerAlive = false, timeAlive; const playerIsAlive = () => playerAlive && $('#advert').css('display') != 'none' ? false : playerAlive; unsafeWindow.playerIsAlive = playerIsAlive; const _setNick = unsafeWindow.setNick; unsafeWindow.setNick = function(){ if(userPreferences.messageBanWarning && /a\s*g\s*a\s*r\s*p\s*o\s*w\s*e\s*r/gmi.test(arguments[0])){ curserMsg("FSFB WARNING: FSFB script has censored your nickname as it has detected that your nickname may've contained a word/phrase that agma.io gives a 24 hour IP ban for. This FSFB feature can be disabled in the tampermonkey script settings.", 'red', 1e4); const newNick = (arguments[0].replace(/a\s*g\s*a\s*r\s*p\s*o\s*w\s*e\s*r/gmi, match => '*'.repeat(match.length))); arguments[0] = newNick; document.getElementById('nick').value = newNick; } if(settings.name_color[0].active && settings.name_color[1].active && arguments[0] != '' && (!/^\[(?:\W{3}|\W{6})\]/gmi.test(arguments[0]) || arguments[0] === document.querySelector('#nick')?.value)){ // check if name already has color tag const tag = `[${encodeCustomNameColor(settings.name_color[1].color)}${settings.name_color[2].active ? encodeCustomNameColor(settings.name_color[2].color) : ''}]`; arguments[0] = tag + arguments[0]; } if(arguments[1] || !playerAlive) timeAlive = Date.now(); // respawned playerAlive = true; setTimeout(() => { svSwitch = true }, 1000); return _setNick.apply(this, arguments); } const _closeAdvert = unsafeWindow.closeAdvert unsafeWindow.closeAdvert = function(){ playerAlive = false; return _closeAdvert.apply(this, arguments); } const getPowerMessage = line => { let obj = {}; [1, 2, 3].forEach(n => (obj[`string${n}`] = `Inv (${n}/?): `)); updatePwCount(); const newPws = { Recombine: pws.rec, Speed: pws.spd, Growth: pws.grw, Virus: pws.vrs, Mothercell: pws.mtcl, Portal: pws.prtl, 'Gold Block': pws.gblk, Freeze: pws.fz, Push: pws.psh, Wall: pws.wall, 'Anti-Freeze': pws.afz, 'Anti-Recombine': pws.arc, Shield: pws.shld, 'Frozen Virus': pws.fvs } for(let i in newPws){ let add = newPws[i] == '' ? '' : `${newPws[i]} ${i}, `; if(obj.string1.length + add.length <= 100) obj.string1 += add; else if(obj.string2.length + add.length <= 100) obj.string2 += add; else obj.string3 += add; } if(obj.string1 == `Inv (1/?): ` && line == 1) return 'Inv (1/1): no powers'; if(obj['string' + line] == `Inv (${line}/?): `){ curserMsg(`This inventory line doesn't exist! Try a smaller number`, 'red', 6e3); return ''; } let totalLines = 1; if(obj.string3 == 'Inv (3/?): ' && obj.string2 != 'Inv (2/?): ') totalLines = 2; else if(obj.string3 != 'Inv (3/?): ' && obj.string2 != 'Inv (2/?): ') totalLines = 3; return obj['string' + line].replace(/,[^,]*$/g, '').replace(/\?/g, totalLines); } let pws = {rec: '', spd: '', grw: '', vrs: '', mtcl: '', prtl: '', gblk: '', fz: '', psh: '', wall: '', afz: '', arc: '', shld: '', fvs: ''}; const updatePwCount = () => { $('.inventory-box').each(function(){ const map = { Wall : 'wall', AntiFreeze: 'afz', AntiRecombine: 'arc', Shield: 'shld', FrozenVirus: 'fvs', Recombine: 'rec', Speed: 'spd', Growth: 'grw', SpawnVirus: 'vrs', SpawnMothercell: 'mtcl', SpawnPortal: 'prtl', SpawnGoldOre: 'gblk', Freeze: 'fz', '360Shot': 'psh' } if(map[$(this)[0]?.id.slice(3)] != null) pws[map[$(this)[0].id.slice(3)]] = $(this).css('display') != 'none' ? $(this).children().eq(0).text() || '1' : ''; }) } $('#fsfb-export-btn').on('click', () => { if(!$('#fsfb-sect-imexport>label>input').is(':checked')) return void(curserMsg('You need to select at least one setting to export!', 'red')); if($('#fsfb-custom-bg').is(':checked')) curserMsg('Exporting settings with a custom background is likely to increase the file size', 'red', 8e3); let script_settings = {}, script_themes = {}; for (let i in settings) { // put the settings & themes into different objects if (i == "theme" || i == "theme_boxes" || i == "name_color") script_themes[i] = settings[i]; else if (i != "export_import") script_settings[i] = settings[i]; } let bgImg = null; const downloadFile = () => { let obj = { selected: { game_settings: $('#fsfb-game-settings').is(':checked'), game_controls: $('#fsfb-game-controls').is(':checked'), game_background: $('#fsfb-custom-bg').is(':checked'), script_settings: $('#fsfb-script-settings').is(':checked'), script_theme: $('#fsfb-theme-settings').is(':checked') }, game_settings: localStorage.settings, game_controls: localStorage.hotkeys, game_background: bgImg, script_settings: script_settings, script_theme: script_themes } // if the setting is turned off, then dont need to export it - set it to null for(let i in obj){ if(i != 'selected' && !obj.selected[i]) obj[i] = null; } const a = document.createElement('a'), file = new Blob([JSON.stringify(obj)], {type: "text/plain"}); a.href = URL.createObjectURL(file); a.download = "fsfb script settings"; a.click(); URL.revokeObjectURL(a.href); // download a txt file of exported settings } if($('#fsfb-custom-bg').is(':checked')){ let db, req = unsafeWindow.indexedDB.open("AgmaDB", 1); req.onsuccess = function (x) { db = req.result; db.onclose = (c) => { db = null; } db.onversionchange = (c) => { db.close(), db = null; } let _ = db.transaction("general", "readonly").objectStore("general").get("cbgDataURL"); _.onsuccess = () => { bgImg = _.result; downloadFile(); } }, req.onupgradeneeded = function (c) { let req = c.target.result; if (!req.objectStoreNames.contains("general")) { req.createObjectStore("general"); downloadFile(); } else downloadFile(); }; } else { downloadFile(); } }); $('#fsfb-import-btn').on('click', () => { if(!$('#fsfb-sect-imexport>label>input').is(':checked')) return void(curserMsg('You need to select at least one setting to import!', 'red')); if($('#fsfb-custom-bg').is(':checked')) curserMsg('Pasting in settings that include a background image is likely to cause initial lag', 'red', 0); swal({ title: "Import Settings", text: "Add your exported settings below and press OK to continue.", type: "input", showCancelButton: true, closeOnConfirm: false, animation: "slide-from-top", inputPlaceholder: "Paste exported settings here" }, function(inputVal){ if (inputVal == null) return false; if (inputVal == "") { swal.showInputError("Please don't leave the input empty!"); return false } try { let val = JSON.parse(inputVal); if(val.selected.script_settings && $('#fsfb-script-settings').is(':checked')){ for (let i in val.script_settings) { for (let j in val.script_settings[i]) { for(let x in settings){ for(let y in settings[x]){ if(val.script_settings[i][j].id == settings[x][y].id) settings[x][y] = val.script_settings[i][j]; } } } } } if(val.selected.script_theme && $('#fsfb-theme-settings').is(':checked')){ for (let i in val.script_theme) { for (let j in val.script_theme[i]) { for(let x in settings){ for(let y in settings[x]){ if(val.script_theme[i][j].id == settings[x][y].id) settings[x][y] = val.script_theme[i][j]; } } } } } if(val.selected.game_settings && $('#fsfb-game-settings').is(':checked')) localStorage.setItem('settings', val.game_settings); if(val.selected.game_controls && $('#fsfb-game-controls').is(':checked')) localStorage.setItem('hotkeys', val.game_controls); if(val.selected.game_background && $('#fsfb-custom-bg').is(':checked')){ let db, req = unsafeWindow.indexedDB.open("AgmaDB", 1); req.onsuccess = function (x) { db = req.result; db.onclose = (c) => { db = null; } db.onversionchange = (c) => { db.close(), db = null; } let _ = db.transaction("general", "readwrite").objectStore("general").put(val.game_background, "cbgDataURL"); }, req.onupgradeneeded = function (c) { let req = c.target.result; if (!req.objectStoreNames.contains("general")) { req.createObjectStore("general"); } }; } // if any agma controls were imported, need to refresh bc it's set using localstorage if((val.selected.game_settings && $('#fsfb-game-settings').is(':checked')) || (val.selected.game_controls && $('#fsfb-game-controls').is(':checked')) || (val.selected.game_background && $('#fsfb-custom-bg').is(':checked'))){ swal({ title: "Please Refresh!", text: "Refreshing the page is required for your imported agma settings to take effect", type: "warning", }); } else swal({ title: "Settings Successfully Imported!", type: "success" }); saveSettings(); styleActiveSettings(); updateScriptSettingsUI(); } catch (error){ swal({ title: "Something went wrong!", text: "Please make sure you've entered in valid settings", type: "error" }); } }); }); $('#fsfb-settings-right').append(`
`) if(userPreferences.hideAds){ localStorage.ad_l_time = "9e99"; // smth like time since last ad $('[id^="agma-io_"], [id^="adWrapper"], #preroll').addClass("fsfb-removeAds"); // move ads way off the screen } else if(localStorage.ad_l_time == "9e99")localStorage.ad_l_time = Date.now(); let {innerWidth: width, innerHeight: height} = unsafeWindow; $(unsafeWindow).on('resize', () => ({innerWidth: width, innerHeight: height} = unsafeWindow)); let pointMove; const linesplit = () => { if(!linesplitting) return; let closest, points = [{n: "top", x: width / 2, y: 0, nx: width / 2, ny: -10e6}, {n: "bottom", x: width / 2, y: height, nx: width / 2, ny: 10e6}, {n: "left", x: 0, y: height / 2, nx: -10e6, ny: height / 2}, {n: "right", x: width, y: height / 2, nx: 10e6, ny: height / 2}]; if(userPreferences.linesplitClosestSide){ let closestSide = [mosY / height, (height - mosY) / height, mosX / width, (width - mosX) / width]; // top, bottom, left, right closest = points[closestSide.indexOf(Math.min(...closestSide))]; } else { let distance = p => Math.sqrt(Math.pow(mosX - p.x, 2) + Math.pow(mosY - p.y, 2)), closestPoint = points.reduce((a, b) => distance(a) < distance(b) ? a : b); for (let i = 0; i < points.length; i++) { if (closestPoint.x == points[i].x && closestPoint.y == points[i].y) closest = points[i] } } pointMove = {x: closest.nx, y: closest.ny}; $('#canvas').trigger($.Event('mousemove', { clientX: closest.nx, clientY: closest.ny })); $("#linesplit-markers div").css('background-color', 'transparent'); $('#linesplit-' + closest.n).css('background-color', '#e25615'); } let confBtns = document.getElementsByClassName('purchase-btn confirmation'); const btnsArr = Array.from(document.getElementsByClassName('purchase-btn confirmation')); const changeHTML = (index, price, id, name) => { setTimeout(() => { const amtDropdown = document.getElementById('shopAmountDropdown') document.getElementsByClassName('sweet-alert showSweetAlert')[0].childNodes[7].firstChild.textContent = 'If you click "Buy", you will purchase this item. It will cost ' + price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ' in total.'; const dropdownChange = () => { if (amtDropdown.value == "custom") return buyCstmAmt(price, id, name); let priceSum = (amtDropdown.value * price).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); document.getElementsByClassName('sweet-alert showSweetAlert')[0].childNodes[7].firstChild.textContent = 'If you click "Buy", you will purchase this item. It will cost ' + priceSum + ' in total.'; }; amtDropdown.addEventListener('change', dropdownChange); }, 50); }; const buyCstmAmt = (price, id, name) => { swal({ title: "Enter Purchase Amount", text: "How many " + name + " would you like to buy?", html: true, type: "input", showCancelButton: true, closeOnConfirm: false, inputPlaceholder: "Input amount here" }, function(input){ let pwAmt = +input, priceTotal = pwAmt * price; if (input == null) return false; if (input == "") { swal.showInputError("Please don't leave the input empty!"); return false } if(!/^[0-9]+$/.test(input) || !(+input >>> 0 === parseFloat(+input))){ swal.showInputError("Please only enter positive integers!"); return false } swal({ title: ' Confirm ', text: '

If you click "Buy", you will purchase this item. It will cost ' + priceTotal.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ' in total.
You chose to purchase ' + pwAmt.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + ' ' + name + '

', html: true, type: 'warning', showCancelButton: true, closeOnConfirm: true, confirmButtonColor: '#4caf51', confirmButtonText: 'Yes, confirm purchase', cancelButtonText: 'No, cancel purchase' }, function(confirmed){ if(confirmed && $('.confirm').is(':visible')) buyPw(id, pwAmt); }) }); }; // buy a certain amount of powers including > 255 const buyPw = (shopID, pwAmt) => { if (pwAmt < 1) return; if (pwAmt > 255) { for (let i = 0; i < ~~(pwAmt / 255); i++) setTimeout(() => purchaseItem(shopID, 255), 500 * i + 250); purchaseItem(shopID, pwAmt % 255); } else purchaseItem(shopID, pwAmt); }; if(userPreferences.improvedShop){ // add event listeners to dropdown buttons for (let i = 0; i < confBtns.length; i++) { confBtns[i].onclick = function () { setTimeout(() => { if (document.getElementById('shopAmountDropdown') != null) document.getElementById('shopAmountDropdown').innerHTML += ' '; }, 5); } } // add event listeners to shop buttons for (let i = 0; i < 16; i++) { if (i != 10 && i != 11){ btnsArr[i].addEventListener('click', function(e){ if(!e.isTrusted && !quickBuying) return; let index = i; changeHTML(index, btnsArr[index].getAttribute('price'), btnsArr[index].getAttribute('item'), $('.purchase-btn.confirmation[item="' + btnsArr[index].getAttribute('item') + '"]').prev().find('h3').eq(0).text()); }); } } } // listen for when a min pack is bought let minBoughtAmt = {}; if(userPreferences.extraChatCommands){ let lastClickedPrice, currentPrice, lastID; const confirmClicked = () => { setTimeout(() => { if($('.sweet-alert h2').text() != "Success!" || lastClickedPrice != currentPrice) return; const map = { 1: '10 Bots 1 Hour', 2: '40 Bots 1 Hour', 3: '50 Bots 2 Hours', 4: '80 Bots 1 Hour', 5: '100 Bots 4 Hours', 6: '125 Bots 8 Hours', 7: '300 Bots 24 Hours', 8: '100 MASS Bots 1 Hour', 9: '100 Bots 24 Hours', 10: '125 Bots 48 Hours', 11: '300 Bots 72 Hours', 12: '100 MASS Bots 24 Hours' } minBoughtAmt[currentUser] = {...minsChatAmt[currentUser], ... {chatAmt: map[lastID], started: false}}; }, 900); }; $('.purchase-btn2.confirm-minion[item]').on('click', function () { lastClickedPrice = this.getAttribute('price').replace(/,/g, ''); lastID = this.getAttribute('item'); $('.confirm').attr('disabled', 'true'); // disable so user doesn't buy early - swal is slow to load text setTimeout(() => { $('.confirm').removeAttr('disabled'); currentPrice = $('.sweet-alert.showSweetAlert.visible p').eq(0).text().replace(/\D+/g, ''); }, 750); setTimeout(() => $('.confirm')[0].addEventListener('click', confirmClicked), 500); }) } // context menu: click on skin -> skin ID to clipboard, click on name -> name to clipboard $('#contextPlayer').on('click', e => { if(!userPreferences.rightClickCopyInfo) return; if($('#contextPlayerSkin').width() + $('#contextPlayerSkin').offset().left + 5 > e.pageX){ // bcs #contextMenu event :dog: // cell was clicked if($('#contextPlayerSkin').css('background-image') != "none"){ let skinID = $('#contextPlayerSkin').css('background-image').match(/(?<=\/skins\/)[0-9]+/gm)[0]; // get the skin image, then match only the skin's ID navigator.clipboard.writeText(skinID).then(function() { curserMsg('Skin ID of ' + skinID + ' was copied to your clipboard.', 'green'); }, function() { curserMsg('Something went wrong. Nothing was added to your clipboard.', 'red'); }); } else if($('#contextPlayerSkin').css('background-color') == 'rgb(51, 51, 51)') curserMsg('No player selected. Nothing was added to your clipboard.', 'red'); else curserMsg('No skin equipped. Nothing was added to your clipboard.', 'red'); } else { // name was clicked if($('#contextPlayerSkin').css('background-color') == 'rgb(51, 51, 51)') curserMsg('No player selected. Nothing was added to your clipboard.', 'red'); else { navigator.clipboard.writeText($('#contextPlayerName').text()).then(function() { curserMsg('Nickname: "' + $('#contextPlayerName').text() + '" was copied to your clipboard', 'green'); }, function() { curserMsg("Something went wrong. Nothing was added to your clipboard.", "red"); }); } } }); // little bar at the top of the screen that tells u stuff let curserTimeout; function curserMsg(msg, color, time, html){ let colorTable = { "green": "rgb(0, 192, 0)", "red": "rgb(255, 0, 0)", "gray": "rgb(153, 153, 153)", "yellow": "rgb(255, 170, 0)", "orange": "rgb(255, 149, 0)", "lightgray": "rgb(194, 194, 194)", "white": "rgb(255, 255, 255)", "purple": "rgb(190, 138, 255)" } color = colorTable[color]; clearTimeout(curserTimeout); $('#curser')[(html ?? false) ? "html" : "text"](msg).show().css('color', color) if(time != 0) curserTimeout = setTimeout(() => $('#curser').fadeOut(400), time ?? 4e3); } unsafeWindow.curserMsg = curserMsg; let minTimeRemaining = 0; const startMin = unsafeWindow.strMin; unsafeWindow.strMin = function(){ minsStart(); return startMin.apply(this, arguments); } let minsChatAmt = {}, accGoldMem = {}; const minsStart = async() => { let minAmt, minsStarted = false; const waitUntil1 = (condition) => new Promise(resolve => { let interval = setInterval(() => { $('#infoContent').children().each(function(){ if($(this).text().includes('Minion Time:')) minsStarted = true; }) condition() && (clearInterval(interval), resolve()); }, 100); setTimeout(() => { (clearInterval(interval), resolve()); }, 1e4); }); await waitUntil1(() => minsStarted == true); if(!minsStarted) return; $('#infoContent').children().each(function(){ if($(this).text().includes('Minion Time:')) minTimeRemaining = $(this).find('span').text(); if($(this).text().includes('Minions:')) minAmt = $(this).find('span').text(); }) let timeArr = minTimeRemaining.split(':'), msBotsTime = (3.6e6 * +timeArr[0]) + (6e4 * +timeArr[1]) + (1e3 * +timeArr[2]); misc_settings.bots[currentUser] = {...misc_settings.bots[currentUser], ...{active: true, amt: minAmt, chatAmt: null, rem: msBotsTime, currMs: Date.now()}}; setStorage("fsfb-misc", misc_settings); } // ability time remaining if(userPreferences.showRemainingAbilityTime){ let lastID; const abilityIds = [18, 20, 22, 23]; abilityIds.forEach(id => { const h5 = $(`.purchase-btn.confirmation[item="${id}"]`).parents().eq(0).find('div h5'); h5.clone().insertAfter(h5).addClass('fsfb-fake').hide(); const checkmarkImg = $(`.purchase-btn.confirmation[item="${id}"]`).parent().find(".checkmark:first"); $(`.purchase-btn[item="${id}"]`).on('click', function () { lastID = this.getAttribute('item'); const hadAbilityBefore = checkmarkImg.is(":visible"); setTimeout(() => { const isVisibleNow = $(`.purchase-btn.confirmation[item="${id}"]`).parent().find(".checkmark:first").is(":visible"); if(!hadAbilityBefore && isVisibleNow){ // purchase successful, set timer misc_settings.abil[currentUser] = {...misc_settings.abil[currentUser], ...{[lastID] : Date.now()}}; setStorage("fsfb-misc", misc_settings); } }, 2500) }); }); } // sort wearables by owned const waitUntil = condition => new Promise(resolve => { let interval = setInterval(() => { condition() && (clearInterval(interval), resolve()); }, 100); setTimeout(() => { (clearInterval(interval), resolve()) }, 15e3); }); if(userPreferences.sortWearablesByOwned){ $('#wearablesTab').on('click', async() => { await waitUntil(() => $('#phpWearables li').length > 55); if($('#phpWearables li').length <= 55) return; $($('[id^="wearableUseBtn"]').get().reverse()).each(function(){ $($(this).parents().get(2)).insertBefore($("#phpWearables li:eq(0)")); }) $('#phpWearables').append('
'); }); } // https://stackoverflow.com/questions/2424191/how-do-i-make-an-element-draggable-in-jquery $.fn.draggable = function(){ var $this = this, ns = 'draggable_'+(Math.random()+'').replace('.',''), mm = 'mousemove.'+ns, mu = 'mouseup.'+ns, $w = $(unsafeWindow), isFixed = ($this.css('position') === 'fixed'), adjX = 0, adjY = 0; $this.mousedown(function(ev){ let zoom = parseFloat($this.css('zoom')) || 1; var pos = $this.offset(); if (isFixed) { adjX = $w.scrollLeft(); adjY = $w.scrollTop(); } var ox = (ev.pageX - pos.left) / zoom, oy = (ev.pageY - pos.top) / zoom; $this.data(ns,{ x : ox, y: oy }); $w.on(mm, function(ev){ ev.preventDefault(); ev.stopPropagation(); if (isFixed) { adjX = $w.scrollLeft(); adjY = $w.scrollTop(); } var offset = $this.data(ns); $this.css({ left: Math.round((ev.pageX - adjX - offset.x * zoom) / zoom), top: Math.round((ev.pageY - adjY - offset.y * zoom) / zoom) }); }); $w.on(mu, function(){ $w.off(mm + ' ' + mu).removeData(ns); }); }); return this; }; /* xp/coins statistics */ const updateTimeXP = 12e3; // xp bar updates every 12 seconds, don't change let lastMinXP = []; let lastHrXP = []; let currentPercent, currentLevel, currentXP, currentCoins; unsafeWindow.logStatsScriptXP = !1; unsafeWindow.logStatsScriptCoins = !1; let scriptStartCoins = Date.now(); let scriptStartXP = Date.now(); let accounts = {}; const guiDisplay = "none"; let coinsHTMLactive = false; const updateTimeCoins = 6e3; let lastMinCoins = []; let lastHrCoins = []; // add stats box html const statsBody = document.createElement('div'); statsBody.setAttribute('id', 'stats-container'); statsBody.style.display = guiDisplay; statsBody.innerHTML = `
XP Stats - Updating Every 12s
0/0
100,000
0
100,000
100,000
100,000
100,000
100,000
100,000
100,000
100,000
100,000
100,000
`; document.querySelector('body').append(statsBody); $("#stats-container").draggable(); let statsboxPos = misc_settings?.statsPos ?? {top: $("#stats-container")[0].style.top, left: $("#stats-container")[0].style.left}; if(userPreferences.saveStatsBoxPosition && statsboxPos) $("#stats-container").css({'top' : statsboxPos.top, 'left' : statsboxPos.left}); const convertToPerc = (xpAmt, lvl = 0) => isNaN(xpAmt / (lvl * 1000)) ? 0 : xpAmt / (lvl * 1000); $('#stats-reset-btn').on('click', () => { if(coinsHTMLactive){ lastMinCoins = []; lastHrCoins = []; for(let i in accounts) accounts[i].coins = 0; if(accounts[currentUser] !== null && currentUser !== 'Please Login First') accounts[currentUser].coins = currentCoins; scriptStartCoins = Date.now(); } else { lastMinXP = []; lastHrXP = []; for(let i in accounts){ accounts[i].xp = 0; accounts[i].lvl = 0; } if(accounts[currentUser] !== null && currentUser !== 'Please Login First'){ accounts[currentUser].xp = currentXP; accounts[currentUser].lvl = round(currentPercent, 3) + currentLevel; } scriptStartXP = Date.now(); } updateUI(); }); let xpStatsInPercentages = false; $('#stats-perc-btn').on('click', () => { xpStatsInPercentages = !xpStatsInPercentages; updateUI(); }); let changingShownStats = false; $('#stats-change-shown').on('click', () => { changingShownStats = !changingShownStats; if(changingShownStats){ $('#stats-table tr').show(); _replaceCSS('stats-input-css', '#stats-table input{ display: unset; }'); } else { for(let i in misc_settings.statsSettings[coinsHTMLactive ? 'coins' : 'xp']){ misc_settings.statsSettings[coinsHTMLactive ? 'coins' : 'xp'][i] = $(`#stats-${i} input[type="checkbox"]`).is(':checked'); $('#stats-' + i)[$(`#stats-${i} input[type="checkbox"]`).is(':checked') ? 'show' : 'hide'](); } setStorage("fsfb-misc", misc_settings); _replaceCSS('stats-input-css', '#stats-table input{ display: none; }'); } }); class StatLog { constructor(val, lvl, user, arr) { this.type = this.findWhich(arr); // mostly for debugging this.id = this.getID(arr); this.user = user; this.amount = val; this.gained = this.calcGain(val, arr, this.id); this.lvl = lvl; // this.timestamp = Date.now(); // mostly for debugging } findWhich(arr) { return ((arr == lastMinXP || arr == lastHrXP ? "xp " : "coins " ) + (arr == lastHrXP || arr == lastHrCoins ? "hour" : "minute")); } calcGain(val, arr, id){ const prevObj = arr[arr.length - 1]; if(prevObj && arr == lastHrXP && id == 1) return round(sigma(getProperty(lastMinXP, "gained")), 3); if(prevObj && arr == lastHrCoins && id == 1) return round(sigma(getProperty(lastMinCoins, "gained")), 3); return prevObj && val - prevObj.amount >= 0 && prevObj.user == this.user && prevObj.amount != 0 ? round(val - prevObj.amount, 3) : 0; } getID(arr) { return arr[arr.length - 1] ? arr[arr.length - 1].id + 1 : 1; } } const xpInfo = () => { currentPercent = $('.progress-bar[role=progressbar]')[0].style.width.slice(0, -1) / 100; currentLevel = +$('#level.user-level')[0].textContent; currentXP = (levelSum(currentLevel) + currentLevel * currentPercent) * 1e3; } const coinsInfo = () => { currentCoins = +($('#coinsDash')[0].textContent.replace(/ /g, '')); } const updateUI = () => { if(changingShownStats) return; if(!coinsHTMLactive){ const xpHr = lastHrXP.length, xpMin = lastMinXP.length, lvlCompleted = currentPercent ? String(Math.round(currentPercent * currentLevel * 1e3, 1)).replace(/\B(?=(\d{3})+(?!\d))/g, ",") + "/" + (currentLevel * 1e3).toLocaleString('en-US') : "0/0", xpRemaining = currentLevel ? currentLevel * 1e3 - currentPercent * currentLevel * 1e3 : 0, projectedHr = xpHr > 0 ? sigma(getProperty(lastHrXP.slice(-5), "gained")) * 12 : 0, lastHr = xpHr > 0 ? sigma(getProperty(lastHrXP, "gained")) : 0, lastHrCompleted = xpHr > 0 ? xpHr : 0, lastMin = xpMin > 0 ? sigma(getProperty(lastMinXP, "gained")) : 0, lastMinCompleted = xpMin > 0 ? xpMin : 0, lastMinTotal = 6e4 / updateTimeXP, last12sec = xpMin > 0 ? lastMinXP[lastMinXP.length - 1].gained : 0, xBar = xpHr > 0 ? mean(getProperty(lastHrXP, "gained")) : 0, xTilde = xpHr > 0 ? median(getProperty(lastHrXP, "gained")) : 0, standardDev = xpHr > 0 ? standardDeviation(getProperty(lastHrXP, "gained")) : 0, outliers = xpHr > 0 ? checkOutliers(getProperty(lastHrXP, "gained")) : 0, sessionXP = currentXP && accounts[currentUser] ? currentXP - accounts[currentUser].xp : 0, sessionLength = msToTime(Date.now() - scriptStartXP), lifetimeXP = currentXP ? Math.round(currentXP) : 0, updateTime = updateTimeXP; document.getElementById('stats-table').innerHTML = ` ${lvlCompleted.toLocaleString('en-US')} ${xpStatsInPercentages ? round(convertToPerc(xpRemaining, currentLevel) * 100, 2) + '%' : round(xpRemaining).toLocaleString('en-US')} ${xpStatsInPercentages ? round(convertToPerc(projectedHr, currentLevel) * 100, 2) + '%' : round(projectedHr).toLocaleString('en-US')} ${xpStatsInPercentages ? round(convertToPerc(lastHr, currentLevel) * 100, 2) + '%' : round(lastHr).toLocaleString('en-US')}(${lastHrCompleted}/60) ${xpStatsInPercentages ? round(convertToPerc(lastMin, currentLevel) * 100, 2) + '%' : round(lastMin).toLocaleString('en-US')}(${lastMinCompleted + "/" + lastMinTotal}) ${xpStatsInPercentages ? round(convertToPerc(last12sec, currentLevel) * 100, 2) + '%' : round(last12sec).toLocaleString('en-US')} ${xpStatsInPercentages ? round(convertToPerc(xBar, currentLevel) * 100, 2) + '%' : round(xBar).toLocaleString('en-US')} ${xpStatsInPercentages ? round(convertToPerc(xTilde, currentLevel) * 100, 2) + '%' : round(xTilde).toLocaleString('en-US')} ${xpStatsInPercentages ? round(convertToPerc(standardDev, currentLevel) * 100, 2) + '%' : round(standardDev).toLocaleString('en-US')} ${xpStatsInPercentages ? round(currentLevel && accounts[currentUser] ? ((round(currentPercent, 3) + currentLevel) - accounts[currentUser].lvl) * 100 : 0, 2) + '%' : round(sessionXP).toLocaleString('en-US')} ${sessionLength} ${lifetimeXP.toLocaleString('en-US')} `; for(let i in misc_settings.statsSettings.xp){ $('#stats-' + i)[misc_settings.statsSettings.xp[i] ? 'show' : 'hide'](); $('#stats-' + i + ' input[type="checkbox"').prop("checked", misc_settings.statsSettings.xp[i]); } $('#stats-extra-info').text(`XP Stats - Updating Every ${updateTime / 1e3}s`).css('color', '#00bbff'); $('#stats-sesh-length').text(msToTime(Date.now() - scriptStartXP)); $('#stats-perc-btn').show(); } else { const coinsHr = lastHrCoins.length, coinsMin = lastMinCoins.length, coinGoalCompleted = currentCoins ? currentCoins.toLocaleString('en-US') + "/" + Math.ceil(currentCoins / 25e4).toLocaleString('en-US') * 25e4 : 0, coinsRemaining = currentCoins ? 25e4 - currentCoins % 25e4 : 0, projectedHr = coinsHr > 5 ? Math.round(sigma(getProperty(lastHrCoins.slice(-5), "gained")) * 12) : 0, lastHr = coinsHr > 0 ? Math.round(sigma(getProperty(lastHrCoins, "gained"))) : 0, lastHrCompleted = coinsHr > 0 ? coinsHr : 0, lastMin = coinsMin > 0 ? Math.round(sigma(getProperty(lastMinCoins, "gained"))) : 0, lastMinCompleted = coinsMin > 0 ? coinsMin : 0, lastMinTotal = 6e4 / updateTimeCoins, last12sec = coinsMin > 0 ? getProperty(lastHrCoins.slice(-5), "amount")[0] : 0, xBar = coinsHr > 0 ? Math.round(mean(getProperty(lastHrCoins, "gained"))) : 0, xTilde = coinsHr > 0 ? Math.round(median(getProperty(lastHrCoins, "gained"))) : 0, standardDev = coinsHr > 0 ? Math.round(standardDeviation(getProperty(lastHrCoins, "gained"))) : 0, outliers = coinsHr > 0 ? checkOutliers(getProperty(lastHrCoins, "gained")) : 0, sessionXP = currentCoins && accounts[currentUser] ? Math.round(currentCoins - accounts[currentUser].coins): 0, sessionLength = msToTime(Date.now() - scriptStartCoins), updateTime = updateTimeCoins; document.getElementById('stats-table').innerHTML = ` ${coinsRemaining.toLocaleString('en-US')} ${projectedHr.toLocaleString('en-US')} ${lastHr.toLocaleString('en-US')}(${lastHrCompleted}/60) ${lastMin.toLocaleString('en-US')}(${lastMinCompleted + "/" + lastMinTotal}) ${xBar.toLocaleString('en-US')} ${xTilde.toLocaleString('en-US')} ${standardDev.toLocaleString('en-US')} ${sessionXP.toLocaleString('en-US')} ${sessionLength} `; for(let i in misc_settings.statsSettings.coins){ $('#stats-' + i)[misc_settings.statsSettings.coins[i] ? 'show' : 'hide'](); $('#stats-' + i + ' input[type="checkbox"').prop("checked", misc_settings.statsSettings.coins[i]); } $('#stats-extra-info').text(`Coin Stats - Updating Every ${updateTime / 1e3}s`).css('color', '#ffc800'); $('#stats-sesh-length').text(msToTime(Date.now() - scriptStartCoins)); $('#stats-perc-btn').hide(); } } $('.progress-bar').eq(1).parent()[0].style.cursor = "pointer"; if(userPreferences.coinXPstats){ $('.progress-bar').eq(1).parent().on("click", () => { const statsCont = $('#stats-container'); if(statsCont[0].style.display == "none") statsCont.fadeIn(400); else if(!coinsHTMLactive) statsCont.fadeOut(400); coinsHTMLactive = false; updateUI(); }), [$(".dash-coin.dcTopBar").eq(0), $("#coinsTopLeft"), $(".progress-bar-coins").eq(1)].forEach(el => { el.on('click', (e) => { const statsCont = $('#stats-container'); if(statsCont[0].style.display == "none") statsCont.fadeIn(400); else if(coinsHTMLactive) statsCont.fadeOut(400); coinsHTMLactive = true; updateUI(); e.stopImmediatePropagation(); }); }); } // copy chat msgs if(userPreferences.rightClickCopyChat){ $('#contextSpectate').after(`
  • Copy Chat Messages

  • `); $('#contextCopyChat').on('click', () => { let arr = chatmsgs, str = ""; if(arr != null){ for(let i of arr.reverse()) str += `${new Date(i.time).toLocaleTimeString()} ${i.name}: ${i.message}\n`; navigator.clipboard.writeText(str).then(function() { curserMsg('Chat messages were successfully added to clipboard.', 'green'); }, function() { curserMsg('Something went wrong. Nothing was added to your clipboard.', 'red'); }); } $('#contextMenu').hide(); }); } // add linesplit bubbles $('body').append(`
    `); // linesplit html // add class to all elements that need to be hidden setTimeout(() => $('#stats-container, #inventory, #chat, #minionUi, #infection_remain_zombie, #party, #challengeInfoBox, #gamemodeBox, #infoBox, #brGameContainer, #infGameContainer, #curser, #leaderboard, #minimap, #btnFriends, .innerBoxDashboard2, #fpsBox, #settingsBtn, #megaholder, #keyboard-layout, div[style^="position: fixed; right: 20px; bottom: 230px; z-index: 998;"], #linesplit_overlay, #fushykng, #art-panel').addClass("hideUI"), 4e3); // apparently sora added delay to declining requests for some reason (avoid powerup "dupe" bugs), so prob won't fix this feature // const addFriendDecline = () => { // if(!userPreferences.friendDeclineAll || currentUser == 'Please Login First') return; // $('#friendAcceptAll').text('Reject All').addClass('fsfb-temp').clone().insertAfter($('#friendAcceptAll')).attr('style', 'right: 93px;').text('Accept All').removeClass('fsfb-temp'); // $('.fsfb-temp').attr('id', 'friendRejectAll').removeAttr('onclick').removeClass('fsfb-temp'); // $('#friendRejectAll').on('click', () => { // $('#requestList>.friend>.btn-friends.remove').each(function(i){ $(this)[0].click() }) // }); // } // if(userPreferences.friendDeclineAll){ // $('#friendAcceptAll').length // $('#btnFriends').on('click', async() => { // await waitUntil(() => $('#friendAcceptAll').length > 0); // if($('#friendAcceptAll').length == 0) return; // await sleep(50); // addFriendDecline(); // }) // } let pushFn = Array.prototype.push, spliceFn = Array.prototype.splice, prop = null, specialCells = !0, customDc = false, cellProto, avgFps = 0, fpsArr = [], svSwitch = false, pubNameSwitch = false, entArr = null, chatmsgs, hideMinionMaxSize = 80; let r1Portal = { portal: null, lastMass: 0, lastMassChange: 0, lastValue: 0, room: 1 }, r2Portal = { portal: null, lastMass: 0, lastMassChange: 0, lastValue: 0, room: 2 }; let svInfo = { "default": { ejPortalMass: 12, r1Id: 1, r2Id: 7, r3Id: null, r1StartMass: 500, r2StartMass: 500, entities: [], serverType: "normal" }, 1: { // POPSPLIT entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 15300, size: 195}, {type: 1, x: 2500, y: 15000, size: 45}, {type: 2, x: 3000, y: 14500, size: 35}, {type: 3, x: 2700, y: 14600, size: 29}, // r2 {type: 0, x: 12000, y: 15500, size: 195}, {type: 1, x: 11000, y: 15000, size: 29}, {type: 2, x: 12600, y: 14900, size: 35}, {type: 2, x: 12000, y: 15200, size: 35}, {type: 2, x: 11300, y: 14900, size: 35}, {type: 3, x: 12800, y: 14500, size: 29} ], bots: 4 }, 2: { // SLOWSPLIT ejPortalMass: 20, r1Id: 1, r2Id: 14, // rightmost portal r3Id: 6, r1StartMass: 500, r2StartMass: 500, entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 7400, y: 21300, size: 195}, {type: 1, x: 3500, y: 21000, size: 45}, {type: 2, x: 5000, y: 20500, size: 35}, {type: 3, x: 3700, y: 20600, size: 29}, // r2 {type: 0, x: 14000, y: 22000, size: 195}, {type: 1, x: 11000, y: 21000, size: 29}, {type: 2, x: 11300, y: 20900, size: 35}, {type: 2, x: 12000, y: 21200, size: 35}, {type: 2, x: 12600, y: 20900, size: 35}, {type: 3, x: 12800, y: 20500, size: 29}, // r2 (2nd?) {type: 0, x: 22000, y: 21500, size: 195}, {type: 2, x: 21300, y: 21000, size: 45} ] }, 3: { // Dodgeball NA entities: [], bots: 7 }, 4: { // FASTSPLIT ejPortalMass: 20, r1Id: 1, r2Id: 14, // rightmost portal r3Id: 6, r1StartMass: 500, r2StartMass: 500, entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 7400, y: 21300, size: 195}, {type: 1, x: 3500, y: 21000, size: 45}, {type: 2, x: 5000, y: 20500, size: 35}, {type: 3, x: 3700, y: 20600, size: 29}, // r2 {type: 0, x: 14000, y: 22000, size: 195}, {type: 1, x: 11000, y: 21000, size: 29}, {type: 2, x: 11300, y: 20900, size: 35}, {type: 2, x: 12000, y: 21200, size: 35}, {type: 2, x: 12600, y: 20900, size: 35}, {type: 3, x: 12800, y: 20500, size: 29}, // r2 (2nd?) {type: 0, x: 22000, y: 21500, size: 195}, {type: 2, x: 21300, y: 21000, size: 35} ], bots: 1 }, 5: { // SPLITRUN entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 15300, size: 195}, {type: 1, x: 2500, y: 15000, size: 45}, {type: 2, x: 3000, y: 14500, size: 35}, {type: 3, x: 2700, y: 14600, size: 29}, // r2 {type: 0, x: 12000, y: 15500, size: 195}, {type: 1, x: 11000, y: 15000, size: 29}, {type: 2, x: 12600, y: 14900, size: 35}, {type: 2, x: 11300, y: 14900, size: 35}, {type: 2, x: 12000, y: 15200, size: 35}, {type: 3, x: 12800, y: 14500, size: 29} ] }, 6: { // XINSTA ejPortalMass: 12, r1Id: 1, r2Id: 6, r1StartMass: 500, r2StartMass: 500, entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 26300, size: 195}, {type: 1, x: 2500, y: 26000, size: 45}, {type: 2, x: 3000, y: 25500, size: 45}, {type: 3, x: 2700, y: 25600, size: 29}, // r2 {type: 0, x: 15000, y: 26500, size: 195}, {type: 1, x: 14000, y: 26000, size: 29}, {type: 2, x: 14300, y: 25900, size: 45}, {type: 2, x: 15000, y: 26200, size: 45}, {type: 2, x: 15600, y: 25900, size: 45}, {type: 3, x: 15800, y: 25500, size: 29} ], bots: 6 }, 7: { // XY entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 15300, size: 195}, {type: 1, x: 2500, y: 15000, size: 45}, {type: 2, x: 3000, y: 14500, size: 35}, {type: 3, x: 2700, y: 14600, size: 29}, // r2 {type: 0, x: 12000, y: 15500, size: 195}, {type: 1, x: 11000, y: 15000, size: 29}, {type: 2, x: 11300, y: 14900, size: 35}, {type: 2, x: 12000, y: 15200, size: 35}, {type: 2, x: 12600, y: 14900, size: 35}, {type: 3, x: 12800, y: 14500, size: 29} ], bots: 5 }, 8: { // INSTANT EU entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 15300, size: 195}, {type: 1, x: 2500, y: 15000, size: 45}, {type: 2, x: 3000, y: 14500, size: 35}, {type: 3, x: 2700, y: 14600, size: 29}, // r2 {type: 0, x: 12000, y: 15500, size: 195}, {type: 1, x: 11000, y: 15000, size: 29}, {type: 2, x: 11300, y: 14900, size: 35}, {type: 2, x: 12000, y: 15200, size: 35}, {type: 2, x: 12600, y: 14900, size: 35}, {type: 3, x: 12800, y: 14500, size: 29} ] }, 9: { // CR EU entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 27300, size: 195}, {type: 1, x: 2500, y: 27000, size: 45}, {type: 2, x: 3000, y: 26500, size: 35}, {type: 3, x: 2700, y: 26600, size: 29}, // r2 {type: 0, x: 12000, y: 27500, size: 195}, {type: 1, x: 11000, y: 27000, size: 29}, {type: 2, x: 11300, y: 26900, size: 35}, {type: 2, x: 12000, y: 27200, size: 35}, {type: 2, x: 12600, y: 26900, size: 35}, {type: 3, x: 12800, y: 26500, size: 29} ], bots: 8 }, 11: { // GIGANTIC 1 entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 12: { // GIANT NA entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 13: { // SS EU ejPortalMass: 13.5, r1Id: 12, //Lower room r2Id: 11, r1StartMass: 500, r2StartMass: 500, entities: [ // r1 {type: 0, x: 1500, y: 27500, size: 195}, {type: 1, x: 14000, y: 32000, size: 45}, {type: 3, x: 13200, y: 33500, size: 45}, {type: 4, x: 12500, y: 32200, size: 142}, {type: 4, x: 14500, y: 32200, size: 142}, // r2 {type: 0, x: 16000, y: 33500, size: 195}, {type: 1, x: 500, y: 24000, size: 45}, {type: 3, x: 2500, y: 24000, size: 45}, {type: 4, x: 900, y: 22000, size: 142}, {type: 4, x: 500, y: 15000, size: 224}, // r3 (?) {type: 4, x: 1200, y: 5500, size: 224}, {type: 4, x: 2000, y: 3000, size: 224}, {type: 4, x: 4000, y: 6000, size: 224}, {type: 4, x: 4500, y: 3000, size: 224}, // on map {type: 4, x: 8000, y: 3500, size: 224}, {type: 4, x: 10000, y: 4500, size: 224}, {type: 4, x: 16000, y: 3000, size: 224}, {type: 4, x: 15400, y: 2400, size: 224}, {type: 4, x: 7500, y: 19000, size: 224}, {type: 4, x: 19200, y: 14000, size: 224}, {type: 4, x: 24400, y: 24000, size: 224}, {type: 4, x: 17500, y: 14000, size: 142}, {type: 4, x: 30000, y: 16000, size: 142} ], serverType: "supersonic" }, 14: { // SS NA ejPortalMass: 13.5, r1Id: 12, //Lower room r2Id: 11, r1StartMass: 500, r2StartMass: 500, entities: [ // r1 {type: 0, x: 1500, y: 27500, size: 195}, {type: 1, x: 14000, y: 32000, size: 45}, {type: 3, x: 13200, y: 33500, size: 45}, {type: 4, x: 12500, y: 32200, size: 142}, {type: 4, x: 14500, y: 32200, size: 142}, // r2 {type: 0, x: 16000, y: 33500, size: 195}, {type: 1, x: 500, y: 24000, size: 45}, {type: 3, x: 2500, y: 24000, size: 45}, {type: 4, x: 900, y: 22000, size: 142}, {type: 4, x: 500, y: 15000, size: 224}, // r3 (?) {type: 4, x: 1200, y: 5500, size: 224}, {type: 4, x: 2000, y: 3000, size: 224}, {type: 4, x: 4000, y: 6000, size: 224}, {type: 4, x: 4500, y: 3000, size: 224}, // on map {type: 4, x: 8000, y: 3500, size: 224}, {type: 4, x: 10000, y: 4500, size: 224}, {type: 4, x: 16000, y: 3000, size: 224}, {type: 4, x: 15400, y: 2400, size: 224}, {type: 4, x: 7500, y: 19000, size: 224}, {type: 4, x: 19200, y: 14000, size: 224}, {type: 4, x: 24400, y: 24000, size: 224}, {type: 4, x: 17500, y: 14000, size: 142}, {type: 4, x: 30000, y: 16000, size: 142} ], serverType: "supersonic" }, 16: { // BR NA entities: [], bots: 7 }, 17: { // CR AS entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 27300, size: 195}, {type: 1, x: 2500, y: 27000, size: 45}, {type: 2, x: 3000, y: 26500, size: 35}, {type: 3, x: 2700, y: 26600, size: 29}, // r2 {type: 0, x: 12000, y: 27500, size: 195}, {type: 1, x: 11000, y: 27000, size: 29}, {type: 2, x: 11300, y: 26900, size: 35}, {type: 2, x: 12000, y: 27200, size: 35}, {type: 2, x: 12600, y: 26900, size: 35}, {type: 3, x: 12800, y: 26500, size: 29} ] }, 18: { // GIGA 1 entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 19: { // GIGANTIC 2 entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 20: { // CR NA entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 27300, size: 195}, {type: 1, x: 2500, y: 27000, size: 45}, {type: 2, x: 3000, y: 26500, size: 35}, {type: 3, x: 2700, y: 26600, size: 29}, // r2 {type: 0, x: 12000, y: 27500, size: 195}, {type: 1, x: 11000, y: 27000, size: 29}, {type: 2, x: 11300, y: 26900, size: 35}, {type: 2, x: 12000, y: 27200, size: 35}, {type: 2, x: 12600, y: 26900, size: 35}, {type: 3, x: 12800, y: 26500, size: 29} ] }, 21: { // EU SF BR entities: [], bots: 7 }, 23: { // GIGANTIC 3 entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 24: { // GIGANTIC 4 entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 25: { // GIANT 2 NA entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 26: { // GIGA 2 entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 37: { // MEGASPLIT EU entities: [], bots: 25 }, 38: { // Solo Agf ejPortalMass: 12, r1Id: 1, r2Id: 6, r1StartMass: 500, r2StartMass: 400, entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // room 1 {type: 0, x: 3500, y: 11500, size: 195}, {type: 1, x: 2500, y: 11500, size: 45}, {type: 2, x: 3000, y: 11000, size: 35}, {type: 3, x: 2700, y: 11100, size: 29}, // room 2 {type: 0, x: 9000, y: 11800, size: 180}, {type: 1, x: 8200, y: 10500, size: 29}, {type: 2, x: 8300, y: 10900, size: 35}, {type: 2, x: 9000, y: 11200, size: 35}, {type: 2, x: 9600, y: 10900, size: 35}, {type: 3, x: 9800, y: 10500, size: 29} ], bots: 9 }, 39: { // MEGASPLIT AS entities: [ ], bots: 12 }, 40: { // INFECTION EU entities: [], bots: 15 }, 41: { // INFECTION NA entities: [], bots: 20 }, 42: { // GIANT 3 NA entities: [ {type: 1, x: 2500, y: 2500, size: 45}, {type: 3, x: 5000, y: 33000, size: 45}, {type: 1, x: 18000, y: 18000, size: 45}, {type: 3, x: 24000, y: 12000, size: 45} ], serverType: "gigantic" }, 43: { // Instant AS entities: [ // A1 {type: 1, x: 2500, y: 2500, size: 45}, // r1 {type: 0, x: 3400, y: 15300, size: 195}, {type: 1, x: 2500, y: 15000, size: 45}, {type: 2, x: 3000, y: 14500, size: 35}, {type: 3, x: 2700, y: 14600, size: 29}, // r2 {type: 0, x: 12000, y: 15500, size: 195}, {type: 1, x: 11000, y: 15000, size: 29}, {type: 2, x: 11300, y: 14900, size: 35}, {type: 2, x: 12000, y: 15200, size: 35}, {type: 2, x: 12600, y: 14900, size: 35}, {type: 3, x: 12800, y: 14500, size: 29} ], bots: 3 } }; let noPortalSvIdList = [11, 19, 23, 24, 37, 36, 31, 29, 40, 41, 16, 15, 21, 35, 12, 25, 42, 28, 32, 22, 18, 26, 30, 39]; let currentServerId = 0; function getServerValue(value) { return (svInfo[currentServerId] && svInfo[currentServerId][value]) ? svInfo[currentServerId][value] : svInfo.default[value] } try{ for(let { isCurrent, id } of JSON.parse(localStorage.gameservers)){ if(isCurrent) currentServerId = id; } } catch {console.warn("FSFB: Failed to grab current server id.")}; function setHideMinionSize() { switch(getServerValue("serverType")){ case "gigantic": hideMinionMaxSize = 120; break; case "supersonic": hideMinionMaxSize = 150; break; case "normal": hideMinionMaxSize = 80; break; default: hideMinionMaxSize = 80; break; } } setHideMinionSize(); let ss = unsafeWindow.setserver; unsafeWindow.setserver = (sv, sn) => { playerAlive = false; setHideMinionSize(); r1Portal.portal = null; r2Portal.portal = null; svSwitch = true; ss(sv, sn); if(sn) currentServerId = sn.includes('AS | Instant') ? 43 : +sv.match(/(?<=s)\d+(?=\.agma\.io)/gm)?.[0]; } function createCell(posX, posY, type, nSize){ if(!cellProto) return null; let color, colorDimmed = "#FFFFFF", size = 0, imageId = 0, spikes = null; switch(type){ case 0: color = "#622373"; colorDimmed = "#4e1c5c"; size = nSize ? nSize : 200; imageId = 1; break; case 1: color = "#ff0000"; colorDimmed = "#cc0001"; size = nSize ? nSize : 32; spikes = {x: posX, y: posY, s: size, p: size}; imageId = 2; break; case 2: color = "#76ff54"; colorDimmed = "#66b319"; size = nSize ? nSize : 35; imageId = 3; break; case 3: color = "#ffd000"; colorDimmed = "#ccb300"; size = nSize ? nSize : 32; spikes = {x: posX, y: posY, s: size, p: size}; imageId = 4; break; case 4: color = "#00a2e8"; colorDimmed = "#0081b9"; size = nSize ? nSize : 150; imageId = 5; break; default: color = "#FFFFFF"; size = 500; }; let cell = new cellProto.constructor(); cell[prop[41]] = imageId; cell[prop[19]] = null; cell[prop[50]] = 0; cell[prop[40]] = spikes ? 1 : 0; cell[prop[26]] = null; cell[prop[52]] = false; cell[prop[53]] = false; cell[prop[39]] = []; cell[prop[57]] = 0; cell[prop[45]] = false; cell[prop[37]] = true; cell[prop[24]] = null; // name cache cell[prop[44]] = false; cell[prop[56]] = false; cell[prop[47]] = false; cell[prop[25]] = null; cell[prop[35]] = Date.now(); cell[prop[51]] = 0; cell[prop[42]] = null; cell.clanCache = null; cell.clanPart = null; cell.color = color; cell[prop[46]] = 69; cell[prop[38]] = spikes; cell[prop[33]] = 1; cell[prop[36]] = 0; cell[prop[31]] = posX; cell[prop[32]] = posY; cell[prop[3]] = 0; cell.id = 1e9; cell[prop[21]] = null; cell[prop[20]] = null; cell.massCache = null; cell[prop[11]] = size; cell.nSize = size; cell.name = null; cell.namePart = null; cell.nameSize = 0; cell.oid = 0; cell.ox = posX; cell.oy = posY; cell[prop[58]] = 0; cell.rotation = 0; cell.shape = 0; cell.size = size; cell.skinId = 0; cell.strokeSize = size + 4; cell.textDrawn = null; cell.transform = null; cell[prop[18]] = true; cell[prop[2]] = colorDimmed ? colorDimmed : dimmColor(color); cell[prop[17]] = null; cell.x = posX; cell[prop[23]] = null; cell.y = posY; cell[prop[22]] = null; cell[prop[54]] = false; cell[prop[34]] = Date.now(); cell[prop[55]] = true; return cell; } const nameColors = {}, nameStrokes = {}; let nameToIdMap = {}; let defaultColorsAmnt = 1; let colorIntComplete = false; let addedNameColors = false; let addedStrokeColors = false; let FSFB_PRIV_CUSTOM_ERROR = false; function contrastColor(hex){ let r = parseInt(hex.substring(1, 3), 16) / 255; let g = parseInt(hex.substring(3, 5), 16) / 255; let b = parseInt(hex.substring(5, 7), 16) / 255; let max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if(max == min){ h = s = 0; // achromatic } else { let d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch(max){ case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } let adjustedLum = 0.2126 * r + 0.7152 * g + 0.0722 * b; // 0 == darkest black; 1 == lightest white let lightChange = 0.5 - adjustedLum; l += lightChange >= 0 ? Math.max(lightChange, 0.3) : Math.min(lightChange, -0.4); // very subtle difference but makes extreme colors more visible return hslToHex(h * 360, s * 100, l * 100); } Object.defineProperty(Array.prototype, "fsfb_was_here", { get: function () { if(this[1] === "#FFD700"){ defaultColorsAmnt = this.length; nameColors.get = () => this; nameColors.add = color => this.push(color); nameColors.set = (index, color) => void(this[index] = color); addedNameColors = true; nameColors?.get?.()?.length === defaultColorsAmnt && nameColors.add(settings.name_color[1].color); return "#FFFFFF"; } if(this[1] === "#5C4D00"){ nameStrokes.get = () => this; nameStrokes.add = stroke => this.push(stroke); nameStrokes.set = (index, color) => void(this[index] = color); addedStrokeColors = true; nameStrokes?.get?.()?.length === defaultColorsAmnt && nameStrokes.add(settings.name_color[2].active ? settings.name_color[2].color : contrastColor(settings.name_color[1].color)); return "#000000"; } return "#FFFFFF"; // ¯\_(ツ)_/¯ } }); function customize(c){ // customize cell stuff cellProto = Object.getPrototypeOf(c); uisdoa && (unsafeWindow.__cellProto = cellProto); // this should stay independent unless sora changes the structure of cell class const methods = []; let a = c; while (a = Reflect.getPrototypeOf(a)) { const keys = Reflect.ownKeys(a); keys.forEach((k) => methods.push(k)); } let dc_fn_name = methods[7]; let dc = cellProto[dc_fn_name]; Object.defineProperty(cellProto, '_drCl', { value: dc }); Object.defineProperty(cellProto, dc_fn_name, { value: function(){ if(!customCells && !customCellsChanged && !antilagCells) return dc.apply(this, arguments); let cell = this, cT = cell.c$, cellColor = cell.color; if (antilagCells && (cT === 0 || cT === 3) && (settings.anti_lag[0].active && cell[prop[52]] && cell.nSize <= hideMinionMaxSize) || (cT === 3 && (settings.anti_lag[2].active || (settings.anti_lag[3].active && !cell[prop[37]])) && cell.color !== "#000101")){ return (cell.hidden = true); } else if(cell.hidden){ cell.hidden = false; } if(cT === 0 && !('oType' in cell)){ // second makes sure that the type wasnt changed to playerCell (mothercell showmass) // * --- name color --- * if(!addedNameColors || !addedStrokeColors){ cell.oNameColorId = cell[prop[51]]; cell[prop[51]] = "fsfb_was_here"; } else if(!colorIntComplete && cell[prop[51]] === "fsfb_was_here"){ cell[prop[51]] = cell.oNameColorId; colorIntComplete = true; // MIGHT be problematic w current implementation but can worry ab later } if(addedNameColors && addedStrokeColors && (pubNameSwitch || settings.name_color[0].active) && !cell[prop[52]] && / (?:\W{3}|\W{6}) /gmi.test(cell?.clanPart)){ let supposedColorId = nameToIdMap?.[cell.clanPart]; if(pubNameSwitch && decodeCustomNameColor(cell.clanPart, 0) != null){ // TODO: To get actual color check which box is active (getting by property is more complicated) cell[prop[51]] = 0; //cell.oNameColorId; // ? atm reverts to 0 } else if(supposedColorId){ cell[prop[51]] = supposedColorId; } else { let color_id = decodeCustomNameColor(cell.clanPart, 0); let stroke_id = decodeCustomNameColor(cell.clanPart, 1); let brevName = cell.clanPart.length === 5; if(color_id != null && (brevName || stroke_id != null)){ nameToIdMap = {...nameToIdMap, ...{[cell.clanPart]: nameColors.get().length}} if(cell[prop[51]] < defaultColorsAmnt){ cell.oNameColorId = cell[prop[51]]; } cell[prop[51]] = nameColors.get().length; nameColors.add(getColorById(color_id)); nameStrokes.add(brevName ? contrastColor(getColorById(color_id)) : getColorById(stroke_id)); }; } } if(cell[prop[52]]){ if(settings.anti_lag[1].active){ cell[prop[18]] = false; } } if(settings.theme_boxes[1].active){ if(!('oOwnCell' in cell)) cell.oOwnCell = cell[prop[45]]; cell[prop[45]] = true; } if(settings.theme_boxes[6].active){ if(!('oSpiked' in cell)) cell.oSpiked = cell[prop[56]]; cell[prop[56]] = settings.theme_boxes[6].active; } else if('oSpiked' in cell){ cell[prop[56]] = cell.oSpiked; } if(onlyCells || customCellsChanged){ if(!settings.name_color[0].active && (userPreferences.rainbowNameColor || settings.name_color[1].active) && addedNameColors && addedStrokeColors && (!("oOwnCell" in cell) ? cell[prop[45]] : cell.oOwnCell)){ if(nameColors.get().length > defaultColorsAmnt){ if(userPreferences.rainbowNameColor){ const color = hslToHex(Math.floor(Date.now() / userPreferences.rainbowNameSpeed + 180) % 360, 100, 50); nameColors.set(defaultColorsAmnt, color); nameStrokes.set(defaultColorsAmnt, dimmColor(color)); } cell[prop[51]] = defaultColorsAmnt; } else { // error if(!FSFB_PRIV_CUSTOM_ERROR) (FSFB_PRIV_CUSTOM_ERROR = true) && console.error("fsfb error, private custom name color not functioning correctly!", nameColors.length); cell[prop[51]] = 0; } // cell[prop[51]] = defaultColorsAmnt;// -> this fails when no color is put in the array!!! } if(settings.theme_boxes[2].active){ if(!('oHasImage' in cell)) cell.oHasImage = cell[prop[18]]; cell[prop[18]] = (!("oOwnCell" in cell) ? cell[prop[45]] : cell.oOwnCell) ? cell[prop[18]] : false; } else if(settings.theme_boxes[3].active){ if(!('oHasImage' in cell)) cell.oHasImage = cell[prop[18]]; cell[prop[18]] = cell[prop[45]] || cell[prop[53]] ? cell[prop[18]] : false; } else if('oHasImage' in cell){ cell[prop[18]] = cell.oHasImage; } if(settings.theme_boxes[4].active){ if(!('oName' in cell)) cell.oName = cell.name; cell.name = (!("oOwnCell" in cell) ? cell[prop[45]] : cell.oOwnCell) ? cell.name : ""; } else if(settings.theme_boxes[5].active){ if(!('oName' in cell)) cell.oName = cell.name; cell.name = cell[prop[45]] || cell[prop[53]] ? cell.name : ""; } else if('oName' in cell){ cell.name = cell.oName; } } } else if(cT === 1){ if(!('oSize' in cell)) cell.oSize = cell.nSize; // food normally doesnt have an oSize; ensures that mothercell food is correct if(foodSizeOn){ cell.nSize = cell.oSize * settings.uiScaling[1].level; cell.size = cell.oSize * settings.uiScaling[1].level; } else if(customCellsChanged) { cell.size = cell.oSize; cell.nSize = cell.oSize; } if(settings.theme[0].active){ if(!('oColor' in cell)) cell.oColor = cell.color; cell.color = settings.theme[0].color; } else if('oColor' in cell){ cell.color = cell.oColor; } } else if(cT === 2){ if(settings.theme[1].active){ if(!('oColor' in cell)) cell.oColor = cell.color; cell.color = settings.theme[1].color; } else if('oColor' in cell){ cell.color = cell.oColor; } if(settings.theme[1].active || settings.theme[2].active){ // dimmed color / stroke if(!('oColorDimmed' in cell)) cell.oColorDimmed = cell[prop[2]]; cell[prop[2]] = settings.theme[2].active ? settings.theme[2].color : settings.theme_boxes[0].active && agmaSettings.sBubbleCells ? settings.theme[1].color : dimmColor(settings.theme[1].color); // if no stroke color is set, it will just be a darker version of the virusColor } else if('oColorDimmed' in cell){ cell[prop[2]] = cell.oColorDimmed; } } else if(cT === 9){ if(settings.theme[3].active){ if(!('oColor' in cell)) cell.oColor = cell.color; cell.color = settings.theme[3].color; } else if('oColor' in cell){ cell.color = cell.oColor; } if(settings.theme[3].active || settings.theme[4].active){ // dimmed color / stroke if(!('oColorDimmed' in cell)) cell.oColorDimmed = cell[prop[2]]; cell[prop[2]] = settings.theme[4].active ? settings.theme[4].color : settings.theme_boxes[0].active && agmaSettings.sBubbleCells ? settings.theme[3].color : dimmColor(settings.theme[3].color); } else if('oColorDimmed' in cell){ cell[prop[2]] = cell.oColorDimmed; } if(settings.checkboxes[9].active){ cell[prop[46]] = 0; cell.oType = 9; cell[prop[45]] = true; cell.oOwnCell = false; dc.apply(this, arguments); cell[prop[46]] = 9; return; } } return dc.apply(this, arguments); }}); Object.defineProperty(cellProto, prop[46], { get: function() { return this.c$; }, set: function(val) { if((val === 0 || val === 3) && this.color === "#000000"){ this.color = "#000101"; } else if(val === 0 && this.color === "#622373"){ this.color = "#622374"; // give purple cells a slightly diff color to make them detectable in .stroke fn } this.c$ = val; } }); customDc = true; } function dimmColor(color) { var r = (Math.floor(parseInt(color.substring(1, 3), 16) * 0.5)).toString(16), g = (Math.floor(parseInt(color.substring(3, 5), 16) * 0.5)).toString(16), b = (Math.floor(parseInt(color.substring(5, 7), 16) * 0.5)).toString(16); if (r.length === 1) r = "0" + r; if (g.length === 1) g = "0" + g; if (b.length === 1) b = "0" + b; return "#" + r + g + b } const newSortFunc = function(oldFunc){ if(settings.theme_boxes[8].active){ return function(a, b){ const oldFuncApplied = oldFunc.apply(this, arguments), aVal = a.c$, bVal = b.c$; return ((settings.theme_boxes[7].active ? -oldFuncApplied : oldFuncApplied) > 0 || aVal === 4) && bVal !== 4 ? 1 : aVal === 4 && bVal === 4 ? 0 : -1; } } else if(settings.theme_boxes[7].active){ return function(a, b){ return -oldFunc.apply(this, arguments); } } else { return oldFunc; } } const _sort = Array.prototype.sort; Array.prototype.sort = function(oldFunc) { return oldFunc == null || typeof this[0]?.color !== "string" ? _sort.apply(this, arguments) : _sort.call(this, newSortFunc(oldFunc)); } // translate megaphone shouts let shouts = []; var jqueryAnimate = $.fn.animate; $.fn.animate = function(){ if(arguments?.[0]?.["margin-right"] === "10px"){ // shout event //console.log("shout"); (async () => { let megaphoneText = $("#megaphone_text").text(); let translatedText = await Request(megaphoneText, settings.chat_translate[3].set, settings.chat_translate[4].set); // use same languages as chat let name = $("#megaphone_name").text(), color = $("#megaphone_name").css("color"); let isTournament = color == 'rgb(255, 153, 34)' && name == 'Tournament'; let isModerator = color == 'rgb(128, 0, 128)' && name == 'Friendly'; shouts.push({ name: $("#megaphone_name").text(), message: megaphoneText, messageTranslated: translatedText || "FSFB: Translation failed.", time: Date.now(), isShout: true, // dont translate again in push intercept... lol isTournament: isTournament, isModerator: isModerator }) })(); } return jqueryAnimate.apply(this, arguments); }; // translation var UA = navigator.userAgent; var googleDomain = "translate.google.com"; var dictURL = "https://" + googleDomain + "/translate_a/single?client=t"; function init_google_value_tk() { var url = "https://" + googleDomain + "/translate_a/element.js"; GM_xmlhttpRequest({ method: "GET", url: url, onreadystatechange: function(resp) { if (resp.readyState == 4) { clearTimeout(setTimeout(function() { this.abort(); }, 2000)); if (resp.status == 200) { init_google_value_tk_parse(resp.responseText); } } } }); } function init_google_value_tk_parse(responseText) { var res = /c\._ctkk='(.+?)'/i.exec(responseText); if (res != null) { setStorage('google_value_tk', res[1]); }; } const Request = async(txt, sl = 'auto', tl = 'auto') => { return new Promise((resolve, reject) => { function parse(gTradStringArray) { var arr = JSON.parse(gTradStringArray); var translation = ''; for (let i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) translation += arr[0][i][0]; } resolve(translation); } var tk = googleTK(txt); var Url = dictURL + "&hl=auto" + "&sl=" + sl + "&tl=" + tl + "&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&otf=2&trs=1&inputm=1&ssel=0&tsel=0&source=btn&kc=3" + "&tk=" + tk + "&q=" + encodeURI(txt); var method = 'POST'; var Data = ''; var Hdr = { "User-Agent": UA, "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", "Accept-Encoding": "gzip, deflate" } var Q = Url.split('&q='); Url = Q[0]; Data = '&q=' + Q[1]; Hdr["Content-Length"] = Data.length + ''; Hdr["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8"; GM_xmlhttpRequest({ method: method, url: Url, data: Data, headers: Hdr, onload: function(resp) { try { parse(resp.responseText) } catch (e) { unsafeWindow.fsfbLogTranslateErrors && console.error("FSFB:", e); resolve(null); } } }); }); } let dURIC = unsafeWindow.decodeURIComponent, opt = [0x92933AFC, 0x75408D32]; unsafeWindow.decodeURIComponent = function(x){ if(x === "") x = opt[Math.round(Math.random())].toString(); return dURIC(x); } // return token for the new API function googleTK(text) { // view-source:https://translate.google.com/translate/releases/twsfe_w_20160620_RC00/r/js/desktop_module_main.js && TKK from HTML var uM = getStorage('google_value_tk'); if (uM == 'undefined' || uM == null) { init_google_value_tk(); uM = "427110.1469889687"; } else if (Number(uM.split('.')[0]) !== Math.floor(Date.now() / 3600000)) { init_google_value_tk(); }; var cb = "&"; var k = ""; var Gf = "="; var Vb = "+-a^+6"; var t = "a"; var Yb = "+"; var Zb = "+-3^+b+-f"; var jd = "."; var sM = function(a) { return function() { return a } } var tM = function(a, b) { for (var c = 0; c < b.length - 2; c += 3) { let d = b.charAt(c + 2); d = d >= t ? d.charCodeAt(0) - 87 : Number(d); d = b.charAt(c + 1) == Yb ? a >>> d : a << d; a = b.charAt(c) == Yb ? a + d & 4294967295 : a ^ d } return a }; var vM = function(a) { var b; if (null !== uM) { b = uM; } else { b = sM(String.fromCharCode(84)); var c = sM(String.fromCharCode(75)); b = [b(), b()]; b[1] = c(); b = (uM = unsafeWindow[b.join(c())] || k) || k } let d = sM(String.fromCharCode(116)); c = sM(String.fromCharCode(107)); d = [d(), d()]; d[1] = c(); c = cb + d.join(k) + Gf; d = b.split(jd); b = Number(d[0]) || 0; for (var e = [], f = 0, g = 0; g < a.length; g++) { var m = a.charCodeAt(g); 128 > m ? e[f++] = m : (2048 > m ? e[f++] = m >> 6 | 192 : (55296 == (m & 64512) && g + 1 < a.length && 56320 == (a.charCodeAt(g + 1) & 64512) ? (m = 65536 + ((m & 1023) << 10) + (a.charCodeAt(++g) & 1023), e[f++] = m >> 18 | 240, e[f++] = m >> 12 & 63 | 128) : e[f++] = m >> 12 | 224, e[f++] = m >> 6 & 63 | 128), e[f++] = m & 63 | 128) } a = b || 0; for (f = 0; f < e.length; f++) { a += e[f]; a = tM(a, Vb); }; a = tM(a, Zb); a ^= Number(d[1]) || 0; 0 > a && (a = (a & 2147483647) + 2147483648); a %= 1E6; return a.toString() + jd + (a ^ b); }; return vM(text); } let skinsArr, translatedCache = {}, entsAdded = false, addChatMsg; Array.prototype.push = function(){ if(this?.length && typeof this?.[0]?.approved === 'boolean' && typeof this?.[0]?.type === 'number' && typeof this?.[0]?.zIndex === 'undefined') skinsArr = this; if(this?.length && typeof this?.[0]?.id === "number" && typeof this?.[0]?.color === "string"){ // if(customCells){ let cell = this[this.length - 1], [pushedCell] = arguments; if(!prop){ prop = Object.keys(cell); uisdoa && (unsafeWindow.__prop = Object.keys(cell)); if(prop.length != 59 || prop[28] != "massCache"){ console.error("FSFB Scripts error, contact authors: ", prop.length, prop[28]); } } if((pushedCell[prop[36]] && settings.anti_lag[4].active) || (settings.anti_lag[0].active && pushedCell.hidden)) return; if(pushedCell.id === getServerValue("r1Id")){ r1Portal.portal = pushedCell; } else if(pushedCell.id === getServerValue("r2Id")){ r2Portal.portal = pushedCell; } !customDc && customize(cell); if(entsAdded && !settings.checkboxes[8].active){ for(let i = this.length - 1; i >= 0; --i) { if(this[i].id == 1e9){ this.splice(i, 1); entsAdded = false; } } } if((svSwitch || !entsAdded) && settings.checkboxes[8].active && this[0][prop[47]] && this.length > 1){ for(let i = 0; i < getServerValue("entities").length; i++){ let ent = getServerValue("entities")[i]; pushFn.apply(this, [createCell(ent.x, ent.y, ent.type, ent.size)]); } svSwitch = false; entsAdded = true; } } let applied = pushFn.apply(this, arguments); if(!(arguments[0]?.isShout) && this?.length && typeof this?.[0]?.message === 'string' && typeof this?.[0]?.name === 'string'){ //&& typeof this?.[0]?.goldMember === 'number' && typeof this?.[0]?.cache === 'object'){ chatmsgs = this; if(arguments[0]?.message && !/[youaie](?!.: )/gmi.test(arguments[0].message)) Object.entries(cmap).forEach(([key, val]) => (arguments[0].message = arguments[0].message.replace(new RegExp(val, 'g'), key))); if(userPreferences.removeColorTagsInChat && /^\[(?:\W{3}|\W{6})\]/gmi.test(arguments[0].name) && decodeCustomNameColor(...arguments[0].name.match(/^\[(?:\W{3}|\W{6})\]/gmi), 0) != null) { arguments[0].name = arguments[0].name.replace(/^\[(?:\W{3}|\W{6})\]/gmi, ''); } (async() => { if(settings.chat_translate[0].active && (settings.chat_translate[1].active || arguments[0][Object.keys(arguments[0])[0]])){ let originalMsg = arguments[0]?.untranslated ?? arguments[0].message, translatedMsg = translatedCache[settings.chat_translate[3].set + settings.chat_translate[4].set]?.[originalMsg] ?? await Request(originalMsg, settings.chat_translate[3].set, settings.chat_translate[4].set); if(translatedMsg != null) translatedCache[settings.chat_translate[3].set + settings.chat_translate[4].set] = {...translatedCache[settings.chat_translate[3].set + settings.chat_translate[4].set], ...{[originalMsg] : translatedMsg}}; if((!('untranslated' in arguments[0]) || arguments[0].translatedLang != settings.chat_translate[3].set + settings.chat_translate[4].set || arguments[0].showingOrig != settings.chat_translate[2].active) && arguments[0]?.message && translatedMsg != null){ setTimeout(() => { arguments[0].untranslated = originalMsg; arguments[0].translatedLang = settings.chat_translate[3].set + settings.chat_translate[4].set; arguments[0].showingOrig = settings.chat_translate[2].active; arguments[0].message = settings.chat_translate[2].active ? originalMsg + ' [ ' + translatedMsg + ' ]' : translatedMsg; arguments[0].filter = false; arguments[0].cache = null; }, 0); } } else { // change translate off if('untranslated' in arguments[0] && arguments[0]?.untranslated != arguments[0].message){ setTimeout(() => { arguments[0].message = arguments[0]?.untranslated; arguments[0].translatedLang = 'none'; arguments[0].filter = false; arguments[0].cache = null; }, 0); } } // addChatMsg = msg => { // if(!Array.isArray(this)) return void(console.error('fsfb: no array ):')); // pushFn.call(this, msg); // } })(); } return applied; } Array.prototype.splice = function(){ if(customCells && this.length && typeof this[0].id == "number" && typeof this[0].color == "string"){ let cell = this[arguments[0]]; if(cell == r1Portal.portal){ r1Portal.portal = null; } else if(cell == r2Portal.portal){ r2Portal.portal = null; } } return spliceFn.apply(this, arguments); } const brSetting = settings.theme[6]; const _fillStyleSetter = Object.getOwnPropertyDescriptor(CanvasRenderingContext2D.prototype, 'fillStyle').set; Object.defineProperty(CanvasRenderingContext2D.prototype, 'fillStyle', { set: function(newFillStyle) { if(brSetting.active && newFillStyle === '#CC3030'){ newFillStyle = userPreferences.rainbowBrHazard ? hslToHex(Math.floor(Date.now() / userPreferences.rainbowBrHazardSpeed) % 360, 100, 50) : brSetting.color; } else if(userPreferences.whiteBorder4BlackCells && newFillStyle === "#000101"){ this.strokeStyle = "#FFFFFF"; this.lineWidth = 12; this.stroke(); } _fillStyleSetter.call(this, newFillStyle); } }); const fillFn = CanvasRenderingContext2D.prototype.fill; CanvasRenderingContext2D.prototype.fill = function() { if(!fillCells) return fillFn.apply(this, arguments); const { globalAlpha } = this; let doStroke = true; if(globalAlpha === .04){ switch(this.fillStyle){ case "#ff0000": // rec this.strokeStyle = "#cc0001"; break; case "#76ff54": // grw this.strokeStyle = "#66b319"; break; case "#ffd000": // spd this.strokeStyle = "#ccb300"; break; case "#00a2e8": // min pack this.strokeStyle = "#0081b9"; break; case "#622373": // portal this.strokeStyle = "#4e1c5c"; break; default: doStroke = false; }; if(doStroke){ this.globalAlpha = uisdoa?.o ?? .2; this.lineWidth = 8; this.stroke(); this.globalAlpha = uisdoa?.oo ?? .1; this.shadowOffsetY = 1; // for f#&%ing curser lock } }; if(!doStroke && globalAlpha === 0.04 && settings.checkboxes[2].active){ this.strokeStyle = agmaSettings.sDark ? "#FFFFFF" : "#000000"; this.globalAlpha = 1; this.lineWidth = 30; this.stroke(); this.globalAlpha = 0.04; } else if (globalAlpha === .4 && settings.theme_boxes[0].active) { this.globalAlpha = 0.15 } return fillFn.apply(this, arguments) } const strokeFn = CanvasRenderingContext2D.prototype.stroke; CanvasRenderingContext2D.prototype.stroke = function() { if (strokeCells && this.canvas.id === "canvas") { const { strokeStyle } = this; if (strokeStyle === "#dddddd" || strokeStyle === "#333333" || strokeStyle === "#4e1c5b" /* adjusted portal cell stroke color*/) { if(settings.checkboxes[2].active) this.strokeStyle = agmaSettings.sDark ? "#FFFFFF" : "#000000"; if(this.shadowOffsetY == 1){ this.shadowOffsetY = 0; return; }; }; if (agmaSettings.sBubbleCells && settings.theme_boxes[0].active && this.lineWidth != 4) { this.lineWidth = 15 + Math.min(Math.max(avgFps - 25, 0), 10); } } return strokeFn.apply(this, arguments) } let drawImgFn = CanvasRenderingContext2D.prototype.drawImage; CanvasRenderingContext2D.prototype.drawImage = function () { if(this.globalAlpha === 0.01 && /ects\/[1-5](?:_lo)?\.p/.test(arguments[0]?.src)){ this.globalAlpha = .35; } drawImgFn.apply(this, arguments); if(settings.checkboxes[7].active && this.canvas.id === "canvas"){ if((r1Portal.portal || r2Portal.portal) && !noPortalSvIdList.includes(currentServerId) && /ects\/1(?:_lo)?\./.test(arguments[0].src)){ // using destroyed doesnt work hence splice let c = p => { if((p.portal.nSize * p.portal.nSize / 100) != p.lastMass){ p.lastMassChange = Date.now(); } p.lastMass = (p.portal.nSize * p.portal.nSize / 100); let value = Date.now() - p.lastMassChange > 200 ? ~~(((p.portal.nSize * p.portal.nSize / 100) - getServerValue("r" + p.room + "StartMass")) / getServerValue("ejPortalMass")).toString() : p.lastValue; p.lastValue = value; if(value > 9 || value < 0){ value = "?"; } this.fillStyle = value == "7" ? "#FFCC12" : "#FFFFFF"; this.globalAlpha = 1; this.font = "72px Ubuntu, serif"; this.fillText(value, p.portal.x - this.measureText(value).width / 2, p.portal.y + 20); } r1Portal.portal && c(r1Portal); r2Portal.portal && c(r2Portal); // } } } } function hue2rgb(p, q, t){ if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; }; function hslToHex(h, s, l) { h /= 360; s /= 100; l /= 100; let r, g, b; if (s === 0) { r = g = b = l; } else { const q = l < 0.5 ? l * (1 + s) : l + s - l * s; const p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } const toHex = x => { const hex = Math.round(x * 255).toString(16); return hex.length === 1 ? '0' + hex : hex; }; return `#${toHex(r)}${toHex(g)}${toHex(b)}`; } const _lineTo = CanvasRenderingContext2D.prototype.lineTo; CanvasRenderingContext2D.prototype.lineTo = function () { if(settings.theme[5].active){ if(!agmaSettings.sGrid){ // use to avoid changing color of background "grid lines" settings this.strokeStyle = userPreferences.rainbowMapBorder ? hslToHex(Math.floor(Date.now() / userPreferences.rainbowBorderSpeed) % 360, 100, 50) : settings.theme[5].color; } else { if(agmaSettings.sDark){ if(!/#(..)\1{2}/gm.test(this.strokeStyle)) this.strokeStyle = userPreferences.rainbowMapBorder ? hslToHex(Math.floor(Date.now() / userPreferences.rainbowBorderSpeed) % 360, 100, 50) : settings.theme[5].color; } else { let [, r, g, b] = this.strokeStyle.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i).map(hex => parseInt(hex, 16)); if(r > g && r > b){ this.strokeStyle = userPreferences.rainbowMapBorder ? hslToHex(Math.floor(Date.now() / userPreferences.rainbowBorderSpeed) % 360, 100, 50) : settings.theme[5].color; } } } } return _lineTo.apply(this, arguments); } const encodeCustomNameColor = (rgb) => { const r = parseInt(rgb.slice(1, 3), 16); const g = parseInt(rgb.slice(3, 5), 16); const b = parseInt(rgb.slice(5, 7), 16); const step = 0xFF / (invisUnicodeIds.length - 1); let color_id_r = ~~(r / step); let color_id_g = ~~(g / step); let color_id_b = ~~(b / step); const char1 = color_id_r % (invisUnicodeIds.length); const char2 = color_id_g % (invisUnicodeIds.length); const char3 = color_id_b % (invisUnicodeIds.length); // console.log("ec", char1, char2, char3, color_id_r, color_id_g, color_id_b, rgb); const tag = String.fromCharCode(invisUnicodeIds[char1], invisUnicodeIds[char2], invisUnicodeIds[char3]); return tag; } const decodeCustomNameColor = (clanPart, pos) => { // adjusted decode function designed to be called with cell.clanPart // designed for 3 characters / color if(!clanPart || ![5, 8].includes(clanPart.length)) return null; // clanPart starts with a space you idiot // ???? wtf - fishy const idx_1 = invisUnicodeIds.indexOf(clanPart.charCodeAt(1 + pos * 3)); const idx_2 = invisUnicodeIds.indexOf(clanPart.charCodeAt(2 + pos * 3)); const idx_3 = invisUnicodeIds.indexOf(clanPart.charCodeAt(3 + pos * 3)); if(idx_1 == -1 || idx_2 == -1 || idx_3 == -1) return null; return {r: idx_1, g: idx_2, b: idx_3}; } const getColorById = (color_id) => { const step = 0xFF / (invisUnicodeIds.length); const r = color_id.r * step; const g = color_id.g * step; const b = color_id.b * step; const rgb = "#" + (~~r).toString(16).padStart(2, '0') + (~~g).toString(16).padStart(2, '0') + (~~b).toString(16).padStart(2, '0'); return rgb; } let currentMass = 0, leaderboardPos; const _fillText = CanvasRenderingContext2D.prototype.fillText; CanvasRenderingContext2D.prototype.fillText = function() { if ((this.fillStyle == "#ffffff" || this.fillStyle == "#626262") && isNaN(arguments?.[0]) && /^Mass: \d+$/gm.test(arguments[0])){ currentMass = +arguments[0].match(/(?<=^Mass: )\d+$/gm)[0]; if(hiddenUI) arguments[0] = " "; } else if(this.canvas.id == "leaderboard" && this.fillStyle == "#ffaaaa" && /^\d+(?=\.\s)/gm.test(arguments[0])) [leaderboardPos] = arguments[0].match(/^\d+(?=\.\s)/gm); _fillText.apply(this, arguments); } const debounce = (func, timeout = 300) => { let timer; return (...args) => { clearTimeout(timer); timer = setTimeout(() => { func.apply(this, args); }, timeout); }; } const isLogged = () => currentUser != 'Please Login First'; let intervalCount = 0, currentUser, lastLoggedOut = Date.now(); // const mainInterval = setInterval(() => { const mainInterval = () => { intervalCount++; if(userPreferences.hoverShowSkinID && $('#publicSkinsPage').children().length > 0 && $('#publicSkinsPage').find('[id^="skinContainer"]>img')[0]?.title == ''){ // check if skins have loaded $('[id^="skinContainer"]').each(function(){ $(this).find('img').attr('title', $(this).attr('id').replace('skinContainer', '')); // make hover show skin ID }) $('.publicskins-nav-btn').on('click', () => { $('[id^="skinContainer"]').each(function(){ $(this).find('img').attr('title', $(this).attr('id').replace('skinContainer', '')); }) }) } if(userPreferences.sortWearablesByOwned && $('#phpWearables>li').length && !$('#fsfb-wearsloaded').length){ $($('[id^="wearableUseBtn"]').get().reverse()).each(function(){ $($(this).parents().get(2)).insertBefore($("#phpWearables li:eq(0)")); }) $('#phpWearables').append('
    ') } if(userPreferences.publicSkinSearch && $('#publicSkinsPage').children().length > 0 && !document.getElementById("fsfb-skinsearch")){ $('.publicskins-nav-bar').eq(0).after(``); // const handlePress = debounce(() => { const handlePress = () => { if(!$('#fsfb-skinsearch').val()) return void($('.btn.publicskins-nav-btn.btn-default').not('.btn-primary')[0].click()); const searchQuery = $('#fsfb-skinsearch').val(); const skinsSearchedArr = skinsArr.filter(skin => skin.type == 4 && (skin.name.toLowerCase().includes(searchQuery.toLowerCase()) || skin.id == +searchQuery)); let totalRows = Math.ceil(skinsSearchedArr.length / 4); if(totalRows == 0){ $('#publicSkinsPage tbody').html('').append('

    No Skins Found

    '); } else { $('#publicSkinsPage tbody').html(''); for(let i = 0; i < totalRows; i++) $('#publicSkinsPage tbody').append(''); let currRow = 0, currColumn = 0; for(let i of skinsSearchedArr){ if(++currColumn > 4) currRow++, currColumn = 1; $('#publicSkinsPage tr').eq(currRow).append(`

    ${softSanitize(i.name)}

    `) } } } // }, 300); let pressTimer; $('#fsfb-skinsearch').on('input', () => { clearTimeout(pressTimer); pressTimer = setTimeout(() => handlePress(), Math.round(300 / ($('#fsfb-skinsearch').val().length || 300))); }); } currentUser = $('#userCoins2')[0].innerText; let user_abil = currentUser == 'Please Login First' ? null : misc_settings.abil?.[currentUser]; if(user_abil != undefined && userPreferences.showRemainingAbilityTime){ for(let i in user_abil){ let text = $(`.purchase-btn.confirmation[item="${i}"]`).parents().eq(0).find('div h5'), active = $('#' + $(`.purchase-btn.confirmation[item="${i}"]`).parents().eq(0)[0].id + ' img').eq(1).css('display') != "none"; // has been 24h+ and the player hasn't logged out since it's expired if(Date.now() - user_abil[i] > 8.64e7 && active){ text.eq(1).text('EXPIRED IF UNLOG'); text.eq(0).find('div h5').hide(); } // has been >24h else if(Date.now() - user_abil[i] < 8.64e7 && active){ text.eq(0).hide(); text.eq(1).text(msToTime(8.64e7 - (Date.now() - user_abil[i]))).show(); } else { // has been 24h+ & player has logged out text.eq(0).find('div h5').show(); text.eq(1).find('div h5').hide(); } } } else { $('.white_shopdesc').show(); $('.white_shopdesc.fsfb-fake').hide(); } if(accounts[currentUser] == null && currentUser !== 'Please Login First'){ xpInfo(); coinsInfo(); accounts = {...accounts, ...{[currentUser] : {coins: currentCoins, xp: currentXP, lvl: round(currentPercent, 3) + currentLevel}}}; } if(accounts[currentUser] != null && accounts[currentUser].coins == 0) accounts[currentUser].coins = currentCoins; if(accounts[currentUser] != null && accounts[currentUser].xp == 0) accounts[currentUser].xp = currentXP; if(accounts[currentUser] != null && accounts[currentUser].lvl == 0) accounts[currentUser].lvl = round(currentPercent, 3) + currentLevel; if(userPreferences.coinXPstats && intervalCount % 12 == 0){ xpInfo(); lastMinXP.push(new StatLog(round(currentXP, 3), round(currentPercent, 3) + currentLevel, currentUser, lastMinXP)); const prevObjXP = lastMinXP[lastMinXP.length - 1]; if(prevObjXP && prevObjXP.id % (6e4 / updateTimeXP) == 0) lastHrXP.push(new StatLog(round(currentXP, 3), round(currentPercent, 3) + currentLevel, currentUser, lastHrXP)); if(lastMinXP.length > 6e4 / updateTimeXP) lastMinXP.shift(); if(lastHrXP.length > 60) lastHrXP.shift(); if(!coinsHTMLactive && $('#stats-container').css('display') == 'block') updateUI(); // unsafeWindow.logStatsScriptXP && console.log(lastMinXP, lastHrXP); } if(userPreferences.coinXPstats && intervalCount % 6 == 0){ coinsInfo(); lastMinCoins.push(new StatLog(currentCoins, 0, currentUser, lastMinCoins)); const lastObjCoins = lastMinCoins[lastMinCoins.length - 1]; if(lastObjCoins && lastObjCoins.id % (6e4 / updateTimeCoins) == 0) lastHrCoins.push(new StatLog(currentCoins, 0, currentUser, lastHrCoins)); if(lastMinCoins.length > 6e4 / updateTimeCoins) lastMinCoins.shift(); if(lastHrCoins.length > 60) lastHrCoins.shift(); if(coinsHTMLactive && $('#stats-container').css('display') == 'block') updateUI(); // unsafeWindow.logStatsScriptCoins && console.log(lastMinCoins, lastHrCoins); } if(userPreferences.coinXPstats && $('#stats-container').css('display') == 'block')$('#stats-sesh-length').text(msToTime(Date.now() - (coinsHTMLactive ? scriptStartCoins : scriptStartXP))) if(intervalCount % 3 == 0 && misc_settings?.statsPos != null){ statsboxPos = {top: $("#stats-container")[0].style.top, left: $("#stats-container")[0].style.left}; misc_settings.statsPos = statsboxPos; setStorage("fsfb-misc", misc_settings); } if(intervalCount % 2 == 0){ // "You have an activated bot pack available: 100 XXL Bots 1 Hours! Restart your bots before they expire!" if(chatmsgs != null && chatmsgs?.length > 2){ // "You have an activated bot pack available: 100 Bots 24 Hours! Restart your bots before they expire!" for(let i of chatmsgs){ if(i.name == '' && i.cache != null && i.cache.color2 == '#ff8100'){ if(i.message.match(/(?<=(Welcome back to Agma, )).+/g)?.[0] == currentUser){ const msgBots = $('.memberType').text() == 'GOLD MEMBER' ? chatmsgs?.[chatmsgs.indexOf(i) - 2] : chatmsgs?.[chatmsgs.indexOf(i) - 1], msgGM = $('.memberType').text() == 'GOLD MEMBER' ? chatmsgs?.[chatmsgs.indexOf(i) - 1] : null; if(msgBots?.message.includes('Restart your bots before they expire!')){ if(misc_settings.bots[currentUser] != null) misc_settings.bots[currentUser].chatAmt = msgBots.message.match(/\d+.+\d Hours/g)[0]; minsChatAmt[currentUser] = {...minsChatAmt[currentUser], ... {amt: msgBots.message.match(/\d+.+\d Hours/g)[0], started: true}}; setStorage("fsfb-misc", misc_settings); } else if(msgBots?.message.match(/(?<=(You have a new bot pack available: )).+(?=(! Start your bots in the minion panel.))/g)?.length){ if(misc_settings.bots[currentUser] != null) misc_settings.bots[currentUser].chatAmt = msgBots.message.match(/\d+.+\d Hours/g)[0]; minsChatAmt[currentUser] = {...minsChatAmt[currentUser], ... {amt: msgBots.message.match(/\d+.+\d Hours/g)[0], started: false}}; setStorage("fsfb-misc", misc_settings); } if(msgGM != null && msgGM.message.match(/(?<=You have )\d+(?= Days left of Gold Member!)/gm)?.length){ accGoldMem[currentUser] = {...accGoldMem[currentUser], ... {days: msgGM.message.match(/(?<=You have )\d+(?= Days left of Gold Member!)/gm)[0], has: true}}; } else { accGoldMem[currentUser] = {...accGoldMem[currentUser], ... {has: false}}; } } else if(i.message.match(/(?<=(You have a new bot pack available: )).+(?=(! Start your bots in the minion panel.))/g)?.length){ if(misc_settings.bots[currentUser] != null) misc_settings.bots[currentUser].chatAmt = i.message.match(/\d+.+\d Hours/g)[0]; minsChatAmt[currentUser] = {...minsChatAmt[currentUser], ... {amt: i.message.match(/\d+.+\d Hours/g)[0], started: false}}; setStorage("fsfb-misc", misc_settings); } } } } } if(currentServerId === 0){ try { for(let { isCurrent, id } of JSON.parse(localStorage.gameservers)){ if(isCurrent) currentServerId = id; } if(currentServerId !== 0) svSwitch = true; } catch {}; } uisdoa && (unsafeWindow.__currentServerId = currentServerId); if(currentUser == 'Please Login First' || $('#level').text() == 0) lastLoggedOut = Date.now(); changeTitle(settings.checkboxes[4].active ? currentUser == 'Please Login First' ? "Agma.io" : "Agma.io | " + currentUser : "Agma.io - A free multiplayer MMO game"); // if($('#friendAcceptAll').length > 0 && userPreferences.friendDeclineAll && $('#friendRejectAll').length < 1 && currentUser != 'Please Login First') addFriendDecline(); // if($('#friendDialogMessage').text() != 'Login to see your friendlist' && $('#friendDialogMessage').text() == 'Loading...' && $('#friendsRequestsAmt').text() == '' && userPreferences.friendDeclineAll && currentUser != 'Please Login First'){ // $('#btnFriends').click().click(); // } fpsArr.push(+document.getElementById("fps").innerText); if(fpsArr.length == 6) fpsArr.shift(); avgFps = mean(fpsArr); setTimeout(mainInterval, 1e3); } setTimeout(mainInterval, 1e3); // }, 1e3); const antiAFK = () => { setTimeout(antiAFK, 3e4); if(!$('#fsfb-antiAFK').is(':checked')) return; // move mouse every 30sec let [moveX, moveY] = linesplitting ? [pointMove.x, pointMove.y] : [mosX, mosY]; [++moveX, --moveX].forEach(x => $('#canvas').trigger($.Event('mousemove', {clientX: x, clientY: moveY}))); } setTimeout(antiAFK, 3e4); uisdoa ?? $('#fsfb-recospeed').parent().hide(); const updateScriptSettingsUI = () => { for(let i of settings.checkboxes) $('#' + i.id).prop("checked", i.active).trigger("change"); for(let i of settings.hotkeys) $('#' + i.id).text(getName(i.key)); for(let i of settings.quickSettings){ $('#' + i.id1).val(i.set); $('#' + i.id).text(getName(i.key)); } // slowfeed $('#' + settings.slowFeed[0].id).text(getName(settings.slowFeed[0].key)); $('#' + settings.slowFeed[1].id).val(settings.slowFeed[1].val); $('#' + settings.frozenvirus[0].id).text(getName(settings.frozenvirus[0].key)); $('#' + settings.frozenvirus[1].id).val(settings.frozenvirus[1].val); for(let i of settings.fastsplit_hotkeys){ i.val == null ? $('#' + i.id).text(getName(i.key)) : $('#' + i.id).val(i.val); } for(let i of settings.uiScaling) $('#' + i.id).val(i.level).trigger("input"); for(let i of settings.export_import) $('#' + i.id).prop("checked", i.active).trigger("change"); for(let i of settings.theme){ $('#' + i.id).prop("checked", i.active).trigger("change"); $('#' + i.id1).val(i.color).trigger("input"); } for(let i of settings.theme_boxes) $('#' + i.id).prop("checked", i.active).trigger("change"); for(let i of settings.name_color){ if('color' in i){ $('#' + i.id).prop("checked", i.active).trigger("change"); $('#' + i.id1).val(i.color).trigger("input"); } else $('#' + i.id).prop("checked", i.active).trigger("change"); } for(let i of settings.anti_lag) $('#' + i.id).prop("checked", i.active).trigger("change"); for(let i of settings.chat_translate){ 'set' in i ? $('#' + i.id).val(i.set) : $('#' + i.id).prop('checked', i.active).trigger('change'); } } setTimeout(() => updateScriptSettingsUI(), 1e3); $('body').append('
    '); const _replaceCSS = (a,b) => { document.getElementById(a).innerHTML = b; } !function(){ $('body').append(`