├── README.md ├── index.js ├── manifest.json ├── module.json ├── npcData.json ├── setting_migration.js └── skillString.json /README.md: -------------------------------------------------------------------------------- 1 | # FPS-UTILS 2 | 3 | **To support development of this mod**: 4 | Buy me a [covfefe](https://ko-fi.com/codeagon) (I can't actually drink coffee but I will eat your money) 5 | 6 | Throw money [here](https://www.patreon.com/saegusa) to show support for Saegusa, the original developer of this mod. 7 | **** 8 | - [FPS-UTILS](#fps-utils) 9 | - [BIG Note](#big-note) 10 | - [Installation](#installation) 11 | - [Commands](#commands) 12 | - [Additional command info](#additional-command-info) 13 | - [Update Log](#update-log) 14 | - [Work In Progress:](#work-in-progress) 15 | - [Suggestions](#suggestions) 16 | - [Credits](#credits) 17 | 18 | 19 | ## BIG Note 20 | FPS-Utils now comes with [badGUI support](https://github.com/codeagon/badGui), I highly recommend downloading it for additional functionality and ease of use. This update also adds a few new commands as well as fixing a couple of bugs. 21 | 22 | ## Installation 23 | ***Note***: *If you're using [Caali's proxy](https://discord.gg/maqBmJV) fps-utils will be automatically updated and already installed so you will not need to do the following.* 24 | * put the script folder "fps-utils" into bin/node_modules 25 | * Log the game using the proxy. 26 | 27 | ## Commands 28 | ***Note:*** *When inputting commands directly from the **proxy channel** the prefix `!` should be ignored.* 29 | 30 | Command | Argument(s) | Example | Description 31 | ---|---|---|--- 32 | **!fps gui** | | !fps gui| Opens up the GUI. granting access to all of these commands. 33 | **!fps party** | | !fps party| Hides all other players except those in your party 34 | **!fps gui npcsearch** | | !fps npcsearch vergos| Opens up a list of NPCs with names matching your search query 35 | **!fps mode** | 1, 2, 3, off | !fps mode 1| Sets the current fps-utils optimization state. 0 disables, 1 hides particles, 2 hides skill animations, 3 hides all players. All modes toggle`fps hit on` 36 | **!fps hit** | me, damage, other | !fps hit other | Enables/Disables hiding of hit effects for the player.`Damage`toggles damage numbers off.`Me` turns hit effects off for **you** (disables damage numbers also unfortunately), other disables effects for other users (recommended). 37 | **!fps hide** | playername, dps, healers, tanks, ranged, classname | !fps hide Spacecats, !fps hide valkyrie |hides dps, healers, tanks or ranged classes, any username or a class, class names can be found in`config.json`. 38 | **!fps show** | playername, dps, healers, tanks, ranged, classname| !fps show Memeboy | Takes the same arguments as above and instead unhides them. 39 | **!fps list** | | !fps list | Prints a list of characters/classes/roles currently hidden by *hide* command to chat. 40 | **!fps fireworks** | None | !fps fireworks | Enables/Disables hiding of firework entities in open world. 41 | **!fps servants** | None | !fps servants | Enables/Disables hiding of Pets and Partners. 42 | **!fps summons** | empty, mine | !fps summons | Enables/Disables hiding of summoned entities(gunner turrets, mystic thralls, etc) fps summons mine hides your own summons 43 | **!fps skill** | blacklist, class | !fps skill class lancer | `black` toggles the skill blacklist feature, `class `toggles displaying of ALL skills for that class 44 | **!fps npc** | None | !fps npc | Enables/Disables hiding of ALL NPCs within the npc blacklist 45 | **!fps effects** | all, blacklist | !fps effects blacklist | Toggles showing of either blacklisted abnormality effects or all abnormality effects (your own ones still display normally in all mode, however not in blacklist mode). 46 | **!fps style** | None | !fps style | Enables/Disables showing of all spawned players as wearing the same outfit. Requires leaving and re-entering the area or re-logging to take effect. 47 | **!fps proj** | all, blacklist | !fps proj all| Enables/Disables showing of all projectiles, or blacklisted one. By default hailstorm is included. 48 | 49 | ### Additional command info 50 | * A full list of skill IDs can be found [here.](https://github.com/pinkipi/skill-prediction/blob/master/config/skills.js) 51 | * A full list of NPCs and Abnormalities will be posted later. 52 | * To get projectile skill IDs you will have to log them yourself, I will add something that does this for you in a later update 53 | 54 | ## Update Log 55 | * Moved to BigInt 56 | * Fixed some other stuff idklol 57 | ## Work In Progress: 58 | Various GUI improvements, fix for mount stuff, projectile and effect lists, fix formatting. 59 | 60 | ## Suggestions 61 | * If you have suggestions, need help, or want to comment on my shitty coding, leave an issue report or message me (Hugedong69 in pinkies/caali's discord) 62 | 63 | ## Credits 64 | The following people have helped in making FPS-Utils: 65 | - [Saegusae](https://github.com/Saegusae/) - Original developer 66 | - [Bernkastel](https://github.com/Bernkastel-0/) - Whos code I stole and then rewrote because it was also broken 67 | - [SerenTera](https://github.com/SerenTera) - God coder who added a lot of features and cleaned a lot of things up 68 | - [Caali](https://github.com/hackerman-caali/) - Provided update functionality to proxy so that I can yell at less users 69 | - [Kasea](https://github.com/Kaseaa/) - Let me steal code (I hope :eyes: ) 70 | - [Kyoukaya](https://github.com/kyoukaya) - Fixed my grabo code 71 | - [SaltyMonkey](https://github.com/SaltyMonkey) - Yelled at me a bunch 72 | - [Pinkie](https://github.com/pinkipi/) - Told me dumb js things that I should know but don't because I'm dumb 73 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* global __dirname */ 2 | let BadGui 3 | 4 | try { 5 | BadGui = require('../badGui') 6 | } catch (e) { 7 | try { 8 | BadGui = require('../badGui-master') 9 | } catch (e) { 10 | console.log(`[FPS-UTILS] - badGUI not installed, GUI functionality disabled, please see the readme for more information`) 11 | } 12 | } 13 | 14 | module.exports = function FpsUtils2(mod) { 15 | const npcData = require(`./npcData.json`) 16 | const skills = require(`./skillString.json`) 17 | let data = [], 18 | gui, 19 | NASux, 20 | useGui = false, 21 | red = `#e3d6d9`, 22 | green = `#204ed3`, 23 | myId, 24 | alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''), 25 | spawnedPlayers = {}, 26 | partyMembers = [], 27 | hiddenUsers = {}, 28 | hiddenNpcs = {}, 29 | hiddenServants = {}; 30 | try { 31 | gui = new BadGui(mod); 32 | useGui = true 33 | } catch (e) { 34 | useGui = false 35 | console.log(`[FPS-UTILS] - badGUI not installed, GUI functionality disabled, please see the readme for more information`) 36 | } 37 | // ~~~ * GUI handling stuff I should put somewhere else * ~~~ 38 | 39 | function listSkills(value) { 40 | let keys = [] 41 | let data = [] 42 | let skillIds = [] 43 | data.push( 44 | { text: `Select the skills that you wish to hide
` }, 45 | { text: `Click here to return
`, command: `fps gui skills` }, 46 | { text: `[[ALL SKILLS]]`, command: `fps skills class ${value};fps gui class ${value}` } 47 | ) 48 | for (let key in skills[value]) { 49 | keys.push(key); 50 | } 51 | skillIds.push(Object.values(skills[value])) 52 | for (var i = 0; i < keys.length; i++) { 53 | data.push({ command: `fps skill class ${value} ${skillIds[0][i]};fps gui class ${value}`, text: ` [${keys[i]}]
` }) 54 | //this is by far the worse and best thing I have ever seen 55 | } 56 | return data 57 | } 58 | 59 | function search(nameKey, array, arg) { 60 | for (let i = 0; i < array.length; i++) { 61 | if (array[i].Name.startsWith(nameKey) && arg == `starts`) { 62 | data.push({ 63 | command: `fps npc hide ${array[i].HuntingZoneId} ${array[i].TemplateId};fps gui npc ${nameKey}`, text: ` [${array[i].Name}]
` 71 | }) 72 | } 73 | if (array[i].Name.includes(nameKey) && arg == `search`) { 74 | data.push({ command: `fps npc hide ${array[i].HuntingZoneId} ${array[i].TemplateId};fps gui npc ${nameKey}`, text: ` [${array[i].Name}]
` }) 75 | } 76 | if (!isNaN(arg)) {//ho boy wow what are you dooooing 77 | if (array[i].nameKey == arg) { 78 | return true 79 | } 80 | } 81 | } 82 | gui.parse(data, ` FPS-UTILS Options - NPCs`) 83 | data = [] 84 | } 85 | 86 | function classId(name) { //this should really be reused for things other than GUI but can't be without adding their bloat here or changing the structure of the commands 87 | for (let ass of Object.keys(mod.settings.classes)) { 88 | if (mod.settings.classes[ass].name == name) { 89 | return ass 90 | } 91 | } 92 | } 93 | 94 | 95 | function handleGui(page, arg) { 96 | switch (page) { 97 | case 'searchnpc': 98 | case 'npcsearch': 99 | data = [] 100 | data.push( 101 | { text: `Search results for "${arg}":
` }, 102 | { text: `Click here to return to the main menu
`, command: `fps gui` } 103 | ) 104 | search(arg, npcData, `search`) 105 | break 106 | case 'npc': 107 | data = [] 108 | data.push( 109 | { text: `Search results for "${arg}":
` }, 110 | { text: `Click here to return to the main menu
`, command: `fps gui` } 111 | ) 112 | search(arg, npcData, `starts`) 113 | break 114 | case 'npclist': 115 | data = [] 116 | data.push( 117 | { text: `Select an NPC ID to remove it from the blacklist:
` }, 118 | { text: `Click here to return to the main menu
`, command: `fps gui` }, 119 | { text: `Click here to return to the main NPC page
`, command: `fps gui npcMain` }, 120 | ) 121 | for (let i = 0; i < mod.settings.hiddenNpcs.length; i++) { 122 | data.push({ text: `${mod.settings.hiddenNpcs[i].zone}, ${mod.settings.hiddenNpcs[i].templateId}
`, command: `fps npc hide ${mod.settings.hiddenNpcs[i].zone} ${mod.settings.hiddenNpcs[i].templateId};fps gui npclist` }) 123 | } 124 | gui.parse(data, ` FPS-UTILS Options - NPCs`) 125 | break 126 | case 'npcMain': 127 | data = [] 128 | data.push( 129 | { text: `Click here to return to the main menu
`, command: `fps gui` }, 130 | { text: `Click here to list currently hidden NPCs by Zone/TemplateId
`, command: `fps gui npclist` }, 131 | { text: `[Toggle hiding of blacklisted NPCs]

`, command: `fps npc;fps gui npcMain` }, 132 | { text: `Select a letter to view all NPCs starting with that letter:
` }, 133 | { text: `You can also use the command "fps gui searchnpc [name]" to search for a specific NPC by name

` }, 134 | 135 | ) 136 | for (var i = 0; i < alphabet.length; i++) { 137 | data.push({ text: `${alphabet[i]} `, command: `fps gui npc ${alphabet[i]}` }) 138 | } 139 | gui.parse(data, ` FPS-UTILS Options - NPCs`) 140 | break 141 | case "hide": 142 | data = [] 143 | data.push( 144 | { text: `Select a player to hide them and add them to the blacklist
` }, 145 | { text: `You can also use the command "fps hide " to hide someone that does not appear here

` }, 146 | { text: `Click here to return to the main menu
`, command: `fps gui` } 147 | ) 148 | for (let i in spawnedPlayers) { 149 | data.push({ text: `${spawnedPlayers[i].name}
`, command: `fps hide ${spawnedPlayers[i].name};fps gui hide` }) 150 | } 151 | gui.parse(data, ` FPS-UTILS Options - Players`) 152 | break 153 | case "show": 154 | data = [] 155 | data.push( 156 | { text: `Select a player to unhide them and remove them from the blacklist
` }, 157 | { text: `Click here to return to the main menu
`, command: `fps gui` } 158 | ) 159 | mod.settings.blacklistedNames.forEach((mem) => { data.push({ text: `${mem}
`, command: `fps show ${mem};fps gui show` }) }) //yes this is not the best 160 | gui.parse(data, ` FPS-UTILS Options - Hidden Users`) 161 | break 162 | case "skills": 163 | gui.parse([ 164 | { text: `Hide skills by class:

` }, 165 | { text: `Click here to return to the main menu
`, command: `fps gui` }, 166 | { text: `[toggle skill blacklisting]
`, command: `fps skill black;fps gui skills` }, 167 | { text: `Hide Specific Skills (Click a class name to open up a list of its skills):
` }, 168 | { text: `Warrior
`, command: `fps gui class warrior` }, 169 | { text: `Lancer
`, command: `fps gui class lancer` }, 170 | { text: `Slayer
`, command: `fps gui class slayer` }, 171 | { text: `Berserker
`, command: `fps gui class berserker` }, 172 | { text: `Sorcerer
`, command: `fps gui class sorcerer` }, 173 | { text: `Archer
`, command: `fps gui class archer` }, 174 | { text: `Priest
`, command: `fps gui class priest` }, 175 | { text: `Mystic
`, command: `fps gui class mystic` }, 176 | { text: `Reaper
`, command: `fps gui class reaper` }, 177 | { text: `Gunner
`, command: `fps gui class gunner` }, 178 | { text: `Brawler
`, command: `fps gui class brawler` }, 179 | { text: `Ninja
`, command: `fps gui class ninja` }, 180 | { text: `Valkyrie
`, command: `fps gui class valkyrie` } 181 | ], ` FPS-UTILS Options - Skills`) 182 | break 183 | case "class": 184 | gui.parse(listSkills(arg), ` FPS-UTILS Options - Skill list for ${arg}`) 185 | break 186 | case "role": 187 | gui.parse([ 188 | { text: `Hide classes/roles:

` }, 189 | { text: `Click here to return to the main menu
`, command: `fps gui` }, 190 | { text: `Warrior
`, command: `fps ${mod.settings.hiddenClasses.includes('warrior') ? `show` : `hide`} warrior;fps gui role` }, 191 | { text: `Lancer
`, command: `fps ${mod.settings.hiddenClasses.includes('lancer') ? `show` : `hide`} lancer;fps gui role` }, 192 | { text: `Slayer
`, command: `fps ${mod.settings.hiddenClasses.includes('slayer') ? `show` : `hide`} slayer;fps gui role` }, 193 | { text: `Berserker
`, command: `fps ${mod.settings.hiddenClasses.includes('berserker') ? `show` : `hide`} berserker;fps gui role` }, 194 | { text: `Sorcerer
`, command: `fps ${mod.settings.hiddenClasses.includes('sorcerer') ? `show` : `hide`} sorcerer;fps gui role` }, 195 | { text: `Archer
`, command: `fps ${mod.settings.hiddenClasses.includes('archer') ? `show` : `hide`} archer;fps gui role` }, 196 | { text: `Priest
`, command: `fps ${mod.settings.hiddenClasses.includes('priest') ? `show` : `hide`} priest;fps gui role` }, 197 | { text: `Mystic
`, command: `fps ${mod.settings.hiddenClasses.includes('mystic') ? `show` : `hide`} mystic;fps gui role` }, 198 | { text: `Reaper
`, command: `fps ${mod.settings.hiddenClasses.includes('reaper') ? `show` : `hide`} reaper;fps gui role` }, 199 | { text: `Gunner
`, command: `fps ${mod.settings.hiddenClasses.includes('gunner') ? `show` : `hide`} gunner;fps gui role` }, 200 | { text: `Brawler
`, command: `fps ${mod.settings.hiddenClasses.includes('brawler') ? `show` : `hide`} brawler;fps gui role` }, 201 | { text: `Ninja

`, command: `fps ${mod.settings.hiddenClasses.includes('ninja') ? `show` : `hide`} ninja;fps gui role` }, 202 | { text: `DPS
`, command: `fps ${mod.settings.hiddenRoles.includes('dps') ? `show` : `hide`} dps;fps gui role` }, 203 | { text: `Healers
`, command: `fps ${mod.settings.hiddenRoles.includes('healer') ? `show` : `hide`} healer;fps gui role` }, 204 | { text: `Tanks
`, command: `fps ${mod.settings.hiddenRoles.includes('tank') ? `show` : `hide`} tank;fps gui role` }, 205 | { text: `Ranged
`, command: `fps ${mod.settings.hiddenRoles.includes('ranged') ? `show` : `hide`} ranged;fps gui role` }, 206 | ], ` FPS-UTILS Options - Hide Roles`) 207 | break 208 | case "abn": 209 | gui.parse([ 210 | { text: `Abnormality/Effect Options:

` }, 211 | { text: `Click here to return to the main menu
`, command: `fps gui` }, 212 | { text: ` [Hide ALL Abnormalities/Effects]
`, command: `fps proj all;fps gui abn` }, 213 | { text: ` [Hide ALL Anormalities/Effects in the blacklist (option to select these ingame soon, sorry!)]
`, command: `fps proj blacklist;fps gui abn` }, 214 | ], ` FPS-UTILS Options - Abnormies`) 215 | break 216 | case "proj": 217 | gui.parse([ 218 | { text: `Projectile Options:

` }, 219 | { text: `Click here to return to the main menu
`, command: `fps gui` }, 220 | { text: ` [Hide ALL Projectiles]
`, command: `fps proj all;fps gui proj` }, 221 | { text: ` [Hide ALL Projectiles in the blacklist (option to select these ingame soon, sorry!)]
`, command: `fps proj blacklist;fps gui proj` }, 222 | ], ` FPS-UTILS Options - Projectiles`) 223 | break 224 | default: 225 | gui.parse([ 226 | { text: `Red = disabled, green = enabled:
` }, 227 | { text: `Make sure you scroll down to see all the options!
:
` }, 228 | { text: `Modes (mode effects from the previous are included in the next):
` }, 229 | { text: ` [0 - Disable all other modes]
`, command: `fps mode 0;fps gui` }, 230 | { text: ` [1 - Hide all projectiles and disable hit effects for other players]
`, command: `fps mode 1;fps gui` }, 231 | { text: ` [2 - Hide skill casts]
`, command: `fps mode 2;fps gui` }, 232 | { text: ` [3 - Hide all players]

`, command: `fps mode 3;fps gui` }, 233 | { text: `Hit mode:
` }, 234 | { text: ` [Hide your own effects and damage numbers]
`, command: `fps hit me;fps gui` }, 235 | { text: ` [Hide other players hit effects]
`, command: `fps hit other;fps gui` }, 236 | { text: ` [Hide damage numbers]

`, command: `fps hit other;fps gui` }, 237 | { text: ` [Hide players not in your party]
`, command: `fps party;fps gui` }, 238 | { text: ` [Hide Servants (pets)]
`, command: `fps servants;fps gui` }, 239 | { text: ` [Hide Summons]
`, command: `fps summons;fps gui` }, 240 | { text: ` [Hide your own summons]
`, command: `fps summons mine;fps gui` }, 241 | { text: ` [Hide Fireworks]
`, command: `fps fireworks;fps gui` }, 242 | { text: ` [Hide other players costumes- requires a loading screen]

`, command: `fps style;fps gui` }, 243 | { text: `Hide Classes/Roles (click here for more options)

`, command: `fps gui role` }, 244 | { text: `Hide Skills (click here for more options)

`, command: `fps gui skills` }, 245 | { text: `Hide Players (click here for more options)

`, command: `fps gui hide` }, 246 | { text: `Show Players (click here for more options)

`, command: `fps gui show` }, 247 | { text: `NPC's (click here for more options)

`, command: `fps gui npcMain` }, 248 | { text: `Abnormalities/Effects (click here for more options)

`, command: `fps gui abn` }, //Need a less bad list/sorting method 249 | { text: `Projectiles (click here for more options)

`, command: `fps gui proj` }, //Need a better list 250 | ], ` FPS-UTILS Options`) 251 | 252 | } 253 | } 254 | 255 | // ~~~ * commands * ~~~ 256 | mod.command.add('fps', (cmd, arg, arg2, arg3) => { 257 | mod.saveSettings() // for some reason settings weren't saving so we have this here now I guess 🤷 258 | switch (cmd) { 259 | case "gui": 260 | if (useGui) { 261 | handleGui(arg, arg2); 262 | } else { 263 | message(`badGUI not installed, please see the FPS-Utils readme for more information`) 264 | } 265 | break; 266 | case "mode": 267 | case "state": 268 | switch (arg) { 269 | case "0": 270 | case "off": 271 | if (mod.settings.mode === 3) { 272 | showAll(); 273 | } 274 | mod.settings.hideAllAbnormies = false 275 | mod.settings.hitOther = false 276 | mod.settings.mode = 0; 277 | message(`All FPS improvements disabled`); 278 | break 279 | case "1": 280 | if (mod.settings.mode === 3) { 281 | showAll(); 282 | } 283 | mod.settings.mode = 1; 284 | //mod.settings.hideAllAbnormies = true; 285 | mod.settings.hitOther = true; 286 | message(`FPS mode set to 1, projectiles hidden and abnormalities disabled`); 287 | break 288 | case "2": 289 | if (mod.settings.mode === 3) { 290 | showAll(); 291 | } 292 | mod.settings.mode = 2; 293 | // mod.settings.hideAllAbnormies = true; 294 | mod.settings.hitOther = true; 295 | message(`FPS mode set to 2, all skill effects disabled`); 296 | break 297 | case "3": 298 | hideAll(); 299 | mod.settings.mode = 3; 300 | mod.settings.hideAllAbnormies = true; 301 | mod.settings.hitOther = true; 302 | message(`FPS mode set to 3, hiding all players, their effects and their hit effects.`); 303 | break 304 | default: 305 | message(`Invalid mode ${arg}, valid modes are : 0,1,2,3`); 306 | } 307 | break 308 | case "hide": 309 | if (typeof arg === "string" && arg !== null) { 310 | if (mod.settings.blacklistedNames.includes(arg)) { 311 | message(`Player "${arg}" already hidden!`); 312 | return; 313 | } else 314 | if ((mod.settings.classNames.includes(arg) && !mod.settings.hiddenClasses.includes(arg)) || (mod.settings.roleNames.includes(arg) && !mod.settings.hiddenRoles.includes(arg))) { 315 | for (let i in mod.settings.classes) { 316 | if ((mod.settings.classes[i].name === arg || mod.settings.classes[i].role.includes(arg)) && mod.settings.classes[i].isHidden !== true) { //loops are fun, right? 317 | mod.settings.classes[i].isHidden = true; 318 | if (mod.settings.classes[i].name === arg) { 319 | mod.settings.hiddenClasses.push(arg); 320 | } 321 | if (mod.settings.classes[i].role.includes(arg)) { 322 | mod.settings.hiddenRoles.push(arg); 323 | } 324 | let classtohide = mod.settings.classes[i].model; 325 | for (let i in spawnedPlayers) { 326 | if (getClass(spawnedPlayers[i].templateId) === classtohide) { 327 | hidePlayer(spawnedPlayers[i].name); 328 | } 329 | } 330 | } 331 | } 332 | message(`Class/Role ${arg} hidden`); 333 | return; 334 | } else if (mod.settings.hiddenClasses.includes(arg) || mod.settings.hiddenRoles.includes(arg)) { 335 | message(`Class/Role "${arg}" already hidden!`); 336 | return; 337 | } 338 | // if (!spawnedPlayers[arg]) { 339 | // message(`Player ${arg} not spawned in, hiding anyway!`); 340 | // } else { 341 | message(`Player "${arg}" hidden!`); 342 | // } 343 | mod.settings.blacklistedNames.push(arg); 344 | hidePlayer(arg); 345 | } else 346 | message(`Invalid name "${arg}"`); 347 | break 348 | case "show": 349 | if (typeof arg === "string" && arg !== null) { 350 | if (mod.settings.blacklistedNames.includes(arg)) { 351 | showPlayer(arg); 352 | removeName(mod.settings.blacklistedNames, arg); 353 | message(`Player "${arg}" shown!`); 354 | return; 355 | } 356 | if ((mod.settings.classNames.includes(arg) && mod.settings.hiddenClasses.includes(arg)) || (mod.settings.hiddenRoles.includes(arg) && mod.settings.roleNames.includes(arg))) { 357 | for (let i in mod.settings.classes) { 358 | if (mod.settings.classes[i].name === arg || mod.settings.classes[i].role.includes(arg)) {//loops are fun, right? 359 | if (mod.settings.classes[i].name === arg) { 360 | removeName(mod.settings.hiddenClasses, arg); 361 | } 362 | if (mod.settings.classes[i].role.includes(arg)) { 363 | removeName(mod.settings.hiddenRoles, arg); 364 | } 365 | mod.settings.classes[i].isHidden = false; 366 | let classToShow = mod.settings.classes[i].model; 367 | for (let i in hiddenUsers) { 368 | if (getClass(hiddenUsers[i].templateId) === classToShow) { 369 | showPlayer(hiddenUsers[i].name); 370 | } 371 | } 372 | 373 | } 374 | } 375 | message(`Class "${arg}" redisplayed!`); 376 | } else if (!mod.settings.hiddenClasses.includes(arg) || !mod.settings.hiddenRoles.includes(arg)) { 377 | message(`Class/Role "${arg}" already displayed!!`); 378 | } else 379 | if (!mod.settings.blacklistedNames.includes(arg)) { 380 | message(`Player "${arg}" is not hidden!`); 381 | } 382 | } 383 | break 384 | case "party": 385 | mod.settings.party = !mod.settings.party 386 | if (mod.settings.party) { 387 | for (let i in spawnedPlayers) { 388 | if (!partyMembers.includes(spawnedPlayers[i].name)) { 389 | mod.send('S_DESPAWN_USER', 3, { 390 | gameId: spawnedPlayers[i].gameId, 391 | type: 1 392 | }); 393 | hiddenUsers[spawnedPlayers[i].gameId] = spawnedPlayers[i]; 394 | } 395 | } 396 | } else { 397 | showAll() 398 | } 399 | message(`Hiding of everyone but your group ${mod.settings.party ? 'en' : 'dis'}abled`); 400 | 401 | break 402 | case "list": 403 | message(`Hidden players: ${mod.settings.blacklistedNames}`); 404 | message(`Hidden classes: ${mod.settings.hiddenClasses}`); 405 | message(`Hidden roles: ${mod.settings.hiddenRoles}`); 406 | break 407 | case "servants": 408 | mod.settings.hideServants = !mod.settings.hideServants; 409 | message(`Hiding of summoned Pets and Partners ${mod.settings.hideServants ? 'en' : 'dis'}abled`); 410 | break; 411 | case "summons": 412 | switch (arg) { 413 | case undefined: 414 | mod.settings.hideAllSummons = !mod.settings.hideAllSummons; 415 | message(`Hiding of summoned NPCs ${mod.settings.hideAllSummons ? 'en' : 'dis'}abled`); 416 | break; 417 | case "mine": 418 | mod.settings.keepMySummons = !mod.settings.keepMySummons; 419 | message(`Hiding of owned summoned NPCs ${mod.settings.keepMySummons ? 'dis' : 'en'}abled`); 420 | break; 421 | } 422 | break 423 | case "skills": 424 | case "skill": 425 | switch (arg) { 426 | case "blacklist": 427 | case "black": 428 | mod.settings.blacklistSkills = !mod.settings.blacklistSkills; 429 | message(`Hiding of blacklisted skills ${mod.settings.blacklistSkills ? 'en' : 'dis'}abled`); 430 | break 431 | case "class": 432 | if (mod.settings.classNames.includes(arg2)) { 433 | for (let i in mod.settings.classes) { 434 | if (mod.settings.classes[i].name === arg2) { 435 | if (arg3 != null && !isNaN(arg3) && arg3 < 50) { 436 | if (mod.settings.classes[i].blockedSkills.includes(arg3)) { 437 | let index = mod.settings.classes[i].blockedSkills.indexOf(arg3) 438 | if (index !== -1) { 439 | mod.settings.classes[i].blockedSkills.splice(index, 1) 440 | message(`Skill ID ${arg3} showing for class ${arg2}`) 441 | } 442 | return 443 | } else { 444 | mod.settings.classes[i].blockedSkills.push(arg3) 445 | message(`Skill ID ${arg3} hidden for class ${arg2}`) 446 | return 447 | } 448 | 449 | } else { 450 | mod.settings.classes[i].blockingSkills = !mod.settings.classes[i].blockingSkills; 451 | message(`Hidding ALL skills for the class ${arg2} ${mod.settings.classes[i].blockingSkills ? 'en' : 'dis'}abled`); 452 | return; 453 | } 454 | } 455 | } 456 | 457 | } else 458 | message(`Class ${arg2} not found!`); 459 | break 460 | } 461 | break 462 | case "npcs": 463 | case "npc": 464 | if (arg == 'hide') { 465 | let found = mod.settings.hiddenNpcs.some((s) => { 466 | return s.zone === arg2 && s.templateId === arg3; 467 | }); 468 | if (found) { 469 | message(`NPC form huntingZone "${arg2} with templateId "${arg3}" now showing`) 470 | mod.settings.hiddenNpcs = mod.settings.hiddenNpcs.filter((obj) => { 471 | return obj.zone != arg2 || obj.templateId != arg3; 472 | }) 473 | 474 | } else { 475 | message(`NPC form huntingZone "${arg2} with templateId "${arg3}" hidden`) 476 | mod.settings.hiddenNpcs.push({ zone: arg2, templateId: arg3 }) 477 | } 478 | return 479 | 480 | /*mod.settings.hiddenNpcs = mod.settings.hiddenNpcs.filter((e) => { // wow an arrow thanks eslint 481 | if (e.zone == arg2 || e.templateId == arg3) { 482 | message(`NPC form huntingZone "${arg2} with templateId "${arg3}" now showing`) 483 | return e.zone != arg2 || e.templateId != arg3 484 | } else { 485 | 486 | } 487 | }) 488 | mod.settings.hiddenNpcs.push({ zone: arg2, templateId: arg3 }) 489 | message(`NPC form huntingZone "${arg2} with templateId "${arg3}" hidden`) 490 | return*/ 491 | } else 492 | mod.settings.blacklistNpcs = !mod.settings.blacklistNpcs; 493 | message(`Hiding of blacklisted NPCs ${mod.settings.blacklistNpcs ? 'en' : 'dis'}abled`); 494 | break 495 | case "hit": 496 | switch (arg) { 497 | case "me": 498 | mod.settings.hitMe = !mod.settings.hitMe; 499 | message(`Hiding of the players skill hits ${mod.settings.hitMe ? 'en' : 'dis'}abled`); 500 | break 501 | case "other": 502 | mod.settings.hitOther = !mod.settings.hitOther; 503 | message(`Hiding of other players skill hits ${mod.settings.hitOther ? 'en' : 'dis'}abled`); 504 | break 505 | case "damage": 506 | mod.settings.hitDamage = !mod.settings.hitDamage; 507 | message(`Hiding of the players skill damage numbers ${mod.settings.hitDamage ? 'en' : 'dis'}abled`); 508 | break 509 | default: 510 | message(`Unrecognized sub-mod.command "${arg}"!`); 511 | break 512 | } 513 | break 514 | case "fireworks": 515 | case "firework": 516 | mod.settings.hideFireworks = !mod.settings.hideFireworks; 517 | message(`Hiding of firework effects ${mod.settings.hideFireworks ? 'en' : 'dis'}abled`); 518 | break 519 | case "fpsbooster9001": 520 | case "effects": 521 | case "abnormies": 522 | switch (arg) { 523 | case "all": 524 | mod.settings.hideAllAbnormies = !mod.settings.hideAllAbnormies; 525 | message(`Hiding of ALL abnormality effects on players ${mod.settings.hideAllAbnormies ? 'en' : 'dis'}abled`); 526 | break 527 | case "blacklist": 528 | case "black": 529 | mod.settings.blacklistAbnormies = !mod.settings.blacklistAbnormies; 530 | message(`Hiding of blacklisted abnormality effects ${mod.settings.blacklistAbnormies ? 'en' : 'dis'}abled`); 531 | break 532 | } 533 | break 534 | case "costume": 535 | case "style": 536 | mod.settings.showStyle = !mod.settings.showStyle; 537 | message(`Displaying of all players as wearing default costumes ${mod.settings.showStyle ? 'en' : 'dis'}abled, you will have to leave and re-enter the zone for this to take effect`); 538 | break 539 | case "proj": 540 | case "projectile": 541 | switch (arg) { 542 | case "all": 543 | mod.settings.hideProjectiles = !mod.settings.hideProjectiles; 544 | message(`Hiding of ALL projectile effects ${mod.settings.hideProjectiles ? 'en' : 'dis'}abled`); 545 | break 546 | case "blacklist": 547 | mod.settings.blacklistProjectiles = !mod.settings.blacklistProjectiles; 548 | message(`Hiding of ALL projectile effects ${mod.settings.blacklistProjectiles ? 'en' : 'dis'}abled`); 549 | break 550 | } 551 | break 552 | default: 553 | message(`Unknown command! Please refer to the readme for more information`); 554 | break 555 | } 556 | 557 | }); 558 | // ~~~ * Functions * ~~~ 559 | function message(msg) { 560 | mod.command.message(`${msg}`); 561 | } 562 | 563 | function getClass(m) { 564 | return (m % 100); 565 | } 566 | 567 | function hidePlayer(name) { 568 | for (let i in spawnedPlayers) { 569 | if (spawnedPlayers[i].name.toString().toLowerCase() === name.toLowerCase()) { 570 | mod.send('S_DESPAWN_USER', 3, { 571 | gameId: spawnedPlayers[i].gameId, 572 | type: 1 573 | }); 574 | hiddenUsers[spawnedPlayers[i].gameId] = spawnedPlayers[i]; 575 | return; 576 | } 577 | } 578 | } 579 | 580 | function removeName(name) { 581 | var what, a = arguments, L = a.length, ax; 582 | while (L > 1 && name.length) { 583 | what = a[--L]; 584 | while ((ax = name.indexOf(what)) !== -1) { 585 | name.splice(ax, 1); 586 | } 587 | } 588 | return name; 589 | } 590 | 591 | function showPlayer(name) { 592 | for (let i in hiddenUsers) { 593 | if (hiddenUsers[i].name.toString().toLowerCase() === name.toLowerCase()) { 594 | mod.send('S_SPAWN_USER', 15, hiddenUsers[i]); 595 | delete hiddenUsers[i]; 596 | return; 597 | } 598 | } 599 | } 600 | 601 | function hideAll() { 602 | if (!mod.settings.party) { 603 | for (let i in spawnedPlayers) { 604 | mod.send('S_DESPAWN_USER', 3, { 605 | gameId: spawnedPlayers[i].gameId, 606 | type: 1 607 | }); 608 | hiddenUsers[spawnedPlayers[i].gameId] = spawnedPlayers[i]; 609 | } 610 | } 611 | } 612 | 613 | function showAll() { 614 | for (let i in hiddenUsers) { 615 | mod.send('S_SPAWN_USER', 15, hiddenUsers[i]); 616 | delete hiddenUsers[i]; 617 | } 618 | } 619 | 620 | function updateLoc(event) { 621 | mod.send('S_USER_LOCATION', 5, { 622 | gameId: event.gameId, 623 | loc: event.loc, 624 | dest: event.loc, 625 | w: event.w, 626 | speed: 300, 627 | type: 7 628 | }); 629 | } 630 | 631 | // ~~~* Hooks * ~~~ 632 | // note: for skills, do if classes[event.templateId].blockedSkills !== 633 | 634 | mod.hook('S_LOGIN', mod.majorPatchVersion >= 86 ? 14 : 13, (event) => { 635 | myId = event.gameId; 636 | }); 637 | 638 | mod.game.on('leave_game', () => { 639 | clearInterval(NASux) 640 | }) 641 | mod.hook('S_SPAWN_USER', 15, { order: 9999 }, (event) => { 642 | spawnedPlayers[event.gameId] = event; 643 | if (mod.settings.mode === 3 || mod.settings.blacklistedNames.includes(event.name.toString().toLowerCase()) || mod.settings.classes[getClass(event.templateId)].isHidden === true || (mod.settings.party && !partyMembers.includes(event.name))) { //includes should work!! 644 | hiddenUsers[event.gameId] = event; 645 | return false; 646 | } 647 | if (mod.settings.showStyle) { 648 | event.weaponEnchant = 0; 649 | event.body = 0; 650 | event.hand = 0; 651 | event.feet = 0; 652 | event.underwear = 0; 653 | event.head = 0; 654 | event.face = 0; 655 | event.weapon = 0; 656 | event.showStyle = false; 657 | return true; 658 | } 659 | }); 660 | 661 | mod.hook('S_USER_EXTERNAL_CHANGE', 7, { order: 9999 }, (event) => { 662 | if (mod.settings.showStyle && event.gameId !== myId) { 663 | event.weaponEnchant = 0; 664 | event.body = 0; 665 | event.hand = 0; 666 | event.feet = 0; 667 | event.underwear = 0; 668 | event.head = 0; 669 | event.face = 0; 670 | event.weapon = 0; 671 | event.showStyle = false; 672 | return true; 673 | } 674 | }); 675 | 676 | mod.hook('S_SPAWN_USER', 15, { order: 99999, filter: { fake: null } }, (event) => { 677 | if (mod.settings.showStyle) { 678 | event.weaponEnchant = 0; 679 | event.body = 0; 680 | event.hand = 0; 681 | event.feet = 0; 682 | event.underwear = 0; 683 | event.head = 0; 684 | event.face = 0; 685 | event.weapon = 0; 686 | event.showStyle = false; 687 | return true; 688 | } 689 | }); 690 | 691 | mod.hook('S_DESPAWN_USER', 3, { order: 999 }, (event) => { 692 | delete hiddenUsers[event.gameId]; 693 | delete spawnedPlayers[event.gameId]; 694 | }); 695 | 696 | mod.hook('S_LOAD_TOPO', 'raw', () => { 697 | spawnedPlayers = {}; 698 | hiddenUsers = {}; 699 | hiddenNpcs = {}; 700 | }); 701 | 702 | mod.hook('S_LEAVE_PARTY', 1, () => { 703 | partyMembers = [] 704 | }) 705 | 706 | mod.hook('S_PARTY_MEMBER_LIST', 7, (event) => { 707 | event.members.map((value) => { 708 | partyMembers.push(value.name) 709 | }) 710 | }) 711 | 712 | mod.hook('S_SPAWN_NPC', 11, (event) => { 713 | if (mod.settings.hideAllSummons && event.huntingZoneId === 1023) { 714 | if (mod.settings.keepMySummons && mod.game.me.is(event.owner)) return true; 715 | hiddenNpcs[event.gameId] = event; // apparently NPCs get feared and crash the client too 716 | return false; 717 | } 718 | if (mod.settings.blacklistNpcs) { 719 | for (var i = 0; i < mod.settings.hiddenNpcs.length; i++) { 720 | if (event.huntingZoneId == mod.settings.hiddenNpcs[i].zone && event.templateId == mod.settings.hiddenNpcs[i].templateId) { 721 | hiddenNpcs[event.gameId] = event; 722 | return false; 723 | } 724 | } 725 | } 726 | if (mod.settings.hideFireworks && event.huntingZoneId === 1023 && (event.templateId === 60016000 || event.templateId === 80037000)) { 727 | return false; 728 | } 729 | }); 730 | 731 | mod.hook('S_DESPAWN_NPC', 3, (event) => { 732 | delete hiddenNpcs[event.gameId]; 733 | }); 734 | 735 | // servants 736 | mod.hook('S_REQUEST_SPAWN_SERVANT', 4, { order: 1000 }, (e) => { 737 | if (mod.settings.hideServants && myId !== e.ownerId) { 738 | hiddenServants[e.gameId] = e; 739 | return false; 740 | } 741 | }); 742 | 743 | mod.hook('S_REQUEST_DESPAWN_SERVANT', 1, (e) => { 744 | delete hiddenServants[e.gameId]; 745 | }); 746 | 747 | mod.hook('S_EACH_SKILL_RESULT', mod.majorPatchVersion >= 86 ? 14 : 13, { order: 200 }, (event) => { 748 | if (event.source == myId || event.owner == myId) { 749 | if (mod.settings.hitMe) { 750 | event.skill.id = 0n; 751 | return true; 752 | } 753 | if (mod.settings.hitDamage) { 754 | event.value = 0n; 755 | return true; 756 | } 757 | } 758 | if (mod.settings.hitOther && (spawnedPlayers[event.owner] || spawnedPlayers[event.source]) && event.target !== myId) { 759 | event.skill.id = ''; 760 | return true; 761 | } 762 | }); 763 | 764 | mod.hook('S_USER_LOCATION', 5, (event) => { 765 | if (hiddenUsers[event.gameId] === undefined) { 766 | return; 767 | } 768 | hiddenUsers[event.gameId].loc = event.dest; 769 | if (hiddenUsers[event.gameId]) { 770 | return false; 771 | } 772 | }); 773 | 774 | 775 | 776 | mod.hook('S_ACTION_STAGE', 9, { order: 999 }, (event) => { 777 | if (event.gameId !== myId && spawnedPlayers[event.gameId]) { 778 | if (event.target !== myId && (mod.settings.mode === 2 || hiddenUsers[event.gameId])) { 779 | updateLoc(event); 780 | return false; 781 | } 782 | if (mod.settings.blacklistSkills) { 783 | if (typeof mod.settings.classes[getClass(event.templateId)].blockedSkills !== "undefined" && mod.settings.classes[getClass(event.templateId)].blockedSkills.includes(event.skill.id / 10000).toString()) { 784 | updateLoc(event); 785 | return false; 786 | } 787 | } 788 | if (mod.settings.classes[getClass(event.templateId)].blockingSkills) { 789 | updateLoc(event); 790 | return false; 791 | } 792 | } 793 | }); 794 | 795 | mod.hook('S_START_USER_PROJECTILE', 9, { order: 999 }, (event) => { // end my life 796 | if (event.gameId !== myId && spawnedPlayers[event.gameId] && (hiddenUsers[event.gameId] || mod.settings.mode > 0 || mod.settings.hideProjectiles)) { 797 | return false; 798 | } 799 | if (mod.settings.blacklistProjectiles && mod.settings.hiddenProjectiles.includes(event.skill.id)) { 800 | return false; 801 | } 802 | }); 803 | 804 | mod.hook('S_SPAWN_PROJECTILE', 5, { order: 999 }, (event) => { 805 | if (event.gameId !== myId && spawnedPlayers[event.gameId] && (hiddenUsers[event.gameId] || mod.settings.mode > 0 || mod.settings.hideProjectiles)) { 806 | return false; 807 | } 808 | if (mod.settings.blacklistProjectiles && mod.settings.hiddenProjectiles.includes(event.skill.id)) { 809 | return false; 810 | } 811 | }); 812 | 813 | mod.hook('S_FEARMOVE_STAGE', 2, (event) => { // we block these to prevent game crashes 814 | if ((event.gameId !== myId && mod.settings.mode === 3) || hiddenUsers[event.gameId] || hiddenNpcs[event.gameId]) { 815 | return false; 816 | } 817 | }); 818 | mod.hook('S_FEARMOVE_END', 2, (event) => { 819 | if ((event.gameId !== myId && mod.settings.mode === 3) || hiddenUsers[event.gameId] || hiddenNpcs[event.gameId]) { 820 | return false; 821 | } 822 | }); 823 | 824 | mod.hook('S_MOUNT_VEHICLE', 2, (event) => { 825 | if (hiddenUsers[event.gameId]) { 826 | hiddenUsers[event.gameId].mount = event.id 827 | } 828 | }); 829 | 830 | mod.hook('S_UNMOUNT_VEHICLE', 2, (event) => { 831 | if (hiddenUsers[event.gameId]) { 832 | hiddenUsers[event.gameId].mount = 0 833 | } 834 | }); 835 | 836 | mod.hook('S_UNICAST_TRANSFORM_DATA', 6, { order: 99999 }, (event) => { //Thanks Trance!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 837 | if (mod.settings.showStyle && event.gameId !== myId) { //Thanks Trance!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 838 | return false;//Thanks Trance!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 839 | }//Thanks Trance!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 840 | });//Thanks Trance!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 841 | 842 | mod.hook('S_USER_MOVETYPE', 'raw', () => { //this little boi crashes us, raw due to def missing from caali 843 | return false; 844 | }); 845 | 846 | mod.hook('S_ABNORMALITY_REFRESH', 1, (event) => { 847 | if (hiddenUsers[event.target]) { 848 | return false; 849 | } 850 | }); 851 | 852 | mod.hook('S_ABNORMALITY_BEGIN', 3, { order: 999 }, (event) => { 853 | if (hiddenUsers[event.target]) { 854 | return false; 855 | } 856 | if (mod.settings.blacklistAbnormies && mod.settings.hiddenAbnormies.includes(event.id)) { 857 | return false; 858 | } 859 | if (mod.settings.hideAllAbnormies && event.target !== myId && (spawnedPlayers[event.target] && spawnedPlayers[event.source])) { 860 | return false; 861 | } 862 | }); 863 | 864 | }; 865 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "README.md": "c0f75cf25ecfa58f09a22b2ce0d26da5500456715f29735e921f21839886256c", 4 | "index.js": "B1B30D8DC5D8F7687F19B7C2B18AC8AABFF12EFF73EEE5D1A62BDF99AC0CFF43", 5 | "module.json": "96707cd0528f2b992b689cd039f84a71adb0f4245156062bbd670d69a60ad2ae", 6 | "npcData.json": "ac5cc26675716568fc7a88772a8c260304ec737221ff4b334ebb20783bcc6440", 7 | "setting_migration.js": "846ddfd500f29e9987edc45c0cb4ab2959d95cde2039ba7e858d3316e42ff885", 8 | "skillString.json": "aab9e1d6589c384f0dc039640e3a05340cf2f5a9eaf346a52714ad8ac127a4bd" 9 | }, 10 | "defs": { 11 | "S_ABNORMALITY_BEGIN": 3, 12 | "S_ABNORMALITY_REFRESH": 1, 13 | "S_ACTION_STAGE": 9, 14 | "S_DESPAWN_NPC": 3, 15 | "S_DESPAWN_USER": 3, 16 | "S_EACH_SKILL_RESULT": 13, 17 | "S_FEARMOVE_END": 2, 18 | "S_FEARMOVE_STAGE": 2, 19 | "S_LEAVE_PARTY": 1, 20 | "S_LOAD_TOPO": "raw", 21 | "S_LOGIN": [12,13], 22 | "S_MOUNT_VEHICLE": 2, 23 | "S_PARTY_MEMBER_LIST": 7, 24 | "S_REQUEST_DESPAWN_SERVANT": 1, 25 | "S_REQUEST_SPAWN_SERVANT": 3, 26 | "S_SPAWN_NPC": 11, 27 | "S_SPAWN_PROJECTILE": 5, 28 | "S_SPAWN_USER": 15, 29 | "S_START_USER_PROJECTILE": 9, 30 | "S_UNICAST_TRANSFORM_DATA": 6, 31 | "S_UNMOUNT_VEHICLE": 2, 32 | "S_USER_EXTERNAL_CHANGE": 7, 33 | "S_USER_LOCATION": 5, 34 | "S_USER_MOVETYPE": "raw" 35 | } 36 | } -------------------------------------------------------------------------------- /module.json: -------------------------------------------------------------------------------- 1 | { 2 | "disableAutoUpdate": false, 3 | "name": "fps-utils", 4 | "author": "Pentagon", 5 | "description": "Hides other players and skill effects to significantly boost your framerate", 6 | "version": "1.0.1", 7 | "donationUrl": "https://ko-fi.com/codeagon", 8 | "conflicts": [ 9 | "fps-utils-lite", 10 | "hide-players" 11 | ], 12 | "options": { 13 | "niceName": "FPS-UTILS", 14 | "settingsVersion": 2, 15 | "settingsFile": "config.json", 16 | "settingsMigrator": "setting_migration.js" 17 | }, 18 | "servers": [ 19 | "https://raw.githubusercontent.com/codeagon/fps-utils/master/" 20 | ], 21 | "dependencies": { 22 | "badgui": "https://raw.githubusercontent.com/codeagon/badGui/master/module.json" 23 | } 24 | } -------------------------------------------------------------------------------- /setting_migration.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const DefaultSettings = { 4 | "mode": 0, 5 | "party": false, 6 | "hideFireworks": false, 7 | "hideAllAbnormies": true, 8 | "hideAllSummons": false, 9 | "keepMySummons": true, 10 | "blacklistNpcs": false, 11 | "blacklistSkills": false, 12 | "blacklistAbnormies": false, 13 | "hideProjectiles": false, 14 | "hideServants": false, 15 | "hiddenAbnormies": [], 16 | "blacklistProjectiles": false, 17 | "hiddenProjectiles": [270120, 270220, 270320, 270420, 270520, 270620, 270720, 270820, 270920, 271020], 18 | "hitMe": false, 19 | "hitOther": true, 20 | "hitDamage": false, 21 | "showStyle": false, 22 | "blacklistedNames": [ 23 | "hugedong" 24 | ], 25 | "hiddenNpcs": [], 26 | "classNames": [ 27 | "warrior", 28 | "lancer", 29 | "slayer", 30 | "berserker", 31 | "sorcerer", 32 | "archer", 33 | "priest", 34 | "mystic", 35 | "reaper", 36 | "gunner", 37 | "brawler", 38 | "ninja", 39 | "valkyrie" 40 | ], 41 | "roleNames": [ 42 | "dps", 43 | "healer", 44 | "tank", 45 | "ranged" 46 | ], 47 | "hiddenClasses": [], 48 | "hiddenRoles": [], 49 | "classes": { 50 | "1": { 51 | "name": "warrior", 52 | "model": 1, 53 | "blockedSkills": [], 54 | "blockingSkills": false, 55 | "role": [ 56 | "dps" 57 | ], 58 | "isHidden": false 59 | }, 60 | "2": { 61 | "name": "lancer", 62 | "model": 2, 63 | "blockedSkills": [], 64 | "blockingSkills": false, 65 | "role": [ 66 | "tank" 67 | ], 68 | "isHidden": false 69 | }, 70 | "3": { 71 | "name": "slayer", 72 | "model": 3, 73 | "blockedSkills": [], 74 | "blockingSkills": false, 75 | "role": [ 76 | "dps" 77 | ], 78 | "isHidden": false 79 | }, 80 | "4": { 81 | "name": "berserker", 82 | "model": 4, 83 | "blockedSkills": [], 84 | "blockingSkills": false, 85 | "role": [ 86 | "dps" 87 | ], 88 | "isHidden": false 89 | }, 90 | "5": { 91 | "name": "sorcerer", 92 | "model": 5, 93 | "blockedSkills": [], 94 | "blockingSkills": false, 95 | "role": [ 96 | "dps", 97 | "ranged" 98 | ], 99 | "isHidden": false 100 | }, 101 | "6": { 102 | "name": "archer", 103 | "model": 6, 104 | "blockedSkills": [], 105 | "blockingSkills": false, 106 | "role": [ 107 | "dps", 108 | "ranged" 109 | ], 110 | "isHidden": false 111 | }, 112 | "7": { 113 | "name": "priest", 114 | "model": 7, 115 | "blockedSkills": [], 116 | "blockingSkills": false, 117 | "role": [ 118 | "healer" 119 | ], 120 | "isHidden": false 121 | }, 122 | "8": { 123 | "name": "mystic", 124 | "model": 8, 125 | "blockedSkills": [], 126 | "blockingSkills": false, 127 | "role": [ 128 | "healer" 129 | ], 130 | "isHidden": false 131 | }, 132 | "9": { 133 | "name": "reaper", 134 | "model": 9, 135 | "blockedSkills": [], 136 | "blockingSkills": false, 137 | "role": [ 138 | "dps" 139 | ], 140 | "isHidden": false 141 | }, 142 | "10": { 143 | "name": "gunner", 144 | "model": 10, 145 | "blockedSkills": [], 146 | "blockingSkills": false, 147 | "role": [ 148 | "dps", 149 | "ranged" 150 | ], 151 | "isHidden": false 152 | }, 153 | "11": { 154 | "name": "brawler", 155 | "model": 11, 156 | "blockedSkills": [], 157 | "blockingSkills": false, 158 | "role": [ 159 | "tank" 160 | ], 161 | "isHidden": false 162 | }, 163 | "12": { 164 | "name": "ninja", 165 | "model": 12, 166 | "blockedSkills": [], 167 | "blockingSkills": false, 168 | "role": [ 169 | "dps" 170 | ], 171 | "isHidden": false 172 | }, 173 | "13": { 174 | "name": "valkyrie", 175 | "model": 13, 176 | "blockedSkills": [], 177 | "blockingSkills": false, 178 | "role": [ 179 | "dps" 180 | ], 181 | "isHidden": false 182 | } 183 | } 184 | } 185 | 186 | function MigrateSettings(from_ver, to_ver, settings) { 187 | if (from_ver === undefined) { 188 | // Migrate legacy config file 189 | console.log(`FPS-UTILS - FPSUTILS has been updated, please check the readme for more info`) 190 | return Object.assign(Object.assign({}, DefaultSettings), settings); 191 | } else if (from_ver === null) { 192 | // No config file exists, use default settings 193 | return DefaultSettings; 194 | } else { 195 | // Migrate from older version (using the new system) to latest one 196 | if (from_ver + 1 < to_ver) { 197 | // Recursively upgrade in one-version steps 198 | console.log(`FPS-UTILS - FPSUTILS has been updated, please check the readme for more info`) 199 | settings = MigrateSettings(from_ver, from_ver + 1, settings); 200 | return MigrateSettings(from_ver + 1, to_ver, settings); 201 | } 202 | 203 | // If we reach this point it's guaranteed that from_ver === to_ver - 1, so we can implement 204 | // a switch for each version step that upgrades to the next version. This enables us to 205 | // upgrade from any version to the latest version without additional effort! 206 | switch (to_ver) { 207 | /*case 2: 208 | // Upgrade from v1 to v2 209 | // EXAMPLE: in v1, colors were specified like "reset_font_color": "green", but we support arbitrary hex colors now! 210 | switch (settings.reset_font_color) { 211 | case "red": settings.reset_font_color = "#FF0000"; break; 212 | case "green": settings.reset_font_color = "#00FF00"; break; 213 | case "blue": settings.reset_font_color = "#0000FF"; break; 214 | default: settings.reset_font_color = DefaultSettings.reset_font_color; break; 215 | } 216 | break; 217 | case 3: 218 | // upgrade from v2 to v3 219 | // EXAMPLE: setting "random_color" was removed (note that it's also absent from DefaultSettings, which should always correspond to the latest version!) 220 | delete settings.random_color; 221 | break; 222 | // ... 223 | // TODO: whenever you increment your settings version, add an entry to the switch here. 224 | // ...*/ 225 | } 226 | 227 | return settings; 228 | } 229 | } 230 | 231 | module.exports = MigrateSettings; -------------------------------------------------------------------------------- /skillString.json: -------------------------------------------------------------------------------- 1 | { 2 | "warrior": { 3 | "Combo Attack": 1, 4 | "Evasive Roll": 2, 5 | "Torrent of Blows": 3, 6 | "Rain of Blows": 4, 7 | "Battle Cry": 5, 8 | "Assault Stance": 8, 9 | "Defensive Stance": 9, 10 | "Death From Above": 10, 11 | "Poison Blade": 11, 12 | "Leaping Strike": 12, 13 | "Retaliate": 13, 14 | "Charging Slash": 16, 15 | "Vortex Slash": 17, 16 | "Combative Strike": 18, 17 | "Rising Fury": 19, 18 | "Deadly Gamble": 20, 19 | "Cascade of Stuns": 21, 20 | "Smoke Aggressor": 24, 21 | "Command: Attack": 25, 22 | "Command: Follow": 26, 23 | "Traverse Cut": 28, 24 | "Blade Draw": 29, 25 | "Scythe": 30, 26 | "Reaping Slash": 31, 27 | "Cross Parry": 32, 28 | "Binding Sword": 34, 29 | "Infuriate": 35, 30 | "Rain of Blows (Deadly Gamble)": 36, 31 | "Blade Draw (Deadly Gamble)": 37, 32 | "Scythe (Deadly Gamble)": 38, 33 | "Traverse Cut (Defensive Stance)": 39, 34 | "Blade Waltz": 40, 35 | "Aerial Scythe": 41, 36 | "Blade Frenzy": 42 37 | }, 38 | "lancer": { 39 | "Combo Attack": 1, 40 | "Stand Fast": 2, 41 | "Onslaught": 3, 42 | "Challenging Shout": 4, 43 | "Shield Bash": 5, 44 | "Guardian Shout": 7, 45 | "Shield Counter": 8, 46 | "Leash": 9, 47 | "Debilitate": 10, 48 | "Retaliate": 11, 49 | "Infuriate": 12, 50 | "Spring Attack": 13, 51 | "Charging Lunge": 15, 52 | "Second Wind": 16, 53 | "Adrenaline Rush": 17, 54 | "Shield Barrage": 18, 55 | "Pledge of Protection": 19, 56 | "Lockdown Blow": 21, 57 | "Iron Will": 22, 58 | "Master's Leash": 23, 59 | "Chained Leash": 24, 60 | "Wallop": 25, 61 | "Backstep": 26, 62 | "Rallying Cry": 27, 63 | "Super Leap": 28, 64 | "Guardian's Barrier": 29, 65 | "Divine Protection": 30 66 | }, 67 | "slayer": { 68 | "Combo Attack": 1, 69 | "Knockdown Strike": 2, 70 | "Whirlwind": 3, 71 | "Evasive Roll": 4, 72 | "Dash": 5, 73 | "Backstab": 6, 74 | "Overhand Strike": 8, 75 | "Leaping Strike": 9, 76 | "Retaliate": 10, 77 | "Heart Thrust": 12, 78 | "Stunning Backhand": 13, 79 | "Distant Blade": 14, 80 | "Startling Kick": 15, 81 | "Fury Strike": 16, 82 | "Headlong Rush": 17, 83 | "Overpower": 18, 84 | "Tenacity": 19, 85 | "In Cold Blood": 20, 86 | "Measured Slice": 23, 87 | "Eviscerate": 24, 88 | "Ultimate Overhand Strike": 25, 89 | "Punishing Blow": 26, 90 | "Savage Strike": 27, 91 | "Unsheathe": 28 92 | }, 93 | "berserker": { 94 | "Combo Attack": 1, 95 | "Axe Block": 2, 96 | "Thunder Strike": 3, 97 | "Flatten": 4, 98 | "Dash": 5, 99 | "Sweeping Strike": 6, 100 | "Fiery Rage": 8, 101 | "Cyclone": 10, 102 | "Leaping Strike": 11, 103 | "Retaliate": 13, 104 | "Vampiric Blow": 15, 105 | "Fearsome Shout": 16, 106 | "Lethal Strike": 18, 107 | "Triumphant Shout": 19, 108 | "Inescapable Doom": 20, 109 | "Bloodlust": 21, 110 | "Evasive Smash": 24, 111 | "Raze": 25, 112 | "Tackle": 26, 113 | "Unbreakable": 27, 114 | "Intimiation": 28, 115 | "Evasive Roll": 29, 116 | "Axe Counter": 30, 117 | "Overwhelm": 31, 118 | "Punishing Strike": 32, 119 | "Unleash": 33, 120 | "Unleash: Dexter": 34, 121 | "Unleash: Sinister": 35, 122 | "Unleash: Rampage": 36, 123 | "Unleash: Beast Fury": 37 124 | }, 125 | "sorcerer": { 126 | "Fireball": 1, 127 | "Frost Sphere": 2, 128 | "Lightning Trap": 3, 129 | "Arcane Pulse": 4, 130 | "Mana Infusion": 5, 131 | "Meteor Strike": 6, 132 | "Backstep": 7, 133 | "Flame Pillar": 8, 134 | "Mana Barrier": 10, 135 | "Lightning Strike": 11, 136 | "Void Pulse": 12, 137 | "Mindblast": 13, 138 | "Retaliate": 14, 139 | "Painblast": 16, 140 | "Painful Trap": 17, 141 | "Glacial Retreat": 18, 142 | "Mana Siphon": 19, 143 | "Flaming Barrage": 20, 144 | "Nerve Exhaustion": 21, 145 | "Burning Breath": 22, 146 | "Mana Volley": 23, 147 | "Time Gyre": 25, 148 | "Teleport Jaunt": 26, 149 | "Hailstorm": 27, 150 | "Nova": 30, 151 | "Warp Barrier": 31, 152 | "Meteor Strike (Mana Boost)": 32, 153 | "Arcane Pulse (Mana Boost)": 33, 154 | "Mana Boost": 34, 155 | "Fusion": 36, 156 | "Implosion": 39 157 | }, 158 | "archer": { 159 | "Arrow": 1, 160 | "Arrow Volley": 2, 161 | "Radiant Arrow": 3, 162 | "Penetrating Arrow": 4, 163 | "Rain of Arrows": 5, 164 | "Backstep": 6, 165 | "Feign Death": 7, 166 | "Rapid Fire": 8, 167 | "Slow Trap": 9, 168 | "Stunning Trap": 10, 169 | "Velik's Mark": 12, 170 | "Retaliate": 14, 171 | "Incendiary Trap": 15, 172 | "Breakaway Bolt": 16, 173 | "Web Arrow": 17, 174 | "Close Quarters": 18, 175 | "Poison Arrow": 19, 176 | "Restraining Arrow": 20, 177 | "Sequential Fire": 22, 178 | "Incendiary Trap Arrow": 25, 179 | "Thunderbolt": 29, 180 | "Tenacity": 31, 181 | "Find Weakness": 32, 182 | "Chase": 33, 183 | "Wind Walk": 24, 184 | "Windsong": 35, 185 | "Gust Arrow": 36 186 | }, 187 | "priest": { 188 | "Divine Radiance": 1, 189 | "Regeneration Circle": 2, 190 | "Healing Circle": 3, 191 | "Blessing of Shakan": 5, 192 | "Arise": 6, 193 | "Mana Infusion": 8, 194 | "Purifying Circle": 10, 195 | "Metamorphic Blast": 11, 196 | "Resurrect": 12, 197 | "Summon: Group": 14, 198 | "Shocking Implosion": 16, 199 | "Heal Thyself": 18, 200 | "Focus Heal": 19, 201 | "Kaia's Shield": 22, 202 | "Retaliate": 25, 203 | "Fiery Escape": 26, 204 | "Final Reprisal": 27, 205 | "Mana Charge / Divine Charge": 28, 206 | "Triple Nemesis": 29, 207 | "Plague of Exhaustion": 30, 208 | "Guardian Sanctuary": 31, 209 | "Divine Prayer": 32, 210 | "Ishara's Lulliby": 33, 211 | "Restorative Burst": 34, 212 | "Energy Stars": 35, 213 | "Healing Immersion": 37, 214 | "Backstep": 38, 215 | "Grace of Resurrection": 39, 216 | "Zenobia's Vortex": 40, 217 | "Divine Intervention / Mass Divine Intervention": 41, 218 | "Holy Burst": 42, 219 | "Edict of Judgement": 43 220 | }, 221 | "mystic": { 222 | "Sharan Bolt": 1, 223 | "Corruption Ring": 2, 224 | "Titanic Favor": 5, 225 | "Shara's Lash": 6, 226 | "Metamorphic Blast": 8, 227 | "Arun's Cleansing": 9, 228 | "Resurrect": 10, 229 | "Summon: Group": 11, 230 | "Vow of Rebirth": 12, 231 | "Aura of the Merciless": 13, 232 | "Aura of the Swift": 14, 233 | "Aura of the Unyielding": 15, 234 | "Aura of the Tenacious": 16, 235 | "Teleport Jaunt": 17, 236 | "Arun's Vitae": 18, 237 | "Retaliate": 21, 238 | "Arun's Tears": 22, 239 | "Metmorphic Smite": 23, 240 | "Volley of Curses": 24, 241 | "Thrall of Protection": 25, 242 | "Thrall of Life": 27, 243 | "Sonorous Dreams": 28, 244 | "Regression": 29, 245 | "Curse of Exhaustion": 30, 246 | "Curse of Confusion": 31, 247 | "Mire": 32, 248 | "Thrall of Vengeance": 33, 249 | "Thrall of Wrath": 34, 250 | "Command: Attack": 35, 251 | "Command: Follow": 36, 252 | "Warding Totem": 37, 253 | "Contagion": 41, 254 | "Boomerang Pulse": 42, 255 | "Unsummon Thrall": 43, 256 | "Mass Teleport": 44, 257 | "Thrall Augmentation": 45, 258 | "Arunic Release": 47, 259 | "Thrall Lord": 48 260 | }, 261 | "reaper": { 262 | "Spiral Barrage": 1, 263 | "Double Shear": 3, 264 | "Sundering Strike": 4, 265 | "Grim Strike": 5, 266 | "Death Spiral": 6, 267 | "Whipsaw": 8, 268 | "Smite": 9, 269 | "Pendulum Strike": 10, 270 | "Shadow Lash": 11, 271 | "Shadow Burst": 12, 272 | "Retaliate": 14, 273 | "Retribution": 15, 274 | "Shadow Reaping": 16, 275 | "Dark Harvest": 19, 276 | "Cable Step": 20, 277 | "Recall Scythes": 21, 278 | "Binding Scythes": 23, 279 | "Shadow Step": 40 280 | }, 281 | "gunner": { 282 | "Blast": 1, 283 | "Bombardment": 2, 284 | "Scattershot": 3, 285 | "Point Blank": 4, 286 | "Burst Fire / Targeted Burst Fire": 5, 287 | "Time Bomb": 6, 288 | "Arcane Barrage": 7, 289 | "Mana Missiles": 9, 290 | "Arc Bomb": 10, 291 | "Rocket Jump": 11, 292 | "Balder's Vengeance": 13, 293 | "Replenishment": 15, 294 | "HB": 18, 295 | "ST": 19, 296 | "Retaliate": 20, 297 | "Rolling Reload / Dashing Reload": 40, 298 | "Modular Weapon System": 41, 299 | "Detonate": 42, 300 | "Remote Trigger": 43, 301 | "Obliteration": 47 302 | }, 303 | "brawler": { 304 | "Punch": 1, 305 | "Counter": 2, 306 | "Divine Wrath": 3, 307 | "Ground Pound": 4, 308 | "Bullrush": 5, 309 | "Haymaker": 6, 310 | "Roundhouse Kick": 7, 311 | "Piledriver": 8, 312 | "Jackhammer": 9, 313 | "Counterpunch": 10, 314 | "Retaliate": 12, 315 | "Provoke": 13, 316 | "Infuriate": 14, 317 | "Flip Kick": 16, 318 | "Mounting Rage": 21, 319 | "Flying Kick": 22, 320 | "One-Inch Punch": 24, 321 | "Rythmic Blows": 26, 322 | "Quick Dash": 40 323 | }, 324 | "ninja": { 325 | "Combo Attack": 1, 326 | "Shadow Jump": 2, 327 | "Leaves on the Wind": 3, 328 | "Jagged Path": 4, 329 | "Impact Bomb": 5, 330 | "One Thousand Cuts": 6, 331 | "Decoy Jutsu": 7, 332 | "Fire Avalanche": 8, 333 | "Smoke Bomb": 9, 334 | "Retaliate": 10, 335 | "Focus": 11, 336 | "Skyfall": 12, 337 | "Circle of Steel": 13, 338 | "Double Cut": 14, 339 | "Burning Heart": 15, 340 | "Death Blossom": 16, 341 | "Attunement": 17, 342 | "Bladestorm": 18, 343 | "Chakra Thrust": 19, 344 | "Clone Jutsu": 20, 345 | "Boomerang Shuriken": 21, 346 | "Quick Attack": 22, 347 | "Inner Harmony": 23 348 | }, 349 | "valkyrie": { 350 | "Slash": 1, 351 | "Overhead Slash": 2, 352 | "Glaive Strike": 3, 353 | "Charge": 4, 354 | "Maelstrom": 5, 355 | "Leaping Strike": 6, 356 | "Spinning Death": 7, 357 | "Titansbane": 8, 358 | "Ground Bash": 9, 359 | "Dream Slash": 10, 360 | "Shining Crescent": 11, 361 | "Ragnarok": 12, 362 | "Bloodflower": 13, 363 | "Evasion": 14, 364 | "Windslash": 15, 365 | "Runeburst": 16, 366 | "Balder's Tears": 17, 367 | "Retaliate": 18, 368 | "Reclamation": 19, 369 | "Backstab": 20, 370 | "Dark Herald": 21, 371 | "Gungir's Bite": 23, 372 | "Twilight Waltz": 24, 373 | "Godsfall": 25 374 | } 375 | } --------------------------------------------------------------------------------