aboutsummaryrefslogtreecommitdiff
path: root/webAO/client.b.js.map
diff options
context:
space:
mode:
Diffstat (limited to 'webAO/client.b.js.map')
-rw-r--r--webAO/client.b.js.map2
1 files changed, 1 insertions, 1 deletions
diff --git a/webAO/client.b.js.map b/webAO/client.b.js.map
index 4aa51b5..43d0a2a 100644
--- a/webAO/client.b.js.map
+++ b/webAO/client.b.js.map
@@ -1 +1 @@
-{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./webAO/client.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","r","value","n","__esModule","object","property","prototype","hasOwnProperty","p","s","onOOCEnter","onEnter","musiclist_click","changeMusicVolume","changeSFXVolume","changeBlipVolume","changeCharacter","imgError","demoError","ReconnectButton","RetryButton","pickchar","pickemotion","toggleshout","queryDict","location","search","substr","split","forEach","item","serverIP","ip","mode","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","playerID","charID","chars","emotes","selectedEmote","checkUpdater","musicList","handlers","MS","args","handleMS","CT","handleCT","MC","handleMC","RMC","handleRMC","CI","handleCI","SC","handleSC","EI","handleEI","EM","handleEM","SM","handleSM","music","handlemusic","DONE","handleDONE","BN","handleBN","NBG","handleNBG","HP","handleHP","ID","handleID","PN","handlePN","SI","handleSI","CharsCheck","handleCharsCheck","PV","handlePV","_lastTimeICReceived","message","send","escapeChat","speaking","silent","side","ssfxname","zoom","ssfxdelay","objection","track","_this2","hashCode","CHECKupdater","setInterval","sendCheck","character","song","e","client","joinServer","document","getElementById","style","display","console","error","reason","code","textContent","cleanup","msg","data","debug","header","handler","warn","close","clearInterval","viewport","chatmsg","content","innerHTML","pre","escape","preanim","nameplate","sound","type","snddelay","evidence","flash","color","isnew","length","className","say","oocLog","scrollTop","scrollHeight","pause","src","play","appendICLog","Audio","totime","offset","getTime","addEventListener","currentTime","parseFloat","toFixed","chargs","desc","icon","hmusiclist","newentry","createElement","text","options","add","bgname","clip","tr","td","icon_chosen","thispick","appendChild","changeBackground","me","xhr","XMLHttpRequest","open","responseType","onload","status","linifile","responseText","pinifile","INI","parse","Options","Emotions","number","emoteinfo","esfx","esfxd","SoundN","SoundT","sfx","sfxdelay","button_off","button_on","Viewport","textnow","startspeaking","blip","volume","blipChannels","Array","currentBlipChannel","sfxaudio","sfxplayed","updater","shoutTimer","textTimer","_animating","_this3","updateText","trim","shout","1","2","3","fontSize","offsetHeight","replace","stylecolor","0","4","5","6","charAt","substring","regex","section","param","comment","line","match","event","keyCode","sendOOC","mychar","myemo","myEmote","checked","sendIC","playtrack","sendMusicChange","setBlipVolume","sendLeaveRoom","image","position","standname","bgfolder","bgFolder","toadd","arguments","undefined","time","entry","nameField","id","createTextNode","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","ccharacter","sendCharacter","emo","estring","window","String","hash","charCodeAt"],"mappings":"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","file":"client.b.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/*\r\n * Glorious webAO\r\n * made by sD, refactored by oldmud0\r\n * credits to aleks for original idea and source\r\n*/\r\n\r\nlet queryDict = {};\r\nlocation.search.substr(1).split(\"&\").forEach(function(item) {\r\n\tqueryDict[item.split(\"=\")[0]] = item.split(\"=\")[1]\r\n});\r\n\r\n/* Server magic */\r\n\r\nconst serverIP = queryDict.ip;\r\nlet mode = queryDict.mode;\r\n\r\nconst AO_HOST = queryDict.asset || \"http://assets.aceattorneyonline.com/base/\";\r\nconst MUSIC_HOST = AO_HOST + \"sounds/music/\";\r\nconst BAR_WIDTH = 90;\r\nconst BAR_HEIGHT = 20;\r\nconst CHAR_SELECT_WIDTH = 8;\r\nconst UPDATE_INTERVAL = 65;\r\n\r\nlet oldLoading = false;\r\nif (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {\r\n\toldLoading = true;\r\n}\r\n\r\nlet selectedShout = 0;\r\nlet lastICMessageTime = new Date(0);\r\n\r\nclass Client {\r\n\tconstructor(address) {\r\n\t\tthis.serv = new WebSocket(\"ws://\" + address);\r\n\r\n\t\tthis.serv.onopen = (evt) => this.onOpen(evt);\r\n\t\tthis.serv.onclose = (evt) => this.onClose(evt);\r\n\t\tthis.serv.onmessage = (evt) => this.onMessage(evt);\r\n\t\tthis.serv.onerror = (evt) => this.onError(evt);\r\n\r\n\t\tthis.playerID = 1;\r\n\t\tthis.charID = -1;\r\n\r\n\t\tthis.chars = [];\r\n\t\tthis.emotes = [];\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\r\n\t\tthis.checkUpdater = null;\r\n\r\n\t\t// Only used for RMC/`music` packets, not EM/SM/MC packets.\r\n\t\tthis.musicList = Object();\r\n\r\n\t\tthis.handlers = {\r\n\t\t\t\"MS\": (args) => this.handleMS(args),\r\n\t\t\t\"CT\": (args) => this.handleCT(args),\r\n\t\t\t\"MC\": (args) => this.handleMC(args),\r\n\t\t\t\"RMC\": (args) => this.handleRMC(args),\r\n\t\t\t\"CI\": (args) => this.handleCI(args),\r\n\t\t\t\"SC\": (args) => this.handleSC(args),\r\n\t\t\t\"EI\": (args) => this.handleEI(args),\r\n\t\t\t\"EM\": (args) => this.handleEM(args),\r\n\t\t\t\"SM\": (args) => this.handleSM(args),\r\n\t\t\t\"music\": (args) => this.handlemusic(args),\r\n\t\t\t\"DONE\": (args) => this.handleDONE(args),\r\n\t\t\t\"BN\": (args) => this.handleBN(args),\r\n\t\t\t\"NBG\": (args) => this.handleNBG(args),\r\n\t\t\t\"HP\": (args) => this.handleHP(args),\r\n\t\t\t\"ID\": (args) => this.handleID(args),\r\n\t\t\t\"PN\": (args) => this.handlePN(args),\r\n\t\t\t\"SI\": (args) => this.handleSI(args),\r\n\t\t\t\"CharsCheck\": (args) => this.handleCharsCheck(args),\r\n\t\t\t\"PV\": (args) => this.handlePV(args)\r\n\t\t}\r\n\r\n\t\tthis._lastTimeICReceived = new Date(0);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the current player's character.\r\n\t */\r\n\tme() {\r\n\t\treturn this.chars[this.charID];\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the player's currently selected emote.\r\n\t */\r\n\tmyEmote() {\r\n\t\treturn this.emotes[this.selectedEmote];\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an out-of-character chat message.\r\n\t * @param {string} message the message to send\r\n\t */\r\n\tsendOOC(message) {\r\n\t\tthis.serv.send(`CT#web${this.playerID}#${escapeChat(message)}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an in-character chat message.\r\n\t * @param {string} speaking who is speaking\r\n\t * @param {string} name the name of the current character\r\n\t * @param {string} silent whether or not it's silent\r\n\t * @param {string} message the message to be sent\r\n\t * @param {string} side the name of the side in the background\r\n\t * @param {string} ssfxname the name of the sound effect\r\n\t * @param {string} zoom whether or not to zoom\r\n\t * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect\r\n\t * @param {string} objection the number of the shout to play\r\n\t */\r\n\tsendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#0#0#0#0#%`\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to change the music to the specified track.\r\n\t * @param {string} track the track ID\r\n\t */\r\n\tsendMusicChange(track) {\r\n\t\tthis.serv.send(`MC#${track}#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to leave the room and free the character slot.\r\n\t * \r\n\t * Note: This packet is undocumented. It is not implemented by\r\n\t * either the AO2 client or tsuserver.\r\n\t */\r\n\tsendLeaveRoom() {\r\n\t\tthis.serv.send(\"FC#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Begins the handshake process by sending an identifier\r\n\t * to the server.\r\n\t */\r\n\tjoinServer() {\r\n\t\tthis.serv.send(`HI#${navigator.userAgent.hashCode()}#%`);\r\n\t\tthis.serv.send(\"ID#webAO#2.4.5#%\");\r\n\t\tthis.CHECKupdater = setInterval(() => this.sendCheck, 5000);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to play as a specified character.\r\n\t * @param {number} character the character ID\r\n\t */\r\n\tsendCharacter(character) {\r\n\t\tthis.serv.send(`CC#${this.playerID}#${character}#web#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to select a music track.\r\n\t * @param {number?} song the song to be played\r\n\t */\r\n\tsendMusic(song) {\r\n\t\tthis.serv.send(`MC#${song}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends a keepalive packet.\r\n\t */\r\n\tsendCheck() {\r\n\t\tthis.serv.send(`CH#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a connection is established to the server.\r\n\t */\r\n\tonOpen(e) {\r\n\t\t// XXX: Why does watching mean just SITTING there and doing nothing?\r\n\t\tif (mode == \"join\") {\r\n\t\t\tclient.joinServer();\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when the connection to the server closes.\r\n\t * @param {CloseEvent} e\r\n\t */\r\n\tonClose(e) {\r\n\t\tconsole.error(`The connection was closed: ${e.reason} (${e.code})`);\r\n\t\tif (e.code !== 1001) {\r\n\t\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\t\tthis.cleanup();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a packet is received from the server.\r\n\t * @param {MessageEvent} e\r\n\t */\r\n\tonMessage(e) {\r\n\t\tlet msg = e.data;\r\n\t\tconsole.debug(msg);\r\n\t\tlet lines = msg.split('%');\r\n\t\tlet args = lines[0].split('#');\r\n\t\tlet header = args[0];\r\n\t\tlet handler = this.handlers[header];\r\n\t\tif (typeof handler !== \"undefined\") {\r\n\t\t\thandler(args);\r\n\t\t} else {\r\n\t\t\tconsole.warn(`Invalid packet header ${header}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when an network error occurs.\r\n\t * @param {ErrorEvent} e \r\n\t */\r\n\tonError(e) {\r\n\t\tconsole.error(`A network error occurred: ${e.reason} (${e.code})`);\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\tthis.cleanup();\r\n\t}\r\n\r\n\tcleanup() {\r\n\t\ttry {\r\n\t\t\tthis.serv.close(1001);\r\n\t\t} catch (e) {\r\n\t\t\t// I don't care if this errors\r\n\t\t}\r\n\t\tclearInterval(this.checkUpdater);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an in-character chat message.\r\n\t * @param {*} args packet arguments\r\n\t */\r\n\thandleMS(args) {\r\n\t\t// TODO: this if-statement might be a bug.\r\n\t\tif (args[4] != viewport.chatmsg.content) {\r\n\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = \"\";\r\n\t\t\tlet chatmsg = {\r\n\t\t\t\tpre: escape(args[2]),\r\n\t\t\t\tcharacter: -1, // Will do a linear search\r\n\t\t\t\tpreanim: escape(args[2]), // XXX: why again?\r\n\t\t\t\tnameplate: args[3], // TODO: parse INI to get this info\r\n\t\t\t\tname: args[3],\r\n\t\t\t\tspeaking: \"(b)\" + escape(args[4]),\r\n\t\t\t\tsilent: \"(a)\" + escape(args[4]),\r\n\t\t\t\tcontent: args[5],\r\n\t\t\t\tside: args[6],\r\n\t\t\t\tsound: escape(args[7]),\r\n\t\t\t\ttype: args[8],\r\n\t\t\t\t// charid: args[9],\r\n\t\t\t\tsnddelay: args[10],\r\n\t\t\t\tobjection: args[11],\r\n\t\t\t\tevidence: args[12],\r\n\t\t\t\t// flip: args[13],\r\n\t\t\t\tflash: args[14],\r\n\t\t\t\tcolor: args[15],\r\n\t\t\t\tisnew: true,\r\n\t\t\t};\r\n\r\n\t\t\t// The dreaded linear search...\r\n\t\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\t\tif (this.chars[i].name == args[3]) {\r\n\t\t\t\t\tchatmsg.character = i;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (chatmsg.character == this.charID) {\r\n\t\t\t\tresetICParams();\r\n\t\t\t}\r\n\r\n\t\t\tviewport.say(chatmsg);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an out-of-character chat message.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCT(args) {\r\n\t\tconst oocLog = document.getElementById(\"client_ooclog\");\r\n\t\toocLog.innerHTML += `${args[1]}: ${args[2]}\\r\\n`;\r\n\t\tif (oocLog.scrollTop > oocLog.scrollHeight - 60) {\r\n\t\t\toocLog.scrollTop = oocLog.scrollHeight;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleMC(args) {\r\n\t\tconst music = viewport.music;\r\n\t\tmusic.pause();\r\n\t\tmusic.src = MUSIC_HOST + args[1];\r\n\t\tmusic.play();\r\n\t\tif (args[2] >= 0) {\r\n\t\t\tlet musicname = this.chars[args[2]].name;\r\n\t\t\tappendICLog(`${musicname} changed music to ${args[1]}`);\r\n\t\t} else {\r\n\t\t\tappendICLog(`The music was changed to ${args[1]}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource, with an offset in seconds.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleRMC(args) {\r\n\t\tviewport.music.pause();\r\n\t\tviewport.music = new Audio(this.musicList[args[1]]);\r\n\t\tconst music = viewport.music;\r\n\t\t// Music offset + drift from song loading\r\n\t\tmusic.totime = args[1];\r\n\t\tmusic.offset = new Date().getTime() / 1000;\r\n\t\tmusic.addEventListener('loadedmetadata', function() {\r\n\t\t\tmusic.currentTime += parseFloat(music.totime + (new Date().getTime() / 1000 - music.offset)).toFixed(3);\r\n\t\t\tmusic.play();\r\n\t\t}, false);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, bundling multiple characters\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Character \" + args[1];\r\n\t\tthis.serv.send(\"AN#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\t\tthis.chars[args[i - 1]] = {\r\n\t\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, containing only one character\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSC(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Characters\";\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\tthis.chars[i - 1] = {\r\n\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming evidence information, containing only one evidence\r\n\t * item per packet.\r\n\t * \r\n\t * Mostly unimplemented in webAO.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Evidence \" + args[1];\r\n\t\t//serv.send(\"AE#\" + (args[1] + 1) + \"#%\");\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing multiple entries\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \" + args[1];\r\n\t\tthis.serv.send(\"AM#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\t\tnewentry.text = args[i];\r\n\t\t\t\thmusiclist.options.add(newentry);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing only one entry\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \";\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\tnewentry.text = args[i];\r\n\t\t\thmusiclist.options.add(newentry);\r\n\t\t}\r\n\t\tthis.serv.send(\"RD#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing all entries\r\n\t * in the same packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlemusic(args) {\r\n\t\tfor (let i = 0; i < args.length / 2; i++) {\r\n\t\t\tthis.musicList[args[2 * i]] = args[2 * i + 1];\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the handshake completion packet, meaning the player\r\n\t * is ready to select a character.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleDONE(args) {\r\n\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a background change.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleBN(args) {\r\n\t\tviewport.bgname = escape(args[1]);\r\n\t}\r\n\r\n\thandleNBG(args) {\r\n\t\t// TODO (set by sD)\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a change in the health bars' states.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleHP(args) {\r\n\t\t// TODO (set by sD)\r\n\t\t// Also, this is broken.\r\n\t\tif (args[1] == 1) {\r\n\t\t\tdocument.getElementById(\"client_defense_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_prosecutor_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t}\r\n\t}\r\n\t\r\n\t/**\r\n\t * Handles the issuance of a player ID by the server.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleID(args) {\r\n\t\tthis.playerID = args[1];\r\n\t}\r\n\r\n\thandlePN(args) {\r\n\t\tthis.serv.send(\"askchaa#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Received when the server announces its server info,\r\n\t * but we use it as a cue to begin retrieving characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSI(args) {\r\n\t\tif (oldLoading) {\r\n\t\t\tthis.serv.send(\"askchar2#%\");\r\n\t\t} else {\r\n\t\t\tthis.serv.send(\"RC#%\");\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the list of all used and vacant characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCharsCheck(args) {\r\n\t\tdocument.getElementById(\"client_chartable\").innerHTML = \"\";\r\n\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tvar tr = document.createElement('TR');\r\n\t\t\t}\r\n\t\t\tlet td = document.createElement('TD');\r\n\t\t\tlet icon_chosen;\r\n\t\t\tlet thispick = this.chars[i].icon;\r\n\t\t\tif (args[i + 1] == \"-1\") {\r\n\t\t\t\ticon_chosen = \" dark\";\r\n\t\t\t} else {\r\n\t\t\t\ticon_chosen = \"\";\r\n\t\t\t}\r\n\t\t\ttd.innerHTML = `<img class='demothing${icon_chosen}' id='demo_${i}' ` +\r\n\t\t\t\t`src='${thispick}' alt='${this.chars[i].desc}' onclick='pickchar(${i})' ` +\r\n\t\t\t\t`onerror='demoError(this);'>`;\r\n\t\t\ttr.appendChild(td);\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tdocument.getElementById(\"client_chartable\").appendChild(tr);\r\n\t\t\t}\r\n\t\t}\r\n\t\tchangeBackground(\"def\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the server's assignment of a character for the player to use.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlePV(args) {\r\n\t\tthis.charID = args[3];\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tlet me = this.me();\r\n\t\tlet emotes = this.emotes;\r\n\t\tlet xhr = new XMLHttpRequest();\r\n\t\txhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true);\r\n\t\txhr.responseType = 'text';\r\n\t\txhr.onload = function (e) {\r\n\t\t\tif (this.status == 200) {\r\n\t\t\t\tlet linifile = this.responseText;\r\n\t\t\t\tlet pinifile = INI.parse(linifile);\r\n\t\t\t\tme.side = pinifile.Options.side;\r\n\t\t\t\tfor (let i = 1; i < pinifile.Emotions.number; i++) {\r\n\t\t\t\t\tlet emoteinfo = pinifile.Emotions[i].split('#');\r\n\t\t\t\t\tlet esfx = \"0\";\r\n\t\t\t\t\tlet esfxd = \"0\";\r\n\t\t\t\t\tif (typeof pinifile.SoundN !== 'undefined') {\r\n\t\t\t\t\t\tesfx = pinifile.SoundN[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (typeof pinifile.SoundT !== 'undefined') {\r\n\t\t\t\t\t\tesfxd = pinifile.SoundT[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\temotes[i] = {\r\n\t\t\t\t\t\tdesc: emoteinfo[0],\r\n\t\t\t\t\t\tspeaking: emoteinfo[1],\r\n\t\t\t\t\t\tsilent: emoteinfo[2],\r\n\t\t\t\t\t\tzoom: emoteinfo[3],\r\n\t\t\t\t\t\tsfx: esfx,\r\n\t\t\t\t\t\tsfxdelay: esfxd,\r\n\t\t\t\t\t\tbutton_off: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_off.png',\r\n\t\t\t\t\t\tbutton_on: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_on.png'\r\n\t\t\t\t\t};\r\n\t\t\t\t\tdocument.getElementById(\"client_emo\").innerHTML += \"<img src='\" + emotes[i].button_off + \"' id='emo_\" + i + \"' alt='\" + emotes[i].desc + \"' class='client_button' onclick='pickemotion(\" + i + \")'>\";\r\n\t\t\t\t}\r\n\t\t\t\tpickemotion(1);\r\n\t\t\t}\r\n\t\t};\r\n\t\txhr.send();\r\n\t}\r\n}\r\n\r\nclass Viewport {\r\n\tconstructor() {\r\n\t\tthis.textnow = \"\";\r\n\t\tthis.chatmsg = {\r\n\t\t\t\"isnew\": false,\r\n\t\t\t\"content\": \"\",\r\n\t\t\t\"objection\": \"0\",\r\n\t\t\t\"sound\": \"\",\r\n\t\t\t\"startspeaking\": false,\r\n\t\t\t\"side\": null,\r\n\t\t\t\"color\": \"0\",\r\n\t\t\t\"snddelay\": 0\r\n\t\t};\r\n\t\tthis.blip = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.blip.volume = 0.5;\r\n\r\n\t\t// Allocate multiple blip audio channels to make blips less jittery\r\n\r\n\t\t// TODO: read blip type (\"gender\") from ini\r\n\t\tthis.blipChannels = new Array(6);\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i] = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\t\tthis.blipChannels[i].volume = 0.5;\r\n\t\t}\r\n\t\tthis.currentBlipChannel = 0;\r\n\r\n\t\tthis.sfxaudio = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.sfxplayed = 0;\r\n\r\n\t\tthis.music = new Audio();\r\n\t\tthis.music.play();\r\n\r\n\t\tthis.updater = null;\r\n\r\n\t\tthis.bgname = \"gs4\";\r\n\r\n\t\tthis.shoutTimer = 0;\r\n\t\tthis.textTimer = 0;\r\n\r\n\t\tthis._animating = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether or not the viewport is busy\r\n\t * performing a task (animating).\r\n\t */\r\n\tisAnimating() {\r\n\t\treturn this._animating;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the volume of the blip sound.\r\n\t * @param {number} volume\r\n\t */\r\n\tsetBlipVolume(volume) {\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i].volume = volume;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the path which the background is located in.\r\n\t */\r\n\tbgFolder() {\r\n\t\treturn `${AO_HOST}background/${this.bgname}/`;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a new emote.\r\n\t * @param {object} chatmsg the new chat message\r\n\t */\r\n\tsay(chatmsg) {\r\n\t\tthis.chatmsg = chatmsg;\r\n\t\tappendICLog(chatmsg.content, chatmsg.nameplate);\r\n\t\tchangeBackground(chatmsg.side);\r\n\t\tthis.textnow = '';\r\n\t\tthis.sfxplayed = 0;\r\n\t\tthis.textTimer = 0;\r\n\t\tthis._animating = true;\r\n\t\tthis.updater = setInterval(() => this.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the chatbox based on the given text.\r\n\t * \r\n\t * XXX: This relies on a global variable `this.chatmsg`!\r\n\t */\r\n\tupdateText() {\r\n\t\tif (this.chatmsg.content.trim() == \"\") {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"block\";\r\n\t\t}\r\n\r\n\t\tif (this.chatmsg.isnew) {\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"takethat\",\r\n\t\t\t\t\"3\": \"objection\"\r\n\t\t\t};\r\n\r\n\t\t\tlet shout = shouts[this.chatmsg.objection];\r\n\t\t\tif (typeof shout !== \"undefined\") {\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"misc/\" + shout + \".gif\";\r\n\t\t\t\t(new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play();\r\n\t\t\t\tthis.shoutTimer = 800;\r\n\t\t\t} else {\r\n\t\t\t\tthis.shoutTimer = 0;\r\n\t\t\t}\r\n\r\n\t\t\tthis.chatmsg.isnew = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t}\r\n\r\n\t\tif (this.textTimer >= this.shoutTimer) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.speaking + \".gif\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").style.fontSize = (document.getElementById(\"client_name\").offsetHeight * 0.7) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_chat\").style.fontSize = (document.getElementById(\"client_chat\").offsetHeight * 0.25) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").innerHTML = \"<p>\" + escapeHtml(this.chatmsg.nameplate) + \"</p>\";\r\n\r\n\t\t\t\tconst colors = {\r\n\t\t\t\t\t\"0\": \"#ffffff\",\r\n\t\t\t\t\t\"1\": \"#00ff00\",\r\n\t\t\t\t\t\"2\": \"#ff0000\",\r\n\t\t\t\t\t\"3\": \"#ffaa00\",\r\n\t\t\t\t\t\"4\": \"#0000ff\",\r\n\t\t\t\t\t\"5\": \"#ffff00\",\r\n\t\t\t\t\t\"6\": \"#aa00aa\"\r\n\t\t\t\t}\r\n\t\t\t\tlet stylecolor = \"color: \" + (colors[this.chatmsg.color] || \"#ffffff\");\r\n\t\t\t\tdocument.getElementById(\"client_inner_chat\").style = stylecolor;\r\n\t\t\t\tthis.chatmsg.startspeaking = false;\r\n\t\t\t} else {\r\n\t\t\t\tif (this.textnow != this.chatmsg.content) {\r\n\t\t\t\t\tif (this.chatmsg.content.charAt(this.textnow.length) != \" \") {\r\n\t\t\t\t\t\tthis.blipChannels[this.currentBlipChannel].play();\r\n\t\t\t\t\t\tthis.currentBlipChannel++;\r\n\t\t\t\t\t\tthis.currentBlipChannel %= this.blipChannels.length;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1);\r\n\t\t\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = this.textnow;\r\n\t\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\t\tthis.textTimer = 0;\r\n\t\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\t\tclearInterval(this.updater);\r\n\t\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) {\r\n\t\t\tthis.sfxaudio.pause();\r\n\t\t\tthis.sfxplayed = 1;\r\n\t\t\tif (this.chatmsg.sound != \"0\" && this.chatmsg.sound != \"1\") {\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/\" + escape(this.chatmsg.sound) + \".wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.textTimer = this.textTimer + UPDATE_INTERVAL;\r\n\t}\r\n}\r\n\r\nclass INI {\r\n\tstatic parse(data) {\r\n\t\tlet regex = {\r\n\t\t\tsection: /^\\s*\\[\\s*([^\\]]*)\\s*\\]\\s*$/,\r\n\t\t\tparam: /^\\s*([\\w\\.\\-\\_]+)\\s*=\\s*(.*?)\\s*$/,\r\n\t\t\tcomment: /^\\s*;.*$/\r\n\t\t};\r\n\t\tlet value = {};\r\n\t\tlet lines = data.split(/\\r\\n|\\r|\\n/);\r\n\t\tlet section = null;\r\n\t\tlines.forEach(function(line) {\r\n\t\t\tif (regex.comment.test(line)) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (line.length == 0) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (regex.param.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.param);\r\n\t\t\t\tif (section) {\r\n\t\t\t\t\tvalue[section][match[1]] = match[2];\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvalue[match[1]] = match[2];\r\n\t\t\t\t}\r\n\t\t\t} else if (regex.section.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.section);\r\n\t\t\t\tvalue[match[1]] = {};\r\n\t\t\t\tsection = match[1];\r\n\t\t\t};\r\n\t\t});\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the out-of-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onOOCEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tclient.sendOOC(document.getElementById(\"client_oocinputbox\").value);\r\n\t\tdocument.getElementById(\"client_oocinputbox\").value = \"\";\r\n\t}\r\n}\r\nwindow.onOOCEnter = onOOCEnter;\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the in-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tlet mychar = client.me();\r\n\t\tlet myemo = client.myEmote();\r\n\t\tlet ssfxname = \"0\";\r\n\t\tlet ssfxdelay = \"0\";\r\n\t\tif (document.getElementById(\"sendsfx\").checked) {\r\n\t\t\tssfxname = myemo.sfx;\r\n\t\t\tssfxdelay = myemo.sfxdelay;\r\n\t\t}\r\n\t\tclient.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById(\"client_inputbox\").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout);\r\n\t}\r\n}\r\nwindow.onEnter = onEnter;\r\n\r\n/**\r\n * Resets the IC parameters for the player to enter a new chat message.\r\n * This should only be called when the player's previous chat message\r\n * was successfully sent/presented.\r\n */\r\nfunction resetICParams() {\r\n\tdocument.getElementById(\"client_inputbox\").value = \"\";\r\n\tif (selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when an item on the music list is clicked.\r\n * @param {MouseEvent} event\r\n */\r\nexport function musiclist_click(event) {\r\n\tlet playtrack = document.getElementById(\"client_musiclist\").value;\r\n\tclient.sendMusicChange(playtrack);\r\n}\r\nwindow.musiclist_click = musiclist_click;\r\n\r\n/**\r\n * Triggered by the music volume slider.\r\n */\r\nexport function changeMusicVolume() {\r\n\tviewport.music.volume = document.getElementById(\"client_mvolume\").value / 100;\r\n}\r\nwindow.changeMusicVolume = changeMusicVolume;\r\n\r\n/**\r\n * Triggered by the sound effect volume slider.\r\n */\r\nexport function changeSFXVolume() {\r\n\tviewport.sfxaudio.volume = document.getElementById(\"client_svolume\").value / 100;\r\n}\r\nwindow.changeSFXVolume = changeSFXVolume;\r\n\r\n/**\r\n * Triggered by the blip volume slider.\r\n */\r\nexport function changeBlipVolume() {\r\n\tviewport.setBlipVolume(document.getElementById(\"client_bvolume\").value / 100);\r\n}\r\nwindow.changeBlipVolume = changeBlipVolume;\r\n\r\n/**\r\n * Triggered when a character icon is clicked in the character selection menu.\r\n * @param {MouseEvent} event\r\n */\r\nexport function changeCharacter(event) {\r\n\tclient.sendLeaveRoom();\r\n\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\tdocument.getElementById(\"client_emo\").innerHTML = \"\";\r\n}\r\nwindow.changeCharacter = changeCharacter;\r\n\r\n/**\r\n * Triggered when there was an error loading a character sprite.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function imgError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.gif\";\r\n\treturn true;\r\n}\r\nwindow.imgError = imgError;\r\n\r\n/**\r\n * Triggered when there was an error loading a character icon.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function demoError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.png\";\r\n\treturn true;\r\n}\r\nwindow.demoError = demoError;\r\n\r\n/**\r\n * Checks if an image exists at the specified URI.\r\n * @param {string} url the URI to be checked\r\n */\r\nfunction ImageExist(url) {\r\n\tvar img = new Image();\r\n\timg.src = url;\r\n\treturn img.height != 0;\r\n}\r\n\r\n/**\r\n * Changes the viewport background based on a given position.\r\n * \r\n * Valid positions: `def, pro, hld, hlp, wit, jud`\r\n * @param {string} position the position to change into\r\n */\r\nfunction changeBackground(position) {\r\n\tvar standname;\r\n\tlet bgfolder = viewport.bgFolder();\r\n\tdocument.getElementById(\"client_fg\").style.display = \"none\";\r\n\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\tswitch (position) {\r\n\t\tcase \"def\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"defenseempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"defensedesk.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"pro\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prosecutorempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"prosecutiondesk.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"hld\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"helperstand.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"hlp\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prohelperstand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"wit\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"witnessempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"estrado.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"jud\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"judgestand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t}\r\n\tif (viewport.chatmsg.type == 5) {\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_court\").src = AO_HOST + \"themes/default/\" + standname + \"_speedlines.gif\";\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the reconnect button is pushed.\r\n */\r\nexport function ReconnectButton() {\r\n\tclient.cleanup();\r\n\tclient = new Client(serverIP);\r\n\tif (client) {\r\n\t\tmode = \"join\"; // HACK: see client.onOpen\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.ReconnectButton = ReconnectButton;\r\n\r\n/**\r\n * Triggered when the retry button is pushed (during the loading process).\r\n */\r\nexport function RetryButton() {\r\n\tclient.joinServer();\r\n}\r\nwindow.RetryButton = RetryButton;\r\n\r\n/**\r\n * Appends a message to the in-character chat log.\r\n * @param {string} toadd the string to be added\r\n * @param {string} name the name of the sender\r\n */\r\nfunction appendICLog(toadd, name = \"\", time = new Date()) {\r\n\tconst entry = document.createElement(\"p\");\r\n\tconst nameField = document.createElement(\"span\");\r\n\tnameField.id = \"iclog_name\";\r\n\tnameField.appendChild(document.createTextNode(name));\r\n\tentry.appendChild(nameField);\r\n\tentry.appendChild(document.createTextNode(toadd));\r\n\r\n\t// Only put a timestamp if the minute has changed.\r\n\tif (lastICMessageTime.getMinutes() !== time.getMinutes()) {\r\n\t\tconst timeStamp = document.createElement(\"span\");\r\n\t\ttimeStamp.id = \"iclog_time\";\r\n\t\ttimeStamp.innerText = time.toLocaleTimeString(undefined, {\r\n\t\t\thour: \"numeric\",\r\n\t\t\tminute: \"2-digit\"\r\n\t\t});\r\n\t\tentry.appendChild(timeStamp);\r\n\t}\r\n\r\n\tconst clientLog = document.getElementById(\"client_log\");\r\n\tclientLog.appendChild(entry);\r\n\r\n\tif (clientLog.scrollTop > clientLog.scrollHeight - 600) {\r\n\t\tclientLog.scrollTop = clientLog.scrollHeight;\r\n\t}\r\n\r\n\tlastICMessageTime = new Date();\r\n}\r\n\r\n/**\r\n * Requests to play as a character.\r\n * @param {number} ccharacter the character ID; if this is a large number, then spectator is chosen instead.\r\n */\r\nexport function pickchar(ccharacter) {\r\n\tif (ccharacter < 1000) {\r\n\t\tclient.sendCharacter(ccharacter);\r\n\t} else {\r\n\t\t// Spectator\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_inputbox\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_emo\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.pickchar = pickchar;\r\n\r\n/**\r\n * Highlights and selects an emotion for in-character chat.\r\n * @param {string} emo the new emotion to be selected\r\n */\r\nexport function pickemotion(emo) {\r\n\tif (client.selectedEmote != -1) {\r\n\t\tdocument.getElementById(\"emo_\" + client.selectedEmote).src = client.myEmote().button_off;\r\n\t}\r\n\tclient.selectedEmote = emo\r\n\tdocument.getElementById(\"emo_\" + emo).src = client.myEmote().button_on;\r\n}\r\nwindow.pickemotion = pickemotion;\r\n\r\n/**\r\n * Highlights and selects a shout for in-character chat.\r\n * If the same shout button is selected, then the shout is canceled.\r\n * @param {string} shout the new shout to be selected\r\n */\r\nexport function toggleshout(shout) {\r\n\tif (shout == selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button dark\";\r\n\t\tif (selectedShout) {\r\n\t\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedShout = shout;\r\n\t}\r\n}\r\nwindow.toggleshout = toggleshout;\r\n\r\n/**\r\n * Escapes a string to be HTML-safe.\r\n * \r\n * XXX: This is unnecessary if we use `createTextNode` instead!\r\n * @param {string} unsafe an unsanitized string\r\n */\r\nfunction escapeHtml(unsafe) {\r\n\treturn unsafe\r\n\t\t.replace(/&/g, \"&amp;\")\r\n\t\t.replace(/</g, \"&lt;\")\r\n\t\t.replace(/>/g, \"&gt;\")\r\n\t\t.replace(/\"/g, \"&quot;\")\r\n\t\t.replace(/'/g, \"&#039;\");\r\n}\r\n\r\n/**\r\n * Escapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be escaped\r\n */\r\nfunction escapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(/#/g, \"<pound>\")\r\n\t\t.replace(/&/g, \"<and>\")\r\n\t\t.replace(/%/g, \"<percent>\")\r\n\t\t.replace(/\\$/g, \"<dollar>\");\r\n}\r\n\r\n// TODO: Possibly safe to remove, since we are using a transpiler.\r\nif (typeof(String.prototype.trim) === \"undefined\")\r\n{\r\n String.prototype.trim = function() \r\n {\r\n return String(this).replace(/^\\s+|\\s+$/g, '');\r\n };\r\n}\r\n\r\n// Used for HDID calculation.\r\nString.prototype.hashCode = function() {\r\n\tvar hash = 0, i, chr;\r\n\tif (this.length === 0) return hash;\r\n\tfor (i = 0; i < this.length; i++) {\r\n\t chr = this.charCodeAt(i);\r\n\t hash = ((hash << 5) - hash) + chr;\r\n\t hash |= 0; // Convert to 32bit integer\r\n\t}\r\n\treturn hash;\r\n};\r\n\r\n\r\n//\r\n// Client code\r\n//\r\n\r\nlet client = new Client(serverIP);\r\nlet viewport = new Viewport();\r\n"],"sourceRoot":""} \ No newline at end of file
+{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./webAO/client.js"],"names":["installedModules","__webpack_require__","moduleId","exports","module","i","l","modules","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","r","value","n","__esModule","object","property","prototype","hasOwnProperty","p","s","onOOCEnter","onEnter","musiclist_click","changeMusicVolume","changeSFXVolume","changeBlipVolume","changeCharacter","imgError","demoError","ReconnectButton","RetryButton","pickchar","pickemotion","toggleshout","queryDict","location","search","substr","split","forEach","item","serverIP","ip","mode","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","playerID","charID","chars","emotes","selectedEmote","checkUpdater","musicList","handlers","MS","args","handleMS","CT","handleCT","MC","handleMC","RMC","handleRMC","CI","handleCI","SC","handleSC","EI","handleEI","EM","handleEM","SM","handleSM","music","handlemusic","DONE","handleDONE","BN","handleBN","NBG","handleNBG","HP","handleHP","ID","handleID","PN","handlePN","SI","handleSI","CharsCheck","handleCharsCheck","PV","handlePV","CHECK","_lastTimeICReceived","message","send","escapeChat","speaking","silent","side","ssfxname","zoom","ssfxdelay","objection","track","_this2","hashCode","setInterval","sendCheck","character","song","e","document","getElementById","style","display","client","joinServer","console","error","reason","code","textContent","cleanup","msg","data","debug","header","handler","warn","close","clearInterval","viewport","chatmsg","content","innerHTML","pre","escape","preanim","nameplate","sound","type","snddelay","evidence","flash","color","isnew","length","className","say","oocLog","scrollTop","scrollHeight","pause","src","play","appendICLog","Audio","totime","offset","getTime","addEventListener","currentTime","parseFloat","toFixed","chargs","desc","icon","hmusiclist","newentry","createElement","text","options","add","bgname","clip","tr","td","icon_chosen","thispick","appendChild","changeBackground","me","xhr","XMLHttpRequest","open","responseType","onload","status","linifile","responseText","pinifile","INI","parse","Options","Emotions","number","emoteinfo","esfx","esfxd","SoundN","SoundT","sfx","sfxdelay","button_off","button_on","Viewport","textnow","startspeaking","blip","volume","blipChannels","Array","currentBlipChannel","sfxaudio","sfxplayed","updater","shoutTimer","textTimer","_animating","_this3","clearTimeout","setTimeout","updateText","_this4","trim","shout","1","2","3","fontSize","offsetHeight","replace","stylecolor","0","4","5","6","charAt","substring","regex","section","param","comment","line","match","event","keyCode","sendOOC","mychar","myemo","myEmote","checked","sendIC","playtrack","sendMusicChange","setBlipVolume","sendLeaveRoom","image","position","standname","bgfolder","bgFolder","toadd","arguments","undefined","time","entry","nameField","id","createTextNode","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","ccharacter","sendCharacter","emo","estring","window","String","hash","charCodeAt"],"mappings":"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","file":"client.b.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n","/*\r\n * Glorious webAO\r\n * made by sD, refactored by oldmud0\r\n * credits to aleks for original idea and source\r\n*/\r\n\r\nlet queryDict = {};\r\nlocation.search.substr(1).split(\"&\").forEach(function(item) {\r\n\tqueryDict[item.split(\"=\")[0]] = item.split(\"=\")[1]\r\n});\r\n\r\n/* Server magic */\r\n\r\nconst serverIP = queryDict.ip;\r\nlet mode = queryDict.mode;\r\n\r\nconst AO_HOST = queryDict.asset || \"http://assets.aceattorneyonline.com/base/\";\r\nconst MUSIC_HOST = AO_HOST + \"sounds/music/\";\r\nconst BAR_WIDTH = 90;\r\nconst BAR_HEIGHT = 20;\r\nconst CHAR_SELECT_WIDTH = 8;\r\nconst UPDATE_INTERVAL = 65;\r\n\r\nlet oldLoading = false;\r\nif (/Android|webOS|iPhone|iPad|iPod|BlackBerry|BB|PlayBook|IEMobile|Windows Phone|Kindle|Silk|Opera Mini/i.test(navigator.userAgent)) {\r\n\toldLoading = true;\r\n}\r\n\r\nlet selectedShout = 0;\r\nlet lastICMessageTime = new Date(0);\r\n\r\nclass Client {\r\n\tconstructor(address) {\r\n\t\tthis.serv = new WebSocket(\"ws://\" + address);\r\n\r\n\t\tthis.serv.onopen = (evt) => this.onOpen(evt);\r\n\t\tthis.serv.onclose = (evt) => this.onClose(evt);\r\n\t\tthis.serv.onmessage = (evt) => this.onMessage(evt);\r\n\t\tthis.serv.onerror = (evt) => this.onError(evt);\r\n\r\n\t\tthis.playerID = 1;\r\n\t\tthis.charID = -1;\r\n\r\n\t\tthis.chars = [];\r\n\t\tthis.emotes = [];\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\r\n\t\tthis.checkUpdater = null;\r\n\r\n\t\t// Only used for RMC/`music` packets, not EM/SM/MC packets.\r\n\t\tthis.musicList = Object();\r\n\r\n\t\tthis.handlers = {\r\n\t\t\t\"MS\": (args) => this.handleMS(args),\r\n\t\t\t\"CT\": (args) => this.handleCT(args),\r\n\t\t\t\"MC\": (args) => this.handleMC(args),\r\n\t\t\t\"RMC\": (args) => this.handleRMC(args),\r\n\t\t\t\"CI\": (args) => this.handleCI(args),\r\n\t\t\t\"SC\": (args) => this.handleSC(args),\r\n\t\t\t\"EI\": (args) => this.handleEI(args),\r\n\t\t\t\"EM\": (args) => this.handleEM(args),\r\n\t\t\t\"SM\": (args) => this.handleSM(args),\r\n\t\t\t\"music\": (args) => this.handlemusic(args),\r\n\t\t\t\"DONE\": (args) => this.handleDONE(args),\r\n\t\t\t\"BN\": (args) => this.handleBN(args),\r\n\t\t\t\"NBG\": (args) => this.handleNBG(args),\r\n\t\t\t\"HP\": (args) => this.handleHP(args),\r\n\t\t\t\"ID\": (args) => this.handleID(args),\r\n\t\t\t\"PN\": (args) => this.handlePN(args),\r\n\t\t\t\"SI\": (args) => this.handleSI(args),\r\n\t\t\t\"CharsCheck\": (args) => this.handleCharsCheck(args),\r\n\t\t\t\"PV\": (args) => this.handlePV(args),\r\n\t\t\t\"CHECK\": (args) => {}\r\n\t\t}\r\n\r\n\t\tthis._lastTimeICReceived = new Date(0);\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the current player's character.\r\n\t */\r\n\tme() {\r\n\t\treturn this.chars[this.charID];\r\n\t}\r\n\r\n\t/**\r\n\t * Gets the player's currently selected emote.\r\n\t */\r\n\tmyEmote() {\r\n\t\treturn this.emotes[this.selectedEmote];\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an out-of-character chat message.\r\n\t * @param {string} message the message to send\r\n\t */\r\n\tsendOOC(message) {\r\n\t\tthis.serv.send(`CT#web${this.playerID}#${escapeChat(message)}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends an in-character chat message.\r\n\t * @param {string} speaking who is speaking\r\n\t * @param {string} name the name of the current character\r\n\t * @param {string} silent whether or not it's silent\r\n\t * @param {string} message the message to be sent\r\n\t * @param {string} side the name of the side in the background\r\n\t * @param {string} ssfxname the name of the sound effect\r\n\t * @param {string} zoom whether or not to zoom\r\n\t * @param {string} ssfxdelay the delay (in milliseconds) to play the sound effect\r\n\t * @param {string} objection the number of the shout to play\r\n\t */\r\n\tsendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(message)}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#0#0#0#0#%`\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to change the music to the specified track.\r\n\t * @param {string} track the track ID\r\n\t */\r\n\tsendMusicChange(track) {\r\n\t\tthis.serv.send(`MC#${track}#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to leave the room and free the character slot.\r\n\t * \r\n\t * Note: This packet is undocumented. It is not implemented by\r\n\t * either the AO2 client or tsuserver.\r\n\t */\r\n\tsendLeaveRoom() {\r\n\t\tthis.serv.send(\"FC#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Begins the handshake process by sending an identifier\r\n\t * to the server.\r\n\t */\r\n\tjoinServer() {\r\n\t\tthis.serv.send(`HI#${navigator.userAgent.hashCode()}#%`);\r\n\t\tthis.serv.send(\"ID#webAO#2.4.5#%\");\r\n\t\tthis.checkUpdater = setInterval(() => this.sendCheck(), 5000);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to play as a specified character.\r\n\t * @param {number} character the character ID\r\n\t */\r\n\tsendCharacter(character) {\r\n\t\tthis.serv.send(`CC#${this.playerID}#${character}#web#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Requests to select a music track.\r\n\t * @param {number?} song the song to be played\r\n\t */\r\n\tsendMusic(song) {\r\n\t\tthis.serv.send(`MC#${song}`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends a keepalive packet.\r\n\t */\r\n\tsendCheck() {\r\n\t\tthis.serv.send(`CH#${this.charID}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a connection is established to the server.\r\n\t */\r\n\tonOpen(e) {\r\n\t\t// XXX: Why does watching mean just SITTING there and doing nothing?\r\n\t\tif (mode === \"watch\") {\r\n\t\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tclient.joinServer();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when the connection to the server closes.\r\n\t * @param {CloseEvent} e\r\n\t */\r\n\tonClose(e) {\r\n\t\tconsole.error(`The connection was closed: ${e.reason} (${e.code})`);\r\n\t\tif (e.code !== 1001) {\r\n\t\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\t\tthis.cleanup();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when a packet is received from the server.\r\n\t * @param {MessageEvent} e\r\n\t */\r\n\tonMessage(e) {\r\n\t\tlet msg = e.data;\r\n\t\tconsole.debug(msg);\r\n\t\tlet lines = msg.split('%');\r\n\t\tlet args = lines[0].split('#');\r\n\t\tlet header = args[0];\r\n\t\tlet handler = this.handlers[header];\r\n\t\tif (typeof handler !== \"undefined\") {\r\n\t\t\thandler(args);\r\n\t\t} else {\r\n\t\t\tconsole.warn(`Invalid packet header ${header}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Triggered when an network error occurs.\r\n\t * @param {ErrorEvent} e \r\n\t */\r\n\tonError(e) {\r\n\t\tconsole.error(`A network error occurred: ${e.reason} (${e.code})`);\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"block\";\r\n\t\tdocument.getElementById(\"error_id\").textContent = e.code;\r\n\t\tthis.cleanup();\r\n\t}\r\n\r\n\tcleanup() {\r\n\t\ttry {\r\n\t\t\tthis.serv.close(1001);\r\n\t\t} catch (e) {\r\n\t\t\t// I don't care if this errors\r\n\t\t}\r\n\t\tclearInterval(this.checkUpdater);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an in-character chat message.\r\n\t * @param {*} args packet arguments\r\n\t */\r\n\thandleMS(args) {\r\n\t\t// TODO: this if-statement might be a bug.\r\n\t\tif (args[4] != viewport.chatmsg.content) {\r\n\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = \"\";\r\n\t\t\tlet chatmsg = {\r\n\t\t\t\tpre: escape(args[2]),\r\n\t\t\t\tcharacter: -1, // Will do a linear search\r\n\t\t\t\tpreanim: escape(args[2]), // XXX: why again?\r\n\t\t\t\tnameplate: args[3], // TODO: parse INI to get this info\r\n\t\t\t\tname: args[3],\r\n\t\t\t\tspeaking: \"(b)\" + escape(args[4]),\r\n\t\t\t\tsilent: \"(a)\" + escape(args[4]),\r\n\t\t\t\tcontent: args[5],\r\n\t\t\t\tside: args[6],\r\n\t\t\t\tsound: escape(args[7]),\r\n\t\t\t\ttype: args[8],\r\n\t\t\t\t// charid: args[9],\r\n\t\t\t\tsnddelay: args[10],\r\n\t\t\t\tobjection: args[11],\r\n\t\t\t\tevidence: args[12],\r\n\t\t\t\t// flip: args[13],\r\n\t\t\t\tflash: args[14],\r\n\t\t\t\tcolor: args[15],\r\n\t\t\t\tisnew: true,\r\n\t\t\t};\r\n\r\n\t\t\t// The dreaded linear search...\r\n\t\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\t\tif (this.chars[i].name == args[3]) {\r\n\t\t\t\t\tchatmsg.character = i;\r\n\t\t\t\t\tbreak;\r\n\t\t\t\t}\r\n\t\t\t}\r\n\r\n\t\t\tif (chatmsg.character == this.charID) {\r\n\t\t\t\tresetICParams();\r\n\t\t\t}\r\n\r\n\t\t\tviewport.say(chatmsg);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles an out-of-character chat message.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCT(args) {\r\n\t\tconst oocLog = document.getElementById(\"client_ooclog\");\r\n\t\toocLog.innerHTML += `${args[1]}: ${args[2]}\\r\\n`;\r\n\t\tif (oocLog.scrollTop > oocLog.scrollHeight - 60) {\r\n\t\t\toocLog.scrollTop = oocLog.scrollHeight;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleMC(args) {\r\n\t\tconst music = viewport.music;\r\n\t\tmusic.pause();\r\n\t\tmusic.src = MUSIC_HOST + args[1];\r\n\t\tmusic.play();\r\n\t\tif (args[2] >= 0) {\r\n\t\t\tlet musicname = this.chars[args[2]].name;\r\n\t\t\tappendICLog(`${musicname} changed music to ${args[1]}`);\r\n\t\t} else {\r\n\t\t\tappendICLog(`The music was changed to ${args[1]}`);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a music change to an arbitrary resource, with an offset in seconds.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleRMC(args) {\r\n\t\tviewport.music.pause();\r\n\t\tviewport.music = new Audio(this.musicList[args[1]]);\r\n\t\tconst music = viewport.music;\r\n\t\t// Music offset + drift from song loading\r\n\t\tmusic.totime = args[1];\r\n\t\tmusic.offset = new Date().getTime() / 1000;\r\n\t\tmusic.addEventListener('loadedmetadata', function() {\r\n\t\t\tmusic.currentTime += parseFloat(music.totime + (new Date().getTime() / 1000 - music.offset)).toFixed(3);\r\n\t\t\tmusic.play();\r\n\t\t}, false);\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, bundling multiple characters\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Character \" + args[1];\r\n\t\tthis.serv.send(\"AN#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\t\tthis.chars[args[i - 1]] = {\r\n\t\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t\t};\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming character information, containing only one character\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSC(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Characters\";\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet chargs = args[i].split(\"&\");\r\n\t\t\tthis.chars[i - 1] = {\r\n\t\t\t\t\"name\": chargs[0],\r\n\t\t\t\t\"desc\": chargs[1],\r\n\t\t\t\t\"evidence\": chargs[3],\r\n\t\t\t\t\"icon\": AO_HOST + \"characters/\" + escape(chargs[0]) + \"/char_icon.png\"\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming evidence information, containing only one evidence\r\n\t * item per packet.\r\n\t * \r\n\t * Mostly unimplemented in webAO.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEI(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Evidence \" + args[1];\r\n\t\t//serv.send(\"AE#\" + (args[1] + 1) + \"#%\");\r\n\t\tthis.serv.send(\"RM#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing multiple entries\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleEM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \" + args[1];\r\n\t\tthis.serv.send(\"AM#\" + ((args[1] / 10) + 1) + \"#%\");\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 2; i < args.length - 1; i++) {\r\n\t\t\tif (i % 2 == 0) {\r\n\t\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\t\tnewentry.text = args[i];\r\n\t\t\t\thmusiclist.options.add(newentry);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing only one entry\r\n\t * per packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSM(args) {\r\n\t\tdocument.getElementById(\"client_loadingtext\").innerHTML = \"Loading Music \";\r\n\t\tlet hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tlet newentry = document.createElement(\"OPTION\");\r\n\t\t\tnewentry.text = args[i];\r\n\t\t\thmusiclist.options.add(newentry);\r\n\t\t}\r\n\t\tthis.serv.send(\"RD#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles incoming music information, containing all entries\r\n\t * in the same packet.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlemusic(args) {\r\n\t\tfor (let i = 0; i < args.length / 2; i++) {\r\n\t\t\tthis.musicList[args[2 * i]] = args[2 * i + 1];\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the handshake completion packet, meaning the player\r\n\t * is ready to select a character.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleDONE(args) {\r\n\t\tdocument.getElementById(\"client_loading\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a background change.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleBN(args) {\r\n\t\tviewport.bgname = escape(args[1]);\r\n\t}\r\n\r\n\thandleNBG(args) {\r\n\t\t// TODO (set by sD)\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a change in the health bars' states.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleHP(args) {\r\n\t\t// TODO (set by sD)\r\n\t\t// Also, this is broken.\r\n\t\tif (args[1] == 1) {\r\n\t\t\tdocument.getElementById(\"client_defense_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_prosecutor_hp\").style.clip = \"rect(0px,\" + BAR_WIDTH * args[2] / 10 + \"px,\" + BAR_HEIGHT + \"px,0px)\";\r\n\t\t}\r\n\t}\r\n\t\r\n\t/**\r\n\t * Handles the issuance of a player ID by the server.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleID(args) {\r\n\t\tthis.playerID = args[1];\r\n\t}\r\n\r\n\thandlePN(args) {\r\n\t\tthis.serv.send(\"askchaa#%\");\r\n\t}\r\n\r\n\t/**\r\n\t * Received when the server announces its server info,\r\n\t * but we use it as a cue to begin retrieving characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleSI(args) {\r\n\t\tif (oldLoading) {\r\n\t\t\tthis.serv.send(\"askchar2#%\");\r\n\t\t} else {\r\n\t\t\tthis.serv.send(\"RC#%\");\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the list of all used and vacant characters.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleCharsCheck(args) {\r\n\t\tdocument.getElementById(\"client_chartable\").innerHTML = \"\";\r\n\t\tfor (let i = 0; i < this.chars.length; i++) {\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tvar tr = document.createElement('TR');\r\n\t\t\t}\r\n\t\t\tlet td = document.createElement('TD');\r\n\t\t\tlet icon_chosen;\r\n\t\t\tlet thispick = this.chars[i].icon;\r\n\t\t\tif (args[i + 1] == \"-1\") {\r\n\t\t\t\ticon_chosen = \" dark\";\r\n\t\t\t} else {\r\n\t\t\t\ticon_chosen = \"\";\r\n\t\t\t}\r\n\t\t\ttd.innerHTML = `<img class='demothing${icon_chosen}' id='demo_${i}' ` +\r\n\t\t\t\t`src='${thispick}' alt='${this.chars[i].name}' onclick='pickchar(${i})' ` +\r\n\t\t\t\t`onerror='demoError(this);'>`;\r\n\t\t\ttr.appendChild(td);\r\n\t\t\tif (i % CHAR_SELECT_WIDTH == 0) {\r\n\t\t\t\tdocument.getElementById(\"client_chartable\").appendChild(tr);\r\n\t\t\t}\r\n\t\t}\r\n\t\tchangeBackground(\"def\");\r\n\t}\r\n\r\n\t/**\r\n\t * Handles the server's assignment of a character for the player to use.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandlePV(args) {\r\n\t\tthis.charID = args[3];\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tlet me = this.me();\r\n\t\tlet emotes = this.emotes;\r\n\t\tlet xhr = new XMLHttpRequest();\r\n\t\txhr.open('GET', AO_HOST + 'characters/' + escape(this.me().name) + '/char.ini', true);\r\n\t\txhr.responseType = 'text';\r\n\t\txhr.onload = function (e) {\r\n\t\t\tif (this.status == 200) {\r\n\t\t\t\tlet linifile = this.responseText;\r\n\t\t\t\tlet pinifile = INI.parse(linifile);\r\n\t\t\t\tme.side = pinifile.Options.side;\r\n\t\t\t\tfor (let i = 1; i < pinifile.Emotions.number; i++) {\r\n\t\t\t\t\tlet emoteinfo = pinifile.Emotions[i].split('#');\r\n\t\t\t\t\tlet esfx = \"0\";\r\n\t\t\t\t\tlet esfxd = \"0\";\r\n\t\t\t\t\tif (typeof pinifile.SoundN !== 'undefined') {\r\n\t\t\t\t\t\tesfx = pinifile.SoundN[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\tif (typeof pinifile.SoundT !== 'undefined') {\r\n\t\t\t\t\t\tesfxd = pinifile.SoundT[i];\r\n\t\t\t\t\t}\r\n\t\t\t\t\temotes[i] = {\r\n\t\t\t\t\t\tdesc: emoteinfo[0],\r\n\t\t\t\t\t\tspeaking: emoteinfo[1],\r\n\t\t\t\t\t\tsilent: emoteinfo[2],\r\n\t\t\t\t\t\tzoom: emoteinfo[3],\r\n\t\t\t\t\t\tsfx: esfx,\r\n\t\t\t\t\t\tsfxdelay: esfxd,\r\n\t\t\t\t\t\tbutton_off: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_off.png',\r\n\t\t\t\t\t\tbutton_on: AO_HOST + 'characters/' + escape(me.name) + '/emotions/button' + i + '_on.png'\r\n\t\t\t\t\t};\r\n\t\t\t\t\tdocument.getElementById(\"client_emo\").innerHTML += \"<img src='\" + emotes[i].button_off + \"' id='emo_\" + i + \"' alt='\" + emotes[i].desc + \"' class='client_button' onclick='pickemotion(\" + i + \")'>\";\r\n\t\t\t\t}\r\n\t\t\t\tpickemotion(1);\r\n\t\t\t}\r\n\t\t};\r\n\t\txhr.send();\r\n\t}\r\n}\r\n\r\nclass Viewport {\r\n\tconstructor() {\r\n\t\tthis.textnow = \"\";\r\n\t\tthis.chatmsg = {\r\n\t\t\t\"isnew\": false,\r\n\t\t\t\"content\": \"\",\r\n\t\t\t\"objection\": \"0\",\r\n\t\t\t\"sound\": \"\",\r\n\t\t\t\"startspeaking\": false,\r\n\t\t\t\"side\": null,\r\n\t\t\t\"color\": \"0\",\r\n\t\t\t\"snddelay\": 0\r\n\t\t};\r\n\t\tthis.blip = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.blip.volume = 0.5;\r\n\r\n\t\t// Allocate multiple blip audio channels to make blips less jittery\r\n\r\n\t\t// TODO: read blip type (\"gender\") from ini\r\n\t\tthis.blipChannels = new Array(6);\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i] = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\t\tthis.blipChannels[i].volume = 0.5;\r\n\t\t}\r\n\t\tthis.currentBlipChannel = 0;\r\n\r\n\t\tthis.sfxaudio = new Audio(AO_HOST + 'sounds/general/sfx-blipmale.wav');\r\n\t\tthis.sfxplayed = 0;\r\n\r\n\t\tthis.music = new Audio();\r\n\t\tthis.music.play();\r\n\r\n\t\tthis.updater = null;\r\n\r\n\t\tthis.bgname = \"gs4\";\r\n\r\n\t\tthis.shoutTimer = 0;\r\n\t\tthis.textTimer = 0;\r\n\r\n\t\tthis._animating = false;\r\n\t}\r\n\r\n\t/**\r\n\t * Returns whether or not the viewport is busy\r\n\t * performing a task (animating).\r\n\t */\r\n\tisAnimating() {\r\n\t\treturn this._animating;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets the volume of the blip sound.\r\n\t * @param {number} volume\r\n\t */\r\n\tsetBlipVolume(volume) {\r\n\t\tfor (let i = 0; i < this.blipChannels.length; i++) {\r\n\t\t\tthis.blipChannels[i].volume = volume;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Returns the path which the background is located in.\r\n\t */\r\n\tbgFolder() {\r\n\t\treturn `${AO_HOST}background/${this.bgname}/`;\r\n\t}\r\n\r\n\t/**\r\n\t * Sets a new emote.\r\n\t * @param {object} chatmsg the new chat message\r\n\t */\r\n\tsay(chatmsg) {\r\n\t\tthis.chatmsg = chatmsg;\r\n\t\tappendICLog(chatmsg.content, chatmsg.nameplate);\r\n\t\tchangeBackground(chatmsg.side);\r\n\t\tthis.textnow = '';\r\n\t\tthis.sfxplayed = 0;\r\n\t\tthis.textTimer = 0;\r\n\t\tthis._animating = true;\r\n\t\tclearTimeout(this.updater);\r\n\t\tthis.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the chatbox based on the given text.\r\n\t * \r\n\t * XXX: This relies on a global variable `this.chatmsg`!\r\n\t */\r\n\tupdateText() {\r\n\t\tif (this.chatmsg.content.trim() == \"\") {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"none\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"none\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_name\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_chat\").style.display = \"block\";\r\n\t\t}\r\n\r\n\t\tif (this._animating) {\r\n\t\t\tthis.updater = setTimeout(() => this.updateText(), UPDATE_INTERVAL);\r\n\t\t}\r\n\r\n\t\tif (this.chatmsg.isnew) {\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"takethat\",\r\n\t\t\t\t\"3\": \"objection\"\r\n\t\t\t};\r\n\r\n\t\t\tlet shout = shouts[this.chatmsg.objection];\r\n\t\t\tif (typeof shout !== \"undefined\") {\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"misc/\" + shout + \".gif\";\r\n\t\t\t\t(new Audio(`${AO_HOST}/characters/${this.chatmsg.name}/${shout}.wav`)).play();\r\n\t\t\t\tthis.shoutTimer = 800;\r\n\t\t\t} else {\r\n\t\t\t\tthis.shoutTimer = 0;\r\n\t\t\t}\r\n\r\n\t\t\tthis.chatmsg.isnew = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t}\r\n\r\n\t\tif (this.textTimer >= this.shoutTimer) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.speaking + \".gif\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").style.fontSize = (document.getElementById(\"client_name\").offsetHeight * 0.7) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_chat\").style.fontSize = (document.getElementById(\"client_chat\").offsetHeight * 0.25) + \"px\";\r\n\t\t\t\tdocument.getElementById(\"client_name\").innerHTML = \"<p>\" + escapeHtml(this.chatmsg.nameplate) + \"</p>\";\r\n\r\n\t\t\t\tconst colors = {\r\n\t\t\t\t\t\"0\": \"#ffffff\",\r\n\t\t\t\t\t\"1\": \"#00ff00\",\r\n\t\t\t\t\t\"2\": \"#ff0000\",\r\n\t\t\t\t\t\"3\": \"#ffaa00\",\r\n\t\t\t\t\t\"4\": \"#0000ff\",\r\n\t\t\t\t\t\"5\": \"#ffff00\",\r\n\t\t\t\t\t\"6\": \"#aa00aa\"\r\n\t\t\t\t}\r\n\t\t\t\tlet stylecolor = \"color: \" + (colors[this.chatmsg.color] || \"#ffffff\");\r\n\t\t\t\tdocument.getElementById(\"client_inner_chat\").style = stylecolor;\r\n\t\t\t\tthis.chatmsg.startspeaking = false;\r\n\r\n\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\tclearTimeout(this.updater);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tif (this.textnow != this.chatmsg.content) {\r\n\t\t\t\t\tif (this.chatmsg.content.charAt(this.textnow.length) != \" \") {\r\n\t\t\t\t\t\tthis.blipChannels[this.currentBlipChannel].play();\r\n\t\t\t\t\t\tthis.currentBlipChannel++;\r\n\t\t\t\t\t\tthis.currentBlipChannel %= this.blipChannels.length;\r\n\t\t\t\t\t}\r\n\t\t\t\t\tthis.textnow = this.chatmsg.content.substring(0, this.textnow.length + 1);\r\n\t\t\t\t\tdocument.getElementById(\"client_inner_chat\").innerHTML = this.textnow;\r\n\t\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\t\tthis.textTimer = 0;\r\n\t\t\t\t\t\tthis._animating = false;\r\n\t\t\t\t\t\tdocument.getElementById(\"client_char\").src = AO_HOST + \"characters/\" + escape(this.chatmsg.name) + \"/\" + this.chatmsg.silent + \".gif\";\r\n\t\t\t\t\t\tclearTimeout(this.updater);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!this.sfxplayed && this.chatmsg.snddelay + this.shoutTimer >= this.textTimer) {\r\n\t\t\tthis.sfxaudio.pause();\r\n\t\t\tthis.sfxplayed = 1;\r\n\t\t\tif (this.chatmsg.sound != \"0\" && this.chatmsg.sound != \"1\") {\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/\" + escape(this.chatmsg.sound) + \".wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.textTimer = this.textTimer + UPDATE_INTERVAL;\r\n\t}\r\n}\r\n\r\nclass INI {\r\n\tstatic parse(data) {\r\n\t\tlet regex = {\r\n\t\t\tsection: /^\\s*\\[\\s*([^\\]]*)\\s*\\]\\s*$/,\r\n\t\t\tparam: /^\\s*([\\w\\.\\-\\_]+)\\s*=\\s*(.*?)\\s*$/,\r\n\t\t\tcomment: /^\\s*;.*$/\r\n\t\t};\r\n\t\tlet value = {};\r\n\t\tlet lines = data.split(/\\r\\n|\\r|\\n/);\r\n\t\tlet section = null;\r\n\t\tlines.forEach(function(line) {\r\n\t\t\tif (regex.comment.test(line)) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (line.length == 0) {\r\n\t\t\t\treturn;\r\n\t\t\t} else if (regex.param.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.param);\r\n\t\t\t\tif (section) {\r\n\t\t\t\t\tvalue[section][match[1]] = match[2];\r\n\t\t\t\t} else {\r\n\t\t\t\t\tvalue[match[1]] = match[2];\r\n\t\t\t\t}\r\n\t\t\t} else if (regex.section.test(line)) {\r\n\t\t\t\tlet match = line.match(regex.section);\r\n\t\t\t\tvalue[match[1]] = {};\r\n\t\t\t\tsection = match[1];\r\n\t\t\t};\r\n\t\t});\r\n\t\treturn value;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the out-of-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onOOCEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tclient.sendOOC(document.getElementById(\"client_oocinputbox\").value);\r\n\t\tdocument.getElementById(\"client_oocinputbox\").value = \"\";\r\n\t}\r\n}\r\nwindow.onOOCEnter = onOOCEnter;\r\n\r\n/**\r\n * Triggered when the Return key is pressed on the in-character chat input box.\r\n * @param {KeyboardEvent} event\r\n */\r\nexport function onEnter(event) {\r\n\tif (event.keyCode == 13) {\r\n\t\tlet mychar = client.me();\r\n\t\tlet myemo = client.myEmote();\r\n\t\tlet ssfxname = \"0\";\r\n\t\tlet ssfxdelay = \"0\";\r\n\t\tif (document.getElementById(\"sendsfx\").checked) {\r\n\t\t\tssfxname = myemo.sfx;\r\n\t\t\tssfxdelay = myemo.sfxdelay;\r\n\t\t}\r\n\t\tclient.sendIC(myemo.speaking, mychar.name, myemo.silent, document.getElementById(\"client_inputbox\").value, mychar.side, ssfxname, myemo.zoom, ssfxdelay, selectedShout);\r\n\t}\r\n}\r\nwindow.onEnter = onEnter;\r\n\r\n/**\r\n * Resets the IC parameters for the player to enter a new chat message.\r\n * This should only be called when the player's previous chat message\r\n * was successfully sent/presented.\r\n */\r\nfunction resetICParams() {\r\n\tdocument.getElementById(\"client_inputbox\").value = \"\";\r\n\tif (selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when an item on the music list is clicked.\r\n * @param {MouseEvent} event\r\n */\r\nexport function musiclist_click(event) {\r\n\tlet playtrack = document.getElementById(\"client_musiclist\").value;\r\n\tclient.sendMusicChange(playtrack);\r\n}\r\nwindow.musiclist_click = musiclist_click;\r\n\r\n/**\r\n * Triggered by the music volume slider.\r\n */\r\nexport function changeMusicVolume() {\r\n\tviewport.music.volume = document.getElementById(\"client_mvolume\").value / 100;\r\n}\r\nwindow.changeMusicVolume = changeMusicVolume;\r\n\r\n/**\r\n * Triggered by the sound effect volume slider.\r\n */\r\nexport function changeSFXVolume() {\r\n\tviewport.sfxaudio.volume = document.getElementById(\"client_svolume\").value / 100;\r\n}\r\nwindow.changeSFXVolume = changeSFXVolume;\r\n\r\n/**\r\n * Triggered by the blip volume slider.\r\n */\r\nexport function changeBlipVolume() {\r\n\tviewport.setBlipVolume(document.getElementById(\"client_bvolume\").value / 100);\r\n}\r\nwindow.changeBlipVolume = changeBlipVolume;\r\n\r\n/**\r\n * Triggered when a character icon is clicked in the character selection menu.\r\n * @param {MouseEvent} event\r\n */\r\nexport function changeCharacter(event) {\r\n\tclient.sendLeaveRoom();\r\n\tdocument.getElementById(\"client_charselect\").style.display = \"block\";\r\n\tdocument.getElementById(\"client_emo\").innerHTML = \"\";\r\n}\r\nwindow.changeCharacter = changeCharacter;\r\n\r\n/**\r\n * Triggered when there was an error loading a character sprite.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function imgError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.gif\";\r\n\treturn true;\r\n}\r\nwindow.imgError = imgError;\r\n\r\n/**\r\n * Triggered when there was an error loading a character icon.\r\n * @param {HTMLImageElement} image the element containing the missing image\r\n */\r\nexport function demoError(image) {\r\n\timage.onerror = \"\";\r\n\timage.src = \"/misc/placeholder.png\";\r\n\treturn true;\r\n}\r\nwindow.demoError = demoError;\r\n\r\n/**\r\n * Checks if an image exists at the specified URI.\r\n * @param {string} url the URI to be checked\r\n */\r\nfunction ImageExist(url) {\r\n\tvar img = new Image();\r\n\timg.src = url;\r\n\treturn img.height != 0;\r\n}\r\n\r\n/**\r\n * Changes the viewport background based on a given position.\r\n * \r\n * Valid positions: `def, pro, hld, hlp, wit, jud`\r\n * @param {string} position the position to change into\r\n */\r\nfunction changeBackground(position) {\r\n\tvar standname;\r\n\tlet bgfolder = viewport.bgFolder();\r\n\tdocument.getElementById(\"client_fg\").style.display = \"none\";\r\n\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\tswitch (position) {\r\n\t\tcase \"def\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"defenseempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"defensedesk.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"pro\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prosecutorempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"prosecutiondesk.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"hld\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"helperstand.png\"\r\n\t\t\tstandname = \"defense\";\r\n\t\t\tbreak;\r\n\t\tcase \"hlp\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prohelperstand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"wit\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"witnessempty.png\"\r\n\t\t\tdocument.getElementById(\"client_bench\").style.display = \"block\"\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"estrado.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t\tcase \"jud\":\r\n\t\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"judgestand.png\"\r\n\t\t\tstandname = \"prosecution\";\r\n\t\t\tbreak;\r\n\t}\r\n\tif (viewport.chatmsg.type == 5) {\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_court\").src = AO_HOST + \"themes/default/\" + standname + \"_speedlines.gif\";\r\n\t}\r\n}\r\n\r\n/**\r\n * Triggered when the reconnect button is pushed.\r\n */\r\nexport function ReconnectButton() {\r\n\tclient.cleanup();\r\n\tclient = new Client(serverIP);\r\n\tif (client) {\r\n\t\tmode = \"join\"; // HACK: see client.onOpen\r\n\t\tdocument.getElementById(\"client_error\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.ReconnectButton = ReconnectButton;\r\n\r\n/**\r\n * Triggered when the retry button is pushed (during the loading process).\r\n */\r\nexport function RetryButton() {\r\n\tclient.joinServer();\r\n}\r\nwindow.RetryButton = RetryButton;\r\n\r\n/**\r\n * Appends a message to the in-character chat log.\r\n * @param {string} toadd the string to be added\r\n * @param {string} name the name of the sender\r\n */\r\nfunction appendICLog(toadd, name = \"\", time = new Date()) {\r\n\tconst entry = document.createElement(\"p\");\r\n\tconst nameField = document.createElement(\"span\");\r\n\tnameField.id = \"iclog_name\";\r\n\tnameField.appendChild(document.createTextNode(name));\r\n\tentry.appendChild(nameField);\r\n\tentry.appendChild(document.createTextNode(toadd));\r\n\r\n\t// Only put a timestamp if the minute has changed.\r\n\tif (lastICMessageTime.getMinutes() !== time.getMinutes()) {\r\n\t\tconst timeStamp = document.createElement(\"span\");\r\n\t\ttimeStamp.id = \"iclog_time\";\r\n\t\ttimeStamp.innerText = time.toLocaleTimeString(undefined, {\r\n\t\t\thour: \"numeric\",\r\n\t\t\tminute: \"2-digit\"\r\n\t\t});\r\n\t\tentry.appendChild(timeStamp);\r\n\t}\r\n\r\n\tconst clientLog = document.getElementById(\"client_log\");\r\n\tclientLog.appendChild(entry);\r\n\r\n\tif (clientLog.scrollTop > clientLog.scrollHeight - 600) {\r\n\t\tclientLog.scrollTop = clientLog.scrollHeight;\r\n\t}\r\n\r\n\tlastICMessageTime = new Date();\r\n}\r\n\r\n/**\r\n * Requests to play as a character.\r\n * @param {number} ccharacter the character ID; if this is a large number, then spectator is chosen instead.\r\n */\r\nexport function pickchar(ccharacter) {\r\n\tif (ccharacter < 1000) {\r\n\t\tclient.sendCharacter(ccharacter);\r\n\t} else {\r\n\t\t// Spectator\r\n\t\tdocument.getElementById(\"client_charselect\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_inputbox\").style.display = \"none\";\r\n\t\tdocument.getElementById(\"client_emo\").style.display = \"none\";\r\n\t}\r\n}\r\nwindow.pickchar = pickchar;\r\n\r\n/**\r\n * Highlights and selects an emotion for in-character chat.\r\n * @param {string} emo the new emotion to be selected\r\n */\r\nexport function pickemotion(emo) {\r\n\tif (client.selectedEmote != -1) {\r\n\t\tdocument.getElementById(\"emo_\" + client.selectedEmote).src = client.myEmote().button_off;\r\n\t}\r\n\tclient.selectedEmote = emo\r\n\tdocument.getElementById(\"emo_\" + emo).src = client.myEmote().button_on;\r\n}\r\nwindow.pickemotion = pickemotion;\r\n\r\n/**\r\n * Highlights and selects a shout for in-character chat.\r\n * If the same shout button is selected, then the shout is canceled.\r\n * @param {string} shout the new shout to be selected\r\n */\r\nexport function toggleshout(shout) {\r\n\tif (shout == selectedShout) {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button\";\r\n\t\tselectedShout = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_\" + shout).className = \"client_button dark\";\r\n\t\tif (selectedShout) {\r\n\t\t\tdocument.getElementById(\"button_\" + selectedShout).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedShout = shout;\r\n\t}\r\n}\r\nwindow.toggleshout = toggleshout;\r\n\r\n/**\r\n * Escapes a string to be HTML-safe.\r\n * \r\n * XXX: This is unnecessary if we use `createTextNode` instead!\r\n * @param {string} unsafe an unsanitized string\r\n */\r\nfunction escapeHtml(unsafe) {\r\n\treturn unsafe\r\n\t\t.replace(/&/g, \"&amp;\")\r\n\t\t.replace(/</g, \"&lt;\")\r\n\t\t.replace(/>/g, \"&gt;\")\r\n\t\t.replace(/\"/g, \"&quot;\")\r\n\t\t.replace(/'/g, \"&#039;\");\r\n}\r\n\r\n/**\r\n * Escapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be escaped\r\n */\r\nfunction escapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(/#/g, \"<pound>\")\r\n\t\t.replace(/&/g, \"<and>\")\r\n\t\t.replace(/%/g, \"<percent>\")\r\n\t\t.replace(/\\$/g, \"<dollar>\");\r\n}\r\n\r\n// TODO: Possibly safe to remove, since we are using a transpiler.\r\nif (typeof(String.prototype.trim) === \"undefined\")\r\n{\r\n String.prototype.trim = function() \r\n {\r\n return String(this).replace(/^\\s+|\\s+$/g, '');\r\n };\r\n}\r\n\r\n// Used for HDID calculation.\r\nString.prototype.hashCode = function() {\r\n\tvar hash = 0, i, chr;\r\n\tif (this.length === 0) return hash;\r\n\tfor (i = 0; i < this.length; i++) {\r\n\t chr = this.charCodeAt(i);\r\n\t hash = ((hash << 5) - hash) + chr;\r\n\t hash |= 0; // Convert to 32bit integer\r\n\t}\r\n\treturn hash;\r\n};\r\n\r\n\r\n//\r\n// Client code\r\n//\r\n\r\nlet client = new Client(serverIP);\r\nlet viewport = new Viewport();\r\n"],"sourceRoot":""} \ No newline at end of file