rscminus.lua 278 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332
  1. -- RSCMINUS.LUA VERSION 2021-01-08 ALPHA
  2. --
  3. -- WARNING: This is being provided as an alpha
  4. -- WARNING: Some opcodes may not be fully implemented.
  5. -- WARNING: Some opcodes may report incorrect data, or be interpretted wrongly.
  6. --
  7. -- Please report any issues you encounter, but only when dissecting original Jagex RSC235 server data.
  8. -- It is expected that private servers may have incorrect data that confuses this dissector.
  9. rsc235_protocol = Proto("rsc235", "RSC235 Protocol")
  10. -- turn this on to see the packet dissection order window,
  11. -- and some extra debugging fields on opcodes 191 & 104 (possibly others if this comment isn't updated)
  12. thisDebugging = false
  13. --============================================================================--
  14. --= =--
  15. --= README: install this file to your wireshark plugins folder. =--
  16. --= =--
  17. --= In linux this is at ~/.config/wireshark/plugins/ =--
  18. --= (create the folder if it doesn't exist) =--
  19. --= =--
  20. --= In windows it's at C:\Program Files\Wireshark\plugins\ =--
  21. --= =--
  22. --= You should also import the colouring rules from: =--
  23. --= "View -> Coloring Rules -> Import... -> "colouring_rules" =--
  24. --= =--
  25. --============================================================================--
  26. --
  27. -- example queries:
  28. -- rsc235.234.updateType.5.equipment[10] == 0x51
  29. -- shows only player updates where the player is wearing a golden amulet
  30. --
  31. -- !(rsc235.149.onlineStatus == 4 || rsc235.149.onlineStatus == 0) && rsc235.opcode == 149
  32. -- shows only players updates from those on the same world as the recorder
  33. --
  34. -- !((rsc235.packetSource == 0 && (rsc235.opcode == 36 || rsc235.opcode == 48 || rsc235.opcode == 79 || rsc235.opcode == 91 || rsc235.opcode == 99 || rsc235.opcode == 104 || rsc235.opcode == 191 || rsc235.opcode == 211 || rsc235.opcode == 213 || (rsc235.opcode == 234 && !(rsc235.234.updateType == 1 || rsc235.234.updateType == 6)))) || rsc235.opcode == 67)
  35. -- filter out most of the "background noise" of making sure the player stays in the world and the world stays sane
  36. -- alternatively, remove the ! in front to only see "background noise"!
  37. --
  38. -- More examples can be found in the colouring_rules file
  39. --
  40. -- Documentation on wireshark bitwise operators
  41. -- http://bitop.luajit.org/
  42. --
  43. --============================================================================--
  44. --------------------------------------------------------------------------------
  45. -- Custom opcodes
  46. --------------------------------------------------------------------------------
  47. VIRTUAL_OPCODE_CONNECT = 10000
  48. VIRTUAL_OPCODE_SERVER_METADATA = 12345
  49. --------------------------------------------------------------------------------
  50. -- Server opcodes
  51. --------------------------------------------------------------------------------
  52. SERVER_OPCODES = {}
  53. SERVER_OPCODES[4] = "CLOSE_CONNECTION_NOTIFY" -- same as opcode 165, but client will send opcode 31 if clientstream still exists
  54. SERVER_OPCODES[5] = "QUEST_STATUS"
  55. SERVER_OPCODES[6] = "UPDATE_STAKED_ITEMS_OPPONENT"
  56. SERVER_OPCODES[15] = "UPDATE_TRADE_ACCEPTANCE"
  57. SERVER_OPCODES[20] = "SHOW_CONFIRM_TRADE"
  58. SERVER_OPCODES[25] = "FLOOR_SET"
  59. SERVER_OPCODES[30] = "SYNC_DUEL_SETTINGS"
  60. SERVER_OPCODES[33] = "UPDATE_XP"
  61. SERVER_OPCODES[36] = "DISPLAY_TELEPORT_TELEGRAB_BUBBLE"
  62. SERVER_OPCODES[42] = "OPEN_BANK"
  63. SERVER_OPCODES[48] = "SCENERY_HANDLER" -- TODO: Confirm functionality
  64. SERVER_OPCODES[51] = "PRIVACY_SETTINGS"
  65. SERVER_OPCODES[52] = "UPDATE_SYSTEM_UPDATE_TIMER"
  66. SERVER_OPCODES[53] = "SET_INVENTORY"
  67. SERVER_OPCODES[59] = "SHOW_APPEARANCE_CHANGE"
  68. SERVER_OPCODES[79] = "NPC_COORDS" -- TODO: coordinates are not always exactly correct, but tracking should be complete.
  69. SERVER_OPCODES[83] = "DISPLAY_DEATH_SCREEN"
  70. SERVER_OPCODES[84] = "WAKE_UP"
  71. SERVER_OPCODES[87] = "SEND_PM"
  72. SERVER_OPCODES[89] = "SHOW_DIALOGUE_SERVER_MESSAGE_NOT_TOP"
  73. SERVER_OPCODES[90] = "SET_INVENTORY_SLOT" -- FINDOUT: confirm no opcode contains multiple data (most likely not, or else it would have been used on bank withdraw)
  74. SERVER_OPCODES[91] = "BOUNDARY_HANDLER" -- TODO: confirm functionality
  75. SERVER_OPCODES[92] = "INITIATE_TRADE"
  76. SERVER_OPCODES[97] = "UPDATE_ITEMS_TRADED_TO_YOU"
  77. SERVER_OPCODES[99] = "GROUND_ITEM_HANDLER" -- TODO: confirm functionality
  78. SERVER_OPCODES[101] = "SHOW_SHOP"
  79. SERVER_OPCODES[104] = "UPDATE_NPC" -- TODO: confirm functionality
  80. SERVER_OPCODES[109] = "SET_IGNORE"
  81. SERVER_OPCODES[111] = "COMPLETED_TUTORIAL" -- TODO: reconfirm after text changes
  82. SERVER_OPCODES[114] = "SET_FATIGUE"
  83. SERVER_OPCODES[117] = "FALL_ASLEEP"
  84. SERVER_OPCODES[120] = "RECEIVE_PM"
  85. SERVER_OPCODES[123] = "REMOVE_INVENTORY_SLOT"
  86. SERVER_OPCODES[128] = "CONCLUDE_TRADE"
  87. SERVER_OPCODES[131] = "SEND_MESSAGE" -- FINDOUT: figure out why eggsampler guy thinks the second username is "clan". as far as I can tell, it's just a duplicate of the username. the client uses it to check against the names in the ignore list.
  88. SERVER_OPCODES[137] = "EXIT_SHOP"
  89. SERVER_OPCODES[149] = "UPDATE_FRIEND"
  90. SERVER_OPCODES[153] = "SET_EQUIP_STATS"
  91. SERVER_OPCODES[156] = "SET_STATS"
  92. SERVER_OPCODES[159] = "UPDATE_STAT"
  93. SERVER_OPCODES[162] = "UPDATE_TRADE_RECIPIENT_ACCEPTANCE" -- TODO: reconfirm after text changes
  94. SERVER_OPCODES[165] = "CLOSE_CONNECTION"
  95. SERVER_OPCODES[172] = "SHOW_CONFIRM_DUEL" -- TODO: CONFIRM FUNCTIONALITY
  96. SERVER_OPCODES[176] = "SHOW_DIALOGUE_DUEL" -- TODO: CONFIRM FUNCTIONALITY
  97. SERVER_OPCODES[182] = "SHOW_WELCOME"
  98. SERVER_OPCODES[183] = "DENY_LOGOUT"
  99. SERVER_OPCODES[189] = "WRITE_28_BYTES_TO_RANDOM.DAT" -- Happens in zero replays out of 10,000+ but is in client.
  100. SERVER_OPCODES[191] = "PLAYER_COORDS" -- TODO: There may be a bug still in the way players are stored; sometimes there are duplicates.
  101. SERVER_OPCODES[194] = "INCORRECT_SLEEPWORD"
  102. SERVER_OPCODES[203] = "CLOSE_BANK"
  103. SERVER_OPCODES[204] = "PLAY_SOUND"
  104. SERVER_OPCODES[206] = "SET_PRAYERS"
  105. SERVER_OPCODES[210] = "UPDATE_DUEL_ACCEPTANCE" -- TODO: CONFIRM FUNCTIONALITY
  106. SERVER_OPCODES[211] = "REMOVE_WORLD_ENTITY" -- removes whatever is at the X Y coordinate provided. can be boundary, scenery, or ground item. -- TODO: CONFIRM FUNCTIONALITY
  107. SERVER_OPCODES[213] = "NO_OP_WHILE_WAITING_FOR_NEW_APPEARANCE"
  108. SERVER_OPCODES[222] = "SHOW_DIALOGUE_SERVER_MESSAGE_TOP"
  109. SERVER_OPCODES[225] = "CONCLUDE_DUEL_DIALOGUE"
  110. SERVER_OPCODES[234] = "UPDATE_PLAYERS" -- FINDOUT: concretely figure out difference between type 3 and 4
  111. SERVER_OPCODES[237] = "UPDATE_IGNORE_BECAUSE_OF_NAME_CHANGE" -- FINDOUT: search for a replay where field 4/2 are filled
  112. SERVER_OPCODES[240] = "GAME_SETTINGS"
  113. SERVER_OPCODES[244] = "SET_FATIGUE_SLEEPING"
  114. SERVER_OPCODES[245] = "SHOW_DIALOGUE_MENU"
  115. SERVER_OPCODES[249] = "UPDATE_BANK_ITEMS_DISPLAY"
  116. SERVER_OPCODES[252] = "DISABLE_OPTION_MENU"
  117. SERVER_OPCODES[253] = "UPDATE_DUEL_OPPONENT_ACCEPTANCE"
  118. SERVER_OPCODES[10000] = "VIRTUAL_OPCODE_LOGIN_RESPONSE"
  119. SERVER_OPCODES[12345] = "VIRTUAL_OPCODE_SERVER_METADATA"
  120. --------------------------------------------------------------------------------
  121. -- Client opcodes
  122. --------------------------------------------------------------------------------
  123. CLIENT_OPCODES = {}
  124. CLIENT_OPCODES[0] = "CONNECT" -- done
  125. -- CLIENT_OPCODES[3] = "SEND_DEBUG_INFO" -- 204 opcode (and possibly earlier) removed in 233, used to send various debug info to jagex if the client was erroring. unlikely that any information was sent back from server in response.
  126. CLIENT_OPCODES[4] = "CAST_ON_INVENTORY_ITEM" -- TODO: confirm functionality
  127. CLIENT_OPCODES[8] = "SEND_DUEL_SETTINGS" -- TODO: confirm working
  128. CLIENT_OPCODES[14] = "INTERACT_WITH_BOUNDARY" -- done
  129. CLIENT_OPCODES[16] = "WALK_AND_PERFORM_ACTION" -- done
  130. CLIENT_OPCODES[22] = "BANK_WITHDRAW" -- done
  131. CLIENT_OPCODES[23] = "BANK_DEPOSIT" -- done
  132. CLIENT_OPCODES[29] = "SEND_COMBAT_STYLE" -- done
  133. CLIENT_OPCODES[31] = "CLOSE_CONNECTION_REPLY" -- done
  134. -- CLIENT_OPCODES[32] = "SESSION" -- 204 opcode (and possibly earlier) removed in 233, used to be able to detect if Login Server was offline
  135. CLIENT_OPCODES[33] = "SEND_STAKED_ITEMS" -- TODO: confirm functionality
  136. CLIENT_OPCODES[38] = "SEND_COMMAND_STRING" -- done
  137. CLIENT_OPCODES[45] = "SEND_SLEEPWORD" -- done
  138. CLIENT_OPCODES[46] = "OFFER_TRADE_ITEM" -- done
  139. CLIENT_OPCODES[50] = "CAST_NPC" -- done
  140. CLIENT_OPCODES[53] = "USE_ON_GROUND_ITEM" -- TODO: confirm functionality
  141. CLIENT_OPCODES[55] = "SET_TRADE_ACCEPTED_TRUE" -- done because it's only the opcode
  142. CLIENT_OPCODES[59] = "ADMIN_TELEPORT_TO_TILE" -- done; can see admins tping around in final day replays most likely using this opcode
  143. CLIENT_OPCODES[60] = "ENABLE_PRAYER" -- done
  144. CLIENT_OPCODES[64] = "SEND_PRIVACY_SETTINGS" -- TODO: confirm functionality, expand meanings
  145. CLIENT_OPCODES[67] = "HEARTBEAT" -- todo: probably add explanation that this is what keeps the server from considering client dead
  146. CLIENT_OPCODES[77] = "DUEL_CONFIRM_ACCEPT" -- done because it's only the opcode
  147. CLIENT_OPCODES[79] = "INTERACT_WITH_SCENERY_OPTION_2" -- done
  148. CLIENT_OPCODES[84] = "SKIP_TUTORIAL" -- done because it's only the opcode
  149. CLIENT_OPCODES[90] = "ACTIVATE_INVENTORY_ITEM" -- done
  150. CLIENT_OPCODES[91] = "COMBINE_INVENTORY_ITEMS" -- done
  151. CLIENT_OPCODES[99] = "CAST_ON_SCENERY" -- TODO: confirm functionality
  152. CLIENT_OPCODES[102] = "REQUEST_LOGOUT" -- done because it's only the opcode
  153. CLIENT_OPCODES[103] = "SEND_DUEL_REQUEST" -- TODO: confirm functionality
  154. CLIENT_OPCODES[104] = "CONFIRM_ACCEPT_TRADE" -- done because it's only the opcode
  155. CLIENT_OPCODES[111] = "SEND_CLIENT_SETTINGS" -- TODO: confirm functionality
  156. CLIENT_OPCODES[113] = "USE_WITH_PLAYER" -- TODO: confirm functionality
  157. CLIENT_OPCODES[115] = "USE_WITH_SCENERY" -- TODO: confirm functionality
  158. CLIENT_OPCODES[116] = "SELECT_DIALOGUE_OPTION" -- done
  159. CLIENT_OPCODES[127] = "INTERACT_WITH_BOUNDARY_OPTION_2" -- TODO: confirm functionality
  160. CLIENT_OPCODES[132] = "ADD_IGNORE" -- TODO: confirm functionality
  161. CLIENT_OPCODES[135] = "USE_ON_NPC" -- TODO: confirm functionality
  162. CLIENT_OPCODES[136] = "INTERACT_WITH_SCENERY" -- done
  163. CLIENT_OPCODES[137] = "CAST_ON_SELF" -- TODO: confirm functionality
  164. CLIENT_OPCODES[142] = "AGREE_TO_TRADE" -- TODO: confirm functionality
  165. CLIENT_OPCODES[153] = "TALK_TO_NPC" -- TODO: confirm functionality
  166. CLIENT_OPCODES[158] = "CAST_ON_GROUND" -- TODO: confirm functionality
  167. CLIENT_OPCODES[161] = "USE_WITH_BOUNDARY" -- TODO: confirm functionality
  168. -- CLIENT_OPCODES[163] = "KNOWN_PLAYERS" -- This opcode was in RSC in all revisions between MC40 (early 2001) and RSC204 (2006). It was removed in RSC233 (2011). The client used to send this opcode as a reply for every PLAYER_COORDS packet with the client's known-players array!
  169. CLIENT_OPCODES[165] = "FOLLOW_PLAYER" -- done
  170. CLIENT_OPCODES[166] = "CLOSE_SHOP" -- done because it's only the opcode
  171. CLIENT_OPCODES[167] = "REMOVE_FRIEND" -- TODO: confirm functionality
  172. CLIENT_OPCODES[169] = "EQUIP_ITEM" -- TODO: confirm functionality
  173. CLIENT_OPCODES[170] = "UNEQUIP_ITEM" -- TODO: confirm functionality
  174. CLIENT_OPCODES[171] = "ATTACK_PLAYER" -- done
  175. CLIENT_OPCODES[176] = "ACCEPT_DUEL" -- done because it's only the opcode
  176. CLIENT_OPCODES[180] = "CAST_ON_BOUNDARY" -- TODO: confirm functionality
  177. CLIENT_OPCODES[187] = "WALK" -- done
  178. CLIENT_OPCODES[190] = "ATTACK_NPC" -- TODO: confirm functionality
  179. CLIENT_OPCODES[195] = "ADD_FRIEND" -- TODO: confirm functionality
  180. CLIENT_OPCODES[197] = "DECLINE_DUEL" -- done because it's only the opcode
  181. CLIENT_OPCODES[202] = "INTERACT_NPC" -- TODO: confirm functionality
  182. CLIENT_OPCODES[206] = "SEND_REPORT" -- done
  183. CLIENT_OPCODES[212] = "BANK_CLOSE" -- done because it's only the opcode
  184. CLIENT_OPCODES[216] = "SEND_CHAT_MESSAGE" -- done
  185. CLIENT_OPCODES[218] = "SEND_PM" -- done
  186. CLIENT_OPCODES[221] = "SELL_TO_SHOP" -- TODO: confirm functionality
  187. CLIENT_OPCODES[229] = "CAST_PVP" -- done
  188. CLIENT_OPCODES[230] = "ABORT_DIALOGUE" -- done because it's only the opcode
  189. CLIENT_OPCODES[235] = "SEND_APPEARANCE"
  190. CLIENT_OPCODES[236] = "BUY_FROM_SHOP" -- TODO: confirm functionality
  191. CLIENT_OPCODES[241] = "REMOVE_IGNORED" -- TODO: confirm functionality
  192. CLIENT_OPCODES[246] = "DROP_ITEM" -- TODO: confirm functionality
  193. CLIENT_OPCODES[247] = "TAKE_GROUND_ITEM" -- done
  194. CLIENT_OPCODES[249] = "CAST_ON_GROUND_ITEM" -- TODO: confirm functionality
  195. CLIENT_OPCODES[254] = "DISABLE_PRAYER" -- done
  196. CLIENT_OPCODES[10000] = "VIRTUAL_OPCODE_LOGIN_REQUEST"
  197. -- Item ID array
  198. ITEM_NAMES = { "Iron Short Sword", "Iron Kite Shield", "Iron Square Shield", "Wooden Shield", "Medium Iron Helmet", "Large Iron Helmet", "Iron Chain Mail Body", "Iron Plate Mail Body", "Iron Plate Mail Legs", "Coins", "Bronze Arrows", "Iron Axe", "Knife", "Logs", "Leather Armour", "Leather Gloves", "Boots", "Cabbage", "Egg", "Bones", "Bucket", "Milk", "Flour", "Amulet of GhostSpeak", "Silverlight key 1", "Silverlight key 2", "skull", "Iron dagger", "grain", "Book", "Fire-Rune", "Water-Rune", "Air-Rune", "Earth-Rune", "Mind-Rune", "Body-Rune", "Life-Rune", "Death-Rune", "Needle", "Nature-Rune", "Chaos-Rune", "Law-Rune", "Thread", "Holy Symbol of saradomin", "Unblessed Holy Symbol", "Cosmic-Rune", "key", "key", "scroll", "Water", "Silverlight key 3", "Silverlight", "Broken shield", "Broken shield", "Cadavaberries", "message", "Cadava", "potion", "Phoenix Crossbow", "Crossbow", "Certificate", "bronze dagger", "Steel dagger", "Mithril dagger", "Adamantite dagger", "Bronze Short Sword", "Steel Short Sword", "Mithril Short Sword", "Adamantite Short Sword", "Bronze Long Sword", "Iron Long Sword", "Steel Long Sword", "Mithril Long Sword", "Adamantite Long Sword", "Rune long sword", "Bronze 2-handed Sword", "Iron 2-handed Sword", "Steel 2-handed Sword", "Mithril 2-handed Sword", "Adamantite 2-handed Sword", "rune 2-handed Sword", "Bronze Scimitar", "Iron Scimitar", "Steel Scimitar", "Mithril Scimitar", "Adamantite Scimitar", "bronze Axe", "Steel Axe", "Iron battle Axe", "Steel battle Axe", "Mithril battle Axe", "Adamantite battle Axe", "Rune battle Axe", "Bronze Mace", "Steel Mace", "Mithril Mace", "Adamantite Mace", "Rune Mace", "Brass key", "staff", "Staff of Air", "Staff of water", "Staff of earth", "Medium Bronze Helmet", "Medium Steel Helmet", "Medium Mithril Helmet", "Medium Adamantite Helmet", "Large Bronze Helmet", "Large Steel Helmet", "Large Mithril Helmet", "Large Adamantite Helmet", "Large Rune Helmet", "Bronze Chain Mail Body", "Steel Chain Mail Body", "Mithril Chain Mail Body", "Adamantite Chain Mail Body", "Bronze Plate Mail Body", "Steel Plate Mail Body", "Mithril Plate Mail Body", "Adamantite Plate Mail Body", "Steel Plate Mail Legs", "Mithril Plate Mail Legs", "Adamantite Plate Mail Legs", "Bronze Square Shield", "Steel Square Shield", "Mithril Square Shield", "Adamantite Square Shield", "Bronze Kite Shield", "Steel Kite Shield", "Mithril Kite Shield", "Adamantite Kite Shield", "cookedmeat", "raw chicken", "burntmeat", "pot", "flour", "bread dough", "bread", "burntbread", "jug", "water", "wine", "grapes", "shears", "wool", "fur", "cow hide", "leather", "clay", "copper ore", "iron ore", "gold", "mithril ore", "adamantite ore", "coal", "Bronze Pickaxe", "uncut diamond", "uncut ruby", "uncut emerald", "uncut sapphire", "diamond", "ruby", "emerald", "sapphire", "Herb", "tinderbox", "chisel", "hammer", "bronze bar", "iron bar", "steel bar", "gold bar", "mithril bar", "adamantite bar", "Pressure gauge", "Fish Food", "Poison", "Poisoned fish food", "spinach roll", "Bad wine", "Ashes", "Apron", "Cape", "Wizards robe", "wizardshat", "Brass necklace", "skirt", "Longbow", "Shortbow", "Crossbow bolts", "Apron", "Chef's hat", "Beer", "skirt", "skirt", "Black Plate Mail Body", "Staff of fire", "Magic Staff", "wizardshat", "silk", "flier", "tin ore", "Mithril Axe", "Adamantite Axe", "bronze battle Axe", "Bronze Plate Mail Legs", "Ball of wool", "Oil can", "Cape", "Kebab", "Spade", "Closet Key", "rubber tube", "Bronze Plated Skirt", "Iron Plated Skirt", "Black robe", "stake", "Garlic", "Red spiders eggs", "Limpwurt root", "Strength Potion", "Strength Potion", "Strength Potion", "Strength Potion", "Steel Plated skirt", "Mithril Plated skirt", "Adamantite Plated skirt", "Cabbage", "Cape", "Large Black Helmet", "Red Bead", "Yellow Bead", "Black Bead", "White Bead", "Amulet of accuracy", "Redberries", "Rope", "Reddye", "Yellowdye", "Paste", "Onion", "Bronze key", "Soft Clay", "wig", "wig", "Half full wine jug", "Keyprint", "Black Plate Mail Legs", "banana", "pastry dough", "Pie dish", "cooking apple", "pie shell", "Uncooked apple pie", "Uncooked meat pie", "Uncooked redberry pie", "apple pie", "Redberry pie", "meat pie", "burntpie", "Half a meat pie", "Half a Redberry pie", "Half an apple pie", "Portrait", "Faladian Knight's sword", "blurite ore", "Asgarnian Ale", "Wizard's Mind Bomb", "Dwarven Stout", "Eye of newt", "Rat's tail", "Bluedye", "Goblin Armour", "Goblin Armour", "Goblin Armour", "unstrung Longbow", "unstrung shortbow", "Unfired Pie dish", "unfired pot", "arrow shafts", "Woad Leaf", "Orangedye", "Gold ring", "Sapphire ring", "Emerald ring", "Ruby ring", "Diamond ring", "Gold necklace", "Sapphire necklace", "Emerald necklace", "Ruby necklace", "Diamond necklace", "ring mould", "Amulet mould", "Necklace mould", "Gold Amulet", "Sapphire Amulet", "Emerald Amulet", "Ruby Amulet", "Diamond Amulet", "Gold Amulet", "Sapphire Amulet", "Emerald Amulet", "Ruby Amulet", "Diamond Amulet", "superchisel", "Mace of Zamorak", "Bronze Plate Mail top", "Steel Plate Mail top", "Mithril Plate Mail top", "Adamantite Plate Mail top", "Iron Plate Mail top", "Black Plate Mail top", "Sapphire Amulet of magic", "Emerald Amulet of protection", "Ruby Amulet of strength", "Diamond Amulet of power", "Karamja Rum", "Cheese", "Tomato", "Pizza Base", "Burnt Pizza", "Incomplete Pizza", "Uncooked Pizza", "Plain Pizza", "Meat Pizza", "Anchovie Pizza", "Half Meat Pizza", "Half Anchovie Pizza", "Cake", "Burnt Cake", "Chocolate Cake", "Partial Cake", "Partial Chocolate Cake", "Slice of Cake", "Chocolate Slice", "Chocolate Bar", "Cake Tin", "Uncooked cake", "Unfired bowl", "Bowl", "Bowl of water", "Incomplete stew", "Incomplete stew", "Uncooked stew", "Stew", "Burnt Stew", "Potato", "Raw Shrimp", "Shrimp", "Raw Anchovies", "Anchovies", "Burnt fish", "Raw Sardine", "Sardine", "Raw Salmon", "Salmon", "Raw Trout", "Trout", "Burnt fish", "Raw Herring", "Herring", "Raw Pike", "Pike", "Burnt fish", "Raw Tuna", "Tuna", "Burnt fish", "Raw Swordfish", "Swordfish", "Burnt Swordfish", "Raw Lobster", "Lobster", "Burnt Lobster", "Lobster Pot", "Net", "Fishing Rod", "Fly Fishing Rod", "Harpoon", "Fishing Bait", "Feather", "Chest key", "Silver", "silver bar", "Holy Symbol of saradomin", "Holy symbol mould", "Disk of Returning", "Monks robe", "Monks robe", "Red key", "Orange Key", "yellow key", "Blue key", "Magenta key", "black key", "rune dagger", "Rune short sword", "rune Scimitar", "Medium Rune Helmet", "Rune Chain Mail Body", "Rune Plate Mail Body", "Rune Plate Mail Legs", "Rune Square Shield", "Rune Kite Shield", "rune Axe", "Rune skirt", "Rune Plate Mail top", "Runite bar", "runite ore", "Plank", "Tile", "skull", "Big Bones", "Muddy key", "Map", "Map Piece", "Map Piece", "Map Piece", "Nails", "Anti dragon breath Shield", "Maze key", "Pumpkin", "Black dagger", "Black Short Sword", "Black Long Sword", "Black 2-handed Sword", "Black Scimitar", "Black Axe", "Black battle Axe", "Black Mace", "Black Chain Mail Body", "Black Square Shield", "Black Kite Shield", "Black Plated skirt", "Herb", "Herb", "Herb", "Herb", "Herb", "Herb", "Herb", "Herb", "Herb", "Guam leaf", "Marrentill", "Tarromin", "Harralander", "Ranarr Weed", "Irit Leaf", "Avantoe", "Kwuarm", "Cadantine", "Dwarf Weed", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Unfinished potion", "Vial", "Vial", "Unicorn horn", "Blue dragon scale", "Pestle and mortar", "Snape grass", "Medium black Helmet", "White berries", "Ground blue dragon scale", "Ground unicorn horn", "attack Potion", "attack Potion", "attack Potion", "stat restoration Potion", "stat restoration Potion", "stat restoration Potion", "defense Potion", "defense Potion", "defense Potion", "restore prayer Potion", "restore prayer Potion", "restore prayer Potion", "Super attack Potion", "Super attack Potion", "Super attack Potion", "fishing Potion", "fishing Potion", "fishing Potion", "Super strength Potion", "Super strength Potion", "Super strength Potion", "Super defense Potion", "Super defense Potion", "Super defense Potion", "ranging Potion", "ranging Potion", "ranging Potion", "wine of Zamorak", "raw bear meat", "raw rat meat", "raw beef", "enchanted bear meat", "enchanted rat meat", "enchanted beef", "enchanted chicken meat", "Dramen Staff", "Dramen Branch", "Cape", "Cape", "Cape", "Cape", "Greendye", "Purpledye", "Iron ore certificate", "Coal certificate", "Mithril ore certificate", "silver certificate", "Gold certificate", "Dragonstone Amulet", "Dragonstone", "Dragonstone Amulet", "Crystal key", "Half of a key", "Half of a key", "Iron bar certificate", "steel bar certificate", "Mithril bar certificate", "silver bar certificate", "Gold bar certificate", "Lobster certificate", "Raw lobster certificate", "Swordfish certificate", "Raw swordfish certificate", "Diary", "Front door key", "Ball", "magnet", "Grey wolf fur", "uncut dragonstone", "Dragonstone ring", "Dragonstone necklace", "Raw Shark", "Shark", "Burnt Shark", "Big Net", "Casket", "Raw cod", "Cod", "Raw Mackerel", "Mackerel", "Raw Bass", "Bass", "Ice Gloves", "Firebird Feather", "Firebird Feather", "Poisoned Iron dagger", "Poisoned bronze dagger", "Poisoned Steel dagger", "Poisoned Mithril dagger", "Poisoned Rune dagger", "Poisoned Adamantite dagger", "Poisoned Black dagger", "Cure poison Potion", "Cure poison Potion", "Cure poison Potion", "Poison antidote", "Poison antidote", "Poison antidote", "weapon poison", "ID Paper", "Poison Bronze Arrows", "Christmas cracker", "Party Hat", "Party Hat", "Party Hat", "Party Hat", "Party Hat", "Party Hat", "Miscellaneous key", "Bunch of keys", "Whisky", "Candlestick", "Master thief armband", "Blamish snail slime", "Blamish oil", "Oily Fishing Rod", "lava eel", "Raw lava eel", "Poison Crossbow bolts", "Dragon sword", "Dragon axe", "Jail keys", "Dusty Key", "Charged Dragonstone Amulet", "Grog", "Candle", "black Candle", "Candle", "black Candle", "insect repellant", "Bat bones", "wax Bucket", "Excalibur", "Druids robe", "Druids robe", "Eye patch", "Unenchanted Dragonstone Amulet", "Unpowered orb", "Fire orb", "Water orb", "Battlestaff", "Battlestaff of fire", "Battlestaff of water", "Battlestaff of air", "Battlestaff of earth", "Blood-Rune", "Beer glass", "glassblowing pipe", "seaweed", "molten glass", "soda ash", "sand", "air orb", "earth orb", "bass certificate", "Raw bass certificate", "shark certificate", "Raw shark certificate", "Oak Logs", "Willow Logs", "Maple Logs", "Yew Logs", "Magic Logs", "Headless Arrows", "Iron Arrows", "Poison Iron Arrows", "Steel Arrows", "Poison Steel Arrows", "Mithril Arrows", "Poison Mithril Arrows", "Adamantite Arrows", "Poison Adamantite Arrows", "Rune Arrows", "Poison Rune Arrows", "Oak Longbow", "Oak Shortbow", "Willow Longbow", "Willow Shortbow", "Maple Longbow", "Maple Shortbow", "Yew Longbow", "Yew Shortbow", "Magic Longbow", "Magic Shortbow", "unstrung Oak Longbow", "unstrung Oak Shortbow", "unstrung Willow Longbow", "unstrung Willow Shortbow", "unstrung Maple Longbow", "unstrung Maple Shortbow", "unstrung Yew Longbow", "unstrung Yew Shortbow", "unstrung Magic Longbow", "unstrung Magic Shortbow", "barcrawl card", "bronze arrow heads", "iron arrow heads", "steel arrow heads", "mithril arrow heads", "adamantite arrow heads", "rune arrow heads", "flax", "bow string", "Easter egg", "scorpion cage", "scorpion cage", "scorpion cage", "scorpion cage", "Enchanted Battlestaff of fire", "Enchanted Battlestaff of water", "Enchanted Battlestaff of air", "Enchanted Battlestaff of earth", "scorpion cage", "scorpion cage", "scorpion cage", "scorpion cage", "gold", "gold bar", "Ruby ring", "Ruby necklace", "Family crest", "Crest fragment", "Crest fragment", "Crest fragment", "Steel gauntlets", "gauntlets of goldsmithing", "gauntlets of cooking", "gauntlets of chaos", "robe of Zamorak", "robe of Zamorak", "Address Label", "Tribal totem", "tourist guide", "spice", "Uncooked curry", "curry", "Burnt curry", "yew logs certificate", "maple logs certificate", "willow logs certificate", "lockpick", "Red vine worms", "Blanket", "Raw giant carp", "giant Carp", "Fishing competition Pass", "Hemenster fishing trophy", "Pendant of Lucien", "Boots of lightfootedness", "Ice Arrows", "Lever", "Staff of Armadyl", "Pendant of Armadyl", "Large cog", "Large cog", "Large cog", "Large cog", "Rat Poison", "shiny Key", "khazard Helmet", "khazard chainmail", "khali brew", "khazard cell keys", "Poison chalice", "magic whistle", "Cup of tea", "orb of protection", "orbs of protection", "Holy table napkin", "bell", "Gnome Emerald Amulet of protection", "magic golden feather", "Holy grail", "Script of Hazeel", "Pineapple", "Pineapple ring", "Pineapple Pizza", "Half pineapple Pizza", "Magic scroll", "Mark of Hazeel", "bloody axe of zamorak", "carnillean armour", "Carnillean Key", "Cattle prod", "Plagued sheep remains", "Poisoned animal feed", "Protective jacket", "Protective trousers", "Plagued sheep remains", "Plagued sheep remains", "Plagued sheep remains", "dwellberries", "Gasmask", "picture", "Book", "Seaslug", "chocolaty milk", "Hangover cure", "Chocolate dust", "Torch", "Torch", "warrant", "Damp sticks", "Dry sticks", "Broken glass", "oyster pearls", "little key", "Scruffy note", "Glarial's amulet", "Swamp tar", "Uncooked Swamp paste", "Swamp paste", "Oyster pearl bolts", "Glarials pebble", "book on baxtorian", "large key", "Oyster pearl bolt tips", "oyster", "oyster pearls", "oyster", "Soil", "Dragon medium Helmet", "Mithril seed", "An old key", "pigeon cage", "Messenger pigeons", "Bird feed", "Rotten apples", "Doctors gown", "Bronze key", "Distillator", "Glarial's urn", "Glarial's urn", "Priest robe", "Priest gown", "Liquid Honey", "Ethenea", "Sulphuric Broline", "Plague sample", "Touch paper", "Dragon Bones", "Herb", "Snake Weed", "Herb", "Ardrigal", "Herb", "Sito Foil", "Herb", "Volencia Moss", "Herb", "Rogues Purse", "Soul-Rune", "king lathas Amulet", "Bronze Spear", "halloween mask", "Dragon bitter", "Greenmans ale", "halloween mask", "halloween mask", "cocktail glass", "cocktail shaker", "Bone Key", "gnome robe", "gnome robe", "gnome robe", "gnome robe", "gnome robe", "gnomeshat", "gnomeshat", "gnomeshat", "gnomeshat", "gnomeshat", "gnome top", "gnome top", "gnome top", "gnome top", "gnome top", "gnome cocktail guide", "Beads of the dead", "cocktail glass", "cocktail glass", "lemon", "lemon slices", "orange", "orange slices", "Diced orange", "Diced lemon", "Fresh Pineapple", "Pineapple chunks", "lime", "lime chunks", "lime slices", "fruit blast", "odd looking cocktail", "Whisky", "vodka", "gin", "cream", "Drunk dragon", "Equa leaves", "SGG", "Chocolate saturday", "brandy", "blurberry special", "wizard blizzard", "pineapple punch", "gnomebatta dough", "gianne dough", "gnomebowl dough", "gnomecrunchie dough", "gnomebatta", "gnomebowl", "gnomebatta", "gnomecrunchie", "gnomebowl", "Uncut Red Topaz", "Uncut Jade", "Uncut Opal", "Red Topaz", "Jade", "Opal", "Swamp Toad", "Toad legs", "King worm", "Gnome spice", "gianne cook book", "gnomecrunchie", "cheese and tomato batta", "toad batta", "gnome batta", "worm batta", "fruit batta", "Veg batta", "Chocolate bomb", "Vegball", "worm hole", "Tangled toads legs", "Choc crunchies", "Worm crunchies", "Toad crunchies", "Spice crunchies", "Crushed Gemstone", "Blurberry badge", "Gianne badge", "tree gnome translation", "Bark sample", "War ship", "gloughs journal", "invoice", "Ugthanki Kebab", "special curry", "glough's key", "glough's notes", "Pebble", "Pebble", "Pebble", "Pebble", "Daconia rock", "Sinister key", "Herb", "Torstol", "Unfinished potion", "Jangerberries", "fruit blast", "blurberry special", "wizard blizzard", "pineapple punch", "SGG", "Chocolate saturday", "Drunk dragon", "cheese and tomato batta", "toad batta", "gnome batta", "worm batta", "fruit batta", "Veg batta", "Chocolate bomb", "Vegball", "worm hole", "Tangled toads legs", "Choc crunchies", "Worm crunchies", "Toad crunchies", "Spice crunchies", "Stone-Plaque", "Tattered Scroll", "Crumpled Scroll", "Bervirius Tomb Notes", "Zadimus Corpse", "Potion of Zamorak", "Potion of Zamorak", "Potion of Zamorak", "Boots", "Boots", "Boots", "Boots", "Boots", "Santa's hat", "Locating Crystal", "Sword Pommel", "Bone Shard", "Steel Wire", "Bone Beads", "Rashiliya Corpse", "ResetCrystal", "Bronze Wire", "Present", "Gnome Ball", "Papyrus", "A lump of Charcoal", "Arrow", "Lit Arrow", "Rocks", "Paramaya Rest Ticket", "Ship Ticket", "Damp cloth", "Desert Boots", "Orb of light", "Orb of light", "Orb of light", "Orb of light", "Railing", "Randas's journal", "Unicorn horn", "Coat of Arms", "Coat of Arms", "Staff of Iban", "Dwarf brew", "Ibans Ashes", "Cat", "A Doll of Iban", "Old Journal", "Klank's gauntlets", "Iban's shadow", "Iban's conscience", "Amulet of Othainian", "Amulet of Doomion", "Amulet of Holthion", "keep key", "Bronze Throwing Dart", "Prototype Throwing Dart", "Iron Throwing Dart", "Full Water Skin", "Lens mould", "Lens", "Desert Robe", "Desert Shirt", "Metal Key", "Slaves Robe Bottom", "Slaves Robe Top", "Steel Throwing Dart", "Astrology Book", "Unholy Symbol mould", "Unholy Symbol of Zamorak", "Unblessed Unholy Symbol of Zamorak", "Unholy Symbol of Zamorak", "Shantay Desert Pass", "Staff of Iban", "Dwarf cannon base", "Dwarf cannon stand", "Dwarf cannon barrels", "Dwarf cannon furnace", "Fingernails", "Powering crystal1", "Mining Barrel", "Ana in a Barrel", "Stolen gold", "multi cannon ball", "Railing", "Ogre tooth", "Ogre relic", "Skavid map", "dwarf remains", "Key", "Ogre relic part", "Ogre relic part", "Ogre relic part", "Ground bat bones", "Unfinished potion", "Ogre potion", "Magic ogre potion", "Tool kit", "Nulodion's notes", "cannon ammo mould", "Tenti Pineapple", "Bedobin Copy Key", "Technical Plans", "Rock cake", "Bronze dart tips", "Iron dart tips", "Steel dart tips", "Mithril dart tips", "Adamantite dart tips", "Rune dart tips", "Mithril Throwing Dart", "Adamantite Throwing Dart", "Rune Throwing Dart", "Prototype dart tip", "info document", "Instruction manual", "Unfinished potion", "Iron throwing knife", "Bronze throwing knife", "Steel throwing knife", "Mithril throwing knife", "Adamantite throwing knife", "Rune throwing knife", "Black throwing knife", "Water Skin mostly full", "Water Skin mostly empty", "Water Skin mouthful left", "Empty Water Skin", "nightshade", "Shaman robe", "Iron Spear", "Steel Spear", "Mithril Spear", "Adamantite Spear", "Rune Spear", "Cat", "Seasoned Sardine", "Kittens", "Kitten", "Wrought iron key", "Cell Door Key", "A free Shantay Disclaimer", "Doogle leaves", "Raw Ugthanki Meat", "Tasty Ugthanki Kebab", "Cooked Ugthanki Meat", "Uncooked Pitta Bread", "Pitta Bread", "Tomato Mixture", "Onion Mixture", "Onion and Tomato Mixture", "Onion and Tomato and Ugthanki Mix", "Burnt Pitta Bread", "Panning tray", "Panning tray", "Panning tray", "Rock pick", "Specimen brush", "Specimen jar", "Rock Sample", "gold Nuggets", "cat", "Scrumpled piece of paper", "Digsite info", "Poisoned Bronze Throwing Dart", "Poisoned Iron Throwing Dart", "Poisoned Steel Throwing Dart", "Poisoned Mithril Throwing Dart", "Poisoned Adamantite Throwing Dart", "Poisoned Rune Throwing Dart", "Poisoned Bronze throwing knife", "Poisoned Iron throwing knife", "Poisoned Steel throwing knife", "Poisoned Mithril throwing knife", "Poisoned Black throwing knife", "Poisoned Adamantite throwing knife", "Poisoned Rune throwing knife", "Poisoned Bronze Spear", "Poisoned Iron Spear", "Poisoned Steel Spear", "Poisoned Mithril Spear", "Poisoned Adamantite Spear", "Poisoned Rune Spear", "Book of experimental chemistry", "Level 1 Certificate", "Level 2 Certificate", "Level 3 Certificate", "Trowel", "Stamped letter of recommendation", "Unstamped letter of recommendation", "Rock Sample", "Rock Sample", "Cracked rock Sample", "Belt buckle", "Powering crystal2", "Powering crystal3", "Powering crystal4", "Old boot", "Bunny ears", "Damaged armour", "Damaged armour", "Rusty sword", "Ammonium Nitrate", "Nitroglycerin", "Old tooth", "Radimus Scrolls", "chest key", "broken arrow", "buttons", "broken staff", "vase", "ceramic remains", "Broken glass", "Unidentified powder", "Machette", "Scroll", "stone tablet", "Talisman of Zaros", "Explosive compound", "Bull Roarer", "Mixed chemicals", "Ground charcoal", "Mixed chemicals", "Spell scroll", "Yommi tree seed", "Totem Pole", "Dwarf cannon base", "Dwarf cannon stand", "Dwarf cannon barrels", "Dwarf cannon furnace", "Golden Bowl", "Golden Bowl with pure water", "Raw Manta ray", "Manta ray", "Raw Sea turtle", "Sea turtle", "Annas Silver Necklace", "Bobs Silver Teacup", "Carols Silver Bottle", "Davids Silver Book", "Elizabeths Silver Needle", "Franks Silver Pot", "Thread", "Thread", "Thread", "Flypaper", "Murder Scene Pot", "A Silver Dagger", "Murderers fingerprint", "Annas fingerprint", "Bobs fingerprint", "Carols fingerprint", "Davids fingerprint", "Elizabeths fingerprint", "Franks fingerprint", "Zamorak Cape", "Saradomin Cape", "Guthix Cape", "Staff of zamorak", "Staff of guthix", "Staff of Saradomin", "A chunk of crystal", "A lump of crystal", "A hunk of crystal", "A red crystal", "Unidentified fingerprint", "Annas Silver Necklace", "Bobs Silver Teacup", "Carols Silver Bottle", "Davids Silver Book", "Elizabeths Silver Needle", "Franks Silver Pot", "A Silver Dagger", "A glowing red crystal", "Unidentified liquid", "Radimus Scrolls", "Robe", "Armour", "Dagger", "eye patch", "Booking of Binding", "Holy Water Vial", "Enchanted Vial", "Scribbled notes", "Scrawled notes", "Scatched notes", "Shamans Tome", "Edible seaweed", "Rough Sketch of a bowl", "Burnt Manta ray", "Burnt Sea turtle", "Cut reed plant", "Magical Fire Pass", "Snakes Weed Solution", "Ardrigal Solution", "Gujuo Potion", "Germinated Yommi tree seed", "Dark Dagger", "Glowing Dark Dagger", "Holy Force Spell", "Iron Pickaxe", "Steel Pickaxe", "Mithril Pickaxe", "Adamantite Pickaxe", "Rune Pickaxe", "Sleeping Bag", "A blue wizards hat", "Gilded Totem Pole", "Blessed Golden Bowl", "Blessed Golden Bowl with Pure Water", "Raw Oomlie Meat", "Cooked Oomlie meat Parcel", "Dragon Bone Certificate", "Limpwurt Root Certificate", "Prayer Potion Certificate", "Super Attack Potion Certificate", "Super Defense Potion Certificate", "Super Strength Potion Certificate", "Half Dragon Square Shield", "Half Dragon Square Shield", "Dragon Square Shield", "Palm tree leaf", "Raw Oomlie Meat Parcel", "Burnt Oomlie Meat parcel", "Bailing Bucket", "Plank", "Arcenia root", "display tea", "Blessed Golden Bowl with plain water", "Golden Bowl with plain water", "Cape of legends", "Scythe" }
  199. ITEM_NAMES[0] = "Iron Mace"
  200. ITEM_BASE_PRICE = { 91,238,168,20,84,154,210,560,280,1,2,56,6,4,21,6,6,1,4,1,2,6,2,35,1,1,1,35,2,1,4,4,4,4,3,3,1,20,1,7,10,12,1,200,200,15,1,1,5,6,1,50,1,1,1,1,1,1,4,70,1,10,125,325,800,26,325,845,2080,40,140,500,1300,3200,32000,80,280,1000,2600,6400,64000,32,112,400,1040,2560,16,200,182,650,1690,4160,41600,18,225,585,1440,14400,1,15,1500,1500,1500,24,300,780,1920,44,550,1430,3520,35200,60,750,1950,4800,160,2000,5200,12800,1000,2600,6400,48,600,1560,3840,68,850,2210,5440,4,1,1,1,10,1,12,1,1,1,1,1,1,1,10,1,1,1,3,17,150,162,400,45,1,200,100,50,25,2000,1000,500,250,1,1,1,1,8,28,100,300,300,640,1,1,1,1,1,1,2,2,2,15,2,30,2,80,50,3,2,2,2,2,2,3840,1500,200,2,30,1,3,520,1280,52,80,2,3,7,3,3,1,3,80,280,13,8,3,7,7,14,13,13,11,1000,2600,6400,1,32,1056,4,4,4,4,100,3,18,5,5,5,3,1,2,2,2,1,2,1920,2,1,3,1,1,1,1,1,30,12,15,1,10,4,5,3,200,3,2,2,2,3,3,5,40,40,40,60,23,3,1,1,1,5,350,900,1275,2025,3525,450,1050,1425,2175,3675,5,5,5,350,900,1275,2025,3525,350,900,1275,2025,3525,3525,4500,160,2000,5200,12800,560,3840,900,1275,2025,3525,30,4,4,4,1,10,25,40,50,60,25,30,50,1,70,30,50,10,30,10,10,20,2,4,3,4,4,10,20,1,1,5,5,15,15,1,10,10,50,50,20,20,1,15,15,25,25,1,100,100,1,200,200,1,150,150,1,20,5,5,5,5,3,2,1,75,150,300,5,12,40,30,1,1,1,1,1,1,8000,20800,25600,19200,50000,65000,64000,38400,54400,12800,64000,65000,5000,3200,1,1,1,1,1,1,1,1,1,3,20,1,30,240,624,960,1920,768,384,1248,432,1440,1152,1632,1920,1,1,1,1,1,1,1,1,1,3,5,11,20,25,40,48,54,65,70,3,5,11,20,25,40,48,54,65,70,2,2,20,50,4,10,576,10,40,20,12,9,6,88,66,44,120,90,60,152,114,76,180,135,90,200,150,100,220,165,110,264,198,132,288,216,144,1,1,1,1,1,1,1,1,15,15,32,32,32,32,5,5,10,20,30,15,25,17625,10000,17625,1,1,1,10,20,30,15,25,10,10,10,10,1,1,1,3,50,1000,17625,18375,300,300,1,20,50,25,25,17,17,120,120,6,2,2,35,10,125,325,8000,800,240,288,216,144,288,216,144,144,1,2,1,2,2,2,2,2,2,1,2,5,5,2,5,10,15,150,150,3,100000,200000,2,1,17625,3,3,3,3,3,3,1,2,200,40,30,2,17625,100,300,300,7000,15500,15500,15500,15500,25,2,2,2,2,2,2,300,300,10,10,10,10,20,40,80,160,320,1,6,6,24,24,64,64,160,160,800,800,160,100,320,200,640,400,1280,800,2560,1600,80,50,160,100,320,200,640,400,1280,800,10,1,3,12,32,80,400,5,10,10,10,10,10,10,42500,42500,42500,42500,10,10,10,10,150,300,2025,2175,10,10,10,10,6,6,6,6,40,30,10,10,1,230,10,20,1,10,20,30,20,3,5,50,50,10,20,12,6,2,20,15,12,10,10,10,10,1,1,10,10,5,1,20,10,10,1,1,10,1,0,2,1,1,1,1,100,50,1,0,5000,65,1,15,0,0,50,50,0,0,0,4,2,2,1,4,2,2,2,4,4,5,0,0,0,1400,1,2,1,1,1,30,110,1,2,1,56,5,112,200,2,100000,200,1,1,1,1,1,40,1,1,1,1,5,5,0,10,1,1,1,1,1,5,1,5,1,5,1,5,1,5,2500,10,4,15,2,2,15,15,0,2,1,180,180,180,180,180,160,160,160,160,160,180,180,180,180,180,2,35,2,2,2,2,2,2,2,2,1,1,2,1,2,2,2,5,5,5,2,2,2,2,2,5,2,2,2,2,2,2,2,2,2,2,2,2,40,30,20,200,150,100,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,20,20,1,2,2,2,2,2,40,1,1,25,25,1,30,30,30,30,30,30,30,120,120,120,120,120,120,160,150,150,160,85,85,85,85,5,5,5,5,1,25,25,25,200,200,200,200,200,160,100,100,1,200,1,1,100,20,160,10,9,45,10,10,10,5,5,10,20,10,10,10,10,10,1,20,10,10,15,2,2,2,2,1,6,2,2,0,0,0,1,2,70,5,30,10,10,40,40,1,40,40,20,2,200,200,200,200,5,15,200000,200000,200000,200000,0,0,100,100,300,10,10,0,0,0,1,1,0,0,0,20,3,120,120,120,1,5,1,20,500,0,1,3,9,25,65,350,50,130,700,1,2,1,3,6,2,21,54,133,333,37,27,24,18,15,30,40,13,46,119,293,1000,2,10,2,2,1,1,1,2,2,20,5,4,10,3,3,3,3,1,1,1,1,1,1,1,1,1,1,10,63,2,5,20,50,130,700,2,6,21,54,37,133,333,4,13,46,119,293,1000,1,1,1,1,1,1,5,1,1,1,1,0,0,0,1,1,1,1,1,20,2,0,5,1,1,1,1,1,1,0,20,40,5,1,1,2,1,2,20,2,5,200,500,200000,200000,200000,150000,1000,1000,500,500,500,500,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,100,100,100,80000,80000,80000,2000,2000,2000,2000,1,1,1,1,1,1,1,1,2000,2,5,15,40,35,2,1,3,200,20,20,20,1,2,5,500,500,2,1,1,1,1,200,91,91,1,140,500,1300,3200,32000,30,2,20,1000,1000,10,35,10,10,10,10,10,10,500000,110000,500000,5,16,1,10,1,7,10,1000,1000,450,15 }
  201. ITEM_BASE_PRICE[0] = 63
  202. ITEM_WEILDABLE = { true,true,true,true,true,true,true,true,true,false,false,true,false,false,true,true,true,false,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,false,false,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,false,true,true,false,true,true,true,true,true,true,false,false,false,true,true,true,true,false,false,true,false,false,false,false,true,true,true,true,false,false,false,false,false,false,false,true,true,true,false,true,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,true,true,true,true,true,false,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,true,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,true,true,true,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,true,false,false,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,true,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,false,false,false,false,false,false,true,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,true,true,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,true,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,true,true,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,true,true,true,false,true,false,true,false,false,false,true,true,false,true,true,true,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,true,true,true,true,true,true,true,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,true,false,true,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,true,true }
  203. ITEM_WEILDABLE[0] = true
  204. ITEM_STACKABLE = { false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,true,true,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,true,true,true,true,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,true,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,false,false,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,false,false,false,false,false,false,false,false,true,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false }
  205. ITEM_STACKABLE[0] = false
  206. -- Scenery Names
  207. SCENERY_NAMES = { "Tree","Well","Table","Treestump","Ladder","Ladder","Chair","logs","Longtable","Throne","Range","Gravestone","Gravestone","Bed","Bed","bar","Chest","Chest","Altar","Post","Support","barrel","Bench","Portrait","candles","fountain","landscape","Millstones","Counter","Stall","Target","PalmTree","PalmTree","Fern","Cactus","Bullrushes","Flower","Mushroom","Coffin","Coffin","stairs","stairs","stairs","stairs","railing","pillar","Bookcase","Sink","Dummy","anvil","Torch","hopper","chute","cart","sacks","cupboard","Gate","gate","gate","gate","signpost","signpost","doors","doors","signpost","signpost","bookcase","henge","Dolmen","Tree","cupboard","Wheat","sign","sails","sign","sign","Drain","manhole","manhole","pipe","Chest","Chest","barrel","cupboard","cupboard","fountain","signpost","Tree","sign","sign","sign","sign","gate","gate","sign","sign","fire","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","Rock","web","web","furnace","Cook's Range","Machine","Spinning wheel","Lever","Lever","LeverA","LeverB","LeverC","LeverD","LeverE","LeverF","Ladder","signpost","signpost","signpost","Compost Heap","Coffin","Coffin","gate","gate","sign","cupboard","cupboard","doors","torch","Altar","Shield","Grill","Cauldron","Grill","Mine Cart","Buffers","Track","Track","Track","Hole","ship","ship","ship","Emergency escape ladder","sign","sign","ship","ship","ship","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","hopper","cupboard","cupboard","Rocks","Doric's anvil","pottery oven","potter's wheel","gate","gate","crate","Banana tree","Banana tree","crate","Chest","Chest","Flower","sign","sign","Potato","fish","fish","fish","Rock","Rock","Rocks","Ladder","Ladder","Monks Altar","Ladder","Coffin","Coffin","Smashed table","Fungus","Smashed chair","Broken pillar","Fallen tree","Danger Sign","Rock","Rock","Rocks","Gravestone","bone","bone","carcass","animalskull","Vine","Vine","Vine","Chest","Chest","Ladder","ship","ship","hole","Ladder","Chest","Chest","Chest","Chest","hole","ship","ship","Altar of Guthix","The Cauldron of Thunder","Tree","ship","ship","ship","ship","ship","ship","Ladder","Dramen Tree","hopper","Chest","Chest","Ladder","sign","sign","gate","gate","gate","Door mat","gate","Cauldron","cupboard","cupboard","gate","fish","sign","cupboard","cupboard","Chest","Chest","sign","signpost","Rockslide","Ladder","fish","barrel","table","Fireplace","Egg","Eggs","Stalagmites","Stool","Bench","table","table","fountain of heros","bush","hedge","flower","plant","Giant crystal","sign","sign","crate","crate","ship","ship","beehive","Ladder","Altar","sign","signpost","Archway","Obelisk of water","Obelisk of fire","sand pit","Obelisk of air","Obelisk of earth","gate","Oak Tree","Willow Tree","Maple Tree","Yew Tree","Tree","gate","sign","flax","Large treestump","Rocks","Lever","Lever","Lever","gate","ship","ship","Bakers Stall","Silk Stall","Fur Stall","Silver Stall","Spices Stall","gems Stall","crate","crate","sign","stairs","Chest","Chest","Chest","Chest","Chest","Chest","Chest","Chest","Chest","empty stall","stairs","hopper","signpost","sign","gate","gate","Lever","Lever","pipe","fish","fish","fish","fish","Vine","gate","gate","gate","stairs","broken cart","Lever","clock pole blue","clock pole red","clock pole purple","clock pole black","wallclockface","Lever Bracket","Lever","stairs","stairs","gate","gate","Lever","Lever","Foodtrough","fish","spearwall","hornedskull","Chest","Chest","guardscupboard","guardscupboard","Coal truck","ship","ship","ship","Tree","Ballista","largespear","spirit tree","young spirit Tree","gate","wall","tree","tree","Fern","Fern","Fern","Fern","fly trap","Fern","Fern","plant","plant","plant","stone head","dead Tree","sacks","khazard open Chest","khazard shut Chest","doorframe","Sewer valve","Sewer valve 2","Sewer valve 3","Sewer valve 4","Sewer valve 5","Cave entrance","Log bridge","Log bridge","tree platform","tree platform","gate","tree platform","tree platform","Log bridge","Log bridge","tree platform","tree platform","Tribal brew","Pineapple tree","Pineapple tree","log raft","log raft","Tomb of hazeel","range","Bookcase","Carnillean Chest","Carnillean Chest","crate","Butlers cupboard","Butlers cupboard","gate","gate","Cattle furnace","Ardounge wall","Ardounge wall corner","Dug up soil","Pile of mud","large Sewer pipe","Ardounge wall gateway","cupboard","cupboard","Fishing crane","Rowboat","Damaged Rowboat","barrel","gate","Ladder","Fishing crane","Fishing crane","Waterfall","leaflessTree","leaflessTree","log raft","doors","Well","Tomb of glarial","Waterfall","Waterfall","Bookcase","doors","doors","Stone stand","Stone stand","Stone stand","Stone stand","Stone stand","Stone stand","Glarial's Gravestone","gate","crate","leaflessTree","Statue of glarial","Chalice of eternity","Chalice of eternity","doors","Lever","Lever","log raft remains","Tree"," Range","crate","fish","Watch tower","signpost","Rocks","doors","Rope ladder","cupboard","cupboard","Rope ladder","Cooking pot","Gallow","gate","crate","cupboard","cupboard","gate","cupboard","cupboard","sign","grand tree","gate","gate","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Log bridge","Watch tower","Log bridge","climbing rocks","Ledge","Ledge","log","log","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","PalmTree","Scorched Earth","Rocks","sign","fish","Rocky Walkway","Rocky Walkway","Rocky Walkway","Rocky Walkway","fight Dummy","gate","Jungle Vine","statue","sign","grand tree","grand tree","grand tree","grand tree","grand tree","Hillside Entrance","tree","Log bridge","Tree platform","Tree platform","Metalic Dungeon Gate","Log bridge","Log bridge","Watch tower","Watch tower","Shallow water","Doors","grand tree","Tree Ladder","Tree Ladder","blurberrys cocktail bar","Gem Rocks","Giannes place","ropeswing","net","Frame","Tree","Tree","Tree","cart","fence","beam","Sign","Sign","Sign","Sign","Sign","Sign","Sign","Sign","Sign","Sign","Root","Root","Metal Gate","Metal Gate","A farm cart","Ledge","Ledge","Ladder","cage","glider","cupboard","cupboard","stairs","glider","gate","gate","chaos altar","Gnome stronghold gate","ropeswing","ropeswing","stairs","stairs","Chest","Chest","Pile of rubble","Stone stand","Watch tower","Pile of rubble","Root","Root","Root","Sign","Hammock","Goal","stone tile","Chest","Chest","Watch tower","net","Watch tower","Watch tower","ropeswing","Bumpy Dirt","pipe","net","pipe","log","pipe","pipe","Handholds","Ladder","gate","stronghold spirit Tree","Tree","Tree","Tree","Spiked pit","Spiked pit","Cave","stone pebble","Pile of rubble","Pile of rubble","pipe","pipe","Stone","Stone","ropeswing","log","net","Ledge","Handholds","log","log","Rotten Gallows","Pile of rubble","ropeswing","ropeswing","ocks","Tree","Well stacked rocks","Tomb Dolmen","Handholds","Bridge Blockade","Log Bridge","Handholds","Tree","Tree","Wet rocks","Smashed table","Crude Raft","Daconia rock","statue","Stepping stones","gate","gate","gate","pipe","ropeswing","Stone","Ledge","Vine","Rocks","Wooden Gate","Wooden Gate","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone platform","fence","Rocks","Stone bridge","Stone bridge","Gate of Iban","Wooden Door","Tomb Dolmen","Cave entrance","Old bridge","Old bridge","Crumbled rock","stalagmite","stalagmite","Rocks","Ledge","Lever","stalactite","stalactite","stalactite","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Ledge","Ledge","Ledge","Ledge","Swamp","Swamp","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Pile of mud","Travel Cart","Travel Cart","Rocks","stalactite","Rocks","Rocks","Rocks","sign","Ladder","Grill","Spiked pit","signpost","Ship","Ship","Grill","sacks","Zamorakian Temple","Grill","Grill","Grill","Grill","Grill","Grill","Grill","Rocks","Rocks","Tomb Doors","Swamp","Rocks","Rocks","stalactite","stalactite","Spiked pit","Lever","Cage","Cage","Rocks","Spear trap","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Ledge","Furnace","Well","Passage","Passage","Passage","stalagmite","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Passage","snap trap","Wooden planks","Passage","Passage","Flames of zamorak","Platform","Rock","Rock","Rock","Rock","wall grill","Ledge","wall grill","Dug up soil","Dug up soil","Pile of mud","stalagmite","Pile of mud","Pile of mud","Pile of mud","Pile of mud","Pile of mud","Spiked pit","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Rocks","Ledge","Ledge","Ledge","Ledge","Ledge","Ledge","Boulder","crate","Door","Platform","Cage remains","Ledge","Passage","Passage","Gate of Zamorak","Rocks","Bridge support","Tomb of Iban","Claws of Iban","barrel","Rock","Rocks","Rocks","Swamp","Chest","Stone bridge","cage","cage","Stone steps","Pile of mud","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Stone bridge","Chest","Chest","Pit of the Damned","Open Door","signpost","Stone Gate","Chest","Zodiac","Chest","Ladder","Stone steps","Rock","Rock","Rock","Telescope","Gate","sacks","Ladder","Chest","Chest","Bookcase","Iron Gate","Ladder","Chest","Chest","Chest","Chest","Rockslide","Altar","column","Grave of Scorpius","Bank Chest","dwarf multicannon","Disturbed sand","Disturbed sand","dwarf multicannon base","dwarf multicannon stand","dwarf multicannon barrels","Cave","Cave","fence","signpost","Rocks","Rocks","Cave entrance","Chest","Chest","Wooden Doors","Pedestal","bush","bush","Standard","Mining Cave","Mining Cave","Rocks","Lift","Mining Barrel","Hole","Hole","Cave","Cave","Cave","Counter","Track","Cave","Mine Cart","Lift Platform","Chest","Chest","Watch tower","Ladder","Cave entrance","Pile of mud","Cave","Ladder","crate","crate","Gate","Gate","bush","bush","bush","bush","multicannon","Rocks","Rocks","Ladder","Cave entrance","Counter","Chest","Chest","Chest","Chest","Bookcase","Captains Chest","Experimental Anvil","Rocks","Rocks","Column","Wall","Wall","Wall","Wall","Lever","Lever","Wall","Ladder","Wall","Gate","Gate","Ladder","shock","Desk","Cave","Mining Cart","Rock of Dalgroth","entrance","Dried Cactus","climbing rocks","Rocks","lightning","Crude Desk","Heavy Metal Gate","Counter","Crude bed","flames","Carved Rock","USE","crate","crate","barrel","Brick","Brick","Brick","Brick","Brick","Brick","Barrier","buried skeleton","Brick","Brick","Specimen tray","winch","crate","crate","Urn","buried skeleton","panning point","Rocks","signpost","signpost","signpost","signpost","signpost","soil","soil","soil","Gate","ship","barrel","Leak","bush","bush","cupboard","sacks","sacks","Leak","cupboard","Wrought Mithril Gates","Legends Hall Doors","Camp bed","barrel","barrel","Chest","Chest","Dense Jungle Tree","Jungle tree stump","signpost","gate","Bookcase","Dense Jungle Tree","Dense Jungle Tree","Spray","Spray","winch","Brick","Rope","Rope","Dense Jungle Palm","Dense Jungle Palm","Trawler net","Trawler net","Brick","Chest","Chest","Trawler catch","Yommi Tree","Grown Yommi Tree","Chopped Yommi Tree","Trimmed Yommi Tree","Totem Pole","Baby Yommi Tree","Fertile earth","Rock Hewn Stairs","Hanging rope","Rocks","Boulder","dwarf multicannon","dwarf multicannon base","dwarf multicannon stand","dwarf multicannon barrels","rock","Rock Hewn Stairs","Rock Hewn Stairs","Rock Hewn Stairs","Compost Heap","beehive","Drain","web","fountain","Sinclair Crest","barrel","barrel","barrel","barrel","barrel","barrel","Flour Barrel","sacks","gate","Dead Yommi Tree","clawspell","Rocks","crate","Cavernous Opening","Ancient Lava Furnace","Spellcharge","Rocks","cupboard","sacks","Rock","Saradomin stone","Guthix stone","Zamorak stone","Magical pool","Wooden Beam","Rope down into darkness","Cave entrance","Cave entrance","Ancient Wooden Doors","Table","Crude bed","Tall Reeds","Goblin foot prints","Dark Metal Gate","Magical pool","Rope Up","Half buried remains","Totem Pole","Totem Pole","Comfy bed","Rotten Yommi Tree","Rotten Yommi Tree","Rotten Yommi Tree","Rotten Totem Pole","Leafy Palm Tree","Grand Viziers Desk","Strange Barrel","ship","ship","ship","digsite bed","Tea stall","Boulder","Boulder","Damaged Earth","Ladder","Ladder" }
  208. SCENERY_NAMES[0] = "Tree"
  209. SCENERY_NAMES[60000] = "Nothing"
  210. BOUNDARY_NAMES = { "Doorframe","Door","Window","Fence","railings","Stained glass window","Highwall","Door","Doorframe","battlement","Doorframe","snowwall","arrowslit","timberwall","timberwindow","blank","highblank","mossybricks","Door","Door","Door","Odd looking wall","Door","web","Door","Door","Door","Door","Door","Door","Door","Door","Door","Window","Door","Door","Door","Door","Door","Door","Crumbled","Cavern","Door","Door","Door","cavern2","Door","Door","Door","Door","Door","Door","Door","Door","Door","Wall","Door","Strange looking wall","Door","Door","Door","memberrailings","Door","Door","Magic Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Strange Panel","Door","Door","Door","Door","Door","Door","blockblank","unusual looking wall","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Fence with loose pannels","Door","Door","Door","Door","Door","Door","Door","Door","Door","rat cage","Door","Door","Door","Door","Door","Door","arrowslit","solidblank","Door","Door","Door","Door","loose panel","Door","plankswindow","Low Fence","Door","Door","Door","Door","Door","Door","Door","Door","Door","Cooking pot","Door","Door","Door","Door","Door","Door","plankstimber","Door","Door","magic portal","magic portal","magic portal","Door","Cavern wall","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Door","Low wall","Low wall","Blacksmiths Door","railings","railings","railings","railings","railings","railings","railings","Door","Doorframe","Tent","Jail Door","Jail Door","Window","magic portal","Jail Door","railings","railings","railings","railings","railings","railings","Cave exit","Cave exit","Cave exit","Cave exit","Cave exit","Cave exit","railings","Door","battlement","Tent Door","Door","Tent Door","Low Fence","Sturdy Iron Gate","battlement","Water","Wheat","Jungle","Window","Rut","Crumbled Cavern 1","Crumbled Cavern 2","cavernhole","flamewall","Ruined wall","Ancient Wall","Door" }
  211. BOUNDARY_NAMES[0] = "Wall"
  212. -- NPC data
  213. NPC_NAMES = { "Bob","Sheep","Chicken","Goblin","Hans","cow","cook","Bear","Priest","Urhney","Man","Bartender","Camel","Gypsy","Ghost","Sir Prysin","Traiborn the wizard","Captain Rovin","Rat","Reldo","mugger","Lesser Demon","Giant Spider","Man","Jonny the beard","Baraek","Katrine","Tramp","Rat","Romeo","Juliet","Father Lawrence","Apothecary","spider","Delrith","Veronica","Weaponsmaster","Professor Oddenstein","Curator","skeleton","zombie","king","Giant bat","Bartender","skeleton","skeleton","Rat","Horvik the Armourer","Bear","skeleton","Shopkeeper","zombie","Ghost","Aubury","Shopkeeper","shopkeeper","Darkwizard","lowe","Thessalia","Darkwizard","Giant","Goblin","farmer","Thief","Guard","Black Knight","Hobgoblin","zombie","Zaff","Scorpion","silk trader","Man","Guide","Giant Spider","Peksa","Barbarian","Fred the farmer","Gunthor the Brave","Witch","Ghost","Wizard","Shop Assistant","Shop Assistant","Zeke","Louie Legs","Warrior","Shopkeeper","Shop Assistant","Highwayman","Kebab Seller","Chicken","Ernest","Monk","Dwarf","Banker","Count Draynor","Morgan","Dr Harlow","Deadly Red spider","Guard","Cassie","White Knight","Ranael","Moss Giant","Shopkeeper","Shop Assistant","Witch","Black Knight","Greldo","Sir Amik Varze","Guildmaster","Valaine","Drogo","Imp","Flynn","Wyson the gardener","Wizard Mizgog","Prince Ali","Hassan","Osman","Joe","Leela","Lady Keli","Ned","Aggie","Prince Ali","Jailguard","Redbeard Frank","Wydin","shop assistant","Brian","squire","Head chef","Thurgo","Ice Giant","King Scorpion","Pirate","Sir Vyvin","Monk of Zamorak","Monk of Zamorak","Wayne","Barmaid","Dwarven shopkeeper","Doric","Shopkeeper","Shop Assistant","Guide","Hetty","Betty","Bartender","General wartface","General Bentnoze","Goblin","Goblin","Herquin","Rommik","Grum","Ice warrior","Warrior","Thrander","Border Guard","Border Guard","Customs Officer","Luthas","Zambo","Captain Tobias","Gerrant","Shopkeeper","Shop Assistant","Seaman Lorris","Seaman Thresnor","Tanner","Dommik","Abbot Langley","Thordur","Brother Jered","Rat","Ghost","skeleton","zombie","Lesser Demon","Melzar the mad","Scavvo","Greater Demon","Shopkeeper","Shop Assistant","Oziach","Bear","Black Knight","chaos Dwarf","dwarf","Wormbrain","Klarense","Ned","skeleton","Dragon","Oracle","Duke of Lumbridge","Dark Warrior","Druid","Red Dragon","Blue Dragon","Baby Blue Dragon","Kaqemeex","Sanfew","Suit of armour","Adventurer","Adventurer","Adventurer","Adventurer","Leprechaun","Monk of entrana","Monk of entrana","zombie","Monk of entrana","tree spirit","cow","Irksol","Fairy Lunderwin","Jakut","Doorman","Fairy Shopkeeper","Fairy Shop Assistant","Fairy banker","Giles","Miles","Niles","Gaius","Fairy Ladder attendant","Jatix","Master Crafter","Bandit","Noterazzo","Bandit","Fat Tony","Donny the lad","Black Heather","Speedy Keith","White wolf sentry","Boy","Rat","Nora T Hag","Grey wolf","shapeshifter","shapeshifter","shapeshifter","shapeshifter","White wolf","Pack leader","Harry","Thug","Firebird","Achetties","Ice queen","Grubor","Trobert","Garv","guard","Grip","Alfonse the waiter","Charlie the cook","Guard Dog","Ice spider","Pirate","Jailer","Lord Darquarius","Seth","Banker","Helemos","Chaos Druid","Poison Scorpion","Velrak the explorer","Sir Lancelot","Sir Gawain","King Arthur","Sir Mordred","Renegade knight","Davon","Bartender","Arhein","Morgan le faye","Candlemaker","lady","lady","lady","Beggar","Merlin","Thrantax","Hickton","Black Demon","Black Dragon","Poison Spider","Monk of Zamorak","Hellhound","Animated axe","Black Unicorn","Frincos","Otherworldly being","Owen","Thormac the sorceror","Seer","Kharid Scorpion","Kharid Scorpion","Kharid Scorpion","Barbarian guard","Bartender","man","gem trader","Dimintheis","chef","Hobgoblin","Ogre","Boot the Dwarf","Wizard","Chronozon","Captain Barnaby","Customs Official","Man","farmer","Warrior","Guard","Knight","Paladin","Hero","Baker","silk merchant","Fur trader","silver merchant","spice merchant","gem merchant","Zenesha","Kangai Mau","Wizard Cromperty","RPDT employee","Horacio","Aemad","Kortan","zoo keeper","Make over mage","Bartender","chuck","Rogue","Shadow spider","Fire Giant","Grandpa Jack","Sinister stranger","Bonzo","Forester","Morris","Brother Omad","Thief","Head Thief","Big Dave","Joshua","Mountain Dwarf","Mountain Dwarf","Brother Cedric","Necromancer","zombie","Lucien","The Fire warrior of lesarkus","guardian of Armadyl","guardian of Armadyl","Lucien","winelda","Brother Kojo","Dungeon Rat","Master fisher","Orven","Padik","Shopkeeper","Lady servil","Guard","Guard","Guard","Guard","Jeremy Servil","Justin Servil","fightslave joe","fightslave kelvin","local","Khazard Bartender","General Khazard","Khazard Ogre","Guard","Khazard Scorpion","hengrad","Bouncer","Stankers","Docky","Shopkeeper","Fairy queen","Merlin","Crone","High priest of entrana","elkoy","remsai","bolkoy","local gnome","bolren","Black Knight titan","kalron","brother Galahad","tracker 1","tracker 2","tracker 3","Khazard troop","commander montai","gnome troop","khazard warlord","Sir Percival","Fisher king","maiden","Fisherman","King Percival","unhappy peasant","happy peasant","ceril","butler","carnillean guard","Tribesman","henryeta","philipe","clivet","cult member","Lord hazeel","alomone","Khazard commander","claus","1st plague sheep","2nd plague sheep","3rd plague sheep","4th plague sheep","Farmer brumty","Doctor orbon","Councillor Halgrive","Edmond","Citizen","Citizen","Citizen","Citizen","Citizen","Jethick","Mourner","Mourner","Ted Rehnison","Martha Rehnison","Billy Rehnison","Milli Rehnison","Alrena","Mourner","Clerk","Carla","Bravek","Caroline","Holgart","Holgart","Holgart","kent","bailey","kennith","Platform Fisherman","Platform Fisherman","Platform Fisherman","Elena","jinno","Watto","Recruiter","Head mourner","Almera","hudon","hadley","Rat","Combat instructor","golrie","Guide","King Black Dragon","cooking instructor","fishing instructor","financial advisor","gerald","mining instructor","Elena","Omart","Bank assistant","Jerico","Kilron","Guidor's wife","Quest advisor","chemist","Mourner","Mourner","Wilderness guide","Magic Instructor","Mourner","Community instructor","boatman","skeleton mage","controls guide","nurse sarah","Tailor","Mourner","Guard","Chemist","Chancy","Hops","DeVinci","Guidor","Chancy","Hops","DeVinci","king Lathas","Head wizard","Magic store owner","Wizard Frumscone","target practice zombie","Trufitus","Colonel Radick","Soldier","Bartender","Jungle Spider","Jiminua","Jogre","Guard","Ogre","Guard","Guard","shop keeper","Bartender","Frenita","Ogre chieftan","rometti","Rashiliyia","Blurberry","Heckel funch","Aluft Gianne","Hudo glenfad","Irena","Mosol","Gnome banker","King Narnode Shareen","UndeadOne","Drucas","tourist","King Narnode Shareen","Hazelmere","Glough","Shar","Shantay","charlie","Gnome guard","Gnome pilot","Mehman","Ana","Chaos Druid warrior","Gnome pilot","Shipyard worker","Shipyard worker","Shipyard worker","Shipyard foreman","Shipyard foreman","Gnome guard","Femi","Femi","Anita","Glough","Salarin the twisted","Black Demon","Gnome pilot","Gnome pilot","Gnome pilot","Gnome pilot","Sigbert the Adventurer","Yanille Watchman","Tower guard","Gnome Trainer","Gnome Trainer","Gnome Trainer","Gnome Trainer","Blurberry barman","Gnome waiter","Gnome guard","Gnome child","Earth warrior","Gnome child","Gnome child","Gulluck","Gunnjorn","Zadimus","Brimstail","Gnome child","Gnome local","Gnome local","Moss Giant","Gnome Baller","Goalie","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Referee","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Gnome Baller","Cheerleader","Cheerleader","Nazastarool Zombie","Nazastarool Skeleton","Nazastarool Ghost","Fernahei","Jungle Banker","Cart Driver","Cart Driver","Obli","Kaleb","Yohnus","Serevel","Yanni","Official","Koftik","Koftik","Koftik","Koftik","Blessed Vermen","Blessed Spider","Paladin","Paladin","slave","slave","slave","slave","slave","slave","slave","Kalrag","Niloof","Kardia the Witch","Souless","Othainian","Doomion","Holthion","Klank","Iban","Koftik","Goblin guard","Observatory Professor","Ugthanki","Observatory assistant","Souless","Dungeon spider","Kamen","Iban disciple","Koftik","Goblin","Chadwell","Professor","San Tojalon","Ghost","Spirit of Scorpius","Scorpion","Dark Mage","Mercenary","Mercenary Captain","Mercenary","Mining Slave","Watchtower wizard","Ogre Shaman","Skavid","Ogre guard","Ogre guard","Ogre guard","Skavid","Skavid","Og","Grew","Toban","Gorad","Ogre guard","Yanille Watchman","Ogre merchant","Ogre trader","Ogre trader","Ogre trader","Mercenary","City Guard","Mercenary","Lawgof","Dwarf","lollk","Skavid","Ogre guard","Nulodion","Dwarf","Al Shabim","Bedabin Nomad","Captain Siad","Bedabin Nomad Guard","Ogre citizen","Rock of ages","Ogre","Skavid","Skavid","Skavid","Draft Mercenary Guard","Mining Cart Driver","kolodion","kolodion","Gertrude","Shilop","Rowdy Guard","Shantay Pass Guard","Rowdy Slave","Shantay Pass Guard","Assistant","Desert Wolf","Workman","Examiner","Student","Student","Guide","Student","Archaeological expert","civillian","civillian","civillian","civillian","Murphy","Murphy","Sir Radimus Erkle","Legends Guild Guard","Escaping Mining Slave","Workman","Murphy","Echned Zekin","Donovan the Handyman","Pierre the Dog Handler","Hobbes the Butler","Louisa The Cook","Mary The Maid","Stanford The Gardener","Guard","Guard Dog","Guard","Man","Anna Sinclair","Bob Sinclair","Carol Sinclair","David Sinclair","Elizabeth Sinclair","Frank Sinclair","kolodion","kolodion","kolodion","kolodion","Irvig Senay","Ranalph Devere","Poison Salesman","Gujuo","Jungle Forester","Ungadulu","Ungadulu","Death Wing","Nezikchened","Dwarf Cannon engineer","Dwarf commander","Viyeldi","Nurmof","Fatigue expert","Karamja Wolf","Jungle Savage","Oomlie Bird","Sidney Smith","Siegfried Erkle","Tea seller","Wilough","Philop","Kanel","chamber guardian","Sir Radimus Erkle","Pit Scorpion","Shadow Warrior","Fionella","Battle mage","Battle mage","Battle mage","Gundai","Lundail" }
  214. NPC_NAMES[0] = "Unicorn"
  215. -- Names of message types are from RSC+
  216. MESSAGE_TYPES = { "Private Incoming", "Private Outgoing", "Quest", "Chat", "Private Log In/Log Out", "Trade Request Received", "Other" }
  217. MESSAGE_TYPES[0] = "None"
  218. -- Spelling & Capitalization is mirrored from Quest List as displayed in client
  219. QUEST_NAMES = { "Cook's assistant", "Demon slayer", "Doric's quest", "The restless ghost", "Goblin diplomacy", "Ernest the chicken", "Imp catcher", "Pirate's treasure", "Prince Ali rescue", "Romeo & Juliet", "Sheep shearer", "Shield of Arrav", "The knight's sword", "Vampire slayer", "Witch's potion", "Dragon slayer", "Witch's house", "Lost city", "Hero's quest", "Druidic ritual", "Merlin's crystal", "Scorpion catcher", "Family crest", "Tribal totem", "Fishing contest", "Monk's friend", "Temple of Ikov", "Clock tower", "The Holy Grail", "Fight Arena", "Tree Gnome Village", "The Hazeel Cult", "Sheep Herder", "Plague City", "Sea Slug", "Waterfall quest", "Biohazard", "Jungle potion", "Grand tree", "Shilo village", "Underground pass", "Observatory quest", "Tourist trap", "Watchtower", "Dwarf Cannon", "Murder Mystery", "Digsite", "Gertrude's Cat", "Legend's Quest" }
  220. QUEST_NAMES[0] = "Black knight's fortress"
  221. SKILL_NAMES = { "Defense", "Strength", "Hits", "Ranged", "Prayer", "Magic", "Cooking", "Woodcutting", "Fletching", "Fishing", "Firemaking", "Crafting", "Smithing", "Mining", "Herblaw", "Agility", "Thieving" }
  222. SKILL_NAMES[0] = "Attack"
  223. PRAYER_NAMES = { "Burst of strength", "Clarity of thought", "Rock skin", "Superhuman strength", "Improved reflexes", "Rapid restore", "Rapid heal", "Protect items", "Steel skin", "Ultimate strength", "Incredible reflexes", "Paralyze monster", "Protect from missiles" }
  224. PRAYER_NAMES[0] = "Thick Skin"
  225. SPELL_NAMES = { "Confuse","Water strike","Enchant lvl-1 amulet","Earth strike","Weaken","Fire strike","Bones to bananas","Wind bolt","Curse","Low level alchemy","Water bolt","Varrock teleport","Enchant lvl-2 amulet","Earth bolt","Lumbridge teleport","Telekinetic grab","Fire bolt","Falador teleport","Crumble undead","Wind blast","Superheat item","Camelot teleport","Water blast","Enchant lvl-3 amulet","Iban blast","Ardougne teleport","Earth blast","High level alchemy","Charge water orb","Enchant lvl-4 amulet","Watchtower teleport","Fire blast","Charge earth orb","Claws of Guthix","Saradomin Strike","Flames of Zamorak","Wind wave","Charge Fire Orb","Water wave","Charge air orb","Vulnerability","Enchant lvl-5","Earth wave","Enfeeble","Fire wave","Stun","Charge" }
  226. SPELL_NAMES[0] = "Wind strike"
  227. ANIMATION_NAMES = {}
  228. ANIMATION_NAMES[0] = "Facing North"
  229. ANIMATION_NAMES[1] = "Facing Northwest"
  230. ANIMATION_NAMES[2] = "Facing West"
  231. ANIMATION_NAMES[3] = "Facing Southwest"
  232. ANIMATION_NAMES[4] = "Facing South"
  233. ANIMATION_NAMES[5] = "Facing Southeast"
  234. ANIMATION_NAMES[6] = "Facing East"
  235. ANIMATION_NAMES[7] = "Facing Northeast"
  236. ANIMATION_NAMES[8] = "In Combat (facing right)"
  237. ANIMATION_NAMES[9] = "In Combat (facing left)"
  238. -- These names were never displayed in game as far as I know, so they're pretty bad.
  239. ANIMATION_SPRITE_NAMES_RAW = { "head1","body1","legs1","fhead1","fbody1","head2","head3","head4","chefshat","apron","apron","boots","fullhelm","fullhelm","fullhelm","fullhelm","fullhelm","fullhelm","fullhelm","fullhelm","chainmail","chainmail","chainmail","chainmail","chainmail","chainmail","chainmail","platemailtop","platemailtop","platemailtop","platemailtop","platemailtop","platemailtop","platemailtop","platemailtop","platemailtop","platemaillegs","platemaillegs","platemaillegs","platemaillegs","platemaillegs","platemaillegs","platemaillegs","platemaillegs","platemaillegs","leatherarmour","leathergloves","sword","sword","sword","sword","sword","sword","sword","fplatemailtop","fplatemailtop","fplatemailtop","fplatemailtop","fplatemailtop","fplatemailtop","fplatemailtop","apron","cape","cape","cape","cape","cape","cape","cape","mediumhelm","mediumhelm","mediumhelm","mediumhelm","mediumhelm","mediumhelm","mediumhelm","wizardsrobe","wizardshat","wizardshat","necklace","necklace","skirt","wizardsrobe","Wizardsrobe","wizardsrobe","Wizardsrobe","skirt","skirt","skirt","skirt","skirt","Skirt","skirt","skirt","skirt","skirt","skirt","squareshield","squareshield","squareshield","squareshield","squareshield","squareshield","squareshield","squareshield","squareshield","crossbow","longbow","battleaxe","battleaxe","battleaxe","battleaxe","battleaxe","battleaxe","battleaxe","mace","mace","mace","mace","mace","mace","mace","staff","rat","demon","spider","spider","camel","cow","sheep","unicorn","bear","chicken","skeleton","skelweap","zombie","zombweap","ghost","bat","goblin","goblin","goblin","gobweap","scorpion","dragon","dragon","dragon","Wolf","Wolf","partyhat","partyhat","partyhat","partyhat","partyhat","partyhat","leathergloves","chicken","fplatemailtop","skirt","Wolf","spider","battleaxe","sword","eyepatch","demon","dragon","spider","Wolf","unicorn","demon","spider","necklace","rat","mediumhelm","chainmail","wizardshat","legs1","gasmask","mediumhelm","spider","spear","halloweenmask","wizardsrobe","skirt","halloweenmask","halloweenmask","skirt","skirt","skirt","skirt","skirt","wizardshat","wizardshat","wizardshat","wizardshat","wizardshat","wizardsrobe","wizardsrobe","wizardsrobe","wizardsrobe","wizardsrobe","Wizardsrobe","skirt","boots","boots","boots","boots","boots","santahat","ibanstaff","souless","boots","legs1","Wizardsrobe","skirt","cape","Wolf","bunnyears","saradominstaff","spear","skirt","wizardsrobe","wolf","chicken","squareshield","cape","boots","wizardsrobe","Scythe" }
  240. ANIMATION_SPRITE_NAMES_RAW[0] = "None"
  241. -- These are names that I came up with based on ANIMATION_SPRITE_NAMES_RAW & by viewing the sprites in-client.
  242. ANIMATION_SPRITE_NAMES = { "Short Hair","Male Body","Coloured Pants","Long Hair","Female Body","Short Hair 2","Long Bearded Head","Bald Head","Chef's Hat","White Apron","Brown Apron","Leather Boots","Large Bronze Helmet","Large Iron Helmet","Large Steel Helmet","Large Mithril Helmet","Large Adamantite Helmet","Large Rune Helmet","Large Black Helmet","Large White Helmet","Bronze Chain Mail Body","Iron Chain Mail Body","Steel Chain Mail Body","Mithril Chain Mail Body","Adamantite Chain Mail Body","Rune Chain Mail Body","Black Chain Mail Body","Bronze Plate Mail Body","Iron Plate Mail Body","Steel Plate Mail Body","Mithril Plate Mail Body","Adamantite Plate Mail Body","Black Plate Mail Body","Rune Plate Mail Body","White Plate Mail Body","Unused Plate Mail Body (Colour between Mithril & Rune)","Bronze Plate Mail Legs","Iron Plate Mail Legs","Steel Plate Mail Legs","Mithril Plate Mail Legs","Adamantite Plate Mail Legs","Rune Plate Mail Legs","Black Plate Mail Legs","White Plate Mail Legs","Unused Plate Mail Legs (Colour between Mithril & Rune)","Leather Armour","Leather Gloves","Bronze Sword","Iron Sword","Steel Sword","Mithril Sword","Adamantite Sword","Rune Sword","Black Sword","Female Bronze Plate Mail top","Female Iron Plate Mail top","Female Steel Plate Mail top","Female Mithril Plate Mail top","Female Adamantite Plate Mail top","Female Rune Plate Mail top","Female Black Plate Mail top","White Apron","Red Cape","Black Cape","Blue Cape","Green Cape","Yellow Cape","Orange Cape","Purple Cape","Medium Bronze Helmet","Medium Iron Helmet","Medium Steel Helmet","Medium Mithril Helmet","Medium Adamantite Helmet","Medium Rune Helmet","Medium Black Helmet","Blue Wizards Robe","Blue Wizardshat","Black Wizardshat","Silver Necklace","Gold Necklace (could be any of them)","Blue Skirt","Black Wizards Robe","Saradomin Monk Robe","Zamorak Monk Robe","Druid Robe","Druid Skirt","Saradomin Monk Skirt","Black Wizards Skirt","Pink Skirt","Zamorak Monk Skirt","Bronze Plated Skirt","Iron Plated Skirt","Steel Plated Skirt","Mithril Plated Skirt","Adamantite Plated Skirt","Rune Plated Skirt","Bronze Square Shield","Iron Square Shield","Steel Square Shield","Mithril Square Shield","Adamantite Square Shield","Rune Square Shield","Black Square Shield","Anti Dragon Breath Shield","Wooden Shield","Crossbow ","Longbow","Bronze Battleaxe","Iron Battleaxe","Steel Battleaxe","Mithril Battleaxe","Adamantite Battleaxe","Rune Battleaxe","Black Battleaxe","Bronze Mace","Iron Mace","Steel Mace","Mithril Mace","Adamantite Mace","Rune Mace","Black Mace","Staff","Rat","Red Demon","Brown Spider","Red Spider","Camel","Cow","Sheep","Unicorn","Bear","Chicken","Skeleton","Skeleton's Scimitar and Shield","Zombie","Zombie's Axe","Ghost","Bat","Goblin","Goblin with Red Armour","Goblin with Green Armour","Goblin's Spear","Scorpion","Elvarg","Red Dragon","Blue Dragon","White Wolf","Grey Wolf","Red Party Hat","Yellow Party Hat","Blue Party Hat","Green Party Hat","Pink Party Hat","White Party Hat","Ice Gloves","Firebird","Unused Plate Mail top (Colour between Mithril & Rune)","Priest Gown","Karamja Wolf","Ice Spider","Dragon Battleaxe","Dragon Sword","Right Eyepatch","Black Demon","Black Dragon","Poison Spider","Hellhound","Black Unicorn","Chronozon","Shadow Spider","Pendant of Lucien","Dungeon Rat","Khazard Helmet","Khazard Chainmail","Zamorak Wizardshat (unused)","Mourner Legs","Gas Mask","Dragon Medium Helmet","Jungle Spider","Spear","Green Halloween Mask","Priest Robe","Priest Gown","Red Halloween Mask","Blue Halloween Mask","Pastel Pink Gnome Skirt","Pastel Green Gnome Skirt","Pastel Blue Gnome Skirt","Pastel Yellow Gnome Skirt","Pastel Cyan Gnome Skirt","Pastel Pink Gnomeshat","Pastel Green Gnomeshat","Pastel Blue Gnomeshat","Pastel Yellow Gnomeshat","Pastel Cyan Gnomeshat","Pastel Pink Gnome Top","Pastel Green Gnome Top","Pastel Blue Gnome Top","Pastel Yellow Gnome Top","Pastel Cyan Gnome Top","Green Robe (unused, perhaps planned for Brimstail)","Green Skirt (unused, perhaps planned for Brimstail)","Pastel Pink Gnome Boots","Pastel Green Gnome Boots","Pastel Blue Gnome Boots","Pastel Yellow Gnome Boots","Pastel Cyan Gnome Boots","Santa's Hat","Staff of Iban","Souless","Desert Boots","White Pants","Slaves Robe Top","Slaves Robe Bottom","Cape of Legends","Desert Wolf","Bunny Ears","Staff of Saradomin","Gujou's Rune Spear","Gujuo's Skirt","Gujuo's Robe top","Karamja Wolf","Oomlie Bird","Dragon Square Shield","Cape of Legends","Shadow Warrior Boots","Shadow Warrior Robe","Scythe" }
  243. ANIMATION_SPRITE_NAMES[0] = "None"
  244. -- this.anIntArray1465
  245. HAIR_COLOURS = { 0xffa040, 0x805030, 0x604020, 0x303030, 0xff6020, 0xff4000, 0xffffff, 0x00ff00, 0x00ffff }
  246. HAIR_COLOURS_STRING = { "#FFA040", "#805030", "#604020", "#303030", "#FF6020", "#FF4000", "#FFFFFF", "#00FF00", "#00FFFF" }
  247. HAIR_COLOUR_NAMES = { "Sunshade Orange", "Korma Brown", "Dark Brown", "Night Rider Grey", "Outrageous Orange", "Orange Red", "White", "Lime Green", "Cyan"}
  248. HAIR_COLOURS[0] = 0xffc030
  249. HAIR_COLOURS_STRING[0] = "#FFC030"
  250. HAIR_COLOUR_NAMES[0] = "Saffron Yellow"
  251. -- this.anIntArray1548
  252. SKIN_COLOURS = { 0xccb366, 0xb38c40, 0x997326, 0x906020 }
  253. SKIN_COLOURS_STRING = { "#CCB366", "#B38C40", "#997326", "#906020" }
  254. SKIN_COLOUR_NAMES = { "Tacha (Tan)", "Marigold", "Buttered Rum Brown", "Brown" }
  255. SKIN_COLOURS[0] = 0xecded0
  256. SKIN_COLOURS_STRING[0] = "#ECDED0"
  257. SKIN_COLOUR_NAMES[0] = "Spring Wood (Pale White)"
  258. -- this.anIntArray1592
  259. CLOTHING_COLOURS = { 0xff8000, 0xffe000, 0xa0e000, 0x00e000, 0x008000, 0x00a080, 0x00b0ff, 0x0080ff, 0x0030f0, 0xe000e0, 0x303030, 0x604000, 0x805000, 0xffffff }
  260. CLOTHING_COLOURS_STRING = { "#FF8000", "#FFE000", "#A0E000", "#00E000", "#008000", "#00A080", "#00B0FF", "#0080FF", "#0030F0", "#E000E0", "#303030", "#604000", "#805000", "#FFFFFF" }
  261. CLOTHING_COLOUR_NAMES = { "Dark Orange", "Yellow", "Inch Worm Green", "Lime Green", "Green", "Free Speech Aquamarine", "Deep Sky Blue", "Dodger Blue", "Blue", "Deep Magenta", "Night Rider Grey", "Dark Brown", "Light Brown", "White" }
  262. CLOTHING_COLOURS[0] = 0xff0000
  263. CLOTHING_COLOURS_STRING[0] = "#FF0000"
  264. CLOTHING_COLOUR_NAMES[0] = "Red"
  265. BUBBLE_TYPE_NAMES = { "Telegrab/Iban's Magic" } -- Both Telegrab & Iban's magic are type 1.
  266. BUBBLE_TYPE_NAMES[0] = "Teleportation"
  267. SPRITE_TYPES = {} -- there is no sprite 0, or sprite greater than 6
  268. SPRITE_TYPES[1] = "Magic Projectile"
  269. SPRITE_TYPES[2] = "Ranged Projectile"
  270. SPRITE_TYPES[3] = "Gnomeball"
  271. SPRITE_TYPES[4] = "Iban Blast" -- never on opcode 234 type 3, only on type 4
  272. SPRITE_TYPES[5] = "Cannonball"
  273. SPRITE_TYPES[6] = "God Spell" -- TODO: observed only claws of guthix / saradomin strike
  274. BOUNDARY_ALIGNMENTS = { "North-South", "Northwest-Southeast", "Southwest-Northeast" }
  275. BOUNDARY_ALIGNMENTS[0] = "East-West"
  276. OPTION_NAMES = { "Player Killer (Unused in RSC235)", "Number of Mouse Buttons", "Sound Enabled" }
  277. OPTION_NAMES[0] = "Camera Mode Auto"
  278. REPORT_REASONS = { "Buying or selling an account", "Encouraging rule-breaking", "Staff impersonation", "Macroing or use of bots", "Scamming", "Exploiting a bug", "Seriously offensive language", "Solicitation", "Disruptive behaviour", "Offensive account name", "Real-life threats", "Asking for or providing contact information", "Breaking real-world laws", "Advertising websites" }
  279. -- there is no reason 0
  280. --============================================================================--
  281. -- this is a little excessive, but we're going to track everything about a player the client does
  282. function rsc_newCharacter()
  283. rsc_newChar = {}
  284. rsc_newChar["damageTaken"] = 0
  285. rsc_newChar["accountName"] = nil
  286. rsc_newChar["healthMax"] = 0
  287. rsc_newChar["stepCount"] = nil
  288. rsc_newChar["colourTop"] = nil
  289. rsc_newChar["messageTimeout"] = 0
  290. rsc_newChar["projectileRange"] = 0
  291. rsc_newChar["movingStep"] = 0
  292. rsc_newChar["waypointCurrent"] = nil
  293. rsc_newChar["animationCurrent"] = nil
  294. rsc_newChar["skullVisible"] = 0
  295. rsc_newChar["incomingProjectileSprite"] = 0
  296. rsc_newChar["bubbleTimeout"] = 0
  297. rsc_newChar["colourBottom"] = nil
  298. rsc_newChar["displayName"] = nil
  299. rsc_newChar["attackingPlayerServerIndex"] = 0
  300. rsc_newChar["serverIndex"] = nil
  301. rsc_newChar["message"] = nil
  302. rsc_newChar["combatTimeout"] = 0
  303. rsc_newChar["currentX"] = nil
  304. rsc_newChar["colourHair"] = nil
  305. rsc_newChar["level"] = -1
  306. rsc_newChar["npcId"] = nil
  307. rsc_newChar["attackingNpcServerIndex"] = 0
  308. rsc_newChar["colourSkin"] = nil
  309. rsc_newChar["animationNext"] = nil
  310. rsc_newChar["currentY"] = nil
  311. rsc_newChar["bubbleItem"] = nil
  312. rsc_newChar["healthCurrent"] = 0
  313. rsc_newChar["waypointsX"] = {}
  314. rsc_newChar["waypointsY"] = {}
  315. rsc_newChar["equippedItem"] = {}
  316. return rsc_newChar
  317. end
  318. --============================================================================--
  319. -- creates new objects
  320. function dereferencePlayerArrays()
  321. newThisPlayers = {}
  322. newThisPlayerServer = {}
  323. newThisPlayerCount = 0
  324. for key, value in next, thisPlayers do
  325. newThisPlayers[key] = value
  326. end
  327. for key, value in next, thisPlayerServer do
  328. newThisPlayerServer[key] = value
  329. end
  330. return { newThisPlayers, newThisPlayerCount + thisPlayerCount, newThisPlayerServer }
  331. end
  332. function dereferenceList(list)
  333. newCache = {}
  334. for key, value in next, list do
  335. newCache[key] = value
  336. end
  337. return newCache
  338. end
  339. --============================================================================--
  340. -- necessary to keep these values over multiple opcodes for context
  341. thisPlayerCount = 0
  342. thisPlayers = {}
  343. thisKnownPlayerCount = 0
  344. thisKnownPlayers = {}
  345. thisPlayerServer = {}
  346. thisNpcs = {}
  347. thisNpcsServer = {}
  348. thisNpcsCache = {}
  349. thisNpcsCacheCount = 0
  350. thisNpcsCount = 0
  351. thisLocalPlayer = rsc_newCharacter()
  352. for i = 0, 500 do
  353. thisPlayers[i] = rsc_newCharacter()
  354. thisKnownPlayers[i] = rsc_newCharacter()
  355. thisPlayerServer[i] = rsc_newCharacter()
  356. thisNpcs[i] = rsc_newCharacter()
  357. thisNpcsServer[i] = rsc_newCharacter()
  358. thisNpcsCache[i] = rsc_newCharacter()
  359. end
  360. for i=500,4000 do
  361. thisPlayerServer[i] = rsc_newCharacter()
  362. thisNpcsServer[i] = rsc_newCharacter()
  363. end
  364. for i=4000,5000 do
  365. thisNpcsServer[i] = rsc_newCharacter()
  366. end
  367. thisRegionX = nil
  368. thisRegionY = nil
  369. thisLocalRegionX = nil
  370. thisLocalRegionY = nil
  371. thisMagicLoc = 128
  372. thisLocalPlayerServerIndex = -1
  373. thisTradeConfirmItems = nil
  374. --============================================================================--
  375. -- other globals
  376. workingBuffer = nil
  377. thisOptionCache = {} -- not an authentic global, just using it to show what option was selected
  378. -- Wireshark first goes through the entire file frame by frame sequentially, which is good,
  379. -- because it lets us use data from previous opcodes to reference necessary variables in
  380. -- the opcode we are currently trying to intepret, the same way that RSC does.
  381. --
  382. -- HOWEVER, Wireshark will then re-dissect frames according to how the user interacts with
  383. -- the graphical interface, i.e. in an unpredictable order, from the middle, "randomly".
  384. -- This screws with the "game state" and displays incorrect data.
  385. --
  386. -- In tshark, it will only go through the file one time, and the user doesn't get a chance
  387. -- to screw up the gamestate by clicking on random frames to be re-examined.
  388. --
  389. -- In order to mitigate the problem in Wireshark, the first time the frame is dissected,
  390. -- when the game state is still intact and sequentially interpretted,
  391. -- we fill this array below to cache any values needed in order to correctly
  392. -- display the dissected frame once it is dissected subsequent times
  393. --
  394. -- Without this, all opcodes still display data properly, except for the following:
  395. -- 116c, 36, 48, 79, 91, 92, 99, 123, 176, 191, 211, 234
  396. thisGameStateValuesAtThisTime = {}
  397. thisPlayerInventory = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
  398. thisPlayerInventory[0] = -1
  399. -- pixels for drawing sleepwords in unicode blocks (unfortunately can't draw more than 158 pixels wide and we would need 255px)
  400. blockChars = { "▗","▖","▄","▝","▐","▞","▟","▘","▚","▌","▙","▀","▜","▛","█" }
  401. blockChars[0] = " "
  402. --============================================================================--
  403. --------------------------------------------------------------------------------
  404. -- shared client/server variables
  405. --------------------------------------------------------------------------------
  406. clientPacket = ProtoField.uint8("rsc235.packetSource", "Server/Client")
  407. clientOpcode = ProtoField.uint32("rsc235.opcode", "Opcode")
  408. clientPacketLength = ProtoField.uint16("rsc235.packetLength", "Packet Length")
  409. --------------------------------------------------------------------------------
  410. --------------------------------------------------------------------------------
  411. -- client opcode related variables
  412. --------------------------------------------------------------------------------
  413. clientConnectReconnecting = ProtoField.uint8("rsc235.0c.reconnecting", "Reconnecting")
  414. clientConnectVersion = ProtoField.uint8("rsc235.0c.clientVersion", "Client Version")
  415. clientConnectEncrypted = ProtoField.bytes("rsc235.0c.encrypted", "Encrypted Block")
  416. clientCastOnInventoryInventoryIndex = ProtoField.int16("rsc235.4c.slot", "Inventory Slot")
  417. clientCastOnInventorySpellID = ProtoField.int16("rsc235.4c.spellID", "Spell ID")
  418. clientSendDuelSettingsRetreat = ProtoField.uint8("rsc235.8c.retreatEnabled", "Retreat Enabled")
  419. clientSendDuelSettingsMagic = ProtoField.uint8("rsc235.8c.magicEnabled", "Magic Enabled")
  420. clientSendDuelSettingsPrayer = ProtoField.uint8("rsc235.8c.prayerEnabled", "Prayer Enabled")
  421. clientSendDuelSettingsWeapons = ProtoField.uint8("rsc235.8c.weaponsEnabled", "Weapons Enabled")
  422. clientInteractWithBoundaryXCoord = ProtoField.uint16("rsc235.14c.xCoord", "X Coordinate")
  423. clientInteractWithBoundaryYCoord = ProtoField.uint16("rsc235.14c.yCoord", "Y Coordinate")
  424. clientInteractWithBoundaryAlignment = ProtoField.uint8("rsc235.14c.alignment", "Alignment")
  425. clientWalkAndPerformActionX = ProtoField.int16("rsc235.16c.xCoord", "X Coordinate")
  426. clientWalkAndPerformActionY = ProtoField.int16("rsc235.16c.yCoord", "Y Coordinate")
  427. clientWalkAndPerformActionPathX = ProtoField.int8("rsc235.16c.xCoordPath", "X Coordinate Path")
  428. clientWalkAndPerformActionPathY = ProtoField.int8("rsc235.16c.yCoordPath", "Y Coordinate Path")
  429. clientBankWithdrawItemID = ProtoField.uint16("rsc235.22c.itemID", "Item ID")
  430. clientBankWithdrawAmount = ProtoField.uint32("rsc235.22c.withdrawAmount", "Amount to Withdraw")
  431. clientBankWithdrawMagicNumber = ProtoField.uint32("rsc235.22c.magicNumber", "Magic Number which could not change and whose purpose is unknown", base.HEX)
  432. clientBankDepositItemID = ProtoField.uint16("rsc235.23c.itemID", "Item ID")
  433. clientBankDepositAmount = ProtoField.uint32("rsc235.23c.withdrawAmount", "Amount to Deposit")
  434. clientBankDepositMagicNumber = ProtoField.uint32("rsc235.23c.magicNumber", "Magic Number which could not change and whose purpose is unknown", base.HEX)
  435. clientCombatStyle = ProtoField.uint8("rsc235.29c.combatStyle", "Style")
  436. clientSendStakedItemsCount = ProtoField.uint8("rsc235.33c.itemCount", "Number of Items to be Staked by Player")
  437. clientSendStakedItemsItemID = ProtoField.uint16("rsc235.33c.itemId", "Item ID of Item to be Staked by Player")
  438. clientSendStakedItemsItemAmount = ProtoField.uint32("rsc235.33c.itemIdStackamount", "Amount of Item to be Staked by Player")
  439. clientSendCommandStringCommand = ProtoField.string("rsc235.38c.command", "\"::[command]\"")
  440. clientGuessSleepwordDelay = ProtoField.uint8("rsc235.45c.delay", "Delay")
  441. clientGuessSleepwordGuess = ProtoField.string("rsc235.45c.wordGuess", "Guess at Word")
  442. clientOfferItemItemCount = ProtoField.uint8("rsc235.46c.itemCount", "Number of items offered")
  443. clientOfferItemItemID = ProtoField.uint16("rsc235.46c.itemID", "Item ID")
  444. clientOfferItemItemStack = ProtoField.uint32("rsc235.46c.itemStackCount", "Items in this stack")
  445. clientCastNPCSpellID = ProtoField.uint16("rsc235.50c.spellID", "Spell ID")
  446. clientCastNPCNPCID = ProtoField.uint16("rsc235.50c.npcID", "NPC Server Index")
  447. clientUseOnGroundItemXCoord = ProtoField.uint16("rsc235.53c.xCoord", "X Coordinate")
  448. clientUseOnGroundItemYCoord = ProtoField.uint16("rsc235.53c.yCoord", "Y Coordinate")
  449. clientUseOnGroundItemInventorySlot = ProtoField.uint16("rsc235.53c.slot", "Inventory Slot")
  450. clientUseOnGroundItemGroundItemID = ProtoField.uint16("rsc235.53c.groundItemID", "Ground Item's ID")
  451. clientAdminTeleportXCoord = ProtoField.uint16("rsc235.59c.xCoord", "X Coordinate")
  452. clientAdminTeleportYCoord = ProtoField.uint16("rsc235.59c.yCoord", "Y Coordinate")
  453. clientPrayerOnPrayer = ProtoField.int8("rsc235.60c.prayer", "Prayer")
  454. clientSendPrivacySettingsChat = ProtoField.uint8("rsc235.64c.chat", "Block Chat")
  455. clientSendPrivacySettingsPrivate = ProtoField.uint8("rsc235.64c.private", "Block Private")
  456. clientSendPrivacySettingsTrade = ProtoField.uint8("rsc235.64c.trade", "Block Trade")
  457. clientSendPrivacySettingsDuel = ProtoField.uint8("rsc235.64c.duel", "Block Duel")
  458. clientInteractWithScenery2XCoord = ProtoField.uint16("rsc235.79c.xCoord", "X Coordinate")
  459. clientInteractWithScenery2YCoord = ProtoField.uint16("rsc235.79c.yCoord", "Y Coordinate")
  460. clientActivateInventoryItemSlot = ProtoField.uint16("rsc235.90c.slot", "Inventory Slot Index of item to be activated")
  461. -- TODO: should add field for what the item activated is
  462. clientCombineInventorySlot1 = ProtoField.uint16("rsc235.91c.slot1", "Inventory Slot Index of first item to be combined")
  463. clientCombineInventorySlot2 = ProtoField.uint16("rsc235.91c.slot2", "Inventory Slot Index of second item to be combined")
  464. -- TODO: should add fields for what the items actually are, to be used in searches (if the wireshark dissector is a search tool...)
  465. clientCastOnSceneryXCoord = ProtoField.uint16("rsc235.99c.xCoord", "X Coordinate")
  466. clientCastOnSceneryYCoord = ProtoField.uint16("rsc235.99c.yCoord", "Y Coordinate")
  467. clientCastOnScenerySpellID = ProtoField.uint16("rsc235.99c.spellID", "Spell ID")
  468. clientSendDuelRequest = ProtoField.int16("rsc235.103c.PID", "PID of Player to send Duel Request to")
  469. clientSetting = ProtoField.uint8("rsc235.111c.setting", "Option")
  470. clientSettingValue = ProtoField.uint8("rsc235.111c.value", "Enabled?")
  471. clientUseOnPlayerPID = ProtoField.uint16("rsc235.113c.pid", "PID")
  472. clientUseOnPlayerSlot = ProtoField.uint16("rsc235.113c.slot", "Inventory Slot Index of item to be used on player")
  473. clientUseOnSceneryX = ProtoField.int16("rsc235.115c.xCoord", "X Coordinate")
  474. clientUseOnSceneryY = ProtoField.int16("rsc235.115c.yCoord", "Y Coordinate")
  475. clientUseOnScenerySlot = ProtoField.int16("rsc235.115c.slot", "Inventory Slot Index of item to be used on scenery")
  476. clientOption = ProtoField.uint8("rsc235.116c.clientOption", "Option")
  477. clientInteractWithBoundary2XCoord = ProtoField.uint16("rsc235.127c.xCoord", "X Coordinate")
  478. clientInteractWithBoundary2YCoord = ProtoField.uint16("rsc235.127c.yCoord", "Y Coordinate")
  479. clientInteractWithBoundary2Alignment = ProtoField.uint8("rsc235.127c.alignment", "Alignment")
  480. clientAddIgnoreName = ProtoField.string("rsc235.132c.name", "Name of Person to Ignore")
  481. clientUseOnNPCNPCID = ProtoField.uint16("rsc235.135c.npcID", "NPC Server Index")
  482. clientUseOnNPCSlot = ProtoField.int16("rsc235.135c.slot", "Inventory Slot Index of item to be used on NPC")
  483. clientInteractWithSceneryX = ProtoField.int16("rsc235.136c.xCoord", "X Coordinate")
  484. clientInteractWithSceneryY = ProtoField.int16("rsc235.136c.yCoord", "Y Coordinate")
  485. clientCastOnSelfSpell = ProtoField.int16("rsc235.137c.spell", "Spell to Cast on Self")
  486. clientAgreeToTradePID = ProtoField.int16("rsc235.142c.PID", "PID of Player to Trade")
  487. clientTalkToNPCID = ProtoField.uint16("rsc235.153c.npcID", "NPC Server Index")
  488. clientCastOnGroundXCoord = ProtoField.int16("rsc235.158c.xCoord", "X Coordinate")
  489. clientCastOnGroundYCoord = ProtoField.int16("rsc235.158c.yCoord", "Y Coordinate")
  490. clientCastOnGroundSpell = ProtoField.int16("rsc235.158c.spell", "Spell to Cast")
  491. clientUseWithBoundaryXCoord = ProtoField.int16("rsc235.161c.xCoord", "X Coordinate")
  492. clientUseWithBoundaryYCoord = ProtoField.int16("rsc235.161c.yCoord", "Y Coordinate")
  493. clientUseWithBoundaryAlignment = ProtoField.uint8("rsc235.161c.alignment", "Alignment")
  494. clientUseWithBoundarySlot = ProtoField.int16("rsc235.161c.slot", "Inventory Slot Index of item to be used on boundary")
  495. clientFollowPlayerPID = ProtoField.int16("rsc235.165c.PID", "PID of Player to Follow")
  496. clientRemoveFriendName = ProtoField.string("rsc235.167c.name", "Name of Ex-Friend")
  497. clientEquipItemSlot = ProtoField.int16("rsc235.169c.slot", "Inventory Slot Index of item to be equipped")
  498. clientUnequipItemItem = ProtoField.int16("rsc235.170c.slot", "Inventory Slot Index of item to be unequipped")
  499. clientAttackPlayerTargetPID = ProtoField.int16("rsc235.171c.targetPID", "Target's PID")
  500. clientCastOnBoundaryXCoord = ProtoField.int16("rsc235.180c.xCoord", "X Coordinate")
  501. clientCastOnBoundaryYCoord = ProtoField.int16("rsc235.180c.yCoord", "Y Coordinate")
  502. clientCastOnBoundaryAlignment = ProtoField.uint8("rsc235.180c.alignment", "Alignment")
  503. clientCastOnBoundarySpell = ProtoField.int16("rsc235.180c.spell", "Spell to Cast")
  504. clientWalkX = ProtoField.int16("rsc235.187c.xCoord", "X Coordinate")
  505. clientWalkY = ProtoField.int16("rsc235.187c.yCoord", "Y Coordinate")
  506. clientWalkPathX = ProtoField.int8("rsc235.187c.xCoordPath", "X Coordinate Path")
  507. clientWalkPathY = ProtoField.int8("rsc235.187c.yCoordPath", "Y Coordinate Path")
  508. clientAttackNPCID = ProtoField.uint16("rsc235.190c.npcID", "NPC Server Index")
  509. clientAddFriendName = ProtoField.string("rsc235.195c.name", "Name of New Friend")
  510. clientInteractNPCID = ProtoField.uint16("rsc235.202c.npcID", "NPC Server Index")
  511. clientSendReportName = ProtoField.string("rsc235.206c.name", "Name of Troublemaker")
  512. clientSendReportReason = ProtoField.int8("rsc235.206c.reason", "Reason")
  513. clientSendReportMute = ProtoField.int8("rsc235.206c.mute", "Add to Ignore List?")
  514. clientSendChatMessageLength = ProtoField.int16("rsc235.216c.messageLength", "Desired Message Length")
  515. clientSendChatMessageMessage = ProtoField.string("rsc235.216c.message", "Desired Chat Message (scrambled)")
  516. clientSendPrivateMessageRecipient = ProtoField.string("rsc235.218c.recipient", "Desired Recipient")
  517. clientSendPrivateMessageLength = ProtoField.int16("rsc235.218c.messageLength", "Desired Message Length")
  518. clientSendPrivateMessageMessage = ProtoField.string("rsc235.218c.message", "Desired Message (scrambled)")
  519. clientSellToShopItemId = ProtoField.int16("rsc235.221c.itemID", "Item ID")
  520. clientSellToShopShopAmount = ProtoField.int16("rsc235.221c.shopAmount", "Shop Amount")
  521. clientSellToShopSellAmount = ProtoField.int16("rsc235.221c.sellAmount", "Sell Amount")
  522. clientCastPVPTargetPID = ProtoField.int16("rsc235.229c.targetPID", "Target's PID")
  523. clientCastPVPSpellID = ProtoField.int16("rsc235.229c.spellID", "Spell ID")
  524. clientChangeAppearanceHeadRestrictions = ProtoField.int8("rsc235.235c.headRestrictions", "Head Restrictions")
  525. clientChangeAppearanceHeadType = ProtoField.int8("rsc235.235c.headType", "Head Type")
  526. clientChangeAppearanceBodyType = ProtoField.int8("rsc235.235c.bodyType", "Body Type")
  527. clientChangeAppearanceAlways2 = ProtoField.int8("rsc235.235c.always2", "Always 2, even in very old versions of client") -- I checked old versions, and this value is always 2 even in client versions 40 & 127 (Those versions have extra fields for PKer & Class)
  528. clientChangeAppearanceHairColour = ProtoField.int8("rsc235.235c.hairColour", "Hair Colour")
  529. clientChangeAppearanceTopColour = ProtoField.int8("rsc235.235c.topColour", "Top Colour")
  530. clientChangeAppearenceBottomColour = ProtoField.int8("rsc235.235c.bottomColour", "Bottom Colour")
  531. clientChangeAppearenceSkinColour = ProtoField.int8("rsc235.235c.skinColour", "Skin Colour")
  532. clientBuyFromShopItemId = ProtoField.int16("rsc235.236c.itemID", "Item ID")
  533. clientBuyFromShopShopAmount = ProtoField.int16("rsc235.236c.shopAmount", "Shop Amount")
  534. clientBuyFromShopSellAmount = ProtoField.int16("rsc235.236c.sellAmount", "Sell Amount")
  535. clientExignoredName = ProtoField.string("rsc235.241c.name", "Name of the Ex-Ignored")
  536. clientDropItemSlot = ProtoField.int16("rsc235.246c.slot", "Inventory Slot Index of item to be dropped")
  537. clientTakeGroundItemXCoord = ProtoField.int16("rsc235.247c.xCoord", "X Coordinate")
  538. clientTakeGroundItemYCoord = ProtoField.int16("rsc235.247c.yCoord", "Y Coordinate")
  539. clientTakeGroundItemItemID = ProtoField.int16("rsc235.247c.itemID", "Item ID")
  540. clientCastOnGroundItemXCoord = ProtoField.int16("rsc235.249c.xCoord", "X Coordinate")
  541. clientCastOnGroundItemYCoord = ProtoField.int16("rsc235.249c.yCoord", "Y Coordinate")
  542. clientCastOnGroundItemItemID = ProtoField.int16("rsc235.249c.itemID", "Item ID")
  543. clientCastOnGroundItemSpellID = ProtoField.int16("rsc235.249c.spell", "Spell to Cast")
  544. clientPrayerOffPrayer = ProtoField.int8("rsc235.254c.prayer", "Prayer")
  545. --------------------------------------------------------------------------------
  546. --------------------------------------------------------------------------------
  547. -- server opcode related variables
  548. --------------------------------------------------------------------------------
  549. serverLoginResponse = ProtoField.int8("rsc235.serverLoginResponse", "Login Response")
  550. serverMetadataLoginResponse = ProtoField.int32("rsc235.12345.loginResponse", "Login Response")
  551. serverMetadataClientVersion = ProtoField.int32("rsc235.12345.clientVersion", "Client Version")
  552. serverMetadataAuthenticClient = ProtoField.int32("rsc235.12345.authenticClient", "Authentic Client")
  553. serverMetadataStartTime = ProtoField.int64("rsc235.12345.startTime", "Start Time")
  554. serverMetadataWorldNumber = ProtoField.int32("rsc235.12345.worldNumber", "World Number")
  555. serverMetadataServerName = ProtoField.string("rsc235.12345.serverName", "Server Name")
  556. serverMetadataUsername = ProtoField.string("rsc235.12345.userName", "Username")
  557. serverMetadataPlayerIP = ProtoField.string("rsc235.12345.playerIP", "Player's IP Address")
  558. serverMetadataReservedBytes = ProtoField.bytes("rsc235.12345.reserved", "Reserved Bytes (If any value other than zero, update your rscminus.lua!)")
  559. QUEST_DISSECTOR_ABRV = {"rsc235.5.cooksAssistant", "rsc235.5.demonSlayer", "rsc235.5.doricsQuest", "rsc235.5.theRestlessGhost", "rsc235.5.goblinDiplomacy", "rsc235.5.ernestTheChicken", "rsc235.5.impCatcher", "rsc235.5.piratesTreasure", "rsc235.5.princeAliRescue", "rsc235.5.romeoJuliet", "rsc235.5.sheepShearer", "rsc235.5.shieldOfArrav", "rsc235.5.theKnightsSword", "rsc235.5.vampireSlayer", "rsc235.5.witchsPotion", "rsc235.5.dragonSlayer", "rsc235.5.witchsHouse", "rsc235.5.lostCity", "rsc235.5.herosQuest", "rsc235.5.druidicRitual", "rsc235.5.merlinsCrystal", "rsc235.5.scorpionCatcher", "rsc235.5.familyCrest", "rsc235.5.tribalTotem", "rsc235.5.fishingContest", "rsc235.5.monksFriend", "rsc235.5.templeOfIkov", "rsc235.5.clockTower", "rsc235.5.theHolyGrail", "rsc235.5.fightArena", "rsc235.5.treeGnomeVillage", "rsc235.5.theHazeelCult", "rsc235.5.sheepHerder", "rsc235.5.plagueCity", "rsc235.5.seaSlug", "rsc235.5.waterfallQuest", "rsc235.5.biohazard", "rsc235.5.junglePotion", "rsc235.5.grandTree", "rsc235.5.shiloVillage", "rsc235.5.undergroundPass", "rsc235.5.observatoryQuest", "rsc235.5.touristTrap", "rsc235.5.watchtower", "rsc235.5.dwarfCannon", "rsc235.5.murderMystery", "rsc235.5.digsite", "rsc235.5.gertrudesCat", "rsc235.5.legendsQuest" }
  560. QUEST_DISSECTOR_ABRV[0] = "rsc235.5.blackKnightsFortress"
  561. serverQuests = {}
  562. for i = 0, 49 do
  563. serverQuests[i] = ProtoField.uint8(QUEST_DISSECTOR_ABRV[i], QUEST_NAMES[i])
  564. end
  565. serverUpdateStakedItemsOpponentNumberOfItemsStaked = ProtoField.uint8("rsc235.6.numberOfItemsStaked", "Number of Items Staked")
  566. serverUpdateStakedItemsOpponentItemId = ProtoField.uint16("rsc235.6.itemID", "Item ID")
  567. serverUpdateStakedItemsOpponentItemStack = ProtoField.int32("rsc235.6.itemStackAmount", "Amount of this Item Staked")
  568. serverUpdateTradeAcceptance = ProtoField.uint8("rsc235.15.tradeAccepted", "Trade Accepted (Local Player Accepts)")
  569. serverConfirmTradeRecipientName = ProtoField.string("rsc235.20.accountName", "Confirm Trade Partner's Name")
  570. serverConfirmTradeRecipientItemCount = ProtoField.uint8("rsc235.20.toRecipientItemCount", "Number of Items Going to Recipient")
  571. serverConfirmTradeRecipientItemID = ProtoField.uint16("rsc235.20.toRecipientItemID", "Item ID")
  572. serverConfirmTradeRecipientItemStack = ProtoField.int32("rsc235.20.toRecipientItemStackCount", "Items in this stack")
  573. serverConfirmTradeItemCount = ProtoField.uint8("rsc235.20.itemCount", "Number of Items Received in Trade")
  574. serverConfirmTradeItemID = ProtoField.uint16("rsc235.20.itemID", "Item ID")
  575. serverConfirmTradeItemStack = ProtoField.int32("rsc235.20.itemStackCount", "Items in this stack")
  576. serverFloorSetLocalPlayerServerIndex = ProtoField.uint16("rsc235.25.localPlayerServerIndex", "Local Player Server Index (PID)")
  577. serverFloorSetPlaneWidth = ProtoField.int16("rsc235.25.planeWidth", "Plane Width")
  578. serverFloorSetPlaneHeight = ProtoField.int16("rsc235.25.planeHeight", "Plane Height")
  579. serverFloorSetPlaneFloor = ProtoField.int16("rsc235.25.floor", "Current Floor")
  580. serverFloorSetPlaneDistanceBetweenFloors = ProtoField.int16("rsc235.25.planeDistanceBetweenFloors", "Distance Between Floors")
  581. serverSyncDuelSettingsRetreat = ProtoField.uint8("rsc235.30.retreatEnabled", "Retreat Enabled")
  582. serverSyncDuelSettingsMagic = ProtoField.uint8("rsc235.30.magicEnabled", "Magic Enabled")
  583. serverSyncDuelSettingsPrayer = ProtoField.uint8("rsc235.30.prayerEnabled", "Prayer Enabled")
  584. serverSyncDuelSettingsWeapons = ProtoField.uint8("rsc235.30.weaponsEnabled", "Weapons Enabled")
  585. serverUpdateXPSkill = ProtoField.uint8("rsc235.33.skill", "Skill")
  586. serverUpdateXPXP = ProtoField.double("rsc235.33.xp", "XP, int/4")
  587. serverDisplayTeleportBubbleType = ProtoField.int8("rsc235.36.type", "Bubble Type")
  588. serverDisplayTeleportBubbleXCoord = ProtoField.uint8("rsc235.36.x", " X Coordinate")
  589. serverDisplayTeleportBubbleYCoord = ProtoField.uint8("rsc235.36.y", " Y Coordinate")
  590. serverOpenBankItemCount = ProtoField.uint8("rsc235.42.bankItemCount", "Items in Bank")
  591. serverOpenBankMaximumItemCount = ProtoField.uint8("rsc235.42.maximumBankItems", "How Many Items Can Fit in the Bank")
  592. serverOpenBankItemID = ProtoField.uint16("rsc235.42.itemID", "Item ID")
  593. serverOpenBankItemsInStack = ProtoField.uint32("rsc235.42.itemsInStack", "Items in Stack")
  594. serverObjectHandlerRemoveMode = ProtoField.uint8("rsc235.48.removeMode", "Only Removing Scenery?")
  595. serverObjectHandlerObjectID = ProtoField.uint16("rsc235.48.sceneryId", "Scenery ID")
  596. serverObjectHandlerXCoordinateOffset = ProtoField.int8("rsc235.48.xCoordinate", "X Coordinate of Scenery")
  597. serverObjectHandlerYCoordinateOffset = ProtoField.int8("rsc235.48.yCoordinate", "Y Coordinate of Scenery")
  598. serverBlockChat = ProtoField.uint8("rsc235.51.serverBlockChat", "Block Chat Messages")
  599. serverBlockPrivate = ProtoField.uint8("rsc235.51.serverBlockPrivate", "Block Private Messages")
  600. serverBlockTrade = ProtoField.uint8("rsc235.51.serverBlockTrade", "Block Trade Requests")
  601. serverBlockDuel = ProtoField.uint8("rsc235.51.serverBlockDuel", "Block Duel Requests")
  602. serverSystemUpdateTimer = ProtoField.uint16("rsc235.52.systemUpdateTimer", "System Update Timer")
  603. serverInventoryItemsCount = ProtoField.uint8("rsc235.53.inventoryItemCount","Inventory Item Count")
  604. serverItemId = ProtoField.uint16("rsc235.53.itemID", "Item ID")
  605. serverItemCount = ProtoField.uint32("rsc235.53.itemAmount", "Amount of Item in Stack")
  606. serverItemEquipped = ProtoField.uint8("rsc235.53.equipped","Equipped")
  607. serverNPCCoordsCount = ProtoField.uint8("rsc235.79.npcCount", "NPC Count")
  608. serverNPCCoordsReqUpdate = ProtoField.bool("rsc235.79.requireUpdate", "Update Required")
  609. serverNPCCoordsUpdateType = ProtoField.bool("rsc235.79.updateType", "Stationary?")
  610. serverNPCCoordsAnimationUpdate = ProtoField.uint8("rsc235.79.animationUpdate", "Animation")
  611. serverNPCCoordsServerIndex = ProtoField.uint16("rsc235.79.serverIndex", "Server Index")
  612. serverNPCCoordsXCoordinate = ProtoField.int32("rsc235.79.xCoordinate", "X Coordinate (sent as offset)")
  613. serverNPCCoordsYCoordinate = ProtoField.int32("rsc235.79.yCoordinate", "Y Coordinate (sent as offset)")
  614. serverNPCCoordsAnimation = ProtoField.uint8("rsc235.79.animation", "Animation")
  615. serverNPCCoordsNPCID = ProtoField.uint16("rsc235.79.npcId", "NPC ID")
  616. serverSendPrivateMessageRecipient = ProtoField.string("rsc235.87.recipient", "Recipient")
  617. serverSendPrivateMessageLength = ProtoField.uint16("rsc235.87.messageLength", "Message Length")
  618. serverSendPrivateMessageMessage = ProtoField.string("rsc235.87.message", "Private Message (Scrambled)")
  619. serverShowDialogueServerMessageTopMessage = ProtoField.string("rsc235.89.message", "Message")
  620. serverSetInventorySlotSlot = ProtoField.uint8("rsc235.90.slot", "Slot Number")
  621. serverSetInventorySlotItemID = ProtoField.uint16("rsc235.90.itemID", "Item ID")
  622. serverSetInventorySlotItemEquipped = ProtoField.bool("rsc235.90.equipped", "Item Equipped")
  623. serverSetInventorySlotItemStackAmount = ProtoField.int32("rsc235.90.itemAmount", "Amount of Item in Stack")
  624. serverBoundaryHandlerRemoveMode = ProtoField.uint8("rsc235.91.removeMode", "Only Removing a Boundary?")
  625. serverBoundaryHandlerObjectID = ProtoField.uint16("rsc235.91.boundaryId", "Boundary ID")
  626. serverBoundaryHandlerXCoordinateOffset = ProtoField.int8("rsc235.91.xCoordinate", "X Coordinate of Boundary")
  627. serverBoundaryHandlerYCoordinateOffset = ProtoField.int8("rsc235.91.yCoordinate", "Y Coordinate of Boundary")
  628. serverBoundaryHandlerAlignment = ProtoField.int8("rsc235.91.alignment", "Alignment")
  629. serverInitiateTradePID = ProtoField.uint16("rsc235.92.pid", "PID of User to Trade With")
  630. serverInitiateTradeUsername = ProtoField.string("rsc235.92.username", "Username (from opcode 234 type 5)")
  631. serverUpdateItemsTradedToYouItemCount = ProtoField.int8("rsc235.97.itemCount", "Number of Item Slots Occupied")
  632. serverUpdateItemsTradedToYouItemID = ProtoField.int16("rsc235.97.itemID", "Item")
  633. serverUpdateItemsTradedToYouItemAmount = ProtoField.int32("rsc235.97.itemAmount", "Amount of Item in Stack")
  634. serverGroundItemHandlerRemoveMode = ProtoField.uint8("rsc235.91.removeMode", "Only Removing a Ground Item?")
  635. serverGroundItemHandlerItemID = ProtoField.uint16("rsc235.99.itemID", "Ground Item ID")
  636. serverGroundItemHandlerXCoordinateOffset = ProtoField.int8("rsc235.99.xCoordinate", "X Coordinate of Ground Item")
  637. serverGroundItemHandlerYCoordinateOffset = ProtoField.int8("rsc235.99.yCoordinate", "Y Coordinate of Ground Item")
  638. serverShowShopItemCount = ProtoField.uint8("rsc235.101.itemCount", "Number of Items in Shop")
  639. serverShowShopType = ProtoField.uint8("rsc235.101.shopType", "Shop Type")
  640. serverShowShopSellPriceGenerosity = ProtoField.uint8("rsc235.101.sellPriceGenerosity", "Sell Price Generosity") -- (divides by 100 and multiply by the base item price)
  641. serverShowShopBuyPriceGenerosity = ProtoField.uint8("rsc235.101.buyPriceGenerosity", "Buy Price Generosity") -- (divides by 100 and multiply by the base item price)
  642. serverShowShopStockEffect = ProtoField.uint8("rsc235.101.stockEffectDegree", "How Much Being Over/Under-Stocked Affects Buy/Sell Prices")
  643. serverShowShopItemID = ProtoField.uint16("rsc235.101.itemID", "Item ID")
  644. serverShowShopItemStackAmount = ProtoField.uint16("rsc235.101.amountInStock", "Amount in Stock")
  645. serverShowShopBaseAmountInStock = ProtoField.uint16("rsc235.101.baseAmountInStock", "Base Amount in Stock")
  646. serverUpdateNPCNPCCount = ProtoField.uint8("rsc235.104.npcCount", "NPC Count")
  647. serverUpdateNPCNPCServerIndex = ProtoField.uint16("rsc235.104.npcServerIndex", "NPC Server Index")
  648. serverUpdateNPCUpdateType = ProtoField.uint8("rsc235.104.updateType", "Update Type")
  649. serverUpdateNPCDamageTaken = ProtoField.uint8("rsc235.104.damageTaken", "Damage Taken (by NPC)")
  650. serverUpdateNPCCurrentHP = ProtoField.uint8("rsc235.104.currentHP", "NPC's HP")
  651. serverUpdateNPCMaxHP = ProtoField.uint8("rsc235.104.maxHP", "NPC's Max HP")
  652. serverUpdateNPCPID = ProtoField.uint8("rsc235.104.pidTalkingTo", "PID of Player NPC is Talking To")
  653. serverUpdateNPCMessageLength = ProtoField.uint8("rsc235.104.messageLength", "Message Length")
  654. serverUpdateNPCMessage = ProtoField.string("rsc235.104.message", "Message (Scrambled)")
  655. serverSetIgnoreListCount = ProtoField.int8("rsc235.109.ignoreListCount", "Number of People on Ignore List")
  656. serverSetIgnoreListName = ProtoField.string("rsc235.109.name", "Name")
  657. serverSetIgnoreListAccountName = ProtoField.string("rsc235.109.accountName", "Account Name")
  658. serverSetIgnoreListOldName = ProtoField.string("rsc235.109.oldName", "Old Name")
  659. serverSetIgnoreListServers = ProtoField.string("rsc235.109.oldName2", "Old Name (Duplicate)") -- FINDOUT: why did Jagex do this? icegold.pcap has this field filled a few times.
  660. serverJustCompletedTutorial = ProtoField.uint8("rsc235.111.justCompletedTutorial", "Completed Tutorial")
  661. serverSetFatigue = ProtoField.double("rsc235.114.fatigue", "Fatigue")
  662. serverSleepWordImage = ProtoField.bytes("rsc235.117.sleepWordImageData", "Sleep Word Image Data (can be converted with rscminus)") -- TODO, could convert to ascii-art since it's just a black and white image
  663. serverReceivePMSender = ProtoField.string("rsc235.120.sender", "Sender")
  664. serverReceivePMSender2 = ProtoField.string("rsc235.120.sender2", "Sender (Duplicate)")
  665. serverReceivePMModStatus = ProtoField.int8("rsc235.120.modStatus", "Moderator Status")
  666. serverReceivePMMessageID = ProtoField.uint64("rsc235.120.messageID", "Packed Message ID")
  667. serverReceivePMMessageIDWorld = ProtoField.int16("rsc235.120.messageID.world", "World the Message was Sent From")
  668. serverReceivePMMessageIDID = ProtoField.int24("rsc235.120.messageID.ID", "Message ID")
  669. serverReceivePMMessageLength = ProtoField.uint16("rsc235.120.messageLength", "Message Length")
  670. serverReceivePMMessage = ProtoField.string("rsc235.120.message", "Private Message (Scrambled)")
  671. serverRemoveSlot = ProtoField.uint8("rsc235.123.removeInventorySlot", "Item In Inventory to Remove")
  672. serverSendMessageType = ProtoField.uint8("rsc235.131.messageType", "Message Type")
  673. serverSendMessageInfoContained = ProtoField.uint8("rsc235.131.infoContained", "Info Contained")
  674. serverSendMessageMessage = ProtoField.string("rsc235.131.message", "Message")
  675. serverSendMessageSender = ProtoField.string("rsc235.131.sender", "Sender")
  676. serverSendMessageSender2 = ProtoField.string("rsc235.131.sender2", "Sender (Always Duplicate)")
  677. serverSendMessageColour = ProtoField.string("rsc235.131.colour", "Colour")
  678. serverUpdateFriendFriendName = ProtoField.string("rsc235.149.friendName", "Friend Name")
  679. serverUpdateFriendOldFriendName = ProtoField.string("rsc235.149.oldFriendName", "Old Friend Name")
  680. serverUpdateFriendOnlineStatus = ProtoField.uint8("rsc235.149.onlineStatus", "Online Status")
  681. serverUpdateFriendFriendServer = ProtoField.string("rsc235.149.friendServer", "Friend's Server")
  682. serverSetEquipmentStatsArmour = ProtoField.uint8("rsc235.153.armour", "Armour Bonus")
  683. serverSetEquipmentStatsWeaponAim = ProtoField.uint8("rsc235.153.weaponAim", "Weapon Aim")
  684. serverSetEquipmentStatsWeaponPower = ProtoField.uint8("rsc235.153.weaponPower", "Weapon Power")
  685. serverSetEquipmentStatsMagic = ProtoField.uint8("rsc235.153.magic", "Magic Bonus")
  686. serverSetEquipmentStatsPrayer = ProtoField.uint8("rsc235.153.prayer", "Prayer Bonus")
  687. serverSetStatsPlayerCurrentStat = {}
  688. serverSetStatsPlayerBaseStat = {}
  689. serverSetStatsPlayerXP = {}
  690. for i = 0, 17 do
  691. local lowerCaseSkill = string.lower(SKILL_NAMES[i])
  692. serverSetStatsPlayerCurrentStat[i] = ProtoField.uint8("rsc235.156.currentStat." .. lowerCaseSkill, "Effective " .. SKILL_NAMES[i] .. " Level")
  693. serverSetStatsPlayerBaseStat[i] = ProtoField.uint8("rsc235.156.baseStat." .. lowerCaseSkill, "Base " .. SKILL_NAMES[i] .. " Level")
  694. serverSetStatsPlayerXP[i] = ProtoField.double("rsc235.156.xp." .. lowerCaseSkill, SKILL_NAMES[i] .. " XP")
  695. end
  696. serverSetStatsPlayerQuestPoints = ProtoField.uint8("rsc235.156.questPoints", "Quest Points")
  697. serverUpdateStatSkill = ProtoField.uint8("rsc235.159.skill", "Skill")
  698. serverUpdateStatPlayerCurrentStat = ProtoField.uint8("rsc235.159.currentStat", "Effective Level")
  699. serverUpdateStatPlayerBaseStat = ProtoField.uint8("rsc235.159.baseStat", "Base Level")
  700. serverUpdateStatExperience = ProtoField.double("rsc235.159.xp", "Experience Points")
  701. serverUpdateTradeRecipientAcceptance = ProtoField.uint8("rsc235.162.tradeAccepted", "Trade Accepted")
  702. serverShowConfirmDuelOpponentName = ProtoField.string("rsc235.172.opponentName", "Opponent Name")
  703. serverShowConfirmDuelOpponentItemCount = ProtoField.uint8("rsc235.172.opponentItemCount", "Number of Items Staked by Opponent")
  704. serverShowConfirmDuelOpponentItemID = ProtoField.uint16("rsc235.172.opponentItemId", "Item ID of Item Staked by Opponent")
  705. serverShowConfirmDuelOpponentItemStackAmount = ProtoField.uint32("rsc235.172.opponentItemIdStackamount", "Amount of Item Staked by Opponent")
  706. serverShowConfirmDuelItemCount = ProtoField.uint8("rsc235.172.itemCount", "Number of Items Staked by Player")
  707. serverShowConfirmDuelItemID = ProtoField.uint16("rsc235.172.itemID", "Item ID of Item Staked by Player")
  708. serverShowConfirmDuelItemStackAmount = ProtoField.uint32("rsc235.172.itemIdStackamount", "Amount of Item Staked")
  709. serverShowConfirmDuelRetreat = ProtoField.uint8("rsc235.172.retreat", "Allowed to Retreat")
  710. serverShowConfirmDuelMagic = ProtoField.uint8("rsc235.172.magic", "Magic Restricted")
  711. serverShowConfirmDuelPrayer = ProtoField.uint8("rsc235.172.prayer", "Prayer Restricted")
  712. serverShowConfirmDuelWeapons = ProtoField.uint8("rsc235.172.weapons", "Weapons Restricted")
  713. serverShowDialogueDuelPID = ProtoField.uint16("rsc235.176.pid", "PID of User to Duel With")
  714. serverShowDialogueDuelUsername = ProtoField.string("rsc235.176.username", "Username (from opcode 234 type 5)")
  715. serverShowWelcomeIP = ProtoField.string("rsc235.182.IPAddress", "Last Logged In IP (almost always replaced by RSC+)")
  716. serverShowWelcomeDays = ProtoField.uint16("rsc235.182.daysAgo", "Days Since Log In")
  717. serverShowWelcomeRecoverySetDays = ProtoField.uint8("rsc235.182.recoverySetDays", "Days Since Recovery Questions Set")
  718. serverShowWelcomeUnreadMessages = ProtoField.uint16("rsc235.182.unreadMessages", "Unread Message Count")
  719. serverPlayerCoordsLocalRegionX = ProtoField.uint16("rsc235.191.thisLocalRegionX", "Local Region X coordinate")
  720. serverPlayerCoordsLocalRegionY = ProtoField.uint16("rsc235.191.thisLocalRegionY", "Local Region Y coordinate")
  721. serverPlayerCoordsAnimation = ProtoField.uint8("rsc235.191.animation", "Animation")
  722. serverPlayerCoordsPlayerCount = ProtoField.uint8("rsc235.191.playerCount", "Player Count")
  723. serverPlayerCoordsAnimationUpdateRequired = ProtoField.bool("rsc235.191.animationUpdateRequired", "Animation Update Required")
  724. -- serverPlayerCoordsUpdateType = ProtoField.bool("rsc235.191.updateType", "Moving Animation Update, or Stationary Animation Update") TODO
  725. serverPlayerCoordsAnimationUpdate = ProtoField.uint8("rsc235.191.animationUpdate", "Animation Update")
  726. serverPlayerCoordsNewPlayerPID = ProtoField.uint16("rsc235.191.newPlayerServerIndex", "New Player's PID")
  727. serverPlayerCoordsNewPlayerX = ProtoField.uint16("rsc235.191.newPlayerXCoordinate", "New Player's X coordinate")
  728. serverPlayerCoordsNewPlayerY = ProtoField.uint16("rsc235.191.newPlayerYCoordinate", "New Player's Y coordinate")
  729. serverPlayerCoordsNewPlayerAnimation = ProtoField.uint8("rsc235.191.newPlayerAnimation", "New Player's Animation State")
  730. serverSoundName = ProtoField.string("rsc235.204.soundName", "Sound File Name")
  731. serverSetPrayersThickSkin = ProtoField.uint8("rsc235.206.thickSkin", PRAYER_NAMES[0])
  732. serverSetPrayersBurstOfStrength = ProtoField.uint8("rsc235.206.burstOfStrength", PRAYER_NAMES[1])
  733. serverSetPrayersClarityOfThought = ProtoField.uint8("rsc235.206.clarityOfThought", PRAYER_NAMES[2])
  734. serverSetPrayersRockSkin = ProtoField.uint8("rsc235.206.rockSkin", PRAYER_NAMES[3])
  735. serverSetPrayersSuperhumanStrength = ProtoField.uint8("rsc235.206.superhumanStrength", PRAYER_NAMES[4])
  736. serverSetPrayersImprovedReflexes = ProtoField.uint8("rsc235.206.improvedReflexes", PRAYER_NAMES[5])
  737. serverSetPrayersRapidRestore = ProtoField.uint8("rsc235.206.rapidRestore", PRAYER_NAMES[6])
  738. serverSetPrayersRapidHeal = ProtoField.uint8("rsc235.206.rapidHeal", PRAYER_NAMES[7])
  739. serverSetPrayersProtectItems = ProtoField.uint8("rsc235.206.protectItems", PRAYER_NAMES[8])
  740. serverSetPrayersSteelSkin = ProtoField.uint8("rsc235.206.steelSkin", PRAYER_NAMES[9])
  741. serverSetPrayersUltimateStrength = ProtoField.uint8("rsc235.206.ultimateStrength", PRAYER_NAMES[10])
  742. serverSetPrayersIncredibleReflexes = ProtoField.uint8("rsc235.206.incredibleReflexes", PRAYER_NAMES[11])
  743. serverSetPrayersParalyzeMonster = ProtoField.uint8("rsc235.206.paralyzeMonster", PRAYER_NAMES[12])
  744. serverSetPrayersProtectFromMissiles = ProtoField.uint8("rsc235.206.protectFromMissiles", PRAYER_NAMES[13])
  745. serverUpdateAcceptedDuelBool = ProtoField.uint8("rsc235.210.accepted", "Accepted Duel")
  746. serverRemoveWorldEntityXCoordinate = ProtoField.int16("rsc235.211.xCoordinate", "X Coordinate")
  747. serverRemoveWorldEntityYCoordinate = ProtoField.int16("rsc235.211.yCoordinate", "Y Coordinate")
  748. serverShowDialogueServerMessageNotTopMessage = ProtoField.string("rsc235.222.message", "Message")
  749. serverPlayerUpdatePlayerCount = ProtoField.uint8("rsc235.234.playerCount", "Player Count")
  750. serverPlayerUpdatePID = ProtoField.uint16("rsc235.234.pid", "PID")
  751. serverPlayerUpdateUpdateType = ProtoField.uint8("rsc235.234.updateType", "Update Type")
  752. serverPlayerUpdateUpdateType0bubbleItem = ProtoField.uint16("rsc235.234.updateType.0.bubbleItem", "Bubble Item")
  753. serverPlayerUpdateUpdateType1modStatus = ProtoField.int8("rsc235.234.updateType.1.modStatus", "Mod Status")
  754. serverPlayerUpdateUpdateType1chatLength = ProtoField.uint16("rsc235.234.updateType.1.chatLength", "Message Length")
  755. serverPlayerUpdateUpdateType1chatMessage = ProtoField.string("rsc235.234.updateType.1.chatMessage", "Chat Message (Scrambled)")
  756. serverPlayerUpdateUpdateType2damage = ProtoField.uint8("rsc235.234.updateType.2.damage", "Damage Taken")
  757. serverPlayerUpdateUpdateType2currentHp = ProtoField.uint8("rsc235.234.updateType.2.currentHP", "Current HP")
  758. serverPlayerUpdateUpdateType2maxHp = ProtoField.uint8("rsc235.234.updateType.2.maxHP", "Max HP")
  759. serverPlayerUpdateUpdateType3sprite = ProtoField.uint16("rsc235.234.updateType.3.sprite", "Sprite")
  760. serverPlayerUpdateUpdateType3shooterServerIndex = ProtoField.uint16("rsc235.234.updateType.3.shooterServerIndex", "Shooter Server Index")
  761. serverPlayerUpdateUpdateType4sprite = ProtoField.uint16("rsc235.234.updateType.4.sprite", "Sprite")
  762. serverPlayerUpdateUpdateType4shooterServerIndex = ProtoField.uint16("rsc235.234.updateType.4.shooterServerIndex", "Shooter Server Index")
  763. serverPlayerUpdateUpdateType5serverIndex = ProtoField.uint16("rsc235.234.updateType.5.serverIndex", "Server Index (unused)")
  764. serverPlayerUpdateUpdateType5username1 = ProtoField.string("rsc235.234.updateType.5.displayName", "Display Name")
  765. serverPlayerUpdateUpdateType5username2 = ProtoField.string("rsc235.234.updateType.5.accountName", "Account Name")
  766. serverPlayerUpdateUpdateType5equipCount = ProtoField.uint8("rsc235.234.updateType.5.equipCount", "Equipment Count")
  767. serverPlayerUpdateUpdateType5equipment = ProtoField.bytes("rsc235.234.updateType.5.equipment", "Equipment")
  768. serverPlayerUpdateUpdateType5hairColor = ProtoField.uint8("rsc235.234.updateType.5.hairColour", "Hair Colour")
  769. serverPlayerUpdateUpdateType5topColor = ProtoField.uint8("rsc235.234.updateType.5.topColour", "Top Colour")
  770. serverPlayerUpdateUpdateType5bottomColor = ProtoField.uint8("rsc235.234.updateType.5.pantsColour", "Pants Colour")
  771. serverPlayerUpdateUpdateType5skinColor = ProtoField.uint8("rsc235.234.updateType.5.skinColour", "Skin Colour")
  772. serverPlayerUpdateUpdateType5level = ProtoField.uint8("rsc235.234.updateType.5.level", "Combat Level")
  773. serverPlayerUpdateUpdateType5skull = ProtoField.uint8("rsc235.234.updateType.5.skull", "Skull")
  774. serverPlayerUpdateUpdateType6chatLength = ProtoField.uint16("rsc235.234.updateType.6.chatLength", "Message Length")
  775. serverPlayerUpdateUpdateType6chatMessage = ProtoField.string("rsc235.234.updateType.6.chatMessage", "Chat Message (Scrambled)")
  776. serverUpdateIgnoreBecauseOfNameChangeIgnoreListName = ProtoField.string("rsc235.237.name", "Name")
  777. serverUpdateIgnoreBecauseOfNameChangeIgnoreListAccountName = ProtoField.string("rsc235.237.accountName", "Account Name")
  778. serverUpdateIgnoreBecauseOfNameChangeIgnoreListOldName = ProtoField.string("rsc235.237.oldName", "Old Name")
  779. serverUpdateIgnoreBecauseOfNameChangeIgnoreListServers = ProtoField.string("rsc235.237.oldName2", "Old Name (Duplicate)") -- TODO, confirm this is just old name duplicate
  780. serverUpdateIgnoreBecauseOfNameChangeAttemptUpdatingExistingEntry = ProtoField.bool("rsc235.237.attemptUpdatingExistingEntry", "Attempt to Update an Existing Name on the Ignore List") -- always false in 10,000+ replays
  781. serverCameraModeAuto = ProtoField.uint8("rsc235.240.serverCameraModeAuto", "Camera Angle Mode")
  782. serverMouseButtonOne = ProtoField.uint8("rsc235.240.serverMouseButtonOne", "Mouse Buttons")
  783. serverSoundDisabled = ProtoField.uint8("rsc235.240.serverSoundDisabled", "Sound Effects")
  784. serverSetFatigueSleepingFatigueSleeping = ProtoField.uint16("rsc235.244.fatigueSleeping", "Displayed Fatigue While Asleep")
  785. serverShowDialogueMenuCount = ProtoField.uint8("rsc235.245.optionCount", "Number of Options")
  786. serverShowDialogueMenuString = ProtoField.string("rsc235.245.optionText", "Option Text")
  787. serverUpdateBankItemDisplaySlot = ProtoField.uint8("rsc235.249.slot", "Slot Number")
  788. serverUpdateBankItemDisplayItemID = ProtoField.uint16("rsc235.249.itemID", "Item ID")
  789. serverUpdateBankItemDisplayItemCount = ProtoField.uint16("rsc235.249.itemCount", "Amount in New Stack")
  790. serverUpdateDuelOpponentAccepted = ProtoField.uint8("rsc235.253.duelOpponentAccepted", "Opponent Accepted Duel")
  791. --------------------------------------------------------------------------------
  792. rsc235_protocol.fields = {
  793. -- common
  794. clientPacket,
  795. clientOpcode,
  796. clientPacketLength,
  797. -- 10000 (rscminus virtual opcode)
  798. serverLoginResponse,
  799. -- 12345 (server-sided metadata field)
  800. serverMetadataLoginResponse,
  801. serverMetadataClientVersion,
  802. serverMetadataAuthenticClient,
  803. serverMetadataStartTime,
  804. serverMetadataWorldNumber,
  805. serverMetadataServerName,
  806. serverMetadataUsername,
  807. serverMetadataPlayerIP,
  808. serverMetadataReservedBytes,
  809. -- 5
  810. serverQuests[0], serverQuests[1], serverQuests[2], serverQuests[3], serverQuests[4], serverQuests[5], serverQuests[6],
  811. serverQuests[7], serverQuests[8], serverQuests[9], serverQuests[10], serverQuests[11], serverQuests[12], serverQuests[13],
  812. serverQuests[14], serverQuests[15], serverQuests[16], serverQuests[17], serverQuests[18], serverQuests[19], serverQuests[20],
  813. serverQuests[21], serverQuests[22], serverQuests[23], serverQuests[24], serverQuests[25], serverQuests[26], serverQuests[27],
  814. serverQuests[28], serverQuests[29], serverQuests[30], serverQuests[31], serverQuests[32], serverQuests[33], serverQuests[34],
  815. serverQuests[35], serverQuests[36], serverQuests[37], serverQuests[38], serverQuests[39], serverQuests[40], serverQuests[41],
  816. serverQuests[42], serverQuests[43], serverQuests[44], serverQuests[45], serverQuests[46], serverQuests[47], serverQuests[48],
  817. serverQuests[49],
  818. -- 6
  819. serverUpdateStakedItemsOpponentNumberOfItemsStaked,
  820. serverUpdateStakedItemsOpponentItemId,
  821. serverUpdateStakedItemsOpponentItemStack,
  822. -- 15
  823. serverUpdateTradeAcceptance,
  824. -- 20
  825. serverConfirmTradeRecipientName,
  826. serverConfirmTradeRecipientItemCount,
  827. serverConfirmTradeRecipientItemID,
  828. serverConfirmTradeRecipientItemStack,
  829. serverConfirmTradeItemCount,
  830. serverConfirmTradeItemID,
  831. serverConfirmTradeItemStack,
  832. -- 25
  833. serverFloorSetLocalPlayerServerIndex,
  834. serverFloorSetPlaneWidth,
  835. serverFloorSetPlaneHeight,
  836. serverFloorSetPlaneIndex,
  837. serverFloorSetPlaneFloor,
  838. serverFloorSetPlaneDistanceBetweenFloors,
  839. -- 30
  840. serverSyncDuelSettingsRetreat,
  841. serverSyncDuelSettingsMagic,
  842. serverSyncDuelSettingsPrayer,
  843. serverSyncDuelSettingsWeapons,
  844. -- 33
  845. serverUpdateXPSkill,
  846. serverUpdateXPXP,
  847. -- 36
  848. serverDisplayTeleportBubbleType,
  849. serverDisplayTeleportBubbleXCoord,
  850. serverDisplayTeleportBubbleYCoord,
  851. -- 42
  852. serverOpenBankItemCount,
  853. serverOpenBankMaximumItemCount,
  854. serverOpenBankItemID,
  855. serverOpenBankItemsInStack,
  856. -- 48
  857. serverObjectHandlerRemoveMode,
  858. serverObjectHandlerObjectID,
  859. serverObjectHandlerXCoordinateOffset,
  860. serverObjectHandlerYCoordinateOffset,
  861. -- 51
  862. serverBlockChat,
  863. serverBlockPrivate,
  864. serverBlockTrade,
  865. serverBlockDuel,
  866. -- 52
  867. serverSystemUpdateTimer,
  868. -- 53
  869. serverInventoryItemsCount,
  870. serverItemId,
  871. serverItemCount,
  872. serverItemEquipped,
  873. -- 79
  874. serverNPCCoordsCount,
  875. serverNPCCoordsReqUpdate,
  876. serverNPCCoordsUpdateType,
  877. serverNPCCoordsAnimationUpdate,
  878. serverNPCCoordsServerIndex,
  879. serverNPCCoordsXCoordinate,
  880. serverNPCCoordsYCoordinate,
  881. serverNPCCoordsAnimation,
  882. serverNPCCoordsNPCID,
  883. -- 87
  884. serverSendPrivateMessageRecipient,
  885. serverSendPrivateMessageLength,
  886. serverSendPrivateMessageMessage,
  887. -- 89
  888. serverShowDialogueServerMessageTopMessage,
  889. -- 90
  890. serverSetInventorySlotSlot,
  891. serverSetInventorySlotItemID,
  892. serverSetInventorySlotItemEquipped,
  893. serverSetInventorySlotItemStackAmount,
  894. -- 91
  895. serverBoundaryHandlerRemoveMode,
  896. serverBoundaryHandlerObjectID,
  897. serverBoundaryHandlerXCoordinateOffset,
  898. serverBoundaryHandlerYCoordinateOffset,
  899. serverBoundaryHandlerAlignment,
  900. -- 92
  901. serverInitiateTradePID,
  902. serverInitiateTradeUsername,
  903. -- 97
  904. serverUpdateItemsTradedToYouItemCount,
  905. serverUpdateItemsTradedToYouItemID,
  906. serverUpdateItemsTradedToYouItemAmount,
  907. -- 99
  908. serverGroundItemHandlerRemoveMode,
  909. serverGroundItemHandlerItemID,
  910. serverGroundItemHandlerXCoordinateOffset,
  911. serverGroundItemHandlerYCoordinateOffset,
  912. -- 101
  913. serverShowShopItemCount,
  914. serverShowShopType,
  915. serverShowShopSellPriceGenerosity,
  916. serverShowShopBuyPriceGenerosity,
  917. serverShowShopStockEffect,
  918. serverShowShopItemID,
  919. serverShowShopItemStackAmount,
  920. serverShowShopBaseAmountInStock,
  921. -- 104
  922. serverUpdateNPCNPCCount,
  923. serverUpdateNPCNPCServerIndex,
  924. serverUpdateNPCUpdateType,
  925. serverUpdateNPCDamageTaken,
  926. serverUpdateNPCCurrentHP,
  927. serverUpdateNPCMaxHP,
  928. serverUpdateNPCPID,
  929. serverUpdateNPCMessageLength,
  930. serverUpdateNPCMessage,
  931. -- 109
  932. serverSetIgnoreListCount,
  933. serverSetIgnoreListName,
  934. serverSetIgnoreListAccountName,
  935. serverSetIgnoreListOldName,
  936. serverSetIgnoreListServers,
  937. -- 111
  938. serverJustCompletedTutorial,
  939. -- 114
  940. serverSetFatigue,
  941. -- 117
  942. serverSleepWordImage,
  943. -- 120
  944. serverReceivePMSender,
  945. serverReceivePMSender2,
  946. serverReceivePMModStatus,
  947. serverReceivePMMessageID,
  948. serverReceivePMMessageIDWorld,
  949. serverReceivePMMessageIDID,
  950. serverReceivePMMessageLength,
  951. serverReceivePMMessage,
  952. -- 123
  953. serverRemoveSlot,
  954. -- 131
  955. serverSendMessageType,
  956. serverSendMessageInfoContained,
  957. serverSendMessageMessage,
  958. serverSendMessageSender,
  959. serverSendMessageSender2,
  960. serverSendMessageColour,
  961. -- 149
  962. serverUpdateFriendFriendName,
  963. serverUpdateFriendOldFriendName,
  964. serverUpdateFriendOnlineStatus,
  965. serverUpdateFriendFriendServer,
  966. -- 153
  967. serverSetEquipmentStatsArmour,
  968. serverSetEquipmentStatsWeaponAim,
  969. serverSetEquipmentStatsWeaponPower,
  970. serverSetEquipmentStatsMagic,
  971. serverSetEquipmentStatsPrayer,
  972. -- 156
  973. serverSetStatsPlayerCurrentStat[0], serverSetStatsPlayerBaseStat[0], serverSetStatsPlayerXP[0],
  974. serverSetStatsPlayerCurrentStat[1], serverSetStatsPlayerBaseStat[1], serverSetStatsPlayerXP[1],
  975. serverSetStatsPlayerCurrentStat[2], serverSetStatsPlayerBaseStat[2], serverSetStatsPlayerXP[2],
  976. serverSetStatsPlayerCurrentStat[3], serverSetStatsPlayerBaseStat[3], serverSetStatsPlayerXP[3],
  977. serverSetStatsPlayerCurrentStat[4], serverSetStatsPlayerBaseStat[4], serverSetStatsPlayerXP[4],
  978. serverSetStatsPlayerCurrentStat[5], serverSetStatsPlayerBaseStat[5], serverSetStatsPlayerXP[5],
  979. serverSetStatsPlayerCurrentStat[6], serverSetStatsPlayerBaseStat[6], serverSetStatsPlayerXP[6],
  980. serverSetStatsPlayerCurrentStat[7], serverSetStatsPlayerBaseStat[7], serverSetStatsPlayerXP[7],
  981. serverSetStatsPlayerCurrentStat[8], serverSetStatsPlayerBaseStat[8], serverSetStatsPlayerXP[8],
  982. serverSetStatsPlayerCurrentStat[9], serverSetStatsPlayerBaseStat[9], serverSetStatsPlayerXP[9],
  983. serverSetStatsPlayerCurrentStat[10], serverSetStatsPlayerBaseStat[10], serverSetStatsPlayerXP[10],
  984. serverSetStatsPlayerCurrentStat[11], serverSetStatsPlayerBaseStat[11], serverSetStatsPlayerXP[11],
  985. serverSetStatsPlayerCurrentStat[12], serverSetStatsPlayerBaseStat[12], serverSetStatsPlayerXP[12],
  986. serverSetStatsPlayerCurrentStat[13], serverSetStatsPlayerBaseStat[13], serverSetStatsPlayerXP[13],
  987. serverSetStatsPlayerCurrentStat[14], serverSetStatsPlayerBaseStat[14], serverSetStatsPlayerXP[14],
  988. serverSetStatsPlayerCurrentStat[15], serverSetStatsPlayerBaseStat[15], serverSetStatsPlayerXP[15],
  989. serverSetStatsPlayerCurrentStat[16], serverSetStatsPlayerBaseStat[16], serverSetStatsPlayerXP[16],
  990. serverSetStatsPlayerCurrentStat[17], serverSetStatsPlayerBaseStat[17], serverSetStatsPlayerXP[17],
  991. serverSetStatsPlayerQuestPoints,
  992. -- 159
  993. serverUpdateStatSkill,
  994. serverUpdateStatPlayerCurrentStat,
  995. serverUpdateStatPlayerBaseStat,
  996. serverUpdateStatExperience,
  997. -- 162
  998. serverUpdateTradeRecipientAcceptance,
  999. -- 172
  1000. serverShowConfirmDuelOpponentName,
  1001. serverShowConfirmDuelOpponentItemCount,
  1002. serverShowConfirmDuelOpponentItemID,
  1003. serverShowConfirmDuelOpponentItemStackAmount,
  1004. serverShowConfirmDuelItemCount,
  1005. serverShowConfirmDuelItemID,
  1006. serverShowConfirmDuelItemStackAmount,
  1007. serverShowConfirmDuelRetreat,
  1008. serverShowConfirmDuelMagic,
  1009. serverShowConfirmDuelPrayer,
  1010. serverShowConfirmDuelWeapons,
  1011. -- 176
  1012. serverShowDialogueDuelPID,
  1013. serverShowDialogueDuelUsername,
  1014. -- 182
  1015. serverShowWelcomeIP,
  1016. serverShowWelcomeDays,
  1017. serverShowWelcomeRecoverySetDays,
  1018. serverShowWelcomeUnreadMessages,
  1019. -- 191
  1020. serverPlayerCoordsLocalRegionX,
  1021. serverPlayerCoordsLocalRegionY,
  1022. serverPlayerCoordsAnimation,
  1023. serverPlayerCoordsPlayerCount,
  1024. serverPlayerCoordsAnimationUpdateRequired,
  1025. serverPlayerCoordsAnimationUpdate,
  1026. serverPlayerCoordsNewPlayerPID,
  1027. serverPlayerCoordsNewPlayerX,
  1028. serverPlayerCoordsNewPlayerY,
  1029. serverPlayerCoordsNewPlayerAnimation,
  1030. -- 204
  1031. serverSoundName,
  1032. -- 206
  1033. serverSetPrayersThickSkin,
  1034. serverSetPrayersBurstOfStrength,
  1035. serverSetPrayersClarityOfThought,
  1036. serverSetPrayersRockSkin,
  1037. serverSetPrayersSuperhumanStrength,
  1038. serverSetPrayersImprovedReflexes,
  1039. serverSetPrayersRapidRestore,
  1040. serverSetPrayersRapidHeal,
  1041. serverSetPrayersProtectItems,
  1042. serverSetPrayersSteelSkin,
  1043. serverSetPrayersUltimateStrength,
  1044. serverSetPrayersIncredibleReflexes,
  1045. serverSetPrayersParalyzeMonster,
  1046. serverSetPrayersProtectFromMissiles,
  1047. -- 210
  1048. serverUpdateAcceptedDuelBool,
  1049. -- 211
  1050. serverRemoveWorldEntityXCoordinate,
  1051. serverRemoveWorldEntityYCoordinate,
  1052. -- 222
  1053. serverShowDialogueServerMessageNotTopMessage,
  1054. -- 234
  1055. serverPlayerUpdatePlayerCount,
  1056. serverPlayerUpdatePID,
  1057. serverPlayerUpdateUpdateType,
  1058. serverPlayerUpdateUpdateType0bubbleItem,
  1059. serverPlayerUpdateUpdateType1modStatus,
  1060. serverPlayerUpdateUpdateType1chatLength,
  1061. serverPlayerUpdateUpdateType1chatMessage,
  1062. serverPlayerUpdateUpdateType2damage,
  1063. serverPlayerUpdateUpdateType2currentHp,
  1064. serverPlayerUpdateUpdateType2maxHp,
  1065. serverPlayerUpdateUpdateType3sprite,
  1066. serverPlayerUpdateUpdateType3shooterServerIndex,
  1067. serverPlayerUpdateUpdateType4sprite,
  1068. serverPlayerUpdateUpdateType4shooterServerIndex,
  1069. serverPlayerUpdateUpdateType5serverIndex,
  1070. serverPlayerUpdateUpdateType5username1,
  1071. serverPlayerUpdateUpdateType5username2,
  1072. serverPlayerUpdateUpdateType5equipCount,
  1073. serverPlayerUpdateUpdateType5equipment,
  1074. serverPlayerUpdateUpdateType5hairColor,
  1075. serverPlayerUpdateUpdateType5topColor,
  1076. serverPlayerUpdateUpdateType5bottomColor,
  1077. serverPlayerUpdateUpdateType5skinColor,
  1078. serverPlayerUpdateUpdateType5level,
  1079. serverPlayerUpdateUpdateType5skull,
  1080. serverPlayerUpdateUpdateType5unused,
  1081. serverPlayerUpdateUpdateType6chatLength,
  1082. serverPlayerUpdateUpdateType6chatMessage,
  1083. -- 237
  1084. serverUpdateIgnoreBecauseOfNameChangeIgnoreListName,
  1085. serverUpdateIgnoreBecauseOfNameChangeIgnoreListAccountName,
  1086. serverUpdateIgnoreBecauseOfNameChangeIgnoreListOldName,
  1087. serverUpdateIgnoreBecauseOfNameChangeIgnoreListServers,
  1088. serverUpdateIgnoreBecauseOfNameChangeAttemptUpdatingExistingEntry,
  1089. -- 240
  1090. serverCameraModeAuto,
  1091. serverMouseButtonOne,
  1092. serverSoundDisabled,
  1093. -- 244
  1094. serverSetFatigueSleepingFatigueSleeping,
  1095. -- 245
  1096. serverShowDialogueMenuCount,
  1097. serverShowDialogueMenuString,
  1098. -- 249
  1099. serverUpdateBankItemDisplaySlot,
  1100. serverUpdateBankItemDisplayItemID,
  1101. serverUpdateBankItemDisplayItemCount,
  1102. -- 253
  1103. serverUpdateDuelOpponentAccepted,
  1104. -- 0c
  1105. clientConnectReconnecting,
  1106. clientConnectVersion,
  1107. clientConnectEncrypted,
  1108. -- 4c
  1109. clientCastOnInventoryInventoryIndex,
  1110. clientCastOnInventorySpellID,
  1111. -- 8c
  1112. clientSendDuelSettingsRetreat,
  1113. clientSendDuelSettingsMagic,
  1114. clientSendDuelSettingsPrayer,
  1115. clientSendDuelSettingsWeapons,
  1116. -- 14c
  1117. clientInteractWithBoundaryXCoord,
  1118. clientInteractWithBoundaryYCoord,
  1119. clientInteractWithBoundaryAlignment,
  1120. -- 16c
  1121. clientWalkAndPerformActionX,
  1122. clientWalkAndPerformActionY,
  1123. clientWalkAndPerformActionPathX,
  1124. clientWalkAndPerformActionPathY,
  1125. -- 22c
  1126. clientBankWithdrawItemID,
  1127. clientBankWithdrawAmount,
  1128. clientBankWithdrawMagicNumber,
  1129. -- 23c
  1130. clientBankDepositItemID,
  1131. clientBankDepositAmount,
  1132. clientBankDepositMagicNumber,
  1133. -- 29c
  1134. clientCombatStyle,
  1135. -- 33c
  1136. clientSendStakedItemsCount,
  1137. clientSendStakedItemsItemID,
  1138. clientSendStakedItemsItemAmount,
  1139. -- 38c
  1140. clientSendCommandStringCommand,
  1141. -- 45c
  1142. clientGuessSleepwordDelay,
  1143. clientGuessSleepwordGuess,
  1144. -- 46c
  1145. clientOfferItemItemCount,
  1146. clientOfferItemItemID,
  1147. clientOfferItemItemStack,
  1148. -- 50c
  1149. clientCastNPCSpellID,
  1150. clientCastNPCNPCID,
  1151. -- 53c
  1152. clientUseOnGroundItemXCoord,
  1153. clientUseOnGroundItemYCoord,
  1154. clientUseOnGroundItemInventorySlot,
  1155. clientUseOnGroundItemGroundItemID,
  1156. -- 59c
  1157. clientAdminTeleportXCoord,
  1158. clientAdminTeleportYCoord,
  1159. -- 60c
  1160. clientPrayerOnPrayer,
  1161. -- 64c
  1162. clientSendPrivacySettingsChat,
  1163. clientSendPrivacySettingsPrivate,
  1164. clientSendPrivacySettingsTrade,
  1165. clientSendPrivacySettingsDuel,
  1166. -- 79c
  1167. clientInteractWithScenery2XCoord,
  1168. clientInteractWithScenery2YCoord,
  1169. -- 90c
  1170. clientActivateInventoryItemSlot,
  1171. -- 91c
  1172. clientCombineInventorySlot1,
  1173. clientCombineInventorySlot2,
  1174. -- 99c
  1175. clientCastOnSceneryXCoord,
  1176. clientCastOnSceneryYCoord,
  1177. clientCastOnScenerySpellID,
  1178. -- 103c
  1179. clientSendDuelRequest,
  1180. -- 111c
  1181. clientSetting,
  1182. clientSettingValue,
  1183. -- 113c
  1184. clientUseOnPlayerPID,
  1185. clientUseOnPlayerSlot,
  1186. -- 115c
  1187. clientUseOnSceneryX,
  1188. clientUseOnSceneryY,
  1189. clientUseOnScenerySlot,
  1190. -- 116c
  1191. clientOption,
  1192. -- 127c
  1193. clientInteractWithBoundary2XCoord,
  1194. clientInteractWithBoundary2YCoord,
  1195. clientInteractWithBoundary2Alignment,
  1196. -- 132c
  1197. clientAddIgnoreName,
  1198. -- 135c
  1199. clientUseOnNPCNPCID,
  1200. clientUseOnNPCSlot,
  1201. -- 136c
  1202. clientInteractWithSceneryX,
  1203. clientInteractWithSceneryY,
  1204. -- 137c
  1205. clientCastOnSelfSpell,
  1206. -- 142c
  1207. clientAgreeToTradePID,
  1208. -- 153c
  1209. clientTalkToNPCID,
  1210. -- 158c
  1211. clientCastOnGroundXCoord,
  1212. clientCastOnGroundYCoord,
  1213. clientCastOnGroundSpell,
  1214. -- 161c
  1215. clientUseWithBoundaryXCoord,
  1216. clientUseWithBoundaryYCoord,
  1217. clientUseWithBoundaryAlignment,
  1218. clientUseWithBoundarySlot,
  1219. -- 165c
  1220. clientFollowPlayerPID,
  1221. -- 167c
  1222. clientRemoveFriendName,
  1223. -- 169c
  1224. clientEquipItemSlot,
  1225. -- 170c
  1226. clientUnequipItemItem,
  1227. -- 171c
  1228. clientAttackPlayerTargetPID,
  1229. -- 180c
  1230. clientCastOnBoundaryXCoord,
  1231. clientCastOnBoundaryYCoord,
  1232. clientCastOnBoundaryAlignment,
  1233. clientCastOnBoundarySpell,
  1234. -- 187c
  1235. clientWalkX,
  1236. clientWalkY,
  1237. clientWalkPathX,
  1238. clientWalkPathY,
  1239. -- 190c
  1240. clientAttackNPCID,
  1241. -- 195c
  1242. clientAddFriendName,
  1243. -- 202c
  1244. clientInteractNPCID,
  1245. -- 206c
  1246. clientSendReportName,
  1247. clientSendReportReason,
  1248. clientSendReportMute,
  1249. -- 216c
  1250. clientSendChatMessageLength,
  1251. clientSendChatMessageMessage,
  1252. -- 218c
  1253. clientSendPrivateMessageRecipient,
  1254. clientSendPrivateMessageLength,
  1255. clientSendPrivateMessageMessage,
  1256. -- 221c
  1257. clientSellToShopItemId,
  1258. clientSellToShopShopAmount,
  1259. clientSellToShopSellAmount,
  1260. -- 229c
  1261. clientCastPVPTargetPID,
  1262. clientCastPVPSpellID,
  1263. -- 235c
  1264. clientChangeAppearanceHeadRestrictions,
  1265. clientChangeAppearanceHeadType,
  1266. clientChangeAppearanceBodyType,
  1267. clientChangeAppearanceAlways2,
  1268. clientChangeAppearanceHairColour,
  1269. clientChangeAppearanceTopColour,
  1270. clientChangeAppearenceBottomColour,
  1271. clientChangeAppearenceSkinColour,
  1272. -- 236c
  1273. clientBuyFromShopItemId,
  1274. clientBuyFromShopShopAmount,
  1275. clientBuyFromShopSellAmount,
  1276. -- 241c
  1277. clientExignoredName,
  1278. -- 246c
  1279. clientDropItemSlot,
  1280. -- 247c
  1281. clientTakeGroundItemXCoord,
  1282. clientTakeGroundItemYCoord,
  1283. clientTakeGroundItemItemID,
  1284. -- 249c
  1285. clientCastOnGroundItemXCoord,
  1286. clientCastOnGroundItemYCoord,
  1287. clientCastOnGroundItemItemID,
  1288. clientCastOnGroundItemSpellID,
  1289. -- 254c
  1290. clientPrayerOffPrayer
  1291. }
  1292. if gui_enabled() then
  1293. if thisDebugging then
  1294. debugWindow = TextWindow.new("debug log")
  1295. end
  1296. end
  1297. --============================================================================--
  1298. function resolveOpcodeName(clientPacket, opcode)
  1299. if (clientPacket == 1) then
  1300. return "CLIENT_" .. resolveClientOpcodeName(opcode)
  1301. else
  1302. return "SERVER_" .. resolveServerOpcodeName(opcode)
  1303. end
  1304. end
  1305. function resolveClientOpcodeName(opcode)
  1306. if (CLIENT_OPCODES[opcode] ~= nil) then
  1307. return CLIENT_OPCODES[opcode]
  1308. else
  1309. return "OPCODE_UNKNOWN"
  1310. end
  1311. end
  1312. function resolveServerOpcodeName(opcode)
  1313. if (SERVER_OPCODES[opcode] ~= nil) then
  1314. return SERVER_OPCODES[opcode]
  1315. else
  1316. return "OPCODE_UNKNOWN"
  1317. end
  1318. end
  1319. function addOpcodeData(clientPacket, opcode, tree, buffer, pinfoNumber, pinfoVisited)
  1320. if (clientPacket == 1) then
  1321. addOpcodeDataClient(opcode, tree, buffer, pinfoNumber, pinfoVisited)
  1322. else
  1323. addOpcodeDataServer(opcode, tree, buffer, pinfoNumber, pinfoVisited)
  1324. end
  1325. end
  1326. -- TODO: search for clientStream.newPacket(
  1327. function addOpcodeDataClient(opcode, tree, buffer, pinfoNumber, pinfoVisited)
  1328. local packetLengthBuffer = rsc_getPacketLengthBuffer(buffer, 0)
  1329. local packetLength = rsc_readPacketLength(packetLengthBuffer)
  1330. -- Offset buffer by length size
  1331. buffer = buffer(packetLengthBuffer:len())
  1332. local clientOpcodeData = buffer(0, 1)
  1333. local opcodeName = resolveClientOpcodeName(clientOpcodeData:uint())
  1334. tree:add(clientPacketLength, packetLengthBuffer, packetLength)
  1335. local opcodeField = tree:add(clientOpcode, clientOpcodeData)
  1336. opcodeField:append_text(" (" .. opcodeName .. ")")
  1337. local clientOpcodeValue = clientOpcodeData:uint()
  1338. -- 0c -- CLIENT_OPCODE_CONNECT
  1339. if (clientOpcodeValue == 0) then
  1340. -- standalone, doesn't require data from other opcodes
  1341. local reconnectingField = opcodeField:add(clientConnectReconnecting, buffer(1, 1))
  1342. if buffer(1, 1):int() == 1 then
  1343. reconnectingField:append_text(" (yes)")
  1344. else
  1345. reconnectingField:append_text(" (no)")
  1346. end
  1347. opcodeField:add(clientConnectVersion, buffer(2, 4)) -- always 235
  1348. -- "encrypted field" only available intact in one known surviving replay,
  1349. -- but because it's a client function, more could be generated if desired.
  1350. local encryptedField = opcodeField:add(clientConnectEncrypted, buffer(6, buffer:len() - 6))
  1351. encryptedField:add("Contains XTEA keys, nonces, password, & username.")
  1352. encryptedField:add("Removed for privacy in almost all replays.")
  1353. -- 4c -- CLIENT_OPCODE_CAST_ON_INVENTORY_ITEM
  1354. elseif (clientOpcodeValue == 4) then
  1355. -- not standalone (unless you're OK not knowing what was in the slot)
  1356. -- requires inventory state
  1357. if pinfoVisited then
  1358. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  1359. else
  1360. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisPlayerInventory) }
  1361. end
  1362. local slotField = opcodeField:add(clientCastOnInventoryInventoryIndex, buffer(1, 2))
  1363. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(1, 2):uint(), 32767)]] .. ")")
  1364. local spellField = opcodeField:add(clientCastOnInventorySpellID, buffer(3, 2))
  1365. spellField:append_text(" (" .. SPELL_NAMES[buffer(3, 2):int()] .. ")")
  1366. -- 8c -- CLIENT_OPCODE_SEND_DUEL_SETTINGS
  1367. elseif (clientOpcodeValue == 8) then
  1368. -- standalone, doesn't require data from other opcodes
  1369. local retreatField = opcodeField:add(clientSendDuelSettingsRetreat, buffer(1, 1))
  1370. retreatField:append_text(" (" .. boolToEnglish(buffer(1, 1):int()) .. ")")
  1371. local magicField = opcodeField:add(clientSendDuelSettingsMagic, buffer(2, 1))
  1372. magicField:append_text(" (" .. boolToEnglish(buffer(2, 1):int()) .. ")")
  1373. local prayerField = opcodeField:add(clientSendDuelSettingsPrayer, buffer(3, 1))
  1374. prayerField:append_text(" (" .. boolToEnglish(buffer(3, 1):int()) .. ")")
  1375. local weaponsField = opcodeField:add(clientSendDuelSettingsWeapons, buffer(4, 1))
  1376. weaponsField:append_text(" (" .. boolToEnglish(buffer(4, 1):int()) .. ")")
  1377. -- 14c -- CLIENT_OPCODE_INTERACT_WITH_BOUNDARY
  1378. elseif (clientOpcodeValue == 14) then
  1379. opcodeField:add(clientInteractWithBoundaryXCoord, buffer(1, 2))
  1380. opcodeField:add(clientInteractWithBoundaryYCoord, buffer(3, 2))
  1381. local alignmentField = opcodeField:add(clientInteractWithBoundaryAlignment, buffer(5, 1))
  1382. alignmentField:append_text(" (" .. BOUNDARY_ALIGNMENTS[buffer(5, 1):int()] .. ")")
  1383. -- 16c -- CLIENT_OPCODE_WALK_AND_PERFORM_ACTION
  1384. elseif (clientOpcodeValue == 16) then
  1385. -- standalone, doesn't require data from other opcodes
  1386. opcodeField:add(clientWalkAndPerformActionX, buffer(1, 2))
  1387. opcodeField:add(clientWalkAndPerformActionY, buffer(3, 2))
  1388. if packetLength > 5 then
  1389. pathField = opcodeField:add("Client Calculated Path:")
  1390. pathField:add("Note: May deviate from actual path taken, especially if player interrupts path with new request.")
  1391. for i = 5, packetLength - 1, 2 do
  1392. if i > 5 then
  1393. pointsField:append_text(" then")
  1394. end
  1395. pointXBuffer = buffer(i, 1)
  1396. pointYBuffer = buffer(i + 1, 1)
  1397. pointsField = pathField:add("Walk to the point ")
  1398. if pointXBuffer:int() > 0 then
  1399. if pointXBuffer:int() > 1 then
  1400. pointsField:append_text(pointXBuffer:int() .. " tiles West")
  1401. else
  1402. pointsField:append_text("1 tile West")
  1403. end
  1404. elseif pointXBuffer:int() < 0 then
  1405. if pointXBuffer:int() < -1 then
  1406. pointsField:append_text((pointXBuffer:int() * -1) .. " tiles East")
  1407. else
  1408. pointsField:append_text("1 tile East")
  1409. end
  1410. end
  1411. if pointYBuffer:int() > 0 then
  1412. if pointXBuffer:int() ~= 0 then
  1413. if pointYBuffer:int() > 1 then
  1414. pointsField:append_text(" and " .. pointYBuffer:int() .. " tiles South")
  1415. else
  1416. pointsField:append_text(" and 1 tile South")
  1417. end
  1418. else
  1419. if pointYBuffer:int() > 1 then
  1420. pointsField:append_text(pointYBuffer:int() .. " tiles South")
  1421. else
  1422. pointsField:append_text("1 tile South")
  1423. end
  1424. end
  1425. elseif pointYBuffer:int() < 0 then
  1426. if pointXBuffer:int() ~= 0 then
  1427. if pointYBuffer:int() < -1 then
  1428. pointsField:append_text(" and " .. (pointYBuffer:int() * -1) .. " tiles North")
  1429. else
  1430. pointsField:append_text(" and 1 tile North")
  1431. end
  1432. else
  1433. if pointYBuffer:int() < -1 then
  1434. pointsField:append_text((pointYBuffer:int() * -1) .. " tiles North")
  1435. else
  1436. pointsField:append_text("1 tile North")
  1437. end
  1438. end
  1439. end
  1440. pointsField:add(clientWalkAndPerformActionPathX, pointXBuffer)
  1441. pointsField:add(clientWalkAndPerformActionPathY, pointYBuffer)
  1442. end
  1443. end
  1444. -- 22c -- CLIENT_OPCODE_BANK_WITHDRAW
  1445. elseif (clientOpcodeValue == 22) then
  1446. -- standalone, doesn't require data from other opcodes
  1447. local itemIDBuffer = buffer(1, 2)
  1448. local itemIDField = opcodeField:add(clientBankWithdrawItemID, itemIDBuffer)
  1449. itemIDField:append_text(" (" .. ITEM_NAMES[itemIDBuffer:uint()] .. ")")
  1450. opcodeField:add(clientBankWithdrawAmount, buffer(3, 4))
  1451. opcodeField:add(clientBankWithdrawMagicNumber, buffer(7, 4))
  1452. -- 23c -- CLIENT_OPCODE_BANK_DEPOSIT
  1453. elseif (clientOpcodeValue == 23) then
  1454. -- standalone, doesn't require data from other opcodes
  1455. local itemIDBuffer = buffer(1, 2)
  1456. local itemIDField = opcodeField:add(clientBankDepositItemID, itemIDBuffer)
  1457. itemIDField:append_text(" (" .. ITEM_NAMES[itemIDBuffer:uint()] .. ")")
  1458. opcodeField:add(clientBankDepositAmount, buffer(3, 4))
  1459. opcodeField:add(clientBankDepositMagicNumber, buffer(7, 4))
  1460. -- 29c -- CLIENT_OPCODE_SEND_COMBAT_STYLE
  1461. elseif (clientOpcodeValue == 29) then
  1462. -- standalone, doesn't require data from other opcodes
  1463. local combatStyleField = opcodeField:add(clientCombatStyle, buffer(1, 1))
  1464. local combatStyle = buffer(1, 1):uint()
  1465. if combatStyle == 0 then
  1466. combatStyleField:append_text(" (Controlled)")
  1467. elseif combatStyle == 1 then
  1468. combatStyleField:append_text(" (Aggressive)")
  1469. elseif combatStyle == 2 then
  1470. combatStyleField:append_text(" (Accurate)")
  1471. elseif combatStyle == 3 then
  1472. combatStyleField:append_text(" (Defensive)")
  1473. end
  1474. if pinfoNumber < 50 then
  1475. local explanationField = tree:add("This opcode existing this early into the login process is a result of RSC+ injecting it.")
  1476. explanationField:add("Authentically, the client cannot send this opcode unless the user is in combat and manually selects a combat style.")
  1477. explanationField:add("One of RSC+'s features was to remember what combat style the user was using last, as the server does not keep track")
  1478. explanationField:add("of that after logging out. RSC+ injecting it here maintained the user's preferred combat style across logins.")
  1479. end
  1480. -- 33c -- SERVER_OPCODE_SEND_STAKED_ITEMS
  1481. elseif (clientOpcodeValue == 33) then
  1482. -- standalone, doesn't require data from other opcodes
  1483. local itemCount = buffer(1, 1):int()
  1484. opcodeField:add(clientSendStakedItemsCount, buffer(1, 1))
  1485. local offset = 2
  1486. for i = 0, itemCount - 1 do
  1487. local itemId = buffer(offset, 2):int()
  1488. local itemIdField = opcodeField:add(clientSendStakedItemsItemID, buffer(offset, 2))
  1489. itemIdField:append_text(" (" .. ITEM_NAMES[itemId] .. ")")
  1490. itemIdField:add(clientSendStakedItemsItemAmount, buffer(offset + 2, 4))
  1491. offset = offset + 6
  1492. end
  1493. -- 38c -- CLIENT_OPCODE_SEND_COMMAND_STRING
  1494. elseif (clientOpcodeValue == 38) then
  1495. -- standalone, doesn't require data from other opcodes
  1496. local commandBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1497. opcodeField:add(clientSendCommandStringCommand, commandBuffer, rsc_readRSCString(commandBuffer))
  1498. -- 45c -- CLIENT_OPCODE_SEND_SLEEP_WORD
  1499. elseif (clientOpcodeValue == 45) then
  1500. local delaySleepWordBuffer = buffer(1, 1)
  1501. opcodeField:add(clientGuessSleepwordDelay, delaySleepWordBuffer)
  1502. local wordGuessBuffer = rsc_getRSCStringBuffer(buffer, 2)
  1503. local guessField = opcodeField:add(clientGuessSleepwordGuess, wordGuessBuffer, rsc_readRSCString(wordGuessBuffer))
  1504. -- TODO: can say if it was successful or not by looking ahead
  1505. -- 46c -- CLIENT_OPCODE_OFFER_TRADE_ITEM
  1506. elseif (clientOpcodeValue == 46) then
  1507. -- standalone, doesn't require data from other opcodes
  1508. local itemCount = buffer(1, 1):uint()
  1509. local itemCountField = opcodeField:add(clientOfferItemItemCount, buffer(1, 1))
  1510. for i = 0, itemCount - 1 do
  1511. local itemOfferedField = itemCountField:add("")
  1512. local itemIDBuffer = buffer(2 + i * 6, 2)
  1513. local itemStackCountBuffer = buffer(4 + i * 6, 4)
  1514. itemOfferedField:append_text(ITEM_NAMES[itemIDBuffer:uint()] .. " (" .. itemStackCountBuffer:uint() .. ")")
  1515. local itemIDField = itemOfferedField:add(clientOfferItemItemID, itemIDBuffer)
  1516. itemIDField:append_text(" (" .. ITEM_NAMES[itemIDBuffer:uint()] .. ")")
  1517. itemOfferedField:add(clientOfferItemItemStack, itemStackCountBuffer)
  1518. end
  1519. -- 50c -- CLIENT_OPCODE_CAST_NPC
  1520. elseif (clientOpcodeValue == 50) then
  1521. -- not standalone
  1522. -- need npc index <-> npc id mapping
  1523. -- load / save those values
  1524. if pinfoVisited then
  1525. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  1526. else
  1527. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisNpcsServer) }
  1528. end
  1529. local npcIDField = opcodeField:add(clientCastNPCNPCID, buffer(1, 2))
  1530. npcIDField:append_text(" (" .. NPC_NAMES[thisNpcsServer[buffer(1, 2):uint()]["npcId"]] .. ")")
  1531. local spellIDField = opcodeField:add(clientCastNPCSpellID, buffer(3, 2))
  1532. spellIDField:append_text(" (" .. SPELL_NAMES[buffer(3, 2):int()] .. ")")
  1533. -- 53c -- CLIENT_OPCODE_USE_ON_GROUND_ITEM
  1534. elseif (clientOpcodeValue == 53) then
  1535. -- not standalone (unless you're OK not knowing what was in the slot)
  1536. -- requires inventory state
  1537. if pinfoVisited then
  1538. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  1539. else
  1540. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisPlayerInventory) }
  1541. end
  1542. opcodeField:add(clientUseOnGroundItemXCoord, buffer(1, 2))
  1543. opcodeField:add(clientUseOnGroundItemYCoord, buffer(3, 2))
  1544. local groundItemIdField = opcodeField:add(clientUseOnGroundItemGroundItemID, buffer(5, 2))
  1545. groundItemIdField:append_text(" (" .. ITEM_NAMES[buffer(5, 2):uint()] .. ")")
  1546. local inventorySlotField = opcodeField:add(clientUseOnGroundItemInventorySlot, buffer(7, 2))
  1547. inventorySlotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(7, 2):uint(), 32767)]] .. ")")
  1548. -- 59c -- CLIENT_OPCODE_ADMIN_TELEPORT_TO_TILE_PROBABLY
  1549. elseif (clientOpcodeValue == 59) then
  1550. -- standalone, doesn't require data from other opcodes
  1551. opcodeField:add(clientAdminTeleportXCoord, buffer(1, 2))
  1552. opcodeField:add(clientAdminTeleportYCoord, buffer(3, 2))
  1553. -- 60c -- CLIENT_OPCODE_ENABLE_PRAYER
  1554. elseif (clientOpcodeValue == 60) then
  1555. -- standalone, doesn't require data from other opcodes
  1556. prayerField = opcodeField:add(clientPrayerOnPrayer, buffer(1, 1))
  1557. prayerField:append_text(" (" .. PRAYER_NAMES[buffer(1, 1):uint()] .. ")")
  1558. -- 64c -- CLIENT_OPCODE_SEND_PRIVACY_SETTINGS
  1559. elseif (clientOpcodeValue == 64) then
  1560. -- standalone, doesn't require data from other opcodes
  1561. opcodeField:add(clientSendPrivacySettingsChat, buffer(1, 1))
  1562. opcodeField:add(clientSendPrivacySettingsPrivate, buffer(2, 1))
  1563. opcodeField:add(clientSendPrivacySettingsTrade, buffer(3, 1))
  1564. opcodeField:add(clientSendPrivacySettingsDuel, buffer(4, 1))
  1565. -- 79c -- CLIENT_OPCODE_INTERACT_WITH_SCENERY2
  1566. elseif (clientOpcodeValue == 79) then
  1567. -- standalone, doesn't require data from other opcodes
  1568. opcodeField:add(clientInteractWithScenery2XCoord, buffer(1, 2))
  1569. opcodeField:add(clientInteractWithScenery2YCoord, buffer(3, 2))
  1570. -- 90c -- CLIENT_OPCODE_ACTIVATE_INVENTORY_ITEM
  1571. elseif (clientOpcodeValue == 90) then
  1572. -- not standalone (unless you're OK not knowing what was in the slot)
  1573. -- requires inventory state
  1574. if pinfoVisited then
  1575. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  1576. else
  1577. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisPlayerInventory) }
  1578. end
  1579. local slotField = opcodeField:add(clientActivateInventoryItemSlot, buffer(1, 2))
  1580. slotField:append_text(" (" .. ITEM_NAMES[bit.band(thisPlayerInventory[buffer(1, 2):uint()], 32767)] .. ")")
  1581. -- 91c -- CLIENT_OPCODE_COMBINE_INVENTORY_ITEMS
  1582. elseif (clientOpcodeValue == 91) then
  1583. -- not standalone (unless you're OK not knowing what was in the slot)
  1584. -- requires inventory state
  1585. if pinfoVisited then
  1586. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  1587. else
  1588. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisPlayerInventory) }
  1589. end
  1590. local slotField = opcodeField:add(clientCombineInventorySlot1, buffer(1, 2))
  1591. slotField:append_text(" (" .. ITEM_NAMES[bit.band(thisPlayerInventory[buffer(1, 2):uint()], 32767)] .. ")")
  1592. local slotField = opcodeField:add(clientCombineInventorySlot2, buffer(3, 2))
  1593. slotField:append_text(" (" .. ITEM_NAMES[bit.band(thisPlayerInventory[buffer(3, 2):uint()], 32767)] .. ")")
  1594. -- 99c -- CLIENT_OPCODE_CAST_ON_SCENERY
  1595. elseif (clientOpcodeValue == 99) then
  1596. -- standalone, doesn't require data from other opcodes
  1597. opcodeField:add(clientCastOnSceneryXCoord, buffer(1, 2))
  1598. opcodeField:add(clientCastOnSceneryYCoord, buffer(3, 2))
  1599. local spellField = opcodeField:add(clientCastOnScenerySpellID, buffer(5, 2))
  1600. spellField:append_text(" (" .. SPELL_NAMES[buffer(5, 2):int()] .. ")")
  1601. -- 103c -- CLIENT_SEND_DUEL_REQUEST
  1602. elseif (clientOpcodeValue == 103) then
  1603. -- not standalone, would like to know which player has which PID
  1604. if pinfoVisited then
  1605. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  1606. else
  1607. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  1608. end
  1609. local targetField = opcodeField:add(clientSendDuelRequest, buffer(1, 2))
  1610. targetField:append_text(" (" .. thisPlayerServer[buffer(1, 2):int()]["displayName"] .. ")")
  1611. -- 111c -- CLIENT_OPCODE_SEND_CLIENT_SETTINGS
  1612. elseif (clientOpcodeValue == 111) then
  1613. -- standalone, doesn't require data from other opcodes
  1614. local optionField = opcodeField:add(clientSetting, buffer(1, 1))
  1615. optionField:append_text(" (" .. OPTION_NAMES[buffer(1, 1):int()] .. ")")
  1616. opcodeField:add(clientSettingValue, buffer(2, 1))
  1617. -- 113c -- CLIENT_OPCODE_USE_WITH_PLAYER
  1618. elseif (clientOpcodeValue == 113) then
  1619. -- not standalone, would like to know which player has which PID & what item they are using
  1620. if pinfoVisited then
  1621. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber][1]
  1622. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][2])
  1623. else
  1624. thisGameStateValuesAtThisTime[pinfoNumber] = { thisPlayerServer[buffer(1, 2):int()]["displayName"], dereferenceList(thisPlayerInventory) }
  1625. end
  1626. local targetField = opcodeField:add(clientUseOnPlayerPID, buffer(1, 2))
  1627. targetField:append_text(" (" .. thisPlayerServer[buffer(1, 2):int()]["displayName"] .. ")")
  1628. local slotField = opcodeField:add(clientUseOnPlayerSlot, buffer(3, 2))
  1629. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(3, 2):uint(), 32767)]] .. ")")
  1630. -- 115c -- CLIENT_USE_WITH_SCENERY
  1631. elseif (clientOpcodeValue == 115) then
  1632. -- not standalone, would like to know what item they are using
  1633. if pinfoVisited then
  1634. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1635. else
  1636. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisPlayerInventory)
  1637. end
  1638. opcodeField:add(clientUseOnSceneryX, buffer(1, 2))
  1639. opcodeField:add(clientUseOnSceneryY, buffer(3, 2))
  1640. local slotField = opcodeField:add(clientUseOnScenerySlot, buffer(5, 2))
  1641. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(5, 2):uint(), 32767)]] .. ")")
  1642. -- 116c -- CLIENT_OPCODE_SELECT_DIALOGUE_OPTION
  1643. elseif (clientOpcodeValue == 116) then
  1644. -- not standalone
  1645. -- requires thisOptionCache
  1646. if pinfoVisited then
  1647. thisOptionCache = thisGameStateValuesAtThisTime[pinfoNumber]
  1648. else
  1649. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisOptionCache)
  1650. end
  1651. local optionBuffer = buffer(1, 1)
  1652. local optionField = opcodeField:add(clientOption, optionBuffer)
  1653. optionField:append_text(" (" .. thisOptionCache[optionBuffer:uint()] .. ")")
  1654. -- 127c -- CLIENT_OPCODE_INTERACT_WITH_BOUNDARY2
  1655. elseif (clientOpcodeValue == 127) then
  1656. -- standalone, doesn't require data from other opcodes
  1657. opcodeField:add(clientInteractWithBoundary2XCoord, buffer(1, 2))
  1658. opcodeField:add(clientInteractWithBoundary2YCoord, buffer(3, 2))
  1659. local alignmentField = opcodeField:add(clientInteractWithBoundary2Alignment, buffer(5, 1))
  1660. alignmentField:append_text(" (" .. BOUNDARY_ALIGNMENTS[buffer(5, 1):int()] .. ")")
  1661. -- 132c -- CLIENT_OPCODE_ADD_IGNORE
  1662. elseif (clientOpcodeValue == 132) then
  1663. -- standalone, doesn't require data from other opcodes
  1664. local ignoreNameBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1665. opcodeField:add(clientAddIgnoreName, ignoreNameBuffer, rsc_readRSCString(ignoreNameBuffer))
  1666. -- 135c -- CLIENT_OPCODE_USE_ON_NPC
  1667. elseif (clientOpcodeValue == 135) then
  1668. -- not standalone, would like to know which player has which PID & what item they are using
  1669. if pinfoVisited then
  1670. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  1671. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][2])
  1672. else
  1673. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisNpcsServer), dereferenceList(thisPlayerInventory) }
  1674. end
  1675. -- TODO: didn't check the order of these yet
  1676. local npcIDField = opcodeField:add(clientUseOnNPCNPCID, buffer(1, 2))
  1677. npcIDField:append_text(" (" .. NPC_NAMES[thisNpcsServer[buffer(1, 2):uint()]["npcId"]] .. ")")
  1678. local slotField = opcodeField:add(clientUseOnNPCSlot, buffer(3, 2))
  1679. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(3, 2):uint(), 32767)]] .. ")")
  1680. -- 136c -- CLIENT_OPCODE_INTERACT_WITH_SCENERY
  1681. elseif (clientOpcodeValue == 136) then
  1682. -- standalone, doesn't require data from other opcodes
  1683. opcodeField:add(clientInteractWithSceneryX, buffer(1, 2))
  1684. opcodeField:add(clientInteractWithSceneryY, buffer(3, 2))
  1685. -- 137c -- CLIENT_OPCODE_CAST_ON_SELF
  1686. elseif (clientOpcodeValue == 137) then
  1687. -- standalone, doesn't require data from other opcodes
  1688. local spellField = opcodeField:add(clientCastOnSelfSpell, buffer(1, 2))
  1689. spellField:append_text(" (" .. SPELL_NAMES[buffer(1, 2):int()] .. ")")
  1690. -- 142c -- CLIENT_OPCODE_AGREE_TO_TRADE
  1691. elseif (clientOpcodeValue == 142) then
  1692. -- not standalone, would like to know which player has which PID
  1693. if pinfoVisited then
  1694. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  1695. else
  1696. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  1697. end
  1698. local targetField = opcodeField:add(clientAgreeToTradePID, buffer(1, 2))
  1699. targetField:append_text(" (" .. thisPlayerServer[buffer(1, 2):int()]["displayName"] .. ")")
  1700. -- 153c -- CLIENT_OPCODE_TALK_TO_NPC
  1701. elseif (clientOpcodeValue == 153) then
  1702. -- not standalone, would like to know which NPC player is talking to
  1703. if pinfoVisited then
  1704. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1705. else
  1706. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisNpcsServer)
  1707. end
  1708. local npcIDField = opcodeField:add(clientTalkToNPCID, buffer(1, 2))
  1709. npcIDField:append_text(" (" .. NPC_NAMES[thisNpcsServer[buffer(1, 2):uint()]["npcId"]] .. ")")
  1710. -- 158c -- CLIENT_OPCODE_CAST_ON_GROUND
  1711. elseif (clientOpcodeValue == 158) then
  1712. -- standalone, doesn't require data from other opcodes
  1713. opcodeField:add(clientCastOnGroundXCoord, buffer(1, 2))
  1714. opcodeField:add(clientCastOnGroundYCoord, buffer(3, 2))
  1715. local spellField = opcodeField:add(clientCastOnGroundSpell, buffer(5, 2))
  1716. spellField:append_text(" (" .. SPELL_NAMES[buffer(5, 2):int()] .. ")")
  1717. -- 161c -- CLIENT_OPCODE_USE_WITH_BOUNDARY
  1718. elseif (clientOpcodeValue == 161) then
  1719. -- not standalone, would like to know what item the player is using
  1720. if pinfoVisited then
  1721. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1722. else
  1723. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisPlayerInventory)
  1724. end
  1725. opcodeField:add(clientUseWithBoundaryXCoord, buffer(1, 2))
  1726. opcodeField:add(clientUseWithBoundaryYCoord, buffer(3, 2))
  1727. opcodeField:add(clientUseWithBoundaryAlignment, buffer(5, 1))
  1728. local slotField = opcodeField:add(clientUseWithBoundarySlot, buffer(6, 2))
  1729. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(6, 2):uint(), 32767)]] .. ")")
  1730. -- 165c -- CLIENT_OPCODE_FOLLOW_PLAYER
  1731. elseif (clientOpcodeValue == 165) then
  1732. -- not standalone, would like to know which player has which PID
  1733. if pinfoVisited then
  1734. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  1735. else
  1736. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  1737. end
  1738. local targetField = opcodeField:add(clientFollowPlayerPID, buffer(1, 2))
  1739. targetField:append_text(" (" .. thisPlayerServer[buffer(1, 2):int()]["displayName"] .. ")")
  1740. -- 167c -- CLIENT_OPCODE_REMOVE_FRIEND
  1741. elseif (clientOpcodeValue == 167) then
  1742. -- standalone, doesn't require data from other opcodes
  1743. local friendBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1744. opcodeField:add(clientRemoveFriendName, friendBuffer, rsc_readRSCString(friendBuffer))
  1745. -- 169c -- CLIENT_OPCODE_EQUIP_ITEM
  1746. elseif (clientOpcodeValue == 169) then
  1747. -- not standalone, would like to know what item the player is equipping
  1748. if pinfoVisited then
  1749. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1750. else
  1751. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisPlayerInventory)
  1752. end
  1753. local slotField = opcodeField:add(clientEquipItemSlot, buffer(1, 2))
  1754. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(1, 2):uint(), 32767)]] .. ")")
  1755. -- 170c -- CLIENT_OPCODE_UNEQUIP_ITEM
  1756. elseif (clientOpcodeValue == 170) then
  1757. -- not standalone, would like to know what item the player is unequipping
  1758. if pinfoVisited then
  1759. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1760. else
  1761. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisPlayerInventory)
  1762. end
  1763. local slotField = opcodeField:add(clientUnequipItemItem, buffer(1, 2))
  1764. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(1, 2):uint(), 32767)]] .. ")")
  1765. -- 171c -- CLIENT_OPCODE_ATTACK_PLAYER
  1766. elseif (clientOpcodeValue == 171) then
  1767. -- not standalone, would like to know which player has which PID
  1768. if pinfoVisited then
  1769. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  1770. else
  1771. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  1772. end
  1773. local targetField = opcodeField:add(clientAttackPlayerTargetPID, buffer(1, 2))
  1774. targetField:append_text(" (" .. thisPlayerServer[buffer(1, 2):int()]["displayName"] .. ")")
  1775. -- 180c -- CLIENT_OPCODE_CAST_ON_BOUNDARY
  1776. elseif (clientOpcodeValue == 180) then
  1777. -- standalone, doesn't require data from other opcodes
  1778. opcodeField:add(clientCastOnBoundaryXCoord, buffer(1, 2))
  1779. opcodeField:add(clientCastOnBoundaryYCoord, buffer(3, 2))
  1780. opcodeField:add(clientCastOnBoundaryAlignment, buffer(5, 1))
  1781. local spellField = opcodeField:add(clientCastOnGroundSpell, buffer(6, 2))
  1782. spellField:append_text(" (" .. SPELL_NAMES[buffer(6, 2):int()] .. ")")
  1783. -- 187c -- CLIENT_OPCODE_WALK
  1784. elseif (clientOpcodeValue == 187) then
  1785. -- standalone, doesn't require data from other opcodes
  1786. opcodeField:add(clientWalkX, buffer(1, 2))
  1787. opcodeField:add(clientWalkY, buffer(3, 2))
  1788. if packetLength > 5 then
  1789. pathField = opcodeField:add("Client Calculated Path:")
  1790. for i = 5, packetLength - 1, 2 do
  1791. if i > 5 then
  1792. pointsField:append_text(" then")
  1793. end
  1794. pointXBuffer = buffer(i, 1)
  1795. pointYBuffer = buffer(i + 1, 1)
  1796. pointsField = pathField:add("Walk to the point ")
  1797. if pointXBuffer:int() > 0 then
  1798. if pointXBuffer:int() > 1 then
  1799. pointsField:append_text(pointXBuffer:int() .. " tiles West")
  1800. else
  1801. pointsField:append_text("1 tile West")
  1802. end
  1803. elseif pointXBuffer:int() < 0 then
  1804. if pointXBuffer:int() < -1 then
  1805. pointsField:append_text((pointXBuffer:int() * -1) .. " tiles East")
  1806. else
  1807. pointsField:append_text("1 tile East")
  1808. end
  1809. end
  1810. if pointYBuffer:int() > 0 then
  1811. if pointXBuffer:int() ~= 0 then
  1812. if pointYBuffer:int() > 1 then
  1813. pointsField:append_text(" and " .. pointYBuffer:int() .. " tiles South")
  1814. else
  1815. pointsField:append_text(" and 1 tile South")
  1816. end
  1817. else
  1818. if pointYBuffer:int() > 1 then
  1819. pointsField:append_text(pointYBuffer:int() .. " tiles South")
  1820. else
  1821. pointsField:append_text("1 tile South")
  1822. end
  1823. end
  1824. elseif pointYBuffer:int() < 0 then
  1825. if pointXBuffer:int() ~= 0 then
  1826. if pointYBuffer:int() < -1 then
  1827. pointsField:append_text(" and " .. (pointYBuffer:int() * -1) .. " tiles North")
  1828. else
  1829. pointsField:append_text(" and 1 tile North")
  1830. end
  1831. else
  1832. if pointYBuffer:int() < -1 then
  1833. pointsField:append_text((pointYBuffer:int() * -1) .. " tiles North")
  1834. else
  1835. pointsField:append_text("1 tile North")
  1836. end
  1837. end
  1838. end
  1839. pointsField:add(clientWalkPathX, pointXBuffer)
  1840. pointsField:add(clientWalkPathY, pointYBuffer)
  1841. end
  1842. end
  1843. -- 190c -- CLIENT_OPCODE_ATTACK_NPC
  1844. elseif (clientOpcodeValue == 190) then
  1845. -- not standalone, would like to know which NPC player is attacking
  1846. if pinfoVisited then
  1847. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1848. else
  1849. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisNpcsServer)
  1850. end
  1851. local npcIDField = opcodeField:add(clientAttackNPCID, buffer(1, 2))
  1852. npcIDField:append_text(" (" .. NPC_NAMES[thisNpcsServer[buffer(1, 2):uint()]["npcId"]] .. ")")
  1853. -- 195c -- CLIENT_OPCODE_ADD_FRIEND
  1854. elseif (clientOpcodeValue == 195) then
  1855. -- standalone, doesn't require data from other opcodes
  1856. local friendBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1857. opcodeField:add(clientAddFriendName, friendBuffer, rsc_readRSCString(friendBuffer))
  1858. -- 202c -- CLIENT_OPCODE_INTERACT_NPC
  1859. elseif (clientOpcodeValue == 202) then
  1860. -- not standalone, would like to know which NPC player is interacting with
  1861. if pinfoVisited then
  1862. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1863. else
  1864. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisNpcsServer)
  1865. end
  1866. local npcIDField = opcodeField:add(clientInteractNPCID, buffer(1, 2))
  1867. npcIDField:append_text(" (" .. NPC_NAMES[thisNpcsServer[buffer(1, 2):uint()]["npcId"]] .. ")")
  1868. -- 206c -- CLIENT_OPCODE_SEND_REPORT
  1869. elseif (clientOpcodeValue == 206) then
  1870. -- standalone, doesn't require data from other opcodes
  1871. local troubleMakerBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1872. offset = 1 + troubleMakerBuffer:len()
  1873. opcodeField:add(clientSendReportName, troubleMakerBuffer, rsc_readRSCString(troubleMakerBuffer))
  1874. local reportReasonField = opcodeField:add(clientSendReportReason, buffer(offset, 1))
  1875. reportReasonField:append_text(" (" .. REPORT_REASONS[buffer(offset, 1):int()] .. ")")
  1876. local muteField = opcodeField:add(clientSendReportMute, buffer(offset + 1, 1))
  1877. if buffer(offset + 1, 1):int() == 1 then
  1878. muteField:append_text(" (yes)")
  1879. else
  1880. muteField:append_text(" (no)")
  1881. end
  1882. -- 216c -- CLIENT_OPCODE_SEND_CHAT_MESSAGE
  1883. elseif (clientOpcodeValue == 216) then
  1884. offset = 1
  1885. local method220Cache = method220(buffer, offset)
  1886. local messageLengthBuffer = method220Cache[1]
  1887. local messageLength = method220Cache[2]
  1888. opcodeField:add(clientSendChatMessageLength, messageLengthBuffer, messageLength)
  1889. offset = offset + method220Cache[3]
  1890. local method240Cache = method240(buffer, 0, offset, messageLength)
  1891. local scrambledChatMessageBufferLength = method240Cache[1]
  1892. local chatMessageInts = method240Cache[2]
  1893. opcodeField:add(clientSendChatMessageMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  1894. offset = offset + scrambledChatMessageBufferLength
  1895. -- 218c -- CLIENT_OPCODE_SEND_PRIVATE_MESSAGE
  1896. elseif (clientOpcodeValue == 218) then
  1897. local recipientNameBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1898. offset = 1 + recipientNameBuffer:len()
  1899. opcodeField:add(clientSendPrivateMessageRecipient, recipientNameBuffer, rsc_readRSCString(recipientNameBuffer))
  1900. local method220Cache = method220(buffer, offset)
  1901. local messageLengthBuffer = method220Cache[1]
  1902. local messageLength = method220Cache[2]
  1903. opcodeField:add(clientSendPrivateMessageLength, messageLengthBuffer, messageLength)
  1904. offset = offset + method220Cache[3]
  1905. local method240Cache = method240(buffer, 0, offset, messageLength)
  1906. local scrambledChatMessageBufferLength = method240Cache[1]
  1907. local chatMessageInts = method240Cache[2]
  1908. opcodeField:add(clientSendPrivateMessageMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  1909. offset = offset + scrambledChatMessageBufferLength
  1910. -- 221c -- CLIENT_OPCODE_SELL_TO_SHOP
  1911. elseif (clientOpcodeValue == 221) then
  1912. -- standalone, doesn't require data from other opcodes
  1913. local itemField = opcodeField:add(clientSellToShopItemId, buffer(1, 2))
  1914. itemField:append_text(" (" .. ITEM_NAMES[buffer(1, 2):uint()] .. ")")
  1915. opcodeField:add(clientSellToShopShopAmount, buffer(3, 2))
  1916. opcodeField:add(clientSellToShopSellAmount, buffer(5, 2))
  1917. -- 229c -- CLIENT_OPCODE_CAST_PVP
  1918. elseif (clientOpcodeValue == 229) then
  1919. -- not standalone, would like to know which player has which PID
  1920. if pinfoVisited then
  1921. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  1922. else
  1923. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  1924. end
  1925. local targetField = opcodeField:add(clientCastPVPTargetPID, buffer(1, 2))
  1926. targetField:append_text(" (" .. thisPlayerServer[buffer(1, 2):int()]["displayName"] .. ")")
  1927. local spellField = opcodeField:add(clientCastPVPSpellID, buffer(3, 2))
  1928. spellField:append_text(" (" .. SPELL_NAMES[buffer(3, 2):int()] .. ")")
  1929. -- 235c -- CLIENT_OPCODE_CHANGE_APPEARANCE
  1930. elseif (clientOpcodeValue == 235) then
  1931. -- standalone, doesn't require data from other opcodes
  1932. local headRestrictionsField = opcodeField:add(clientChangeAppearanceHeadRestrictions, buffer(1, 1))
  1933. if (buffer(1, 1):uint() == 1) then
  1934. headRestrictionsField:append_text(" (Beard Allowed)")
  1935. elseif (buffer(1, 1):uint() == 2) then
  1936. headRestrictionsField:append_text(" (Beard Not Allowed)")
  1937. end
  1938. local headTypeField = opcodeField:add(clientChangeAppearanceHeadType, buffer(2, 1))
  1939. if (buffer(2, 1):uint() == 0) then
  1940. headTypeField:append_text(" (?)")
  1941. elseif (buffer(2, 1):uint() == 3) then
  1942. headTypeField:append_text(" (?)")
  1943. elseif (buffer(2, 1):uint() == 5) then
  1944. headTypeField:append_text(" (?)")
  1945. elseif (buffer(2, 1):uint() == 6) then
  1946. headTypeField:append_text(" (?)")
  1947. elseif (buffer(2, 1):uint() == 7) then
  1948. headTypeField:append_text(" (Bald normal type)")
  1949. end
  1950. local bodyTypeField = opcodeField:add(clientChangeAppearanceBodyType, buffer(3, 1))
  1951. if (buffer(3, 1):uint() == 1) then
  1952. bodyTypeField:append_text(" (Flat Chest)")
  1953. elseif (buffer(3, 1):uint() == 4) then
  1954. bodyTypeField:append_text(" (Busty Chest)")
  1955. end
  1956. -- Always 2, even in very old versions of client, including v40, v127, v204, & v233
  1957. opcodeField:add(clientChangeAppearanceAlways2, buffer(4, 1))
  1958. local hairColourField = opcodeField:add(clientChangeAppearanceHairColour, buffer(5, 1))
  1959. hairColourField:append_text(" (HTML Colour: " .. HAIR_COLOURS_STRING[buffer(5, 1):uint()] .. ") (English Name: " .. HAIR_COLOUR_NAMES[buffer(5, 1):uint()] .. ")")
  1960. local topColourField = opcodeField:add(clientChangeAppearanceTopColour, buffer(6, 1))
  1961. topColourField:append_text(" (HTML Colour: " .. CLOTHING_COLOURS_STRING[buffer(6, 1):uint()] .. ") (English Name: " .. CLOTHING_COLOUR_NAMES[buffer(6, 1):uint()] .. ")")
  1962. local bottomColourField = opcodeField:add(clientChangeAppearenceBottomColour, buffer(7, 1))
  1963. bottomColourField:append_text(" (HTML Colour: " .. CLOTHING_COLOURS_STRING[buffer(7, 1):uint()] .. ") (English Name: " .. CLOTHING_COLOUR_NAMES[buffer(7, 1):uint()] .. ")")
  1964. local skinColourField = opcodeField:add(clientChangeAppearenceSkinColour, buffer(8, 1))
  1965. skinColourField:append_text(" (HTML Colour: " .. SKIN_COLOURS_STRING[buffer(8, 1):uint()] .. ") (English Name: " .. SKIN_COLOUR_NAMES[buffer(8, 1):uint()] .. ")")
  1966. -- 236c -- CLIENT_OPCODE_BUY_FROM_SHOP
  1967. elseif (clientOpcodeValue == 236) then
  1968. -- standalone, doesn't require data from other opcodes
  1969. local itemField = opcodeField:add(clientBuyFromShopItemId, buffer(1, 2))
  1970. itemField:append_text(" (" .. ITEM_NAMES[buffer(1, 2):uint()] .. ")")
  1971. opcodeField:add(clientBuyFromShopShopAmount, buffer(3, 2))
  1972. opcodeField:add(clientBuyFromShopSellAmount, buffer(5, 2))
  1973. -- 241c -- CLIENT_OPCODE_REMOVE_IGNORED
  1974. elseif (clientOpcodeValue == 241) then
  1975. -- standalone, doesn't require data from other opcodes
  1976. local exignoredBuffer = rsc_getRSCStringBuffer(buffer, 1)
  1977. opcodeField:add(clientExignoredName, exignoredBuffer, rsc_readRSCString(exignoredBuffer))
  1978. -- 246c -- CLIENT_OPCODE_DROP_ITEM
  1979. elseif (clientOpcodeValue == 246) then
  1980. -- not standalone, would like to know what item the player is unequipping
  1981. if pinfoVisited then
  1982. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber])
  1983. else
  1984. thisGameStateValuesAtThisTime[pinfoNumber] = dereferenceList(thisPlayerInventory)
  1985. end
  1986. local slotField = opcodeField:add(clientDropItemSlot, buffer(1, 2))
  1987. slotField:append_text(" (" .. ITEM_NAMES[thisPlayerInventory[bit.band(buffer(1, 2):uint(), 32767)]] .. ")")
  1988. -- 247c -- CLIENT_OPCODE_TAKE_GROUND_ITEM
  1989. elseif (clientOpcodeValue == 247) then
  1990. -- standalone, doesn't require data from other opcodes
  1991. opcodeField:add(clientTakeGroundItemXCoord, buffer(1, 2))
  1992. opcodeField:add(clientTakeGroundItemYCoord, buffer(3, 2))
  1993. local itemField = opcodeField:add(clientTakeGroundItemItemID, buffer(5, 2))
  1994. itemField:append_text(" (" .. ITEM_NAMES[buffer(5, 2):uint()] .. ")")
  1995. -- 249c -- CLIENT_OPCODE_CAST_ON_GROUND_ITEM
  1996. elseif (clientOpcodeValue == 249) then
  1997. -- standalone, doesn't require data from other opcodes
  1998. opcodeField:add(clientCastOnGroundItemXCoord, buffer(1, 2))
  1999. opcodeField:add(clientCastOnGroundItemYCoord, buffer(3, 2))
  2000. local itemField = opcodeField:add(clientCastOnGroundItemItemID, buffer(5, 2))
  2001. itemField:append_text(" (" .. ITEM_NAMES[buffer(5, 2):uint()] .. ")")
  2002. local spellField = opcodeField:add(clientCastOnGroundItemSpellID, buffer(7, 2))
  2003. spellField:append_text(" (" .. SPELL_NAMES[buffer(7, 2):int()] .. ")")
  2004. -- 254c -- CLIENT_OPCODE_DISABLE_PRAYER
  2005. elseif (clientOpcodeValue == 254) then
  2006. -- standalone, doesn't require data from other opcodes
  2007. local prayerField = opcodeField:add(clientPrayerOffPrayer, buffer(1, 1))
  2008. prayerField:append_text(" (" .. PRAYER_NAMES[buffer(1, 1):uint()] .. ")")
  2009. end
  2010. end
  2011. function addOpcodeDataServer(opcode, tree, buffer, pinfoNumber, pinfoVisited)
  2012. if (opcode == VIRTUAL_OPCODE_CONNECT) then
  2013. local loginResponse = buffer(0, 1)
  2014. tree:add(serverLoginResponse, loginResponse)
  2015. elseif (opcode == VIRTUAL_OPCODE_SERVER_METADATA) then
  2016. tree:add(clientPacketLength, buffer(0, 1))
  2017. dataFields = tree:add(clientOpcode, buffer(1, 1), VIRTUAL_OPCODE_SERVER_METADATA)
  2018. local opcodeName = resolveServerOpcodeName(serverOpcode)
  2019. dataFields:append_text(" (VIRTUAL_OPCODE_SERVER_METADATA)")
  2020. dataFields:add(serverMetadataLoginResponse, buffer(2, 4)) -- Login Response
  2021. dataFields:add(serverMetadataClientVersion, buffer(6, 4)) -- Client Version
  2022. dataFields:add(serverMetadataAuthenticClient, buffer(10, 4)) -- Authentic Client
  2023. dataFields:add(serverMetadataStartTime, buffer(14, 8)) -- Start Time (already in header)
  2024. offset = 26
  2025. -- Server Name
  2026. local recipientNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2027. offset = offset + recipientNameBuffer:len()
  2028. dataFields:add(serverMetadataServerName, recipientNameBuffer, rsc_readRSCString(recipientNameBuffer))
  2029. dataFields:add(serverMetadataWorldNumber, buffer(22, 4)) -- World Number
  2030. -- Username
  2031. local recipientNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2032. offset = offset + recipientNameBuffer:len()
  2033. dataFields:add(serverMetadataUsername, recipientNameBuffer, rsc_readRSCString(recipientNameBuffer))
  2034. -- Player's IP Address
  2035. local recipientNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2036. offset = offset + recipientNameBuffer:len()
  2037. dataFields:add(serverMetadataPlayerIP, recipientNameBuffer, rsc_readRSCString(recipientNameBuffer))
  2038. -- Reserved Bytes
  2039. if (buffer:len() - offset > 0) then
  2040. dataFields:add(serverMetadataReservedBytes, buffer(offset, buffer:len() - offset))
  2041. end
  2042. else
  2043. local packetLengthBuffer = rsc_getPacketLengthBuffer(buffer, 0)
  2044. local packetLength = rsc_readPacketLength(packetLengthBuffer)
  2045. -- Offset buffer by length size
  2046. buffer = buffer(packetLengthBuffer:len())
  2047. local serverOpcodeBuffer = buffer(packetOffset, 1)
  2048. local serverOpcode = serverOpcodeBuffer:uint()
  2049. local opcodeName = resolveServerOpcodeName(serverOpcode)
  2050. tree:add(clientPacketLength, packetLengthBuffer, packetLength)
  2051. local opcodeField = tree:add(clientOpcode, serverOpcodeBuffer)
  2052. opcodeField:append_text(" (" .. opcodeName .. ")")
  2053. -- 5 -- SERVER_OPCODE_QUEST_STATUS
  2054. if (serverOpcode == 5) then
  2055. -- standalone, doesn't require data from other opcodes
  2056. for i = 0, 49 do
  2057. local questField = opcodeField:add(serverQuests[i], buffer(i + 1, 1), buffer(i + 1, 1):int())
  2058. if (buffer(i + 1, 1):int() > 0) then
  2059. questField:append_text(" (done)")
  2060. else
  2061. questField:append_text(" (not done)")
  2062. end
  2063. end
  2064. -- 6 -- SERVER_OPCODE_UPDATE_STAKED_ITEMS_OPPONENT
  2065. elseif (serverOpcode == 6) then
  2066. -- standalone, doesn't require data from other opcodes
  2067. local itemCount = buffer(1, 1):int()
  2068. opcodeField:add(serverUpdateStakedItemsOpponentNumberOfItemsStaked, buffer(1, 1))
  2069. local offset = 2
  2070. for i = 0, itemCount - 1 do
  2071. local itemId = buffer(offset, 2):int()
  2072. local itemIdField = opcodeField:add(serverUpdateStakedItemsOpponentItemId, buffer(offset, 2))
  2073. itemIdField:append_text(" (" .. ITEM_NAMES[itemId] .. ")")
  2074. itemIdField:add(serverUpdateStakedItemsOpponentItemStack, buffer(offset + 2, 4))
  2075. offset = offset + 6
  2076. end
  2077. -- 15 -- SERVER_OPCODE_UPDATE_TRADE_ACCEPTANCE
  2078. elseif (serverOpcode == 15) then
  2079. -- standalone, doesn't require data from other opcodes
  2080. local tradeAcceptanceField = opcodeField:add(serverUpdateTradeAcceptance, buffer(1, 1))
  2081. tradeAcceptanceField:append_text(" (" .. boolToEnglish(buffer(1, 1):int()) .. ")")
  2082. tradeAcceptanceField:add("Note: actually in all known replays, this field is always equal to zero.")
  2083. -- 20 -- SERVER_OPCODE_CONFIRM_TRADE
  2084. elseif (serverOpcode == 20) then
  2085. -- standalone, doesn't require data from other opcodes
  2086. local recipientNameBuffer = rsc_getRSCStringBuffer(buffer, 1)
  2087. offset = 1 + recipientNameBuffer:len()
  2088. opcodeField:add(serverConfirmTradeRecipientName, recipientNameBuffer, rsc_readRSCString(recipientNameBuffer))
  2089. local itemsReceivedCount = buffer(offset, 1)
  2090. local itemsReceivedCountField = opcodeField:add(serverConfirmTradeItemCount, itemsReceivedCount)
  2091. for i = 0, itemsReceivedCount:int() - 1 do
  2092. local itemId = buffer(offset + 1 + i * 6, 2)
  2093. local itemIdField = itemsReceivedCountField:add(serverConfirmTradeItemID, itemId)
  2094. itemIdField:append_text(" (" .. ITEM_NAMES[itemId:int()] .. ")")
  2095. itemIdField:add(serverConfirmTradeItemStack, buffer(offset + 3 + i * 6, 4))
  2096. end
  2097. offset = offset + itemsReceivedCount:int() * 6 + 1
  2098. local recipientItemCount = buffer(offset, 1)
  2099. local recipientItemCountField = opcodeField:add(serverConfirmTradeRecipientItemCount, recipientItemCount)
  2100. for i = 0, recipientItemCount:int() - 1 do
  2101. local itemId = buffer(offset + 1 + i * 6, 2)
  2102. local itemIdField = recipientItemCountField:add(serverConfirmTradeRecipientItemID, itemId)
  2103. itemIdField:append_text(" (" .. ITEM_NAMES[itemId:int()] .. ")")
  2104. itemIdField:add(serverConfirmTradeRecipientItemStack, buffer(offset + 3 + i * 6, 4))
  2105. end
  2106. -- 25 -- SERVER_OPCODE_FLOOR_SET
  2107. elseif (serverOpcode == 25) then
  2108. -- standalone, doesn't require data from other opcodes
  2109. -- it's actually the opcode that sets many of the values we end up needing to cache
  2110. local localPlayerServerIndexBuffer = buffer(1, 2)
  2111. thisLocalPlayerServerIndex = localPlayerServerIndexBuffer:int()
  2112. local planeWidthBuffer = buffer(3, 2)
  2113. thisPlaneWidth = planeWidthBuffer:int()
  2114. local planeHeightBuffer = buffer(5, 2)
  2115. thisPlaneHeight = planeHeightBuffer:int()
  2116. local planeFloorBuffer = buffer(7, 2)
  2117. thisPlaneFloor = planeFloorBuffer:int()
  2118. local planeDistanceBetweenFloorsBuffer = buffer(9, 2)
  2119. thisPlaneDistanceBetweenFloors = planeDistanceBetweenFloorsBuffer:int()
  2120. thisPlaneHeight = thisPlaneHeight - (thisPlaneFloor * thisPlaneDistanceBetweenFloors)
  2121. opcodeField:add(serverFloorSetLocalPlayerServerIndex, localPlayerServerIndexBuffer)
  2122. opcodeField:add(serverFloorSetPlaneWidth, planeWidthBuffer)
  2123. local planeHeightField = opcodeField:add(serverFloorSetPlaneHeight, planeHeightBuffer, thisPlaneHeight)
  2124. planeHeightField:append_text(" (takes into account the Floor & Distance Between Floors)")
  2125. opcodeField:add(serverFloorSetPlaneFloor, planeFloorBuffer)
  2126. opcodeField:add(serverFloorSetPlaneDistanceBetweenFloors, planeDistanceBetweenFloorsBuffer)
  2127. -- 30 -- SERVER_OPCODE_SYNC_DUEL_SETTINGS
  2128. elseif (serverOpcode == 30) then
  2129. -- standalone, doesn't require data from other opcodes
  2130. local retreatField = opcodeField:add(serverSyncDuelSettingsRetreat, buffer(1, 1))
  2131. retreatField:append_text(" (" .. boolToEnglish(buffer(1, 1):int()) .. ")")
  2132. local magicField = opcodeField:add(serverSyncDuelSettingsMagic, buffer(2, 1))
  2133. magicField:append_text(" (" .. boolToEnglish(buffer(2, 1):int()) .. ")")
  2134. local prayerField = opcodeField:add(serverSyncDuelSettingsPrayer, buffer(3, 1))
  2135. prayerField:append_text(" (" .. boolToEnglish(buffer(3, 1):int()) .. ")")
  2136. local weaponsField = opcodeField:add(serverSyncDuelSettingsWeapons, buffer(4, 1))
  2137. weaponsField:append_text(" (" .. boolToEnglish(buffer(4, 1):int()) .. ")")
  2138. -- 33 -- SERVER_OPCODE_UPDATE_XP
  2139. elseif (serverOpcode == 33) then
  2140. -- standalone, doesn't require data from other opcodes
  2141. local skillField = opcodeField:add(serverUpdateXPSkill, buffer(1, 1))
  2142. skillField:append_text(" (" .. SKILL_NAMES[buffer(1, 1):int()] .. ")")
  2143. opcodeField:add(serverUpdateXPXP, buffer(2, 4), buffer(2, 4):int() / 4)
  2144. -- 36 -- SERVER_OPCODE_DISPLAY_TELEPORT_BUBBLE
  2145. elseif (serverOpcode == 36) then
  2146. -- not standalone
  2147. -- requires thisLocalRegionX and thisLocalRegionY
  2148. -- load / save those values
  2149. if pinfoVisited then
  2150. thisLocalRegionX = thisGameStateValuesAtThisTime[pinfoNumber][1]
  2151. thisLocalRegionY = thisGameStateValuesAtThisTime[pinfoNumber][2]
  2152. else
  2153. thisGameStateValuesAtThisTime[pinfoNumber] = { thisLocalRegionX, thisLocalRegionY }
  2154. end
  2155. -- parse opcode data
  2156. for i = 0, math.floor(buffer:len() / 3) - 1 do
  2157. local bubbleTypeBuffer = buffer(1 + i * 3, 1)
  2158. local bubbleTypeField = opcodeField:add(serverDisplayTeleportBubbleType, bubbleTypeBuffer)
  2159. bubbleTypeField:append_text(" (" .. BUBBLE_TYPE_NAMES[bubbleTypeBuffer:int()] .. ")")
  2160. opcodeField:add(serverDisplayTeleportBubbleXCoord, buffer(2 + i * 3, 1), buffer(2 + i * 3, 1):int() + thisLocalRegionX + 2) -- TODO: investigate why there is + 2
  2161. opcodeField:add(serverDisplayTeleportBubbleYCoord, buffer(3 + i * 3, 1), buffer(3 + i * 3, 1):int() + thisLocalRegionY - 1) -- TODO: investigate why there is - 1
  2162. end
  2163. -- 42 -- SERVER_OPCODE_OPEN_BANK
  2164. elseif (serverOpcode == 42) then
  2165. -- standalone, doesn't require data from other opcodes
  2166. local itemsInBank = buffer(1, 1)
  2167. local itemsMaxInBank = buffer(2, 1)
  2168. local offset = 3
  2169. local itemsInBankField = opcodeField:add(serverOpenBankItemCount, itemsInBank)
  2170. local maxField = opcodeField:add(serverOpenBankMaximumItemCount, itemsMaxInBank)
  2171. maxField:add("Note: This value is always 192, would be 48 on a F2P world if they existed")
  2172. for i = 0, itemsInBank:uint() - 1 do
  2173. local itemIdBuffer = buffer(offset, 2)
  2174. local itemIdField = itemsInBankField:add(serverOpenBankItemID, itemIdBuffer)
  2175. itemIdField:append_text(" (" .. ITEM_NAMES[itemIdBuffer:int()] .. ")")
  2176. offset = offset + 2
  2177. local getIntCache = rsc_getUnsignedInt3(buffer, offset)
  2178. offset = offset + getIntCache[1]:len() -- 2 or 4 long
  2179. itemIdField:add(serverOpenBankItemsInStack, getIntCache[1], getIntCache[2])
  2180. end
  2181. -- 48 -- SERVER_OPCODE_SCENERY_HANDLER
  2182. elseif (serverOpcode == 48) then
  2183. -- not standalone
  2184. -- requires thisLocalRegionX and thisLocalRegionY
  2185. -- load / save those values
  2186. if pinfoVisited then
  2187. thisLocalRegionX = thisGameStateValuesAtThisTime[pinfoNumber][1]
  2188. thisLocalRegionY = thisGameStateValuesAtThisTime[pinfoNumber][2]
  2189. else
  2190. thisGameStateValuesAtThisTime[pinfoNumber] = { thisLocalRegionX, thisLocalRegionY }
  2191. end
  2192. -- TODO: should put "data from previous opcodes" field here
  2193. local offset = 1
  2194. while buffer:len() > offset + 1 do
  2195. local removeModeField = opcodeField:add(serverObjectHandlerRemoveMode, buffer(offset, 1)) -- shares the first byte with objectIDField
  2196. if buffer(offset, 1):uint() == 255 then
  2197. removeModeField:append_text(" (In remove mode)")
  2198. removeModeField:add(serverObjectHandlerXCoordinateOffset, buffer(offset + 1, 1), (buffer(offset + 1, 1):int() / 8) + thisLocalRegionX)
  2199. removeModeField:add(serverObjectHandlerYCoordinateOffset, buffer(offset + 2, 1), (buffer(offset + 2, 1):int() / 8) + thisLocalRegionY)
  2200. offset = offset + 3
  2201. else
  2202. removeModeField:append_text(" (Adding ")
  2203. local objectIDField = removeModeField:add(serverObjectHandlerObjectID, buffer(offset, 2))
  2204. local objectName = SCENERY_NAMES[buffer(offset, 2):uint()]
  2205. removeModeField:append_text(objectName .. " scenery)")
  2206. objectIDField:append_text(" (" .. objectName .. ")")
  2207. removeModeField:add(serverObjectHandlerXCoordinateOffset, buffer(offset + 2, 1), buffer(offset + 2, 1):int() + thisLocalRegionX)
  2208. removeModeField:add(serverObjectHandlerYCoordinateOffset, buffer(offset + 3, 1), buffer(offset + 3, 1):int() + thisLocalRegionY)
  2209. offset = offset + 4
  2210. end
  2211. end
  2212. -- 51 -- SERVER_OPCODE_PRIVACY_SETTINGS
  2213. elseif (serverOpcode == 51) then
  2214. -- standalone, doesn't require data from other opcodes
  2215. local blockChat = buffer(1, 1)
  2216. local blockPrivate = buffer(2, 1)
  2217. local blockTrade = buffer(3, 1)
  2218. local blockDuel = buffer(4, 1)
  2219. local field = opcodeField:add(serverBlockChat, blockChat)
  2220. if (blockChat:uint() == 0) then
  2221. field:append_text(" (Off)")
  2222. else
  2223. field:append_text(" (On)")
  2224. end
  2225. field = opcodeField:add(serverBlockPrivate, blockPrivate)
  2226. if (blockPrivate:uint() == 0) then
  2227. field:append_text(" (Off)")
  2228. else
  2229. field:append_text(" (On)")
  2230. end
  2231. field = opcodeField:add(serverBlockTrade, blockTrade)
  2232. if (blockTrade:uint() == 0) then
  2233. field:append_text(" (Off)")
  2234. else
  2235. field:append_text(" (On)")
  2236. end
  2237. field = opcodeField:add(serverBlockDuel, blockDuel)
  2238. if (blockDuel:uint() == 0) then
  2239. field:append_text(" (Off)")
  2240. else
  2241. field:append_text(" (On)")
  2242. end
  2243. -- 52 -- SERVER_OPCODE_UPDATE_SYSTEM_UPDATE_TIMER
  2244. elseif (serverOpcode == 52) then
  2245. -- standalone, doesn't require data from other opcodes
  2246. local systemUpdateTimerBuffer = buffer(1, 2)
  2247. local systemUpdateTimer = (buffer(1, 2):int() * 32) / 50
  2248. local minutes = math.floor(systemUpdateTimer / 60)
  2249. local seconds = systemUpdateTimer % 60
  2250. local systemUpdateTimerField = opcodeField:add(serverSystemUpdateTimer, systemUpdateTimerBuffer, systemUpdateTimer)
  2251. if seconds < 10 then
  2252. systemUpdateTimerField:append_text(" (" .. minutes .. ":0" .. seconds .. ")")
  2253. else
  2254. systemUpdateTimerField:append_text(" (" .. minutes .. ":" .. seconds .. ")")
  2255. end
  2256. -- 53 -- SERVER_OPCODE_SET_INVENTORY
  2257. elseif (serverOpcode == 53) then
  2258. -- standalone, doesn't require data from other opcodes
  2259. local inventoryItemsCount = buffer(1, 1)
  2260. opcodeField:add(serverInventoryItemsCount, inventoryItemsCount)
  2261. offset = 2
  2262. for index = 0, inventoryItemsCount:uint() - 1, 1 do
  2263. local itemInfo = buffer(offset, 2)
  2264. local equipped = math.floor(itemInfo:uint() / 32768) -- the first bit of itemInfo is for equipped
  2265. local itemId = bit.band(itemInfo:uint(), 32767) -- the rightmost 15 bits are for item ID
  2266. thisPlayerInventory[index] = itemInfo:uint()
  2267. local itemIdField = opcodeField:add(serverItemId, itemInfo, itemId)
  2268. itemIdField:append_text(" (" .. ITEM_NAMES[itemId] .. ")")
  2269. if (ITEM_WEILDABLE[itemId] or equipped == 1) then
  2270. local equippedField = itemIdField:add(serverItemEquipped, buffer(offset, 1), equipped)
  2271. equippedField:append_text(" (" .. boolToEnglish(equipped) .. ")")
  2272. end
  2273. offset = offset + 2
  2274. local itemCount
  2275. local itemCountValue
  2276. if (ITEM_STACKABLE[itemId]) then
  2277. local getIntCache = rsc_getUnsignedInt3(buffer, offset)
  2278. offset = offset + getIntCache[1]:len()
  2279. itemIdField:add(serverItemCount, getIntCache[1], getIntCache[2])
  2280. else
  2281. itemCountValue = 1
  2282. end
  2283. end
  2284. -- 79 -- SERVER_OPCODE_NPC_COORDS
  2285. elseif (serverOpcode == 79) then
  2286. -- not standalone
  2287. -- requires thisLocalRegionX and thisLocalRegionY
  2288. -- load / save those values
  2289. if pinfoVisited then
  2290. thisLocalRegionX = thisGameStateValuesAtThisTime[pinfoNumber][1]
  2291. thisLocalRegionY = thisGameStateValuesAtThisTime[pinfoNumber][2]
  2292. thisNpcs = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][3])
  2293. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][4])
  2294. thisNpcsCache = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][5])
  2295. thisNpcsCount = thisGameStateValuesAtThisTime[pinfoNumber][6]
  2296. else
  2297. thisGameStateValuesAtThisTime[pinfoNumber] = { thisLocalRegionX, thisLocalRegionY,
  2298. dereferenceList(thisNpcs), dereferenceList(thisNpcsServer), dereferenceList(thisNpcsCache), thisNpcsCount }
  2299. end
  2300. local initialStateField = opcodeField:add("Necessary Variables From Previous Opcodes")
  2301. initialStateField:add("Local Player's X Coordinate: " .. thisLocalRegionX)
  2302. initialStateField:add("Local Player's Y Coordinate: " .. thisLocalRegionY)
  2303. for index = 0, thisNpcsCount - 1 do
  2304. thisNpcsCache = {}
  2305. for key, value in next, thisNpcs do
  2306. if key <= index then
  2307. thisNpcsCache[key] = value
  2308. end
  2309. end
  2310. end
  2311. thisNpcsCount = 0
  2312. local npcCountBuffer = buffer(1, 1)
  2313. local npcCount = npcCountBuffer:uint()
  2314. opcodeField:add(serverNPCCoordsCount, npcCountBuffer)
  2315. local bitOffset = 8
  2316. if npcCount > 0 then
  2317. npcAnimationUpdatesField = opcodeField:add("Animation & Coordinate Updates")
  2318. end
  2319. for index = 0, npcCount - 1 do
  2320. local reqUpdate = rsc_getBitMask(1, bitOffset, buffer)
  2321. local reqUpdateField = npcAnimationUpdatesField:add(serverNPCCoordsReqUpdate, workingBuffer, reqUpdate == 1)
  2322. bitOffset = bitOffset + 1
  2323. if (thisNpcsCache[index] == nil) then
  2324. if thisDebugging then
  2325. debugWindow:append("Warning! encountered nil NPC on pinfo.number: ")
  2326. debugWindow:append(pinfo.number)
  2327. debugWindow:append("\n")
  2328. end
  2329. thisNpcsCache[index] = {}
  2330. thisNpcsCache[index]["currentX"] = 0
  2331. thisNpcsCache[index]["currentY"] = 0
  2332. thisNpcsCache[index]["animationNext"] = 0
  2333. end
  2334. if reqUpdate ~= 0 then
  2335. local updateType = rsc_getBitMask(1, bitOffset, buffer)
  2336. local typeField = reqUpdateField:add(serverNPCCoordsUpdateType, workingBuffer, updateType)
  2337. bitOffset = bitOffset + 1
  2338. if updateType ~= 0 then -- Animation update
  2339. typeField:append_text(" (Stationary)")
  2340. local animationNextFragment = rsc_getBitMask(2, bitOffset, buffer)
  2341. if animationNextFragment ~= 3 then
  2342. thisNpcsCache[index]["animationNext"] = rsc_getBitMask(4, bitOffset, buffer)
  2343. bitOffset = bitOffset + 4
  2344. local animUpdateField = reqUpdateField:add(serverNPCCoordsAnimationUpdate, workingBuffer, thisNpcsCache[index]["animationNext"])
  2345. animUpdateField:append_text(" (" .. ANIMATION_NAMES[thisNpcsCache[index]["animationNext"]] .. ")")
  2346. else
  2347. reqUpdateField:append_text(" (Remove NPC)")
  2348. bitOffset = bitOffset + 2
  2349. thisNpcsCache[index]["removed"] = true
  2350. goto continue -- lol
  2351. end
  2352. else -- Animation update (while walking, adds to coordinates based on animation direction)
  2353. typeField:append_text(" (Moving)")
  2354. thisNpcsCache[index]["animationNext"] = rsc_getBitMask(3, bitOffset, buffer)
  2355. bitOffset = bitOffset + 3
  2356. if (thisNpcsCache[index]["animationNext"] == 1 or thisNpcsCache[index]["animationNext"] == 2 or thisNpcsCache[index]["animationNext"] == 3) then
  2357. thisNpcsCache[index]["currentX"] = thisNpcsCache[index]["currentX"] + 1
  2358. else
  2359. if (thisNpcsCache[index]["animationNext"] == 5 or thisNpcsCache[index]["animationNext"] == 6 or thisNpcsCache[index]["animationNext"] == 7) then
  2360. thisNpcsCache[index]["currentX"] = thisNpcsCache[index]["currentX"] - 1
  2361. end
  2362. end
  2363. if (thisNpcsCache[index]["animationNext"] == 3 or thisNpcsCache[index]["animationNext"] == 4 or thisNpcsCache[index]["animationNext"] == 5) then
  2364. thisNpcsCache[index]["currentY"] = thisNpcsCache[index]["currentY"] + 1
  2365. else
  2366. if (thisNpcsCache[index]["animationNext"] == 0 or thisNpcsCache[index]["animationNext"] == 1 or thisNpcsCache[index]["animationNext"] == 7) then
  2367. thisNpcsCache[index]["currentY"] = thisNpcsCache[index]["currentY"] - 1
  2368. end
  2369. end
  2370. local animUpdateField = reqUpdateField:add(serverPlayerCoordsAnimationUpdate, workingBuffer, thisNpcsCache[index]["animationNext"])
  2371. animUpdateField:append_text(" (" .. ANIMATION_NAMES[thisNpcsCache[index]["animationNext"]] .. ")")
  2372. end
  2373. end
  2374. thisNpcs[thisNpcsCount] = thisNpcsCache[index]
  2375. thisNpcsCount = thisNpcsCount + 1
  2376. ::continue::
  2377. if (thisNpcsCache[index] ~= nil) then
  2378. if (thisNpcsCache[index]["npcId"] ~= nil) then
  2379. reqUpdateField:prepend_text("(index: " .. thisNpcsCache[index]["serverIndex"] .. " aka " .. NPC_NAMES[thisNpcsCache[index]["npcId"]] .. "@(" .. thisNpcsCache[index]["currentX"] .. "," .. thisNpcsCache[index]["currentY"] .. ")) ")
  2380. else
  2381. reqUpdateField:prepend_text("(index: " .. index .. " (unknown npc aka bug))) ")
  2382. end
  2383. end
  2384. end
  2385. if (packetLength * 8 > bitOffset + 34) then
  2386. newNpcsField = opcodeField:add("New NPC or Coordinate Refresh")
  2387. local newNpcCount = math.floor((packetLength * 8 - bitOffset) / 36)
  2388. newNpcsField:prepend_text(newNpcCount .. " ")
  2389. if newNpcCount ~= 1 then
  2390. newNpcsField:append_text("s")
  2391. end
  2392. end
  2393. while (packetLength * 8 > bitOffset + 34) do
  2394. local serverIndex = rsc_getBitMask(12, bitOffset, buffer)
  2395. local newNpcsServerIndexField = newNpcsField:add(serverNPCCoordsServerIndex, workingBuffer, serverIndex)
  2396. bitOffset = bitOffset + 12
  2397. local areaX = rsc_getBitMask(5, bitOffset, buffer)
  2398. if areaX > 15 then
  2399. areaX = areaX - 32
  2400. end
  2401. local x = thisLocalRegionX + areaX
  2402. newNpcsServerIndexField:add(serverNPCCoordsXCoordinate, workingBuffer, x)
  2403. bitOffset = bitOffset + 5
  2404. local areaY = rsc_getBitMask(5, bitOffset, buffer)
  2405. if areaY > 15 then
  2406. areaY = areaY - 32
  2407. end
  2408. local y = thisLocalRegionY + areaY
  2409. newNpcsServerIndexField:add(serverNPCCoordsYCoordinate, workingBuffer, y)
  2410. bitOffset = bitOffset + 5
  2411. local anim = rsc_getBitMask(4, bitOffset, buffer)
  2412. local newNpcsServerIndexFieldAnimField = newNpcsServerIndexField:add(serverNPCCoordsAnimation, workingBuffer, anim)
  2413. bitOffset = bitOffset + 4
  2414. newNpcsServerIndexFieldAnimField:append_text(" (" .. ANIMATION_NAMES[anim] .. ")")
  2415. local npcId = rsc_getBitMask(10, bitOffset, buffer)
  2416. local newNpcsServerIndexFieldNPCIDField = newNpcsServerIndexField:add(serverNPCCoordsNPCID, workingBuffer, npcId)
  2417. bitOffset = bitOffset + 10
  2418. newNpcsServerIndexFieldNPCIDField:append_text(" (" .. NPC_NAMES[npcId] .. ")")
  2419. local found = false
  2420. for findIndex = 0, thisNpcsCount - 1 do
  2421. if (thisNpcsCache[findIndex] ~= nil) then
  2422. if (serverIndex == thisNpcsCache[findIndex]["serverIndex"]) then
  2423. if (thisNpcsCache[findIndex]["removed"] == false) then
  2424. found = true
  2425. end
  2426. end
  2427. end
  2428. end
  2429. thisNpcs[thisNpcsCount] = rsc_createNPC(serverIndex, y, x, animation, npcId)
  2430. if (found == false) then
  2431. thisNpcsCount = thisNpcsCount + 1
  2432. end
  2433. end
  2434. -- 87 -- SERVER_OPCODE_SEND_PM
  2435. elseif (serverOpcode == 87) then
  2436. -- standalone, doesn't require data from other opcodes
  2437. local senderBuffer = rsc_getRSCStringBuffer(buffer, 1)
  2438. offset = senderBuffer:len() + 1
  2439. opcodeField:add(serverSendPrivateMessageRecipient, senderBuffer, rsc_readRSCString(senderBuffer))
  2440. local method220Cache = method220(buffer, offset)
  2441. local messageLengthBuffer = method220Cache[1]
  2442. local messageLength = method220Cache[2]
  2443. opcodeField:add(serverSendPrivateMessageLength, messageLengthBuffer, messageLength)
  2444. offset = offset + method220Cache[3]
  2445. local method240Cache = method240(buffer, 0, offset, messageLength)
  2446. local scrambledChatMessageBufferLength = method240Cache[1]
  2447. local chatMessageInts = method240Cache[2]
  2448. opcodeField:add(serverSendPrivateMessageMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  2449. offset = offset + scrambledChatMessageBufferLength
  2450. -- 89 -- SERVER_OPCODE_SHOW_DIALOGUE_SERVER_MESSAGE_TOP
  2451. elseif (serverOpcode == 89) then
  2452. -- standalone, doesn't require data from other opcodes
  2453. local messageBuffer = rsc_getRSCStringBuffer(buffer, 1)
  2454. opcodeField:add(serverShowDialogueServerMessageTopMessage, messageBuffer, rsc_readRSCString(messageBuffer))
  2455. -- 90 -- SERVER_OPCODE_SET_INVENTORY_SLOT
  2456. elseif (serverOpcode == 90) then
  2457. -- standalone, doesn't require data from other opcodes
  2458. local slotBuffer = buffer(1, 1)
  2459. local slotField = opcodeField:add(serverSetInventorySlotSlot, slotBuffer)
  2460. local itemIDAndEquippedBuffer = buffer(2, 2)
  2461. local equipped = math.floor(itemIDAndEquippedBuffer:uint() / 32768) -- the first bit of itemInfo is for equipped
  2462. local itemID = bit.band(itemIDAndEquippedBuffer:uint(), 32767) -- the rightmost 15 bits are for item ID
  2463. slotField:add(serverSetInventorySlotItemEquipped, buffer(2, 1), equipped)
  2464. local itemIDField = slotField:add(serverSetInventorySlotItemID, itemIDAndEquippedBuffer, itemID)
  2465. itemIDField:append_text(" (" .. ITEM_NAMES[itemID] .. ")")
  2466. thisPlayerInventory[slotBuffer:uint()] = itemIDAndEquippedBuffer:uint()
  2467. if (ITEM_STACKABLE[itemID]) then
  2468. local getItemStack = rsc_getUnsignedInt3(buffer, 4)
  2469. slotField:add(serverSetInventorySlotItemStackAmount, getItemStack[1], getItemStack[2])
  2470. end
  2471. -- 91 -- SERVER_OPCODE_BOUNDARY_HANDLER
  2472. elseif (serverOpcode == 91) then
  2473. -- not standalone
  2474. -- requires thisLocalRegionX and thisLocalRegionY
  2475. -- load / save those values
  2476. if pinfoVisited then
  2477. thisLocalRegionX = thisGameStateValuesAtThisTime[pinfoNumber][1]
  2478. thisLocalRegionY = thisGameStateValuesAtThisTime[pinfoNumber][2]
  2479. else
  2480. thisGameStateValuesAtThisTime[pinfoNumber] = { thisLocalRegionX, thisLocalRegionY }
  2481. end
  2482. local offset = 1
  2483. while buffer:len() > offset + 1 do
  2484. local removeModeField = opcodeField:add(serverBoundaryHandlerRemoveMode, buffer(offset, 1)) -- shares the first byte with objectIDField
  2485. if buffer(offset, 1):uint() == 255 then
  2486. removeModeField:append_text(" (In remove mode, removes 8x8 chunks at a time)")
  2487. removeModeField:add(serverBoundaryHandlerXCoordinateOffset, buffer(offset + 1, 1), (buffer(offset + 1, 1):int() / 8) + thisLocalRegionX)
  2488. removeModeField:add(serverBoundaryHandlerYCoordinateOffset, buffer(offset + 2, 1), (buffer(offset + 2, 1):int() / 8) + thisLocalRegionY)
  2489. offset = offset + 3
  2490. else
  2491. removeModeField:append_text(" (Adding ")
  2492. local objectIDField = removeModeField:add(serverBoundaryHandlerObjectID, buffer(offset, 2))
  2493. local objectName = BOUNDARY_NAMES[buffer(offset, 2):uint()]
  2494. removeModeField:append_text(objectName .. " object)")
  2495. objectIDField:append_text(" (" .. objectName .. ")")
  2496. removeModeField:add(serverBoundaryHandlerXCoordinateOffset, buffer(offset + 2, 1), buffer(offset + 2, 1):int() + thisLocalRegionX)
  2497. removeModeField:add(serverBoundaryHandlerYCoordinateOffset, buffer(offset + 3, 1), buffer(offset + 3, 1):int() + thisLocalRegionY)
  2498. local alignmentField = removeModeField:add(serverBoundaryHandlerAlignment, buffer(offset + 4, 1))
  2499. alignmentField:append_text(" (" .. BOUNDARY_ALIGNMENTS[buffer(offset + 4, 1):int()] .. ")")
  2500. offset = offset + 5
  2501. end
  2502. end
  2503. -- 92 -- SERVER_OPCODE_INITIATE_TRADE
  2504. elseif (serverOpcode == 92) then
  2505. -- not standalone, (unless you're okay not knowing the username you're trading with)
  2506. -- load / save player display name
  2507. if pinfoVisited then
  2508. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  2509. else
  2510. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  2511. end
  2512. opcodeField:add(serverInitiateTradePID, buffer(1, 2))
  2513. opcodeField:add(serverInitiateTradeUsername, buffer(1, 2), thisPlayerServer[buffer(1, 2):int()]["displayName"])
  2514. -- 97 -- SERVER_OPCODE_UPDATE_ITEMS_TRADED_TO_YOU
  2515. elseif (serverOpcode == 97) then
  2516. -- standalone, doesn't require data from other opcodes
  2517. local itemCount = buffer(1, 1):int()
  2518. opcodeField:add(serverUpdateItemsTradedToYouItemCount, buffer(1, 1))
  2519. local offset = 2
  2520. for i = 0, itemCount - 1 do
  2521. local itemId = buffer(offset, 2):int()
  2522. local itemIdField = opcodeField:add(serverUpdateItemsTradedToYouItemID, buffer(offset, 2))
  2523. itemIdField:append_text(" (" .. ITEM_NAMES[itemId] .. ")")
  2524. itemIdField:add(serverUpdateItemsTradedToYouItemAmount, buffer(offset + 2, 4))
  2525. offset = offset + 6
  2526. end
  2527. -- 99 -- SERVER_OPCODE_GROUND_ITEM_HANDLER
  2528. elseif (serverOpcode == 99) then
  2529. -- not standalone
  2530. -- requires thisLocalRegionX and thisLocalRegionY
  2531. -- load / save those values
  2532. if pinfoVisited then
  2533. thisLocalRegionX = thisGameStateValuesAtThisTime[pinfoNumber][1]
  2534. thisLocalRegionY = thisGameStateValuesAtThisTime[pinfoNumber][2]
  2535. else
  2536. thisGameStateValuesAtThisTime[pinfoNumber] = { thisLocalRegionX, thisLocalRegionY }
  2537. end
  2538. -- TODO: should put "data from previous opcodes" field here
  2539. local offset = 1
  2540. while buffer:len() > offset + 1 do
  2541. local removeModeField = opcodeField:add(serverGroundItemHandlerRemoveMode, buffer(offset, 1)) -- shares the first byte with objectIDField
  2542. if buffer(offset, 1):uint() == 255 then
  2543. removeModeField:append_text(" (In remove mode)")
  2544. removeModeField:add(serverGroundItemHandlerXCoordinateOffset, buffer(offset + 1, 1), (buffer(offset + 1, 1):int() / 8) + thisLocalRegionX)
  2545. removeModeField:add(serverGroundItemHandlerYCoordinateOffset, buffer(offset + 2, 1), (buffer(offset + 2, 1):int() / 8) + thisLocalRegionY)
  2546. offset = offset + 3
  2547. else
  2548. local objectIDField = removeModeField:add(serverGroundItemHandlerItemID, buffer(offset, 2))
  2549. -- First bit being on means that it is removing a specific item ID from that location
  2550. local removing = math.floor(thisPlayerInventory[buffer(1, 1):uint()] / 32768)
  2551. local objectName = ITEM_NAMES[buffer(offset, 2):uint() % 32767]
  2552. if (removing == 1) then
  2553. removeModeField:append_text(" (Removing ")
  2554. removeModeField:append_text(objectName .. " from the ground)")
  2555. else
  2556. removeModeField:append_text(" (Adding ")
  2557. removeModeField:append_text(objectName .. " to the ground)")
  2558. end
  2559. objectIDField:append_text(" (" .. objectName .. ")")
  2560. removeModeField:add(serverGroundItemHandlerXCoordinateOffset, buffer(offset + 2, 1), buffer(offset + 2, 1):int() + thisLocalRegionX)
  2561. removeModeField:add(serverGroundItemHandlerYCoordinateOffset, buffer(offset + 3, 1), buffer(offset + 3, 1):int() + thisLocalRegionY)
  2562. offset = offset + 4
  2563. end
  2564. end
  2565. -- 101 -- SERVER_OPCODE_SHOW_SHOP
  2566. elseif(serverOpcode == 101) then
  2567. -- standalone, doesn't require data from other opcodes
  2568. local itemCountField = opcodeField:add(serverShowShopItemCount, buffer(1, 1))
  2569. local shopTypeField = opcodeField:add(serverShowShopType, buffer(2, 1))
  2570. if buffer(2, 1):int() == 1 then
  2571. shopTypeField:append_text(" (general store)")
  2572. else
  2573. shopTypeField:append_text(" (specialty store)")
  2574. end
  2575. local sellGenerosityField = opcodeField:add(serverShowShopSellPriceGenerosity, buffer(3, 1))
  2576. local shopSellGenerosity = buffer(3, 1):uint()
  2577. sellGenerosityField:append_text(" (" .. shopSellGenerosity / 100 .. " * base_item_value)")
  2578. local buyGenerosityField = opcodeField:add(serverShowShopBuyPriceGenerosity, buffer(4, 1))
  2579. local shopBuyGenerosity = buffer(4, 1):uint()
  2580. buyGenerosityField:append_text(" (" .. shopBuyGenerosity / 100 .. " * base_item_value)")
  2581. opcodeField:add(serverShowShopStockEffect, buffer(5, 1))
  2582. local stockEffectValue = buffer(5, 1):uint()
  2583. for i = 0, buffer(1, 1):int() - 1 do
  2584. local itemIDBuffer = buffer(6 + i * 6, 2)
  2585. local itemIDField = itemCountField:add(serverShowShopItemID, itemIDBuffer)
  2586. local itemID = itemIDBuffer:uint()
  2587. itemIDField:append_text(" (" .. ITEM_NAMES[itemID] ..")")
  2588. local amountBuffer = buffer(8 + i * 6, 2)
  2589. local amountInStock = amountBuffer:uint()
  2590. local amountField = itemIDField:add(serverShowShopItemStackAmount, amountBuffer)
  2591. local baseAmountInStockBuffer = buffer(10 + i * 6, 2)
  2592. local baseAmountField = itemIDField:add(serverShowShopBaseAmountInStock, baseAmountInStockBuffer)
  2593. local baseAmountInStock = baseAmountInStockBuffer:uint()
  2594. local sellValue = calculateShopItemPrice(ITEM_BASE_PRICE[itemID], amountInStock, baseAmountInStock, stockEffectValue, shopSellGenerosity)
  2595. local buyValue = calculateShopItemPrice(ITEM_BASE_PRICE[itemID], amountInStock, baseAmountInStock, stockEffectValue, shopBuyGenerosity)
  2596. local calculatedField = itemIDField:add("Client-Calculated Price Data")
  2597. calculatedField:add("Base Item Value (from cache): " .. ITEM_BASE_PRICE[itemID] .. " gp")
  2598. calculatedField:add("Sell Value (calculated): " .. sellValue .. " gp")
  2599. calculatedField:add("Buy Value (calculated): " .. buyValue .. " gp")
  2600. end
  2601. -- 104 -- SERVER_OPCODE_UPDATE_NPC
  2602. elseif (serverOpcode == 104) then
  2603. -- not standalone
  2604. -- requires thisLocalRegionX and thisLocalRegionY
  2605. -- load / save those values
  2606. if pinfoVisited then
  2607. thisNpcsServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  2608. thisPlayerServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][2])
  2609. else
  2610. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisNpcsServer), dereferenceList(thisPlayerServer) }
  2611. end
  2612. local npcCountBuffer = buffer(1, 2)
  2613. local npcCount = npcCountBuffer:uint()
  2614. local npcCountField = opcodeField:add(serverUpdateNPCNPCCount, npcCountBuffer)
  2615. if thisDebugging then
  2616. local debugField = opcodeField:add("DEBUG")
  2617. for key, value in next, thisNpcsServer do
  2618. if thisNpcsServer[key]["serverIndex"] then
  2619. debugField:add("serverIndex: " .. key)
  2620. end
  2621. end
  2622. end
  2623. local offset = 3
  2624. for index = 0, npcCount - 1 do
  2625. local serverIndexBuffer = buffer(offset, 2)
  2626. local serverIndexField = npcCountField:add(serverUpdateNPCNPCServerIndex, serverIndexBuffer)
  2627. offset = offset + 2
  2628. if (thisNpcsServer[serverIndexBuffer:uint()] ~= nil) then
  2629. serverIndexField:append_text(" (" .. NPC_NAMES[thisNpcsServer[serverIndexBuffer:uint()]["npcId"]].. ")")
  2630. end
  2631. local updateTypeBuffer = buffer(offset, 1)
  2632. local updateTypeField = serverIndexField:add(serverUpdateNPCUpdateType, updateTypeBuffer)
  2633. offset = offset + 1
  2634. if updateTypeBuffer:uint() == 2 then
  2635. updateTypeField:append_text(" (Combat Update)")
  2636. updateTypeField:add(serverUpdateNPCDamageTaken, buffer(offset, 1))
  2637. updateTypeField:add(serverUpdateNPCCurrentHP, buffer(offset + 1, 1))
  2638. updateTypeField:add(serverUpdateNPCMaxHP, buffer(offset + 2, 1))
  2639. offset = offset + 3
  2640. elseif updateTypeBuffer:uint() == 1 then
  2641. updateTypeField:append_text(" (NPC Chat Message)")
  2642. local playerTalkingToPIDBuffer = buffer(offset, 2)
  2643. local playerPIDField = updateTypeField:add(serverUpdateNPCPID, playerTalkingToPIDBuffer)
  2644. playerPIDField:append_text(" (" .. thisPlayerServer[playerTalkingToPIDBuffer:uint()]["displayName"] .. ")")
  2645. offset = offset + 2
  2646. local method220Cache = method220(buffer, offset)
  2647. local messageLengthBuffer = method220Cache[1]
  2648. local messageLength = method220Cache[2]
  2649. updateTypeField:add(serverUpdateNPCMessageLength, messageLengthBuffer, messageLength)
  2650. offset = offset + method220Cache[3]
  2651. local method240Cache = method240(buffer, 0, offset, messageLength)
  2652. local scrambledChatMessageBufferLength = method240Cache[1]
  2653. local chatMessageInts = method240Cache[2]
  2654. updateTypeField:add(serverUpdateNPCMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  2655. offset = offset + scrambledChatMessageBufferLength
  2656. end
  2657. end
  2658. -- 109 -- SERVER_OPCODE_SET_IGNORE
  2659. elseif (serverOpcode == 109) then
  2660. -- standalone, doesn't require data from other opcodes
  2661. local ignoreListCount = buffer(1, 1):int()
  2662. opcodeField:add(serverSetIgnoreListCount, buffer(1, 1))
  2663. local offset = 2
  2664. for i = 0, ignoreListCount - 1 do
  2665. local ignoreListNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2666. offset = offset + ignoreListNameBuffer:len()
  2667. local nameField = opcodeField:add(serverSetIgnoreListName, ignoreListNameBuffer, rsc_readRSCString(ignoreListNameBuffer))
  2668. local ignoreListAccNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2669. offset = offset + ignoreListAccNameBuffer:len()
  2670. nameField:add(serverSetIgnoreListAccountName, ignoreListAccNameBuffer, rsc_readRSCString(ignoreListAccNameBuffer))
  2671. local ignoreListOldNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2672. offset = offset + ignoreListOldNameBuffer:len()
  2673. nameField:add(serverSetIgnoreListOldName, ignoreListOldNameBuffer, rsc_readRSCString(ignoreListOldNameBuffer))
  2674. local ignoreListServerBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2675. offset = offset + ignoreListServerBuffer:len()
  2676. nameField:add(serverSetIgnoreListServers, ignoreListServerBuffer, rsc_readRSCString(ignoreListServerBuffer))
  2677. end
  2678. -- 111 -- SERVER_OPCODE_COMPLETED_TUTORIAL
  2679. elseif (serverOpcode == 111) then
  2680. -- standalone, doesn't require data from other opcodes
  2681. local field = opcodeField:add(serverJustCompletedTutorial,buffer(1, 1))
  2682. if buffer(1, 1):int() == 0 then
  2683. field:append_text(" (Completed Tutorial)")
  2684. else
  2685. field:append_text(" (In Tutorial)")
  2686. end
  2687. -- 114 -- SERVER_OPCODE_SET_FATIGUE
  2688. elseif (serverOpcode == 114) then
  2689. -- standalone, doesn't require data from other opcodes
  2690. local field = opcodeField:add(serverSetFatigue, buffer(1,2), buffer(1,2):int()/7.5)
  2691. field:append_text(" (note that this is client fatigue, server fatigue is more precise)")
  2692. -- 117 -- SERVER_OPCODE_FALL_ASLEEP
  2693. elseif (serverOpcode == 117) then
  2694. -- standalone, doesn't require data from other opcodes
  2695. opcodeField:add(serverSleepWordImage, buffer(1,buffer:len() - 1))
  2696. -- TODO: put the player attempted word here, and say if it was successful or not.
  2697. -- TODO: would be fun to show ascii art representation of this image
  2698. -- However, Wireshark truncates text fields a maximum of 79 unicode characters long
  2699. -- Which means we can only get an effective resolution of 158x40, but sleep words are 255x40.
  2700. -- The image could be drawn sideways, but, with the space between lines too, it seems "not worth it."
  2701. -- local pictureField = opcodeField:add("Picture:")
  2702. -- for y = 0, 19 do
  2703. -- local lineField = opcodeField:add("")
  2704. -- for x = 0, 78 do
  2705. -- lineField:append_text("▚")
  2706. -- end
  2707. -- end
  2708. -- 120 -- SERVER_OPCODE_RECEIVE_PM
  2709. elseif (serverOpcode == 120) then
  2710. -- standalone, doesn't require data from other opcodes
  2711. local offset = 1
  2712. local senderBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2713. opcodeField:add(serverReceivePMSender, senderBuffer, rsc_readRSCString(senderBuffer))
  2714. offset = offset + senderBuffer:len()
  2715. -- Confirmed that in all samples, this sender2 is ALWAYS equal to the first sender.
  2716. -- TODO: should try creating replay with sender2 different and see if it is used as former name.
  2717. local senderBuffer2 = rsc_getRSCStringBuffer(buffer, offset)
  2718. opcodeField:add(serverReceivePMSender2, senderBuffer2, rsc_readRSCString(senderBuffer2))
  2719. offset = offset + senderBuffer2:len()
  2720. local modStatus = buffer(offset, 1)
  2721. local modStatusField = opcodeField:add(serverReceivePMModStatus, modStatus)
  2722. if (modStatus:int() == 0) then
  2723. modStatusField:append_text(" (not a mod)")
  2724. elseif (modStatus:int() == 1) then
  2725. modStatusField:append_text(" (pmod)")
  2726. elseif (modStatus:int() == 2) then
  2727. modStatusField:append_text(" (jmod)")
  2728. else
  2729. modStatusField:append_text(" (unknown)")
  2730. end
  2731. offset = offset + 1
  2732. local messageIDField = opcodeField:add(serverReceivePMMessageID, buffer(offset, 8))
  2733. local explanationField = messageIDField:add("Explanation")
  2734. explanationField:add("If the client receives a Private Message with the same Message ID within 100 PMs")
  2735. explanationField:add("of each other, the client will not display the PM. This happens occasionally, possibly")
  2736. explanationField:add("due to a race condition where multiple login servers attempt to handle the same PM.")
  2737. messageIDField:add(serverReceivePMMessageIDWorld, buffer(offset + 3, 2))
  2738. local messageIDIDField = messageIDField:add(serverReceivePMMessageIDID, buffer(offset + 5, 3))
  2739. local explanationField = messageIDIDField:add("Explanation")
  2740. explanationField:add("This number is the number of PMs sent from that world since the world was last rebooted.")
  2741. -- I know this from talking to RuneLite developer abex & having them hook the same field in OSRS, observing that
  2742. -- it was 505514 before an update, and 7, 8, 9, 10, 11, 12 sequentially after the server rebooted for an update.
  2743. offset = offset + 8
  2744. local method220Cache = method220(buffer, offset)
  2745. local messageLengthBuffer = method220Cache[1]
  2746. local messageLength = method220Cache[2]
  2747. opcodeField:add(serverReceivePMMessageLength, messageLengthBuffer, messageLength)
  2748. offset = offset + method220Cache[3]
  2749. local method240Cache = method240(buffer, 0, offset, messageLength)
  2750. local scrambledChatMessageBufferLength = method240Cache[1]
  2751. local chatMessageInts = method240Cache[2]
  2752. opcodeField:add(serverReceivePMMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  2753. offset = offset + scrambledChatMessageBufferLength
  2754. -- 123 -- SERVER_OPCODE_REMOVE_INVENTORY_SLOT
  2755. elseif (serverOpcode == 123) then
  2756. -- not standalone (unless you're OK not knowing what was in the slot)
  2757. -- requires inventory state
  2758. if pinfoVisited then
  2759. thisPlayerInventory = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  2760. else
  2761. thisGameStateValuesAtThisTime[pinfoNumber] = { dereferenceList(thisPlayerInventory) }
  2762. end
  2763. local itemRemovedField = opcodeField:add(serverRemoveSlot, buffer(1, 1))
  2764. local equipped = math.floor(thisPlayerInventory[buffer(1, 1):uint()] / 32768) -- the first bit of itemInfo is for equipped
  2765. local itemId = bit.band(thisPlayerInventory[buffer(1, 1):uint()], 32767) -- the rightmost 15 bits are for item ID
  2766. itemRemovedField:append_text(" (" .. ITEM_NAMES[itemId] .. ")")
  2767. -- TODO: possibly say if it was equipped or not
  2768. for i = buffer(1, 1):uint() - 1, 29 do
  2769. thisPlayerInventory[i] = thisPlayerInventory[i + 1]
  2770. end
  2771. -- 131 -- SERVER_OPCODE_SEND_MESSAGE
  2772. elseif (serverOpcode == 131) then
  2773. -- standalone, doesn't require data from other opcodes
  2774. local offset = 1
  2775. local messageType = buffer(offset, 1)
  2776. offset = offset + 1
  2777. local messageTypeField = opcodeField:add(serverSendMessageType, messageType)
  2778. messageTypeField:append_text(" (" .. MESSAGE_TYPES[messageType:int()] .. ")")
  2779. local infoContained = buffer(offset, 1)
  2780. offset = offset + 1
  2781. local infoContainedField = opcodeField:add(serverSendMessageInfoContained, infoContained)
  2782. local message = rsc_getRSCStringBuffer(buffer, offset)
  2783. offset = offset + message:len()
  2784. opcodeField:add(serverSendMessageMessage, message, rsc_readRSCString(message))
  2785. local infoContainedEffect = 0
  2786. if (bit.band(infoContained:int(), 1) ~= 0) then
  2787. local sender = rsc_getRSCStringBuffer(buffer, offset)
  2788. offset = offset + sender:len()
  2789. local sender2 = rsc_getRSCStringBuffer(buffer, offset)
  2790. offset = offset + sender2:len()
  2791. opcodeField:add(serverSendMessageSender, sender, rsc_readRSCString(sender))
  2792. opcodeField:add(serverSendMessageSender2, sender2, rsc_readRSCString(sender2))
  2793. infoContainedEffect = infoContainedEffect + 1
  2794. end
  2795. if (bit.band(infoContained:int(),2) ~= 0) then
  2796. local colour = rsc_getRSCStringBuffer(buffer, offset)
  2797. opcodeField:add(serverSendMessageColour, colour, rsc_readRSCString(colour))
  2798. infoContainedEffect = infoContainedEffect + 2
  2799. end
  2800. if infoContainedEffect == 0 then
  2801. infoContainedField:append_text(" (only the message)")
  2802. elseif infoContainedEffect == 1 then
  2803. infoContainedField:append_text(" (message, sender, sender duplicate)")
  2804. elseif infoContainedEffect == 2 then
  2805. infoContainedField:append_text(" (message, colour)")
  2806. elseif infoContainedEffect == 3 then
  2807. infoContainedField:append_text(" (message, sender, sender duplicate, colour)")
  2808. end
  2809. -- 149 -- SERVER_OPCODE_UPDATE_FRIEND
  2810. elseif (serverOpcode == 149) then
  2811. -- standalone, doesn't require data from other opcodes
  2812. local friendName = rsc_getRSCStringBuffer(buffer, 1)
  2813. local offset = friendName:len() + 1
  2814. local oldFriendName = rsc_getRSCStringBuffer(buffer, offset)
  2815. offset = offset + oldFriendName:len()
  2816. local onlineStatus = buffer(offset, 1)
  2817. local loggedIn = bit.band(onlineStatus:uint(), 4) ~= 0
  2818. opcodeField:add(serverUpdateFriendFriendName, friendName, rsc_readRSCString(friendName))
  2819. opcodeField:add(serverUpdateFriendOldFriendName, oldFriendName, rsc_readRSCString(oldFriendName))
  2820. onlineStatusField = opcodeField:add(serverUpdateFriendOnlineStatus, onlineStatus)
  2821. if (loggedIn) then
  2822. local friendServer = rsc_getRSCStringBuffer(buffer, offset + 1)
  2823. opcodeField:add(serverUpdateFriendFriendServer, friendServer, rscStringCrop(friendServer))
  2824. if (onlineStatus:uint() == 4) then
  2825. onlineStatusField:append_text(" (online different world)")
  2826. else
  2827. onlineStatusField:append_text(" (online same world)")
  2828. end
  2829. else
  2830. onlineStatusField:append_text(" (offline)")
  2831. end
  2832. -- 153 -- SERVER_OPCODE_SET_EQUIP_STATS
  2833. elseif (serverOpcode == 153) then
  2834. -- standalone, doesn't require data from other opcodes
  2835. opcodeField:add(serverSetEquipmentStatsArmour, buffer(1, 1))
  2836. opcodeField:add(serverSetEquipmentStatsWeaponAim, buffer(2, 1))
  2837. opcodeField:add(serverSetEquipmentStatsWeaponPower, buffer(3, 1))
  2838. opcodeField:add(serverSetEquipmentStatsMagic, buffer(4, 1))
  2839. opcodeField:add(serverSetEquipmentStatsPrayer, buffer(5, 1))
  2840. -- 156 -- SERVER_OPCODE_SET_STATS
  2841. elseif (serverOpcode == 156) then
  2842. -- standalone, doesn't require data from other opcodes
  2843. for i = 0, 17 do
  2844. local skillNameField = opcodeField:add(SKILL_NAMES[i])
  2845. skillNameField:add(serverSetStatsPlayerCurrentStat[i], buffer(i + 1, 1))
  2846. skillNameField:add(serverSetStatsPlayerBaseStat[i], buffer(i + 19, 1))
  2847. local xpBuffer = buffer(i * 4 + 37, 4)
  2848. skillNameField:add(serverSetStatsPlayerXP[i], xpBuffer, xpBuffer:int() / 4)
  2849. end
  2850. opcodeField:add(serverSetStatsPlayerQuestPoints, buffer(109, 1))
  2851. -- 159 -- SERVER_OPCODE_UPDATE_STAT
  2852. elseif (serverOpcode == 159) then
  2853. -- standalone, doesn't require data from other opcodes
  2854. local skillBuffer = buffer(1, 1)
  2855. local skillField = opcodeField:add(serverUpdateStatSkill, skillBuffer)
  2856. skillField:append_text(" (" .. SKILL_NAMES[skillBuffer:int()] .. ")")
  2857. opcodeField:add(serverUpdateStatPlayerCurrentStat, buffer(2, 1))
  2858. opcodeField:add(serverUpdateStatPlayerBaseStat, buffer(3, 1))
  2859. opcodeField:add(serverUpdateStatExperience, buffer(4, 4), buffer(4, 4):int() / 4)
  2860. -- 162 -- SERVER_OPCODE_UPDATE_TRADE_RECIPIENT_ACCEPTANCE
  2861. elseif (serverOpcode == 162) then
  2862. -- standalone, doesn't require data from other opcodes
  2863. local tradeAcceptanceField = opcodeField:add(serverUpdateTradeRecipientAcceptance, buffer(1, 1))
  2864. if buffer(1, 1):uint() == 1 then
  2865. tradeAcceptanceField:append_text(" (Accepted)")
  2866. else
  2867. tradeAcceptanceField:append_text(" (Not Accepted)")
  2868. end
  2869. -- 172 -- SERVER_OPCODE_SHOW_CONFIRM_DUEL
  2870. elseif (serverOpcode == 172) then
  2871. -- standalone, doesn't require data from other opcodes
  2872. local offset = 1
  2873. local opponentUsernameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  2874. offset = offset + opponentUsernameBuffer:len()
  2875. opcodeField:add(serverShowConfirmDuelOpponentName, opponentUsernameBuffer, rsc_readRSCString(opponentUsernameBuffer))
  2876. local opponentItemCount = buffer(offset, 1):uint()
  2877. local opponentItemCountField = opcodeField:add(serverShowConfirmDuelOpponentItemCount, buffer(offset, 1), opponentItemCount)
  2878. offset = offset + 1
  2879. for index = 0, opponentItemCount - 1 do
  2880. local itemIDField = opponentItemCountField:add(serverShowConfirmDuelOpponentItemID, buffer(offset, 2))
  2881. itemIDField:append_text(" (" .. ITEM_NAMES[buffer(offset ,2):int()] .. ")")
  2882. itemIDField:add(serverShowConfirmDuelOpponentItemStackAmount, buffer(offset + 2, 4))
  2883. offset = offset + 6
  2884. end
  2885. local itemCount = buffer(offset, 1):uint()
  2886. local itemCountField = opcodeField:add(serverShowConfirmDuelItemCount, buffer(offset, 1), itemCount)
  2887. offset = offset + 1
  2888. for index = 0, itemCount - 1 do
  2889. local itemIDField = itemCountField:add(serverShowConfirmDuelItemID, buffer(offset, 2))
  2890. itemIDField:append_text(" (" .. ITEM_NAMES[buffer(offset ,2):int()] .. ")")
  2891. itemIDField:add(serverShowConfirmDuelItemStackAmount, buffer(offset + 2, 4))
  2892. offset = offset + 6
  2893. end
  2894. local retreatField = opcodeField:add(serverShowConfirmDuelRetreat, buffer(offset, 1))
  2895. if buffer(offset, 1):int() == 0 then
  2896. retreatField:append_text(" (No retreat is possible!)")
  2897. else
  2898. retreatField:append_text(" (You can retreat from this duel)")
  2899. end
  2900. local magicField = opcodeField:add(serverShowConfirmDuelMagic, buffer(offset + 1, 1))
  2901. if buffer(offset + 1, 1):int() == 0 then
  2902. magicField:append_text(" (Magic may be used)")
  2903. else
  2904. magicField:append_text(" (Magic cannot be used)")
  2905. end
  2906. local prayerField = opcodeField:add(serverShowConfirmDuelPrayer, buffer(offset + 2, 1))
  2907. if buffer(offset + 2, 1):int() == 0 then
  2908. prayerField:append_text(" (Prayer may be used)")
  2909. else
  2910. prayerField:append_text(" (Prayer cannot be used)")
  2911. end
  2912. local weaponField = opcodeField:add(serverShowConfirmDuelWeapons, buffer(offset + 3, 1))
  2913. if buffer(offset + 3, 1):int() == 0 then
  2914. weaponField:append_text(" (Weapons may be used)")
  2915. else
  2916. weaponField:append_text(" (Weapons cannot be used)")
  2917. end
  2918. -- 176 -- SERVER_OPCODE_SHOW_DIALOGUE_DUEL
  2919. elseif (serverOpcode == 176) then
  2920. -- not standalone, (unless you're okay not knowing the username you're duelling with)
  2921. -- load / save player display name
  2922. if pinfoVisited then
  2923. thisPlayerServer[buffer(1, 2):int()]["displayName"] = thisGameStateValuesAtThisTime[pinfoNumber]
  2924. else
  2925. thisGameStateValuesAtThisTime[pinfoNumber] = thisPlayerServer[buffer(1, 2):int()]["displayName"]
  2926. end
  2927. opcodeField:add(serverShowDialogueDuelPID, buffer(1, 2))
  2928. opcodeField:add(serverShowDialogueDuelUsername, buffer(1, 2), thisPlayerServer[buffer(1, 2):int()]["displayName"])
  2929. -- 182 -- SERVER_OPCODE_SHOW_WELCOME
  2930. elseif (serverOpcode == 182) then
  2931. -- standalone, doesn't require data from other opcodes
  2932. opcodeField:add(serverShowWelcomeIP, buffer(1,4), buffer(1, 1):uint() .. "." .. buffer(2, 1):uint() .. "." .. buffer(3, 1):uint() .. "." .. buffer(4, 1):uint())
  2933. local lastLoginField = opcodeField:add(serverShowWelcomeDays, buffer(5, 2))
  2934. if buffer(5, 2):int() == 0 then
  2935. lastLoginField:append_text(" (earlier today)")
  2936. elseif buffer(5, 2):int() == 1 then
  2937. lastLoginField:append_text(" (yesterday)")
  2938. end
  2939. local recoveryDaysField = opcodeField:add(serverShowWelcomeRecoverySetDays, buffer(7, 1))
  2940. if buffer(7, 1):uint() == 200 then
  2941. recoveryDaysField:append_text(" (recovery questions not set)")
  2942. elseif buffer(7, 1):uint() == 201 then
  2943. recoveryDaysField:append_text(" (unspecified days ago)")
  2944. end
  2945. local unreadMessageField = opcodeField:add(serverShowWelcomeUnreadMessages, buffer(8, 2), buffer(8, 2):int() - 1)
  2946. if (buffer(8, 2):int() == 0) then
  2947. unreadMessageField:append_text(" (don't display how many messages there are)")
  2948. else
  2949. unreadMessageField:append_text(" (after subtracting 1 from byte)")
  2950. end
  2951. -- 191 -- SERVER_OPCODE_PLAYER_COORDS
  2952. -- TODO: sometimes there may still be problems with PID not lining up with player name
  2953. elseif (serverOpcode == 191) then
  2954. -- not standalone
  2955. -- requires lots of previously recorded data!
  2956. if pinfoVisited then
  2957. thisPlayers = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1])
  2958. thisPlayerCount = thisGameStateValuesAtThisTime[pinfoNumber][2]
  2959. thisPlayerServer = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][3])
  2960. else
  2961. thisGameStateValuesAtThisTime[pinfoNumber] = dereferencePlayerArrays()
  2962. end
  2963. -- interpret opcode data
  2964. local bitOffset = 0
  2965. thisKnownPlayerCount = thisGameStateValuesAtThisTime[pinfoNumber][2] -- dereferenced thisPlayerCount
  2966. thisKnownPlayers = dereferenceList(thisGameStateValuesAtThisTime[pinfoNumber][1]) -- dereferenced thisPlayers
  2967. thisPlayerCount = 0
  2968. local initialStateField = opcodeField:add("Necessary Variables From Previous Opcodes")
  2969. initialStateField:add("Local Player's PID: " .. thisLocalPlayerServerIndex)
  2970. initialStateField:add("Known Player Count: " .. thisKnownPlayerCount)
  2971. local localPlayerInfoField = opcodeField:add("Local Player Information")
  2972. -- first 3 bytes are shared by localRegion X & Y
  2973. local localPlayerXCoordinate = rsc_getBitMask(11, bitOffset, buffer)
  2974. local localPlayerXField = localPlayerInfoField:add(serverPlayerCoordsLocalRegionX, workingBuffer, localPlayerXCoordinate)
  2975. if not pinfoVisited then
  2976. thisLocalRegionX = localPlayerXCoordinate
  2977. end
  2978. bitOffset = bitOffset + 11
  2979. local localPlayerYCoordinate = rsc_getBitMask(13, bitOffset, buffer)
  2980. local localRegionYField = localPlayerInfoField:add(serverPlayerCoordsLocalRegionY, workingBuffer, localPlayerYCoordinate)
  2981. if not pinfoVisited then
  2982. thisLocalRegionY = localPlayerYCoordinate
  2983. end
  2984. bitOffset = bitOffset + 13
  2985. -- next nibble is animation
  2986. local localPlayerAnimation = rsc_getBitMask(4, bitOffset, buffer)
  2987. local animationField = localPlayerInfoField:add(serverPlayerCoordsAnimation, workingBuffer, localPlayerAnimation)
  2988. animationField:append_text(" (" .. ANIMATION_NAMES[localPlayerAnimation] .. ")")
  2989. bitOffset = bitOffset + 4
  2990. local animationUpdatesField = opcodeField:add("Animation Updates")
  2991. -- this byte is in the middle of the next 2 bytes
  2992. local playerCount = rsc_getBitMask(8, bitOffset, buffer)
  2993. local playerCountField = animationUpdatesField:add(serverPlayerCoordsPlayerCount, workingBuffer, playerCount)
  2994. bitOffset = bitOffset + 8
  2995. -- loadNextRegion() may have this impact on the variables we read in: TODO
  2996. -- regionX = thisLocalRegionX - 24
  2997. -- regionY = thisLocalRegionY - 24
  2998. thisLocalPlayer = rsc_createPlayer(1, thisLocalPlayerServerIndex, localPlayerYCoordinate, localPlayerXCoordinate, localPlayerAnimation)
  2999. thisPlayers[0] = thisLocalPlayer[1]
  3000. -- debugField:add("local player pid: " .. thisPlayers[0]["serverIndex"])
  3001. for index = 0, playerCount - 1 do
  3002. local reqUpdate = rsc_getBitMask(1, bitOffset, buffer)
  3003. local reqUpdateField = animationUpdatesField:add(serverPlayerCoordsAnimationUpdateRequired, workingBuffer, reqUpdate == 1)
  3004. bitOffset = bitOffset + 1
  3005. local relevantPlayerPID = thisKnownPlayers[index + 1]["serverIndex"]
  3006. if reqUpdate ~= 0 then
  3007. local updateType = rsc_getBitMask(1, bitOffset, buffer)
  3008. --bitViewField:add("updateType: " .. updateType) -- TODO: Not really going to expose this at this time because "who cares"
  3009. --TODO: improve the bit-view of these fields, and expose updateType
  3010. bitOffset = bitOffset + 1
  3011. if updateType ~= 0 then -- Animation update
  3012. local animationNextFragment = rsc_getBitMask(2, bitOffset, buffer)
  3013. if animationNextFragment ~= 3 then
  3014. thisKnownPlayers[index + 1]["animationNext"] = rsc_getBitMask(4, bitOffset, buffer)
  3015. bitOffset = bitOffset + 4
  3016. local animUpdateField = reqUpdateField:add(serverPlayerCoordsAnimationUpdate, workingBuffer, thisKnownPlayers[index + 1]["animationNext"])
  3017. animUpdateField:append_text(" (" .. ANIMATION_NAMES[thisKnownPlayers[index + 1]["animationNext"]] .. ")")
  3018. else
  3019. reqUpdateField:append_text(" (remove player)")
  3020. bitOffset = bitOffset + 2
  3021. thisKnownPlayers[index + 1]["removed"] = true
  3022. goto continuePlayer -- lol
  3023. end
  3024. else -- Animation update (while walking)
  3025. thisKnownPlayers[index + 1]["animationNext"] = rsc_getBitMask(3, bitOffset, buffer)
  3026. bitOffset = bitOffset + 3
  3027. local animUpdateField = reqUpdateField:add(serverPlayerCoordsAnimationUpdate, workingBuffer, thisKnownPlayers[index + 1]["animationNext"])
  3028. animUpdateField:append_text(" (" .. ANIMATION_NAMES[thisKnownPlayers[index + 1]["animationNext"]] .. ")")
  3029. end
  3030. end
  3031. thisPlayers[thisPlayerCount] = thisKnownPlayers[index + 1]
  3032. thisPlayerCount = thisPlayerCount + 1
  3033. ::continuePlayer::
  3034. reqUpdateField:prepend_text("(Username: " .. thisPlayerServer[relevantPlayerPID]["displayName"] .. ") ")
  3035. end
  3036. if (packetLength * 8 > bitOffset + 24) then
  3037. newPlayersField = opcodeField:add("Newly Created Player")
  3038. local newPlayersCount = math.floor((packetLength * 8 - bitOffset) / 25)
  3039. newPlayersField:prepend_text(newPlayersCount .. " ")
  3040. if newPlayersCount ~= 1 then
  3041. newPlayersField:append_text("s")
  3042. end
  3043. end
  3044. while (packetLength * 8 > bitOffset + 24) do
  3045. local serverIndex = rsc_getBitMask(11, bitOffset, buffer)
  3046. local newPlayersPIDField = newPlayersField:add(serverPlayerCoordsNewPlayerPID, workingBuffer, serverIndex)
  3047. bitOffset = bitOffset + 11
  3048. local areaX = rsc_getBitMask(5, bitOffset, buffer)
  3049. if areaX > 15 then
  3050. areaX = areaX - 32
  3051. end
  3052. local x = localPlayerXCoordinate + areaX
  3053. newPlayersPIDField:add(serverPlayerCoordsNewPlayerX, workingBuffer, x)
  3054. bitOffset = bitOffset + 5
  3055. local areaY = rsc_getBitMask(5, bitOffset, buffer)
  3056. if areaY > 15 then
  3057. areaY = areaY - 32
  3058. end
  3059. local y = localPlayerYCoordinate + areaY + thisPlaneFloor * thisPlaneDistanceBetweenFloors
  3060. newPlayersPIDField:add(serverPlayerCoordsNewPlayerY, workingBuffer, y)
  3061. bitOffset = bitOffset + 5
  3062. local anim = rsc_getBitMask(4, bitOffset, buffer)
  3063. local newPlayersPIDFieldAnimField = newPlayersPIDField:add(serverPlayerCoordsNewPlayerAnimation, workingBuffer, anim)
  3064. bitOffset = bitOffset + 4
  3065. newPlayersPIDFieldAnimField:append_text(" (" .. ANIMATION_NAMES[anim] .. ")")
  3066. local potentialNewPlayer = rsc_createPlayer(1, serverIndex, y, x, anim)
  3067. --if potentialNewPlayer[2] == false then -- TODO
  3068. thisPlayers[thisPlayerCount - 1] = potentialNewPlayer[1]
  3069. --end
  3070. end
  3071. -- for i = 0, thisPlayerCount - 1 do -- TODO: remove
  3072. -- debugField:add("pid: " .. thisPlayers[i]["serverIndex"] .. " thisPlayers[".. i .. "][\"displayName\"]: " .. thisPlayers[i]["displayName"])
  3073. -- end
  3074. -- 204 -- SERVER_OPCODE_PLAY_SOUND
  3075. elseif (serverOpcode == 204) then
  3076. -- standalone, doesn't require data from other opcodes
  3077. local soundBuffer = rsc_getRSCStringBuffer(buffer, 1)
  3078. opcodeField:add(serverSoundName, soundBuffer, rsc_readRSCString(soundBuffer))
  3079. -- 206 -- SERVER_OPCODE_SET_PRAYERS
  3080. elseif (serverOpcode == 206) then
  3081. -- standalone, doesn't require data from other opcodes
  3082. local prayerField = opcodeField:add(serverSetPrayersThickSkin, buffer(1, 1))
  3083. if (buffer(1, 1):int() == 1) then
  3084. prayerField:append_text(" (on)")
  3085. else
  3086. prayerField:append_text(" (off)")
  3087. end
  3088. local prayerField = opcodeField:add(serverSetPrayersBurstOfStrength, buffer(2, 1))
  3089. if (buffer(2, 1):int() == 1) then
  3090. prayerField:append_text(" (on)")
  3091. else
  3092. prayerField:append_text(" (off)")
  3093. end
  3094. local prayerField = opcodeField:add(serverSetPrayersClarityOfThought, buffer(3, 1))
  3095. if (buffer(3, 1):int() == 1) then
  3096. prayerField:append_text(" (on)")
  3097. else
  3098. prayerField:append_text(" (off)")
  3099. end
  3100. local prayerField = opcodeField:add(serverSetPrayersRockSkin, buffer(4, 1))
  3101. if (buffer(4, 1):int() == 1) then
  3102. prayerField:append_text(" (on)")
  3103. else
  3104. prayerField:append_text(" (off)")
  3105. end
  3106. local prayerField = opcodeField:add(serverSetPrayersSuperhumanStrength, buffer(5, 1))
  3107. if (buffer(5, 1):int() == 1) then
  3108. prayerField:append_text(" (on)")
  3109. else
  3110. prayerField:append_text(" (off)")
  3111. end
  3112. local prayerField = opcodeField:add(serverSetPrayersImprovedReflexes, buffer(6, 1))
  3113. if (buffer(6, 1):int() == 1) then
  3114. prayerField:append_text(" (on)")
  3115. else
  3116. prayerField:append_text(" (off)")
  3117. end
  3118. local prayerField = opcodeField:add(serverSetPrayersRapidRestore, buffer(7, 1))
  3119. if (buffer(7, 1):int() == 1) then
  3120. prayerField:append_text(" (on)")
  3121. else
  3122. prayerField:append_text(" (off)")
  3123. end
  3124. local prayerField = opcodeField:add(serverSetPrayersRapidHeal, buffer(8, 1))
  3125. if (buffer(8, 1):int() == 1) then
  3126. prayerField:append_text(" (on)")
  3127. else
  3128. prayerField:append_text(" (off)")
  3129. end
  3130. local prayerField = opcodeField:add(serverSetPrayersProtectItems, buffer(9, 1))
  3131. if (buffer(9, 1):int() == 1) then
  3132. prayerField:append_text(" (on)")
  3133. else
  3134. prayerField:append_text(" (off)")
  3135. end
  3136. local prayerField = opcodeField:add(serverSetPrayersSteelSkin, buffer(10, 1))
  3137. if (buffer(10, 1):int() == 1) then
  3138. prayerField:append_text(" (on)")
  3139. else
  3140. prayerField:append_text(" (off)")
  3141. end
  3142. local prayerField = opcodeField:add(serverSetPrayersUltimateStrength, buffer(11, 1))
  3143. if (buffer(11, 1):int() == 1) then
  3144. prayerField:append_text(" (on)")
  3145. else
  3146. prayerField:append_text(" (off)")
  3147. end
  3148. local prayerField = opcodeField:add(serverSetPrayersIncredibleReflexes, buffer(12, 1))
  3149. if (buffer(12, 1):int() == 1) then
  3150. prayerField:append_text(" (on)")
  3151. else
  3152. prayerField:append_text(" (off)")
  3153. end
  3154. local prayerField = opcodeField:add(serverSetPrayersParalyzeMonster, buffer(13, 1))
  3155. if (buffer(13, 1):int() == 1) then
  3156. prayerField:append_text(" (on)")
  3157. else
  3158. prayerField:append_text(" (off)")
  3159. end
  3160. local prayerField = opcodeField:add(serverSetPrayersProtectFromMissiles, buffer(14, 1))
  3161. if (buffer(14, 1):int() == 1) then
  3162. prayerField:append_text(" (on)")
  3163. else
  3164. prayerField:append_text(" (off)")
  3165. end
  3166. -- 210 -- SERVER_OPCODE_UPDATE_DUEL_ACCEPTANCE
  3167. elseif (serverOpcode == 210) then
  3168. -- standalone, doesn't require data from other opcodes
  3169. local acceptedDuelField = opcodeField:add(serverUpdateAcceptedDuelBool, buffer(1, 1))
  3170. if buffer(1, 1):uint() == 1 then
  3171. acceptedDuelField:append_text(" (Accepted)")
  3172. else
  3173. acceptedDuelField:append_text(" (Not Accepted)")
  3174. end
  3175. -- 211 -- SERVER_OPCODE_REMOVE_WORLD_ENTITY
  3176. elseif (serverOpcode == 211) then
  3177. -- not standalone
  3178. -- requires thisLocalRegionX and thisLocalRegionY
  3179. -- load / save those values
  3180. if pinfoVisited then
  3181. thisLocalRegionX = thisGameStateValuesAtThisTime[pinfoNumber][1]
  3182. thisLocalRegionY = thisGameStateValuesAtThisTime[pinfoNumber][2]
  3183. else
  3184. thisGameStateValuesAtThisTime[pinfoNumber] = { thisLocalRegionX, thisLocalRegionY }
  3185. end
  3186. -- TODO: possibly say what was removed at the coordinate, but it would be quite resource intensive and for not much benefit.
  3187. for offset = 1, buffer:len() - 1, 4 do
  3188. local xCoord = math.floor((buffer(offset, 2):int() / 8) + thisLocalRegionX)
  3189. local yCoord = math.floor((buffer(offset + 2, 2):int() / 8) + thisLocalRegionY)
  3190. local entityField = opcodeField:add("Remove any non-living thing at coordinate (" .. xCoord .. ", " .. yCoord .. ")")
  3191. entityField:add(serverRemoveWorldEntityXCoordinate, buffer(offset, 2), xCoord)
  3192. entityField:add(serverRemoveWorldEntityYCoordinate, buffer(offset + 2, 2), yCoord)
  3193. end
  3194. -- 222 -- SHOW_DIALOGUE_SERVER_MESSAGE_NOT_TOP
  3195. elseif (serverOpcode == 222) then
  3196. -- standalone, doesn't require data from other opcodes
  3197. local messageBuffer = rsc_getRSCStringBuffer(buffer, 1)
  3198. opcodeField:add(serverShowDialogueServerMessageTopMessage, messageBuffer, rsc_readRSCString(messageBuffer))
  3199. -- 234 -- SERVER_OPCODE_UPDATE_PLAYERS
  3200. elseif (serverOpcode == 234) then
  3201. -- not standalone
  3202. -- technically this could be a standalone opcode, but,
  3203. -- it also depends on itself in order to link the PID with the player's usernames.
  3204. local playerCount = buffer(1,2)
  3205. local offset = 3
  3206. local playerCountField = opcodeField:add(serverPlayerUpdatePlayerCount, playerCount)
  3207. for update = 0, playerCount:uint() - 1, 1 do
  3208. local pid = buffer(offset,2)
  3209. offset = offset + 2
  3210. local updateType = buffer(offset, 1)
  3211. offset = offset + 1
  3212. pidField = playerCountField:add(serverPlayerUpdatePID, pid)
  3213. pid = pid:int()
  3214. updateTypeField = pidField:add(serverPlayerUpdateUpdateType, updateType)
  3215. updateType = updateType:uint()
  3216. -- display bubble over player
  3217. if (updateType == 0) then
  3218. updateTypeField:append_text(" (display bubble)")
  3219. local itemID = buffer(offset, 2)
  3220. bubbleItem = updateTypeField:add(serverPlayerUpdateUpdateType0bubbleItem, itemID)
  3221. bubbleItem:append_text(" (" .. ITEM_NAMES[itemID:uint()] ..")")
  3222. offset = offset + 2
  3223. -- chat message
  3224. elseif (updateType == 1) then
  3225. updateTypeField:append_text(" (chat message)")
  3226. local modStatus = buffer(offset, 1)
  3227. offset = offset + 1
  3228. modStatusField = updateTypeField:add(serverPlayerUpdateUpdateType1modStatus, modStatus)
  3229. if (modStatus:int() == 0) then
  3230. modStatusField:append_text(" (not a mod)")
  3231. elseif (modStatus:int() == 1) then
  3232. modStatusField:append_text(" (pmod)")
  3233. elseif (modStatus:int() == 2) then
  3234. modStatusField:append_text(" (jmod)")
  3235. else
  3236. modStatusField:append_text(" (unknown)")
  3237. end
  3238. local method220Cache = method220(buffer, offset)
  3239. local messageLengthBuffer = method220Cache[1]
  3240. local messageLength = method220Cache[2]
  3241. updateTypeField:add(serverPlayerUpdateUpdateType1chatLength, messageLengthBuffer, messageLength)
  3242. offset = offset + method220Cache[3]
  3243. local method240Cache = method240(buffer, 0, offset, messageLength)
  3244. local scrambledChatMessageBufferLength = method240Cache[1]
  3245. local chatMessageInts = method240Cache[2]
  3246. updateTypeField:add(serverPlayerUpdateUpdateType1chatMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  3247. offset = offset + scrambledChatMessageBufferLength
  3248. -- update damage taken
  3249. elseif (updateType == 2) then
  3250. updateTypeField:append_text(" (damage update)")
  3251. local damage = buffer(offset, 1)
  3252. local currentHp = buffer(offset + 1, 1)
  3253. local maxHp = buffer(offset + 2, 1)
  3254. offset = offset + 3
  3255. updateTypeField:add(serverPlayerUpdateUpdateType2damage, damage)
  3256. updateTypeField:add(serverPlayerUpdateUpdateType2currentHp, currentHp)
  3257. updateTypeField:add(serverPlayerUpdateUpdateType2maxHp, maxHp)
  3258. -- show projectile sprite from player towards NPC
  3259. elseif (updateType == 3) then
  3260. updateTypeField:append_text(" (show projectile from player to NPC)")
  3261. local sprite = buffer(offset, 2)
  3262. spriteType = updateTypeField:add(serverPlayerUpdateUpdateType3sprite, sprite)
  3263. offset = offset + 2
  3264. spriteType:append_text(" (" .. SPRITE_TYPES[sprite:int()] .. ")")
  3265. local shooterServerIndex = buffer(offset, 2) -- TODO: interpret who this is
  3266. offset = offset + 2
  3267. updateTypeField:add(serverPlayerUpdateUpdateType3shooterServerIndex, shooterServerIndex)
  3268. -- show projectile sprite between 2 players
  3269. elseif (updateType == 4) then
  3270. updateTypeField:append_text(" (show projectile from player to player)")
  3271. local sprite = buffer(offset, 2)
  3272. local spriteField = updateTypeField:add(serverPlayerUpdateUpdateType4sprite, sprite)
  3273. offset = offset + 2
  3274. spriteField:append_text(" (" .. SPRITE_TYPES[sprite:int()] .. ")")
  3275. local shooterServerIndex = buffer(offset, 2) -- TODO: interpret who this is
  3276. offset = offset + 2
  3277. bubbleItem = updateTypeField:add(serverPlayerUpdateUpdateType4shooterServerIndex, shooterServerIndex)
  3278. -- equipment change
  3279. elseif (updateType == 5) then
  3280. updateTypeField:append_text(" (equipment change, player name & appearance)")
  3281. local serverIndex = buffer(offset, 2)
  3282. offset = offset + 2
  3283. updateTypeField:add(serverPlayerUpdateUpdateType5serverIndex, serverIndex)
  3284. local username1 = rsc_getRSCStringBuffer(buffer, offset)
  3285. offset = offset + username1:len()
  3286. local username = rsc_readRSCString(username1)
  3287. updateTypeField:add(serverPlayerUpdateUpdateType5username1, username1, username)
  3288. thisPlayerServer[pid]["displayName"] = username
  3289. local username2 = rsc_getRSCStringBuffer(buffer, offset)
  3290. offset = offset + username2:len()
  3291. local accountName = rsc_readRSCString(username2)
  3292. updateTypeField:add(serverPlayerUpdateUpdateType5username2, username2, accountName)
  3293. thisPlayerServer[pid]["accountName"] = accountName
  3294. local equipCount = buffer(offset, 1)
  3295. offset = offset + 1
  3296. updateTypeField:add(serverPlayerUpdateUpdateType5equipCount, equipCount)
  3297. local equipment = buffer(offset, equipCount:uint())
  3298. equipmentField = updateTypeField:add(serverPlayerUpdateUpdateType5equipment, equipment)
  3299. local slot = {}
  3300. slot[0] = "Hair Style: "
  3301. slot[1] = "Shirt Style: "
  3302. slot[2] = "Pants Style: "
  3303. slot[3] = "Shield: "
  3304. slot[4] = "Weapon: "
  3305. slot[5] = "Head: "
  3306. slot[6] = "Body: "
  3307. slot[7] = "Legs: "
  3308. slot[8] = "Glove: "
  3309. slot[9] = "Boots: "
  3310. slot[10] = "Amulet: "
  3311. slot[11] = "Cape: "
  3312. for i = 0, equipCount:uint() - 1, 1 do
  3313. local equipField = equipmentField:add(buffer(offset, 1), slot[i] .. buffer(offset, 1):uint())
  3314. thisPlayerServer[pid]["equippedItem"][i] = buffer(offset, 1):uint()
  3315. equipField:append_text(" (" .. ANIMATION_SPRITE_NAMES[thisPlayerServer[pid]["equippedItem"][i]] .. ")")
  3316. offset = offset + 1
  3317. end
  3318. local hairColourField = updateTypeField:add(serverPlayerUpdateUpdateType5hairColor, buffer(offset, 1))
  3319. thisPlayerServer[pid]["colourHair"] = buffer(offset, 1):int()
  3320. hairColourField:append_text(" (HTML Colour: " .. HAIR_COLOURS_STRING[thisPlayerServer[pid]["colourHair"]] .. ") (English Name: " .. HAIR_COLOUR_NAMES[thisPlayerServer[pid]["colourHair"]] .. ")")
  3321. local topColourField = updateTypeField:add(serverPlayerUpdateUpdateType5topColor, buffer(offset + 1, 1))
  3322. thisPlayerServer[pid]["colourTop"] = buffer(offset + 1, 1):int()
  3323. topColourField:append_text(" (HTML Colour: " .. CLOTHING_COLOURS_STRING[thisPlayerServer[pid]["colourTop"]] .. ") (English Name: " .. CLOTHING_COLOUR_NAMES[thisPlayerServer[pid]["colourTop"]] .. ")")
  3324. local bottomColourField = updateTypeField:add(serverPlayerUpdateUpdateType5bottomColor, buffer(offset + 2, 1))
  3325. thisPlayerServer[pid]["colourBottom"] = buffer(offset + 2, 1):int()
  3326. bottomColourField:append_text(" (HTML Colour: " .. CLOTHING_COLOURS_STRING[thisPlayerServer[pid]["colourBottom"]] .. ") (English Name: " .. CLOTHING_COLOUR_NAMES[thisPlayerServer[pid]["colourBottom"]] .. ")")
  3327. local skinColourField = updateTypeField:add(serverPlayerUpdateUpdateType5skinColor, buffer(offset + 3, 1))
  3328. thisPlayerServer[pid]["colourSkin"] = buffer(offset + 3, 1):int()
  3329. skinColourField:append_text(" (HTML Colour: " .. SKIN_COLOURS_STRING[thisPlayerServer[pid]["colourSkin"]] .. ") (English Name: " .. SKIN_COLOUR_NAMES[thisPlayerServer[pid]["colourSkin"]] .. ")")
  3330. updateTypeField:add(serverPlayerUpdateUpdateType5level, buffer(offset + 4, 1))
  3331. thisPlayerServer[pid]["level"] = buffer(offset + 4, 1):int()
  3332. local skullField = updateTypeField:add(serverPlayerUpdateUpdateType5skull, buffer(offset + 5, 1))
  3333. thisPlayerServer[pid]["skullVisible"] = buffer(offset + 5, 1):int()
  3334. skullField:append_text(" (" .. boolToEnglish(thisPlayerServer[pid]["skullVisible"]) .. ")")
  3335. offset = offset + 6
  3336. -- quest chat over players' heads
  3337. elseif (updateType == 6) then
  3338. updateTypeField:append_text(" (quest chat from player)")
  3339. local method220Cache = method220(buffer, offset)
  3340. local messageLengthBuffer = method220Cache[1]
  3341. local messageLength = method220Cache[2]
  3342. updateTypeField:add(serverPlayerUpdateUpdateType6chatLength, messageLengthBuffer, messageLength)
  3343. offset = offset + method220Cache[3]
  3344. local method240Cache = method240(buffer, 0, offset, messageLength)
  3345. local scrambledChatMessageBufferLength = method240Cache[1]
  3346. local chatMessageInts = method240Cache[2]
  3347. updateTypeField:add(serverPlayerUpdateUpdateType6chatMessage, buffer(offset, scrambledChatMessageBufferLength), byteArrayToString(chatMessageInts))
  3348. offset = offset + scrambledChatMessageBufferLength
  3349. else
  3350. -- There is not actually another update type
  3351. -- but there was client logic for an "else" that hypothetically
  3352. -- might have been hit if the player was null
  3353. -- (it would have also been hit if there was another update type)
  3354. updateTypeField:append_text(" (unknown)")
  3355. -- TODO: determine if this condition was ever hit in any known replays
  3356. end
  3357. pidField:append_text(" (Username: " .. thisPlayerServer[pid]["displayName"] .. ") ")
  3358. end
  3359. -- 237 -- SERVER_OPCODE_UPDATE_IGNORE_BECAUSE_OF_NAME_CHANGE
  3360. elseif (serverOpcode == 237) then
  3361. -- standalone, doesn't require data from other opcodes
  3362. local offset = 1
  3363. local ignoreListNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  3364. local ignoreListNameValue = rsc_readRSCString(ignoreListNameBuffer)
  3365. opcodeField:add(serverUpdateIgnoreBecauseOfNameChangeIgnoreListName, ignoreListNameBuffer, ignoreListNameValue)
  3366. offset = offset + ignoreListNameBuffer:len()
  3367. local ignoreListAccountNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  3368. local ignoreListAccountNameValue = rsc_readRSCString(ignoreListAccountNameBuffer)
  3369. opcodeField:add(serverUpdateIgnoreBecauseOfNameChangeIgnoreListAccountName, ignoreListAccountNameBuffer, ignoreListAccountNameValue)
  3370. offset = offset + ignoreListAccountNameBuffer:len()
  3371. local ignoreListOldNameBuffer = rsc_getRSCStringBuffer(buffer, offset)
  3372. local ignoreListOldNameValue = rsc_readRSCString(ignoreListOldNameBuffer)
  3373. opcodeField:add(serverUpdateIgnoreBecauseOfNameChangeIgnoreListOldName, ignoreListOldNameBuffer, ignoreListOldNameValue)
  3374. offset = offset + ignoreListOldNameBuffer:len()
  3375. local ignoreListServersBuffer = rsc_getRSCStringBuffer(buffer, offset)
  3376. local ignoreListServersValue = rsc_readRSCString(ignoreListServersBuffer)
  3377. opcodeField:add(serverUpdateIgnoreBecauseOfNameChangeIgnoreListServers, ignoreListServersBuffer, ignoreListServersValue)
  3378. offset = offset + ignoreListServersBuffer:len()
  3379. local updateExistingField = opcodeField:add(serverUpdateIgnoreBecauseOfNameChangeAttemptUpdatingExistingEntry, buffer(offset, 1), buffer(offset, 1):int() == 1)
  3380. updateExistingField:append_text(" (currently no known replays that show this value being true)")
  3381. -- 240 -- SERVER_OPCODE_GAME_SETTINGS
  3382. elseif (serverOpcode == 240) then
  3383. -- standalone, doesn't require data from other opcodes
  3384. local cameraModeAuto = buffer(1, 1)
  3385. local mouseModeOne = buffer(2, 1)
  3386. local disableSound = buffer(3, 1)
  3387. local field = opcodeField:add(serverCameraModeAuto, cameraModeAuto)
  3388. if (cameraModeAuto:uint() == 1) then
  3389. field:append_text(" (Auto)")
  3390. else
  3391. field:append_text(" (Manual)")
  3392. end
  3393. field = opcodeField:add(serverMouseButtonOne, mouseModeOne)
  3394. if (mouseModeOne:uint() == 1) then
  3395. field:append_text(" (One)")
  3396. else
  3397. field:append_text(" (Two)")
  3398. end
  3399. field = opcodeField:add(serverSoundDisabled, disableSound)
  3400. if (disableSound:uint() == 1) then
  3401. field:append_text(" (Disabled)")
  3402. else
  3403. field:append_text(" (Enabled)")
  3404. end
  3405. -- 244 -- SERVER_OPCODE_SET_FATIGUE_SLEEPING
  3406. elseif (serverOpcode == 244) then
  3407. -- standalone, doesn't require data from other opcodes
  3408. opcodeField:add(serverSetFatigueSleepingFatigueSleeping, buffer(1, 2), buffer(1, 2):int() / 7.5)
  3409. -- 245 -- SERVER_OPCODE_SHOW_DIALOGUE_MENU
  3410. elseif (serverOpcode == 245) then
  3411. -- standalone, doesn't require data from other opcodes
  3412. local optionCount = buffer(1, 1)
  3413. local menuCountField = opcodeField:add(serverShowDialogueMenuCount, optionCount)
  3414. local offset = 2
  3415. for i = 0, optionCount:uint() - 1, 1 do
  3416. local stringBuffer = rsc_getRSCStringBuffer(buffer, offset)
  3417. local stringValue = rsc_readRSCString(stringBuffer)
  3418. local stringTree = menuCountField:add(serverShowDialogueMenuString, stringBuffer, "")
  3419. stringTree:set_text("Option (" .. i .. "): " .. stringValue)
  3420. if not pinfoVisited then
  3421. thisOptionCache[i] = stringValue
  3422. end
  3423. offset = offset + stringBuffer:len()
  3424. end
  3425. -- 249 -- SERVER_OPCODE_UPDATE_BANK_ITEM_DISPLAY
  3426. elseif (serverOpcode == 249) then
  3427. -- standalone, doesn't require data from other opcodes
  3428. local slotField = opcodeField:add(serverUpdateBankItemDisplaySlot, buffer(1, 1))
  3429. local slot = buffer (1, 1):uint()
  3430. local page = math.floor(slot / 48) + 1
  3431. local row = math.floor((slot % 48) / 8) + 1
  3432. local column = math.floor((slot % 48) % 8) + 1
  3433. slotField:append_text(" (Page " .. page .. ", Row " .. row .. ", Column " .. column .. ")")
  3434. local itemIDField = opcodeField:add(serverUpdateBankItemDisplayItemID, buffer(2, 2))
  3435. itemIDField:append_text(" (" .. ITEM_NAMES[buffer(2, 2):int()] .. ")")
  3436. local count = rsc_getUnsignedInt3(buffer, 4)
  3437. itemIDField:add(serverUpdateBankItemDisplayItemCount, count[1], count[2])
  3438. -- TODO: you'll most likely want to actually implement the bank slot shifting code here in order to track CLIENT_BANK_WITHDRAW & other stuff
  3439. -- 253 -- SERVER_OPCODE_UPDATE_DUEL_OPPONENT_ACCEPTED
  3440. elseif (serverOpcode == 253) then
  3441. -- standalone, doesn't require data from other opcodes
  3442. local duelAcceptedField = opcodeField:add(serverUpdateDuelOpponentAccepted, buffer(1, 1))
  3443. if (buffer(1, 1):int() == 1) then
  3444. duelAcceptedField:append_text(" (Accepted)")
  3445. else
  3446. duelAcceptedField:append_text(" (Not Accepted)")
  3447. end
  3448. end
  3449. end
  3450. end
  3451. function bytesToString(bytes)
  3452. local length = bytes:len()
  3453. local bytesString = bytes(0, 1):uint()
  3454. for i = 1, length - 1, 1 do
  3455. bytesString = bytesString .. " " .. bytes(i, 1):uint()
  3456. end
  3457. return bytesString
  3458. end
  3459. function boolToEnglish(bool)
  3460. if bool == 0 then
  3461. return "No"
  3462. else
  3463. return "Yes"
  3464. end
  3465. end
  3466. function byteArrayToString(bytes)
  3467. local length = #bytes
  3468. local bytesString = string.char(bytes[1])
  3469. for i = 2, length do
  3470. bytesString = bytesString .. string.char(bytes[i])
  3471. end
  3472. return bytesString
  3473. end
  3474. function rscStringCrop(buffer)
  3475. return buffer(1, buffer:len() - 2):string()
  3476. end
  3477. function rsc_getPacketLengthBuffer(buffer, offset)
  3478. local length = buffer(offset, 1)
  3479. if (length:uint() >= 160) then
  3480. length = buffer(offset, 2)
  3481. end
  3482. return length
  3483. end
  3484. function rsc_getRSCStringBuffer(buffer, offset)
  3485. local length = 1
  3486. local value = buffer(offset + 1, 1)
  3487. while (value:uint() ~= 0) do
  3488. length = length + 1
  3489. value = buffer(offset + length, 1)
  3490. end
  3491. length = length + 1
  3492. return buffer(offset, length)
  3493. end
  3494. function rsc_getUnsignedInt3(buffer, offset)
  3495. if buffer(offset, 1):int() >= 0 then
  3496. return { buffer(offset, 2), buffer(offset, 2):uint() }
  3497. else
  3498. return { buffer(offset, 4), bit.band(buffer(offset, 4):uint(), 2147483647) }
  3499. end
  3500. end
  3501. function rsc_readPacketLength(buffer)
  3502. local length = buffer(0, 1):uint()
  3503. if (buffer:len() > 1) then
  3504. length = 256 * length - (40960 - buffer(1, 1):uint())
  3505. end
  3506. return length
  3507. end
  3508. function rsc_readRSCString(buffer)
  3509. local RSCString = ""
  3510. local length = buffer:len()
  3511. for i = 1, length - 2, 1 do
  3512. value = buffer(i, 1):uint()
  3513. if (value == 160) then -- 0xa0 in hex
  3514. RSCString = RSCString .. " "
  3515. else
  3516. RSCString = RSCString .. string.char(value)
  3517. end
  3518. end
  3519. return RSCString
  3520. end
  3521. -- Keeping anIntArray486 instead of "2^bitsToGet - 1" because anIntArray486 is faster
  3522. anIntArray486 = { 1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535,131071,262143,524287,1048575,2097151,4194303,8388607,16777215,33554431,67108863,134217727,268435455,536870911,1073741823,2147483647,-1 }
  3523. anIntArray486[0] = 0
  3524. -- reads "bitsToGet" bits from the entire buffer, starting at bitOffset
  3525. -- reimplemented for lua datatypes where :int() can return an 8 bit int, a 16 bit int, or a 32 bit int (maybe 24 bit int too!)
  3526. function rsc_getBitMask(bitsToGet, bitOffset, buffer)
  3527. local byteOffset = math.floor(bitOffset / 8)
  3528. local spannedBytes = math.ceil((bitsToGet + bitOffset % 8) / 8)
  3529. workingBuffer = buffer(byteOffset + 1, spannedBytes)
  3530. bitOffset = bitOffset - byteOffset * 8
  3531. return bit.band(bit.rshift(workingBuffer:int(), spannedBytes * 8 - bitsToGet - bitOffset), anIntArray486[bitsToGet])
  3532. end
  3533. -- Cheat on not having to reimplement anIntArray209 in lua by precomputing it
  3534. -- In case you are uninitiated, this is a dictionary used for decoding chat in opcode 234 update types 1 & 6, for NPC chat, and also for Send/Receive PMs
  3535. -- anIntArray209 contains 512 elements.
  3536. anIntArray209 = { 215,203,83,158,104,101,93,84,107,103,109,95,94,98,89,86,70,41,32,27,24,23,-1,-2,26,-3,-4,31,30,-5,-6,-7,37,38,36,-8,-9,-10,40,-11,-12,55,48,46,47,-13,-14,-15,52,51,-16,-17,54,-18,-19,63,60,59,-20,-21,62,-22,-23,67,66,-24,-25,69,-26,-27,199,132,80,77,76,-28,-29,79,-30,-31,87,85,-32,-33,-34,-35,-36,197,-37,91,-38,134,-39,-40,-41,97,-42,-43,133,106,-44,117,-45,-46,139,-47,-48,110,-49,-50,114,113,-51,-52,116,-53,-54,135,138,136,129,125,124,-55,-56,130,128,-57,-58,-59,183,-60,-61,-62,-63,-64,148,-65,-66,153,149,145,144,-67,-68,147,-69,-70,-71,152,154,-72,-73,-74,157,171,-75,-76,207,184,174,167,166,165,-77,-78,-79,172,170,-80,-81,-82,178,-83,177,182,-84,-85,187,181,-86,-87,-88,-89,206,221,-90,189,-91,198,254,262,195,196,-92,-93,-94,-95,-96,252,255,250,-97,211,209,-98,-99,212,-100,213,-101,-102,-103,224,-104,232,227,220,226,-105,-106,246,236,-107,243,-108,-109,231,237,235,-110,-111,239,238,-112,-113,-114,-115,-116,241,-117,244,-118,-119,248,-120,249,-121,-122,-123,253,-124,-125,-126,-127,259,258,-128,-129,261,-130,-131,390,327,296,281,274,271,270,-132,-133,273,-134,-135,278,277,-136,-137,280,-138,-139,289,286,285,-140,-141,288,-142,-143,293,292,-144,-145,295,-146,-147,312,305,302,301,-148,-149,304,-150,-151,309,308,-152,-153,311,-154,-155,320,317,316,-156,-157,319,-158,-159,324,323,-160,-161,326,-162,-163,359,344,337,334,333,-164,-165,336,-166,-167,341,340,-168,-169,343,-170,-171,352,349,348,-172,-173,351,-174,-175,356,355,-176,-177,358,-178,-179,375,368,365,364,-180,-181,367,-182,-183,372,371,-184,-185,374,-186,-187,383,380,379,-188,-189,382,-190,-191,387,386,-192,-193,389,-194,-195,454,423,408,401,398,397,-196,-197,400,-198,-199,405,404,-200,-201,407,-202,-203,416,413,412,-204,-205,415,-206,-207,420,419,-208,-209,422,-210,-211,439,432,429,428,-212,-213,431,-214,-215,436,435,-216,-217,438,-218,-219,447,444,443,-220,-221,446,-222,-223,451,450,-224,-225,453,-226,-227,486,471,464,461,460,-228,-229,463,-230,-231,468,467,-232,-233,470,-234,-235,479,476,475,-236,-237,478,-238,-239,483,482,-240,-241,485,-242,-243,499,495,492,491,-244,-245,494,-246,-247,497,-248,502,-249,506,503,-250,-251,505,-252,-253,508,-254,510,-255,-256,0 }
  3537. -- BufferBase_Sub3 method220 determines length of message
  3538. function method220(buffer, offset)
  3539. local messageLengthTenative = buffer(offset, 1)
  3540. local messageLengthBuffer -- can be either 1 or 2 bytes long
  3541. local messageLength -- how many characters are in the message the player sent (not directly related to the number of bytes)
  3542. if (messageLengthTenative:uint() < 128) then
  3543. messageLengthBuffer = buffer(offset, 1)
  3544. messageLength = messageLengthBuffer:uint()
  3545. return { messageLengthBuffer, messageLength, 1 }
  3546. else
  3547. messageLengthBuffer = buffer(offset, 2)
  3548. messageLength = messageLengthBuffer:uint() - 32768
  3549. return { messageLengthBuffer, messageLength, 2 }
  3550. end
  3551. end
  3552. -- from Class11.java, takes each byte in the opcode data as an instruction on how to read anIntArray209
  3553. function method240(opcodeBuffer, returnStringIndex, currentBufferOffset, chatLength)
  3554. if (chatLength == 0) then
  3555. return { 0, "" }
  3556. else
  3557. local scrambleIndex = 0
  3558. local returnLength = currentBufferOffset
  3559. local returnString = {}
  3560. while (true)
  3561. do
  3562. currentByte = opcodeBuffer(returnLength, 1):int()
  3563. -----------------------------------------------------------------
  3564. if (currentByte >= 0) then
  3565. scrambleIndex = scrambleIndex + 1
  3566. else
  3567. scrambleIndex = anIntArray209[scrambleIndex + 1]
  3568. end
  3569. decodedCharacter = anIntArray209[scrambleIndex + 1]
  3570. if (decodedCharacter < 0) then
  3571. returnString[returnStringIndex + 1] = bit.bnot(decodedCharacter)
  3572. returnStringIndex = returnStringIndex + 1
  3573. scrambleIndex = 0
  3574. end
  3575. -----------------------------------------------------------------
  3576. for bitIndex = 6, 0, -1 do
  3577. if (bit.band(currentByte, 2^bitIndex) == 0) then
  3578. scrambleIndex = scrambleIndex + 1
  3579. else
  3580. scrambleIndex = anIntArray209[scrambleIndex + 1]
  3581. end
  3582. decodedCharacter = anIntArray209[scrambleIndex + 1]
  3583. if (decodedCharacter < 0) then
  3584. returnString[returnStringIndex + 1] = bit.bnot(decodedCharacter)
  3585. returnStringIndex = returnStringIndex + 1
  3586. scrambleIndex = 0
  3587. end
  3588. end
  3589. -----------------------------------------------------------------
  3590. returnLength = returnLength + 1
  3591. if (returnStringIndex >= chatLength) then
  3592. break
  3593. end
  3594. if (returnLength >= opcodeBuffer:len()) then
  3595. break
  3596. end
  3597. end
  3598. return { returnLength - currentBufferOffset, returnString }
  3599. end
  3600. end
  3601. function calculateShopItemPrice(basePrice, amountInStock, baseAmountInStock, degreeToWhichShopkeeperCaresAboutStock, generosityBonus)
  3602. howMuchICareAboutMyOverstockUnderstockSituation = degreeToWhichShopkeeperCaresAboutStock * (baseAmountInStock - amountInStock)
  3603. -- clamp howMuchICareAboutMyOverstockUnderstockSituation to -100 to 100 range
  3604. if howMuchICareAboutMyOverstockUnderstockSituation < -100 then
  3605. howMuchICareAboutMyOverstockUnderstockSituation = -100
  3606. elseif howMuchICareAboutMyOverstockUnderstockSituation > 100 then
  3607. howMuchICareAboutMyOverstockUnderstockSituation = 100
  3608. end
  3609. -- clamp hectoBasePriceMultiplier to be at least positive 10
  3610. hectoBasePriceMultiplier = generosityBonus + howMuchICareAboutMyOverstockUnderstockSituation
  3611. if (hectoBasePriceMultiplier < 10) then
  3612. hectoBasePriceMultiplier = 10
  3613. end
  3614. return math.floor((basePrice * hectoBasePriceMultiplier) / 100)
  3615. end
  3616. function rsc_createPlayer(wipeTradeItems, serverIndex, yPos, xPos, animation)
  3617. if (wipeTradeItems ~= 1) then
  3618. thisTradeConfirmItems = nil
  3619. end
  3620. local alreadyKnownPlayer = false
  3621. for i = 0, thisKnownPlayerCount - 1 do
  3622. if (thisKnownPlayers[i]["serverIndex"] == serverIndex) then
  3623. if (thisKnownPlayers[i]["removed"] == false) then
  3624. alreadyKnownPlayer = true
  3625. break
  3626. end
  3627. end
  3628. end
  3629. thisPlayerServer[serverIndex]["serverIndex"] = serverIndex
  3630. thisPlayerServer[serverIndex]["waypointCurrent"] = 0
  3631. thisPlayerServer[serverIndex]["movingStep"] = 0
  3632. thisPlayerServer[serverIndex]["stepCount"] = 0
  3633. thisPlayerServer[serverIndex]["waypointsX"][0] = xPos
  3634. thisPlayerServer[serverIndex]["currentX"] = xPos
  3635. thisPlayerServer[serverIndex]["waypointsY"][0] = yPos
  3636. thisPlayerServer[serverIndex]["currentY"] = yPos
  3637. thisPlayerServer[serverIndex]["animationNext"] = animation
  3638. thisPlayerServer[serverIndex]["animationCurrent"] = animation
  3639. thisPlayerServer[serverIndex]["removed"] = false -- this is not part of normal client code, just a helper here in lua
  3640. if ((xPos ~= thisPlayerServer[serverIndex]["waypointsX"][thisPlayerServer[serverIndex]["waypointCurrent"]]) or (yPos ~= thisPlayerServer[serverIndex]["waypointsY"][thisPlayerServer[serverIndex]["waypointCurrent"]])) then
  3641. thisPlayerServer[serverIndex]["waypointCurrent"] = (thisPlayerServer[serverIndex]["waypointCurrent"] + 1) % 10
  3642. thisPlayerServer[serverIndex]["waypointsX"][thisPlayerServer[serverIndex]["waypointCurrent"]] = xPos
  3643. thisPlayerServer[serverIndex]["waypointsY"][thisPlayerServer[serverIndex]["waypointCurrent"]] = ypos
  3644. end
  3645. thisPlayerCount = thisPlayerCount + 1
  3646. return { thisPlayerServer[serverIndex], alreadyKnownPlayer }
  3647. end
  3648. function rsc_createNPC(serverIndex, yPos, xPos, animation, npcId)
  3649. thisNpcsServer[serverIndex]["serverIndex"] = serverIndex
  3650. thisNpcsServer[serverIndex]["waypointCurrent"] = 0
  3651. thisNpcsServer[serverIndex]["movingStep"] = 0
  3652. thisNpcsServer[serverIndex]["stepCount"] = 0
  3653. thisNpcsServer[serverIndex]["waypointsX"][0] = xPos
  3654. thisNpcsServer[serverIndex]["currentX"] = xPos
  3655. thisNpcsServer[serverIndex]["waypointsY"][0] = yPos
  3656. thisNpcsServer[serverIndex]["currentY"] = yPos
  3657. thisNpcsServer[serverIndex]["npcId"] = npcId
  3658. thisNpcsServer[serverIndex]["animationNext"] = animation
  3659. thisNpcsServer[serverIndex]["animationCurrent"] = animation
  3660. thisNpcsServer[serverIndex]["removed"] = false -- this is not part of normal client code, just a helper here in lua
  3661. return thisNpcsServer[serverIndex]
  3662. end
  3663. function rsc235_protocol.dissector(buffer, pinfo, tree)
  3664. length = buffer:len()
  3665. if length == 0 then return end
  3666. pinfo.cols.protocol = rsc235_protocol.name
  3667. local clientPacketValue = buffer(0, 1)
  3668. local clientOpcodeValue = buffer(1, 4)
  3669. local opcodeName = resolveOpcodeName(clientPacketValue:uint(), clientOpcodeValue:uint())
  3670. pinfo.cols['info'] = opcodeName
  3671. local header_subtree = tree:add(rsc235_protocol, buffer(0, 5), "rscminus Header")
  3672. local clientPacketField = header_subtree:add(clientPacket, clientPacketValue)
  3673. if (clientPacketValue:uint() == 1) then
  3674. clientPacketField:append_text(" (Client)")
  3675. else
  3676. clientPacketField:append_text(" (Server)")
  3677. end
  3678. local clientOpcodeField = header_subtree:add(clientOpcode, clientOpcodeValue)
  3679. clientOpcodeField:append_text(" (" .. opcodeName .. ")")
  3680. local data_buffer = buffer(5)
  3681. local data_subtree = tree:add(rsc235_protocol, data_buffer, "RSC235 Data")
  3682. if not gui_enabled() then
  3683. addOpcodeData(clientPacketValue:uint(), clientOpcodeValue:uint(), data_subtree, data_buffer, pinfo.number, pinfo.visited)
  3684. return
  3685. end
  3686. if thisDebugging then
  3687. debugWindow:append(pinfo.number)
  3688. debugWindow:append(", ")
  3689. debugWindow:append(tostring(pinfo.visited))
  3690. debugWindow:append("\n")
  3691. end
  3692. addOpcodeData(clientPacketValue:uint(), clientOpcodeValue:uint(), data_subtree, data_buffer, pinfo.number, pinfo.visited)
  3693. end
  3694. local ethertype_table = DissectorTable.get("ethertype")
  3695. ethertype_table:add(0x0, rsc235_protocol)