From 1db7474cbdcf13c586ee3fc446375d8a9d638a10 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Sat, 8 Sep 2018 21:12:16 -0500 Subject: Fix some more annoyances - Use createTextNode instead of escapeHtml - Add area change messages in IC log - Move "Call Mod" button to menu, replacing "Guide" which was mostly empty except for the BBCode reference (but you can surely look that up somewhere else, at least until more documentation for webAO has been produced) - Compact the evidence editor - Fix bug where the last emote was not displayed in the emotes list Some issues that remain: - Clients still cannot send special Unicode characters, but they can receive them correctly. - Shout animations run for longer than the GIF animation length. - Preanims sometimes play when they are not supposed to. - GoldenLayout panels cannot be dragged around for some reason. - The chatbox does not automatically scroll down. - When the game panel is maximized, the viewport should not exceed the size of the game panel. --- webAO/client.b.js | 2 +- webAO/client.b.js.map | 2 +- webAO/client.css | 11 ++++-- webAO/client.html | 93 ++++++++++++++------------------------------------- webAO/client.js | 43 +++++++++++++++++------- 5 files changed, 66 insertions(+), 85 deletions(-) diff --git a/webAO/client.b.js b/webAO/client.b.js index ac6b321..8eae4ff 100644 --- a/webAO/client.b.js +++ b/webAO/client.b.js @@ -1,2 +1,2 @@ -!function(e){var n={};function t(o){if(n[o])return n[o].exports;var a=n[o]={i:o,l:!1,exports:{}};return e[o].call(a.exports,a,a.exports,t),a.l=!0,a.exports}t.m=e,t.c=n,t.d=function(e,n,o){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:o})},t.r=function(e){Object.defineProperty(e,"__esModule",{value:!0})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,n){return Object.prototype.hasOwnProperty.call(e,n)},t.p="",t(t.s=2)}([function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.default=["1.gif","1.png","2.png","3.png","4.png","5.gif","5.png","6.gif","6.png","AACastApril.png","AACastBellboy.png","AACastButz.png","AACastButz2.png","AACastButz3.png","AACastCindy.png","AACastCody.png","AACastDarke.png","AACastEma.png","AACastGant.png","AACastGoodman.png","AACastGregory.png","AACastGrossberg.png","AACastGumshoe.png","AACastHammer.png","AACastJake.png","AACastJudge.png","AACastLana.png","AACastLotta.png","AACastManfred.png","AACastMaya.png","AACastMeekins.png","AACastMia.png","AACastMiles.png","AACastMisty.png","AACastNeil.png","AACastOldbag.png","AACastOldbag2.png","AACastPayne.png","AACastPayne2.png","AACastPenny.png","AACastPhoenix.png","AACastPhoenix2.png","AACastPowers.png","AACastPowers2.png","AACastSahwit.png","AACastSal.png","AACastStarr.png","AACastVasquez.png","AACastWhite.png","AAI2CastBlaise.png","AAI2CastBonnie.png","AAI2CastCameron.png","AAI2CastCourtney.png","AAI2CastDelicia.png","AAI2CastDogen.png","AAI2CastElbird.png","AAI2CastGustavia.png","AAI2CastGustavia2.png","AAI2CastJill.png","AAI2CastKarin.png","AAI2CastKatherine.png","AAI2CastKatherine2.png","AAI2CastKnightley.png","AAI2CastMarsh.png","AAI2CastMaster.png","AAI2CastMaster2.png","AAI2CastNicole.png","AAI2CastPierre.png","AAI2CastRaymond.png","AAI2CastRaymond2.png","AAI2CastRoland.png","AAI2CastRooke.png","AAI2CastSahwit.png","AAI2CastSebastian.png","AAI2CastShelly.png","AAI2CastSimon.png","AAI2bag.png","AAI2balloon.png","AAI2bell.png","AAI2blanket.png","AAI2body.png","AAI2button.png","AAI2chess.png","AAI2clip.png","AAI2cuffs.png","AAI2dog.png","AAI2door.png","AAI2floor.png","AAI2gate.png","AAI2glove.png","AAI2gun.png","AAI2key.png","AAI2map.png","AAI2map2.png","AAI2map3.png","AAI2note.png","AAI2rope.png","AAI2shovel.png","AAI2tunnel.png","AAI2uniform.png","AAI2video.png","AAI2well.png","AAICastAkbey.png","AAICastAlba.png","AAICastAlba2.png","AAICastAmano.png","AAICastBadd.png","AAICastBuddy.png","AAICastButz.png","AAICastByrne.png","AAICastCammy.png","AAICastDeacon.png","AAICastDeid.png","AAICastFranziska.png","AAICastFranziska2.png","AAICastGumshoe.png","AAICastGumshoe2.png","AAICastHuang.png","AAICastJudge.png","AAICastKay.png","AAICastKay2.png","AAICastLance.png","AAICastLang.png","AAICastMack.png","AAICastMaggey.png","AAICastManfred.png","AAICastManny.png","AAICastNou.png","AAICastPalaeno.png","AAICastPaups.png","AAICastPortsman.png","AAICastRhoda.png","AAICastShihna.png","AAICastSkye.png","AAICastYew.png","AAICastZinc.png","AAIFIRE.png","AAIad.png","AAIad2.png","AAIad3.png","AAIarrow.png","AAIbadge.png","AAIbadger.png","AAIbadger2.png","AAIbadger3.png","AAIbadger4.png","AAIbag.png","AAIballoon.png","AAIbody.png","AAIbody2.png","AAIbody3.png","AAIbody4.png","AAIbody5.png","AAIbook.png","AAIbook2.png","AAIbook3.png","AAIbook4.png","AAIboxes.png","AAIbusinesscard.png","AAIbusinesscard2.png","AAIcar.png","AAIcargo.png","AAIcart.png","AAIchange.png","AAIclip.png","AAIcravat.png","AAIdecoration.png","AAIdoor.png","AAIfile.png","AAIfile2.png","AAIfile3.png","AAIflowers.png","AAIfountain.png","AAIfountain2.png","AAIgift.png","AAIguitarpick.png","AAIgun.png","AAIgun2.png","AAIgun3.png","AAIhandprint.png","AAIhat.png","AAIhoop.png","AAIink.png","AAIkey.png","AAIkey2.png","AAIkey3.png","AAIkey4.png","AAIkey5.png","AAIknife.png","AAIknife2.png","AAIknife3.png","AAIknife4.png","AAIknife5.png","AAIlantern.png","AAIlittlethief.png","AAIluggage.png","AAImoney.png","AAInote.png","AAInote2.png","AAInote3.png","AAInote4.png","AAInote5.png","AAInote6.png","AAInote7.png","AAInote8.png","AAInote9.png","AAInote10.png","AAInote11.png","AAInote12.png","AAInote13.png","AAInote14.png","AAInote15.png","AAInote16.png","AAInote17.png","AAIpen.png","AAIpendant.png","AAIpendant2.png","AAIperfume.png","AAIperfume2.png","AAIphone.png","AAIphone2.png","AAIphone3.png","AAIphoto.png","AAIphoto2.png","AAIphoto3.png","AAIphoto4.png","AAIplates.png","AAIquercuswound.png","AAIreceipt.png","AAIsafe.png","AAIsafe2.png","AAIsciencekit.png","AAIshards.png","AAIshards2.png","AAIshards3.png","AAIshears.png","AAIshirt.png","AAIsnack.png","AAIspear.png","AAIspill.png","AAIstatue.png","AAIstatue2.png","AAIstatue3.png","AAIstatue4.png","AAIsuspect.png","AAIsword.png","AAIsword2.png","AAItape.png","AAItonosamanju.png","AAItonosamanju2.png","AAItonosamanju3.png","AAIvideo.png","AAIwakasaman.png","AAIwallet.png","AAIwire.png","AATHATCARD.png","AAaffidavit.png","AAairtube.png","AAautopsy.png","AAbluebadger.png","AAbook.png","AAbook2.png","AAbook3.png","AAbullet.png","AAbullet2.png","AAcamera.png","AAcamera2.png","AAcards.png","AAclip.png","AAclip2.png","AAclip3.png","AAclip4.png","AAclip5.png","AAdata.png","AAdata2.png","AAdata3.png","AAdata4.png","AAenvelope.png","AAevidencelaw.png","AAfingerprintpowder.png","AAfirecracker.png","AAfishingpole.png","AAflyer.png","AAglassshards.png","AAglove.png","AAgun.png","AAhandprint.png","AAidcard.png","AAkey.png","AAkeycard.png","AAknife1.png","AAkoptrophy.png","AAleather.png","AAlocker.png","AAlocker2.png","AAlocker3.png","AAluminol.png","AAluminol2.png","AAlunch.png","AAlunch2.png","AAlunch3.png","AAmagatama.png","AAmagatama2.png","AAmayanote.png","AAmayoinote.png","AAmetaldetector.png","AAmissile.png","AAmissile2.png","AAmissle2.png","AAmrmonkey.png","AAnote.png","AAnote2.png","AAnote3.png","AAnote4.png","AAparkingticket.png","AApassport.png","AApassport2.png","AAphone.png","AAphone2.png","AAphone3.png","AAphone4.png","AAphoto.png","AAphoto2.png","AAphoto3.png","AAphoto4.png","AAphoto5.png","AAphoto6.png","AAphoto7.png","AAphoto8.png","AAphoto9.png","AAphoto10.png","AAphoto11.png","AApills.png","AApills2.png","AAplate.png","AAplate2.png","AApolly.png","AAprint.png","AAprint2.png","AAprint3.png","AAprint4.png","AAprint5.png","AAprint6.png","AAprint7.png","AAprint8.png","AApsychelock.png","AAsafe.png","AAscarf.png","AAscrewdriver.png","AAscript.png","AAscript2.png","AAshoe.png","AAshoe2.png","AAspear.png","AAstudiovan.png","AAswitchblade.png","AAswitchblade2.png","AAswitchblade3.png","AAthinker.png","AAvase.png","AAvase2.png","AAvase3.png","AAvase4.png","AAvase5.png","AAvideo.png","AAvideo2.png","AAwallet.png","AAwiretap.png","AJCastAlita.png","AJCastApollo.png","AJCastDaryan.jpg","AJCastDaryan.png","AJCastDrew.png","AJCastEldoon.png","AJCastEma.png","AJCastKlavier.png","AJCastKlavier2.png","AJCastKristoph.png","AJCastLamiroir.png","AJCastLeTouse.png","AJCastMachi.png","AJCastMagnifi.png","AJCastMeraktis.png","AJCastOlga.png","AJCastOlga2.png","AJCastPayne.png","AJCastPhoenix.png","AJCastPlum.png","AJCastShadi.png","AJCastSpark.png","AJCastStickler.png","AJCastThalassa.png","AJCastTrucy.gif","AJCastTrucy.png","AJCastValant.png","AJCastValant2.png","AJCastVera.png","AJCastWinfred.png","AJCastWocky.png","AJCastZak.png","AJad.png","AJad2.png","AJad3.png","AJad4.png","AJad5.png","AJautopsy.png","AJbadge.png","AJbook.png","AJbottle.png","AJbowl.png","AJbox.png","AJbracelet.png","AJbrooch.png","AJbullet.png","AJburntstuff.png","AJbusinesscard.png","AJbusinesscard2.png","AJbusinesscard3.png","AJbusinesscard4.png","AJbusinesscard5.png","AJbusinesscard6.png","AJbutton.png","AJcard.png","AJcard2.png","AJcard3.png","AJcard4.png","AJcard5.png","AJcart.png","AJclip.png","AJclip2.png","AJclip3.png","AJcocoon.png","AJdata1.png","AJdata2.png","AJdata3.png","AJdevice.png","AJdevice2.png","AJdevice3.png","AJearpiece.png","AJfingerprintpowder.png","AJframe.png","AJgoldsnackoo.png","AJguitar.png","AJgun.png","AJgun2.png","AJgun3.png","AJiv.png","AJiv2.png","AJkey.png","AJknife.png","AJlamp.png","AJlocket.png","AJluminol.png","AJmagatama.png","AJmap.png","AJmap2.png","AJmap3.png","AJmap4.png","AJmirror.png","AJmixer.png","AJmrhat.png","AJmug.png","AJnailpolish.png","AJnote.png","AJnote2.png","AJnote3.png","AJnote4.png","AJnote5.png","AJnote6.png","AJnote7.png","AJnote8.png","AJnote9.png","AJnote10.png","AJnote11.png","AJnote12.png","AJnote13.png","AJnote14.png","AJnote15.png","AJnote16.png","AJnote17.png","AJnote18.png","AJnote19.png","AJnote","AJpainting.png","AJpainting2.png","AJpainting3.png","AJpainting4.png","AJpanties.png","AJpanties2.png","AJpanties3.png","AJphone.png","AJphone2.png","AJphoto.png","AJphoto2.png","AJphoto3.png","AJphoto4.png","AJphoto5.png","AJphoto6.png","AJphoto7.png","AJphoto8.png","AJpoisonspray.png","AJsciencekit.png","AJshoe.png","AJshoe2.png","AJshoe3.png","AJsnack.png","AJsnack2.png","AJsnack3.png","AJsnackoos.png","AJstamp.png","AJsyringe.png","AJticket.png","AJticket2.png","AJticket3.png","AJvideo.png","AJxraymachine.png","Compin.png","Credit.png","CustomEvidence1.png","CustomEvidence2.png","CustomEvidence3.png","CustomEvidence4.png","CustomEvidence5.png","CustomEvidence6.png","CustomEvidence7.png","CustomEvidence8.png","CustomEvidence9.png","CustomEvidence10.png","CustomEvidence11.png","CustomEvidence12.png","CustomEvidence13.png","CustomEvidence14.png","CustomEvidence15.png","CustomEvidence16.png","CustomEvidence17.png","CustomEvidence18.png","CustomEvidence19.png","CustomEvidence","DDAutopsy.png","DDBadge.png","DDCaseCandice.png","DDCastApollo.png","DDCastApollo2.png","DDCastApollo3.png","DDCastAthena.png","DDCastAura.png","DDCastBlackquill.png","DDCastCandice.png","DDCastClay.png","DDCastClonco.png","DDCastClonco2.png","DDCastCourte.png","DDCastCrab.png","DDCastDamien.png","DDCastFilch.png","DDCastFulbright.png","DDCastJinxie.png","DDCastJuniper.png","DDCastJuniper2.png","DDCastKlavier.png","DDCastLBelle.png","DDCastLBelle2.png","DDCastMeans.png","DDCastMetis.png","DDCastMiles.png","DDCastNineTails.png","DDCastNorma.png","DDCastOConnor.png","DDCastOrla.png","DDCastPayne.png","DDCastPearl.png","DDCastPhoenix.png","DDCastRex.png","DDCastRimes.png","DDCastRobin.png","DDCastRobin2.png","DDCastSasha.png","DDCastSasha2.png","DDCastSasha3.png","DDCastScuttlebutt.png","DDCastShipley.png","DDCastSniper.png","DDCastSniper2.png","DDCastStarbuck.png","DDCastSummers.png","DDCastTonate.png","DDCastTrucy.png","DDCastYuri.png","DDSTEPladder.png","DDScrewdriver.png","DDStatueStands.png","DDarrow.png","DDbadge2.png","DDbag.png","DDball.png","DDbed.png","DDbomb.png","DDbomb2.png","DDbomb3.png","DDbomb4.png","DDbook.png","DDbook2.png","DDbook3.png","DDbook4.png","DDbook5.png","DDbowl.png","DDbox.png","DDbox2.png","DDbox3.png","DDbox4.png","DDbracelet.png","DDbullet.png","DDbullet2.png","DDbullethole.png","DDcalendar.png","DDcamera.png","DDcamera2.png","DDcamera3.png","DDcart.png","DDcd.png","DDcharm.png","DDclip.png","DDclip2.png","DDclip3.png","DDcloth.png","DDcoin.png","DDcoin2.png","DDcomputer.png","DDcostume.png","DDcostume2.png","DDcostumes.png","DDdata.png","DDdata2.png","DDdata3.png","DDdetonator.png","DDdoor.png","DDdoor2.png","DDdoor3.png","DDdye.png","DDearring.png","DDemblem.png","DDenvelope.png","DDfingerprint.png","DDfingerprintpowder.png","DDfish.png","DDflower.png","DDfood.png","DDfood2.png","DDgun.png","DDhair.png","DDhairspray.png","DDhandprint.png","DDhat.png","DDheadphones.png","DDkey.png","DDkey2.png","DDkey3.png","DDkeycard.png","DDkeycard2.png","DDkeycard3.png","DDkeycard4.png","DDkeycard5.png","DDkeycard6.png","DDkeycard7.png","DDknife.png","DDladder.png","DDladder2.png","DDlighter.png","DDluminol.png","DDmagatama.png","DDmagatama2.png","DDmap.png","DDmap2.png","DDmap3.png","DDmap4.png","DDmap5.png","DDmap6.png","DDmap7.png","DDmap8.png","DDmap9.png","DDmap10.png","DDmap11.png","DDmap12.png","DDmask.png","DDmedicine.png","DDmedicine2.png","DDmedicine3.png","DDnote.png","DDnote2.png","DDnote4.png","DDnote5.png","DDnote6.png","DDnote7.png","DDnote8.png","DDnote9.png","DDnote10.png","DDnote16.png","DDpenguin.png","DDphone.png","DDphone2.png","DDphoto.png","DDphoto2.png","DDphoto3.png","DDphoto4.png","DDphoto5.png","DDphoto6.png","DDphoto7.png","DDphoto10.png","DDphoto11.png","DDphoto12.png","DDphoto13.png","DDphoto14.png","DDphoto15.png","DDplate.png","DDposter.png","DDposter2.png","DDposter3.png","DDpuppet.png","DDrecorder.png","DDscienceglasses.png","DDscroll.png","DDshard.png","DDshard2.png","DDshard3.png","DDshard4.png","DDshard5.png","DDshard6.png","DDshard7.png","DDshoe.png","DDskull.png","DDstaff.png","DDstatue.png","DDstatue2.png","DDstatue3.png","DDstatue4.png","DDstatue5.png","DDstatue6.png","DDstatue7.png","DDstatue8.png","DDstatue9.png","DDsurgery.png","DDsuspect.png","DDsword.png","DDsword2.png","DDtail.png","DDtank.png","DDtank2.png","DDvideo.png","DDwhistle.png","DDwidget.png","DGSCastAuchi.png","DGSCastBarok.png","DGSCastBeppo.png","DGSCastCrogrey.png","DGSCastDemiglaski.png","DGSCastFairplay.png","DGSCastGina.png","DGSCastGreen.png","DGSCastGregson.png","DGSCastHolmes.png","DGSCastHosonaga.png","DGSCastHosonaga2.png","DGSCastHutch.png","DGSCastJWatson.png","DGSCastJezail.png","DGSCastJoan.png","DGSCastJohn.png","DGSCastKazuma.png","DGSCastLadyfirst.png","DGSCastMegundal.png","DGSCastMilverton.png","DGSCastNatsume.png","DGSCastNemmy.png","DGSCastNikomina.png","DGSCastPat.png","DGSCastRola.png","DGSCastRoylott.png","DGSCastRyuunosuke.png","DGSCastSanmon.png","DGSCastStroganov.png","DGSCastSusato.png","DGSCastSuspect.png","DGSCastTaizou.png","DGSCastTully.png","DGSCastVortex.png","DGSCastWagahai.png","DGSCastWatson.png","DGSCastYuujin.png","DGSbadge.png","DGSbag.png","DGSbag2.png","DGSbell.png","DGSbell2.png","DGSbell3.png","DGSbook.png","DGSbook2.png","DGSbook3.png","DGSbook4.png","DGSbook5.png","DGSbook6.png","DGSbook7.png","DGSbook8.png","DGSbook9.png","DGSbook10.png","DGSbullet.png","DGScamera.png","DGScane.png","DGScart.png","DGSclip.png","DGSclip2.png","DGSclip3.png","DGSclip4.png","DGScoin.png","DGSdevice.png","DGSflower.png","DGSfood.png","DGSfood2.png","DGSfood3.png","DGSfood4.png","DGSgloves.png","DGSgloves2.png","DGSgun.png","DGSgun2.png","DGSgun3.png","DGSherbaltea.png","DGSknife.png","DGSknife2.png","DGSknife3.png","DGSknife4.png","DGSmap.png","DGSmap2.png","DGSmap3.png","DGSmusicbox.png","DGSmusicbox2.png","DGSmusicbox3.png","DGSmusicdisk.png","DGSmusicdisk2.png","DGSmusicdisk3.png","DGSmusicdisk4.png","DGSmusicdisk15.png","DGSnote.png","DGSnote2.png","DGSnote3.png","DGSnote4.png","DGSnote5.png","DGSnote6.png","DGSnote7.png","DGSnote8.png","DGSnote9.png","DGSnote10.png","DGSnote11.png","DGSnote12.png","DGSnote13.png","DGSnote14.png","DGSnote15.png","DGSnote16.png","DGSnote17.png","DGSnote18.png","DGSnote19.png","DGSnote","DGSnote21.png","DGSphoto.png","DGSphoto2.png","DGSphoto3.png","DGSphoto4.png","DGSphoto5.png","DGSphoto6.png","DGSphoto7.png","DGSphoto8.png","DGSphoto9.png","DGSphoto10.png","DGSphoto11.png","DGSphoto12.png","DGSphoto13.png","DGSphoto14.png","DGSphoto15.png","DGSphoto16.png","DGSphoto17.png","DGSphoto18.png","DGSphoto19.png","DGSpin.png","DGSpin2.png","DGSpipe.png","DGSpressing.png","DGSsciencekit.png","DGSshard.png","DGSstereoscope.png","DGSstereoscope2.png","DGStiara.png","DGSviola.png","DGSviola2.png","DGSwhip.png","Datapad.png","Interface.png","JFACastAcro.png","JFACastAdrian.png","JFACastAmi.png","JFACastBat.png","JFACastBen.png","JFACastCeleste.png","JFACastDeKiller.png","JFACastDustin.png","JFACastFranziska.png","JFACastGalactica.png","JFACastGrey.png","JFACastHotti.png","JFACastIni.png","JFACastJuan.png","JFACastMaggey.png","JFACastMatt.png","JFACastMimi.png","JFACastMoe.png","JFACastMorgan.png","JFACastPearl.png","JFACastRegina.png","JFACastRussel.png","JFACastShelly.png","JFACastWellington.png","JFATHATCARD.png","JFATHATCARD2.png","JFAautograph.png","JFAautograph2.png","JFAball.png","JFAball2.png","JFAbear.png","JFAbear2.png","JFAbear3.png","JFAbottle.png","JFAbox.png","JFAbox2.png","JFAbusinesscard.png","JFAbusinesscard2.png","JFAbutton.png","JFAbutton2.png","JFAbutton3.png","JFAcamera.png","JFAcard.png","JFAcard2.png","JFAclip.png","JFAclip2.png","JFAclip3.png","JFAclip4.png","JFAcoat.png","JFAfrequencydetector.png","JFAglasses.png","JFAglove.png","JFAgrapes.png","JFAguitar.png","JFAgun.png","JFAgun2.png","JFAhammond.png","JFAhat.png","JFAjuice.png","JFAkey.png","JFAknife.png","JFAknife2.png","JFAleon.png","JFAmilk.png","JFAmilk2.png","JFAmoney.png","JFAnote.png","JFAnote2.png","JFApepper.png","JFAphoto.png","JFAposter.png","JFAreceipt.png","JFAregent.png","JFAring.png","JFArobe.png","JFArobescrap.png","JFAscarf.png","JFAscreen.png","JFAshoe.png","JFAspycamera.png","JFAticket.png","JFAticket2.png","JFAtracker.png","JFAtransceiver.png","JFAtransmitter.png","JFAtrilo.png","JFAuniform.png","JFAurn1.png","JFAurn2.png","JFAvest.png","JFAwhip.png","MiscAKMS.png","MiscAsthmaPump.png","MiscBaggie.png","MiscBeach.png","MiscBlueRuby.png","MiscCandy Cane.png","MiscCandy Cane Dark.png","MiscCorkscrew.png","MiscCrowbar.png","MiscDragonPepper.png","MiscFlintlock.png","MiscGenerator.png","MiscGrapeJuice.png","MiscGreen Hut.png","MiscGrill.png","MiscHalf-Eaten Burger.png","MiscHangGlider.png","MiscLockpicks.png","MiscMapBiolab.png","MiscMapCourthouse.png","MiscMapLobby1.png","MiscMichigan J Frog.png","MiscMystery1.png","MiscMystery2.png","MiscMystery3.png","MiscOldTrain.png","MiscRaffleTickets.png","MiscSpatula.png","MiscSpecimenAlpha.png","MiscTimeCrystal.png","MiscTins.png","MiscUnknown People.png","MiscVDF.png","MiscVodka.png","MiscZombie.png","Scanner.png","SoJad.png","SoJad2.png","SoJad3.png","SoJad4.png","SoJad5.png","SoJad6.png","SoJad7.png","SoJarrow.png","SoJautopsy.png","SoJbadge.png","SoJbadge2.png","SoJblimp.png","SoJblimp2.png","SoJblood.png","SoJboiler.png","SoJbook.png","SoJbook2.png","SoJbook3.png","SoJbook4.png","SoJbook5.png","SoJbook6.png","SoJbook7.png","SoJbook8.png","SoJbook9.png","SoJbook10.png","SoJbook11.png","SoJbook12.png","SoJbook13.png","SoJbook14.png","SoJbox.png","SoJbox2.png","SoJbracelet.png","SoJbucket.png","SoJcamera.png","SoJcandelabra.png","SoJcandelabra2.png","SoJcandelabra3.png","SoJcastAhlbi.png","SoJcastAmara.png","SoJcastAndistan'dhin.png","SoJcastApollo.png","SoJcastArchie.png","SoJcastArmie.png","SoJcastAthena.png","SoJcastAtishon.png","SoJcastBeh'leeb.png","SoJcastBetty.png","SoJcastBlackquill.png","SoJcastBonny.png","SoJcastBucky.png","SoJcastButz.png","SoJcastDatz.png","SoJcastDatz2.png","SoJcastDhurke.png","SoJcastDumas.png","SoJcastEllen.png","SoJcastEma.png","SoJcastGa'ran.png","SoJcastGeiru.png","SoJcastInga.png","SoJcastMaya.png","SoJcastMiles.png","SoJcastNahyuta.png","SoJcastNayna.png","SoJcastPayne.png","SoJcastPearl.png","SoJcastPhoenix.png","SoJcastPierce.png","SoJcastPuhray.png","SoJcastRayfa.png","SoJcastRetinz.png","SoJcastReus.png","SoJcastRohl.png","SoJcastSelena.png","SoJcastSergeant.png","SoJcastSorin.png","SoJcastTahrust.png","SoJcastTaifu.png","SoJcastTrucy.png","SoJcastUendo.png","SoJcd.png","SoJcd2.png","SoJcharm.png","SoJclip.png","SoJclip2.png","SoJcog.png","SoJcontract.png","SoJdog.png","SoJflag.png","SoJflower.png","SoJfood1.png","SoJfood2.png","SoJfood3.png","SoJgem.png","SoJglasses.png","SoJgoop.png","SoJhat.png","SoJhelicopter.png","SoJhorse.png","SoJhorse2.png","SoJkey.png","SoJkey2.png","SoJkey3.png","SoJkey4.png","SoJkeycard.png","SoJkeycharm.png","SoJlantern.png","SoJlantern2.png","SoJluminol.png","SoJmagatama.png","SoJmagatama2.png","SoJmagatama3.png","SoJmap.png","SoJmap2.png","SoJmap3.png","SoJmap4.png","SoJmap5.png","SoJmap6.png","SoJmap7.png","SoJmrhat.png","SoJnote.png","SoJnote2.png","SoJnote3.png","SoJnote4.png","SoJnote5.png","SoJnote6.png","SoJnote7.png","SoJnote8.png","SoJnote9.png","SoJnote10.png","SoJnote11.png","SoJnote12.png","SoJnote13.png","SoJnote14.png","SoJnote15.png","SoJnote16.png","SoJnote17.png","SoJorb.png","SoJpassport.png","SoJpendant.png","SoJphone.png","SoJphoto.png","SoJphoto2.png","SoJphoto3.png","SoJphoto4.png","SoJphoto5.png","SoJphoto6.png","SoJphoto7.png","SoJphoto8.png","SoJphoto9.png","SoJphoto10.png","SoJphoto11.png","SoJphoto12.png","SoJphoto13.png","SoJphoto14.png","SoJphoto15.png","SoJphoto16.png","SoJphoto17.png","SoJphoto18.png","SoJphoto19.png","SoJphoto","SoJphoto21.png","SoJphoto22.png","SoJphoto23.png","SoJphoto24.png","SoJphoto25.png","SoJphoto26.png","SoJphoto27.png","SoJphoto28.png","SoJprintpowder.png","SoJraincoat.png","SoJscissorlift.png","SoJscroll.png","SoJscroll2.png","SoJsnackoo.png","SoJstand.png","SoJstatue.png","SoJsuspect.png","SoJsword.png","SoJsword2.png","SoJsyringe.png","SoJtape1.png","SoJtext.png","SoJunknown.png","SoJurn.png","SoJusb.png","SoJwallet.png","SoJwidget.png","TTCastAdrian.png","TTCastArmstrong.png","TTCastAtmey.png","TTCastBikini.png","TTCastBruto.png","TTCastBullard.png","TTCastDahlia.png","TTCastDeMasque.png","TTCastDesiree.png","TTCastDiego.png","TTCastElg.png","TTCastElise.png","TTCastFawles.png","TTCastGodot.png","TTCastGrossberg.png","TTCastGumshoe.png","TTCastIris.png","TTCastIris2.png","TTCastKudo.png","TTCastLisa.png","TTCastMaggey.png","TTCastMiles.png","TTCastRon.png","TTCastSwallow.png","TTCastTigre.png","TTCastValerie.png","TTCastViola.png","TTad.png","TTad2.png","TTapron.png","TTbadge.png","TTbag.png","TTblood1.png","TTblood2.png","TTbottle1.png","TTbottle2.png","TTbox.png","TTbox2.png","TTbutton.png","TTcalendar.png","TTcamera.png","TTcard.png","TTcd.png","TTcd2.png","TTclip.png","TTclip2.png","TTclip3.png","TTclip4.png","TTclip5.png","TTcoldkiller.png","TTcoldkiller2.png","TTcup.png","TTdata.png","TTdata2.png","TTdata3.png","TTdata4.png","TTdrawing.png","TTemblem.png","TTemployee.png","TTfood1.png","TTfood2.png","TThood.png","TTjewel.png","TTjewel2.png","TTkeycard.png","TTknife.png","TTlantern.png","TTlantern2.png","TTmagazine.png","TTmagazine2.png","TTmatchbook.png","TTmatchbook2.png","TTmedicine.png","TTmedicine2.png","TTmoped.png","TTnecklace.png","TTnote.png","TTnote2.png","TTnote3.png","TTnote4.png","TTnote5.png","TTnote6.png","TTnote7.png","TTperfume.png","TTphotoold.png","TTsapphire.png","TTscarf.png","TTschichishito.png","TTschichishito2.png","TTschichishito3.png","TTscroll.png","TTscroll2.png","TTseal.png","TTseal2.png","TTstaff.png","TTstaff2.png","TTstaff3.png","TTstain.png","TTstatue.png","TTticket.png","TTticket2.png","TTumbrella.png","TTvase.png","TTvase2.png","TTvase3.png","TTvase4.png","TTwallet.png","TTwatch.png","Vivaster.png","empty.png","lawyerbadge.png"]},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.default=["1st server","999.1","999","999Apartment","999CaptainsQuarters","999Cargo","999Casino","999Cdeck","999CentralStairs","999Chapel","999Chart","999Confinement","999DoorsA","999DoorsB","999Hospital","999Kitchen","999Library","999Operating","999Shower","999Steam","999Steeldoor","999Study","999Torture","9991stClassCabinA","9991stClassCabinB","9992ndClassCabin","AA - Edgewort's Office","AA - Gantsroom","AA - Gatewater room","AA - Gourd Lake","AA - Gourd Lake Entrance","AA - Hotel Lobby","AA - Hotticlinic","AA - Kurain","AA - Parkinglot","AA - Police Deparment","AA - Police Station","AA - Records Room","AA - Sc13","AA - Wright's Office","AABluecorp","AACourt","AACourtAnime","AACourtChristmasDecorations","AACourtChristmasLights","AACourtHD","AADefendantLobby","AADefendantLobbyHD","AADetentionCenter","AAEdgeworthOffice","AAGantOffice","AAGatewaterHotel","AAGlobalStudiosEast","AAGlobalStudiosWest","AAGourdLake","AAGrossbergOffice","AAI2Circus","AAI2City","AAI2GourdLake","AAI2LogicChess","AAI2MuseumPast","AAI2MuseumPresent","AAI2PIC","AAI2Prison","AAICohdopianEmbassy","AAICourt","AAICourtFlipped","AAIEdgeworthOffice","AAIGatewaterLandStage","AAIGatewaterLandWildWest","AAIiFlyAirlines","AALobby","AAParkingLot","AAPoliceStation","AATrainStation","AAWrightOffice","AJBorschtBowlClub","AJCourt","AJCourtBirthday","AJCourtHalloween","AJCourtNight","AJCourtTV","AJDefendantLobby","AJDetentionCenter","AJDrewStudio","AJHottiClinic","AJKlavierOffice","AJKristophCell","AJLobby","AJMeraktisClinic","AJPeoplePark","AJSunshineColiseum","AJWrightOffice","Ace","AcroRoomJFA","AirportJFA","AlbaOfficeAAI","Anime","Arcade","AtmeyOfficeTT","Atrium (SG)","AutumnForest","BB - Flowerfield","BB - Market","BB - Street","BandoLandAAI","Basement","Battlegrounds","BerryBigCircusJFA","Blackout","BlueScreensTT","BluecorpAA","BridgeNest","Brig","Building","CC1","CC2","CC3","CC4","CC5","CC6","CC7","CC8","CC9","CC10","CC11","CC12","CO - Big door","CO - Finalroom","CO - Meetingroom","CO - Whitedoor","CO - Whitelobby","CO - Whitelowerfloor","CO - White room","CP","CPRP2 Chap1","CPRP2 Chap2and3","CPRP2 Chap4","CPRP2 Chap5","CPRP Chap1","CPRP Chap2","CPRP Chap3","CPRP Chap4","CPRP Chap5","CVStMystere","Cafe","CafeCourt","CaffeeCase","Cal","CargoHoldAAI","Casino","CasinoCourt","Cathedral (SG)","Christmas","Christmas Courtroom","CinemaFamousi","Classroom","Co - Lobby 1","Co - Lobby 2","CochenOfficeAAI","ColosseumFerox","Control Room","Control Room Interior","CountyCourt","CourtroomAA","CourtroomAAHD","CourtroomAAI","CourtroomAJ","CourtroomAJNight","CourtroomAnime","CourtroomCounty","CourtroomDD","CourtroomEnglish","CourtroomNew","CourtroomRuined","CourtroomThemis","CourtroomTouhou","CourtroomWitch","CruiseCourt","CustomEight","CustomEleven","CustomFifteen","CustomFive","CustomFour","CustomFourteen","CustomNine","CustomOne","CustomSeven","CustomSix","CustomTen","CustomThirteen","CustomThree","CustomTwelve","CustomTwo","DC","DDCourt","DDCourtGray","DDCourtRuined","DDCourtRuinedInvestigation","DDCourtThemis","DDDefendantLobby","DDGyaxa","DDLobby","DDNinetailsVale","DDShipshapeAquarium","DDThemisAcademy","DFreightTrain","DGS-ENG","DGS-JAP","DGS","DGSCourtJapanese","DGSCourtOldBailey","DGSCourtOldBaileyJury","DGSDefendantLobbyJapanese","DGSDefendantLobbyOldBailey","DGSEnglishCourt","DGSJapanCourt","DGSLondon","DGSenglishcourt","DRAE-Area1","DRAE-Area2","DRClassTrial","DRRP","Dark Cave","Darkness","Datrone Heart","Datrone HeartHQ","DeLiteHouseTT","Despair vs. Hope","DetentionCenterAAI2","DimensionalGate","DogenCellAAI2","DualDestinies","Dungeon Courtroom","EdgeworthOfficeAA","EdgeworthOfficeAAI","EmbassyAAI","Endless Courtroom","EngardeManorJFA","EnglishCourt","Errors","Errors2","FECastle","FECave","FEFort","FEPlain","FETavern","Factory","FieldFortune","FilmSetAAI2","Flowerfield","ForensicCourt","Forest","GS4Night","GantOfficeAA","GetwaterHotelJFA","GetwaterStageJFA","GlobalStudiosIndoorsAA","GlobalStudiosOutdoorsAA","GourdLakeAA","GrandChokmah","GrandStadium","Graveyard","GreatWitchtrialCourt","GrossbergOfficeAA","HD","HQFarm","HQHalloweenTown","HQHolodeck","HQShrine","HQTown","HQVolcanoCherry","HallOfFame","HarborTown","HarvestFestival","HazakuraTemple1TT","HazakuraTemple2TT","Headquarters","Headquarters 2","Hell Correspondence","Hospital","HotelRoomAA","HottiClinicJFA","Innsmouth","InsidePlaneAAI2","Interiors (Day)","Interiors (Night)","JFAAirport","JFABerryBigCircusEast","JFABerryBigCircusWest","JFAGatewaterHotel","JFAHottiClinic","JFAKurainVillage","JFAMattHouse","JapaneseCourt","Kamurocho (Day)","Kamurocho (Night)","Keterburg","Khura'in","Khurain","KokonoeLab","KurainCourt","KurainVillageJFA","LBCastle","LBMisc","LBScotlandYard","Lab 8","Lentomain","Library","LogicChessAAI2","MI - Ashleys Shack","MLP - Apple barn","MLP - CMC Clubhouse","MLP - CMC Clubhouse inside","MLP - Canterlot Castle galaroom","MLP - Canterlot Hallway","MLP - Canterlot Library2","MLP - Canterlot Town","MLP - Canterlot alley","MLP - Canterlot library","MLP - Carousel Boutique","MLP - Clearing","MLP - Curio Shop","MLP - Everfree Forest","MLP - Everfree Forest entrance","MLP - Fluttershy's cottage","MLP - Hospital Room","MLP - Hotelroom","MLP - Library 2F","MLP - Library mainfloor","MLP - Old Castle","MLP - Orchard","MLP - PV Hospital","MLP - PV Street","MLP - Ponyville","MLP - Shining's apartment","MLP - Sugarcube Corner","MLP - Twilight's Lab","MM - Castle","MM - Madokas house","MM - School yard","MM - Street","MM - Street2","MM - classroom","MM - dark hallway","MM - rooftop","MM - room whit Kyubey","MM - school hallway","MM - staircase","MMA-Bedrooms1","MMA-Floor 1","MS - Cathedral","MS - Zakum's Tree","Mansion","MansionAAI2","MansionHQ","Maplecrest - Nightmare","Maplecrest","Market","Mayonaka","MechHangar","Medici Tower","Military Base Exterior","MoeRoomJFA","MuseumAAI2","MuseumTT","Music","NewCourt","New Meridian","Ninetailsvale","Nordon Plains","Nordon Plains Night","OCArcade","OCBebop","OCCourtCafe","OCCourtCounty","OCCourtCruise","OCCourtEndless","OCCourtFinalDestination","OCCourtInverted","OCCourtPirateShip","OCCourtSky","OCCourtSpace","OCCourtSpaceShip","OCCourtTouhou","OCCourtZetta","OCDungeon","OCHospital","OCRoad","OCTownPirate","OCTownShanty","OCWhiteRoom","OfficeHouseHQ","OfficeNightAA","Osaka (Night)","Osaka","OutsidePlaneAAI2","P4UBasement","P4ULab","P4Ubaseball","P4Ubeach","P4Ubuilding","P4Uconcert","P4Ugarden","P4Ugraveyard","P4Uhell","P4Ujail","P4Umisc","P4Unight","P4Uoffices","P4Urailway","P4Urestaurants","P4Urooms","P4Uruins","P4Uschool","P4Ustage1","P4Ustage2","P4Ustation","P4Ustore","P4Utent","P4Utransport","P4Utv","P4Uvelvetroom","PICAAI2","PLvsAAAlchemistHouse","PLvsAABellTower","PLvsAACastle","PLvsAACourtEnglish","PLvsAACourtLabyrinthia","PLvsAACourthouse","PLvsAADefendantLobbyEnglish","PLvsAADefendantLobbyLabyrinthia","PLvsAAEclaireBakery","PLvsAAForest","PLvsAAGreatArchive","PLvsAALabyrinthiaInner","PLvsAALabyrinthiaOuter","PLvsAALondon","PLvsAARougeTavern","PLvsAARuins","PLvsAAStorytellerTower","PLvsAAWagon","PLvsAAWorkshop","PMMMRP","PMMMWitch","ParkingLotAA","PeonyCastle","Persona Afternoon","Persona DH","Persona Morning","Persona Night","PersonaRP","PhoenixOfficeAA","PirateShip","PlaneAAI","PlaneLoungeAAI","PlaneLoungeLandAAI","PlatPark","PlatRemnant","PlatunaArea1","PlatunaArea1HQ","PlatunaArea2","PlatunaArea2HQ","PlatunaMain","PlatunamainHQ","PrecinctAA","PrisonAAI2","PrisonCourtyardAAI2","RG - 104","RG - A-East","RG - AMX","RG - Bus Terminal","RG - Cadoi City","RG - Concert","RG - Dogenzaka","RG - God Pad","RG - Miyashita Underpass","RG - Station Underpass","RG - Trail","RG - Udagawa","RaysDeLite","Retreat","RetreatHQ","RiverVista","Road","Role Play","Ronpa Mansion Area 5","Ronpa Mansion Day","Ronpa Mansion Day2","Ronpa Mansion Day3","Ronpa Mansion Day4","Ronpa Mansion Night","Ronpa Mansion Night2","Ronpa Mansion Night3","Ronpa Mansion Night4","Ronpa mansion Haunted","Ronpers Express","RooftopAAI2","RuinedCastle","RuinedCourt","Ruins Entrance","SDR2 ISLAND","SDR2 ISLAND2","SDR2 ISLAND2 NIGHT","SDR2 ISLAND3","SDR2 ISLAND NIGHT","SI - Bedroom","SI - Class(sunset)","SI - Class","SI - Council1","SI - Council2","SI - Council3","SI - Gym","SI - Gym2","SI - Hall","SI - Hall2","SI - Lockers","SI - Nurse","SI - Office","SI - Pink","SI - Roof","SI - Roof2","SI - School","Seance","SecretRoomsJFA","SecurityCompanyTT","ShipAAI2","SkialForest","Sky","SkyDeck","SoJCourt","SoJDefendantLobby","Somina Castle","Somina Castle Night","SpaceCourt","SpaceCourtBlue","SpaceCourtGreen","SpaceCourtNormal","SpaceCourtOrange","SpaceCourtRainbow","SpaceCourtRed","SpaceCourtYellow","SpacePort","Spaceship","StageAAI","StageDisassembledAAI","SteamBar","SteamGarden","SteamGovt","SteamSquare","SteamStreet","Street","SummerFestival","SummerFestivalEvening","TARDIS","TEOS Lab","TTAtmeyOffice","TTBlueScreensInc","TTDemasqueHideout","TTHazakuraTemple","TTHazakuraTempleInner","TTKBSecurity","TTLordlyTailor","TTTenderLender","TTTresBien","TenderLenderTT","Themis","Titania","TitaniaValley","Togami Mansion","TouhouCourt","Tower","Town","Town Night","Tr0LLc0urt","TrainstationAA","TresBienTT","TrollCourt","Twotorial Village","Twotorial Village Night","VC 1","VLR","VLR2.2","VLR2.3","VLR2","VLR3","VitaminSquareTT","WEN","WaitingRoomAAI","WestAAI","WinterPalaceAAI2","WitchTrialCourt","WitchtrialCourtHQ","Witchwood","WorldEmulator","Wreckage (SG)","Wrightagency","Xmas","Zetta","animation","apollojustice","background","basement","birthday","blackout","chess","chessw1","chessw2","chessw3","chessw4","christmas","circus","classtrial","cofe","courthouseofgods","cruise","cruise court","custom","custom1","custom2","custom3","custom4","custom5","custom6","custom7","custom8","custom9","custom10","daimoncourt","default - Kopie","default","default_christmas","defendantlobby","defendantlobbyapollo","detentioncenter","doppler","dr1stfloor","dr1stfloordorms","dr1stfloorhalls","dr2ndfloor","dr3rdfloor","druq1stfloordorms","druq2ndfloordorms","dualdestinies","dualdestiniesOG","dungeon","endless","englishcourt","forest","gs4","gs4night","gs5","hd","inn","investigationbando","investigationsembassylobby","investigationsgourdlake","investigationsmilesoffice","investigationsplaneair","investigationsroyalcourt","investigationstvroom","investigationswestern","investigationswitchtown","island 1(uranus zone)","lcourt","legacy","lobbyDGS-ENG","lobbyDGS-JAP","lobbyPLvsAA-ENG","lobbyPLvsAA-LAB","lobbySOJ","magatama","magatama1","magatama2","magatama3","magatama4","magatama5","marblefade","matrix","matrixall","matrixangry","matrixangrysad","matrixangrysurprised","matrixhappy","matrixhappyangry","matrixhappysad","matrixhappysurprised","matrixsad","matrixsadsurprised","matrixsurprise","mlp","newcourt","night (no lights)","plvsaa","policestation","prisonvestigation","sdr2classtrial","sky","sshope2ndfloorday(incident)","sshope2ndfloorday","sshope2ndfloornight(incident)","sshope2ndfloornight","sshopeday(incident)","sshopeday","sshopenight(incident)","sshopenight","thief","thiefbash","thiefpoint","thiefpoisoning","thiefprints","thiefstab","thiefsteal","turnaboutstorm - Kopie","turnaboutstorm","vocalcourt","witchtrialcourt"]},function(e,n,t){"use strict";Object.defineProperty(n,"__esModule",{value:!0});var o=function(){function e(e,n){for(var t=0;t").replace(/\[(\/?)b\]/g,"<$1b>").replace(/\[(\/?)i\]/g,"<$1i>").replace(/\[(\/?)s\]/g,"<$1del>").replace(/\[(\/?)u\]/g,"<$1u>").replace(/\[(\/?)sub\]/g,"<$1sub>").replace(/\[(\/?)sup\]/g,"<$1sup>").replace(/\[m=([#a-zA-Z0-9]+)\]/g,'').replace(/\[(\/?)m\]/g,"<$1m>").replace(/\[c=?([#a-zA-Z0-9]+)\]/g,'').replace(/\[\/c\]/g,"")}},{key:"handleMS",value:function(e){if(e[4]!=he.chatmsg.content){document.getElementById("client_inner_chat").innerHTML="";for(var n={character:-1,preanim:escape(e[2]),nameplate:e[3],name:e[3],speaking:"(b)"+escape(e[4]),silent:"(a)"+escape(e[4]),content:this.prepChat(e[5]),side:e[6],sound:escape(e[7]),type:e[8],snddelay:e[10],objection:e[11],evidence:e[12],flip:e[13],flash:e[14],color:e[15],isnew:!0},t=0;tn.scrollHeight-600&&(n.scrollTop=n.scrollHeight)}},{key:"handleMC",value:function(e){var n=he.music;(n.pause(),n.src=d+e[1].toLowerCase(),n.play(),e[2]>=0)?F(this.chars[e[2]].name+" changed music to "+e[1]):F("The music was changed to "+e[1])}},{key:"handleRMC",value:function(e){he.music.pause(),he.music=new Audio(this.musicList[e[1]]);var n=he.music;n.totime=e[1],n.offset=(new Date).getTime()/1e3,n.addEventListener("loadedmetadata",function(){n.currentTime+=parseFloat(n.totime+((new Date).getTime()/1e3-n.offset)).toFixed(3),n.play()},!1)}},{key:"handleCI",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Character "+e[1],this.serv.send("AN#"+(e[1]/10+1)+"#%");for(var n=2;n'}},{key:"handleEM",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Music "+e[1],this.serv.send("AM#"+(e[1]/10+1)+"#%");for(var n=document.getElementById("client_musiclist"),t=2;t .health-bar").animate({width:n+"%"},500)):(this.hp[1]=e[2],$("#client_prosecutor_hp > .health-bar").animate({width:n+"%"},500))}},{key:"handleRT",value:function(e){"testimony1"==e[1]?this.testimonyID=1:this.testimonyID=2,he.initTestimonyUpdater()}},{key:"handleZZ",value:function(e){var n=document.getElementById("client_ooclog");n.innerHTML+="$Alert: "+Ae(de(e[1]))+"\r\n",n.scrollTop>n.scrollHeight-60&&(n.scrollTop=n.scrollHeight)}},{key:"handleID",value:function(e){this.playerID=e[1]}},{key:"handlePN",value:function(e){this.serv.send("askchaa#%")}},{key:"handleSI",value:function(e){u?this.serv.send("askchar2#%"):this.serv.send("RC#%")}},{key:"handleCharsCheck",value:function(e){document.getElementById("client_chartable").innerHTML="";for(var n=void 0,t=0;t",n.appendChild(o),t%8==0&&document.getElementById("client_chartable").appendChild(n)}}},{key:"handlePV",value:function(e){this.charID=e[3],document.getElementById("client_charselect").style.display="none";var n=this.me(),t=this.emotes,o=new XMLHttpRequest;o.withCredentials=!1,document.getElementById("client_emo").innerHTML="",o.open("GET",l+"characters/"+escape(this.me().name.toLowerCase())+"/char.ini",!0),o.responseType="text",o.onload=function(e){if(200==this.status){var o=this.responseText,a=f.parse(o);n.side=a.Options.side,K(n.side);for(var s=1;s'}R(1)}},o.send()}}]),e}(),y=function(){function e(){p(this,e),this.textnow="",this.chatmsg={isnew:!1,content:"",objection:"0",sound:"",startpreanim:!1,startspeaking:!1,side:null,color:"0",snddelay:0,preanimdelay:0},this.blip=new Audio(l+"sounds/general/sfx-blipmale.wav"),this.blip.volume=.5,this.blipChannels=new Array(6);for(var n=0;n0){var n="";1==me.testimonyID?n="witnesstestimony":2==me.testimonyID&&(n="crossexamination"),new Audio(me.resources[n].sfx).play(),this.testimonyTimer=0;var t=document.getElementById("client_testimony");t.src=me.resources[n].src,t.style.display="",this.testimonyUpdater=setTimeout(function(){return e.updateTestimony()},60)}}},{key:"getAnimLength",value:function(e,n,t){var o=new XMLHttpRequest;o.open("GET",e,!0),o.responseType="arraybuffer",o.addEventListener("load",function(){var e=gify.getInfo(o.response);console.log(e.duration),n(e.duration,t)}),o.send()}},{key:"updateTestimony",value:function(){var e=this;this.testimonyTimer=this.testimonyTimer+60,1==me.testimonyID?this.testimonyTimer>=me.resources.witnesstestimony.duration?this.disposeTestimony():this.testimonyUpdater=setTimeout(function(){return e.updateTestimony()},60):2==me.testimonyID?this.testimonyTimer>=me.resources.crossexamination.duration?this.disposeTestimony():this.testimonyUpdater=setTimeout(function(){return e.updateTestimony()},60):this.disposeTestimony()}},{key:"disposeTestimony",value:function(){me.testimonyID=0,this.testimonyTimer=0,document.getElementById("client_testimony").style.display="none",clearTimeout(this.testimonyUpdater)}},{key:"updateText",value:function(){var e=this,n=document.getElementById("client_name"),t=document.getElementById("client_chat"),o=document.getElementById("client_char"),a=document.getElementById("client_evi"),s=document.getElementById("client_background"),i=document.getElementById("client_shout"),p=document.getElementById("client_inner_chat");if(1==this.chatmsg.flip?o.style.transform="scaleX(-1)":o.style.transform="scaleX(1)",this._animating&&(this.updater=setTimeout(function(){return e.updateText()},60)),this.chatmsg.isnew){s.style.backgroundColor="transparent",n.style.display="none",t.style.display="none",a.style.opacity="0",a.style.height="0%";var g={1:"holdit",2:"objection",3:"takethat"}[this.chatmsg.objection];void 0!==g?(i.src=me.resources[g].src,new Audio(l+"characters/"+this.chatmsg.name.toLowerCase()+"/"+g+".wav").play(),this.shoutTimer=850):this.shoutTimer=0,this.chatmsg.isnew=!1,this.chatmsg.startpreanim=!0}if(this.textTimer>=this.shoutTimer&&this.chatmsg.startpreanim)2==this.chatmsg.flash?(this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=l+"sounds/general/sfx-stab.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("shake",{direction:"up"})):1==this.chatmsg.flash&&(s.style.backgroundColor="white",this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=l+"sounds/general/sfx-realization.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("pulsate")),this.chatmsg.preanimdelay>0&&(i.src="misc/placeholder.gif",M(this.chatmsg.side),o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.preanim.toLowerCase()+".gif"),this.chatmsg.startpreanim=!1,this.chatmsg.startspeaking=!0;else if(this.textTimer>=this.shoutTimer+this.chatmsg.preanimdelay&&!this.chatmsg.startpreanim)if(this.chatmsg.startspeaking){this.chatmsg.evidence>0&&(a.style.backgroundImage="url('"+me.evidences[this.chatmsg.evidence-1].icon+"')","def"==this.chatmsg.side?(a.style.right="1.5em",a.style.left="initial",$("#client_evi").animate({height:"30%",opacity:1},250)):(a.style.right="initial",a.style.left="1.5em",$("#client_evi").animate({height:"30%",opacity:1},250))),n.style.display="block",n.style.fontSize=.7*n.offsetHeight+"px",n.innerHTML="

"+ce(this.chatmsg.nameplate)+"

",t.style.display="block",t.style.fontSize=.25*t.offsetHeight+"px";p.style.color={0:"#ffffff",1:"#00ff00",2:"#ff0000",3:"#ffaa00",4:"#0000ff",5:"#ffff00",6:"#aa00aa"}[this.chatmsg.color]||"#ffffff",this.chatmsg.startspeaking=!1,0==this.chatmsg.preanimdelay&&(i.src="misc/placeholder.gif",M(this.chatmsg.side)),o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.speaking.toLowerCase()+".gif",this.textnow==this.chatmsg.content&&(o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.silent.toLowerCase()+".gif",this._animating=!1,clearTimeout(this.updater))}else this.textnow!=this.chatmsg.content&&(" "!=this.chatmsg.content.charAt(this.textnow.length)&&(this.blipChannels[this.currentBlipChannel].play(),this.currentBlipChannel++,this.currentBlipChannel%=this.blipChannels.length),this.textnow=this.chatmsg.content.substring(0,this.textnow.length+1),p.innerHTML=this.textnow,this.textnow==this.chatmsg.content&&(this.textTimer=0,this._animating=!1,o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.silent.toLowerCase()+".gif",clearTimeout(this.updater)));!this.sfxplayed&&this.chatmsg.snddelay+this.shoutTimer>=this.textTimer&&(this.sfxaudio.pause(),this.sfxplayed=1,"0"!=this.chatmsg.sound&&"1"!=this.chatmsg.sound&&(this.sfxaudio.src=l+"sounds/general/"+escape(this.chatmsg.sound.toLowerCase())+".wav",this.sfxaudio.play())),this.textTimer=this.textTimer+60}}]),e}(),f=function(){function e(){p(this,e)}return o(e,null,[{key:"parse",value:function(e){var n={section:/^\s*\[\s*([^\]]*)\s*\]\s*$/,param:/^\s*([\w.\-_]+)\s*=\s*(.*?)\s*$/,comment:/^\s*;.*$/},t={},o=null;return e.split(/\r\n|\r|\n/).forEach(function(e){if(!n.comment.test(e)&&0!=e.length)if(n.param.test(e)){var a=e.match(n.param);o?t[o][a[1]]=a[2]:t[a[1]]=a[2]}else if(n.section.test(e)){var s=e.match(n.section);t[s[1]]={},o=s[1]}}),t}}]),e}();function S(e){13==e.keyCode&&(me.sendOOC(document.getElementById("client_oocinputbox").value),document.getElementById("client_oocinputbox").value="")}function I(e){if(13==e.keyCode){var n=me.me(),t=me.myEmote(),o=me.myEvidence(),a=me.flip?1:0,s=document.getElementById("textcolor").value,i="0",p="0";document.getElementById("sendsfx").checked&&(i=t.sfx,p=t.sfxdelay),me.sendIC(t.speaking,n.name,t.silent,document.getElementById("client_inputbox").value,n.side,i,t.zoom,p,h,o,a,A,s)}}function v(e){var n=document.getElementById("client_musiclist").value;me.sendMusicChange(n)}function J(e){var n=e.textContent;me.sendMusicChange(n)}function b(){he.music.volume=document.getElementById("client_mvolume").value/100}function T(){he.sfxaudio.volume=document.getElementById("client_svolume").value/100}function k(){he.setBlipVolume(document.getElementById("client_bvolume").value/100)}function w(e){me.sendLeaveRoom(),document.getElementById("client_charselect").style.display="block",document.getElementById("client_emo").innerHTML=""}function E(e){return e.onerror="",e.src="misc/placeholder.gif",!0}function B(e){return e.onerror="",e.src="/misc/placeholder.png",!0}function G(e,n,t){var o=new XMLHttpRequest;o.onreadystatechange=function(){4==this.readyState&&200==this.status?n(!0,t,e):n(!1,t,e)},o.open("GET",e,!0),o.send()}function M(e){var n=void 0,t=he.bgFolder();switch(document.getElementById("client_fg").style.display="none",document.getElementById("client_bench").style.display="none",e){case"def":document.getElementById("client_court").src=t+"defenseempty.png",document.getElementById("client_bench").style.display="block",G(t+"defensedesk.png",_,e),n="defense";break;case"pro":document.getElementById("client_court").src=t+"prosecutorempty.png",document.getElementById("client_bench").style.display="block",G(t+"defensedesk.png",_,e),n="prosecution";break;case"hld":document.getElementById("client_court").src=t+"helperstand.png",n="defense";break;case"hlp":document.getElementById("client_court").src=t+"prohelperstand.png",n="prosecution";break;case"wit":document.getElementById("client_court").src=t+"witnessempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=t+"estrado.png",n="prosecution";break;case"jud":document.getElementById("client_court").src=t+"judgestand.png",n="prosecution"}5==he.chatmsg.type&&(document.getElementById("client_bench").style.display="none",document.getElementById("client_court").src=l+"themes/default/"+n+"_speedlines.gif")}function _(e,n){var t=he.bgFolder();document.getElementById("client_bench").src="def"==n?e?t+"defensedesk.png":t+"bancodefensa.png":e?t+"prosecutiondesk.png":t+"bancoacusacion.png"}function P(){me.cleanup(),(me=new D(r))&&(c="join",document.getElementById("client_error").style.display="none")}function L(){me.joinServer()}function F(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:new Date,o=document.createElement("p"),a=document.createElement("span");if(a.id="iclog_name",a.appendChild(document.createTextNode(n)),o.appendChild(a),o.appendChild(document.createTextNode(e)),C.getMinutes()!==t.getMinutes()){var s=document.createElement("span");s.id="iclog_time",s.innerText=t.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"}),o.appendChild(s)}var i=document.getElementById("client_log");i.appendChild(o),i.scrollTop>i.scrollHeight-800&&(i.scrollTop=i.scrollHeight),C=new Date}function x(e){e<1e3?me.sendCharacter(e):(document.getElementById("client_charselect").style.display="none",document.getElementById("client_inputbox").style.display="none",document.getElementById("client_emo").style.display="none")}function R(e){-1!=me.selectedEmote&&(document.getElementById("emo_"+me.selectedEmote).src=me.myEmote().button_off),me.selectedEmote=e,document.getElementById("emo_"+e).src=me.myEmote().button_on}function O(e){if(me.selectedEvidence!==e){me.selectedEvidence>0&&(document.getElementById("evi_"+me.selectedEvidence).className="client_button"),document.getElementById("evi_"+e).className="client_button dark",me.selectedEvidence=e,document.getElementById("evi_name").value=me.evidences[e-1].name,document.getElementById("evi_desc").value=me.evidences[e-1].desc;var n=W("evi_select",me.evidences[e-1].filename);document.getElementById("evi_select").selectedIndex=n,0==n&&(document.getElementById("evi_filename").value=me.evidences[e-1].filename),j(),document.getElementById("evi_add").className="client_button hover_button inactive",document.getElementById("evi_edit").className="client_button hover_button",document.getElementById("evi_cancel").className="client_button hover_button",document.getElementById("evi_del").className="client_button hover_button"}else V()}function H(){var e=document.getElementById("evi_select");me.sendPE(document.getElementById("evi_name").value,document.getElementById("evi_desc").value,0==e.selectedIndex?document.getElementById("evi_filename").value:e.options[e.selectedIndex].text),V()}function N(){var e=document.getElementById("evi_select"),n=parseInt(me.selectedEvidence)-1;me.sendEE(n,document.getElementById("evi_name").value,document.getElementById("evi_desc").value,0==e.selectedIndex?document.getElementById("evi_filename").value:e.options[e.selectedIndex].text),V()}function U(){var e=parseInt(me.selectedEvidence)-1;me.sendDE(e),V()}function V(){me.selectedEvidence>0&&(document.getElementById("evi_"+me.selectedEvidence).className="client_button"),me.selectedEvidence=0,document.getElementById("evi_select").selectedIndex=0,j(),document.getElementById("evi_filename").value="",document.getElementById("evi_name").value="",document.getElementById("evi_desc").value="",document.getElementById("evi_icon").style.backgroundImage="url('misc/empty.png')",document.getElementById("evi_add").className="client_button hover_button",document.getElementById("evi_edit").className="client_button hover_button inactive",document.getElementById("evi_cancel").className="client_button hover_button inactive",document.getElementById("evi_del").className="client_button hover_button inactive"}function W(e,n){for(var t=document.getElementById(e),o=1;o/g,">").replace(/"/g,""").replace(/'/g,"'")}function le(e){return e.replace(/#/g,"").replace(/&/g,"").replace(/%/g,"").replace(/\$/g,"")}function de(e){return e.replace(//g,"#").replace(//g,"&").replace(//g,"%").replace(//g,"$")}function ue(e){var n=document.getElementById("client_encoding").value;if("unicode"==n)return e.replace(/[^\0-~]/g,function(e){return"\\u"+("000"+e.charCodeAt().toString(16)).slice(-4)});if("utf16"==n){for(var t=new ArrayBuffer(2*e.length),o=new Uint16Array(t),a=0,s=e.length;a").replace(/\[(\/?)b\]/g,"<$1b>").replace(/\[(\/?)i\]/g,"<$1i>").replace(/\[(\/?)s\]/g,"<$1del>").replace(/\[(\/?)u\]/g,"<$1u>").replace(/\[(\/?)sub\]/g,"<$1sub>").replace(/\[(\/?)sup\]/g,"<$1sup>").replace(/\[m=([#a-zA-Z0-9]+)\]/g,'').replace(/\[(\/?)m\]/g,"<$1m>").replace(/\[c=?([#a-zA-Z0-9]+)\]/g,'').replace(/\[\/c\]/g,"")}},{key:"handleMS",value:function(e){if(e[4]!=me.chatmsg.content){document.getElementById("client_inner_chat").innerHTML="";for(var n={character:-1,preanim:escape(e[2]),nameplate:e[3],name:e[3],speaking:"(b)"+escape(e[4]),silent:"(a)"+escape(e[4]),content:this.prepChat(e[5]),side:e[6],sound:escape(e[7]),type:e[8],snddelay:e[10],objection:e[11],evidence:e[12],flip:e[13],flash:e[14],color:e[15],isnew:!0},t=0;tn.scrollHeight-600&&(n.scrollTop=n.scrollHeight)}},{key:"handleMC",value:function(e){var n=me.music;(n.pause(),n.src=d+e[1].toLowerCase(),n.play(),e[2]>=0)?F(this.chars[e[2]].name+" changed music to "+e[1]):F("The music was changed to "+e[1])}},{key:"handleRMC",value:function(e){me.music.pause(),me.music=new Audio(this.musicList[e[1]]);var n=me.music;n.totime=e[1],n.offset=(new Date).getTime()/1e3,n.addEventListener("loadedmetadata",function(){n.currentTime+=parseFloat(n.totime+((new Date).getTime()/1e3-n.offset)).toFixed(3),n.play()},!1)}},{key:"handleCI",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Character "+e[1],this.serv.send("AN#"+(e[1]/10+1)+"#%");for(var n=2;n'}},{key:"handleEM",value:function(e){document.getElementById("client_loadingtext").innerHTML="Loading Music "+e[1],this.serv.send("AM#"+(e[1]/10+1)+"#%");for(var n=document.getElementById("client_musiclist"),t=2;t .health-bar").animate({width:n+"%"},500)):(this.hp[1]=e[2],$("#client_prosecutor_hp > .health-bar").animate({width:n+"%"},500))}},{key:"handleRT",value:function(e){"testimony1"==e[1]?this.testimonyID=1:this.testimonyID=2,me.initTestimonyUpdater()}},{key:"handleZZ",value:function(e){var n=document.getElementById("client_ooclog");n.innerHTML+="$Alert: "+ue(le(e[1]))+"\r\n",n.scrollTop>n.scrollHeight-60&&(n.scrollTop=n.scrollHeight)}},{key:"handleID",value:function(e){this.playerID=e[1]}},{key:"handlePN",value:function(e){this.serv.send("askchaa#%")}},{key:"handleSI",value:function(e){u?this.serv.send("askchar2#%"):this.serv.send("RC#%")}},{key:"handleCharsCheck",value:function(e){document.getElementById("client_chartable").innerHTML="";for(var n=void 0,t=0;t",n.appendChild(o),t%8==0&&document.getElementById("client_chartable").appendChild(n)}}},{key:"handlePV",value:function(e){this.charID=e[3],document.getElementById("client_charselect").style.display="none",document.getElementById("client_inputbox").style.display="";var n=this.me(),t=this.emotes,o=document.getElementById("client_emo");o.innerHTML="",o.style.display="";var a=new XMLHttpRequest;a.withCredentials=!1,a.open("GET",l+"characters/"+escape(this.me().name.toLowerCase())+"/char.ini",!0),a.responseType="text",a.onload=function(e){if(200==this.status){var a=this.responseText,s=f.parse(a);n.side=s.Options.side,K(n.side);for(var i=1;i<=s.Emotions.number;i++){var p=s.Emotions[i].split("#"),g="0",r="0";void 0!==s.SoundN&&(g=s.SoundN[i]),void 0!==s.SoundT&&(r=s.SoundT[i]),t[i]={desc:p[0].toLowerCase(),speaking:p[1].toLowerCase(),silent:p[2].toLowerCase(),zoom:p[3],sfx:g.toLowerCase(),sfxdelay:r,button_off:l+"characters/"+escape(n.name).toLowerCase()+"/emotions/button"+i+"_off.png",button_on:l+"characters/"+escape(n.name).toLowerCase()+"/emotions/button"+i+"_on.png"},o.innerHTML+="'+t[i].desc+''}R(1)}},a.send()}}]),e}(),y=function(){function e(){p(this,e),this.textnow="",this.chatmsg={isnew:!1,content:"",objection:"0",sound:"",startpreanim:!1,startspeaking:!1,side:null,color:"0",snddelay:0,preanimdelay:0},this.blip=new Audio(l+"sounds/general/sfx-blipmale.wav"),this.blip.volume=.5,this.blipChannels=new Array(6);for(var n=0;n0){var n="";1==Ae.testimonyID?n="witnesstestimony":2==Ae.testimonyID&&(n="crossexamination"),new Audio(Ae.resources[n].sfx).play(),this.testimonyTimer=0;var t=document.getElementById("client_testimony");t.src=Ae.resources[n].src,t.style.display="",this.testimonyUpdater=setTimeout(function(){return e.updateTestimony()},60)}}},{key:"getAnimLength",value:function(e,n,t){var o=new XMLHttpRequest;o.open("GET",e,!0),o.responseType="arraybuffer",o.addEventListener("load",function(){var e=gify.getInfo(o.response);console.log(e.duration),n(e.duration,t)}),o.send()}},{key:"updateTestimony",value:function(){var e=this;this.testimonyTimer=this.testimonyTimer+60,1==Ae.testimonyID?this.testimonyTimer>=Ae.resources.witnesstestimony.duration?this.disposeTestimony():this.testimonyUpdater=setTimeout(function(){return e.updateTestimony()},60):2==Ae.testimonyID?this.testimonyTimer>=Ae.resources.crossexamination.duration?this.disposeTestimony():this.testimonyUpdater=setTimeout(function(){return e.updateTestimony()},60):this.disposeTestimony()}},{key:"disposeTestimony",value:function(){Ae.testimonyID=0,this.testimonyTimer=0,document.getElementById("client_testimony").style.display="none",clearTimeout(this.testimonyUpdater)}},{key:"updateText",value:function(){var e=this,n=document.getElementById("client_name"),t=document.getElementById("client_chat"),o=document.getElementById("client_char"),a=document.getElementById("client_evi"),s=document.getElementById("client_background"),i=document.getElementById("client_shout"),p=document.getElementById("client_inner_chat");if(1==this.chatmsg.flip?o.style.transform="scaleX(-1)":o.style.transform="scaleX(1)",this._animating&&(this.updater=setTimeout(function(){return e.updateText()},60)),this.chatmsg.isnew){s.style.backgroundColor="transparent",n.style.display="none",t.style.display="none",a.style.opacity="0",a.style.height="0%";var g={1:"holdit",2:"objection",3:"takethat"}[this.chatmsg.objection];void 0!==g?(i.src=Ae.resources[g].src,new Audio(l+"characters/"+this.chatmsg.name.toLowerCase()+"/"+g+".wav").play(),this.shoutTimer=850):this.shoutTimer=0,this.chatmsg.isnew=!1,this.chatmsg.startpreanim=!0}if(this.textTimer>=this.shoutTimer&&this.chatmsg.startpreanim)2==this.chatmsg.flash?(this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=l+"sounds/general/sfx-stab.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("shake",{direction:"up"})):1==this.chatmsg.flash&&(s.style.backgroundColor="white",this.sfxaudio.pause(),this.sfxplayed=1,this.sfxaudio.src=l+"sounds/general/sfx-realization.wav",this.sfxaudio.play(),$("#client_gamewindow").effect("pulsate")),this.chatmsg.preanimdelay>0&&(i.src="misc/placeholder.gif",M(this.chatmsg.side),o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.preanim.toLowerCase()+".gif"),this.chatmsg.startpreanim=!1,this.chatmsg.startspeaking=!0;else if(this.textTimer>=this.shoutTimer+this.chatmsg.preanimdelay&&!this.chatmsg.startpreanim)if(this.chatmsg.startspeaking){for(this.chatmsg.evidence>0&&(a.style.backgroundImage="url('"+Ae.evidences[this.chatmsg.evidence-1].icon+"')","def"==this.chatmsg.side?(a.style.right="1.5em",a.style.left="initial",$("#client_evi").animate({height:"30%",opacity:1},250)):(a.style.right="initial",a.style.left="1.5em",$("#client_evi").animate({height:"30%",opacity:1},250))),n.style.display="block",n.style.fontSize=.7*n.offsetHeight+"px";n.hasChildNodes();)n.removeChild(n.firstChild);n.appendChild(document.createTextNode(this.chatmsg.nameplate)),t.style.display="block",t.style.fontSize=.25*t.offsetHeight+"px";p.style.color={0:"#ffffff",1:"#00ff00",2:"#ff0000",3:"#ffaa00",4:"#0000ff",5:"#ffff00",6:"#aa00aa"}[this.chatmsg.color]||"#ffffff",this.chatmsg.startspeaking=!1,0==this.chatmsg.preanimdelay&&(i.src="misc/placeholder.gif",M(this.chatmsg.side)),o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.speaking.toLowerCase()+".gif",this.textnow==this.chatmsg.content&&(o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.silent.toLowerCase()+".gif",this._animating=!1,clearTimeout(this.updater))}else if(this.textnow!=this.chatmsg.content){for(" "!=this.chatmsg.content.charAt(this.textnow.length)&&(this.blipChannels[this.currentBlipChannel].play(),this.currentBlipChannel++,this.currentBlipChannel%=this.blipChannels.length),this.textnow=this.chatmsg.content.substring(0,this.textnow.length+1);p.hasChildNodes();)p.removeChild(p.firstChild);p.appendChild(document.createTextNode(this.textnow)),this.textnow==this.chatmsg.content&&(this.textTimer=0,this._animating=!1,o.src=l+"characters/"+escape(this.chatmsg.name.toLowerCase())+"/"+this.chatmsg.silent.toLowerCase()+".gif",clearTimeout(this.updater))}!this.sfxplayed&&this.chatmsg.snddelay+this.shoutTimer>=this.textTimer&&(this.sfxaudio.pause(),this.sfxplayed=1,"0"!=this.chatmsg.sound&&"1"!=this.chatmsg.sound&&(this.sfxaudio.src=l+"sounds/general/"+escape(this.chatmsg.sound.toLowerCase())+".wav",this.sfxaudio.play())),this.textTimer=this.textTimer+60}}]),e}(),f=function(){function e(){p(this,e)}return o(e,null,[{key:"parse",value:function(e){var n={section:/^\s*\[\s*([^\]]*)\s*\]\s*$/,param:/^\s*([\w.\-_]+)\s*=\s*(.*?)\s*$/,comment:/^\s*;.*$/},t={},o=null;return e.split(/\r\n|\r|\n/).forEach(function(e){if(!n.comment.test(e)&&0!=e.length)if(n.param.test(e)){var a=e.match(n.param);o?t[o][a[1]]=a[2]:t[a[1]]=a[2]}else if(n.section.test(e)){var s=e.match(n.section);t[s[1]]={},o=s[1]}}),t}}]),e}();function S(e){13==e.keyCode&&(Ae.sendOOC(document.getElementById("client_oocinputbox").value),document.getElementById("client_oocinputbox").value="")}function I(e){if(13==e.keyCode){var n=Ae.me(),t=Ae.myEmote(),o=Ae.myEvidence(),a=Ae.flip?1:0,s=document.getElementById("textcolor").value,i="0",p="0";document.getElementById("sendsfx").checked&&(i=t.sfx,p=t.sfxdelay),Ae.sendIC(t.speaking,n.name,t.silent,document.getElementById("client_inputbox").value,n.side,i,t.zoom,p,h,o,a,A,s)}}function v(e){var n=document.getElementById("client_musiclist").value;Ae.sendMusicChange(n)}function J(e){var n=e.textContent;Ae.sendMusicChange(n);var t=document.createElement("div");t.className="hrtext",t.textContent="switched to "+e.textContent,document.getElementById("client_log").appendChild(t)}function b(){me.music.volume=document.getElementById("client_mvolume").value/100}function T(){me.sfxaudio.volume=document.getElementById("client_svolume").value/100}function k(){me.setBlipVolume(document.getElementById("client_bvolume").value/100)}function E(e){Ae.sendLeaveRoom(),document.getElementById("client_charselect").style.display="block",document.getElementById("client_emo").innerHTML=""}function w(e){return e.onerror="",e.src="misc/placeholder.gif",!0}function B(e){return e.onerror="",e.src="/misc/placeholder.png",!0}function G(e,n,t){var o=new XMLHttpRequest;o.onreadystatechange=function(){4==this.readyState&&200==this.status?n(!0,t,e):n(!1,t,e)},o.open("GET",e,!0),o.send()}function M(e){var n=void 0,t=me.bgFolder();switch(document.getElementById("client_fg").style.display="none",document.getElementById("client_bench").style.display="none",e){case"def":document.getElementById("client_court").src=t+"defenseempty.png",document.getElementById("client_bench").style.display="block",G(t+"defensedesk.png",_,e),n="defense";break;case"pro":document.getElementById("client_court").src=t+"prosecutorempty.png",document.getElementById("client_bench").style.display="block",G(t+"defensedesk.png",_,e),n="prosecution";break;case"hld":document.getElementById("client_court").src=t+"helperstand.png",n="defense";break;case"hlp":document.getElementById("client_court").src=t+"prohelperstand.png",n="prosecution";break;case"wit":document.getElementById("client_court").src=t+"witnessempty.png",document.getElementById("client_bench").style.display="block",document.getElementById("client_bench").src=t+"estrado.png",n="prosecution";break;case"jud":document.getElementById("client_court").src=t+"judgestand.png",n="prosecution"}5==me.chatmsg.type&&(document.getElementById("client_bench").style.display="none",document.getElementById("client_court").src=l+"themes/default/"+n+"_speedlines.gif")}function _(e,n){var t=me.bgFolder();document.getElementById("client_bench").src="def"==n?e?t+"defensedesk.png":t+"bancodefensa.png":e?t+"prosecutiondesk.png":t+"bancoacusacion.png"}function P(){Ae.cleanup(),(Ae=new D(r))&&(c="join",document.getElementById("client_error").style.display="none")}function L(){Ae.joinServer()}function F(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"",t=arguments.length>2&&void 0!==arguments[2]?arguments[2]:new Date,o=document.createElement("p"),a=document.createElement("span");if(a.id="iclog_name",a.appendChild(document.createTextNode(n)),o.appendChild(a),o.appendChild(document.createTextNode(e)),C.getMinutes()!==t.getMinutes()){var s=document.createElement("span");s.id="iclog_time",s.innerText=t.toLocaleTimeString(void 0,{hour:"numeric",minute:"2-digit"}),o.appendChild(s)}var i=document.getElementById("client_log");i.appendChild(o),i.scrollTop>i.scrollHeight-800&&(i.scrollTop=i.scrollHeight),C=new Date}function x(e){e<1e3?Ae.sendCharacter(e):(document.getElementById("client_charselect").style.display="none",document.getElementById("client_inputbox").style.display="none",document.getElementById("client_emo").style.display="none")}function R(e){-1!=Ae.selectedEmote&&(document.getElementById("emo_"+Ae.selectedEmote).src=Ae.myEmote().button_off),Ae.selectedEmote=e,document.getElementById("emo_"+e).src=Ae.myEmote().button_on}function O(e){if(Ae.selectedEvidence!==e){Ae.selectedEvidence>0&&(document.getElementById("evi_"+Ae.selectedEvidence).className="client_button"),document.getElementById("evi_"+e).className="client_button dark",Ae.selectedEvidence=e,document.getElementById("evi_name").value=Ae.evidences[e-1].name,document.getElementById("evi_desc").value=Ae.evidences[e-1].desc;var n=W("evi_select",Ae.evidences[e-1].filename);document.getElementById("evi_select").selectedIndex=n,0==n&&(document.getElementById("evi_filename").value=Ae.evidences[e-1].filename),j(),document.getElementById("evi_add").className="client_button hover_button inactive",document.getElementById("evi_edit").className="client_button hover_button",document.getElementById("evi_cancel").className="client_button hover_button",document.getElementById("evi_del").className="client_button hover_button"}else V()}function H(){var e=document.getElementById("evi_select");Ae.sendPE(document.getElementById("evi_name").value,document.getElementById("evi_desc").value,0==e.selectedIndex?document.getElementById("evi_filename").value:e.options[e.selectedIndex].text),V()}function N(){var e=document.getElementById("evi_select"),n=parseInt(Ae.selectedEvidence)-1;Ae.sendEE(n,document.getElementById("evi_name").value,document.getElementById("evi_desc").value,0==e.selectedIndex?document.getElementById("evi_filename").value:e.options[e.selectedIndex].text),V()}function U(){var e=parseInt(Ae.selectedEvidence)-1;Ae.sendDE(e),V()}function V(){Ae.selectedEvidence>0&&(document.getElementById("evi_"+Ae.selectedEvidence).className="client_button"),Ae.selectedEvidence=0,document.getElementById("evi_select").selectedIndex=0,j(),document.getElementById("evi_filename").value="",document.getElementById("evi_name").value="",document.getElementById("evi_desc").value="",document.getElementById("evi_icon").style.backgroundImage="url('misc/empty.png')",document.getElementById("evi_add").className="client_button hover_button",document.getElementById("evi_edit").className="client_button hover_button inactive",document.getElementById("evi_cancel").className="client_button hover_button inactive",document.getElementById("evi_del").className="client_button hover_button inactive"}function W(e,n){for(var t=document.getElementById(e),o=1;o").replace(/&/g,"").replace(/%/g,"").replace(/\$/g,"")}function le(e){return e.replace(//g,"#").replace(//g,"&").replace(//g,"%").replace(//g,"$")}function de(e){var n=document.getElementById("client_encoding").value;if("unicode"==n)return e.replace(/[^\0-~]/g,function(e){return"\\u"+("000"+e.charCodeAt().toString(16)).slice(-4)});if("utf16"==n){for(var t=new ArrayBuffer(2*e.length),o=new Uint16Array(t),a=0,s=e.length;a 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.flip = false;\r\n\t\tthis.presentable = false;\r\n\r\n\t\tthis.hp = [0, 0];\r\n\r\n\t\tthis.playerID = 1;\r\n\t\tthis.charID = -1;\r\n\t\tthis.testimonyID = 0;\r\n\r\n\t\tthis.chars = [];\r\n\t\tthis.emotes = [];\r\n\t\tthis.evidences = [];\r\n\r\n\t\tthis.resources = {\r\n\t\t\t\"holdit\": {\r\n\t\t\t\t\"src\": \"misc/holdit.gif\",\r\n\t\t\t\t\"duration\": 720\r\n\t\t\t},\r\n\t\t\t\"objection\": {\r\n\t\t\t\t\"src\": \"misc/objection.gif\",\r\n\t\t\t\t\"duration\": 720\r\n\t\t\t},\r\n\t\t\t\"takethat\": {\r\n\t\t\t\t\"src\": \"misc/takethat.gif\",\r\n\t\t\t\t\"duration\": 840\r\n\t\t\t},\r\n\t\t\t\"witnesstestimony\": {\r\n\t\t\t\t\"src\": \"misc/witnesstestimony.gif\",\r\n\t\t\t\t\"duration\": 1560,\r\n\t\t\t\t\"sfx\": \"sounds/general/sfx-testimony.wav\"\r\n\t\t\t},\r\n\t\t\t\"crossexamination\": {\r\n\t\t\t\t\"src\": \"misc/crossexamination.gif\",\r\n\t\t\t\t\"duration\": 1600,\r\n\t\t\t\t\"sfx\": \"sounds/general/sfx-testimony2.wav\"\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\t\tthis.selectedEvidence = 0;\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\"LE\": (args) => this.handleLE(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\"RT\": (args) => this.handleRT(args),\r\n\t\t\t\"ZZ\": (args) => this.handleZZ(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 * Gets the player's currently selected evidence if presentable.\r\n\t */\r\n\tmyEvidence() {\r\n\t\treturn this.presentable ? this.selectedEvidence : 0;\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#${escapeChat(encodeChat(document.getElementById(\"OOC_name\").value))}#${escapeChat(encodeChat(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 {number} 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 * @param {string} evidence the filename of evidence to show\r\n\t * @param {number} flip change to 1 to reverse sprite for position changes\r\n\t * @param {string} flash screen flash effect\r\n\t * @param {string} color text color\r\n\t */\r\n\tsendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, evidence, flip, flash, color) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(encodeChat(message))}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#${evidence}#${flip}#${flash}#${color}#%`\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends add evidence command.\r\n\t * @param {string} evidence name\r\n\t * @param {string} evidence description\r\n\t * @param {string} evidence image filename\r\n\t */\r\n\tsendPE(name, desc, img) {\r\n\t\tthis.serv.send(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends edit evidence command.\r\n\t * @param {number} evidence id\r\n\t * @param {string} evidence name\r\n\t * @param {string} evidence description\r\n\t * @param {string} evidence image filename\r\n\t */\r\n\tsendEE(id, name, desc, img) {\r\n\t\tthis.serv.send(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends delete evidence command.\r\n\t * @param {number} evidence id\r\n\t */\r\n\tsendDE(id) {\r\n\t\tthis.serv.send(`DE#${id}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends health point command.\r\n\t * @param {number} side the position\r\n\t * @param {number} hp the health point\r\n\t */\r\n\tsendHP(side, hp) {\r\n\t\tthis.serv.send(`HP#${side}#${hp}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends call mod command.\r\n\t * @param {string} message to mod\r\n\t */\r\n\tsendZZ(msg) {\r\n\t\tthis.serv.send(`ZZ#${msg}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends testimony command.\r\n\t * @param {string} testimony type\r\n\t */\r\n\tsendRT(testimony) {\r\n\t\tif (this.chars[this.charID].side == \"jud\") {\r\n\t\t\tthis.serv.send(`RT#${testimony}#%`);\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.3#%\");\r\n\t\tthis.checkUpdater = setInterval(() => this.sendCheck(), 5000);\r\n\t}\r\n\r\n\t/**\r\n\t * Load game resources.\r\n\t */\r\n\tloadResources() {\r\n\t\t// Set to playerID to server chat name\r\n\t\t// TODO: Make a text box for this!\r\n\t\tdocument.getElementById(\"OOC_name\").value = \"web\" + this.playerID;\r\n\r\n\t\t// Load evidence array to select\r\n\t\tconst evidence_select = document.getElementById(\"evi_select\");\r\n\t\tevidence_select.add(new Option(\"Custom\", 0));\r\n\t\tevidence_arr.forEach(evidence => {\r\n\t\t\tevidence_select.add(new Option(evidence));\r\n\t\t});\r\n\r\n\t\t// Load background array to select\r\n\t\tconst background_select = document.getElementById(\"bg_select\");\r\n\t\tbackground_select.add(new Option(\"Custom\", 0));\r\n\t\tbackground_arr.forEach(background => {\r\n\t\t\tbackground_select.add(new Option(background));\r\n\t\t});\r\n\t\t// Calculate gif duration of shouts\r\n\t\tconst shouts = [\"holdit\", \"objection\", \"takethat\"];\r\n\t\tfor (let i = 0; i < shouts.length; i++) {\r\n\t\t\tlet shout_src = AO_HOST + this.resources[shouts[i]][\"src\"].toLowerCase();\r\n\t\t\tfileExists(shout_src, this.callbackLoadImageResources, shouts[i]);\r\n\t\t}\r\n\r\n\t\t// Calculate gif duration of testimony\r\n\t\tconst testimony = [\"witnesstestimony\", \"crossexamination\"];\r\n\t\tfor (let i = 0; i < testimony.length; i++) {\r\n\t\t\tconst testimony_src = `${AO_HOST}themes/default/${testimony[i]}.gif`;\r\n\t\t\t// Check image existed\r\n\t\t\tfileExists(testimony_src, this.callbackLoadImageResources, testimony[i]);\r\n\t\t\t// Check sfx existed\r\n\t\t\tfileExists(AO_HOST + this.resources[testimony[i]][\"sfx\"].toLowerCase(), this.callbackLoadSFXResources, testimony[i]);\r\n\t\t}\r\n\t\t// TODO: Cache some resources\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Callback for image resources.\r\n\t * @param {boolean} result the image is existed or not\r\n\t * @param {string} resource the resource name\r\n\t * @param {string} src the url of resource\r\n\t */\r\n\tcallbackLoadImageResources(result, resource, src) {\r\n\t\tif (result) {\r\n\t\t\tclient.resources[resource][\"src\"] = src;\r\n\t\t\tviewport.getAnimLength(src, client.callbackGetResourceLength, resource);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Callback for animation duration resource\r\n\t * @param {integer} length the animation length\r\n\t * @param {string} resource the resource name\r\n\t */\r\n\tcallbackGetResourceLength(length, resource) {\r\n\t\tclient.resources[resource][\"duration\"] = length;\r\n\t}\r\n\r\n\t/**\r\n\t * Callback for sfx resources.\r\n\t * @param {boolean} result the audio is existed or not\r\n\t * @param {string} resource the resource name\r\n\t * @param {string} src the url of resource\r\n\t */\r\n\tcallbackLoadSFXResources(result, resource, src) {\r\n\t\tif (result) {\r\n\t\t\tclient.resources[resource][\"sfx\"] = src;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Create observer to detect BBCode elements\r\n\t * then manipulate them.\r\n\t */\r\n\tinitialObservBBCode() {\r\n\t\tconst target = document.getElementById(\"client_inner_chat\");\r\n\t\tconst observer = new MutationObserver(function (mutations) {\r\n\t\t\tmutations.forEach(function (mutation) {\r\n\t\t\t\tconst children = mutation.addedNodes;\r\n\t\t\t\tif (children !== null) {\r\n\t\t\t\t\tchildren.forEach(function (node) {\r\n\t\t\t\t\t\tif (node.tagName == \"C\") {\r\n\t\t\t\t\t\t\tnode.style.color = node.getAttribute(\"a\");\r\n\t\t\t\t\t\t} else if (node.tagName == \"M\") {\r\n\t\t\t\t\t\t\tif (node.hasAttribute(\"a\")) {\r\n\t\t\t\t\t\t\t\tnode.style.backgroundColor = node.getAttribute(\"a\");\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tnode.style.backgroundColor = \"yellow\";\r\n\t\t\t\t\t\t\t\tnode.style.color = \"black\";\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\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\tconst config = {\r\n\t\t\tattributes: true,\r\n\t\t\tchildList: true\r\n\t\t};\r\n\t\tobserver.observe(target, config);\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 * XXX: a nasty hack made by gameboyprinter.\r\n\t * @param {string} msg chat message to prepare for display \r\n\t */\r\n\tprepChat(msg){\r\n\t\t// TODO: make this less awful\r\n\t\treturn decodeBBCode(escapeHtml(decodeChat(unescapeChat(msg))));\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\tconst chatmsg = {\r\n\t\t\t\t// pre: 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: this.prepChat(args[5]), // Escape HTML tag, Use BBCode Only!\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\tflip: 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 += `${decodeChat(unescapeChat(args[1]))}: ${decodeChat(unescapeChat(args[2]))}\\r\\n`;\r\n\t\tif (oocLog.scrollTop > oocLog.scrollHeight - 600) {\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].toLowerCase();\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].toLowerCase()) + \"/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].toLowerCase()) + \"/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 evidence list, all evidences at once\r\n\t * item per packet.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleLE(args) {\r\n\t\tthis.evidences = [];\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tconst arg = args[i].split(\"&\");\r\n\t\t\tthis.evidences[i - 1] = {\r\n\t\t\t\t\"name\": escapeHtml(decodeChat(unescapeChat(arg[0]))),\r\n\t\t\t\t\"desc\": escapeHtml(decodeChat(unescapeChat(arg[1]))),\r\n\t\t\t\t\"filename\": escape(arg[2]),\r\n\t\t\t\t\"icon\": AO_HOST + \"evidence/\" + escape(arg[2].toLowerCase())\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tconst evidence_box = document.getElementById(\"evidences\");\r\n\t\tevidence_box.innerHTML = \"\";\r\n\t\tfor (let i = 1; i <= this.evidences.length; i++) {\r\n\t\t\tevidence_box.innerHTML += ``;\r\n\t\t}\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\tconst hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tlet flagAudio = false;\r\n\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\t// Check when found the song for the first time\r\n\t\t\tif (/\\.(?:wav|mp3|mp4|ogg|opus)$/i.test(args[i]) && !flagAudio) {\r\n\t\t\t\tflagAudio = true;\r\n\t\t\t}\r\n\r\n\t\t\tif (flagAudio) {\r\n\t\t\t\t// After reached the audio put everything in the music list\r\n\t\t\t\tconst 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} else {\r\n\t\t\t\t// Create area button\r\n\t\t\t\tconst newarea = document.createElement(\"SPAN\");\r\n\t\t\t\tnewarea.className = \"location-box\";\r\n\t\t\t\tnewarea.textContent = args[i];\r\n\t\t\t\tnewarea.onclick = function () {\r\n\t\t\t\t\tarea_click(this);\r\n\t\t\t\t};\r\n\t\t\t\tdocument.getElementById(\"areas\").appendChild(newarea);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// We need to check if the last area that we got was actually a category\r\n\t\t// header for music. If it was, then move it over to the music list.\r\n\t\tconst area_box = document.getElementById(\"areas\");\r\n\t\tif (area_box.lastChild.textContent.startsWith(\"=\")) {\r\n\t\t\tconst audio_title = document.createElement(\"OPTION\");\r\n\t\t\taudio_title.text = area_box.lastChild.textContent;\r\n\t\t\thmusiclist.insertBefore(audio_title, hmusiclist.firstChild);\r\n\t\t\tarea_box.removeChild(area_box.lastChild);\r\n\t\t}\r\n\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\tconst bg_index = getIndexFromSelect(\"bg_select\", escape(args[1]));\r\n\t\tdocument.getElementById(\"bg_select\").selectedIndex = bg_index;\r\n\t\tupdateBackgroundPreview();\r\n\t\tif (bg_index == 0) {\r\n\t\t\tdocument.getElementById(\"bg_filename\").value = args[1];\r\n\t\t}\r\n\t\tdocument.getElementById(\"bg_preview\").src = AO_HOST + \"background/\" + escape(args[1].toLowerCase()) + \"/defenseempty.png\";\r\n\t\tif (this.charID == -1) {\r\n\t\t\tchangeBackground(\"jud\");\r\n\t\t} else {\r\n\t\t\tchangeBackground(this.chars[this.charID].side);\r\n\t\t}\r\n\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\tconst percent_hp = args[2] * 10;\r\n\t\tif (args[1] == 1) {\r\n\t\t\t// Def hp\r\n\t\t\tthis.hp[0] = args[2];\r\n\t\t\t$(\"#client_defense_hp > .health-bar\").animate({\r\n\t\t\t\t\"width\": percent_hp + \"%\"\r\n\t\t\t}, 500);\r\n\t\t} else {\r\n\t\t\t// Pro hp\r\n\t\t\tthis.hp[1] = args[2];\r\n\t\t\t$(\"#client_prosecutor_hp > .health-bar\").animate({\r\n\t\t\t\t\"width\": percent_hp + \"%\"\r\n\t\t\t}, 500);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a testimony states.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleRT(args) {\r\n\t\tif (args[1] == \"testimony1\") {\r\n\t\t\t//Witness Testimony\r\n\t\t\tthis.testimonyID = 1;\r\n\t\t} else {\r\n\t\t\t//Cross Examination\r\n\t\t\tthis.testimonyID = 2;\r\n\t\t}\r\n\t\tviewport.initTestimonyUpdater();\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a call mod message.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleZZ(args) {\r\n\t\tconst oocLog = document.getElementById(\"client_ooclog\");\r\n\t\toocLog.innerHTML += `$Alert: ${decodeChat(unescapeChat(args[1]))}\\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 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\tlet tr;\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\ttr = document.createElement(\"TR\");\r\n\t\t\t}\r\n\t\t\tconst td = document.createElement(\"TD\");\r\n\t\t\tlet icon_chosen = \"\";\r\n\t\t\tconst 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}\r\n\t\t\ttd.innerHTML = `${this.chars[i].name}\";\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\t//changeBackground(\"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\tconst me = this.me();\r\n\t\tconst emotes = this.emotes;\r\n\t\tconst xhr = new XMLHttpRequest();\r\n\t\txhr.withCredentials = false;\r\n\t\tdocument.getElementById(\"client_emo\").innerHTML = \"\"; // Clear emote box\r\n\t\txhr.open(\"GET\", AO_HOST + \"characters/\" + escape(this.me().name.toLowerCase()) + \"/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\tconst linifile = this.responseText;\r\n\t\t\t\tconst pinifile = INI.parse(linifile);\r\n\t\t\t\tme.side = pinifile.Options.side;\r\n\t\t\t\tupdateActionCommands(me.side);\r\n\t\t\t\tfor (let i = 1; i < pinifile.Emotions.number; i++) {\r\n\t\t\t\t\tconst 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\t// Make sure the asset server is case insensitive, or that everything on it is lowercase\r\n\t\t\t\t\temotes[i] = {\r\n\t\t\t\t\t\tdesc: emoteinfo[0].toLowerCase(),\r\n\t\t\t\t\t\tspeaking: emoteinfo[1].toLowerCase(),\r\n\t\t\t\t\t\tsilent: emoteinfo[2].toLowerCase(),\r\n\t\t\t\t\t\tzoom: emoteinfo[3],\r\n\t\t\t\t\t\tsfx: esfx.toLowerCase(),\r\n\t\t\t\t\t\tsfxdelay: esfxd,\r\n\t\t\t\t\t\tbutton_off: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_off.png`,\r\n\t\t\t\t\t\tbutton_on: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_on.png`\r\n\t\t\t\t\t};\r\n\t\t\t\t\tdocument.getElementById(\"client_emo\").innerHTML += \r\n\t\t\t\t\t\t`\"${emotes[i].desc}\"\r\n\t\t\t\t\t\t`;\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\"startpreanim\": false,\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\t\"preanimdelay\": 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\t\tthis.testimonyUpdater = null;\r\n\r\n\t\tthis.bgname = \"gs4\";\r\n\r\n\t\tthis.testimonyTimer = 0;\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.toLowerCase()}/`;\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\t//If preanim existed then determine the length\r\n\t\tif (chatmsg.preanim != \"-\") {\r\n\t\t\tchatmsg.preanimdelay = this.getAnimLength(`${AO_HOST}characters/${escape(chatmsg.name.toLowerCase())}/${chatmsg.preanim.toLowerCase()}.gif`, this.initUpdater);\r\n\t\t} else {\r\n\t\t\tthis.initUpdater(0);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Intialize updater\r\n\t * @param {number} animdelay the length of pre-animation \r\n\t */\r\n\tinitUpdater(animdelay) {\r\n\t\tviewport.chatmsg.preanimdelay = parseInt(animdelay);\r\n\t\tviewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\r\n\t/**\r\n\t * Intialize testimony updater \r\n\t */\r\n\tinitTestimonyUpdater() {\r\n\t\tif (client.testimonyID > 0) {\r\n\t\t\tlet testimony = \"\";\r\n\t\t\tif (client.testimonyID == 1) {\r\n\t\t\t\ttestimony = \"witnesstestimony\";\r\n\t\t\t} else if (client.testimonyID == 2) {\r\n\t\t\t\ttestimony = \"crossexamination\";\r\n\t\t\t}\r\n\t\t\t(new Audio(client.resources[testimony][\"sfx\"])).play();\r\n\t\t\tthis.testimonyTimer = 0;\r\n\t\t\tconst testimonyOverlay = document.getElementById(\"client_testimony\");\r\n\t\t\ttestimonyOverlay.src = client.resources[testimony][\"src\"];\r\n\t\t\ttestimonyOverlay.style.display = \"\";\r\n\t\t\tthis.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets animation length.\r\n\t * @param {string} filename the animation file name\r\n\t * @param {function} callback the callback function\r\n\t * @param {object} param \r\n\t */\r\n\tgetAnimLength(filename, callback, param) {\r\n\t\tconst request = new XMLHttpRequest();\r\n\t\trequest.open(\"GET\", filename, true);\r\n\t\trequest.responseType = \"arraybuffer\";\r\n\t\trequest.addEventListener(\"load\", function () {\r\n\t\t\tconst gifInfo = gify.getInfo(request.response);\r\n\t\t\tconsole.log(gifInfo[\"duration\"]);\r\n\t\t\t// Return animation length\r\n\t\t\tcallback(gifInfo[\"duration\"], param);\r\n\t\t});\r\n\t\trequest.send();\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the testimony overaly\r\n\t */\r\n\tupdateTestimony() {\r\n\t\t//Update timer\r\n\t\tthis.testimonyTimer = this.testimonyTimer + UPDATE_INTERVAL;\r\n\r\n\t\tif (client.testimonyID == 1) {\r\n\t\t\t//Witness Testimony\r\n\t\t\tif (this.testimonyTimer >= client.resources[\"witnesstestimony\"][\"duration\"]) {\r\n\t\t\t\t//Finish\r\n\t\t\t\tthis.disposeTestimony();\r\n\t\t\t} else {\r\n\t\t\t\tthis.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL);\r\n\t\t\t}\r\n\t\t} else if (client.testimonyID == 2) {\r\n\t\t\t//Cross Examination\r\n\t\t\tif (this.testimonyTimer >= client.resources[\"crossexamination\"][\"duration\"]) {\r\n\t\t\t\t//Finish\r\n\t\t\t\tthis.disposeTestimony();\r\n\t\t\t} else {\r\n\t\t\t\tthis.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis.disposeTestimony();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Dispose the testimony overlay\r\n\t */\r\n\tdisposeTestimony() {\r\n\t\tclient.testimonyID = 0;\r\n\t\tthis.testimonyTimer = 0;\r\n\t\tdocument.getElementById(\"client_testimony\").style.display = \"none\";\r\n\t\tclearTimeout(this.testimonyUpdater);\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\tconst nameBox = document.getElementById(\"client_name\");\r\n\t\tconst chatBox = document.getElementById(\"client_chat\");\r\n\t\tconst charSprite = document.getElementById(\"client_char\");\r\n\t\tconst eviBox = document.getElementById(\"client_evi\");\r\n\t\tconst background = document.getElementById(\"client_background\");\r\n\t\tconst shoutSprite = document.getElementById(\"client_shout\");\r\n\t\tconst chatBoxInner = document.getElementById(\"client_inner_chat\");\r\n\r\n\t\t// Flip the character\r\n\t\tif (this.chatmsg.flip == 1) {\r\n\t\t\tcharSprite.style.transform = \"scaleX(-1)\";\r\n\t\t} else {\r\n\t\t\tcharSprite.style.transform = \"scaleX(1)\";\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\t// Reset screen background\r\n\t\t\tbackground.style.backgroundColor = \"transparent\";\r\n\t\t\t// Hide message and evidence window\r\n\t\t\tnameBox.style.display = \"none\";\r\n\t\t\tchatBox.style.display = \"none\";\r\n\t\t\teviBox.style.opacity = \"0\";\r\n\t\t\teviBox.style.height = \"0%\";\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"objection\",\r\n\t\t\t\t\"3\": \"takethat\"\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\tshoutSprite.src = client.resources[shout][\"src\"];\r\n\t\t\t\t(new Audio(`${AO_HOST}characters/${this.chatmsg.name.toLowerCase()}/${shout}.wav`)).play();\r\n\t\t\t\tthis.shoutTimer = 850;\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.startpreanim = true;\r\n\t\t}\r\n\r\n\t\tif (this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) {\r\n\t\t\t// Effect stuff\r\n\t\t\tif (this.chatmsg.flash == 2) {\r\n\t\t\t\t//Shake screen\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-stab.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$(\"#client_gamewindow\").effect(\"shake\", {\r\n\t\t\t\t\t\"direction\": \"up\"\r\n\t\t\t\t});\r\n\t\t\t} else if (this.chatmsg.flash == 1) {\r\n\t\t\t\t//Flash screen\r\n\t\t\t\tbackground.style.backgroundColor = \"white\";\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-realization.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$(\"#client_gamewindow\").effect(\"pulsate\");\r\n\t\t\t}\r\n\r\n\t\t\t//Pre-animation stuff\r\n\t\t\tif (this.chatmsg.preanimdelay > 0) {\r\n\t\t\t\tshoutSprite.src = \"misc/placeholder.gif\";\r\n\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.preanim.toLowerCase() + \".gif\";\r\n\t\t\t}\r\n\t\t\tthis.chatmsg.startpreanim = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t} else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\tif (this.chatmsg.evidence > 0) {\r\n\t\t\t\t\t// Prepare evidence\r\n\t\t\t\t\teviBox.style.backgroundImage = \"url('\" + client.evidences[this.chatmsg.evidence - 1].icon + \"')\";\r\n\r\n\t\t\t\t\tif (this.chatmsg.side == \"def\") {\r\n\t\t\t\t\t\t// Only def show evidence on right\r\n\t\t\t\t\t\teviBox.style.right = \"1.5em\";\r\n\t\t\t\t\t\teviBox.style.left = \"initial\";\r\n\t\t\t\t\t\t$(\"#client_evi\").animate({\r\n\t\t\t\t\t\t\theight: \"30%\",\r\n\t\t\t\t\t\t\topacity: 1\r\n\t\t\t\t\t\t}, 250);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\teviBox.style.right = \"initial\";\r\n\t\t\t\t\t\teviBox.style.left = \"1.5em\";\r\n\t\t\t\t\t\t$(\"#client_evi\").animate({\r\n\t\t\t\t\t\t\theight: \"30%\",\r\n\t\t\t\t\t\t\topacity: 1\r\n\t\t\t\t\t\t}, 250);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tnameBox.style.display = \"block\";\r\n\t\t\t\tnameBox.style.fontSize = (nameBox.offsetHeight * 0.7) + \"px\";\r\n\t\t\t\tnameBox.innerHTML = \"

\" + escapeHtml(this.chatmsg.nameplate) + \"

\";\r\n\r\n\t\t\t\tchatBox.style.display = \"block\";\r\n\t\t\t\tchatBox.style.fontSize = (chatBox.offsetHeight * 0.25) + \"px\";\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\tchatBoxInner.style.color = colors[this.chatmsg.color] || \"#ffffff\";\r\n\t\t\t\tthis.chatmsg.startspeaking = false;\r\n\r\n\t\t\t\tif (this.chatmsg.preanimdelay == 0) {\r\n\t\t\t\t\tshoutSprite.src = \"misc/placeholder.gif\";\r\n\t\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.speaking.toLowerCase() + \".gif\";\r\n\r\n\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.silent.toLowerCase() + \".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\tchatBoxInner.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\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.silent.toLowerCase() + \".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\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.toLowerCase()) + \".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 myevi = client.myEvidence();\r\n\t\tlet myflip = ((client.flip) ? 1 : 0);\r\n\t\tlet mycolor = document.getElementById(\"textcolor\").value;\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, myevi, myflip, selectedEffect, mycolor);\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 (selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t}\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 when an item on the music list is clicked.\r\n * @param {MouseEvent} event\r\n */\r\nexport function area_click(el) {\r\n\tlet playtrack = el.textContent;\r\n\tclient.sendMusicChange(playtrack);\r\n}\r\nwindow.area_click = area_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 a file exists at the specified URI.\r\n * @param {string} url the URI to be checked\r\n * @param {function} callback the function to be called when finished\r\n * @param {object} param \r\n */\r\nfunction fileExists(url, callback, param) {\r\n\tconst xhttp = new XMLHttpRequest();\r\n\txhttp.onreadystatechange = function () {\r\n\t\tif (this.readyState == 4 && this.status == 200) {\r\n\t\t\tcallback(true, param, url);\r\n\t\t} else {\r\n\t\t\tcallback(false, param, url);\r\n\t\t}\r\n\t};\r\n\txhttp.open(\"GET\", url, true);\r\n\txhttp.send();\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\tlet standname;\r\n\tconst 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\tcase \"def\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"defenseempty.png\";\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\tfileExists(bgfolder + \"defensedesk.png\", callbackChangeBackground, position);\r\n\t\tstandname = \"defense\";\r\n\t\tbreak;\r\n\tcase \"pro\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prosecutorempty.png\";\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\tfileExists(bgfolder + \"defensedesk.png\", callbackChangeBackground, position);\r\n\t\tstandname = \"prosecution\";\r\n\t\tbreak;\r\n\tcase \"hld\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"helperstand.png\";\r\n\t\tstandname = \"defense\";\r\n\t\tbreak;\r\n\tcase \"hlp\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prohelperstand.png\";\r\n\t\tstandname = \"prosecution\";\r\n\t\tbreak;\r\n\tcase \"wit\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"witnessempty.png\";\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"estrado.png\";\r\n\t\tstandname = \"prosecution\";\r\n\t\tbreak;\r\n\tcase \"jud\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"judgestand.png\";\r\n\t\tstandname = \"prosecution\";\r\n\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 * Callback for desk resource\r\n * \r\n * Valid positions: `def, pro, hld, hlp, wit, jud`\r\n * @param {boolean} result the image is existed or not\r\n * @param {string} position the position to change into\r\n */\r\nfunction callbackChangeBackground(result, position) {\r\n\tlet bgfolder = viewport.bgFolder();\r\n\tif (position == \"def\") {\r\n\t\tif (result) {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"defensedesk.png\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"bancodefensa.png\";\r\n\t\t}\r\n\t} else {\r\n\t\tif (result) {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"prosecutiondesk.png\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"bancoacusacion.png\";\r\n\t\t}\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 - 800) {\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 an evidence for in-character chat.\r\n * @param {string} evidence the evidence to be presented\r\n */\r\nexport function pickEvidence(evidence) {\r\n\tif (client.selectedEvidence !== evidence) {\r\n\t\t//Update selected evidence\t\t\r\n\t\tif (client.selectedEvidence > 0) {\r\n\t\t\tdocument.getElementById(\"evi_\" + client.selectedEvidence).className = \"client_button\";\r\n\t\t}\r\n\t\tdocument.getElementById(\"evi_\" + evidence).className = \"client_button dark\";\r\n\t\tclient.selectedEvidence = evidence;\r\n\r\n\t\t// Show evidence on information window\r\n\t\tdocument.getElementById(\"evi_name\").value = client.evidences[evidence - 1].name;\r\n\t\tdocument.getElementById(\"evi_desc\").value = client.evidences[evidence - 1].desc;\r\n\r\n\t\t//Update Icon\r\n\t\tlet icon_id = getIndexFromSelect(\"evi_select\", client.evidences[evidence - 1].filename);\r\n\t\tdocument.getElementById(\"evi_select\").selectedIndex = icon_id;\r\n\t\tif (icon_id == 0) {\r\n\t\t\tdocument.getElementById(\"evi_filename\").value = client.evidences[evidence - 1].filename;\r\n\t\t}\r\n\t\tupdateEvidenceIcon();\r\n\r\n\t\t// Update button\r\n\t\tdocument.getElementById(\"evi_add\").className = \"client_button hover_button inactive\";\r\n\t\tdocument.getElementById(\"evi_edit\").className = \"client_button hover_button\";\r\n\t\tdocument.getElementById(\"evi_cancel\").className = \"client_button hover_button\";\r\n\t\tdocument.getElementById(\"evi_del\").className = \"client_button hover_button\";\r\n\t} else {\r\n\t\tcancelEvidence();\r\n\t}\r\n}\r\nwindow.pickEvidence = pickEvidence;\r\n\r\n/**\r\n * Add evidence.\r\n */\r\nexport function addEvidence() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tclient.sendPE(document.getElementById(\"evi_name\").value,\r\n\t\tdocument.getElementById(\"evi_desc\").value,\r\n\t\tevidence_select.selectedIndex == 0 ?\r\n\t\t\tdocument.getElementById(\"evi_filename\").value :\r\n\t\t\tevidence_select.options[evidence_select.selectedIndex].text\r\n\t);\r\n\tcancelEvidence();\r\n}\r\nwindow.addEvidence = addEvidence;\r\n\r\n/**\r\n * Edit selected evidence.\r\n */\r\nexport function editEvidence() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tlet id = parseInt(client.selectedEvidence) - 1;\r\n\tclient.sendEE(id,\r\n\t\tdocument.getElementById(\"evi_name\").value,\r\n\t\tdocument.getElementById(\"evi_desc\").value,\r\n\t\tevidence_select.selectedIndex == 0 ?\r\n\t\t\tdocument.getElementById(\"evi_filename\").value :\r\n\t\t\tevidence_select.options[evidence_select.selectedIndex].text\r\n\t);\r\n\tcancelEvidence();\r\n}\r\nwindow.editEvidence = editEvidence;\r\n\r\n/**\r\n * Delete selected evidence.\r\n */\r\nexport function deleteEvidence() {\r\n\tlet id = parseInt(client.selectedEvidence) - 1;\r\n\tclient.sendDE(id);\r\n\tcancelEvidence();\r\n}\r\nwindow.deleteEvidence = deleteEvidence;\r\n\r\n/**\r\n * Cancel evidence selection.\r\n */\r\nexport function cancelEvidence() {\r\n\t//Clear evidence data\r\n\tif (client.selectedEvidence > 0) {\r\n\t\tdocument.getElementById(\"evi_\" + client.selectedEvidence).className = \"client_button\";\r\n\t}\r\n\tclient.selectedEvidence = 0;\r\n\r\n\t// Clear evidence on information window\r\n\tdocument.getElementById(\"evi_select\").selectedIndex = 0;\r\n\tupdateEvidenceIcon(); // Update icon widget\r\n\tdocument.getElementById(\"evi_filename\").value = \"\";\r\n\tdocument.getElementById(\"evi_name\").value = \"\";\r\n\tdocument.getElementById(\"evi_desc\").value = \"\";\r\n\tdocument.getElementById(\"evi_icon\").style.backgroundImage = \"url('misc/empty.png')\"; //Clear icon\r\n\r\n\t// Update button\r\n\tdocument.getElementById(\"evi_add\").className = \"client_button hover_button\";\r\n\tdocument.getElementById(\"evi_edit\").className = \"client_button hover_button inactive\";\r\n\tdocument.getElementById(\"evi_cancel\").className = \"client_button hover_button inactive\";\r\n\tdocument.getElementById(\"evi_del\").className = \"client_button hover_button inactive\";\r\n}\r\nwindow.cancelEvidence = cancelEvidence;\r\n\r\n/**\r\n * Find index of anything in select box.\r\n * @param {string} select_box the select element name\r\n * @param {string} value the value that need to be compared\r\n */\r\nexport function getIndexFromSelect(select_box, value) {\r\n\t//Find if icon alraedy existed in select box\r\n\tconst select_element = document.getElementById(select_box);\r\n\tfor (let i = 1; i < select_element.length; ++i) {\r\n\t\tif (select_element.options[i].value == value) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\nwindow.getIndexFromSelect = getIndexFromSelect;\r\n\r\n/**\r\n * Update evidence icon.\r\n */\r\nexport function updateEvidenceIcon() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tlet evidence_filename = document.getElementById(\"evi_filename\");\r\n\tlet evidence_iconbox = document.getElementById(\"evi_icon\");\r\n\r\n\tif (evidence_select.selectedIndex === 0) {\r\n\t\tevidence_filename.style.display = \"initial\";\r\n\t\tevidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_filename.value.toLowerCase()})`;\r\n\t} else {\r\n\t\tevidence_filename.style.display = \"none\";\r\n\t\tevidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_select.value.toLowerCase()})`;\r\n\t}\r\n}\r\nwindow.updateEvidenceIcon = updateEvidenceIcon;\r\n\r\n/**\r\n * Update evidence icon.\r\n */\r\nexport function updateActionCommands(side) {\r\n\tif (side == \"jud\") {\r\n\t\tdocument.getElementById(\"judge_action\").style.display = \"inline-table\";\r\n\t\tdocument.getElementById(\"no_action\").style.display = \"none\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"no_action\").style.display = \"inline-table\";\r\n\t\tdocument.getElementById(\"judge_action\").style.display = \"none\";\r\n\t}\r\n\t//Update role selector\r\n\tfor (let i = 0, role_select = document.getElementById(\"role_select\").options; i < role_select.length; i++) {\r\n\t\tif (side == role_select[i].value) {\r\n\t\t\trole_select.selectedIndex = i;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\nwindow.updateActionCommands = updateActionCommands;\r\n\r\n/**\r\n * Change background via OOC.\r\n */\r\nexport function changeBackgroundOOC() {\r\n\tlet filename = \"\",\r\n\t\tbackground_select = document.getElementById(\"bg_select\"),\r\n\t\tbg_command = document.getElementById(\"bg_command\").value;\r\n\tif (background_select.selectedIndex == 0) {\r\n\t\tfilename = document.getElementById(\"bg_filename\").value;\r\n\t} else {\r\n\t\tfilename = background_select.value;\r\n\t}\r\n\tclient.sendOOC(\"/\" + bg_command.replace(\"$1\", filename));\r\n}\r\nwindow.changeBackgroundOOC = changeBackgroundOOC;\r\n\r\n/**\r\n * Change role via OOC.\r\n */\r\nexport function changeRoleOOC() {\r\n\tlet role_select = document.getElementById(\"role_select\"),\r\n\t\trole_command = document.getElementById(\"role_command\").value;\r\n\r\n\tclient.sendOOC(\"/\" + role_command.replace(\"$1\", role_select.value));\r\n\tupdateActionCommands(role_select.value);\r\n}\r\nwindow.changeRoleOOC = changeRoleOOC;\r\n\r\n/**\r\n * Random character via OOC.\r\n */\r\nexport function randomCharacterOOC() {\r\n\tclient.sendOOC(\"/\" + document.getElementById(\"randomchar_command\").value);\r\n}\r\nwindow.randomCharacterOOC = randomCharacterOOC;\r\n\r\n/**\r\n * Call mod.\r\n */\r\nexport function callMod() {\r\n\t$(\"#callmod_dialog\").dialog(\"open\");\r\n}\r\nwindow.callMod = callMod;\r\n\r\n/**\r\n * Declare witness testimony.\r\n */\r\nexport function initWT() {\r\n\tclient.sendRT(\"testimony1\");\r\n}\r\nwindow.initWT = initWT;\r\n\r\n/**\r\n * Declare cross examination.\r\n */\r\nexport function initCE() {\r\n\tclient.sendRT(\"testimony2\");\r\n}\r\nwindow.initCE = initCE;\r\n\r\n/**\r\n * Increment defense health point.\r\n */\r\nexport function addHPD() {\r\n\tclient.sendHP(1, String(parseInt(client.hp[0]) + 1));\r\n}\r\nwindow.addHPD = addHPD;\r\n\r\n/**\r\n * Decrement defense health point.\r\n */\r\nexport function redHPD() {\r\n\tclient.sendHP(1, String(parseInt(client.hp[0]) - 1));\r\n}\r\nwindow.redHPD = redHPD;\r\n\r\n/**\r\n * Increment prosecution health point.\r\n */\r\nexport function addHPP() {\r\n\tclient.sendHP(2, String(parseInt(client.hp[1]) + 1));\r\n}\r\nwindow.addHPP = addHPP;\r\n\r\n/**\r\n * Decrement prosecution health point.\r\n */\r\nexport function redHPP() {\r\n\tclient.sendHP(2, String(parseInt(client.hp[1]) - 1));\r\n}\r\nwindow.redHPP = redHPP;\r\n\r\n/**\r\n * Update background preview.\r\n */\r\nexport function updateBackgroundPreview() {\r\n\tlet background_select = document.getElementById(\"bg_select\");\r\n\tlet background_filename = document.getElementById(\"bg_filename\");\r\n\tlet background_preview = document.getElementById(\"bg_preview\");\r\n\r\n\tif (background_select.selectedIndex == 0) {\r\n\t\tbackground_filename.style.display = \"initial\";\r\n\t\tbackground_preview.src = AO_HOST + \"background/\" + background_filename.value.toLowerCase() + \"/defenseempty.png\";\r\n\t} else {\r\n\t\tbackground_filename.style.display = \"none\";\r\n\t\tbackground_preview.src = AO_HOST + \"background/\" + background_select.value.toLowerCase() + \"/defenseempty.png\";\r\n\t}\r\n}\r\nwindow.updateBackgroundPreview = updateBackgroundPreview;\r\n\r\n/**\r\n * Highlights and selects an effect for in-character chat.\r\n * If the same effect button is selected, then the effect is canceled.\r\n * @param {string} effect the new effect to be selected\r\n */\r\nexport function toggleEffect(effect) {\r\n\tif (effect == selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button dark\";\r\n\t\tif (selectedEffect) {\r\n\t\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedEffect = effect;\r\n\t}\r\n}\r\nwindow.toggleEffect = toggleEffect;\r\n\r\n/**\r\n * Toggle flip for in-character chat.\r\n */\r\nexport function toggleFlip() {\r\n\tif (client.flip) {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button dark\";\r\n\t}\r\n\tclient.flip = !client.flip;\r\n}\r\nwindow.toggleFlip = toggleFlip;\r\n\r\n/**\r\n * Toggle presentable for presenting evidence in-character chat.\r\n */\r\nexport function togglePresent() {\r\n\tif (client.presentable) {\r\n\t\tdocument.getElementById(\"button_present\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_present\").className = \"client_button dark\";\r\n\t}\r\n\tclient.presentable = !client.presentable;\r\n}\r\nwindow.togglePresent = togglePresent;\r\n\r\n/**\r\n * Highlights and selects a menu.\r\n * @param {string} menu the menu to be selected\r\n */\r\nexport function toggleMenu(menu) {\r\n\tif (menu != selectedMenu) {\r\n\t\tdocument.getElementById(\"menu_\" + menu).className = \"menu_icon active\";\r\n\t\tdocument.getElementById(\"content_\" + menu).className = \"menu_content active\";\r\n\t\tdocument.getElementById(\"menu_\" + selectedMenu).className = \"menu_icon\";\r\n\t\tdocument.getElementById(\"content_\" + selectedMenu).className = \"menu_content\";\r\n\t\tselectedMenu = menu;\r\n\t}\r\n}\r\nwindow.toggleMenu = toggleMenu;\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, \"&\")\r\n\t\t.replace(//g, \">\")\r\n\t\t.replace(/\"/g, \""\")\r\n\t\t.replace(/'/g, \"'\");\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, \"\")\r\n\t\t.replace(/&/g, \"\")\r\n\t\t.replace(/%/g, \"\")\r\n\t\t.replace(/\\$/g, \"\");\r\n}\r\n\r\n/**\r\n * Unescapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be unescaped\r\n */\r\nfunction unescapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(//g, \"#\")\r\n\t\t.replace(//g, \"&\")\r\n\t\t.replace(//g, \"%\")\r\n\t\t.replace(//g, \"$\");\r\n}\r\n\r\n/**\r\n * Encode text on client side.\r\n * @param {string} estring the string to be encoded\r\n */\r\nfunction encodeChat(estring) {\r\n\tlet selectedEncoding = document.getElementById(\"client_encoding\").value;\r\n\tif (selectedEncoding == \"unicode\") {\r\n\t\t// This approach works by escaping all special characters to Unicode escape sequences.\r\n\t\t// Source: https://gist.github.com/mathiasbynens/1243213\r\n\t\treturn estring.replace(/[^\\0-~]/g, function (ch) {\r\n\t\t\treturn \"\\\\u\" + (\"000\" + ch.charCodeAt().toString(16)).slice(-4);\r\n\t\t});\r\n\t} else if (selectedEncoding == \"utf16\") {\r\n\t\t// Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\r\n\t\tconst buffer = new ArrayBuffer(estring.length * 2);\r\n\t\tconst result = new Uint16Array(buffer);\r\n\t\tfor (let i = 0, strLen = estring.length; i < strLen; i++) {\r\n\t\t\tresult[i] = estring.charCodeAt(i);\r\n\t\t}\r\n\t\treturn String(result);\r\n\t} else {\r\n\t\treturn estring;\r\n\t}\r\n}\r\n\r\n/**\r\n * Decodes text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeChat(estring) {\r\n\tlet selectedDecoding = document.getElementById(\"client_decoding\").value;\r\n\tif (selectedDecoding == \"unicode\") {\r\n\t\t// Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode\r\n\t\treturn estring.replace(/\\\\u([\\d\\w]{1,})/gi, function (match, group) {\r\n\t\t\treturn String.fromCharCode(parseInt(group, 16));\r\n\t\t});\r\n\t} else if (selectedDecoding == \"utf16\") {\r\n\t\t// Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\r\n\t\treturn String.fromCharCode.apply(null, new Uint16Array(estring.split(\",\")));\r\n\t} else {\r\n\t\treturn estring;\r\n\t}\r\n}\r\n\r\n/**\r\n * Decoding text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeBBCode(estring) {\r\n\treturn estring\r\n\t\t.replace(/\\\\n/g, \"
\") // Newline \\n\r\n\t\t.replace(/\\[(\\/?)b\\]/g, \"<$1b>\") // Bold [b][/b]\r\n\t\t.replace(/\\[(\\/?)i\\]/g, \"<$1i>\") // Italic [i][/i]\r\n\t\t.replace(/\\[(\\/?)s\\]/g, \"<$1del>\") // Strikethrough [s][/s]\r\n\t\t.replace(/\\[(\\/?)u\\]/g, \"<$1u>\") // Underline [u][/u]\r\n\t\t.replace(/\\[(\\/?)sub\\]/g, \"<$1sub>\") // Subscript [sub][/sub]\r\n\t\t.replace(/\\[(\\/?)sup\\]/g, \"<$1sup>\") // Superscript [sup][/sup]\r\n\t\t.replace(/\\[m=([#a-zA-Z0-9]+)\\]/g, \"\") // Markup [m=#0ff]\r\n\t\t.replace(/\\[(\\/?)m\\]/g, \"<$1m>\") // [m][/m]\r\n\t\t.replace(/\\[c=?([#a-zA-Z0-9]+)\\]/g, \"\") // Color [c=red]\r\n\t\t.replace(/\\[\\/c\\]/g, \"\"); // [/c]\r\n}\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\tString.prototype.trim = function () {\r\n\t\treturn String(this).replace(/^\\s+|\\s+$/g, \"\");\r\n\t};\r\n}\r\n\r\n// Used for HDID calculation.\r\nString.prototype.hashCode = function () {\r\n\tlet hash = 0;\r\n\tif (this.length === 0) return hash;\r\n\tfor (let i = 0; i < this.length; i++) {\r\n\t\tconst chr = this.charCodeAt(i);\r\n\t\thash = ((hash << 5) - hash) + chr;\r\n\t\thash |= 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\r\n$(document).ready(function () {\r\n\tclient.initialObservBBCode();\r\n\tclient.loadResources();\r\n});\r\n\r\n// Create dialog and link to button\t\r\n$(function () {\r\n\t$(\"#callmod_dialog\").dialog({\r\n\t\tautoOpen: false,\r\n\t\tresizable: false,\r\n\t\tshow: {\r\n\t\t\teffect: \"drop\",\r\n\t\t\tdirection: \"down\",\r\n\t\t\tduration: 500\r\n\t\t},\r\n\t\thide: {\r\n\t\t\teffect: \"drop\",\r\n\t\t\tdirection: \"down\",\r\n\t\t\tduration: 500\r\n\t\t},\r\n\t\theight: \"auto\",\r\n\t\twidth: 400,\r\n\t\tmodal: true,\r\n\t\tbuttons: {\r\n\t\t\tSure: function () {\r\n\t\t\t\tclient.sendZZ(\"\");\r\n\t\t\t\t$(this).dialog(\"close\");\r\n\t\t\t},\r\n\t\t\tCancel: function () {\r\n\t\t\t\t$(this).dialog(\"close\");\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n});"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./webAO/evidence.js","webpack:///./webAO/backgrounds.js","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","area_click","changeMusicVolume","changeSFXVolume","changeBlipVolume","changeCharacter","imgError","demoError","ReconnectButton","RetryButton","pickChar","pickEmotion","pickEvidence","addEvidence","editEvidence","deleteEvidence","cancelEvidence","getIndexFromSelect","updateEvidenceIcon","updateActionCommands","changeBackgroundOOC","changeRoleOOC","randomCharacterOOC","callMod","initWT","initCE","addHPD","redHPD","addHPP","redHPP","updateBackgroundPreview","toggleEffect","toggleFlip","togglePresent","toggleMenu","toggleShout","queryDict","location","search","substr","split","forEach","item","serverIP","ip","mode","AO_HOST","asset","MUSIC_HOST","oldLoading","test","navigator","userAgent","selectedEffect","selectedMenu","selectedShout","lastICMessageTime","Date","Client","address","_this","this","_classCallCheck","serv","WebSocket","onopen","evt","onOpen","onclose","onClose","onmessage","onMessage","onerror","onError","flip","presentable","hp","playerID","charID","testimonyID","chars","emotes","evidences","resources","holdit","src","duration","objection","takethat","witnesstestimony","sfx","crossexamination","selectedEmote","selectedEvidence","checkUpdater","musicList","handlers","MS","args","handleMS","CT","handleCT","MC","handleMC","RMC","handleRMC","CI","handleCI","SC","handleSC","EI","handleEI","LE","handleLE","EM","handleEM","SM","handleSM","music","handlemusic","DONE","handleDONE","BN","handleBN","NBG","handleNBG","HP","handleHP","RT","handleRT","ZZ","handleZZ","ID","handleID","PN","handlePN","SI","handleSI","CharsCheck","handleCharsCheck","PV","handlePV","CHECK","_lastTimeICReceived","message","send","escapeChat","encodeChat","document","getElementById","speaking","silent","side","ssfxname","zoom","ssfxdelay","evidence","flash","color","desc","img","id","msg","testimony","track","_this2","hashCode","setInterval","sendCheck","evidence_select","add","Option","evidence_arr","background_select","background_arr","background","shouts","length","fileExists","toLowerCase","callbackLoadImageResources","callbackLoadSFXResources","result","resource","client","viewport","getAnimLength","callbackGetResourceLength","target","MutationObserver","mutations","mutation","children","addedNodes","node","tagName","style","getAttribute","hasAttribute","backgroundColor","observe","attributes","childList","character","song","e","display","joinServer","console","error","reason","code","textContent","cleanup","data","debug","header","handler","warn","close","clearInterval","unescapeChat","decodeChat","replace","chatmsg","content","innerHTML","preanim","escape","nameplate","prepChat","sound","type","snddelay","isnew","className","resetICParams","say","oocLog","scrollTop","scrollHeight","pause","play","appendICLog","Audio","totime","offset","getTime","addEventListener","currentTime","parseFloat","toFixed","chargs","icon","arg","filename","evidence_box","hmusiclist","newentry","createElement","text","options","flagAudio","newarea","onclick","appendChild","area_box","lastChild","startsWith","audio_title","insertBefore","firstChild","removeChild","bgname","bg_index","selectedIndex","changeBackground","percent_hp","$","animate","width","initTestimonyUpdater","tr","td","icon_chosen","thispick","me","emotesList","xhr","XMLHttpRequest","withCredentials","open","responseType","onload","status","linifile","responseText","pinifile","INI","parse","Options","Emotions","number","emoteinfo","esfx","esfxd","SoundN","SoundT","sfxdelay","button_off","button_on","Viewport","textnow","startpreanim","startspeaking","preanimdelay","blip","volume","blipChannels","Array","currentBlipChannel","sfxaudio","sfxplayed","updater","testimonyUpdater","testimonyTimer","shoutTimer","textTimer","_animating","clearTimeout","initUpdater","animdelay","parseInt","setTimeout","updateText","_this3","testimonyOverlay","updateTestimony","callback","param","request","gifInfo","gify","getInfo","response","log","_this4","disposeTestimony","_this5","nameBox","chatBox","charSprite","eviBox","shoutSprite","chatBoxInner","transform","opacity","height","shout","1","2","3","effect","direction","backgroundImage","right","left","fontSize","offsetHeight","hasChildNodes","createTextNode","0","4","5","6","charAt","substring","regex","section","comment","line","match","event","keyCode","sendOOC","mychar","myemo","myEmote","myevi","myEvidence","myflip","mycolor","checked","sendIC","playtrack","sendMusicChange","el","area","areaHr","setBlipVolume","sendLeaveRoom","image","url","xhttp","onreadystatechange","readyState","position","standname","bgfolder","bgFolder","callbackChangeBackground","toadd","arguments","undefined","time","entry","nameField","getMinutes","timeStamp","innerText","toLocaleTimeString","hour","minute","clientLog","ccharacter","sendCharacter","emo","icon_id","sendPE","sendEE","sendDE","select_box","select_element","evidence_filename","evidence_iconbox","role_select","bg_command","role_command","dialog","sendRT","sendHP","String","background_filename","background_preview","menu","estring","selectedEncoding","ch","charCodeAt","toString","slice","buffer","ArrayBuffer","Uint16Array","strLen","selectedDecoding","group","fromCharCode","apply","window","trim","hash","ready","initialObservBBCode","loadResources","autoOpen","resizable","show","hide","modal","buttons","Sure","sendZZ","Cancel"],"mappings":"aACA,IAAAA,KAGA,SAAAC,EAAAC,GAGA,GAAAF,EAAAE,GACA,OAAAF,EAAAE,GAAAC,QAGA,IAAAC,EAAAJ,EAAAE,IACAG,EAAAH,EACAI,GAAA,EACAH,YAUA,OANAI,EAAAL,GAAAM,KAAAJ,EAAAD,QAAAC,IAAAD,QAAAF,GAGAG,EAAAE,GAAA,EAGAF,EAAAD,QAKAF,EAAAQ,EAAAF,EAGAN,EAAAS,EAAAV,EAGAC,EAAAU,EAAA,SAAAR,EAAAS,EAAAC,GACAZ,EAAAa,EAAAX,EAAAS,IACAG,OAAAC,eAAAb,EAAAS,GACAK,cAAA,EACAC,YAAA,EACAC,IAAAN,KAMAZ,EAAAmB,EAAA,SAAAjB,GACAY,OAAAC,eAAAb,EAAA,cAAiDkB,OAAA,KAIjDpB,EAAAqB,EAAA,SAAAlB,GACA,IAAAS,EAAAT,KAAAmB,WACA,WAA2B,OAAAnB,EAAA,SAC3B,WAAiC,OAAAA,GAEjC,OADAH,EAAAU,EAAAE,EAAA,IAAAA,GACAA,GAIAZ,EAAAa,EAAA,SAAAU,EAAAC,GAAsD,OAAAV,OAAAW,UAAAC,eAAAnB,KAAAgB,EAAAC,IAGtDxB,EAAA2B,EAAA,GAIA3B,IAAA4B,EAAA,8FClEC,QACA,QACA,QACA,QACA,QACA,QACA,QACA,QACA,QACA,kBACA,oBACA,iBACA,kBACA,kBACA,kBACA,iBACA,kBACA,gBACA,iBACA,oBACA,oBACA,sBACA,oBACA,mBACA,iBACA,kBACA,iBACA,kBACA,oBACA,iBACA,oBACA,gBACA,kBACA,kBACA,iBACA,mBACA,oBACA,kBACA,mBACA,kBACA,oBACA,qBACA,mBACA,oBACA,mBACA,gBACA,kBACA,oBACA,kBACA,qBACA,qBACA,sBACA,uBACA,sBACA,oBACA,qBACA,uBACA,wBACA,mBACA,oBACA,wBACA,yBACA,wBACA,oBACA,qBACA,sBACA,qBACA,qBACA,sBACA,uBACA,qBACA,oBACA,qBACA,wBACA,qBACA,oBACA,cACA,kBACA,eACA,kBACA,eACA,iBACA,gBACA,eACA,gBACA,cACA,eACA,gBACA,eACA,gBACA,cACA,cACA,cACA,eACA,eACA,eACA,eACA,iBACA,iBACA,kBACA,gBACA,eACA,mBACA,kBACA,mBACA,mBACA,kBACA,mBACA,kBACA,mBACA,mBACA,oBACA,kBACA,uBACA,wBACA,qBACA,sBACA,mBACA,mBACA,iBACA,kBACA,mBACA,kBACA,kBACA,oBACA,qBACA,mBACA,iBACA,qBACA,mBACA,sBACA,mBACA,oBACA,kBACA,iBACA,kBACA,cACA,YACA,aACA,aACA,eACA,eACA,gBACA,iBACA,iBACA,iBACA,aACA,iBACA,cACA,eACA,eACA,eACA,eACA,cACA,eACA,eACA,eACA,eACA,sBACA,uBACA,aACA,eACA,cACA,gBACA,cACA,gBACA,oBACA,cACA,cACA,eACA,eACA,iBACA,kBACA,mBACA,cACA,oBACA,aACA,cACA,cACA,mBACA,aACA,cACA,aACA,aACA,cACA,cACA,cACA,cACA,eACA,gBACA,gBACA,gBACA,gBACA,iBACA,qBACA,iBACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,aACA,iBACA,kBACA,iBACA,kBACA,eACA,gBACA,gBACA,eACA,gBACA,gBACA,gBACA,gBACA,sBACA,iBACA,cACA,eACA,oBACA,gBACA,iBACA,iBACA,gBACA,eACA,eACA,eACA,eACA,gBACA,iBACA,iBACA,iBACA,iBACA,eACA,gBACA,cACA,qBACA,sBACA,sBACA,eACA,mBACA,gBACA,cACA,iBACA,kBACA,gBACA,gBACA,mBACA,aACA,cACA,cACA,eACA,gBACA,eACA,gBACA,cACA,aACA,cACA,cACA,cACA,cACA,aACA,cACA,cACA,cACA,iBACA,oBACA,0BACA,oBACA,oBACA,cACA,oBACA,cACA,YACA,kBACA,eACA,YACA,gBACA,eACA,kBACA,gBACA,eACA,gBACA,gBACA,gBACA,iBACA,cACA,eACA,eACA,iBACA,kBACA,iBACA,kBACA,sBACA,gBACA,iBACA,gBACA,iBACA,aACA,cACA,cACA,cACA,sBACA,iBACA,kBACA,cACA,eACA,eACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,cACA,eACA,cACA,eACA,cACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,mBACA,aACA,cACA,oBACA,eACA,gBACA,aACA,cACA,cACA,kBACA,oBACA,qBACA,qBACA,gBACA,aACA,cACA,cACA,cACA,cACA,cACA,eACA,eACA,gBACA,kBACA,mBACA,mBACA,mBACA,iBACA,mBACA,gBACA,oBACA,qBACA,qBACA,qBACA,oBACA,kBACA,oBACA,qBACA,iBACA,kBACA,kBACA,oBACA,iBACA,kBACA,kBACA,qBACA,qBACA,kBACA,kBACA,mBACA,oBACA,iBACA,oBACA,kBACA,gBACA,WACA,YACA,YACA,YACA,YACA,gBACA,cACA,aACA,eACA,aACA,YACA,iBACA,eACA,eACA,mBACA,qBACA,sBACA,sBACA,sBACA,sBACA,sBACA,eACA,aACA,cACA,cACA,cACA,cACA,aACA,aACA,cACA,cACA,eACA,cACA,cACA,cACA,eACA,gBACA,gBACA,iBACA,0BACA,cACA,oBACA,eACA,YACA,aACA,aACA,WACA,YACA,YACA,cACA,aACA,eACA,gBACA,iBACA,YACA,aACA,aACA,aACA,eACA,cACA,cACA,YACA,mBACA,aACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,SACA,iBACA,kBACA,kBACA,kBACA,gBACA,iBACA,iBACA,cACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,oBACA,mBACA,aACA,cACA,cACA,cACA,eACA,eACA,iBACA,cACA,gBACA,eACA,gBACA,gBACA,cACA,oBACA,aACA,aACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,sBACA,uBACA,uBACA,uBACA,uBACA,uBACA,uBACA,uBACA,uBACA,uBACA,uBACA,iBACA,gBACA,cACA,oBACA,mBACA,oBACA,oBACA,mBACA,iBACA,uBACA,oBACA,iBACA,mBACA,oBACA,mBACA,iBACA,mBACA,kBACA,sBACA,mBACA,oBACA,qBACA,oBACA,mBACA,oBACA,kBACA,kBACA,kBACA,sBACA,kBACA,oBACA,iBACA,kBACA,kBACA,oBACA,gBACA,kBACA,kBACA,mBACA,kBACA,mBACA,mBACA,wBACA,oBACA,mBACA,oBACA,qBACA,oBACA,mBACA,kBACA,iBACA,mBACA,oBACA,qBACA,cACA,eACA,YACA,aACA,YACA,aACA,cACA,cACA,cACA,aACA,cACA,cACA,cACA,cACA,aACA,YACA,aACA,aACA,aACA,iBACA,eACA,gBACA,mBACA,iBACA,eACA,gBACA,gBACA,aACA,WACA,cACA,aACA,cACA,cACA,cACA,aACA,cACA,iBACA,gBACA,iBACA,iBACA,aACA,cACA,cACA,kBACA,aACA,cACA,cACA,YACA,gBACA,eACA,iBACA,oBACA,0BACA,aACA,eACA,aACA,cACA,YACA,aACA,kBACA,kBACA,YACA,mBACA,YACA,aACA,aACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,cACA,eACA,gBACA,gBACA,gBACA,iBACA,kBACA,YACA,aACA,aACA,aACA,aACA,aACA,aACA,aACA,aACA,cACA,cACA,cACA,aACA,iBACA,kBACA,kBACA,aACA,cACA,cACA,cACA,cACA,cACA,cACA,cACA,eACA,eACA,gBACA,cACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,cACA,eACA,gBACA,gBACA,eACA,iBACA,uBACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,aACA,cACA,cACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,cACA,eACA,aACA,aACA,cACA,cACA,gBACA,eACA,mBACA,mBACA,mBACA,qBACA,wBACA,sBACA,kBACA,mBACA,qBACA,oBACA,sBACA,uBACA,mBACA,qBACA,oBACA,kBACA,kBACA,oBACA,uBACA,sBACA,uBACA,qBACA,mBACA,sBACA,iBACA,kBACA,qBACA,wBACA,oBACA,uBACA,oBACA,qBACA,oBACA,mBACA,oBACA,qBACA,oBACA,oBACA,eACA,aACA,cACA,cACA,eACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,gBACA,cACA,cACA,cACA,eACA,eACA,eACA,cACA,gBACA,gBACA,cACA,eACA,eACA,eACA,gBACA,iBACA,aACA,cACA,cACA,mBACA,eACA,gBACA,gBACA,gBACA,aACA,cACA,cACA,kBACA,mBACA,mBACA,mBACA,oBACA,oBACA,oBACA,qBACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,UACA,gBACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,aACA,cACA,cACA,kBACA,oBACA,eACA,qBACA,sBACA,eACA,eACA,gBACA,cACA,cACA,gBACA,kBACA,oBACA,iBACA,iBACA,iBACA,qBACA,sBACA,oBACA,uBACA,uBACA,kBACA,mBACA,iBACA,kBACA,oBACA,kBACA,kBACA,iBACA,oBACA,mBACA,oBACA,oBACA,oBACA,wBACA,kBACA,mBACA,mBACA,oBACA,cACA,eACA,cACA,eACA,eACA,gBACA,aACA,cACA,sBACA,uBACA,gBACA,iBACA,iBACA,gBACA,cACA,eACA,cACA,eACA,eACA,eACA,cACA,2BACA,iBACA,eACA,gBACA,gBACA,aACA,cACA,iBACA,aACA,eACA,aACA,eACA,gBACA,cACA,cACA,eACA,eACA,cACA,eACA,gBACA,eACA,gBACA,iBACA,gBACA,cACA,cACA,mBACA,eACA,gBACA,cACA,mBACA,gBACA,iBACA,iBACA,qBACA,qBACA,eACA,iBACA,cACA,cACA,cACA,cACA,eACA,qBACA,iBACA,gBACA,mBACA,qBACA,0BACA,oBACA,kBACA,uBACA,oBACA,oBACA,qBACA,oBACA,gBACA,4BACA,qBACA,oBACA,oBACA,wBACA,oBACA,0BACA,mBACA,mBACA,mBACA,mBACA,wBACA,kBACA,wBACA,sBACA,eACA,yBACA,cACA,gBACA,iBACA,cACA,YACA,aACA,aACA,aACA,aACA,aACA,aACA,eACA,iBACA,eACA,gBACA,eACA,gBACA,eACA,gBACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,aACA,cACA,kBACA,gBACA,gBACA,oBACA,qBACA,qBACA,mBACA,mBACA,2BACA,oBACA,oBACA,mBACA,oBACA,qBACA,sBACA,mBACA,wBACA,mBACA,mBACA,kBACA,kBACA,mBACA,oBACA,mBACA,mBACA,iBACA,oBACA,mBACA,kBACA,kBACA,mBACA,qBACA,mBACA,mBACA,mBACA,qBACA,oBACA,oBACA,mBACA,oBACA,kBACA,kBACA,oBACA,sBACA,mBACA,qBACA,mBACA,mBACA,mBACA,YACA,aACA,eACA,cACA,eACA,aACA,kBACA,aACA,cACA,gBACA,eACA,eACA,eACA,aACA,iBACA,cACA,aACA,oBACA,eACA,gBACA,aACA,cACA,cACA,cACA,iBACA,kBACA,iBACA,kBACA,iBACA,kBACA,mBACA,mBACA,aACA,cACA,cACA,cACA,cACA,cACA,cACA,eACA,cACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,aACA,kBACA,iBACA,eACA,eACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,gBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,WACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,iBACA,qBACA,kBACA,qBACA,gBACA,iBACA,iBACA,eACA,gBACA,iBACA,eACA,gBACA,iBACA,eACA,cACA,iBACA,aACA,aACA,gBACA,gBACA,mBACA,sBACA,kBACA,mBACA,kBACA,oBACA,mBACA,qBACA,oBACA,kBACA,gBACA,kBACA,mBACA,kBACA,sBACA,oBACA,iBACA,kBACA,iBACA,iBACA,mBACA,kBACA,gBACA,oBACA,kBACA,oBACA,kBACA,WACA,YACA,cACA,cACA,YACA,eACA,eACA,gBACA,gBACA,YACA,aACA,eACA,iBACA,eACA,aACA,WACA,YACA,aACA,cACA,cACA,cACA,cACA,mBACA,oBACA,YACA,aACA,cACA,cACA,cACA,gBACA,eACA,iBACA,cACA,cACA,aACA,cACA,eACA,gBACA,cACA,gBACA,iBACA,iBACA,kBACA,kBACA,mBACA,iBACA,kBACA,cACA,iBACA,aACA,cACA,cACA,cACA,cACA,cACA,cACA,gBACA,iBACA,iBACA,cACA,qBACA,sBACA,sBACA,eACA,gBACA,aACA,cACA,cACA,eACA,eACA,cACA,eACA,eACA,gBACA,iBACA,aACA,cACA,cACA,cACA,eACA,cACA,eACA,YACA,6GCvyCA,aACA,QACA,MACA,eACA,sBACA,WACA,YACA,WACA,mBACA,YACA,WACA,iBACA,YACA,YACA,cACA,aACA,aACA,eACA,YACA,WACA,eACA,WACA,aACA,oBACA,oBACA,mBACA,yBACA,iBACA,sBACA,kBACA,2BACA,mBACA,mBACA,cACA,kBACA,wBACA,sBACA,oBACA,YACA,uBACA,aACA,UACA,eACA,8BACA,yBACA,YACA,mBACA,qBACA,oBACA,oBACA,eACA,mBACA,sBACA,sBACA,cACA,oBACA,aACA,WACA,gBACA,iBACA,iBACA,oBACA,UACA,aACA,sBACA,WACA,kBACA,qBACA,wBACA,2BACA,kBACA,UACA,eACA,kBACA,iBACA,iBACA,oBACA,UACA,kBACA,mBACA,eACA,YACA,mBACA,oBACA,eACA,gBACA,kBACA,iBACA,UACA,mBACA,eACA,qBACA,iBACA,MACA,cACA,aACA,gBACA,QACA,SACA,gBACA,cACA,eACA,mBACA,cACA,cACA,eACA,WACA,gBACA,oBACA,WACA,gBACA,aACA,aACA,OACA,WACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,MACA,OACA,OACA,OACA,gBACA,iBACA,mBACA,iBACA,kBACA,uBACA,kBACA,KACA,cACA,kBACA,cACA,cACA,aACA,aACA,aACA,aACA,aACA,cACA,OACA,YACA,aACA,MACA,eACA,SACA,cACA,iBACA,YACA,sBACA,gBACA,YACA,eACA,eACA,kBACA,iBACA,eACA,wBACA,cACA,cACA,gBACA,eACA,cACA,mBACA,iBACA,kBACA,cACA,mBACA,eACA,kBACA,kBACA,kBACA,iBACA,cACA,cACA,eACA,gBACA,aACA,aACA,iBACA,aACA,YACA,cACA,YACA,YACA,iBACA,cACA,eACA,YACA,KACA,UACA,cACA,gBACA,6BACA,gBACA,mBACA,UACA,UACA,kBACA,sBACA,kBACA,gBACA,UACA,UACA,MACA,mBACA,oBACA,wBACA,4BACA,6BACA,kBACA,gBACA,YACA,kBACA,aACA,aACA,eACA,OACA,YACA,WACA,gBACA,kBACA,gBACA,mBACA,sBACA,kBACA,gBACA,gBACA,oBACA,oBACA,qBACA,aACA,oBACA,kBACA,eACA,SACA,UACA,WACA,SACA,SACA,UACA,WACA,UACA,eACA,cACA,cACA,gBACA,SACA,WACA,eACA,mBACA,mBACA,yBACA,0BACA,cACA,eACA,eACA,YACA,uBACA,oBACA,KACA,SACA,kBACA,aACA,WACA,SACA,kBACA,aACA,aACA,kBACA,oBACA,oBACA,eACA,iBACA,sBACA,WACA,cACA,iBACA,YACA,kBACA,kBACA,oBACA,aACA,wBACA,wBACA,oBACA,iBACA,mBACA,eACA,gBACA,kBACA,oBACA,YACA,WACA,UACA,aACA,cACA,mBACA,WACA,SACA,iBACA,QACA,YACA,UACA,iBACA,qBACA,mBACA,sBACA,6BACA,kCACA,0BACA,2BACA,uBACA,wBACA,0BACA,0BACA,iBACA,mBACA,wBACA,iCACA,6BACA,sBACA,kBACA,mBACA,0BACA,mBACA,gBACA,oBACA,kBACA,kBACA,4BACA,yBACA,uBACA,cACA,qBACA,mBACA,cACA,eACA,iBACA,oBACA,eACA,wBACA,sBACA,iBACA,gBACA,cACA,iBACA,oBACA,UACA,cACA,YACA,yBACA,aACA,SACA,WACA,aACA,eACA,yBACA,aACA,aACA,WACA,QACA,WACA,eACA,gBACA,gBACA,sBACA,WACA,UACA,cACA,gBACA,gBACA,iBACA,0BACA,kBACA,oBACA,aACA,eACA,mBACA,gBACA,eACA,YACA,aACA,SACA,eACA,eACA,cACA,gBACA,gBACA,gBACA,QACA,mBACA,cACA,SACA,cACA,WACA,cACA,aACA,YACA,eACA,UACA,UACA,UACA,WACA,aACA,aACA,iBACA,WACA,WACA,YACA,YACA,YACA,aACA,WACA,UACA,eACA,QACA,gBACA,UACA,uBACA,kBACA,eACA,qBACA,yBACA,mBACA,8BACA,kCACA,sBACA,eACA,qBACA,yBACA,yBACA,eACA,oBACA,cACA,yBACA,cACA,iBACA,SACA,YACA,eACA,cACA,oBACA,aACA,kBACA,gBACA,YACA,kBACA,aACA,WACA,iBACA,qBACA,WACA,cACA,eACA,iBACA,eACA,iBACA,cACA,gBACA,aACA,aACA,sBACA,WACA,cACA,WACA,oBACA,kBACA,eACA,iBACA,eACA,2BACA,yBACA,aACA,eACA,aACA,UACA,YACA,aACA,OACA,YACA,uBACA,oBACA,qBACA,qBACA,qBACA,sBACA,uBACA,uBACA,uBACA,wBACA,kBACA,cACA,eACA,cACA,iBACA,cACA,eACA,qBACA,eACA,oBACA,eACA,qBACA,aACA,gBACA,gBACA,gBACA,WACA,YACA,YACA,aACA,eACA,aACA,cACA,YACA,YACA,aACA,cACA,SACA,iBACA,oBACA,WACA,cACA,MACA,UACA,WACA,oBACA,gBACA,sBACA,aACA,iBACA,kBACA,mBACA,mBACA,oBACA,gBACA,mBACA,YACA,YACA,WACA,uBACA,WACA,cACA,YACA,cACA,cACA,SACA,iBACA,wBACA,SACA,WACA,gBACA,mBACA,oBACA,mBACA,wBACA,eACA,iBACA,iBACA,aACA,iBACA,SACA,UACA,gBACA,iBACA,cACA,QACA,OACA,aACA,aACA,iBACA,aACA,aACA,oBACA,0BACA,OACA,MACA,SACA,SACA,OACA,OACA,kBACA,MACA,iBACA,UACA,mBACA,kBACA,oBACA,YACA,gBACA,gBACA,eACA,OACA,QACA,YACA,gBACA,aACA,WACA,WACA,WACA,QACA,UACA,UACA,UACA,UACA,YACA,SACA,aACA,OACA,mBACA,SACA,eACA,SACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,UACA,WACA,cACA,kBACA,UACA,oBACA,iBACA,uBACA,kBACA,UACA,aACA,kBACA,kBACA,aACA,aACA,oBACA,oBACA,gBACA,kBACA,UACA,UACA,eACA,SACA,MACA,WACA,MACA,KACA,MACA,qBACA,6BACA,0BACA,4BACA,yBACA,2BACA,uBACA,wBACA,0BACA,wBACA,SACA,SACA,eACA,eACA,kBACA,kBACA,WACA,WACA,YACA,YACA,YACA,YACA,YACA,aACA,SACA,YACA,cACA,iBACA,uBACA,cACA,mBACA,iBACA,uBACA,YACA,qBACA,iBACA,MACA,WACA,oBACA,SACA,gBACA,oBACA,iBACA,MACA,8BACA,oBACA,gCACA,sBACA,sBACA,YACA,wBACA,cACA,QACA,YACA,aACA,iBACA,cACA,YACA,aACA,yBACA,iBACA,aACA,6VCokBeC,eAYAC,YAuCAC,oBAUAC,eAcAC,sBAQAC,oBAQAC,qBASAC,oBAWAC,aAWAC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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 = 2);\n","export default [\r\n\t\"1.gif\",\r\n\t\"1.png\",\r\n\t\"2.png\",\r\n\t\"3.png\",\r\n\t\"4.png\",\r\n\t\"5.gif\",\r\n\t\"5.png\",\r\n\t\"6.gif\",\r\n\t\"6.png\",\r\n\t\"AACastApril.png\",\r\n\t\"AACastBellboy.png\",\r\n\t\"AACastButz.png\",\r\n\t\"AACastButz2.png\",\r\n\t\"AACastButz3.png\",\r\n\t\"AACastCindy.png\",\r\n\t\"AACastCody.png\",\r\n\t\"AACastDarke.png\",\r\n\t\"AACastEma.png\",\r\n\t\"AACastGant.png\",\r\n\t\"AACastGoodman.png\",\r\n\t\"AACastGregory.png\",\r\n\t\"AACastGrossberg.png\",\r\n\t\"AACastGumshoe.png\",\r\n\t\"AACastHammer.png\",\r\n\t\"AACastJake.png\",\r\n\t\"AACastJudge.png\",\r\n\t\"AACastLana.png\",\r\n\t\"AACastLotta.png\",\r\n\t\"AACastManfred.png\",\r\n\t\"AACastMaya.png\",\r\n\t\"AACastMeekins.png\",\r\n\t\"AACastMia.png\",\r\n\t\"AACastMiles.png\",\r\n\t\"AACastMisty.png\",\r\n\t\"AACastNeil.png\",\r\n\t\"AACastOldbag.png\",\r\n\t\"AACastOldbag2.png\",\r\n\t\"AACastPayne.png\",\r\n\t\"AACastPayne2.png\",\r\n\t\"AACastPenny.png\",\r\n\t\"AACastPhoenix.png\",\r\n\t\"AACastPhoenix2.png\",\r\n\t\"AACastPowers.png\",\r\n\t\"AACastPowers2.png\",\r\n\t\"AACastSahwit.png\",\r\n\t\"AACastSal.png\",\r\n\t\"AACastStarr.png\",\r\n\t\"AACastVasquez.png\",\r\n\t\"AACastWhite.png\",\r\n\t\"AAI2CastBlaise.png\",\r\n\t\"AAI2CastBonnie.png\",\r\n\t\"AAI2CastCameron.png\",\r\n\t\"AAI2CastCourtney.png\",\r\n\t\"AAI2CastDelicia.png\",\r\n\t\"AAI2CastDogen.png\",\r\n\t\"AAI2CastElbird.png\",\r\n\t\"AAI2CastGustavia.png\",\r\n\t\"AAI2CastGustavia2.png\",\r\n\t\"AAI2CastJill.png\",\r\n\t\"AAI2CastKarin.png\",\r\n\t\"AAI2CastKatherine.png\",\r\n\t\"AAI2CastKatherine2.png\",\r\n\t\"AAI2CastKnightley.png\",\r\n\t\"AAI2CastMarsh.png\",\r\n\t\"AAI2CastMaster.png\",\r\n\t\"AAI2CastMaster2.png\",\r\n\t\"AAI2CastNicole.png\",\r\n\t\"AAI2CastPierre.png\",\r\n\t\"AAI2CastRaymond.png\",\r\n\t\"AAI2CastRaymond2.png\",\r\n\t\"AAI2CastRoland.png\",\r\n\t\"AAI2CastRooke.png\",\r\n\t\"AAI2CastSahwit.png\",\r\n\t\"AAI2CastSebastian.png\",\r\n\t\"AAI2CastShelly.png\",\r\n\t\"AAI2CastSimon.png\",\r\n\t\"AAI2bag.png\",\r\n\t\"AAI2balloon.png\",\r\n\t\"AAI2bell.png\",\r\n\t\"AAI2blanket.png\",\r\n\t\"AAI2body.png\",\r\n\t\"AAI2button.png\",\r\n\t\"AAI2chess.png\",\r\n\t\"AAI2clip.png\",\r\n\t\"AAI2cuffs.png\",\r\n\t\"AAI2dog.png\",\r\n\t\"AAI2door.png\",\r\n\t\"AAI2floor.png\",\r\n\t\"AAI2gate.png\",\r\n\t\"AAI2glove.png\",\r\n\t\"AAI2gun.png\",\r\n\t\"AAI2key.png\",\r\n\t\"AAI2map.png\",\r\n\t\"AAI2map2.png\",\r\n\t\"AAI2map3.png\",\r\n\t\"AAI2note.png\",\r\n\t\"AAI2rope.png\",\r\n\t\"AAI2shovel.png\",\r\n\t\"AAI2tunnel.png\",\r\n\t\"AAI2uniform.png\",\r\n\t\"AAI2video.png\",\r\n\t\"AAI2well.png\",\r\n\t\"AAICastAkbey.png\",\r\n\t\"AAICastAlba.png\",\r\n\t\"AAICastAlba2.png\",\r\n\t\"AAICastAmano.png\",\r\n\t\"AAICastBadd.png\",\r\n\t\"AAICastBuddy.png\",\r\n\t\"AAICastButz.png\",\r\n\t\"AAICastByrne.png\",\r\n\t\"AAICastCammy.png\",\r\n\t\"AAICastDeacon.png\",\r\n\t\"AAICastDeid.png\",\r\n\t\"AAICastFranziska.png\",\r\n\t\"AAICastFranziska2.png\",\r\n\t\"AAICastGumshoe.png\",\r\n\t\"AAICastGumshoe2.png\",\r\n\t\"AAICastHuang.png\",\r\n\t\"AAICastJudge.png\",\r\n\t\"AAICastKay.png\",\r\n\t\"AAICastKay2.png\",\r\n\t\"AAICastLance.png\",\r\n\t\"AAICastLang.png\",\r\n\t\"AAICastMack.png\",\r\n\t\"AAICastMaggey.png\",\r\n\t\"AAICastManfred.png\",\r\n\t\"AAICastManny.png\",\r\n\t\"AAICastNou.png\",\r\n\t\"AAICastPalaeno.png\",\r\n\t\"AAICastPaups.png\",\r\n\t\"AAICastPortsman.png\",\r\n\t\"AAICastRhoda.png\",\r\n\t\"AAICastShihna.png\",\r\n\t\"AAICastSkye.png\",\r\n\t\"AAICastYew.png\",\r\n\t\"AAICastZinc.png\",\r\n\t\"AAIFIRE.png\",\r\n\t\"AAIad.png\",\r\n\t\"AAIad2.png\",\r\n\t\"AAIad3.png\",\r\n\t\"AAIarrow.png\",\r\n\t\"AAIbadge.png\",\r\n\t\"AAIbadger.png\",\r\n\t\"AAIbadger2.png\",\r\n\t\"AAIbadger3.png\",\r\n\t\"AAIbadger4.png\",\r\n\t\"AAIbag.png\",\r\n\t\"AAIballoon.png\",\r\n\t\"AAIbody.png\",\r\n\t\"AAIbody2.png\",\r\n\t\"AAIbody3.png\",\r\n\t\"AAIbody4.png\",\r\n\t\"AAIbody5.png\",\r\n\t\"AAIbook.png\",\r\n\t\"AAIbook2.png\",\r\n\t\"AAIbook3.png\",\r\n\t\"AAIbook4.png\",\r\n\t\"AAIboxes.png\",\r\n\t\"AAIbusinesscard.png\",\r\n\t\"AAIbusinesscard2.png\",\r\n\t\"AAIcar.png\",\r\n\t\"AAIcargo.png\",\r\n\t\"AAIcart.png\",\r\n\t\"AAIchange.png\",\r\n\t\"AAIclip.png\",\r\n\t\"AAIcravat.png\",\r\n\t\"AAIdecoration.png\",\r\n\t\"AAIdoor.png\",\r\n\t\"AAIfile.png\",\r\n\t\"AAIfile2.png\",\r\n\t\"AAIfile3.png\",\r\n\t\"AAIflowers.png\",\r\n\t\"AAIfountain.png\",\r\n\t\"AAIfountain2.png\",\r\n\t\"AAIgift.png\",\r\n\t\"AAIguitarpick.png\",\r\n\t\"AAIgun.png\",\r\n\t\"AAIgun2.png\",\r\n\t\"AAIgun3.png\",\r\n\t\"AAIhandprint.png\",\r\n\t\"AAIhat.png\",\r\n\t\"AAIhoop.png\",\r\n\t\"AAIink.png\",\r\n\t\"AAIkey.png\",\r\n\t\"AAIkey2.png\",\r\n\t\"AAIkey3.png\",\r\n\t\"AAIkey4.png\",\r\n\t\"AAIkey5.png\",\r\n\t\"AAIknife.png\",\r\n\t\"AAIknife2.png\",\r\n\t\"AAIknife3.png\",\r\n\t\"AAIknife4.png\",\r\n\t\"AAIknife5.png\",\r\n\t\"AAIlantern.png\",\r\n\t\"AAIlittlethief.png\",\r\n\t\"AAIluggage.png\",\r\n\t\"AAImoney.png\",\r\n\t\"AAInote.png\",\r\n\t\"AAInote2.png\",\r\n\t\"AAInote3.png\",\r\n\t\"AAInote4.png\",\r\n\t\"AAInote5.png\",\r\n\t\"AAInote6.png\",\r\n\t\"AAInote7.png\",\r\n\t\"AAInote8.png\",\r\n\t\"AAInote9.png\",\r\n\t\"AAInote10.png\",\r\n\t\"AAInote11.png\",\r\n\t\"AAInote12.png\",\r\n\t\"AAInote13.png\",\r\n\t\"AAInote14.png\",\r\n\t\"AAInote15.png\",\r\n\t\"AAInote16.png\",\r\n\t\"AAInote17.png\",\r\n\t\"AAIpen.png\",\r\n\t\"AAIpendant.png\",\r\n\t\"AAIpendant2.png\",\r\n\t\"AAIperfume.png\",\r\n\t\"AAIperfume2.png\",\r\n\t\"AAIphone.png\",\r\n\t\"AAIphone2.png\",\r\n\t\"AAIphone3.png\",\r\n\t\"AAIphoto.png\",\r\n\t\"AAIphoto2.png\",\r\n\t\"AAIphoto3.png\",\r\n\t\"AAIphoto4.png\",\r\n\t\"AAIplates.png\",\r\n\t\"AAIquercuswound.png\",\r\n\t\"AAIreceipt.png\",\r\n\t\"AAIsafe.png\",\r\n\t\"AAIsafe2.png\",\r\n\t\"AAIsciencekit.png\",\r\n\t\"AAIshards.png\",\r\n\t\"AAIshards2.png\",\r\n\t\"AAIshards3.png\",\r\n\t\"AAIshears.png\",\r\n\t\"AAIshirt.png\",\r\n\t\"AAIsnack.png\",\r\n\t\"AAIspear.png\",\r\n\t\"AAIspill.png\",\r\n\t\"AAIstatue.png\",\r\n\t\"AAIstatue2.png\",\r\n\t\"AAIstatue3.png\",\r\n\t\"AAIstatue4.png\",\r\n\t\"AAIsuspect.png\",\r\n\t\"AAIsword.png\",\r\n\t\"AAIsword2.png\",\r\n\t\"AAItape.png\",\r\n\t\"AAItonosamanju.png\",\r\n\t\"AAItonosamanju2.png\",\r\n\t\"AAItonosamanju3.png\",\r\n\t\"AAIvideo.png\",\r\n\t\"AAIwakasaman.png\",\r\n\t\"AAIwallet.png\",\r\n\t\"AAIwire.png\",\r\n\t\"AATHATCARD.png\",\r\n\t\"AAaffidavit.png\",\r\n\t\"AAairtube.png\",\r\n\t\"AAautopsy.png\",\r\n\t\"AAbluebadger.png\",\r\n\t\"AAbook.png\",\r\n\t\"AAbook2.png\",\r\n\t\"AAbook3.png\",\r\n\t\"AAbullet.png\",\r\n\t\"AAbullet2.png\",\r\n\t\"AAcamera.png\",\r\n\t\"AAcamera2.png\",\r\n\t\"AAcards.png\",\r\n\t\"AAclip.png\",\r\n\t\"AAclip2.png\",\r\n\t\"AAclip3.png\",\r\n\t\"AAclip4.png\",\r\n\t\"AAclip5.png\",\r\n\t\"AAdata.png\",\r\n\t\"AAdata2.png\",\r\n\t\"AAdata3.png\",\r\n\t\"AAdata4.png\",\r\n\t\"AAenvelope.png\",\r\n\t\"AAevidencelaw.png\",\r\n\t\"AAfingerprintpowder.png\",\r\n\t\"AAfirecracker.png\",\r\n\t\"AAfishingpole.png\",\r\n\t\"AAflyer.png\",\r\n\t\"AAglassshards.png\",\r\n\t\"AAglove.png\",\r\n\t\"AAgun.png\",\r\n\t\"AAhandprint.png\",\r\n\t\"AAidcard.png\",\r\n\t\"AAkey.png\",\r\n\t\"AAkeycard.png\",\r\n\t\"AAknife1.png\",\r\n\t\"AAkoptrophy.png\",\r\n\t\"AAleather.png\",\r\n\t\"AAlocker.png\",\r\n\t\"AAlocker2.png\",\r\n\t\"AAlocker3.png\",\r\n\t\"AAluminol.png\",\r\n\t\"AAluminol2.png\",\r\n\t\"AAlunch.png\",\r\n\t\"AAlunch2.png\",\r\n\t\"AAlunch3.png\",\r\n\t\"AAmagatama.png\",\r\n\t\"AAmagatama2.png\",\r\n\t\"AAmayanote.png\",\r\n\t\"AAmayoinote.png\",\r\n\t\"AAmetaldetector.png\",\r\n\t\"AAmissile.png\",\r\n\t\"AAmissile2.png\",\r\n\t\"AAmissle2.png\",\r\n\t\"AAmrmonkey.png\",\r\n\t\"AAnote.png\",\r\n\t\"AAnote2.png\",\r\n\t\"AAnote3.png\",\r\n\t\"AAnote4.png\",\r\n\t\"AAparkingticket.png\",\r\n\t\"AApassport.png\",\r\n\t\"AApassport2.png\",\r\n\t\"AAphone.png\",\r\n\t\"AAphone2.png\",\r\n\t\"AAphone3.png\",\r\n\t\"AAphone4.png\",\r\n\t\"AAphoto.png\",\r\n\t\"AAphoto2.png\",\r\n\t\"AAphoto3.png\",\r\n\t\"AAphoto4.png\",\r\n\t\"AAphoto5.png\",\r\n\t\"AAphoto6.png\",\r\n\t\"AAphoto7.png\",\r\n\t\"AAphoto8.png\",\r\n\t\"AAphoto9.png\",\r\n\t\"AAphoto10.png\",\r\n\t\"AAphoto11.png\",\r\n\t\"AApills.png\",\r\n\t\"AApills2.png\",\r\n\t\"AAplate.png\",\r\n\t\"AAplate2.png\",\r\n\t\"AApolly.png\",\r\n\t\"AAprint.png\",\r\n\t\"AAprint2.png\",\r\n\t\"AAprint3.png\",\r\n\t\"AAprint4.png\",\r\n\t\"AAprint5.png\",\r\n\t\"AAprint6.png\",\r\n\t\"AAprint7.png\",\r\n\t\"AAprint8.png\",\r\n\t\"AApsychelock.png\",\r\n\t\"AAsafe.png\",\r\n\t\"AAscarf.png\",\r\n\t\"AAscrewdriver.png\",\r\n\t\"AAscript.png\",\r\n\t\"AAscript2.png\",\r\n\t\"AAshoe.png\",\r\n\t\"AAshoe2.png\",\r\n\t\"AAspear.png\",\r\n\t\"AAstudiovan.png\",\r\n\t\"AAswitchblade.png\",\r\n\t\"AAswitchblade2.png\",\r\n\t\"AAswitchblade3.png\",\r\n\t\"AAthinker.png\",\r\n\t\"AAvase.png\",\r\n\t\"AAvase2.png\",\r\n\t\"AAvase3.png\",\r\n\t\"AAvase4.png\",\r\n\t\"AAvase5.png\",\r\n\t\"AAvideo.png\",\r\n\t\"AAvideo2.png\",\r\n\t\"AAwallet.png\",\r\n\t\"AAwiretap.png\",\r\n\t\"AJCastAlita.png\",\r\n\t\"AJCastApollo.png\",\r\n\t\"AJCastDaryan.jpg\",\r\n\t\"AJCastDaryan.png\",\r\n\t\"AJCastDrew.png\",\r\n\t\"AJCastEldoon.png\",\r\n\t\"AJCastEma.png\",\r\n\t\"AJCastKlavier.png\",\r\n\t\"AJCastKlavier2.png\",\r\n\t\"AJCastKristoph.png\",\r\n\t\"AJCastLamiroir.png\",\r\n\t\"AJCastLeTouse.png\",\r\n\t\"AJCastMachi.png\",\r\n\t\"AJCastMagnifi.png\",\r\n\t\"AJCastMeraktis.png\",\r\n\t\"AJCastOlga.png\",\r\n\t\"AJCastOlga2.png\",\r\n\t\"AJCastPayne.png\",\r\n\t\"AJCastPhoenix.png\",\r\n\t\"AJCastPlum.png\",\r\n\t\"AJCastShadi.png\",\r\n\t\"AJCastSpark.png\",\r\n\t\"AJCastStickler.png\",\r\n\t\"AJCastThalassa.png\",\r\n\t\"AJCastTrucy.gif\",\r\n\t\"AJCastTrucy.png\",\r\n\t\"AJCastValant.png\",\r\n\t\"AJCastValant2.png\",\r\n\t\"AJCastVera.png\",\r\n\t\"AJCastWinfred.png\",\r\n\t\"AJCastWocky.png\",\r\n\t\"AJCastZak.png\",\r\n\t\"AJad.png\",\r\n\t\"AJad2.png\",\r\n\t\"AJad3.png\",\r\n\t\"AJad4.png\",\r\n\t\"AJad5.png\",\r\n\t\"AJautopsy.png\",\r\n\t\"AJbadge.png\",\r\n\t\"AJbook.png\",\r\n\t\"AJbottle.png\",\r\n\t\"AJbowl.png\",\r\n\t\"AJbox.png\",\r\n\t\"AJbracelet.png\",\r\n\t\"AJbrooch.png\",\r\n\t\"AJbullet.png\",\r\n\t\"AJburntstuff.png\",\r\n\t\"AJbusinesscard.png\",\r\n\t\"AJbusinesscard2.png\",\r\n\t\"AJbusinesscard3.png\",\r\n\t\"AJbusinesscard4.png\",\r\n\t\"AJbusinesscard5.png\",\r\n\t\"AJbusinesscard6.png\",\r\n\t\"AJbutton.png\",\r\n\t\"AJcard.png\",\r\n\t\"AJcard2.png\",\r\n\t\"AJcard3.png\",\r\n\t\"AJcard4.png\",\r\n\t\"AJcard5.png\",\r\n\t\"AJcart.png\",\r\n\t\"AJclip.png\",\r\n\t\"AJclip2.png\",\r\n\t\"AJclip3.png\",\r\n\t\"AJcocoon.png\",\r\n\t\"AJdata1.png\",\r\n\t\"AJdata2.png\",\r\n\t\"AJdata3.png\",\r\n\t\"AJdevice.png\",\r\n\t\"AJdevice2.png\",\r\n\t\"AJdevice3.png\",\r\n\t\"AJearpiece.png\",\r\n\t\"AJfingerprintpowder.png\",\r\n\t\"AJframe.png\",\r\n\t\"AJgoldsnackoo.png\",\r\n\t\"AJguitar.png\",\r\n\t\"AJgun.png\",\r\n\t\"AJgun2.png\",\r\n\t\"AJgun3.png\",\r\n\t\"AJiv.png\",\r\n\t\"AJiv2.png\",\r\n\t\"AJkey.png\",\r\n\t\"AJknife.png\",\r\n\t\"AJlamp.png\",\r\n\t\"AJlocket.png\",\r\n\t\"AJluminol.png\",\r\n\t\"AJmagatama.png\",\r\n\t\"AJmap.png\",\r\n\t\"AJmap2.png\",\r\n\t\"AJmap3.png\",\r\n\t\"AJmap4.png\",\r\n\t\"AJmirror.png\",\r\n\t\"AJmixer.png\",\r\n\t\"AJmrhat.png\",\r\n\t\"AJmug.png\",\r\n\t\"AJnailpolish.png\",\r\n\t\"AJnote.png\",\r\n\t\"AJnote2.png\",\r\n\t\"AJnote3.png\",\r\n\t\"AJnote4.png\",\r\n\t\"AJnote5.png\",\r\n\t\"AJnote6.png\",\r\n\t\"AJnote7.png\",\r\n\t\"AJnote8.png\",\r\n\t\"AJnote9.png\",\r\n\t\"AJnote10.png\",\r\n\t\"AJnote11.png\",\r\n\t\"AJnote12.png\",\r\n\t\"AJnote13.png\",\r\n\t\"AJnote14.png\",\r\n\t\"AJnote15.png\",\r\n\t\"AJnote16.png\",\r\n\t\"AJnote17.png\",\r\n\t\"AJnote18.png\",\r\n\t\"AJnote19.png\",\r\n\t\"AJnote\",\r\n\t\"AJpainting.png\",\r\n\t\"AJpainting2.png\",\r\n\t\"AJpainting3.png\",\r\n\t\"AJpainting4.png\",\r\n\t\"AJpanties.png\",\r\n\t\"AJpanties2.png\",\r\n\t\"AJpanties3.png\",\r\n\t\"AJphone.png\",\r\n\t\"AJphone2.png\",\r\n\t\"AJphoto.png\",\r\n\t\"AJphoto2.png\",\r\n\t\"AJphoto3.png\",\r\n\t\"AJphoto4.png\",\r\n\t\"AJphoto5.png\",\r\n\t\"AJphoto6.png\",\r\n\t\"AJphoto7.png\",\r\n\t\"AJphoto8.png\",\r\n\t\"AJpoisonspray.png\",\r\n\t\"AJsciencekit.png\",\r\n\t\"AJshoe.png\",\r\n\t\"AJshoe2.png\",\r\n\t\"AJshoe3.png\",\r\n\t\"AJsnack.png\",\r\n\t\"AJsnack2.png\",\r\n\t\"AJsnack3.png\",\r\n\t\"AJsnackoos.png\",\r\n\t\"AJstamp.png\",\r\n\t\"AJsyringe.png\",\r\n\t\"AJticket.png\",\r\n\t\"AJticket2.png\",\r\n\t\"AJticket3.png\",\r\n\t\"AJvideo.png\",\r\n\t\"AJxraymachine.png\",\r\n\t\"Compin.png\",\r\n\t\"Credit.png\",\r\n\t\"CustomEvidence1.png\",\r\n\t\"CustomEvidence2.png\",\r\n\t\"CustomEvidence3.png\",\r\n\t\"CustomEvidence4.png\",\r\n\t\"CustomEvidence5.png\",\r\n\t\"CustomEvidence6.png\",\r\n\t\"CustomEvidence7.png\",\r\n\t\"CustomEvidence8.png\",\r\n\t\"CustomEvidence9.png\",\r\n\t\"CustomEvidence10.png\",\r\n\t\"CustomEvidence11.png\",\r\n\t\"CustomEvidence12.png\",\r\n\t\"CustomEvidence13.png\",\r\n\t\"CustomEvidence14.png\",\r\n\t\"CustomEvidence15.png\",\r\n\t\"CustomEvidence16.png\",\r\n\t\"CustomEvidence17.png\",\r\n\t\"CustomEvidence18.png\",\r\n\t\"CustomEvidence19.png\",\r\n\t\"CustomEvidence\",\r\n\t\"DDAutopsy.png\",\r\n\t\"DDBadge.png\",\r\n\t\"DDCaseCandice.png\",\r\n\t\"DDCastApollo.png\",\r\n\t\"DDCastApollo2.png\",\r\n\t\"DDCastApollo3.png\",\r\n\t\"DDCastAthena.png\",\r\n\t\"DDCastAura.png\",\r\n\t\"DDCastBlackquill.png\",\r\n\t\"DDCastCandice.png\",\r\n\t\"DDCastClay.png\",\r\n\t\"DDCastClonco.png\",\r\n\t\"DDCastClonco2.png\",\r\n\t\"DDCastCourte.png\",\r\n\t\"DDCastCrab.png\",\r\n\t\"DDCastDamien.png\",\r\n\t\"DDCastFilch.png\",\r\n\t\"DDCastFulbright.png\",\r\n\t\"DDCastJinxie.png\",\r\n\t\"DDCastJuniper.png\",\r\n\t\"DDCastJuniper2.png\",\r\n\t\"DDCastKlavier.png\",\r\n\t\"DDCastLBelle.png\",\r\n\t\"DDCastLBelle2.png\",\r\n\t\"DDCastMeans.png\",\r\n\t\"DDCastMetis.png\",\r\n\t\"DDCastMiles.png\",\r\n\t\"DDCastNineTails.png\",\r\n\t\"DDCastNorma.png\",\r\n\t\"DDCastOConnor.png\",\r\n\t\"DDCastOrla.png\",\r\n\t\"DDCastPayne.png\",\r\n\t\"DDCastPearl.png\",\r\n\t\"DDCastPhoenix.png\",\r\n\t\"DDCastRex.png\",\r\n\t\"DDCastRimes.png\",\r\n\t\"DDCastRobin.png\",\r\n\t\"DDCastRobin2.png\",\r\n\t\"DDCastSasha.png\",\r\n\t\"DDCastSasha2.png\",\r\n\t\"DDCastSasha3.png\",\r\n\t\"DDCastScuttlebutt.png\",\r\n\t\"DDCastShipley.png\",\r\n\t\"DDCastSniper.png\",\r\n\t\"DDCastSniper2.png\",\r\n\t\"DDCastStarbuck.png\",\r\n\t\"DDCastSummers.png\",\r\n\t\"DDCastTonate.png\",\r\n\t\"DDCastTrucy.png\",\r\n\t\"DDCastYuri.png\",\r\n\t\"DDSTEPladder.png\",\r\n\t\"DDScrewdriver.png\",\r\n\t\"DDStatueStands.png\",\r\n\t\"DDarrow.png\",\r\n\t\"DDbadge2.png\",\r\n\t\"DDbag.png\",\r\n\t\"DDball.png\",\r\n\t\"DDbed.png\",\r\n\t\"DDbomb.png\",\r\n\t\"DDbomb2.png\",\r\n\t\"DDbomb3.png\",\r\n\t\"DDbomb4.png\",\r\n\t\"DDbook.png\",\r\n\t\"DDbook2.png\",\r\n\t\"DDbook3.png\",\r\n\t\"DDbook4.png\",\r\n\t\"DDbook5.png\",\r\n\t\"DDbowl.png\",\r\n\t\"DDbox.png\",\r\n\t\"DDbox2.png\",\r\n\t\"DDbox3.png\",\r\n\t\"DDbox4.png\",\r\n\t\"DDbracelet.png\",\r\n\t\"DDbullet.png\",\r\n\t\"DDbullet2.png\",\r\n\t\"DDbullethole.png\",\r\n\t\"DDcalendar.png\",\r\n\t\"DDcamera.png\",\r\n\t\"DDcamera2.png\",\r\n\t\"DDcamera3.png\",\r\n\t\"DDcart.png\",\r\n\t\"DDcd.png\",\r\n\t\"DDcharm.png\",\r\n\t\"DDclip.png\",\r\n\t\"DDclip2.png\",\r\n\t\"DDclip3.png\",\r\n\t\"DDcloth.png\",\r\n\t\"DDcoin.png\",\r\n\t\"DDcoin2.png\",\r\n\t\"DDcomputer.png\",\r\n\t\"DDcostume.png\",\r\n\t\"DDcostume2.png\",\r\n\t\"DDcostumes.png\",\r\n\t\"DDdata.png\",\r\n\t\"DDdata2.png\",\r\n\t\"DDdata3.png\",\r\n\t\"DDdetonator.png\",\r\n\t\"DDdoor.png\",\r\n\t\"DDdoor2.png\",\r\n\t\"DDdoor3.png\",\r\n\t\"DDdye.png\",\r\n\t\"DDearring.png\",\r\n\t\"DDemblem.png\",\r\n\t\"DDenvelope.png\",\r\n\t\"DDfingerprint.png\",\r\n\t\"DDfingerprintpowder.png\",\r\n\t\"DDfish.png\",\r\n\t\"DDflower.png\",\r\n\t\"DDfood.png\",\r\n\t\"DDfood2.png\",\r\n\t\"DDgun.png\",\r\n\t\"DDhair.png\",\r\n\t\"DDhairspray.png\",\r\n\t\"DDhandprint.png\",\r\n\t\"DDhat.png\",\r\n\t\"DDheadphones.png\",\r\n\t\"DDkey.png\",\r\n\t\"DDkey2.png\",\r\n\t\"DDkey3.png\",\r\n\t\"DDkeycard.png\",\r\n\t\"DDkeycard2.png\",\r\n\t\"DDkeycard3.png\",\r\n\t\"DDkeycard4.png\",\r\n\t\"DDkeycard5.png\",\r\n\t\"DDkeycard6.png\",\r\n\t\"DDkeycard7.png\",\r\n\t\"DDknife.png\",\r\n\t\"DDladder.png\",\r\n\t\"DDladder2.png\",\r\n\t\"DDlighter.png\",\r\n\t\"DDluminol.png\",\r\n\t\"DDmagatama.png\",\r\n\t\"DDmagatama2.png\",\r\n\t\"DDmap.png\",\r\n\t\"DDmap2.png\",\r\n\t\"DDmap3.png\",\r\n\t\"DDmap4.png\",\r\n\t\"DDmap5.png\",\r\n\t\"DDmap6.png\",\r\n\t\"DDmap7.png\",\r\n\t\"DDmap8.png\",\r\n\t\"DDmap9.png\",\r\n\t\"DDmap10.png\",\r\n\t\"DDmap11.png\",\r\n\t\"DDmap12.png\",\r\n\t\"DDmask.png\",\r\n\t\"DDmedicine.png\",\r\n\t\"DDmedicine2.png\",\r\n\t\"DDmedicine3.png\",\r\n\t\"DDnote.png\",\r\n\t\"DDnote2.png\",\r\n\t\"DDnote4.png\",\r\n\t\"DDnote5.png\",\r\n\t\"DDnote6.png\",\r\n\t\"DDnote7.png\",\r\n\t\"DDnote8.png\",\r\n\t\"DDnote9.png\",\r\n\t\"DDnote10.png\",\r\n\t\"DDnote16.png\",\r\n\t\"DDpenguin.png\",\r\n\t\"DDphone.png\",\r\n\t\"DDphone2.png\",\r\n\t\"DDphoto.png\",\r\n\t\"DDphoto2.png\",\r\n\t\"DDphoto3.png\",\r\n\t\"DDphoto4.png\",\r\n\t\"DDphoto5.png\",\r\n\t\"DDphoto6.png\",\r\n\t\"DDphoto7.png\",\r\n\t\"DDphoto10.png\",\r\n\t\"DDphoto11.png\",\r\n\t\"DDphoto12.png\",\r\n\t\"DDphoto13.png\",\r\n\t\"DDphoto14.png\",\r\n\t\"DDphoto15.png\",\r\n\t\"DDplate.png\",\r\n\t\"DDposter.png\",\r\n\t\"DDposter2.png\",\r\n\t\"DDposter3.png\",\r\n\t\"DDpuppet.png\",\r\n\t\"DDrecorder.png\",\r\n\t\"DDscienceglasses.png\",\r\n\t\"DDscroll.png\",\r\n\t\"DDshard.png\",\r\n\t\"DDshard2.png\",\r\n\t\"DDshard3.png\",\r\n\t\"DDshard4.png\",\r\n\t\"DDshard5.png\",\r\n\t\"DDshard6.png\",\r\n\t\"DDshard7.png\",\r\n\t\"DDshoe.png\",\r\n\t\"DDskull.png\",\r\n\t\"DDstaff.png\",\r\n\t\"DDstatue.png\",\r\n\t\"DDstatue2.png\",\r\n\t\"DDstatue3.png\",\r\n\t\"DDstatue4.png\",\r\n\t\"DDstatue5.png\",\r\n\t\"DDstatue6.png\",\r\n\t\"DDstatue7.png\",\r\n\t\"DDstatue8.png\",\r\n\t\"DDstatue9.png\",\r\n\t\"DDsurgery.png\",\r\n\t\"DDsuspect.png\",\r\n\t\"DDsword.png\",\r\n\t\"DDsword2.png\",\r\n\t\"DDtail.png\",\r\n\t\"DDtank.png\",\r\n\t\"DDtank2.png\",\r\n\t\"DDvideo.png\",\r\n\t\"DDwhistle.png\",\r\n\t\"DDwidget.png\",\r\n\t\"DGSCastAuchi.png\",\r\n\t\"DGSCastBarok.png\",\r\n\t\"DGSCastBeppo.png\",\r\n\t\"DGSCastCrogrey.png\",\r\n\t\"DGSCastDemiglaski.png\",\r\n\t\"DGSCastFairplay.png\",\r\n\t\"DGSCastGina.png\",\r\n\t\"DGSCastGreen.png\",\r\n\t\"DGSCastGregson.png\",\r\n\t\"DGSCastHolmes.png\",\r\n\t\"DGSCastHosonaga.png\",\r\n\t\"DGSCastHosonaga2.png\",\r\n\t\"DGSCastHutch.png\",\r\n\t\"DGSCastJWatson.png\",\r\n\t\"DGSCastJezail.png\",\r\n\t\"DGSCastJoan.png\",\r\n\t\"DGSCastJohn.png\",\r\n\t\"DGSCastKazuma.png\",\r\n\t\"DGSCastLadyfirst.png\",\r\n\t\"DGSCastMegundal.png\",\r\n\t\"DGSCastMilverton.png\",\r\n\t\"DGSCastNatsume.png\",\r\n\t\"DGSCastNemmy.png\",\r\n\t\"DGSCastNikomina.png\",\r\n\t\"DGSCastPat.png\",\r\n\t\"DGSCastRola.png\",\r\n\t\"DGSCastRoylott.png\",\r\n\t\"DGSCastRyuunosuke.png\",\r\n\t\"DGSCastSanmon.png\",\r\n\t\"DGSCastStroganov.png\",\r\n\t\"DGSCastSusato.png\",\r\n\t\"DGSCastSuspect.png\",\r\n\t\"DGSCastTaizou.png\",\r\n\t\"DGSCastTully.png\",\r\n\t\"DGSCastVortex.png\",\r\n\t\"DGSCastWagahai.png\",\r\n\t\"DGSCastWatson.png\",\r\n\t\"DGSCastYuujin.png\",\r\n\t\"DGSbadge.png\",\r\n\t\"DGSbag.png\",\r\n\t\"DGSbag2.png\",\r\n\t\"DGSbell.png\",\r\n\t\"DGSbell2.png\",\r\n\t\"DGSbell3.png\",\r\n\t\"DGSbook.png\",\r\n\t\"DGSbook2.png\",\r\n\t\"DGSbook3.png\",\r\n\t\"DGSbook4.png\",\r\n\t\"DGSbook5.png\",\r\n\t\"DGSbook6.png\",\r\n\t\"DGSbook7.png\",\r\n\t\"DGSbook8.png\",\r\n\t\"DGSbook9.png\",\r\n\t\"DGSbook10.png\",\r\n\t\"DGSbullet.png\",\r\n\t\"DGScamera.png\",\r\n\t\"DGScane.png\",\r\n\t\"DGScart.png\",\r\n\t\"DGSclip.png\",\r\n\t\"DGSclip2.png\",\r\n\t\"DGSclip3.png\",\r\n\t\"DGSclip4.png\",\r\n\t\"DGScoin.png\",\r\n\t\"DGSdevice.png\",\r\n\t\"DGSflower.png\",\r\n\t\"DGSfood.png\",\r\n\t\"DGSfood2.png\",\r\n\t\"DGSfood3.png\",\r\n\t\"DGSfood4.png\",\r\n\t\"DGSgloves.png\",\r\n\t\"DGSgloves2.png\",\r\n\t\"DGSgun.png\",\r\n\t\"DGSgun2.png\",\r\n\t\"DGSgun3.png\",\r\n\t\"DGSherbaltea.png\",\r\n\t\"DGSknife.png\",\r\n\t\"DGSknife2.png\",\r\n\t\"DGSknife3.png\",\r\n\t\"DGSknife4.png\",\r\n\t\"DGSmap.png\",\r\n\t\"DGSmap2.png\",\r\n\t\"DGSmap3.png\",\r\n\t\"DGSmusicbox.png\",\r\n\t\"DGSmusicbox2.png\",\r\n\t\"DGSmusicbox3.png\",\r\n\t\"DGSmusicdisk.png\",\r\n\t\"DGSmusicdisk2.png\",\r\n\t\"DGSmusicdisk3.png\",\r\n\t\"DGSmusicdisk4.png\",\r\n\t\"DGSmusicdisk15.png\",\r\n\t\"DGSnote.png\",\r\n\t\"DGSnote2.png\",\r\n\t\"DGSnote3.png\",\r\n\t\"DGSnote4.png\",\r\n\t\"DGSnote5.png\",\r\n\t\"DGSnote6.png\",\r\n\t\"DGSnote7.png\",\r\n\t\"DGSnote8.png\",\r\n\t\"DGSnote9.png\",\r\n\t\"DGSnote10.png\",\r\n\t\"DGSnote11.png\",\r\n\t\"DGSnote12.png\",\r\n\t\"DGSnote13.png\",\r\n\t\"DGSnote14.png\",\r\n\t\"DGSnote15.png\",\r\n\t\"DGSnote16.png\",\r\n\t\"DGSnote17.png\",\r\n\t\"DGSnote18.png\",\r\n\t\"DGSnote19.png\",\r\n\t\"DGSnote\",\r\n\t\"DGSnote21.png\",\r\n\t\"DGSphoto.png\",\r\n\t\"DGSphoto2.png\",\r\n\t\"DGSphoto3.png\",\r\n\t\"DGSphoto4.png\",\r\n\t\"DGSphoto5.png\",\r\n\t\"DGSphoto6.png\",\r\n\t\"DGSphoto7.png\",\r\n\t\"DGSphoto8.png\",\r\n\t\"DGSphoto9.png\",\r\n\t\"DGSphoto10.png\",\r\n\t\"DGSphoto11.png\",\r\n\t\"DGSphoto12.png\",\r\n\t\"DGSphoto13.png\",\r\n\t\"DGSphoto14.png\",\r\n\t\"DGSphoto15.png\",\r\n\t\"DGSphoto16.png\",\r\n\t\"DGSphoto17.png\",\r\n\t\"DGSphoto18.png\",\r\n\t\"DGSphoto19.png\",\r\n\t\"DGSpin.png\",\r\n\t\"DGSpin2.png\",\r\n\t\"DGSpipe.png\",\r\n\t\"DGSpressing.png\",\r\n\t\"DGSsciencekit.png\",\r\n\t\"DGSshard.png\",\r\n\t\"DGSstereoscope.png\",\r\n\t\"DGSstereoscope2.png\",\r\n\t\"DGStiara.png\",\r\n\t\"DGSviola.png\",\r\n\t\"DGSviola2.png\",\r\n\t\"DGSwhip.png\",\r\n\t\"Datapad.png\",\r\n\t\"Interface.png\",\r\n\t\"JFACastAcro.png\",\r\n\t\"JFACastAdrian.png\",\r\n\t\"JFACastAmi.png\",\r\n\t\"JFACastBat.png\",\r\n\t\"JFACastBen.png\",\r\n\t\"JFACastCeleste.png\",\r\n\t\"JFACastDeKiller.png\",\r\n\t\"JFACastDustin.png\",\r\n\t\"JFACastFranziska.png\",\r\n\t\"JFACastGalactica.png\",\r\n\t\"JFACastGrey.png\",\r\n\t\"JFACastHotti.png\",\r\n\t\"JFACastIni.png\",\r\n\t\"JFACastJuan.png\",\r\n\t\"JFACastMaggey.png\",\r\n\t\"JFACastMatt.png\",\r\n\t\"JFACastMimi.png\",\r\n\t\"JFACastMoe.png\",\r\n\t\"JFACastMorgan.png\",\r\n\t\"JFACastPearl.png\",\r\n\t\"JFACastRegina.png\",\r\n\t\"JFACastRussel.png\",\r\n\t\"JFACastShelly.png\",\r\n\t\"JFACastWellington.png\",\r\n\t\"JFATHATCARD.png\",\r\n\t\"JFATHATCARD2.png\",\r\n\t\"JFAautograph.png\",\r\n\t\"JFAautograph2.png\",\r\n\t\"JFAball.png\",\r\n\t\"JFAball2.png\",\r\n\t\"JFAbear.png\",\r\n\t\"JFAbear2.png\",\r\n\t\"JFAbear3.png\",\r\n\t\"JFAbottle.png\",\r\n\t\"JFAbox.png\",\r\n\t\"JFAbox2.png\",\r\n\t\"JFAbusinesscard.png\",\r\n\t\"JFAbusinesscard2.png\",\r\n\t\"JFAbutton.png\",\r\n\t\"JFAbutton2.png\",\r\n\t\"JFAbutton3.png\",\r\n\t\"JFAcamera.png\",\r\n\t\"JFAcard.png\",\r\n\t\"JFAcard2.png\",\r\n\t\"JFAclip.png\",\r\n\t\"JFAclip2.png\",\r\n\t\"JFAclip3.png\",\r\n\t\"JFAclip4.png\",\r\n\t\"JFAcoat.png\",\r\n\t\"JFAfrequencydetector.png\",\r\n\t\"JFAglasses.png\",\r\n\t\"JFAglove.png\",\r\n\t\"JFAgrapes.png\",\r\n\t\"JFAguitar.png\",\r\n\t\"JFAgun.png\",\r\n\t\"JFAgun2.png\",\r\n\t\"JFAhammond.png\",\r\n\t\"JFAhat.png\",\r\n\t\"JFAjuice.png\",\r\n\t\"JFAkey.png\",\r\n\t\"JFAknife.png\",\r\n\t\"JFAknife2.png\",\r\n\t\"JFAleon.png\",\r\n\t\"JFAmilk.png\",\r\n\t\"JFAmilk2.png\",\r\n\t\"JFAmoney.png\",\r\n\t\"JFAnote.png\",\r\n\t\"JFAnote2.png\",\r\n\t\"JFApepper.png\",\r\n\t\"JFAphoto.png\",\r\n\t\"JFAposter.png\",\r\n\t\"JFAreceipt.png\",\r\n\t\"JFAregent.png\",\r\n\t\"JFAring.png\",\r\n\t\"JFArobe.png\",\r\n\t\"JFArobescrap.png\",\r\n\t\"JFAscarf.png\",\r\n\t\"JFAscreen.png\",\r\n\t\"JFAshoe.png\",\r\n\t\"JFAspycamera.png\",\r\n\t\"JFAticket.png\",\r\n\t\"JFAticket2.png\",\r\n\t\"JFAtracker.png\",\r\n\t\"JFAtransceiver.png\",\r\n\t\"JFAtransmitter.png\",\r\n\t\"JFAtrilo.png\",\r\n\t\"JFAuniform.png\",\r\n\t\"JFAurn1.png\",\r\n\t\"JFAurn2.png\",\r\n\t\"JFAvest.png\",\r\n\t\"JFAwhip.png\",\r\n\t\"MiscAKMS.png\",\r\n\t\"MiscAsthmaPump.png\",\r\n\t\"MiscBaggie.png\",\r\n\t\"MiscBeach.png\",\r\n\t\"MiscBlueRuby.png\",\r\n\t\"MiscCandy Cane.png\",\r\n\t\"MiscCandy Cane Dark.png\",\r\n\t\"MiscCorkscrew.png\",\r\n\t\"MiscCrowbar.png\",\r\n\t\"MiscDragonPepper.png\",\r\n\t\"MiscFlintlock.png\",\r\n\t\"MiscGenerator.png\",\r\n\t\"MiscGrapeJuice.png\",\r\n\t\"MiscGreen Hut.png\",\r\n\t\"MiscGrill.png\",\r\n\t\"MiscHalf-Eaten Burger.png\",\r\n\t\"MiscHangGlider.png\",\r\n\t\"MiscLockpicks.png\",\r\n\t\"MiscMapBiolab.png\",\r\n\t\"MiscMapCourthouse.png\",\r\n\t\"MiscMapLobby1.png\",\r\n\t\"MiscMichigan J Frog.png\",\r\n\t\"MiscMystery1.png\",\r\n\t\"MiscMystery2.png\",\r\n\t\"MiscMystery3.png\",\r\n\t\"MiscOldTrain.png\",\r\n\t\"MiscRaffleTickets.png\",\r\n\t\"MiscSpatula.png\",\r\n\t\"MiscSpecimenAlpha.png\",\r\n\t\"MiscTimeCrystal.png\",\r\n\t\"MiscTins.png\",\r\n\t\"MiscUnknown People.png\",\r\n\t\"MiscVDF.png\",\r\n\t\"MiscVodka.png\",\r\n\t\"MiscZombie.png\",\r\n\t\"Scanner.png\",\r\n\t\"SoJad.png\",\r\n\t\"SoJad2.png\",\r\n\t\"SoJad3.png\",\r\n\t\"SoJad4.png\",\r\n\t\"SoJad5.png\",\r\n\t\"SoJad6.png\",\r\n\t\"SoJad7.png\",\r\n\t\"SoJarrow.png\",\r\n\t\"SoJautopsy.png\",\r\n\t\"SoJbadge.png\",\r\n\t\"SoJbadge2.png\",\r\n\t\"SoJblimp.png\",\r\n\t\"SoJblimp2.png\",\r\n\t\"SoJblood.png\",\r\n\t\"SoJboiler.png\",\r\n\t\"SoJbook.png\",\r\n\t\"SoJbook2.png\",\r\n\t\"SoJbook3.png\",\r\n\t\"SoJbook4.png\",\r\n\t\"SoJbook5.png\",\r\n\t\"SoJbook6.png\",\r\n\t\"SoJbook7.png\",\r\n\t\"SoJbook8.png\",\r\n\t\"SoJbook9.png\",\r\n\t\"SoJbook10.png\",\r\n\t\"SoJbook11.png\",\r\n\t\"SoJbook12.png\",\r\n\t\"SoJbook13.png\",\r\n\t\"SoJbook14.png\",\r\n\t\"SoJbox.png\",\r\n\t\"SoJbox2.png\",\r\n\t\"SoJbracelet.png\",\r\n\t\"SoJbucket.png\",\r\n\t\"SoJcamera.png\",\r\n\t\"SoJcandelabra.png\",\r\n\t\"SoJcandelabra2.png\",\r\n\t\"SoJcandelabra3.png\",\r\n\t\"SoJcastAhlbi.png\",\r\n\t\"SoJcastAmara.png\",\r\n\t\"SoJcastAndistan'dhin.png\",\r\n\t\"SoJcastApollo.png\",\r\n\t\"SoJcastArchie.png\",\r\n\t\"SoJcastArmie.png\",\r\n\t\"SoJcastAthena.png\",\r\n\t\"SoJcastAtishon.png\",\r\n\t\"SoJcastBeh'leeb.png\",\r\n\t\"SoJcastBetty.png\",\r\n\t\"SoJcastBlackquill.png\",\r\n\t\"SoJcastBonny.png\",\r\n\t\"SoJcastBucky.png\",\r\n\t\"SoJcastButz.png\",\r\n\t\"SoJcastDatz.png\",\r\n\t\"SoJcastDatz2.png\",\r\n\t\"SoJcastDhurke.png\",\r\n\t\"SoJcastDumas.png\",\r\n\t\"SoJcastEllen.png\",\r\n\t\"SoJcastEma.png\",\r\n\t\"SoJcastGa'ran.png\",\r\n\t\"SoJcastGeiru.png\",\r\n\t\"SoJcastInga.png\",\r\n\t\"SoJcastMaya.png\",\r\n\t\"SoJcastMiles.png\",\r\n\t\"SoJcastNahyuta.png\",\r\n\t\"SoJcastNayna.png\",\r\n\t\"SoJcastPayne.png\",\r\n\t\"SoJcastPearl.png\",\r\n\t\"SoJcastPhoenix.png\",\r\n\t\"SoJcastPierce.png\",\r\n\t\"SoJcastPuhray.png\",\r\n\t\"SoJcastRayfa.png\",\r\n\t\"SoJcastRetinz.png\",\r\n\t\"SoJcastReus.png\",\r\n\t\"SoJcastRohl.png\",\r\n\t\"SoJcastSelena.png\",\r\n\t\"SoJcastSergeant.png\",\r\n\t\"SoJcastSorin.png\",\r\n\t\"SoJcastTahrust.png\",\r\n\t\"SoJcastTaifu.png\",\r\n\t\"SoJcastTrucy.png\",\r\n\t\"SoJcastUendo.png\",\r\n\t\"SoJcd.png\",\r\n\t\"SoJcd2.png\",\r\n\t\"SoJcharm.png\",\r\n\t\"SoJclip.png\",\r\n\t\"SoJclip2.png\",\r\n\t\"SoJcog.png\",\r\n\t\"SoJcontract.png\",\r\n\t\"SoJdog.png\",\r\n\t\"SoJflag.png\",\r\n\t\"SoJflower.png\",\r\n\t\"SoJfood1.png\",\r\n\t\"SoJfood2.png\",\r\n\t\"SoJfood3.png\",\r\n\t\"SoJgem.png\",\r\n\t\"SoJglasses.png\",\r\n\t\"SoJgoop.png\",\r\n\t\"SoJhat.png\",\r\n\t\"SoJhelicopter.png\",\r\n\t\"SoJhorse.png\",\r\n\t\"SoJhorse2.png\",\r\n\t\"SoJkey.png\",\r\n\t\"SoJkey2.png\",\r\n\t\"SoJkey3.png\",\r\n\t\"SoJkey4.png\",\r\n\t\"SoJkeycard.png\",\r\n\t\"SoJkeycharm.png\",\r\n\t\"SoJlantern.png\",\r\n\t\"SoJlantern2.png\",\r\n\t\"SoJluminol.png\",\r\n\t\"SoJmagatama.png\",\r\n\t\"SoJmagatama2.png\",\r\n\t\"SoJmagatama3.png\",\r\n\t\"SoJmap.png\",\r\n\t\"SoJmap2.png\",\r\n\t\"SoJmap3.png\",\r\n\t\"SoJmap4.png\",\r\n\t\"SoJmap5.png\",\r\n\t\"SoJmap6.png\",\r\n\t\"SoJmap7.png\",\r\n\t\"SoJmrhat.png\",\r\n\t\"SoJnote.png\",\r\n\t\"SoJnote2.png\",\r\n\t\"SoJnote3.png\",\r\n\t\"SoJnote4.png\",\r\n\t\"SoJnote5.png\",\r\n\t\"SoJnote6.png\",\r\n\t\"SoJnote7.png\",\r\n\t\"SoJnote8.png\",\r\n\t\"SoJnote9.png\",\r\n\t\"SoJnote10.png\",\r\n\t\"SoJnote11.png\",\r\n\t\"SoJnote12.png\",\r\n\t\"SoJnote13.png\",\r\n\t\"SoJnote14.png\",\r\n\t\"SoJnote15.png\",\r\n\t\"SoJnote16.png\",\r\n\t\"SoJnote17.png\",\r\n\t\"SoJorb.png\",\r\n\t\"SoJpassport.png\",\r\n\t\"SoJpendant.png\",\r\n\t\"SoJphone.png\",\r\n\t\"SoJphoto.png\",\r\n\t\"SoJphoto2.png\",\r\n\t\"SoJphoto3.png\",\r\n\t\"SoJphoto4.png\",\r\n\t\"SoJphoto5.png\",\r\n\t\"SoJphoto6.png\",\r\n\t\"SoJphoto7.png\",\r\n\t\"SoJphoto8.png\",\r\n\t\"SoJphoto9.png\",\r\n\t\"SoJphoto10.png\",\r\n\t\"SoJphoto11.png\",\r\n\t\"SoJphoto12.png\",\r\n\t\"SoJphoto13.png\",\r\n\t\"SoJphoto14.png\",\r\n\t\"SoJphoto15.png\",\r\n\t\"SoJphoto16.png\",\r\n\t\"SoJphoto17.png\",\r\n\t\"SoJphoto18.png\",\r\n\t\"SoJphoto19.png\",\r\n\t\"SoJphoto\",\r\n\t\"SoJphoto21.png\",\r\n\t\"SoJphoto22.png\",\r\n\t\"SoJphoto23.png\",\r\n\t\"SoJphoto24.png\",\r\n\t\"SoJphoto25.png\",\r\n\t\"SoJphoto26.png\",\r\n\t\"SoJphoto27.png\",\r\n\t\"SoJphoto28.png\",\r\n\t\"SoJprintpowder.png\",\r\n\t\"SoJraincoat.png\",\r\n\t\"SoJscissorlift.png\",\r\n\t\"SoJscroll.png\",\r\n\t\"SoJscroll2.png\",\r\n\t\"SoJsnackoo.png\",\r\n\t\"SoJstand.png\",\r\n\t\"SoJstatue.png\",\r\n\t\"SoJsuspect.png\",\r\n\t\"SoJsword.png\",\r\n\t\"SoJsword2.png\",\r\n\t\"SoJsyringe.png\",\r\n\t\"SoJtape1.png\",\r\n\t\"SoJtext.png\",\r\n\t\"SoJunknown.png\",\r\n\t\"SoJurn.png\",\r\n\t\"SoJusb.png\",\r\n\t\"SoJwallet.png\",\r\n\t\"SoJwidget.png\",\r\n\t\"TTCastAdrian.png\",\r\n\t\"TTCastArmstrong.png\",\r\n\t\"TTCastAtmey.png\",\r\n\t\"TTCastBikini.png\",\r\n\t\"TTCastBruto.png\",\r\n\t\"TTCastBullard.png\",\r\n\t\"TTCastDahlia.png\",\r\n\t\"TTCastDeMasque.png\",\r\n\t\"TTCastDesiree.png\",\r\n\t\"TTCastDiego.png\",\r\n\t\"TTCastElg.png\",\r\n\t\"TTCastElise.png\",\r\n\t\"TTCastFawles.png\",\r\n\t\"TTCastGodot.png\",\r\n\t\"TTCastGrossberg.png\",\r\n\t\"TTCastGumshoe.png\",\r\n\t\"TTCastIris.png\",\r\n\t\"TTCastIris2.png\",\r\n\t\"TTCastKudo.png\",\r\n\t\"TTCastLisa.png\",\r\n\t\"TTCastMaggey.png\",\r\n\t\"TTCastMiles.png\",\r\n\t\"TTCastRon.png\",\r\n\t\"TTCastSwallow.png\",\r\n\t\"TTCastTigre.png\",\r\n\t\"TTCastValerie.png\",\r\n\t\"TTCastViola.png\",\r\n\t\"TTad.png\",\r\n\t\"TTad2.png\",\r\n\t\"TTapron.png\",\r\n\t\"TTbadge.png\",\r\n\t\"TTbag.png\",\r\n\t\"TTblood1.png\",\r\n\t\"TTblood2.png\",\r\n\t\"TTbottle1.png\",\r\n\t\"TTbottle2.png\",\r\n\t\"TTbox.png\",\r\n\t\"TTbox2.png\",\r\n\t\"TTbutton.png\",\r\n\t\"TTcalendar.png\",\r\n\t\"TTcamera.png\",\r\n\t\"TTcard.png\",\r\n\t\"TTcd.png\",\r\n\t\"TTcd2.png\",\r\n\t\"TTclip.png\",\r\n\t\"TTclip2.png\",\r\n\t\"TTclip3.png\",\r\n\t\"TTclip4.png\",\r\n\t\"TTclip5.png\",\r\n\t\"TTcoldkiller.png\",\r\n\t\"TTcoldkiller2.png\",\r\n\t\"TTcup.png\",\r\n\t\"TTdata.png\",\r\n\t\"TTdata2.png\",\r\n\t\"TTdata3.png\",\r\n\t\"TTdata4.png\",\r\n\t\"TTdrawing.png\",\r\n\t\"TTemblem.png\",\r\n\t\"TTemployee.png\",\r\n\t\"TTfood1.png\",\r\n\t\"TTfood2.png\",\r\n\t\"TThood.png\",\r\n\t\"TTjewel.png\",\r\n\t\"TTjewel2.png\",\r\n\t\"TTkeycard.png\",\r\n\t\"TTknife.png\",\r\n\t\"TTlantern.png\",\r\n\t\"TTlantern2.png\",\r\n\t\"TTmagazine.png\",\r\n\t\"TTmagazine2.png\",\r\n\t\"TTmatchbook.png\",\r\n\t\"TTmatchbook2.png\",\r\n\t\"TTmedicine.png\",\r\n\t\"TTmedicine2.png\",\r\n\t\"TTmoped.png\",\r\n\t\"TTnecklace.png\",\r\n\t\"TTnote.png\",\r\n\t\"TTnote2.png\",\r\n\t\"TTnote3.png\",\r\n\t\"TTnote4.png\",\r\n\t\"TTnote5.png\",\r\n\t\"TTnote6.png\",\r\n\t\"TTnote7.png\",\r\n\t\"TTperfume.png\",\r\n\t\"TTphotoold.png\",\r\n\t\"TTsapphire.png\",\r\n\t\"TTscarf.png\",\r\n\t\"TTschichishito.png\",\r\n\t\"TTschichishito2.png\",\r\n\t\"TTschichishito3.png\",\r\n\t\"TTscroll.png\",\r\n\t\"TTscroll2.png\",\r\n\t\"TTseal.png\",\r\n\t\"TTseal2.png\",\r\n\t\"TTstaff.png\",\r\n\t\"TTstaff2.png\",\r\n\t\"TTstaff3.png\",\r\n\t\"TTstain.png\",\r\n\t\"TTstatue.png\",\r\n\t\"TTticket.png\",\r\n\t\"TTticket2.png\",\r\n\t\"TTumbrella.png\",\r\n\t\"TTvase.png\",\r\n\t\"TTvase2.png\",\r\n\t\"TTvase3.png\",\r\n\t\"TTvase4.png\",\r\n\t\"TTwallet.png\",\r\n\t\"TTwatch.png\",\r\n\t\"Vivaster.png\",\r\n\t\"empty.png\",\r\n\t\"lawyerbadge.png\"\r\n];","export default [\r\n\t\"1st server\",\r\n\t\"999.1\",\r\n\t\"999\",\r\n\t\"999Apartment\",\r\n\t\"999CaptainsQuarters\",\r\n\t\"999Cargo\",\r\n\t\"999Casino\",\r\n\t\"999Cdeck\",\r\n\t\"999CentralStairs\",\r\n\t\"999Chapel\",\r\n\t\"999Chart\",\r\n\t\"999Confinement\",\r\n\t\"999DoorsA\",\r\n\t\"999DoorsB\",\r\n\t\"999Hospital\",\r\n\t\"999Kitchen\",\r\n\t\"999Library\",\r\n\t\"999Operating\",\r\n\t\"999Shower\",\r\n\t\"999Steam\",\r\n\t\"999Steeldoor\",\r\n\t\"999Study\",\r\n\t\"999Torture\",\r\n\t\"9991stClassCabinA\",\r\n\t\"9991stClassCabinB\",\r\n\t\"9992ndClassCabin\",\r\n\t\"AA - Edgewort's Office\",\r\n\t\"AA - Gantsroom\",\r\n\t\"AA - Gatewater room\",\r\n\t\"AA - Gourd Lake\",\r\n\t\"AA - Gourd Lake Entrance\",\r\n\t\"AA - Hotel Lobby\",\r\n\t\"AA - Hotticlinic\",\r\n\t\"AA - Kurain\",\r\n\t\"AA - Parkinglot\",\r\n\t\"AA - Police Deparment\",\r\n\t\"AA - Police Station\",\r\n\t\"AA - Records Room\",\r\n\t\"AA - Sc13\",\r\n\t\"AA - Wright's Office\",\r\n\t\"AABluecorp\",\r\n\t\"AACourt\",\r\n\t\"AACourtAnime\",\r\n\t\"AACourtChristmasDecorations\",\r\n\t\"AACourtChristmasLights\",\r\n\t\"AACourtHD\",\r\n\t\"AADefendantLobby\",\r\n\t\"AADefendantLobbyHD\",\r\n\t\"AADetentionCenter\",\r\n\t\"AAEdgeworthOffice\",\r\n\t\"AAGantOffice\",\r\n\t\"AAGatewaterHotel\",\r\n\t\"AAGlobalStudiosEast\",\r\n\t\"AAGlobalStudiosWest\",\r\n\t\"AAGourdLake\",\r\n\t\"AAGrossbergOffice\",\r\n\t\"AAI2Circus\",\r\n\t\"AAI2City\",\r\n\t\"AAI2GourdLake\",\r\n\t\"AAI2LogicChess\",\r\n\t\"AAI2MuseumPast\",\r\n\t\"AAI2MuseumPresent\",\r\n\t\"AAI2PIC\",\r\n\t\"AAI2Prison\",\r\n\t\"AAICohdopianEmbassy\",\r\n\t\"AAICourt\",\r\n\t\"AAICourtFlipped\",\r\n\t\"AAIEdgeworthOffice\",\r\n\t\"AAIGatewaterLandStage\",\r\n\t\"AAIGatewaterLandWildWest\",\r\n\t\"AAIiFlyAirlines\",\r\n\t\"AALobby\",\r\n\t\"AAParkingLot\",\r\n\t\"AAPoliceStation\",\r\n\t\"AATrainStation\",\r\n\t\"AAWrightOffice\",\r\n\t\"AJBorschtBowlClub\",\r\n\t\"AJCourt\",\r\n\t\"AJCourtBirthday\",\r\n\t\"AJCourtHalloween\",\r\n\t\"AJCourtNight\",\r\n\t\"AJCourtTV\",\r\n\t\"AJDefendantLobby\",\r\n\t\"AJDetentionCenter\",\r\n\t\"AJDrewStudio\",\r\n\t\"AJHottiClinic\",\r\n\t\"AJKlavierOffice\",\r\n\t\"AJKristophCell\",\r\n\t\"AJLobby\",\r\n\t\"AJMeraktisClinic\",\r\n\t\"AJPeoplePark\",\r\n\t\"AJSunshineColiseum\",\r\n\t\"AJWrightOffice\",\r\n\t\"Ace\",\r\n\t\"AcroRoomJFA\",\r\n\t\"AirportJFA\",\r\n\t\"AlbaOfficeAAI\",\r\n\t\"Anime\",\r\n\t\"Arcade\",\r\n\t\"AtmeyOfficeTT\",\r\n\t\"Atrium (SG)\",\r\n\t\"AutumnForest\",\r\n\t\"BB - Flowerfield\",\r\n\t\"BB - Market\",\r\n\t\"BB - Street\",\r\n\t\"BandoLandAAI\",\r\n\t\"Basement\",\r\n\t\"Battlegrounds\",\r\n\t\"BerryBigCircusJFA\",\r\n\t\"Blackout\",\r\n\t\"BlueScreensTT\",\r\n\t\"BluecorpAA\",\r\n\t\"BridgeNest\",\r\n\t\"Brig\",\r\n\t\"Building\",\r\n\t\"CC1\",\r\n\t\"CC2\",\r\n\t\"CC3\",\r\n\t\"CC4\",\r\n\t\"CC5\",\r\n\t\"CC6\",\r\n\t\"CC7\",\r\n\t\"CC8\",\r\n\t\"CC9\",\r\n\t\"CC10\",\r\n\t\"CC11\",\r\n\t\"CC12\",\r\n\t\"CO - Big door\",\r\n\t\"CO - Finalroom\",\r\n\t\"CO - Meetingroom\",\r\n\t\"CO - Whitedoor\",\r\n\t\"CO - Whitelobby\",\r\n\t\"CO - Whitelowerfloor\",\r\n\t\"CO - White room\",\r\n\t\"CP\",\r\n\t\"CPRP2 Chap1\",\r\n\t\"CPRP2 Chap2and3\",\r\n\t\"CPRP2 Chap4\",\r\n\t\"CPRP2 Chap5\",\r\n\t\"CPRP Chap1\",\r\n\t\"CPRP Chap2\",\r\n\t\"CPRP Chap3\",\r\n\t\"CPRP Chap4\",\r\n\t\"CPRP Chap5\",\r\n\t\"CVStMystere\",\r\n\t\"Cafe\",\r\n\t\"CafeCourt\",\r\n\t\"CaffeeCase\",\r\n\t\"Cal\",\r\n\t\"CargoHoldAAI\",\r\n\t\"Casino\",\r\n\t\"CasinoCourt\",\r\n\t\"Cathedral (SG)\",\r\n\t\"Christmas\",\r\n\t\"Christmas Courtroom\",\r\n\t\"CinemaFamousi\",\r\n\t\"Classroom\",\r\n\t\"Co - Lobby 1\",\r\n\t\"Co - Lobby 2\",\r\n\t\"CochenOfficeAAI\",\r\n\t\"ColosseumFerox\",\r\n\t\"Control Room\",\r\n\t\"Control Room Interior\",\r\n\t\"CountyCourt\",\r\n\t\"CourtroomAA\",\r\n\t\"CourtroomAAHD\",\r\n\t\"CourtroomAAI\",\r\n\t\"CourtroomAJ\",\r\n\t\"CourtroomAJNight\",\r\n\t\"CourtroomAnime\",\r\n\t\"CourtroomCounty\",\r\n\t\"CourtroomDD\",\r\n\t\"CourtroomEnglish\",\r\n\t\"CourtroomNew\",\r\n\t\"CourtroomRuined\",\r\n\t\"CourtroomThemis\",\r\n\t\"CourtroomTouhou\",\r\n\t\"CourtroomWitch\",\r\n\t\"CruiseCourt\",\r\n\t\"CustomEight\",\r\n\t\"CustomEleven\",\r\n\t\"CustomFifteen\",\r\n\t\"CustomFive\",\r\n\t\"CustomFour\",\r\n\t\"CustomFourteen\",\r\n\t\"CustomNine\",\r\n\t\"CustomOne\",\r\n\t\"CustomSeven\",\r\n\t\"CustomSix\",\r\n\t\"CustomTen\",\r\n\t\"CustomThirteen\",\r\n\t\"CustomThree\",\r\n\t\"CustomTwelve\",\r\n\t\"CustomTwo\",\r\n\t\"DC\",\r\n\t\"DDCourt\",\r\n\t\"DDCourtGray\",\r\n\t\"DDCourtRuined\",\r\n\t\"DDCourtRuinedInvestigation\",\r\n\t\"DDCourtThemis\",\r\n\t\"DDDefendantLobby\",\r\n\t\"DDGyaxa\",\r\n\t\"DDLobby\",\r\n\t\"DDNinetailsVale\",\r\n\t\"DDShipshapeAquarium\",\r\n\t\"DDThemisAcademy\",\r\n\t\"DFreightTrain\",\r\n\t\"DGS-ENG\",\r\n\t\"DGS-JAP\",\r\n\t\"DGS\",\r\n\t\"DGSCourtJapanese\",\r\n\t\"DGSCourtOldBailey\",\r\n\t\"DGSCourtOldBaileyJury\",\r\n\t\"DGSDefendantLobbyJapanese\",\r\n\t\"DGSDefendantLobbyOldBailey\",\r\n\t\"DGSEnglishCourt\",\r\n\t\"DGSJapanCourt\",\r\n\t\"DGSLondon\",\r\n\t\"DGSenglishcourt\",\r\n\t\"DRAE-Area1\",\r\n\t\"DRAE-Area2\",\r\n\t\"DRClassTrial\",\r\n\t\"DRRP\",\r\n\t\"Dark Cave\",\r\n\t\"Darkness\",\r\n\t\"Datrone Heart\",\r\n\t\"Datrone HeartHQ\",\r\n\t\"DeLiteHouseTT\",\r\n\t\"Despair vs. Hope\",\r\n\t\"DetentionCenterAAI2\",\r\n\t\"DimensionalGate\",\r\n\t\"DogenCellAAI2\",\r\n\t\"DualDestinies\",\r\n\t\"Dungeon Courtroom\",\r\n\t\"EdgeworthOfficeAA\",\r\n\t\"EdgeworthOfficeAAI\",\r\n\t\"EmbassyAAI\",\r\n\t\"Endless Courtroom\",\r\n\t\"EngardeManorJFA\",\r\n\t\"EnglishCourt\",\r\n\t\"Errors\",\r\n\t\"Errors2\",\r\n\t\"FECastle\",\r\n\t\"FECave\",\r\n\t\"FEFort\",\r\n\t\"FEPlain\",\r\n\t\"FETavern\",\r\n\t\"Factory\",\r\n\t\"FieldFortune\",\r\n\t\"FilmSetAAI2\",\r\n\t\"Flowerfield\",\r\n\t\"ForensicCourt\",\r\n\t\"Forest\",\r\n\t\"GS4Night\",\r\n\t\"GantOfficeAA\",\r\n\t\"GetwaterHotelJFA\",\r\n\t\"GetwaterStageJFA\",\r\n\t\"GlobalStudiosIndoorsAA\",\r\n\t\"GlobalStudiosOutdoorsAA\",\r\n\t\"GourdLakeAA\",\r\n\t\"GrandChokmah\",\r\n\t\"GrandStadium\",\r\n\t\"Graveyard\",\r\n\t\"GreatWitchtrialCourt\",\r\n\t\"GrossbergOfficeAA\",\r\n\t\"HD\",\r\n\t\"HQFarm\",\r\n\t\"HQHalloweenTown\",\r\n\t\"HQHolodeck\",\r\n\t\"HQShrine\",\r\n\t\"HQTown\",\r\n\t\"HQVolcanoCherry\",\r\n\t\"HallOfFame\",\r\n\t\"HarborTown\",\r\n\t\"HarvestFestival\",\r\n\t\"HazakuraTemple1TT\",\r\n\t\"HazakuraTemple2TT\",\r\n\t\"Headquarters\",\r\n\t\"Headquarters 2\",\r\n\t\"Hell Correspondence\",\r\n\t\"Hospital\",\r\n\t\"HotelRoomAA\",\r\n\t\"HottiClinicJFA\",\r\n\t\"Innsmouth\",\r\n\t\"InsidePlaneAAI2\",\r\n\t\"Interiors (Day)\",\r\n\t\"Interiors (Night)\",\r\n\t\"JFAAirport\",\r\n\t\"JFABerryBigCircusEast\",\r\n\t\"JFABerryBigCircusWest\",\r\n\t\"JFAGatewaterHotel\",\r\n\t\"JFAHottiClinic\",\r\n\t\"JFAKurainVillage\",\r\n\t\"JFAMattHouse\",\r\n\t\"JapaneseCourt\",\r\n\t\"Kamurocho (Day)\",\r\n\t\"Kamurocho (Night)\",\r\n\t\"Keterburg\",\r\n\t\"Khura'in\",\r\n\t\"Khurain\",\r\n\t\"KokonoeLab\",\r\n\t\"KurainCourt\",\r\n\t\"KurainVillageJFA\",\r\n\t\"LBCastle\",\r\n\t\"LBMisc\",\r\n\t\"LBScotlandYard\",\r\n\t\"Lab 8\",\r\n\t\"Lentomain\",\r\n\t\"Library\",\r\n\t\"LogicChessAAI2\",\r\n\t\"MI - Ashleys Shack\",\r\n\t\"MLP - Apple barn\",\r\n\t\"MLP - CMC Clubhouse\",\r\n\t\"MLP - CMC Clubhouse inside\",\r\n\t\"MLP - Canterlot Castle galaroom\",\r\n\t\"MLP - Canterlot Hallway\",\r\n\t\"MLP - Canterlot Library2\",\r\n\t\"MLP - Canterlot Town\",\r\n\t\"MLP - Canterlot alley\",\r\n\t\"MLP - Canterlot library\",\r\n\t\"MLP - Carousel Boutique\",\r\n\t\"MLP - Clearing\",\r\n\t\"MLP - Curio Shop\",\r\n\t\"MLP - Everfree Forest\",\r\n\t\"MLP - Everfree Forest entrance\",\r\n\t\"MLP - Fluttershy's cottage\",\r\n\t\"MLP - Hospital Room\",\r\n\t\"MLP - Hotelroom\",\r\n\t\"MLP - Library 2F\",\r\n\t\"MLP - Library mainfloor\",\r\n\t\"MLP - Old Castle\",\r\n\t\"MLP - Orchard\",\r\n\t\"MLP - PV Hospital\",\r\n\t\"MLP - PV Street\",\r\n\t\"MLP - Ponyville\",\r\n\t\"MLP - Shining's apartment\",\r\n\t\"MLP - Sugarcube Corner\",\r\n\t\"MLP - Twilight's Lab\",\r\n\t\"MM - Castle\",\r\n\t\"MM - Madokas house\",\r\n\t\"MM - School yard\",\r\n\t\"MM - Street\",\r\n\t\"MM - Street2\",\r\n\t\"MM - classroom\",\r\n\t\"MM - dark hallway\",\r\n\t\"MM - rooftop\",\r\n\t\"MM - room whit Kyubey\",\r\n\t\"MM - school hallway\",\r\n\t\"MM - staircase\",\r\n\t\"MMA-Bedrooms1\",\r\n\t\"MMA-Floor 1\",\r\n\t\"MS - Cathedral\",\r\n\t\"MS - Zakum's Tree\",\r\n\t\"Mansion\",\r\n\t\"MansionAAI2\",\r\n\t\"MansionHQ\",\r\n\t\"Maplecrest - Nightmare\",\r\n\t\"Maplecrest\",\r\n\t\"Market\",\r\n\t\"Mayonaka\",\r\n\t\"MechHangar\",\r\n\t\"Medici Tower\",\r\n\t\"Military Base Exterior\",\r\n\t\"MoeRoomJFA\",\r\n\t\"MuseumAAI2\",\r\n\t\"MuseumTT\",\r\n\t\"Music\",\r\n\t\"NewCourt\",\r\n\t\"New Meridian\",\r\n\t\"Ninetailsvale\",\r\n\t\"Nordon Plains\",\r\n\t\"Nordon Plains Night\",\r\n\t\"OCArcade\",\r\n\t\"OCBebop\",\r\n\t\"OCCourtCafe\",\r\n\t\"OCCourtCounty\",\r\n\t\"OCCourtCruise\",\r\n\t\"OCCourtEndless\",\r\n\t\"OCCourtFinalDestination\",\r\n\t\"OCCourtInverted\",\r\n\t\"OCCourtPirateShip\",\r\n\t\"OCCourtSky\",\r\n\t\"OCCourtSpace\",\r\n\t\"OCCourtSpaceShip\",\r\n\t\"OCCourtTouhou\",\r\n\t\"OCCourtZetta\",\r\n\t\"OCDungeon\",\r\n\t\"OCHospital\",\r\n\t\"OCRoad\",\r\n\t\"OCTownPirate\",\r\n\t\"OCTownShanty\",\r\n\t\"OCWhiteRoom\",\r\n\t\"OfficeHouseHQ\",\r\n\t\"OfficeNightAA\",\r\n\t\"Osaka (Night)\",\r\n\t\"Osaka\",\r\n\t\"OutsidePlaneAAI2\",\r\n\t\"P4UBasement\",\r\n\t\"P4ULab\",\r\n\t\"P4Ubaseball\",\r\n\t\"P4Ubeach\",\r\n\t\"P4Ubuilding\",\r\n\t\"P4Uconcert\",\r\n\t\"P4Ugarden\",\r\n\t\"P4Ugraveyard\",\r\n\t\"P4Uhell\",\r\n\t\"P4Ujail\",\r\n\t\"P4Umisc\",\r\n\t\"P4Unight\",\r\n\t\"P4Uoffices\",\r\n\t\"P4Urailway\",\r\n\t\"P4Urestaurants\",\r\n\t\"P4Urooms\",\r\n\t\"P4Uruins\",\r\n\t\"P4Uschool\",\r\n\t\"P4Ustage1\",\r\n\t\"P4Ustage2\",\r\n\t\"P4Ustation\",\r\n\t\"P4Ustore\",\r\n\t\"P4Utent\",\r\n\t\"P4Utransport\",\r\n\t\"P4Utv\",\r\n\t\"P4Uvelvetroom\",\r\n\t\"PICAAI2\",\r\n\t\"PLvsAAAlchemistHouse\",\r\n\t\"PLvsAABellTower\",\r\n\t\"PLvsAACastle\",\r\n\t\"PLvsAACourtEnglish\",\r\n\t\"PLvsAACourtLabyrinthia\",\r\n\t\"PLvsAACourthouse\",\r\n\t\"PLvsAADefendantLobbyEnglish\",\r\n\t\"PLvsAADefendantLobbyLabyrinthia\",\r\n\t\"PLvsAAEclaireBakery\",\r\n\t\"PLvsAAForest\",\r\n\t\"PLvsAAGreatArchive\",\r\n\t\"PLvsAALabyrinthiaInner\",\r\n\t\"PLvsAALabyrinthiaOuter\",\r\n\t\"PLvsAALondon\",\r\n\t\"PLvsAARougeTavern\",\r\n\t\"PLvsAARuins\",\r\n\t\"PLvsAAStorytellerTower\",\r\n\t\"PLvsAAWagon\",\r\n\t\"PLvsAAWorkshop\",\r\n\t\"PMMMRP\",\r\n\t\"PMMMWitch\",\r\n\t\"ParkingLotAA\",\r\n\t\"PeonyCastle\",\r\n\t\"Persona Afternoon\",\r\n\t\"Persona DH\",\r\n\t\"Persona Morning\",\r\n\t\"Persona Night\",\r\n\t\"PersonaRP\",\r\n\t\"PhoenixOfficeAA\",\r\n\t\"PirateShip\",\r\n\t\"PlaneAAI\",\r\n\t\"PlaneLoungeAAI\",\r\n\t\"PlaneLoungeLandAAI\",\r\n\t\"PlatPark\",\r\n\t\"PlatRemnant\",\r\n\t\"PlatunaArea1\",\r\n\t\"PlatunaArea1HQ\",\r\n\t\"PlatunaArea2\",\r\n\t\"PlatunaArea2HQ\",\r\n\t\"PlatunaMain\",\r\n\t\"PlatunamainHQ\",\r\n\t\"PrecinctAA\",\r\n\t\"PrisonAAI2\",\r\n\t\"PrisonCourtyardAAI2\",\r\n\t\"RG - 104\",\r\n\t\"RG - A-East\",\r\n\t\"RG - AMX\",\r\n\t\"RG - Bus Terminal\",\r\n\t\"RG - Cadoi City\",\r\n\t\"RG - Concert\",\r\n\t\"RG - Dogenzaka\",\r\n\t\"RG - God Pad\",\r\n\t\"RG - Miyashita Underpass\",\r\n\t\"RG - Station Underpass\",\r\n\t\"RG - Trail\",\r\n\t\"RG - Udagawa\",\r\n\t\"RaysDeLite\",\r\n\t\"Retreat\",\r\n\t\"RetreatHQ\",\r\n\t\"RiverVista\",\r\n\t\"Road\",\r\n\t\"Role Play\",\r\n\t\"Ronpa Mansion Area 5\",\r\n\t\"Ronpa Mansion Day\",\r\n\t\"Ronpa Mansion Day2\",\r\n\t\"Ronpa Mansion Day3\",\r\n\t\"Ronpa Mansion Day4\",\r\n\t\"Ronpa Mansion Night\",\r\n\t\"Ronpa Mansion Night2\",\r\n\t\"Ronpa Mansion Night3\",\r\n\t\"Ronpa Mansion Night4\",\r\n\t\"Ronpa mansion Haunted\",\r\n\t\"Ronpers Express\",\r\n\t\"RooftopAAI2\",\r\n\t\"RuinedCastle\",\r\n\t\"RuinedCourt\",\r\n\t\"Ruins Entrance\",\r\n\t\"SDR2 ISLAND\",\r\n\t\"SDR2 ISLAND2\",\r\n\t\"SDR2 ISLAND2 NIGHT\",\r\n\t\"SDR2 ISLAND3\",\r\n\t\"SDR2 ISLAND NIGHT\",\r\n\t\"SI - Bedroom\",\r\n\t\"SI - Class(sunset)\",\r\n\t\"SI - Class\",\r\n\t\"SI - Council1\",\r\n\t\"SI - Council2\",\r\n\t\"SI - Council3\",\r\n\t\"SI - Gym\",\r\n\t\"SI - Gym2\",\r\n\t\"SI - Hall\",\r\n\t\"SI - Hall2\",\r\n\t\"SI - Lockers\",\r\n\t\"SI - Nurse\",\r\n\t\"SI - Office\",\r\n\t\"SI - Pink\",\r\n\t\"SI - Roof\",\r\n\t\"SI - Roof2\",\r\n\t\"SI - School\",\r\n\t\"Seance\",\r\n\t\"SecretRoomsJFA\",\r\n\t\"SecurityCompanyTT\",\r\n\t\"ShipAAI2\",\r\n\t\"SkialForest\",\r\n\t\"Sky\",\r\n\t\"SkyDeck\",\r\n\t\"SoJCourt\",\r\n\t\"SoJDefendantLobby\",\r\n\t\"Somina Castle\",\r\n\t\"Somina Castle Night\",\r\n\t\"SpaceCourt\",\r\n\t\"SpaceCourtBlue\",\r\n\t\"SpaceCourtGreen\",\r\n\t\"SpaceCourtNormal\",\r\n\t\"SpaceCourtOrange\",\r\n\t\"SpaceCourtRainbow\",\r\n\t\"SpaceCourtRed\",\r\n\t\"SpaceCourtYellow\",\r\n\t\"SpacePort\",\r\n\t\"Spaceship\",\r\n\t\"StageAAI\",\r\n\t\"StageDisassembledAAI\",\r\n\t\"SteamBar\",\r\n\t\"SteamGarden\",\r\n\t\"SteamGovt\",\r\n\t\"SteamSquare\",\r\n\t\"SteamStreet\",\r\n\t\"Street\",\r\n\t\"SummerFestival\",\r\n\t\"SummerFestivalEvening\",\r\n\t\"TARDIS\",\r\n\t\"TEOS Lab\",\r\n\t\"TTAtmeyOffice\",\r\n\t\"TTBlueScreensInc\",\r\n\t\"TTDemasqueHideout\",\r\n\t\"TTHazakuraTemple\",\r\n\t\"TTHazakuraTempleInner\",\r\n\t\"TTKBSecurity\",\r\n\t\"TTLordlyTailor\",\r\n\t\"TTTenderLender\",\r\n\t\"TTTresBien\",\r\n\t\"TenderLenderTT\",\r\n\t\"Themis\",\r\n\t\"Titania\",\r\n\t\"TitaniaValley\",\r\n\t\"Togami Mansion\",\r\n\t\"TouhouCourt\",\r\n\t\"Tower\",\r\n\t\"Town\",\r\n\t\"Town Night\",\r\n\t\"Tr0LLc0urt\",\r\n\t\"TrainstationAA\",\r\n\t\"TresBienTT\",\r\n\t\"TrollCourt\",\r\n\t\"Twotorial Village\",\r\n\t\"Twotorial Village Night\",\r\n\t\"VC 1\",\r\n\t\"VLR\",\r\n\t\"VLR2.2\",\r\n\t\"VLR2.3\",\r\n\t\"VLR2\",\r\n\t\"VLR3\",\r\n\t\"VitaminSquareTT\",\r\n\t\"WEN\",\r\n\t\"WaitingRoomAAI\",\r\n\t\"WestAAI\",\r\n\t\"WinterPalaceAAI2\",\r\n\t\"WitchTrialCourt\",\r\n\t\"WitchtrialCourtHQ\",\r\n\t\"Witchwood\",\r\n\t\"WorldEmulator\",\r\n\t\"Wreckage (SG)\",\r\n\t\"Wrightagency\",\r\n\t\"Xmas\",\r\n\t\"Zetta\",\r\n\t\"animation\",\r\n\t\"apollojustice\",\r\n\t\"background\",\r\n\t\"basement\",\r\n\t\"birthday\",\r\n\t\"blackout\",\r\n\t\"chess\",\r\n\t\"chessw1\",\r\n\t\"chessw2\",\r\n\t\"chessw3\",\r\n\t\"chessw4\",\r\n\t\"christmas\",\r\n\t\"circus\",\r\n\t\"classtrial\",\r\n\t\"cofe\",\r\n\t\"courthouseofgods\",\r\n\t\"cruise\",\r\n\t\"cruise court\",\r\n\t\"custom\",\r\n\t\"custom1\",\r\n\t\"custom2\",\r\n\t\"custom3\",\r\n\t\"custom4\",\r\n\t\"custom5\",\r\n\t\"custom6\",\r\n\t\"custom7\",\r\n\t\"custom8\",\r\n\t\"custom9\",\r\n\t\"custom10\",\r\n\t\"daimoncourt\",\r\n\t\"default - Kopie\",\r\n\t\"default\",\r\n\t\"default_christmas\",\r\n\t\"defendantlobby\",\r\n\t\"defendantlobbyapollo\",\r\n\t\"detentioncenter\",\r\n\t\"doppler\",\r\n\t\"dr1stfloor\",\r\n\t\"dr1stfloordorms\",\r\n\t\"dr1stfloorhalls\",\r\n\t\"dr2ndfloor\",\r\n\t\"dr3rdfloor\",\r\n\t\"druq1stfloordorms\",\r\n\t\"druq2ndfloordorms\",\r\n\t\"dualdestinies\",\r\n\t\"dualdestiniesOG\",\r\n\t\"dungeon\",\r\n\t\"endless\",\r\n\t\"englishcourt\",\r\n\t\"forest\",\r\n\t\"gs4\",\r\n\t\"gs4night\",\r\n\t\"gs5\",\r\n\t\"hd\",\r\n\t\"inn\",\r\n\t\"investigationbando\",\r\n\t\"investigationsembassylobby\",\r\n\t\"investigationsgourdlake\",\r\n\t\"investigationsmilesoffice\",\r\n\t\"investigationsplaneair\",\r\n\t\"investigationsroyalcourt\",\r\n\t\"investigationstvroom\",\r\n\t\"investigationswestern\",\r\n\t\"investigationswitchtown\",\r\n\t\"island 1(uranus zone)\",\r\n\t\"lcourt\",\r\n\t\"legacy\",\r\n\t\"lobbyDGS-ENG\",\r\n\t\"lobbyDGS-JAP\",\r\n\t\"lobbyPLvsAA-ENG\",\r\n\t\"lobbyPLvsAA-LAB\",\r\n\t\"lobbySOJ\",\r\n\t\"magatama\",\r\n\t\"magatama1\",\r\n\t\"magatama2\",\r\n\t\"magatama3\",\r\n\t\"magatama4\",\r\n\t\"magatama5\",\r\n\t\"marblefade\",\r\n\t\"matrix\",\r\n\t\"matrixall\",\r\n\t\"matrixangry\",\r\n\t\"matrixangrysad\",\r\n\t\"matrixangrysurprised\",\r\n\t\"matrixhappy\",\r\n\t\"matrixhappyangry\",\r\n\t\"matrixhappysad\",\r\n\t\"matrixhappysurprised\",\r\n\t\"matrixsad\",\r\n\t\"matrixsadsurprised\",\r\n\t\"matrixsurprise\",\r\n\t\"mlp\",\r\n\t\"newcourt\",\r\n\t\"night (no lights)\",\r\n\t\"plvsaa\",\r\n\t\"policestation\",\r\n\t\"prisonvestigation\",\r\n\t\"sdr2classtrial\",\r\n\t\"sky\",\r\n\t\"sshope2ndfloorday(incident)\",\r\n\t\"sshope2ndfloorday\",\r\n\t\"sshope2ndfloornight(incident)\",\r\n\t\"sshope2ndfloornight\",\r\n\t\"sshopeday(incident)\",\r\n\t\"sshopeday\",\r\n\t\"sshopenight(incident)\",\r\n\t\"sshopenight\",\r\n\t\"thief\",\r\n\t\"thiefbash\",\r\n\t\"thiefpoint\",\r\n\t\"thiefpoisoning\",\r\n\t\"thiefprints\",\r\n\t\"thiefstab\",\r\n\t\"thiefsteal\",\r\n\t\"turnaboutstorm - Kopie\",\r\n\t\"turnaboutstorm\",\r\n\t\"vocalcourt\",\r\n\t\"witchtrialcourt\"\r\n];","/*\r\n * Glorious webAO\r\n * made by sD, refactored by oldmud0 and Qubrick\r\n * credits to aleks for original idea and source\r\n*/\r\n\r\n// Uses the Gify library:\r\n// https://github.com/rfrench/gify\r\n// The following comment is needed for ESLint:\r\n/* global gify */\r\n\r\nimport background_arr from \"./backgrounds.js\";\r\nimport evidence_arr from \"./evidence.js\";\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://s3.wasabisys.com/webao/base/\";\r\nconst MUSIC_HOST = AO_HOST + \"sounds/music/\";\r\nconst CHAR_SELECT_WIDTH = 8;\r\nconst UPDATE_INTERVAL = 60;\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 selectedEffect = 0;\r\nlet selectedMenu = 1;\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.flip = false;\r\n\t\tthis.presentable = false;\r\n\r\n\t\tthis.hp = [0, 0];\r\n\r\n\t\tthis.playerID = 1;\r\n\t\tthis.charID = -1;\r\n\t\tthis.testimonyID = 0;\r\n\r\n\t\tthis.chars = [];\r\n\t\tthis.emotes = [];\r\n\t\tthis.evidences = [];\r\n\r\n\t\tthis.resources = {\r\n\t\t\t\"holdit\": {\r\n\t\t\t\t\"src\": \"misc/holdit.gif\",\r\n\t\t\t\t\"duration\": 720\r\n\t\t\t},\r\n\t\t\t\"objection\": {\r\n\t\t\t\t\"src\": \"misc/objection.gif\",\r\n\t\t\t\t\"duration\": 720\r\n\t\t\t},\r\n\t\t\t\"takethat\": {\r\n\t\t\t\t\"src\": \"misc/takethat.gif\",\r\n\t\t\t\t\"duration\": 840\r\n\t\t\t},\r\n\t\t\t\"witnesstestimony\": {\r\n\t\t\t\t\"src\": \"misc/witnesstestimony.gif\",\r\n\t\t\t\t\"duration\": 1560,\r\n\t\t\t\t\"sfx\": \"sounds/general/sfx-testimony.wav\"\r\n\t\t\t},\r\n\t\t\t\"crossexamination\": {\r\n\t\t\t\t\"src\": \"misc/crossexamination.gif\",\r\n\t\t\t\t\"duration\": 1600,\r\n\t\t\t\t\"sfx\": \"sounds/general/sfx-testimony2.wav\"\r\n\t\t\t}\r\n\t\t};\r\n\r\n\t\tthis.selectedEmote = -1;\r\n\t\tthis.selectedEvidence = 0;\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\"LE\": (args) => this.handleLE(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\"RT\": (args) => this.handleRT(args),\r\n\t\t\t\"ZZ\": (args) => this.handleZZ(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 * Gets the player's currently selected evidence if presentable.\r\n\t */\r\n\tmyEvidence() {\r\n\t\treturn this.presentable ? this.selectedEvidence : 0;\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#${escapeChat(encodeChat(document.getElementById(\"OOC_name\").value))}#${escapeChat(encodeChat(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 {number} 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 * @param {string} evidence the filename of evidence to show\r\n\t * @param {number} flip change to 1 to reverse sprite for position changes\r\n\t * @param {string} flash screen flash effect\r\n\t * @param {string} color text color\r\n\t */\r\n\tsendIC(speaking, name, silent, message, side, ssfxname, zoom, ssfxdelay, objection, evidence, flip, flash, color) {\r\n\t\tthis.serv.send(\r\n\t\t\t`MS#chat#${speaking}#${name}#${silent}` +\r\n\t\t\t`#${escapeChat(encodeChat(message))}#${side}#${ssfxname}#${zoom}` +\r\n\t\t\t`#${this.charID}#${ssfxdelay}#${selectedShout}#${evidence}#${flip}#${flash}#${color}#%`\r\n\t\t);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends add evidence command.\r\n\t * @param {string} evidence name\r\n\t * @param {string} evidence description\r\n\t * @param {string} evidence image filename\r\n\t */\r\n\tsendPE(name, desc, img) {\r\n\t\tthis.serv.send(`PE#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends edit evidence command.\r\n\t * @param {number} evidence id\r\n\t * @param {string} evidence name\r\n\t * @param {string} evidence description\r\n\t * @param {string} evidence image filename\r\n\t */\r\n\tsendEE(id, name, desc, img) {\r\n\t\tthis.serv.send(`EE#${id}#${escapeChat(encodeChat(name))}#${escapeChat(encodeChat(desc))}#${img}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends delete evidence command.\r\n\t * @param {number} evidence id\r\n\t */\r\n\tsendDE(id) {\r\n\t\tthis.serv.send(`DE#${id}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends health point command.\r\n\t * @param {number} side the position\r\n\t * @param {number} hp the health point\r\n\t */\r\n\tsendHP(side, hp) {\r\n\t\tthis.serv.send(`HP#${side}#${hp}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends call mod command.\r\n\t * @param {string} message to mod\r\n\t */\r\n\tsendZZ(msg) {\r\n\t\tthis.serv.send(`ZZ#${msg}#%`);\r\n\t}\r\n\r\n\t/**\r\n\t * Sends testimony command.\r\n\t * @param {string} testimony type\r\n\t */\r\n\tsendRT(testimony) {\r\n\t\tif (this.chars[this.charID].side == \"jud\") {\r\n\t\t\tthis.serv.send(`RT#${testimony}#%`);\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.3#%\");\r\n\t\tthis.checkUpdater = setInterval(() => this.sendCheck(), 5000);\r\n\t}\r\n\r\n\t/**\r\n\t * Load game resources.\r\n\t */\r\n\tloadResources() {\r\n\t\t// Set to playerID to server chat name\r\n\t\t// TODO: Make a text box for this!\r\n\t\tdocument.getElementById(\"OOC_name\").value = \"web\" + this.playerID;\r\n\r\n\t\t// Load evidence array to select\r\n\t\tconst evidence_select = document.getElementById(\"evi_select\");\r\n\t\tevidence_select.add(new Option(\"Custom\", 0));\r\n\t\tevidence_arr.forEach(evidence => {\r\n\t\t\tevidence_select.add(new Option(evidence));\r\n\t\t});\r\n\r\n\t\t// Load background array to select\r\n\t\tconst background_select = document.getElementById(\"bg_select\");\r\n\t\tbackground_select.add(new Option(\"Custom\", 0));\r\n\t\tbackground_arr.forEach(background => {\r\n\t\t\tbackground_select.add(new Option(background));\r\n\t\t});\r\n\t\t// Calculate gif duration of shouts\r\n\t\tconst shouts = [\"holdit\", \"objection\", \"takethat\"];\r\n\t\tfor (let i = 0; i < shouts.length; i++) {\r\n\t\t\tlet shout_src = AO_HOST + this.resources[shouts[i]][\"src\"].toLowerCase();\r\n\t\t\tfileExists(shout_src, this.callbackLoadImageResources, shouts[i]);\r\n\t\t}\r\n\r\n\t\t// Calculate gif duration of testimony\r\n\t\tconst testimony = [\"witnesstestimony\", \"crossexamination\"];\r\n\t\tfor (let i = 0; i < testimony.length; i++) {\r\n\t\t\tconst testimony_src = `${AO_HOST}themes/default/${testimony[i]}.gif`;\r\n\t\t\t// Check image existed\r\n\t\t\tfileExists(testimony_src, this.callbackLoadImageResources, testimony[i]);\r\n\t\t\t// Check sfx existed\r\n\t\t\tfileExists(AO_HOST + this.resources[testimony[i]][\"sfx\"].toLowerCase(), this.callbackLoadSFXResources, testimony[i]);\r\n\t\t}\r\n\t\t// TODO: Cache some resources\r\n\r\n\t}\r\n\r\n\t/**\r\n\t * Callback for image resources.\r\n\t * @param {boolean} result the image is existed or not\r\n\t * @param {string} resource the resource name\r\n\t * @param {string} src the url of resource\r\n\t */\r\n\tcallbackLoadImageResources(result, resource, src) {\r\n\t\tif (result) {\r\n\t\t\tclient.resources[resource][\"src\"] = src;\r\n\t\t\tviewport.getAnimLength(src, client.callbackGetResourceLength, resource);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Callback for animation duration resource\r\n\t * @param {integer} length the animation length\r\n\t * @param {string} resource the resource name\r\n\t */\r\n\tcallbackGetResourceLength(length, resource) {\r\n\t\tclient.resources[resource][\"duration\"] = length;\r\n\t}\r\n\r\n\t/**\r\n\t * Callback for sfx resources.\r\n\t * @param {boolean} result the audio is existed or not\r\n\t * @param {string} resource the resource name\r\n\t * @param {string} src the url of resource\r\n\t */\r\n\tcallbackLoadSFXResources(result, resource, src) {\r\n\t\tif (result) {\r\n\t\t\tclient.resources[resource][\"sfx\"] = src;\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Create observer to detect BBCode elements\r\n\t * then manipulate them.\r\n\t */\r\n\tinitialObservBBCode() {\r\n\t\tconst target = document.getElementById(\"client_inner_chat\");\r\n\t\tconst observer = new MutationObserver(function (mutations) {\r\n\t\t\tmutations.forEach(function (mutation) {\r\n\t\t\t\tconst children = mutation.addedNodes;\r\n\t\t\t\tif (children !== null) {\r\n\t\t\t\t\tchildren.forEach(function (node) {\r\n\t\t\t\t\t\tif (node.tagName == \"C\") {\r\n\t\t\t\t\t\t\tnode.style.color = node.getAttribute(\"a\");\r\n\t\t\t\t\t\t} else if (node.tagName == \"M\") {\r\n\t\t\t\t\t\t\tif (node.hasAttribute(\"a\")) {\r\n\t\t\t\t\t\t\t\tnode.style.backgroundColor = node.getAttribute(\"a\");\r\n\t\t\t\t\t\t\t} else {\r\n\t\t\t\t\t\t\t\tnode.style.backgroundColor = \"yellow\";\r\n\t\t\t\t\t\t\t\tnode.style.color = \"black\";\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t}\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\tconst config = {\r\n\t\t\tattributes: true,\r\n\t\t\tchildList: true\r\n\t\t};\r\n\t\tobserver.observe(target, config);\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 * XXX: a nasty hack made by gameboyprinter.\r\n\t * @param {string} msg chat message to prepare for display \r\n\t */\r\n\tprepChat(msg){\r\n\t\t// TODO: make this less awful\r\n\t\treturn decodeBBCode(unescapeChat(decodeChat(msg)));\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\tconst chatmsg = {\r\n\t\t\t\t// pre: 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: this.prepChat(args[5]), // Escape HTML tag, Use BBCode Only!\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\tflip: 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 += `${decodeChat(unescapeChat(args[1]))}: ${decodeChat(unescapeChat(args[2]))}\\r\\n`;\r\n\t\tif (oocLog.scrollTop > oocLog.scrollHeight - 600) {\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].toLowerCase();\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].toLowerCase()) + \"/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].toLowerCase()) + \"/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 evidence list, all evidences at once\r\n\t * item per packet.\r\n\t * \r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleLE(args) {\r\n\t\tthis.evidences = [];\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\tconst arg = args[i].split(\"&\");\r\n\t\t\tthis.evidences[i - 1] = {\r\n\t\t\t\t\"name\": decodeChat(unescapeChat(arg[0])),\r\n\t\t\t\t\"desc\": decodeChat(unescapeChat(arg[1])),\r\n\t\t\t\t\"filename\": escape(arg[2]),\r\n\t\t\t\t\"icon\": AO_HOST + \"evidence/\" + escape(arg[2].toLowerCase())\r\n\t\t\t};\r\n\t\t}\r\n\r\n\t\tconst evidence_box = document.getElementById(\"evidences\");\r\n\t\tevidence_box.innerHTML = \"\";\r\n\t\tfor (let i = 1; i <= this.evidences.length; i++) {\r\n\t\t\tevidence_box.innerHTML += ``;\r\n\t\t}\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\tconst hmusiclist = document.getElementById(\"client_musiclist\");\r\n\t\tlet flagAudio = false;\r\n\r\n\t\tfor (let i = 1; i < args.length - 1; i++) {\r\n\t\t\t// Check when found the song for the first time\r\n\t\t\tif (/\\.(?:wav|mp3|mp4|ogg|opus)$/i.test(args[i]) && !flagAudio) {\r\n\t\t\t\tflagAudio = true;\r\n\t\t\t}\r\n\r\n\t\t\tif (flagAudio) {\r\n\t\t\t\t// After reached the audio put everything in the music list\r\n\t\t\t\tconst 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} else {\r\n\t\t\t\t// Create area button\r\n\t\t\t\tconst newarea = document.createElement(\"SPAN\");\r\n\t\t\t\tnewarea.className = \"location-box\";\r\n\t\t\t\tnewarea.textContent = args[i];\r\n\t\t\t\tnewarea.onclick = function () {\r\n\t\t\t\t\tarea_click(this);\r\n\t\t\t\t};\r\n\t\t\t\tdocument.getElementById(\"areas\").appendChild(newarea);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// We need to check if the last area that we got was actually a category\r\n\t\t// header for music. If it was, then move it over to the music list.\r\n\t\tconst area_box = document.getElementById(\"areas\");\r\n\t\tif (area_box.lastChild.textContent.startsWith(\"=\")) {\r\n\t\t\tconst audio_title = document.createElement(\"OPTION\");\r\n\t\t\taudio_title.text = area_box.lastChild.textContent;\r\n\t\t\thmusiclist.insertBefore(audio_title, hmusiclist.firstChild);\r\n\t\t\tarea_box.removeChild(area_box.lastChild);\r\n\t\t}\r\n\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\tconst bg_index = getIndexFromSelect(\"bg_select\", escape(args[1]));\r\n\t\tdocument.getElementById(\"bg_select\").selectedIndex = bg_index;\r\n\t\tupdateBackgroundPreview();\r\n\t\tif (bg_index == 0) {\r\n\t\t\tdocument.getElementById(\"bg_filename\").value = args[1];\r\n\t\t}\r\n\t\tdocument.getElementById(\"bg_preview\").src = AO_HOST + \"background/\" + escape(args[1].toLowerCase()) + \"/defenseempty.png\";\r\n\t\tif (this.charID == -1) {\r\n\t\t\tchangeBackground(\"jud\");\r\n\t\t} else {\r\n\t\t\tchangeBackground(this.chars[this.charID].side);\r\n\t\t}\r\n\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\tconst percent_hp = args[2] * 10;\r\n\t\tif (args[1] == 1) {\r\n\t\t\t// Def hp\r\n\t\t\tthis.hp[0] = args[2];\r\n\t\t\t$(\"#client_defense_hp > .health-bar\").animate({\r\n\t\t\t\t\"width\": percent_hp + \"%\"\r\n\t\t\t}, 500);\r\n\t\t} else {\r\n\t\t\t// Pro hp\r\n\t\t\tthis.hp[1] = args[2];\r\n\t\t\t$(\"#client_prosecutor_hp > .health-bar\").animate({\r\n\t\t\t\t\"width\": percent_hp + \"%\"\r\n\t\t\t}, 500);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a testimony states.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleRT(args) {\r\n\t\tif (args[1] == \"testimony1\") {\r\n\t\t\t//Witness Testimony\r\n\t\t\tthis.testimonyID = 1;\r\n\t\t} else {\r\n\t\t\t//Cross Examination\r\n\t\t\tthis.testimonyID = 2;\r\n\t\t}\r\n\t\tviewport.initTestimonyUpdater();\r\n\t}\r\n\r\n\t/**\r\n\t * Handles a call mod message.\r\n\t * @param {Array} args packet arguments\r\n\t */\r\n\thandleZZ(args) {\r\n\t\tconst oocLog = document.getElementById(\"client_ooclog\");\r\n\t\toocLog.innerHTML += `$Alert: ${decodeChat(unescapeChat(args[1]))}\\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 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\tlet tr;\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\ttr = document.createElement(\"TR\");\r\n\t\t\t}\r\n\t\t\tconst td = document.createElement(\"TD\");\r\n\t\t\tlet icon_chosen = \"\";\r\n\t\t\tconst 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}\r\n\t\t\ttd.innerHTML = `${this.chars[i].name}\";\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\t//changeBackground(\"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\tdocument.getElementById(\"client_inputbox\").style.display = \"\";\r\n\t\tconst me = this.me();\r\n\t\tconst emotes = this.emotes;\r\n\t\tconst emotesList = document.getElementById(\"client_emo\");\r\n\t\temotesList.innerHTML = \"\"; // Clear emote box\r\n\t\temotesList.style.display = \"\";\r\n\t\tconst xhr = new XMLHttpRequest();\r\n\t\txhr.withCredentials = false;\r\n\t\txhr.open(\"GET\", AO_HOST + \"characters/\" + escape(this.me().name.toLowerCase()) + \"/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\tconst linifile = this.responseText;\r\n\t\t\t\tconst pinifile = INI.parse(linifile);\r\n\t\t\t\tme.side = pinifile.Options.side;\r\n\t\t\t\tupdateActionCommands(me.side);\r\n\t\t\t\tfor (let i = 1; i <= pinifile.Emotions.number; i++) {\r\n\t\t\t\t\tconst 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\t// Make sure the asset server is case insensitive, or that everything on it is lowercase\r\n\t\t\t\t\temotes[i] = {\r\n\t\t\t\t\t\tdesc: emoteinfo[0].toLowerCase(),\r\n\t\t\t\t\t\tspeaking: emoteinfo[1].toLowerCase(),\r\n\t\t\t\t\t\tsilent: emoteinfo[2].toLowerCase(),\r\n\t\t\t\t\t\tzoom: emoteinfo[3],\r\n\t\t\t\t\t\tsfx: esfx.toLowerCase(),\r\n\t\t\t\t\t\tsfxdelay: esfxd,\r\n\t\t\t\t\t\tbutton_off: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_off.png`,\r\n\t\t\t\t\t\tbutton_on: AO_HOST + `characters/${escape(me.name).toLowerCase()}/emotions/button${i}_on.png`\r\n\t\t\t\t\t};\r\n\t\t\t\t\temotesList.innerHTML += \r\n\t\t\t\t\t\t`\"${emotes[i].desc}\"\r\n\t\t\t\t\t\t`;\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\"startpreanim\": false,\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\t\"preanimdelay\": 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\t\tthis.testimonyUpdater = null;\r\n\r\n\t\tthis.bgname = \"gs4\";\r\n\r\n\t\tthis.testimonyTimer = 0;\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.toLowerCase()}/`;\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\t// If preanim existed then determine the length\r\n\t\tif (chatmsg.preanim != \"-\") {\r\n\t\t\tchatmsg.preanimdelay = this.getAnimLength(`${AO_HOST}characters/${escape(chatmsg.name.toLowerCase())}/${chatmsg.preanim.toLowerCase()}.gif`, this.initUpdater);\r\n\t\t} else {\r\n\t\t\tthis.initUpdater(0);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Intialize updater\r\n\t * @param {number} animdelay the length of pre-animation \r\n\t */\r\n\tinitUpdater(animdelay) {\r\n\t\tviewport.chatmsg.preanimdelay = parseInt(animdelay);\r\n\t\tviewport.updater = setTimeout(() => viewport.updateText(), UPDATE_INTERVAL);\r\n\t}\r\n\r\n\t/**\r\n\t * Intialize testimony updater \r\n\t */\r\n\tinitTestimonyUpdater() {\r\n\t\tif (client.testimonyID > 0) {\r\n\t\t\tlet testimony = \"\";\r\n\t\t\tif (client.testimonyID == 1) {\r\n\t\t\t\ttestimony = \"witnesstestimony\";\r\n\t\t\t} else if (client.testimonyID == 2) {\r\n\t\t\t\ttestimony = \"crossexamination\";\r\n\t\t\t}\r\n\t\t\t(new Audio(client.resources[testimony][\"sfx\"])).play();\r\n\t\t\tthis.testimonyTimer = 0;\r\n\t\t\tconst testimonyOverlay = document.getElementById(\"client_testimony\");\r\n\t\t\ttestimonyOverlay.src = client.resources[testimony][\"src\"];\r\n\t\t\ttestimonyOverlay.style.display = \"\";\r\n\t\t\tthis.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Gets animation length.\r\n\t * @param {string} filename the animation file name\r\n\t * @param {function} callback the callback function\r\n\t * @param {object} param \r\n\t */\r\n\tgetAnimLength(filename, callback, param) {\r\n\t\tconst request = new XMLHttpRequest();\r\n\t\trequest.open(\"GET\", filename, true);\r\n\t\trequest.responseType = \"arraybuffer\";\r\n\t\trequest.addEventListener(\"load\", function () {\r\n\t\t\tconst gifInfo = gify.getInfo(request.response);\r\n\t\t\tconsole.log(gifInfo[\"duration\"]);\r\n\t\t\t// Return animation length\r\n\t\t\tcallback(gifInfo[\"duration\"], param);\r\n\t\t});\r\n\t\trequest.send();\r\n\t}\r\n\r\n\t/**\r\n\t * Updates the testimony overaly\r\n\t */\r\n\tupdateTestimony() {\r\n\t\t//Update timer\r\n\t\tthis.testimonyTimer = this.testimonyTimer + UPDATE_INTERVAL;\r\n\r\n\t\tif (client.testimonyID == 1) {\r\n\t\t\t//Witness Testimony\r\n\t\t\tif (this.testimonyTimer >= client.resources[\"witnesstestimony\"][\"duration\"]) {\r\n\t\t\t\t//Finish\r\n\t\t\t\tthis.disposeTestimony();\r\n\t\t\t} else {\r\n\t\t\t\tthis.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL);\r\n\t\t\t}\r\n\t\t} else if (client.testimonyID == 2) {\r\n\t\t\t//Cross Examination\r\n\t\t\tif (this.testimonyTimer >= client.resources[\"crossexamination\"][\"duration\"]) {\r\n\t\t\t\t//Finish\r\n\t\t\t\tthis.disposeTestimony();\r\n\t\t\t} else {\r\n\t\t\t\tthis.testimonyUpdater = setTimeout(() => this.updateTestimony(), UPDATE_INTERVAL);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis.disposeTestimony();\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Dispose the testimony overlay\r\n\t */\r\n\tdisposeTestimony() {\r\n\t\tclient.testimonyID = 0;\r\n\t\tthis.testimonyTimer = 0;\r\n\t\tdocument.getElementById(\"client_testimony\").style.display = \"none\";\r\n\t\tclearTimeout(this.testimonyUpdater);\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\tconst nameBox = document.getElementById(\"client_name\");\r\n\t\tconst chatBox = document.getElementById(\"client_chat\");\r\n\t\tconst charSprite = document.getElementById(\"client_char\");\r\n\t\tconst eviBox = document.getElementById(\"client_evi\");\r\n\t\tconst background = document.getElementById(\"client_background\");\r\n\t\tconst shoutSprite = document.getElementById(\"client_shout\");\r\n\t\tconst chatBoxInner = document.getElementById(\"client_inner_chat\");\r\n\r\n\t\t// Flip the character\r\n\t\tif (this.chatmsg.flip == 1) {\r\n\t\t\tcharSprite.style.transform = \"scaleX(-1)\";\r\n\t\t} else {\r\n\t\t\tcharSprite.style.transform = \"scaleX(1)\";\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\t// Reset screen background\r\n\t\t\tbackground.style.backgroundColor = \"transparent\";\r\n\t\t\t// Hide message and evidence window\r\n\t\t\tnameBox.style.display = \"none\";\r\n\t\t\tchatBox.style.display = \"none\";\r\n\t\t\teviBox.style.opacity = \"0\";\r\n\t\t\teviBox.style.height = \"0%\";\r\n\t\t\tconst shouts = {\r\n\t\t\t\t\"1\": \"holdit\",\r\n\t\t\t\t\"2\": \"objection\",\r\n\t\t\t\t\"3\": \"takethat\"\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\tshoutSprite.src = client.resources[shout][\"src\"];\r\n\t\t\t\t(new Audio(`${AO_HOST}characters/${this.chatmsg.name.toLowerCase()}/${shout}.wav`)).play();\r\n\t\t\t\tthis.shoutTimer = 850;\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.startpreanim = true;\r\n\t\t}\r\n\r\n\t\tif (this.textTimer >= this.shoutTimer && this.chatmsg.startpreanim) {\r\n\t\t\t// Effect stuff\r\n\t\t\tif (this.chatmsg.flash == 2) {\r\n\t\t\t\t//Shake screen\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-stab.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$(\"#client_gamewindow\").effect(\"shake\", {\r\n\t\t\t\t\t\"direction\": \"up\"\r\n\t\t\t\t});\r\n\t\t\t} else if (this.chatmsg.flash == 1) {\r\n\t\t\t\t//Flash screen\r\n\t\t\t\tbackground.style.backgroundColor = \"white\";\r\n\t\t\t\tthis.sfxaudio.pause();\r\n\t\t\t\tthis.sfxplayed = 1;\r\n\t\t\t\tthis.sfxaudio.src = AO_HOST + \"sounds/general/sfx-realization.wav\";\r\n\t\t\t\tthis.sfxaudio.play();\r\n\t\t\t\t$(\"#client_gamewindow\").effect(\"pulsate\");\r\n\t\t\t}\r\n\r\n\t\t\t//Pre-animation stuff\r\n\t\t\tif (this.chatmsg.preanimdelay > 0) {\r\n\t\t\t\tshoutSprite.src = \"misc/placeholder.gif\";\r\n\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.preanim.toLowerCase() + \".gif\";\r\n\t\t\t}\r\n\t\t\tthis.chatmsg.startpreanim = false;\r\n\t\t\tthis.chatmsg.startspeaking = true;\r\n\t\t} else if (this.textTimer >= this.shoutTimer + this.chatmsg.preanimdelay && !this.chatmsg.startpreanim) {\r\n\t\t\tif (this.chatmsg.startspeaking) {\r\n\t\t\t\tif (this.chatmsg.evidence > 0) {\r\n\t\t\t\t\t// Prepare evidence\r\n\t\t\t\t\teviBox.style.backgroundImage = \"url('\" + client.evidences[this.chatmsg.evidence - 1].icon + \"')\";\r\n\r\n\t\t\t\t\tif (this.chatmsg.side == \"def\") {\r\n\t\t\t\t\t\t// Only def show evidence on right\r\n\t\t\t\t\t\teviBox.style.right = \"1.5em\";\r\n\t\t\t\t\t\teviBox.style.left = \"initial\";\r\n\t\t\t\t\t\t$(\"#client_evi\").animate({\r\n\t\t\t\t\t\t\theight: \"30%\",\r\n\t\t\t\t\t\t\topacity: 1\r\n\t\t\t\t\t\t}, 250);\r\n\t\t\t\t\t} else {\r\n\t\t\t\t\t\teviBox.style.right = \"initial\";\r\n\t\t\t\t\t\teviBox.style.left = \"1.5em\";\r\n\t\t\t\t\t\t$(\"#client_evi\").animate({\r\n\t\t\t\t\t\t\theight: \"30%\",\r\n\t\t\t\t\t\t\topacity: 1\r\n\t\t\t\t\t\t}, 250);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\r\n\t\t\t\tnameBox.style.display = \"block\";\r\n\t\t\t\tnameBox.style.fontSize = (nameBox.offsetHeight * 0.7) + \"px\";\r\n\r\n\t\t\t\twhile (nameBox.hasChildNodes()) {\r\n\t\t\t\t\tnameBox.removeChild(nameBox.firstChild);\r\n\t\t\t\t}\r\n\t\t\t\tnameBox.appendChild(document.createTextNode(this.chatmsg.nameplate));\r\n\r\n\t\t\t\tchatBox.style.display = \"block\";\r\n\t\t\t\tchatBox.style.fontSize = (chatBox.offsetHeight * 0.25) + \"px\";\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\tchatBoxInner.style.color = colors[this.chatmsg.color] || \"#ffffff\";\r\n\t\t\t\tthis.chatmsg.startspeaking = false;\r\n\r\n\t\t\t\tif (this.chatmsg.preanimdelay == 0) {\r\n\t\t\t\t\tshoutSprite.src = \"misc/placeholder.gif\";\r\n\t\t\t\t\tchangeBackground(this.chatmsg.side);\r\n\t\t\t\t}\r\n\r\n\t\t\t\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.speaking.toLowerCase() + \".gif\";\r\n\r\n\t\t\t\tif (this.textnow == this.chatmsg.content) {\r\n\t\t\t\t\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.silent.toLowerCase() + \".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\r\n\t\t\t\t\twhile (chatBoxInner.hasChildNodes()) {\r\n\t\t\t\t\t\tchatBoxInner.removeChild(chatBoxInner.firstChild);\r\n\t\t\t\t\t}\r\n\t\t\t\t\tchatBoxInner.appendChild(document.createTextNode(this.textnow));\r\n\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\tcharSprite.src = AO_HOST + \"characters/\" + escape(this.chatmsg.name.toLowerCase()) + \"/\" + this.chatmsg.silent.toLowerCase() + \".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\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.toLowerCase()) + \".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 myevi = client.myEvidence();\r\n\t\tlet myflip = ((client.flip) ? 1 : 0);\r\n\t\tlet mycolor = document.getElementById(\"textcolor\").value;\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, myevi, myflip, selectedEffect, mycolor);\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 (selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t}\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\tconst 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 when an item on the area list is clicked.\r\n * @param {MouseEvent} event\r\n */\r\nexport function area_click(el) {\r\n\tconst area = el.textContent;\r\n\tclient.sendMusicChange(area);\r\n\r\n\tconst areaHr = document.createElement(\"div\");\r\n\tareaHr.className = \"hrtext\";\r\n\tareaHr.textContent = `switched to ${el.textContent}`;\r\n\tdocument.getElementById(\"client_log\").appendChild(areaHr);\r\n}\r\nwindow.area_click = area_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 a file exists at the specified URI.\r\n * @param {string} url the URI to be checked\r\n * @param {function} callback the function to be called when finished\r\n * @param {object} param \r\n */\r\nfunction fileExists(url, callback, param) {\r\n\tconst xhttp = new XMLHttpRequest();\r\n\txhttp.onreadystatechange = function () {\r\n\t\tif (this.readyState == 4 && this.status == 200) {\r\n\t\t\tcallback(true, param, url);\r\n\t\t} else {\r\n\t\t\tcallback(false, param, url);\r\n\t\t}\r\n\t};\r\n\txhttp.open(\"GET\", url, true);\r\n\txhttp.send();\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\tlet standname;\r\n\tconst 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\tcase \"def\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"defenseempty.png\";\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\tfileExists(bgfolder + \"defensedesk.png\", callbackChangeBackground, position);\r\n\t\tstandname = \"defense\";\r\n\t\tbreak;\r\n\tcase \"pro\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prosecutorempty.png\";\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\tfileExists(bgfolder + \"defensedesk.png\", callbackChangeBackground, position);\r\n\t\tstandname = \"prosecution\";\r\n\t\tbreak;\r\n\tcase \"hld\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"helperstand.png\";\r\n\t\tstandname = \"defense\";\r\n\t\tbreak;\r\n\tcase \"hlp\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"prohelperstand.png\";\r\n\t\tstandname = \"prosecution\";\r\n\t\tbreak;\r\n\tcase \"wit\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"witnessempty.png\";\r\n\t\tdocument.getElementById(\"client_bench\").style.display = \"block\";\r\n\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"estrado.png\";\r\n\t\tstandname = \"prosecution\";\r\n\t\tbreak;\r\n\tcase \"jud\":\r\n\t\tdocument.getElementById(\"client_court\").src = bgfolder + \"judgestand.png\";\r\n\t\tstandname = \"prosecution\";\r\n\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 * Callback for desk resource\r\n * \r\n * Valid positions: `def, pro, hld, hlp, wit, jud`\r\n * @param {boolean} result the image is existed or not\r\n * @param {string} position the position to change into\r\n */\r\nfunction callbackChangeBackground(result, position) {\r\n\tlet bgfolder = viewport.bgFolder();\r\n\tif (position == \"def\") {\r\n\t\tif (result) {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"defensedesk.png\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"bancodefensa.png\";\r\n\t\t}\r\n\t} else {\r\n\t\tif (result) {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"prosecutiondesk.png\";\r\n\t\t} else {\r\n\t\t\tdocument.getElementById(\"client_bench\").src = bgfolder + \"bancoacusacion.png\";\r\n\t\t}\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 - 800) {\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 an evidence for in-character chat.\r\n * @param {string} evidence the evidence to be presented\r\n */\r\nexport function pickEvidence(evidence) {\r\n\tif (client.selectedEvidence !== evidence) {\r\n\t\t//Update selected evidence\t\t\r\n\t\tif (client.selectedEvidence > 0) {\r\n\t\t\tdocument.getElementById(\"evi_\" + client.selectedEvidence).className = \"client_button\";\r\n\t\t}\r\n\t\tdocument.getElementById(\"evi_\" + evidence).className = \"client_button dark\";\r\n\t\tclient.selectedEvidence = evidence;\r\n\r\n\t\t// Show evidence on information window\r\n\t\tdocument.getElementById(\"evi_name\").value = client.evidences[evidence - 1].name;\r\n\t\tdocument.getElementById(\"evi_desc\").value = client.evidences[evidence - 1].desc;\r\n\r\n\t\t//Update Icon\r\n\t\tlet icon_id = getIndexFromSelect(\"evi_select\", client.evidences[evidence - 1].filename);\r\n\t\tdocument.getElementById(\"evi_select\").selectedIndex = icon_id;\r\n\t\tif (icon_id == 0) {\r\n\t\t\tdocument.getElementById(\"evi_filename\").value = client.evidences[evidence - 1].filename;\r\n\t\t}\r\n\t\tupdateEvidenceIcon();\r\n\r\n\t\t// Update button\r\n\t\tdocument.getElementById(\"evi_add\").className = \"client_button hover_button inactive\";\r\n\t\tdocument.getElementById(\"evi_edit\").className = \"client_button hover_button\";\r\n\t\tdocument.getElementById(\"evi_cancel\").className = \"client_button hover_button\";\r\n\t\tdocument.getElementById(\"evi_del\").className = \"client_button hover_button\";\r\n\t} else {\r\n\t\tcancelEvidence();\r\n\t}\r\n}\r\nwindow.pickEvidence = pickEvidence;\r\n\r\n/**\r\n * Add evidence.\r\n */\r\nexport function addEvidence() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tclient.sendPE(document.getElementById(\"evi_name\").value,\r\n\t\tdocument.getElementById(\"evi_desc\").value,\r\n\t\tevidence_select.selectedIndex == 0 ?\r\n\t\t\tdocument.getElementById(\"evi_filename\").value :\r\n\t\t\tevidence_select.options[evidence_select.selectedIndex].text\r\n\t);\r\n\tcancelEvidence();\r\n}\r\nwindow.addEvidence = addEvidence;\r\n\r\n/**\r\n * Edit selected evidence.\r\n */\r\nexport function editEvidence() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tlet id = parseInt(client.selectedEvidence) - 1;\r\n\tclient.sendEE(id,\r\n\t\tdocument.getElementById(\"evi_name\").value,\r\n\t\tdocument.getElementById(\"evi_desc\").value,\r\n\t\tevidence_select.selectedIndex == 0 ?\r\n\t\t\tdocument.getElementById(\"evi_filename\").value :\r\n\t\t\tevidence_select.options[evidence_select.selectedIndex].text\r\n\t);\r\n\tcancelEvidence();\r\n}\r\nwindow.editEvidence = editEvidence;\r\n\r\n/**\r\n * Delete selected evidence.\r\n */\r\nexport function deleteEvidence() {\r\n\tlet id = parseInt(client.selectedEvidence) - 1;\r\n\tclient.sendDE(id);\r\n\tcancelEvidence();\r\n}\r\nwindow.deleteEvidence = deleteEvidence;\r\n\r\n/**\r\n * Cancel evidence selection.\r\n */\r\nexport function cancelEvidence() {\r\n\t//Clear evidence data\r\n\tif (client.selectedEvidence > 0) {\r\n\t\tdocument.getElementById(\"evi_\" + client.selectedEvidence).className = \"client_button\";\r\n\t}\r\n\tclient.selectedEvidence = 0;\r\n\r\n\t// Clear evidence on information window\r\n\tdocument.getElementById(\"evi_select\").selectedIndex = 0;\r\n\tupdateEvidenceIcon(); // Update icon widget\r\n\tdocument.getElementById(\"evi_filename\").value = \"\";\r\n\tdocument.getElementById(\"evi_name\").value = \"\";\r\n\tdocument.getElementById(\"evi_desc\").value = \"\";\r\n\tdocument.getElementById(\"evi_icon\").style.backgroundImage = \"url('misc/empty.png')\"; //Clear icon\r\n\r\n\t// Update button\r\n\tdocument.getElementById(\"evi_add\").className = \"client_button hover_button\";\r\n\tdocument.getElementById(\"evi_edit\").className = \"client_button hover_button inactive\";\r\n\tdocument.getElementById(\"evi_cancel\").className = \"client_button hover_button inactive\";\r\n\tdocument.getElementById(\"evi_del\").className = \"client_button hover_button inactive\";\r\n}\r\nwindow.cancelEvidence = cancelEvidence;\r\n\r\n/**\r\n * Find index of anything in select box.\r\n * @param {string} select_box the select element name\r\n * @param {string} value the value that need to be compared\r\n */\r\nexport function getIndexFromSelect(select_box, value) {\r\n\t//Find if icon alraedy existed in select box\r\n\tconst select_element = document.getElementById(select_box);\r\n\tfor (let i = 1; i < select_element.length; ++i) {\r\n\t\tif (select_element.options[i].value == value) {\r\n\t\t\treturn i;\r\n\t\t}\r\n\t}\r\n\treturn 0;\r\n}\r\nwindow.getIndexFromSelect = getIndexFromSelect;\r\n\r\n/**\r\n * Update evidence icon.\r\n */\r\nexport function updateEvidenceIcon() {\r\n\tlet evidence_select = document.getElementById(\"evi_select\");\r\n\tlet evidence_filename = document.getElementById(\"evi_filename\");\r\n\tlet evidence_iconbox = document.getElementById(\"evi_icon\");\r\n\r\n\tif (evidence_select.selectedIndex === 0) {\r\n\t\tevidence_filename.style.display = \"initial\";\r\n\t\tevidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_filename.value.toLowerCase()})`;\r\n\t} else {\r\n\t\tevidence_filename.style.display = \"none\";\r\n\t\tevidence_iconbox.style.backgroundImage = `url(${AO_HOST}evidence/${evidence_select.value.toLowerCase()})`;\r\n\t}\r\n}\r\nwindow.updateEvidenceIcon = updateEvidenceIcon;\r\n\r\n/**\r\n * Update evidence icon.\r\n */\r\nexport function updateActionCommands(side) {\r\n\tif (side == \"jud\") {\r\n\t\tdocument.getElementById(\"judge_action\").style.display = \"inline-table\";\r\n\t\tdocument.getElementById(\"no_action\").style.display = \"none\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"no_action\").style.display = \"inline-table\";\r\n\t\tdocument.getElementById(\"judge_action\").style.display = \"none\";\r\n\t}\r\n\t//Update role selector\r\n\tfor (let i = 0, role_select = document.getElementById(\"role_select\").options; i < role_select.length; i++) {\r\n\t\tif (side == role_select[i].value) {\r\n\t\t\trole_select.selectedIndex = i;\r\n\t\t\treturn;\r\n\t\t}\r\n\t}\r\n}\r\nwindow.updateActionCommands = updateActionCommands;\r\n\r\n/**\r\n * Change background via OOC.\r\n */\r\nexport function changeBackgroundOOC() {\r\n\tlet filename = \"\",\r\n\t\tbackground_select = document.getElementById(\"bg_select\"),\r\n\t\tbg_command = document.getElementById(\"bg_command\").value;\r\n\tif (background_select.selectedIndex == 0) {\r\n\t\tfilename = document.getElementById(\"bg_filename\").value;\r\n\t} else {\r\n\t\tfilename = background_select.value;\r\n\t}\r\n\tclient.sendOOC(\"/\" + bg_command.replace(\"$1\", filename));\r\n}\r\nwindow.changeBackgroundOOC = changeBackgroundOOC;\r\n\r\n/**\r\n * Change role via OOC.\r\n */\r\nexport function changeRoleOOC() {\r\n\tlet role_select = document.getElementById(\"role_select\"),\r\n\t\trole_command = document.getElementById(\"role_command\").value;\r\n\r\n\tclient.sendOOC(\"/\" + role_command.replace(\"$1\", role_select.value));\r\n\tupdateActionCommands(role_select.value);\r\n}\r\nwindow.changeRoleOOC = changeRoleOOC;\r\n\r\n/**\r\n * Random character via OOC.\r\n */\r\nexport function randomCharacterOOC() {\r\n\tclient.sendOOC(\"/\" + document.getElementById(\"randomchar_command\").value);\r\n}\r\nwindow.randomCharacterOOC = randomCharacterOOC;\r\n\r\n/**\r\n * Call mod.\r\n */\r\nexport function callMod() {\r\n\t$(\"#callmod_dialog\").dialog(\"open\");\r\n}\r\nwindow.callMod = callMod;\r\n\r\n/**\r\n * Declare witness testimony.\r\n */\r\nexport function initWT() {\r\n\tclient.sendRT(\"testimony1\");\r\n}\r\nwindow.initWT = initWT;\r\n\r\n/**\r\n * Declare cross examination.\r\n */\r\nexport function initCE() {\r\n\tclient.sendRT(\"testimony2\");\r\n}\r\nwindow.initCE = initCE;\r\n\r\n/**\r\n * Increment defense health point.\r\n */\r\nexport function addHPD() {\r\n\tclient.sendHP(1, String(parseInt(client.hp[0]) + 1));\r\n}\r\nwindow.addHPD = addHPD;\r\n\r\n/**\r\n * Decrement defense health point.\r\n */\r\nexport function redHPD() {\r\n\tclient.sendHP(1, String(parseInt(client.hp[0]) - 1));\r\n}\r\nwindow.redHPD = redHPD;\r\n\r\n/**\r\n * Increment prosecution health point.\r\n */\r\nexport function addHPP() {\r\n\tclient.sendHP(2, String(parseInt(client.hp[1]) + 1));\r\n}\r\nwindow.addHPP = addHPP;\r\n\r\n/**\r\n * Decrement prosecution health point.\r\n */\r\nexport function redHPP() {\r\n\tclient.sendHP(2, String(parseInt(client.hp[1]) - 1));\r\n}\r\nwindow.redHPP = redHPP;\r\n\r\n/**\r\n * Update background preview.\r\n */\r\nexport function updateBackgroundPreview() {\r\n\tlet background_select = document.getElementById(\"bg_select\");\r\n\tlet background_filename = document.getElementById(\"bg_filename\");\r\n\tlet background_preview = document.getElementById(\"bg_preview\");\r\n\r\n\tif (background_select.selectedIndex == 0) {\r\n\t\tbackground_filename.style.display = \"initial\";\r\n\t\tbackground_preview.src = AO_HOST + \"background/\" + background_filename.value.toLowerCase() + \"/defenseempty.png\";\r\n\t} else {\r\n\t\tbackground_filename.style.display = \"none\";\r\n\t\tbackground_preview.src = AO_HOST + \"background/\" + background_select.value.toLowerCase() + \"/defenseempty.png\";\r\n\t}\r\n}\r\nwindow.updateBackgroundPreview = updateBackgroundPreview;\r\n\r\n/**\r\n * Highlights and selects an effect for in-character chat.\r\n * If the same effect button is selected, then the effect is canceled.\r\n * @param {string} effect the new effect to be selected\r\n */\r\nexport function toggleEffect(effect) {\r\n\tif (effect == selectedEffect) {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button\";\r\n\t\tselectedEffect = 0;\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_effect_\" + effect).className = \"client_button dark\";\r\n\t\tif (selectedEffect) {\r\n\t\t\tdocument.getElementById(\"button_effect_\" + selectedEffect).className = \"client_button\";\r\n\t\t}\r\n\t\tselectedEffect = effect;\r\n\t}\r\n}\r\nwindow.toggleEffect = toggleEffect;\r\n\r\n/**\r\n * Toggle flip for in-character chat.\r\n */\r\nexport function toggleFlip() {\r\n\tif (client.flip) {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_flip\").className = \"client_button dark\";\r\n\t}\r\n\tclient.flip = !client.flip;\r\n}\r\nwindow.toggleFlip = toggleFlip;\r\n\r\n/**\r\n * Toggle presentable for presenting evidence in-character chat.\r\n */\r\nexport function togglePresent() {\r\n\tif (client.presentable) {\r\n\t\tdocument.getElementById(\"button_present\").className = \"client_button\";\r\n\t} else {\r\n\t\tdocument.getElementById(\"button_present\").className = \"client_button dark\";\r\n\t}\r\n\tclient.presentable = !client.presentable;\r\n}\r\nwindow.togglePresent = togglePresent;\r\n\r\n/**\r\n * Highlights and selects a menu.\r\n * @param {string} menu the menu to be selected\r\n */\r\nexport function toggleMenu(menu) {\r\n\tif (menu != selectedMenu) {\r\n\t\tdocument.getElementById(\"menu_\" + menu).className = \"menu_icon active\";\r\n\t\tdocument.getElementById(\"content_\" + menu).className = \"menu_content active\";\r\n\t\tdocument.getElementById(\"menu_\" + selectedMenu).className = \"menu_icon\";\r\n\t\tdocument.getElementById(\"content_\" + selectedMenu).className = \"menu_content\";\r\n\t\tselectedMenu = menu;\r\n\t}\r\n}\r\nwindow.toggleMenu = toggleMenu;\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, \"&\")\r\n\t\t.replace(//g, \">\")\r\n\t\t.replace(/\"/g, \""\")\r\n\t\t.replace(/'/g, \"'\");\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, \"\")\r\n\t\t.replace(/&/g, \"\")\r\n\t\t.replace(/%/g, \"\")\r\n\t\t.replace(/\\$/g, \"\");\r\n}\r\n\r\n/**\r\n * Unescapes a string to AO1 escape codes.\r\n * @param {string} estring the string to be unescaped\r\n */\r\nfunction unescapeChat(estring) {\r\n\treturn estring\r\n\t\t.replace(//g, \"#\")\r\n\t\t.replace(//g, \"&\")\r\n\t\t.replace(//g, \"%\")\r\n\t\t.replace(//g, \"$\");\r\n}\r\n\r\n/**\r\n * Encode text on client side.\r\n * @param {string} estring the string to be encoded\r\n */\r\nfunction encodeChat(estring) {\r\n\tlet selectedEncoding = document.getElementById(\"client_encoding\").value;\r\n\tif (selectedEncoding == \"unicode\") {\r\n\t\t// This approach works by escaping all special characters to Unicode escape sequences.\r\n\t\t// Source: https://gist.github.com/mathiasbynens/1243213\r\n\t\treturn estring.replace(/[^\\0-~]/g, function (ch) {\r\n\t\t\treturn \"\\\\u\" + (\"000\" + ch.charCodeAt().toString(16)).slice(-4);\r\n\t\t});\r\n\t} else if (selectedEncoding == \"utf16\") {\r\n\t\t// Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\r\n\t\tconst buffer = new ArrayBuffer(estring.length * 2);\r\n\t\tconst result = new Uint16Array(buffer);\r\n\t\tfor (let i = 0, strLen = estring.length; i < strLen; i++) {\r\n\t\t\tresult[i] = estring.charCodeAt(i);\r\n\t\t}\r\n\t\treturn String(result);\r\n\t} else {\r\n\t\treturn estring;\r\n\t}\r\n}\r\n\r\n/**\r\n * Decodes text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeChat(estring) {\r\n\tlet selectedDecoding = document.getElementById(\"client_decoding\").value;\r\n\tif (selectedDecoding == \"unicode\") {\r\n\t\t// Source: https://stackoverflow.com/questions/7885096/how-do-i-decode-a-string-with-escaped-unicode\r\n\t\treturn estring.replace(/\\\\u([\\d\\w]{1,})/gi, function (match, group) {\r\n\t\t\treturn String.fromCharCode(parseInt(group, 16));\r\n\t\t});\r\n\t} else if (selectedDecoding == \"utf16\") {\r\n\t\t// Source: https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String\r\n\t\treturn String.fromCharCode.apply(null, new Uint16Array(estring.split(\",\")));\r\n\t} else {\r\n\t\treturn estring;\r\n\t}\r\n}\r\n\r\n/**\r\n * Decoding text on client side.\r\n * @param {string} estring the string to be decoded\r\n */\r\nfunction decodeBBCode(estring) {\r\n\treturn estring\r\n\t\t.replace(/\\\\n/g, \"
\") // Newline \\n\r\n\t\t.replace(/\\[(\\/?)b\\]/g, \"<$1b>\") // Bold [b][/b]\r\n\t\t.replace(/\\[(\\/?)i\\]/g, \"<$1i>\") // Italic [i][/i]\r\n\t\t.replace(/\\[(\\/?)s\\]/g, \"<$1del>\") // Strikethrough [s][/s]\r\n\t\t.replace(/\\[(\\/?)u\\]/g, \"<$1u>\") // Underline [u][/u]\r\n\t\t.replace(/\\[(\\/?)sub\\]/g, \"<$1sub>\") // Subscript [sub][/sub]\r\n\t\t.replace(/\\[(\\/?)sup\\]/g, \"<$1sup>\") // Superscript [sup][/sup]\r\n\t\t.replace(/\\[m=([#a-zA-Z0-9]+)\\]/g, \"\") // Markup [m=#0ff]\r\n\t\t.replace(/\\[(\\/?)m\\]/g, \"<$1m>\") // [m][/m]\r\n\t\t.replace(/\\[c=?([#a-zA-Z0-9]+)\\]/g, \"\") // Color [c=red]\r\n\t\t.replace(/\\[\\/c\\]/g, \"\"); // [/c]\r\n}\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\tString.prototype.trim = function () {\r\n\t\treturn String(this).replace(/^\\s+|\\s+$/g, \"\");\r\n\t};\r\n}\r\n\r\n// Used for HDID calculation.\r\nString.prototype.hashCode = function () {\r\n\tlet hash = 0;\r\n\tif (this.length === 0) return hash;\r\n\tfor (let i = 0; i < this.length; i++) {\r\n\t\tconst chr = this.charCodeAt(i);\r\n\t\thash = ((hash << 5) - hash) + chr;\r\n\t\thash |= 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\r\n$(document).ready(function () {\r\n\tclient.initialObservBBCode();\r\n\tclient.loadResources();\r\n});\r\n\r\n// Create dialog and link to button\t\r\n$(function () {\r\n\t$(\"#callmod_dialog\").dialog({\r\n\t\tautoOpen: false,\r\n\t\tresizable: false,\r\n\t\tshow: {\r\n\t\t\teffect: \"drop\",\r\n\t\t\tdirection: \"down\",\r\n\t\t\tduration: 500\r\n\t\t},\r\n\t\thide: {\r\n\t\t\teffect: \"drop\",\r\n\t\t\tdirection: \"down\",\r\n\t\t\tduration: 500\r\n\t\t},\r\n\t\theight: \"auto\",\r\n\t\twidth: 400,\r\n\t\tmodal: true,\r\n\t\tbuttons: {\r\n\t\t\tSure: function () {\r\n\t\t\t\tclient.sendZZ(\"\");\r\n\t\t\t\t$(this).dialog(\"close\");\r\n\t\t\t},\r\n\t\t\tCancel: function () {\r\n\t\t\t\t$(this).dialog(\"close\");\r\n\t\t\t}\r\n\t\t}\r\n\t});\r\n});"],"sourceRoot":""} \ No newline at end of file diff --git a/webAO/client.css b/webAO/client.css index 79c2d00..29ff3cd 100644 --- a/webAO/client.css +++ b/webAO/client.css @@ -327,13 +327,18 @@ img { background-size: contain; } -.evi_options { +#evi_options { display: inline-block; + padding-left: 5px; } -.evi_options label { +#evi_options label { display: inline-block; - width: 6em; + width: 3em; +} + +#evi_desc { + flex: 1 auto; } #bg_preview { diff --git a/webAO/client.html b/webAO/client.html index 2e5b7d1..73d9ec6 100644 --- a/webAO/client.html +++ b/webAO/client.html @@ -25,8 +25,8 @@
Courtroom background - Character sprite - Bench overlay + + Various overlay Character Evidence Effect overlay @@ -114,17 +114,12 @@ No actions available for this role. -
- - report -
Call Mod
-