ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/html5client/main.js
Revision: 1.19
Committed: Thu Nov 8 03:49:04 2012 UTC (11 years, 7 months ago) by root
Content type: application/javascript
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +0 -0 lines
State: FILE REMOVED
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra clientV.
3 *
4 * Copyright (©) 2012 Marek Olszewski <m.olszewski@wit.edu.pl>
5 *
6 * Deliantra clientV is free software: you can redistribute it and/or
7 * modify it under the terms of the Affero GNU General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the Affero GNU General Public Licens
17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>.
19 *
20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */
22
23 String.prototype.each = function (f,p){
24 for (var i=0;i<this.length;++i){
25 f.apply(this,[this[i],i,p]);
26 }
27 };
28
29 Array.prototype.each = function (f,p){
30 for (var i=0;i<this.length;++i){
31 f.apply(this,[this[i],i,p]);
32 }
33 };
34
35 Array.prototype.contains = function (e){
36 return this.indexOf(e) >= 0 && this.indexOf(e)<this.length;
37 }
38
39 var ctx = null;
40 var stage = null;
41 var output = null;
42 var commandline = null;
43
44 var channels = {length: 0,list: []};
45
46 var dx=0;
47 var dy=0;
48
49 var Map = null;
50
51 messageBox = window.alert;
52
53 alert = function (s){
54 writeToScreen(s);
55 }
56
57 var floorItems = [];
58 var myItems = [];
59 var mySpells = [];
60 var myStats = [];
61 var skillNames = [];
62
63 var skipKeyTest = false;
64
65 var keys = {
66 shift: 0,
67 alt: 0,
68 ctrl: 0,
69 states : []
70 };
71
72 var player = {
73 tag: 0,
74 weight: 0,
75 face: 0,
76 name: ""
77 }
78
79
80 var versionInfo = {
81 perlver: "5.014002",
82 clientver: "3.0Af0000000",
83 client: "deliantra",
84 gl_vendor: "NVIDIA Corporation",
85 gl_version: "4.2.0 NVIDIA 302.11",
86 modulever: "1.31",
87 osver: "linux",
88 protver: 1
89 };
90 var expTableFacenum = -1;
91
92 var isRunning = false;
93 var isFiring = false;
94
95 mapsize = {width: 0,height:0};
96
97 var currentWindow=null;
98 var currentWindowOffset = {x:0,y:0};
99 var currentWindowResize = false;
100
101 var xMapWindow = null;
102 var xFloorWindow = null;
103 var xPlayerWindow = null;
104 var pattern = null;
105 var patternImage = null;
106 var isMainCalled = false;
107 var xInfoWindow = null;
108 var xBarsWindow = null;
109 var xCommmandWindow = null;
110 var xChatBoxWindow = null;
111
112 function appendToBody(e){
113 document.getElementsByTagName("body")[0].appendChild(e);
114 }
115
116 function getPassword (){
117 return document.getElementById("password").value.trim();
118 }
119
120 function getLogin (){
121 return document.getElementById("login").value.trim();
122 }
123
124 function createCommandWindow (){
125 var div = createWindow("command",250,250,stage.stageWidth/2-250/2,stage.stageHeight-250/2);
126 var login = document.createElement("input");
127 login.type = "text";
128 login.placeholder = login.id = "command";
129 login.style.width = "100%";
130
131 div.contents.appendChild(login);
132
133 var button = document.createElement("input");
134 button.type = "button";
135 button.value = "execute command";
136 button.style.width = "100%";
137 div.contents.appendChild(button);
138 button.addEventListener("click",function (e){
139 doSend("command " + login.value);
140 xCommmandWindow.show(false);
141 skipKeyTest = false;
142 })
143 var button = document.createElement("input");
144 button.type = "button";
145 button.value = "cancel";
146 button.style.width = "100%";
147 div.contents.appendChild(button);
148 button.addEventListener("click",function (e){
149 xCommmandWindow.show(false);
150 skipKeyTest = false;
151 })
152 return div;
153
154 }
155
156 function createLoginWindow(){
157 var div = createWindow("login",260,180,stage.stageWidth/2-250/2,stage.stageHeight/2-250/2).contents;;
158 var login = document.createElement("input");
159 login.type = "text";
160 login.placeholder = login.id = "login";
161 login.style.width = "100%";
162 login.value = "deliantra login";
163 div.appendChild(login);
164 var password = document.createElement("input");
165 password.type = "password";
166 password.value = "";
167 password.style.width = "100%";
168 password.placeholder = password.id = "password";
169 div.appendChild(password);
170
171 var button = document.createElement("input");
172 button.type = "button";
173 button.value = "logmein";
174 button.style.width = "100%";
175 div.appendChild(button);
176
177
178 button.addEventListener("click",function (e){
179 div.parent.style.display="none";
180 xMapWindow.contents.appendChild(canvas);
181 xMapWindow.show(true);
182 xFloorWindow.show(true);
183 xBarsWindow.show(true);
184 ctx.fillStyle = "#000";
185
186
187 setInterval(draw,1000/5);
188
189 websocket = new WebSocket(wsUri);
190 websocket.onopen = function(evt) { onOpen(evt) };
191 websocket.onclose = function(evt) { onClose(evt) };
192 websocket.onmessage = function(evt) { onMessage(evt) };
193 websocket.onerror = function(evt) { onError(evt) };
194 })
195 button = document.createElement("input");
196 button.type = "button";
197 button.value = "logmeinasnull";
198 button.style.width = "100%";
199 div.appendChild(button);
200 button.addEventListener("click",function (e){
201 login.value = password.value = "null";
202 div.parent.style.display="none";
203 xMapWindow.contents.appendChild(canvas);
204 xMapWindow.show(true);
205 xFloorWindow.show(true);
206 xBarsWindow.show(true);
207 ctx.fillStyle = "#000";
208 ctx.font = "10px Courier New,MonoSpace";
209 setInterval(draw,1000/5);
210
211 websocket = new WebSocket(wsUri);
212 websocket.onopen = function(evt) { onOpen(evt) };
213 websocket.onclose = function(evt) { onClose(evt) };
214 websocket.onmessage = function(evt) { onMessage(evt) };
215 websocket.onerror = function(evt) { onError(evt) };
216 })
217 button = document.createElement("input");
218 button.type = "button";
219 button.value = "logmeinasNULL";
220 button.style.width = "100%";
221 div.appendChild(button);
222 button.addEventListener("click",function (e){
223 login.value = password.value = "NULL";
224 div.parent.style.display="none";
225 xMapWindow.contents.appendChild(canvas);
226 xMapWindow.show(true);
227 xFloorWindow.show(true);
228 xBarsWindow.show(true);
229 ctx.fillStyle = "#000";
230 ctx.font = "10px Courier New,MonoSpace";
231 setInterval(draw,1000/5);
232 websocket = new WebSocket(wsUri);
233 websocket.onopen = function(evt) { onOpen(evt) };
234 websocket.onclose = function(evt) { onClose(evt) };
235 websocket.onmessage = function(evt) { onMessage(evt) };
236 websocket.onerror = function(evt) { onError(evt) };
237 })
238 button = document.createElement("input");
239 button.type = "button";
240 button.value = "logmeinasVOID";
241 button.style.width = "100%";
242 div.appendChild(button);
243 button.addEventListener("click",function (e){
244 login.value = password.value = "VOID";
245 div.parent.style.display="none";
246 xMapWindow.contents.appendChild(canvas);
247 xMapWindow.show(true);
248 xFloorWindow.show(true);
249 xBarsWindow.show(true);
250 ctx.fillStyle = "#000";
251 ctx.font = "10px Courier New,MonoSpace";
252 setInterval(draw,1000/5);
253 websocket = new WebSocket(wsUri);
254 websocket.onopen = function(evt) { onOpen(evt) };
255 websocket.onclose = function(evt) { onClose(evt) };
256 websocket.onmessage = function(evt) { onMessage(evt) };
257 websocket.onerror = function(evt) { onError(evt) };
258 })
259 return div.parent;
260
261
262 }
263
264 function draw(){
265 xBarsWindow.ctx.fillStyle = "#000";
266 xBarsWindow.ctx.fillRect(0,0,xBarsWindow.sw,xBarsWindow.sh);
267
268
269 if ( typeof (myStats[CS_STAT_MAXHP]) == typeof(1)){
270 xBarsWindow.ctx.save();
271
272 xBarsWindow.ctx.fillStyle = "#F00";
273 xBarsWindow.ctx.globalAlpha = 0.5;
274 xBarsWindow.ctx.fillRect(10,10,20,xBarsWindow.sh);
275 xBarsWindow.ctx.fillRect(10,10+xBarsWindow.sh-(myStats[CS_STAT_HP]/myStats[CS_STAT_MAXHP])*xBarsWindow.sh,20,(myStats[CS_STAT_HP]/myStats[CS_STAT_MAXHP])*xBarsWindow.sh);
276 xBarsWindow.ctx.restore();
277 }
278
279 if ( typeof (myStats[CS_STAT_MAXSP]) == typeof(1)){
280 xBarsWindow.ctx.save();
281
282 xBarsWindow.ctx.fillStyle = "#00F";
283 xBarsWindow.ctx.globalAlpha = 0.5;
284 xBarsWindow.ctx.fillRect(50,10,20,xBarsWindow.sh);
285 xBarsWindow.ctx.fillRect(50,10+xBarsWindow.sh-(myStats[CS_STAT_SP]/myStats[CS_STAT_MAXSP])*xBarsWindow.sh,20,(myStats[CS_STAT_SP]/myStats[CS_STAT_MAXSP])*xBarsWindow.sh);
286 xBarsWindow.ctx.restore();
287 }
288 if ( typeof (myStats[CS_STAT_MAXGRACE]) == typeof(1)){
289 xBarsWindow.ctx.save();
290 xBarsWindow.ctx.fillStyle = "#0FF";
291 xBarsWindow.ctx.globalAlpha = 0.5;
292 xBarsWindow.ctx.fillRect(90,10,20,xBarsWindow.sh);
293 xBarsWindow.ctx.fillRect(90,10+xBarsWindow.sh-(myStats[CS_STAT_GRACE]/myStats[CS_STAT_MAXGRACE])*xBarsWindow.sh,20,(myStats[CS_STAT_GRACE]/myStats[CS_STAT_MAXGRACE])*xBarsWindow.sh);
294 xBarsWindow.ctx.restore();
295 }
296
297 if ( typeof (myStats[CS_STAT_FOOD]) == typeof(1)){
298 xBarsWindow.ctx.save();
299 xBarsWindow.ctx.fillStyle = "#ff0";
300 xBarsWindow.ctx.globalAlpha = 0.5;
301 xBarsWindow.ctx.fillRect(130,10,20,xBarsWindow.sh);
302 xBarsWindow.ctx.fillRect(130,10+xBarsWindow.sh-(myStats[CS_STAT_FOOD]/999)*xBarsWindow.sh,20,(myStats[CS_STAT_FOOD]/999)*xBarsWindow.sh);
303 xBarsWindow.ctx.restore();
304 }
305 }
306
307 function main (){
308
309 for (var i = 0;i<255;++i){
310 keys.states[i]=0;
311 };
312
313
314
315
316 if (isMainCalled==true){
317 return;
318 }
319 isMainCalled = true;
320
321 window.WebSocket = window.WebSocket || window.MozWebSocket;
322
323 if (window.WebSocket){
324
325
326 canvas = document.createElement("canvas");
327 var sw = canvas.width = window.innerWidth-10;
328 var sh = canvas.height =window.innerHeight-10;
329 var dx = Math.floor(sw/64);
330 var dy = Math.floor((sh-120)/64);
331
332 dx = dy = Math.min(dx,dy);
333 stage = {stageWidth:sw,stageHeight:sh};
334 var logWindow = createWindow("log",stage.stageWidth,120,0,0);
335 xMapWindow = createWindow("map",dx*64+30,dy*64+30,0,120);
336 xMapWindow.style.top = (sh-xMapWindow.height()-20)+"px";
337 xMapWindow.show(false);
338 canvas.width = xMapWindow.width()-10;
339 canvas.height = xMapWindow.height()-25;
340
341
342
343
344 xFloorWindow = createWindow("floor",Math.floor((sw-xMapWindow.width()-30)/2),350,xMapWindow.width()+30,stage.stageHeight-20-350);
345 xFloorWindow.show(false);
346
347 xPlayerWindow = createWindow("player",sw - 30,sh-30,10,10);
348 //xPlayerWindow.show(false);
349
350 xPlayerWindow.contents.innerHTML = "";
351 var buttons = ["Statistics","Skills","SpellBook","Inventory"];
352 var div = document.createElement("div");
353 div.className = "buttons_widnow_content";
354 xPlayerWindow.contents.appendChild(div);
355
356 for (var i = 0;i<buttons.length;++i){
357 var button = document.createElement("input");
358 button.type="button";
359 button.value = buttons[i] + " (F"+(i+2)+")";
360 button.addEventListener("click",showPlayerTab);
361 div.appendChild(button);
362 }
363 div = document.createElement("div");
364 div.className = "player_widnow_content";
365 xPlayerWindow.contents.appendChild(div);
366
367 div = document.createElement("div");
368 div.className = "floor_widnow_content";
369 xPlayerWindow.contents.appendChild(div);
370
371 div = document.createElement("div");
372 div.className = "spellbook_widnow_content";
373 xPlayerWindow.contents.appendChild(div);
374
375 div = document.createElement("div");
376 div.className = "skills_widnow_content";
377 xPlayerWindow.contents.appendChild(div);
378
379 div = document.createElement("div");
380 div.className = "statistics_widnow_content";
381 xPlayerWindow.contents.appendChild(div);
382
383 hideAllPlayerTabs();
384
385 xPlayerWindow.show(false);
386 ctx = canvas.getContext('2d');
387
388 appendToBody(createLoginWindow());
389 window.addEventListener("click",onClick);
390 window.addEventListener("contextmenu",onClick);
391 window.addEventListener("mousemove",onMouseMove);
392 window.addEventListener("mouseup",onMouseUp);
393
394 //document.getElementsByTagName("body")[0].addEventListener("contextmenu",onClick);
395 //document.addEventListener("contextmenu",onClick);
396
397 output = $_("textarea");
398
399 output.style.opacity ="0.3";
400 output.style.filter ="filter:alpha(opacity=30);";
401
402 output.style.width = "99%"
403 output.style.height = "70%";
404 logWindow.contents.appendChild(output);
405
406 xBarsWindow = createWindow("bars",250,300,sw - 280,sh-320);
407 var barsCanvas = $_("canvas");
408 barsCanvas.width = xBarsWindow.sw = xBarsWindow.width() - 20;
409 barsCanvas.height =xBarsWindow.sh = xBarsWindow.height() - 20;
410 xBarsWindow.contents.appendChild(barsCanvas);
411 xBarsWindow.ctx = barsCanvas.getContext("2d");
412 xBarsWindow.ctx.fillStyle = "#000";
413 xBarsWindow.ctx.fillRect(0,0,xBarsWindow.sw,xBarsWindow.sh);
414 xBarsWindow.show(false);
415 xInfoWindow = createWindow("info",300,200,-400,-300);
416 xInfoWindow.show(false);
417 xCommmandWindow = createCommandWindow();
418 xCommmandWindow.show(false);
419 xChatBoxWindow = createWindow("chatbox",sw-xMapWindow.width()-20,300,sw-(sw-xMapWindow.width()-20),logWindow.height()+10);
420 xChatBoxWindow.buttonsContainer = $_("div");
421 xChatBoxWindow.contents.appendChild(xChatBoxWindow.buttonsContainer);
422 xChatBoxWindow.channelContainer = $_("div");
423 xChatBoxWindow.channelContainer.style.height = "100%";
424 xChatBoxWindow.contents.appendChild(xChatBoxWindow.channelContainer);
425
426
427 }
428 };
429
430
431 function showPlayerTab (e,tn){
432
433 xPlayerWindow.show(true);
434 var tabName = tn ? tn : (this.value).split(" ")[0].toLowerCase();
435
436 var div;
437
438 switch (tabName){
439 case "inventory":
440 hideAllPlayerTabs();
441 var content = xPlayerWindow.getElementsByClassName("player_widnow_content")[0];
442 content.style.display = "block";
443 content = xPlayerWindow.getElementsByClassName("floor_widnow_content")[0];
444 content.style.display = "block";
445 updateItemsList();
446 break;
447 case "spellbook":
448
449 hideAllPlayerTabs();
450 var content = xPlayerWindow.getElementsByClassName("spellbook_widnow_content")[0];
451 content.style.display = "block";
452 updateSpellList();
453 break;
454 case "skills":
455 hideAllPlayerTabs();
456 var content = xPlayerWindow.getElementsByClassName("skills_widnow_content")[0];
457 content.style.display = "block";
458 updateSkillList();
459 break;;
460 case "statistics":
461 hideAllPlayerTabs();
462 var content = xPlayerWindow.getElementsByClassName("statistics_widnow_content")[0];
463 content.style.display = "block";
464 updateStatsList();
465 break;;
466 default:
467
468 break;
469 }
470 }
471 var playerTabs = ["player_widnow_content","floor_widnow_content","spellbook_widnow_content","skills_widnow_content","statistics_widnow_content"];
472
473 function hideAllPlayerTabs (){
474 for (var i = 0;i<playerTabs.length;++i){
475 xPlayerWindow.getElementsByClassName(playerTabs[i])[0].style.display="none";
476 }
477 }
478
479 function updateStatsList(){
480 var content = xPlayerWindow.getElementsByClassName("statistics_widnow_content")[0];
481 var div;
482 content.innerHTML = "";
483 var tableLeft;
484 var tableRight;
485 var tr;
486 var td;
487
488 content.appendChild(div=$_("div"));
489 div.innerHTML = "Primary/Secondary statistics.";
490 content.appendChild($_("hr"));
491 content.appendChild(tableLeft = $_("table"));
492 tableLeft.style.width="45%";
493 tableLeft.style.float = "left";
494 content.appendChild(tableRight = $_("table"));
495 tableRight.style.width="45%";
496 tableRight.style.float = "right";
497 content.appendChild(div=$_("br"));
498 content.appendChild(div=$_("br"));
499 content.appendChild(div=$_("div"));
500 div.innerHTML = "Resistances.";
501 div.style.clear = "both";
502 content.appendChild($_("hr"));
503
504 var j=0;
505
506 var basicStats = [CS_STAT_STR,CS_STAT_INT,CS_STAT_WIS,CS_STAT_DEX,CS_STAT_CON,CS_STAT_CHA,CS_STAT_WC,CS_STAT_AC,CS_STAT_DAM,/*CS_STAT_ARMOUR,*/CS_STAT_SPEED,CS_STAT_WEAP_SP];
507 var basicStatsNames = ['CS_STAT_STR','CS_STAT_INT','CS_STAT_WIS','CS_STAT_DEX','CS_STAT_CON','CS_STAT_CHA','CS_STAT_WC','CS_STAT_AC','CS_STAT_DAM',/*'CS_STAT_ARMOUR',*/'CS_STAT_SPEED','CS_STAT_WEAP_SP'];
508
509
510 for (i=0;i<basicStats.length;++i){
511
512 var table = i<6 ? tableLeft : tableRight;
513
514 table.appendChild(tr = $_("tr"));
515 tr.index = i;
516
517
518 tr.appendChild(td=$_("td"));
519 td.innerHTML = basicStatsNames[i];
520
521
522 tr.appendChild(td=$_("td"));
523 td.innerHTML = myStats[basicStats[i]];
524
525 };
526 var resNames = ['CS_STAT_RES_PHYS','CS_STAT_RES_MAG','CS_STAT_RES_FIRE','CS_STAT_RES_ELEC','CS_STAT_RES_COLD','CS_STAT_RES_CONF','CS_STAT_RES_ACID',
527 'CS_STAT_RES_DRAIN','CS_STAT_RES_GHOSTHIT','CS_STAT_RES_POISON','CS_STAT_RES_SLOW','CS_STAT_RES_PARA','CS_STAT_TURN_UNDEAD','CS_STAT_RES_FEAR',
528 'CS_STAT_RES_DEPLETE', 'CS_STAT_RES_DEATH', 'CS_STAT_RES_HOLYWORD','CS_STAT_RES_BLIND'];
529
530 content.appendChild(tableLeft = $_("table"));
531 tableLeft.style.width="40%";
532 tableLeft.style.float = "left";
533 content.appendChild(tableRight = $_("table"));
534 tableRight.style.width="40%";
535 tableRight.style.float = "right";
536
537 for (i=CS_STAT_RESIST_START;i<CS_STAT_RESIST_END;++i){
538 var table = i%2==0 ? tableLeft : tableRight;
539
540 table.appendChild(tr = $_("tr"));
541 tr.index = i;
542
543
544 tr.appendChild(td=$_("td"));
545 td.innerHTML = resNames[i-CS_STAT_RESIST_START];
546
547
548 tr.appendChild(td=$_("td"));
549 td.innerHTML = myStats[i];
550
551 }
552
553
554
555
556 }
557
558 function getItemById(itmid){
559 var itm = findItem(myItems,itmid);
560 if (itm){
561 return itm;
562 }
563 itm = findItem(floorItems,itmid);
564 if (itm){
565 return itm;
566 }
567 for (var s in containers){
568 if (typeof(containers[s]) == typeof({}) ){
569 itm = findItem(containers[s],itmid);
570 if (itm){
571 return itm;
572 }
573
574 }
575 }
576 }
577 function updateItemsList(){
578 var content = xPlayerWindow.getElementsByClassName("player_widnow_content")[0];
579
580
581 content.innerHTML = "";
582 myItems.each(function (item,i,p){
583 if (isNaN(item.nr_of))
584 return;
585 content.appendChild(div = $_("div"));
586 var img = tilesInfo.getImgByFaceNum(item.face);
587 if (img){
588 div.innerHTML="<div><input type='hidden' value='"+item.itemId+"'/> <img src='"+img.src+"' alt='' style='width:32px;'/>"+(item.nr_of>1?item.namepl:item.name)+(item.nr_of>1?item.nr_of:"")+"</div>"
589 }else{
590 div.innerHTML="<div><input type='hidden' value='"+item.itemId+"'/>"+(item.nr_of>1?item.namepl:item.name)+"</div>"
591 }
592
593 div.addEventListener("click",myInventoryItemClick);
594 div.addEventListener("mouseover",inventoryItemMouseOver);
595 div.addEventListener("mouseout",inventoryItemMouseOut);
596 div.addEventListener("mousemove",inventoryItemMouseMove);
597 },{})
598
599 content = xPlayerWindow.getElementsByClassName("floor_widnow_content")[0];
600
601
602 content.innerHTML = "";
603 var container = secondaryContainer != 0 ? containers["container_" + secondaryContainer] : floorItems;
604 container.each(function (item,i,p){
605 if (isNaN(item.nr_of))
606 return;
607 content.appendChild(div = $_("div"));
608 var img = tilesInfo.getImgByFaceNum(item.face);
609 if (img){
610 div.innerHTML="<div><input type='hidden' value='"+item.itemId+"'/> <img src='"+img.src+"' alt='' style='width:32px;'/>"+(item.nr_of>1?item.namepl:item.name)+(item.nr_of>1?item.nr_of:"")+"</div>"
611 }else{
612 div.innerHTML="<div><input type='hidden' value='"+item.itemId+"'/>"+(item.nr_of>1?item.namepl:item.name)+"</div>"
613 }
614 div.addEventListener("mouseover",inventoryItemMouseOver);
615 div.addEventListener("mouseout",inventoryItemMouseOut);
616 div.addEventListener("mousemove",inventoryItemMouseMove);
617 div.addEventListener("click",floorInventoryItemClick);
618 },{})
619
620 }
621
622 function floorInventoryItemClick(e){
623 var itemId = parseInt(this.getElementsByTagName("input")[0].value);
624
625 if (!keys.shift){
626 return;
627 }
628
629 for (var i = 0;i<floorItems.length;++i){
630 if (parseInt(floorItems[i].itemId) == itemId){
631 doSend("command get "+ (floorItems[i].nr_of>1 ? floorItems[i].namepl:floorItems[i].name));
632 }else{
633
634 }
635 }
636 }
637
638 function myInventoryItemClick(e){
639 var itemId = parseInt(this.getElementsByTagName("input")[0].value);
640
641 if (!keys.shift){
642 return;
643 }
644 for (var i = 0;i<myItems.length;++i){
645
646
647 if (parseInt(myItems[i].itemId) == itemId){
648 doSend("command drop "+ (myItems[i].nr_of>1 ? myItems[i].namepl:myItems[i].name));
649 }else{
650
651 }
652 }
653
654 }
655
656 function inventoryItemMouseOver(e){
657 this.style.background = "solid";
658 this.style.backgroundColor="white";
659 var itemId = this.getElementsByTagName("input")[0].value;
660 doSend("ex " + itemId);
661
662 xInfoWindow.show(true);
663 xInfoWindow.style.left = (e.clientX+5)+"px";
664 xInfoWindow.style.top = (e.clientY+5)+"px";
665 }
666
667 function inventoryItemMouseMove(e){
668
669 xInfoWindow.style.left = (e.clientX+5)+"px";
670 xInfoWindow.style.top = (e.clientY+5)+"px";
671
672 }
673
674 function inventoryItemMouseOut(e){
675 this.style.background = "transparent";
676 xInfoWindow.show(false);
677 }
678
679 function createWindow(title,width,height,x,y){
680 var windowTemplate = document.getElementById("window_template_container").innerHTML;
681 var div = $_("div");
682 div.innerHTML = windowTemplate;
683
684 var xwindow = div.getElementsByClassName("window")[0];
685 xwindow.style.left = x+"px";
686 xwindow.style.top = y+"px";
687 xwindow.style.width = width + "px";
688 xwindow.width = function (){
689 return parseInt(xwindow.style.width);
690 };
691
692 xwindow.height = function (){
693 return parseInt(xwindow.style.height);
694 };
695 xwindow.show = function (b){
696 xwindow.style.display = b?"block":"none";
697 return true;
698 };
699 xwindow.visible = function (b){
700 return xwindow.style.display =="block";
701 };
702 xwindow.style.height = height + "px";
703 xwindow.getElementsByClassName("window_top_title")[0].innerHTML = title;
704 xwindow.getElementsByClassName("window_close")[0].onclick = function (){(xwindow.close());};
705 xwindow.onmousedown = function (e) { if (e.clientY-parseInt(xwindow.style.top)<25){
706 currentWindow = xwindow;
707 currentWindowOffset={x:e.clientX-parseInt(xwindow.style.left),y:e.clientY-parseInt(xwindow.style.top)}
708 }else if (e.clientY-parseInt(xwindow.style.top)>parseInt(xwindow.style.height)-5){
709 if (e.clientX-parseInt(xwindow.style.left)>parseInt(xwindow.style.width)-5){
710 currentWindowResize = true;
711 currentWindow = xwindow;
712 }
713 }
714 };
715 xwindow.contents = xwindow.getElementsByClassName("content")[0];
716 xwindow.contents.parent = xwindow;
717 xwindow.close = function (){document.getElementsByTagName("body")[0].removeChild(xwindow);};
718 appendToBody(xwindow);
719 return xwindow;
720 }
721
722 function onMouseUp (e){
723
724 if (currentWindow!=null){
725 currentWindow = null;
726 currentWindowResize = false;
727 }
728 }
729
730 function onMouseMove (e){
731 stage.mouseX = e.clientX;
732 stage.mouseY = e.clientY;
733 if (currentWindow!=null){
734 if (currentWindowResize == false){
735 currentWindow.style.left = (stage.mouseX-currentWindowOffset.x)+"px";
736 currentWindow.style.top = (stage.mouseY-currentWindowOffset.y)+"px";
737 }else{
738 currentWindow.style.width = (stage.mouseX-parseInt(currentWindow.style.left))+"px";
739 currentWindow.style.height = (stage.mouseY-parseInt(currentWindow.style.top))+"px";
740 }
741 }
742 }
743
744 function ptInRect(pt,rect){
745 if (pt.x<rect.x) return false;
746 if (pt.y<rect.y) return false;
747 if (pt.x>rect.x+rect.width) return false;
748 if (pt.y>rect.y+rect.height) return false;
749 return true;
750 }
751
752 function onClick (e){
753 x = e.clientX;
754 y = e.clientY;
755
756 try{
757 e.preventDefault();
758 }catch (ex){
759
760 }
761 return false;
762 }
763
764 function channels_setActive(channel_info){
765 for (var i=0;i<channels.length;++i){
766 if (channels.list[i]==channel_info){
767 channels.list[i].isActive = true;
768 }else{
769 channels.list[i].isActive = false;
770 }
771 }
772 }
773
774 function channels_addMessage(channelId,o){
775 var ta = channels_get_chat_box("channel_" + channelId);
776 if (ta == null)
777 return;
778 ta.value = ta.value + JSON.stringify(o);;
779 channels[channelId].newMessages = true;
780 }
781
782
783 function channels_add(channel_info){
784 var button,textarea;
785 if (channels[channel_info['id']]){
786 return;
787 }
788 channel_info.messages = [];
789 channel_info.index = channels.list.length;
790 channels[channel_info['id']] = channel_info;
791 channels.list.push (channel_info);
792 channels.length+=1;
793 channels_setActive(channel_info);
794 xChatBoxWindow.buttonsContainer.appendChild(button=$_("input"));
795 button.value = channel_info['id'];
796 button.type = "button";
797 xChatBoxWindow.channelContainer.appendChild(textarea=$_("textarea"));
798 textarea.id = "channel_" + button.value;
799 textarea.style.width = "90%";
800 textarea.style.height = "85%";
801 channels_hide_other ("channel_" + button.value);
802 button.onclick = function (){
803 channels_hide_other ("channel_" + button.value);
804 };
805 }
806 function channels_get_chat_box (pid){
807 var list = xChatBoxWindow.channelContainer.getElementsByTagName("textarea");
808 for (var i=0;i<list.length;++i){
809 var e = list[i];
810 if (e.id == pid)
811 return e;
812 };
813 return null;
814 }
815 function channels_hide_other(pid){
816 var list = xChatBoxWindow.channelContainer.getElementsByTagName("textarea");
817 for (var i=0;i<list.length;++i){
818 var e = list[i];
819 if (e.id != pid)e.style.display = "none";else e.style.display = "block";
820 };
821 }
822
823
824 /**
825 * SOCKET EVENTS
826 */
827 function onOpen(evt)
828 {
829 writeToScreen("CONNECTED");
830 doSend('version {"clientver":"0.001","client":"deliantra html5 client","osver":"linux","protver":1}');
831 }
832
833 function onClose(evt)
834 {
835 writeToScreen("DISCONNECTED");
836 }
837 function onError(evt)
838 {
839 writeToScreen("ERROR!");
840 }
841
842 function onMessage2(data)
843 {
844 var patt=/[0-9a-z_]*[^0-9a-z_]/i;
845 var feed = "" + data.match(patt);
846 feed = feed.substr (0,feed.length -1);
847 if (feed=="nul"){
848 if (data=="newmap"){
849 feed="newmap";
850 }else{
851 return;
852 }
853 }
854 if ((window['feed_' + feed])&&(typeof(window['feed_' + feed])=="function")){
855 var retVal = window['feed_' + feed](data,bytes2arr(data),data);
856 if (!retVal){
857 }
858 }else{
859 //unhandled feed
860 }
861 }
862
863 function onMessage(evt)
864 {
865 var data = evt.data;
866
867 if (data instanceof Blob){
868 var r = new FileReader ();
869 r.readAsBinaryString (data);
870 r.onloadend = function(progress) {
871 onMessage2 (r.result);
872 };
873 }else{
874 onMessage2 (data);
875 }
876 }
877
878 var exti = {
879 nextId : 100,
880 getNextId : function (){
881 return this.nextId++;
882 }
883 };
884
885
886 /**
887 * HANDLE FEEDS FROM SERVER
888 */
889 function feed_upditem (data,dataAsArray){
890 var buff=new Buffer(dataAsArray);
891 buff.position = "upditem ".length;
892 var flags = buff.readUint8();
893 var tag = buff.readUint32();
894
895 var itm = getItemById(tag);
896 if (!itm){
897 return;
898 }
899
900 if (flags & UPD_LOCATION) {
901 removeItemEx(tag);
902
903 var container = buff.readUint32();
904 if (container==player.tag){
905 myItems.push(itm);
906 }else if (container==0){
907 floorItems.push(itm);
908 }else{
909 if (!typof(containers["container_" + container])==typeof([])){
910 containers["container_" + container] = [];
911 }
912 containers["container_" + container].push (itm);
913 }
914 }
915 if (flags & UPD_FLAGS)
916 itm.flags = buff.readUint32();
917 if (flags & UPD_WEIGHT)
918 itm.weight = buff.readUint32();//$item->{weight} = unpack "l", pack "L", unpack "N", substr $data, 0, 4, "" ;
919 if (flags & UPD_FACE)
920 itm.face = buff.readUint32();
921
922
923 if((itm.flags&F_OPEN)){
924 secondaryContainer = tag;
925 updateItemsList();
926 }
927
928 //TODO: finish it!
929 /*
930 if ($flags & UPD_NAME) {
931 my $len = unpack "C", substr $data, 0, 1, "";
932
933 my $names = substr $data, 0, $len, "";
934 utf8::decode $names;
935 @$item{qw(name name_pl)} = split /\x00/, $names;
936 }
937
938 $item->{anim} = unpack "n", substr $data, 0, 2, "" if $flags & UPD_ANIM;
939 $item->{animspeed} = TICK * unpack "C", substr $data, 0, 1, "" if $flags & UPD_ANIMSPEED;
940 $item->{nrof} = unpack "N", substr $data, 0, 4, "" if $flags & UPD_NROF;
941
942 $item->{mtime} = time;
943
944 if ($item->{tag} == $self->{player}{tag}) {
945 $self->player_update ($self->{player} = $item);
946 } else {
947 $self->item_update ($item);
948 }
949 */
950 }
951 function removeItemEx(itmid){
952 removeItem(myItems,itmid);
953 removeItem(floorItems,itmid);
954 for (var s in containers){
955 if (typeof(containers[s]) == typeof({}) ){
956 removeItem(containers[s],itmid);
957 }
958 }
959 }
960 function feed_delitem (data,dataAsArray){
961
962 var buff=new Buffer(dataAsArray);
963 buff.position = 8;
964
965 while (buff.position<dataAsArray.length){
966 var itmid = buff.readUint32();
967 removeItemEx(itmid);
968 if (typeof(containers["container_" + itmid]) == typeof({}) ){
969 containers["container_" + itmid] = [];
970 }
971
972 }
973
974
975 updateItemsList();
976
977 }
978 function findItem (items,itmid){
979 for (var i=items.length-1;i>=0;--i){
980 if (items[i].itemId == itmid){
981 return items[i];
982 }
983 }
984 return null;
985 }
986
987 function removeItem (items,itmid){
988 for (var i=items.length-1;i>=0;--i){
989 if (items[i].itemId == itmid){
990 items.splice(i,1);
991 }
992 }
993
994 updateItemsList();
995 }
996
997 function feed_ex (data,dataAsArray){
998 var buff=new Buffer(dataAsArray);
999 buff.position = 3;
1000 var len = buff.unpack_w();
1001 var str = buff.readString(len);
1002 xInfoWindow.contents.innerHTML = str.split("\n").join("<br/>")+"<small>shift+click - drop,move or pickup item</small>";
1003
1004 }
1005
1006 function feed_query (data,dataAsArray){
1007 switch (String.fromCharCode(dataAsArray[6])){
1008 case "0":
1009 //var login = prompt("What is your name? (login names are case-sensitive):");
1010 doSend("reply " + getLogin())
1011 return true;
1012 break;
1013
1014 case "4":
1015 //var password = prompt("What is your password?");
1016 doSend("reply " + getPassword());
1017
1018 return true
1019 break;
1020
1021 }
1022 return false;
1023 }
1024
1025
1026 function feed_version (data,dataAsArray){
1027 var smapsize = Math.floor(xMapWindow.width()/64);
1028 mapsize.width = mapsize.height = parseInt(smapsize);
1029 smapsize = smapsize +"x" + smapsize;
1030 map_clear();
1031 doSend('setup tileset 1 excmd 1 smoothing 1 mapinfocmd 1 facecache 1 newmapcmd 1 extmap 1 fxix 3 darkness 1 extcmd 2 msg 2 frag 0 map1acmd 1 spellmon 1 itemcmd 2 exp64 1 widget 1 lzf 0 mapsize ' + smapsize);
1032
1033 window.addEventListener("keydown",function (e){
1034 if (skipKeyTest){
1035 return;
1036 }
1037
1038 if (keys.states [e.keyCode]==0){
1039 onKeyDown(e.keyCode);
1040 }
1041
1042 keys.states [e.keyCode] = 1;
1043
1044 try {
1045 e.preventDefault();
1046 }catch (e){
1047
1048 }
1049 return false;
1050 });
1051 window.addEventListener("keyup",function (e){
1052 if (skipKeyTest){
1053 return;
1054 }
1055 if (keys.states [e.keyCode]==1){
1056 onKeyUp(e.keyCode);
1057 }
1058 keys.states [e.keyCode] = 0;
1059 try {
1060 e.preventDefault();
1061 }catch (e){
1062
1063 }
1064 //isRunning = false;
1065 return false;
1066 });
1067 channels_add({id:"log"});
1068 channels_add({id:"map"});
1069 return false;
1070 }
1071
1072 function feed_setup (data,dataAsArray){
1073 doSend('exti ["http_faceurl", ' + exti.getNextId() +']');
1074 }
1075
1076 function clear_cell (cell){
1077 cell.darkness = 256;
1078 cell.flags = 0;
1079 cell.player =0;
1080 cell.tiles = [];
1081 return cell;
1082 }
1083
1084 function MapCell(){
1085 this.previousCell = null;
1086 this.nextCell = null;
1087 this.data = {};
1088 clear_cell(this.data);
1089 }
1090
1091 function MapRow(){
1092 this.previousRow = null;
1093 this.nextRow = null;
1094 this.firstCell = null;
1095 this.lastCell = null;
1096 this.length = 0;
1097 while (this.length<mapsize.width){
1098 this.addCell(new MapCell());
1099 }
1100 }
1101 MapRow.prototype.addCell = function (cell){
1102 if (this.firstCell == null){
1103 this.firstCell = this.lastCell = cell;
1104
1105 this.lastCell.nextCell = this.firstCell;
1106 this.lastCell.previousCell = this.firstCell;
1107
1108 this.firstCell.nextCell = this.lastCell;
1109 this.firstCell.previousCell = this.lastCell;
1110
1111 this.length = 1;
1112 return;
1113 }
1114 this.lastCell.nextCell = cell;
1115 cell.previousCell = this.lastCell;
1116 this.lastCell = cell;
1117 this.firstCell.previousCell = cell;
1118 cell.nextCell = this.firstCell;
1119 this.length+=1;
1120 }
1121
1122 MapRow.prototype.shift = function (){
1123 var ret = this.firstCell;
1124 this.firstCell = ret.nextCell;
1125 this.lastCell.nextCell = this.firstCell;
1126 this.firstCell.previousCell = this.lastCell;
1127 return ret;
1128 }
1129
1130 MapRow.prototype.pop = function (){
1131 var ret = this.lastCell;
1132 this.lastCell = ret.previousCell;
1133 this.lastCell.nextCell = this.firstCell;
1134 this.firstCell.previousCell = this.lastCell;
1135 return ret;
1136 }
1137
1138 MapRow.prototype.push = function (cell){
1139 this.addCell(cell);
1140 }
1141
1142 MapRow.prototype.unshift = function (cell){
1143 var tmp = this.firstCell;
1144 this.firstCell = cell;
1145 this.firstCell.nextCell = tmp;
1146 tmp.previousCell = this.firstCell;
1147 this.firstCell.previousCell = this.lastCell;
1148 this.lastCell.nextCell = this.firstCell;
1149 }
1150
1151 function map_clear (){
1152 Map = {length:0,firstRow:null,lastRow : null,addRow:function (row){
1153 if (this.firstRow==null){
1154 this.firstRow = this.lastRow = row;
1155 this.length = 1;
1156 return;
1157 }
1158 this.lastRow.nextRow = row;
1159 row.previousRow = this.lastRow;
1160 this.lastRow = row;
1161 row.nextRow = this.firstRow;
1162 this.firstRow.previousRow = row;
1163 this.length++;
1164 }};
1165
1166 while (Map.length<mapsize.height){
1167 Map.addRow(new MapRow());
1168 }
1169
1170 if (stage&&stage.stageWidth)
1171 ctx.clearRect(0,0,stage.stageWidth,stage.stageHeight);
1172 }
1173
1174 function map_get_cell (x,y){
1175 var i = 0;
1176 var mapRow = Map.firstRow;
1177 while (i<y){
1178 mapRow = mapRow.nextRow;
1179 ++i;
1180 }
1181 i = 0;
1182 var mapCell = mapRow.firstCell;
1183 while (i<x){
1184 mapCell=mapCell.nextCell;
1185 ++i;
1186 }
1187 return mapCell.data;
1188 }
1189
1190 function map_get_cell_ex (x,y){
1191 var i = 0;
1192 var mapRow = Map.firstRow;
1193 while (i<y){
1194 mapRow = mapRow.nextRow;
1195 ++i;
1196 }
1197 i = 0;
1198 var mapCell = mapRow.firstCell;
1199 while (i<x){
1200 mapCell=mapCell.nextCell;
1201 ++i;
1202 }
1203 return mapCell;
1204
1205 }
1206
1207 function scroll_map (dx,dy){
1208 var x,y;
1209 var tmpDx = dx;
1210 var tmpDy = dy;
1211 var i=0;
1212 while (i<tmpDy){
1213
1214 Map.firstRow = Map.firstRow.nextRow;
1215 Map.addRow(new MapRow());
1216 Map.length -=1;
1217 ++i;
1218 }
1219 i=0;
1220 while (tmpDy<i){
1221 var mapRow = new MapRow();
1222 mapRow.nextRow = Map.firstRow;
1223 Map.firstRow.previousRow = mapRow;
1224 mapRow.previousRow = Map.lastRow;
1225 Map.lastRow.nextRow = mapRow;
1226 Map.firstRow = mapRow;
1227 --i;
1228 }
1229 i = 0;
1230 while (i<tmpDx){
1231 var row = Map.firstRow;
1232 do {
1233 row.shift();
1234 row.push(new MapCell());
1235 row = row.nextRow;
1236 }while (row!=Map.firstRow);
1237 i++;
1238 }
1239 i = 0;
1240 while (tmpDx<i){
1241 var row = Map.firstRow;
1242 do {
1243 row.pop();
1244 row.unshift(new MapCell());
1245 row = row.nextRow;
1246 }while (row!=Map.firstRow);
1247 i--;
1248 }
1249 }
1250
1251 function feed_map1a (stringData,data){
1252
1253 scroll_map(dx,dy);
1254 dx = dy = 0;
1255
1256 var x,y;
1257
1258 var index = 6;
1259
1260 while (index<data.length-2){
1261 var flags = (data[index++]<<8) + data[index++];
1262 x = ((flags >> 10) & 63);
1263 y = ((flags >> 4) & 63);
1264
1265 cell = map_get_cell (x, y);
1266 if (!(flags&15)){
1267 clear_cell(cell);
1268 //ctx.clearRect(x<<6,(y<<6),64,64);
1269 continue;
1270 }
1271
1272 if (cell.darkness==0){
1273 cell.darkness = 256;
1274 }
1275
1276 if ((flags & 8)){
1277 do {
1278 var cmd = 0;
1279 var ext = 0;
1280
1281 ext = data[index++];
1282 cmd = ext & 0x7f;
1283 if (cmd<4){
1284 cell.darkness = 255 - ext * 64 + 1;
1285 }else if (cmd == 5){
1286 cell.stat_width = 1;
1287 cell.stat_hp = data[index++];
1288 }else if (cmd == 6) {// monster width{
1289 cell.stat_width = data[index++] + 1;
1290 }else if (cmd == 0x47){
1291 if (data[index] == 1) cell.player = data [index + 1];
1292 else if (data[index] == 2) cell.player = data [index + 2] + (data [index + 1] << 8);
1293 else if (data[index] == 3) cell.player = data [index + 3] + (data [index + 2] << 8) + (data [index + 1] << 16);
1294 else if (data[index] == 4) cell.player = data [index + 4] + (data [index + 3] << 8) + (data [index + 2] << 16) + (data [index + 1] << 24);
1295
1296 index += data[index] +1;
1297 }
1298 else if (cmd == 8) // cell flags
1299 cell.flags = data[index++];
1300 else if (ext & 0x40) // unknown, multibyte => skip
1301 index+= data[index]+1;
1302 else
1303 index++;
1304 }while (ext&0x80);
1305 }
1306
1307
1308
1309 for (var z = 0; z <= 2; ++z)
1310 if ((flags & (4 >> z)))
1311 {
1312 var face = (data [index++] << 8) + data [index++];
1313 //need_facenum (face);
1314 cell.tiles [z] = face;
1315 }
1316 //Map[y][x]=cell;
1317
1318
1319 }
1320 drawMap();
1321 return true;
1322
1323 }
1324
1325 function drawMap(){
1326
1327
1328 ctx.clearRect(0,0,stage.stageWidth,stage.stageHeight);
1329 ctx.fillStyle = "#000";
1330 ctx.fillRect(0,0,canvas.width,canvas.height);
1331
1332 for (var i = 0;i<mapsize.height;++i){
1333 var cell = map_get_cell_ex(0,i);
1334 var y = i<<6;
1335 var x = 0;
1336 for (var j=0;j<mapsize.width;++j){
1337 x+=64;
1338
1339 var cellx = cell.data;
1340 for (var z=0;z<=2;++z){
1341 if (!cellx.tiles[z])
1342 continue;
1343 var img = tilesInfo.getImgByFaceNum(cellx.tiles[z]);
1344 if (img){
1345 ctx.drawImage(img,x,y);
1346 }else{
1347 Faces.request(cellx.tiles[z],"map");
1348 }
1349 }
1350 if ((typeof(cellx.stat_hp) == typeof(1))&&cellx.stat_hp>0){
1351 ctx.fillStyle = "#f00";
1352 ctx.fillRect(x,y,((255-cellx.stat_hp)/255)*64,8);
1353
1354 //ctx.fillText(cellx.stat_hp,x,y);
1355 }
1356 cell = cell.nextCell;
1357
1358 }
1359 }
1360 }
1361
1362 function feed_ext (data,dataAsArray){
1363
1364
1365
1366
1367
1368 if (data.indexOf ("channel_info")>0){
1369 var channel_info = JSON.parse(data.substr(4))[1];
1370 channels_add(channel_info);
1371 return true;
1372 }else{
1373
1374 var o = JSON.parse(data.substr(4));
1375 var replyID = parseInt(o[0].split("-")[1]);
1376
1377 if (replyID == 100){
1378 baseURL = o[1];
1379 baseURL = "http://testserver.deliantra.net:13327" + baseURL + "";
1380 doSend('exti ["resource",'+exti.getNextId()+',"exp_table"]');
1381
1382
1383 }else if (replyID==101){
1384 expTableFacenum = parseInt(o[1]);
1385
1386 Faces.request(expTableFacenum,"json",function (tileInfo){expTable=(tileInfo.resource);});
1387
1388
1389 doSend ('exti ["resource",'+exti.getNextId() + ', "skill_info", "spell_paths","command_help"]');
1390 }else if (replyID==102){
1391
1392 Faces.request(parseInt(o[1]),"json",function (faceInfo){skillNames=(faceInfo.resource);});
1393 Faces.request(parseInt(o[2]),"json",function (faceInfo){spellPaths=(faceInfo.resource);});
1394 Faces.request(parseInt(o[3]),"json",function (faceInfo){commandsAll=(faceInfo.resource);});
1395 doSend("addme");
1396
1397 }
1398 else{
1399
1400 }
1401
1402
1403 writeToScreen(data);
1404 }
1405 return false;
1406 }
1407 var Constants = {
1408 a_none : 0,
1409 a_readied : 1,
1410 a_wielded : 2,
1411 a_worn : 3,
1412 a_active : 4,
1413 a_applied : 5,
1414 F_APPLIED : 0x000F,
1415 F_LOCATION : 0x00F0,
1416 F_UNPAID : 0x0200,
1417 F_MAGIC : 0x0400,
1418 F_CURSED : 0x0800,
1419 F_DAMNED : 0x1000,
1420 F_OPEN : 0x2000,
1421 F_NOPICK : 0x4000,
1422 F_LOCKED : 0x8000
1423 };
1424 function Buffer (dataArray){
1425 this.buffer = dataArray;
1426 this.position = 0;
1427 this.length = dataArray.length;
1428 return this;
1429 }
1430
1431 Buffer.prototype.unpack_w = function (){
1432 var num = 0;
1433 var byte = 0;
1434 do {
1435 num*=128;
1436 byte = parseInt(this.buffer[this.position++]);
1437 num+=byte&0x7f;
1438 }while (byte&0x80);
1439 return num;
1440 };
1441
1442 Buffer.prototype.readUint32 = function (){
1443 var ret = 0;
1444 for (var i=0;i<4;++i){
1445 ret*=256;
1446 ret+=this.buffer[this.position++];
1447 }
1448 return ret;
1449 };
1450
1451 Buffer.prototype.readUint8 = function (){
1452 var ret = 0;
1453 for (var i=0;i<1;++i){
1454 ret*=256;
1455 ret+=parseInt(this.buffer[this.position++]);
1456 }
1457 return ret;
1458 };
1459
1460 Buffer.prototype.readUint16 = function (){
1461 var ret = 0;
1462 for (var i=0;i<2;++i){
1463 ret*=256;
1464 ret+=this.buffer[this.position++];
1465 }
1466 return ret;
1467 };
1468
1469 Buffer.prototype.readString = function (len){
1470 var ret = "";
1471
1472 if ( typeof (len) != "undefined"){
1473 for (var i=0;i<len;++i){
1474 ret+=String.fromCharCode(this.buffer[this.position++]);
1475 }
1476 }else{
1477
1478 while (this.buffer[this.position]!=0){
1479 ret+=String.fromCharCode(this.buffer[this.position++]);
1480 }
1481 }
1482
1483 return ret;
1484 };
1485
1486
1487
1488 function unselectable (target){
1489 target.setAttribute('unselectable','on');
1490 if (typeof target.onselectstart != "undefined") //IE route
1491 target.onselectstart = function() { return false }
1492 else if (typeof target.style.MozUserSelect != "undefined") //Firefox route
1493 target.style.MozUserSelect = "none"
1494 else //All other route (ie: Opera)
1495 target.onmousedown = function() { return false }
1496 }
1497
1498 function Item (){
1499 this.itemId = 0;
1500 this.flags = 0;
1501 this.weight = 0;
1502 this.face = 0;
1503 this.name = "";
1504 this.namepl = "";
1505 this.animation_id=0;
1506 this.anim_speed=0;
1507 this.nr_of=0;
1508 this.clientType=0;
1509 }
1510
1511
1512 function feed_replyinfo (data){
1513 return false;
1514 }
1515
1516 var containers = {};
1517 var secondaryContainer = 0;
1518
1519 function feed_item2 (data,dataAsArray){
1520 var buff = new Buffer(dataAsArray);
1521 buff.position = 6;
1522 var container = buff.readUint32();
1523
1524 while (buff.position<buff.length){
1525 var item = new Item();
1526
1527 item.itemId = buff.readUint32();
1528
1529 item.flags = buff.readUint32();
1530 item.weight = buff.readUint32();
1531 item.face = buff.readUint32();
1532 var len = (buff.readUint8());
1533
1534 var names = (buff.readString(len)).split(String.fromCharCode(0));
1535 item.name = names[0];
1536 item.namepl = "";
1537
1538 if (names.length>1)
1539 item.namepl = names[1];
1540
1541 item.animation_id = buff.readUint16();
1542 item.anim_speed = buff.readUint8();
1543 item.nr_of = buff.readUint32();
1544 item.clientType = buff.readUint16();
1545 item.container = container;
1546
1547 if (container==player.tag){
1548 myItems.push (item);
1549 }else if (container==0){
1550 floorItems.push(item);
1551 }else {
1552 if ( typeof(containers['container_' + container]) != typeof([])){
1553 containers['container_' + container] = [];
1554 }
1555 containers['container_' + container].push(item);
1556 }
1557 }
1558 if (container==0){
1559 xFloorWindow.contents.innerHTML="";
1560 for (var i=0;i<floorItems.length;++i){
1561 var item = floorItems[i];
1562 if (item.itemId==null||isNaN(item.itemId))
1563 continue;
1564 var img = tilesInfo.getImgByFaceNum(item.face);
1565 var div = $_("div");
1566 xFloorWindow.contents.appendChild(div);
1567 if (img){
1568 div.innerHTML+="<div><input type='hidden' value='"+item.itemId+"'/><img src='"+img.src+"' alt='' style='width:32px;'/>"+(item.nr_of>1?item.namepl:item.name)+(item.nr_of>1?item.nr_of:"")+"</div>"
1569 }else{
1570 div.innerHTML+="<div><input type='hidden' value='"+item.itemId+"'/>"+(item.nr_of>1?item.namepl:item.name)+"</div>"
1571 }
1572
1573 div.addEventListener("click",floorInventoryItemClick);
1574 div.addEventListener("mouseover",inventoryItemMouseOver);
1575 div.addEventListener("mouseout",inventoryItemMouseOut);
1576 div.addEventListener("mousemove",inventoryItemMouseMove);
1577
1578 }
1579
1580
1581 }
1582 updateItemsList();
1583 return false;
1584 }
1585
1586 function Spell (){
1587
1588 }
1589
1590 function updateSpellList (){
1591 var content = xPlayerWindow.getElementsByClassName("spellbook_widnow_content")[0];
1592 content.style.display = "block";
1593
1594 content.innerHTML = "";
1595 var table;
1596 var tr;
1597 var td;
1598
1599 content.appendChild(table = $_("table"));
1600 table.style.width="100%";
1601 if (mySpells.length<=0){
1602 return;
1603 }
1604 table.appendChild(tr = $_("tr"));
1605 item = mySpells[0];
1606 for (s in item){
1607
1608 if ((typeof(item[s])==typeof(1))||(typeof(item[s])==typeof(""))){
1609 if (s=="tag"){
1610
1611 }else if (s=="message"){
1612
1613 }else if (s=="face"){
1614 tr.appendChild(td=$_("td"));
1615 td.innerHTML = s;
1616 }else{
1617 tr.appendChild(td=$_("td"));
1618 td.innerHTML = s;
1619 }
1620 }
1621
1622 }
1623
1624
1625 mySpells.each(function (item,i,p){
1626
1627 table.appendChild(tr = $_("tr"));
1628 tr.index = i;
1629 var img = tilesInfo.getImgByFaceNum(item.face);
1630
1631 var s;
1632 for (s in item){
1633 if (isNaN(item['face'])){
1634 continue;
1635 }
1636
1637 if ((typeof(item[s])==typeof(1))||(typeof(item[s])==typeof(""))){
1638 if (s=="tag"){
1639 tr.tag = item[s];
1640 }else if (s=="message"){
1641 tr.message = item[s];
1642 }else if (s=="face"){
1643 tr.appendChild(td=$_("td"));
1644 td.innerHTML = "<img src='"+img.src+"' alt='' style='width:32px;'/>";
1645 }else{
1646 tr.appendChild(td=$_("td"));
1647 td.innerHTML = item[s];
1648 }
1649 }
1650
1651 }
1652 tr.addEventListener("click",mySpellItemClick);
1653 tr.addEventListener("mouseover",SpellItemMouseOver);
1654 tr.addEventListener("mouseout",SpellItemMouseOut);
1655 tr.addEventListener("mousemove",SpellItemMouseMove);
1656
1657 /*if (img){
1658 div.innerHTML="<div><input type='hidden' value='"+item.itemId+"'/> <img src='"+img.src+"' alt='' style='width:32px;'/>"+(item.nr_of>1?item.namepl:item.name)+(item.nr_of>1?item.nr_of:"")+"</div>"
1659 }else{
1660 div.innerHTML="<div><input type='hidden' value='"+item.itemId+"'/>"+(item.nr_of>1?item.namepl:item.name)+"</div>"
1661 }*/
1662
1663
1664 },{})
1665
1666
1667 }
1668 function updateSkillList (){
1669 var content = xPlayerWindow.getElementsByClassName("skills_widnow_content")[0];
1670
1671
1672 content.innerHTML = "";
1673 var tableLeft;
1674 var tableRight;
1675 var tr;
1676 var td;
1677
1678 content.appendChild(tableLeft = $_("table"));
1679 tableLeft.style.width="45%";
1680 tableLeft.style.float = "left";
1681 content.appendChild(tableRight = $_("table"));
1682 tableRight.style.width="45%";
1683 tableRight.style.float = "right";
1684
1685 var j=0;
1686
1687 for (i=CS_STAT_SKILLINFO;i<CS_STAT_SKILLINFO+CS_NUM_SKILLS;++i){
1688
1689 if (!myStats[i]){
1690 continue;
1691 }
1692 var table = j%2==0 ? tableLeft : tableRight;
1693
1694 table.appendChild(tr = $_("tr"));
1695 tr.index = i;
1696
1697
1698 tr.appendChild(td=$_("td"));
1699 td.innerHTML = skillNames[i-CS_STAT_SKILLINFO][0];
1700
1701 for (var k =0 ;k<myStats[i].length;++k){
1702
1703 tr.appendChild(td=$_("td"));
1704 td.innerHTML = myStats[i][k];
1705
1706 }
1707 tr.appendChild(td=$_("td"));
1708 td.innerHTML = Math.floor(myStats[i][1]/expTable[parseInt(myStats[i][0])]*100) + "%";
1709 /*tr.addEventListener("click",mySpellItemClick);
1710 tr.addEventListener("mouseover",SpellItemMouseOver);
1711 tr.addEventListener("mouseout",SpellItemMouseOut);
1712 tr.addEventListener("mousemove",SpellItemMouseMove);
1713 */
1714 ++j;
1715 };
1716
1717
1718 }
1719
1720 function mySpellItemClick(e){
1721 if (keys.ctrl){
1722 doSend("command invoke " + mySpells[this.index].name);
1723 }else if (keys.shift){
1724 doSend("command cast " + mySpells[this.index].name);
1725 }
1726 }
1727
1728
1729 function SpellItemMouseOver(e){
1730 this.style.background = "solid";
1731 this.style.backgroundColor="white";
1732
1733 xInfoWindow.contents.innerHTML = this.message + "<small><br/>shift-click to cast<br/>ctrl-click to invoke</small>";
1734 xInfoWindow.show(true);
1735 xInfoWindow.style.left = (e.clientX+5)+"px";
1736 xInfoWindow.style.top = (e.clientY+5)+"px";
1737 }
1738
1739 function SpellItemMouseMove(e){
1740
1741 xInfoWindow.style.left = (e.clientX+5)+"px";
1742 xInfoWindow.style.top = (e.clientY+5)+"px";
1743
1744 }
1745
1746 function SpellItemMouseOut(e){
1747 this.style.background = "transparent";
1748 xInfoWindow.show(false);
1749 }
1750
1751
1752 function feed_addspell (data,dataAsArray){
1753
1754 var buff = new Buffer(dataAsArray);
1755 buff.position = data.indexOf(" ")+1;
1756 while (buff.position<buff.length){
1757 spell=new Spell();
1758
1759 spell.tag = buff.readUint32();
1760
1761 spell.minLevel = buff.readUint16();
1762
1763 spell.castingTime = buff.readUint16();
1764
1765 spell.mana = buff.readUint16();
1766
1767 spell.grace = buff.readUint16();
1768
1769 spell.level = buff.readUint16();
1770
1771 spell.skill = buff.readUint8();
1772
1773 spell.path = buff.readUint32();
1774
1775 spell.face = buff.readUint32();
1776 var len = buff.readUint8();
1777 spell.name = buff.readString(len);
1778 len = buff.readUint16();
1779 spell.message = buff.readString(len);
1780 mySpells.push(spell);
1781 }
1782
1783
1784 }
1785
1786 function feed_delinv (data,dataAsArray){
1787 var container = parseInt(data.split(" ")[1]);
1788 if (container==player.tag){
1789 myItems = [];
1790 }else if (container!=0){
1791 containers["container_" +container]=[];
1792 }else{
1793 floorItems = [];
1794 }
1795 updateItemsList();
1796 return false;
1797 }
1798
1799 var expTable = [];
1800 var spellPaths = [];
1801
1802
1803 function FaceInfo (){
1804 this.name = "";
1805 this.num = -1;
1806 this.type = 0;
1807 this.isLoaded = false;
1808 this.isLoading = false;
1809 this.isPending = false;
1810 this.isRequested = false;
1811 this.requestedBy = "";
1812 this.resource = null;
1813 this.json = "{}";
1814 this.afterLoad = [];
1815 }
1816
1817 FaceInfo.prototype.request = function (rby){
1818 this.isRequested = true;
1819 this.requestedBy = rby;
1820
1821
1822 if ((this.name==""))
1823 return this;
1824
1825 if ((!this.isPending) && (!this.isLoading)){
1826 this.load();
1827 }
1828
1829 return this;
1830 };
1831
1832 FaceInfo.prototype.appendOnLoad = function (f){
1833
1834 if (typeof(f) == typeof(function(){})){
1835 this.afterLoad.push (f);
1836 }
1837 return this;
1838 };
1839
1840 FaceInfo.prototype.setName = function (name){
1841 this.name = name;
1842 return this;
1843 };
1844
1845 FaceInfo.prototype.setType = function (type){
1846 this.type = parseInt(type);
1847 return this;
1848 };
1849
1850 FaceInfo.prototype.load = function (){
1851
1852 this.isPending = true;
1853
1854 Faces.load (this);
1855
1856 }
1857 FaceInfo.prototype.onload = function (){
1858 this.isPending = false;
1859 this.isLoading = false;
1860
1861 var o = this;
1862 this.afterLoad.each (function (e,i){
1863 e(o);
1864 });
1865 Faces.onload(this);
1866 }
1867 FaceInfo.prototype.loadStart = function (){
1868
1869 this.isPending = false;
1870 this.isLoading = true;
1871 if (this.requestedBy == "map"){//map tile
1872 var img = this.resource = $_("img");
1873 img.faceInfo = this;
1874 img.addEventListener("load",function (){ img.faceInfo.onload(); });
1875 img.src = baseURL+ "" + this.name;
1876
1877 }else{ //json but maybe other types
1878 var req = new XMLHttpRequest();
1879 req.open('GET', baseURL+""+this.name, false);
1880 req.send(null);
1881 if(req.status == 200){
1882 this.json = req.responseText;
1883 this.resource = JSON.parse(this.json);
1884 }
1885 this.onload();
1886 }
1887 }
1888
1889 var Faces = {
1890 byNum:[],
1891
1892 nDownloads: 0,
1893 pending : [],
1894
1895 add : function (id,name){
1896 var faceInfo = new FaceInfo;
1897 faceInfo.num = id;
1898 this.byNum[id] = faceInfo;
1899 return faceInfo;
1900 },
1901 getByNum : function (id,createIfNotExist){
1902 if (createIfNotExist)
1903 return Faces.byNum[id] ? Faces.byNum[id] : Faces.add(id);
1904 return Faces.byNum[id] ? Faces.byNum[id] : null;
1905 },
1906 request : function (id,by,f){
1907 return this.getByNum(id,true).appendOnLoad(f).request(by);
1908 },
1909
1910 load : function (faceInfo){
1911 if (this.nDownloads<this.MAXDOWNLOADS){
1912 this.nDownloads++
1913 faceInfo.loadStart();
1914 }else{
1915 this.pending.push (faceInfo);
1916 }
1917 },
1918 onload : function (faceInfo){
1919 alert(this.nDownloads);
1920 this.nDownloads--;
1921
1922 if ((this.nDownloads<this.MAXDOWNLOADS) && (this.pending.length>0)){
1923 var faceInfo = this.pending.pop();
1924 faceInfo.load();
1925 }
1926 },
1927
1928 FT_FACE : 0 * 2 + 0, // faces (images)
1929 FT_MUSIC : 1 * 2 + 1, // background music
1930 FT_SOUND : 2 * 2 + 1, // effects
1931 FT_RSRC : 3 * 2 + 0, // generic data files
1932
1933 MAXDOWNLOADS : 5
1934 }
1935
1936
1937 function feed_fx (data,dataAsArray){
1938
1939 var buff = new Buffer(dataAsArray);
1940 buff.position = 3;
1941 var out="";
1942 var type = 0;
1943 var nameX = "";
1944 var len;
1945
1946 while (buff.position<buff.length){
1947 nameX = "";
1948 var id = buff.unpack_w();
1949
1950 if (id == 0){
1951 buff.readUint8();
1952 type = buff.unpack_w();
1953 continue;
1954 }
1955 len = buff.readUint8();
1956
1957 for (var i = 0;i<len;++i){
1958 var c = parseInt(buff.readUint8());
1959 out = "";
1960 out+="0123456789abcdef"[c&0xf];
1961 out= "0123456789abcdef"[c>>4]+out;
1962 nameX+=out;
1963 }
1964 var faceInfo = Faces.getByNum(id,true);
1965
1966 faceInfo.setType (type).setName (nameX);
1967
1968 if (faceInfo.isRequested){
1969 faceInfo.load();
1970 }
1971 }
1972
1973 return false;
1974 }
1975
1976
1977
1978 function feed_newmap (data,dataAsArray){
1979 //messageBox("newmap");
1980 map_clear();
1981
1982 }
1983
1984 function feed_mapinfo (data,dataAsArray){
1985 var parts = data.split(/ /);
1986 //map_clear();
1987 return false;
1988 }
1989
1990
1991 function feed_msg (data,dataAsArray){
1992 var o = null;
1993 if (data.indexOf("[")>0){
1994 o = JSON.parse(data.substr(4));
1995
1996 channels_addMessage(o[1],o)
1997 return true;
1998 }
1999 return false;
2000 }
2001
2002
2003 function feed_anim (data,dataAsArray){
2004 return false;
2005 }
2006
2007 function feed_stats (data,dataAsArray){
2008 var buff = new Buffer(dataAsArray);
2009 buff.position = "stats".length + 1;
2010 while (buff.position < buff.length){
2011 var stat = buff.readUint8();
2012 var value;
2013 if (stat_32bit.contains(stat)){
2014 value = buff.readUint32();
2015 }else if (stat == CS_STAT_SPEED||stat==CS_STAT_WEAP_SP){
2016 value = (1/FLOAT_MULTF) * buff.readUint32();
2017 }else if (stat==CS_STAT_RANGE||stat==CS_STAT_TITLE){
2018 var len = buff.readUint8();
2019 value = buff.readString(len);
2020 }else if (stat == CS_STAT_EXP64){
2021 var hi = buff.readUint32();
2022 var lo = buff.readUint32();
2023 value = hi * Math.pow(2,32) + lo;
2024 }else if (stat>=CS_STAT_SKILLINFO && stat < CS_STAT_SKILLINFO + CS_NUM_SKILLS){
2025 var lvl = buff.readUint8();
2026 var hi = buff.readUint32();
2027 var lo = buff.readUint32();
2028 value = [lvl,hi * Math.pow(2,32) + lo];
2029 }else{
2030 value = buff.readUint16();
2031 if (value > 60000){
2032 value -= 65536;
2033 }
2034 }
2035 myStats [stat] = value;
2036 //stats_update (stat);
2037 }
2038
2039 return true;
2040 }
2041
2042 function feed_player (data,dataAsArray){
2043 var buff = new Buffer(dataAsArray);
2044 buff.position ="player ".length;
2045 //my ($tag, $weight, $face, $name) = unpack "NNN C/a", $data;
2046 player.tag = buff.readUint32();
2047 player.weight = buff.readUint32();
2048 player.face = buff.readUint32();
2049 var len = buff.readUint8();
2050 player.name = buff.readString(len);
2051 return false;
2052 }
2053
2054 function feed_drawinfo (data,dataAsArray){
2055 return false;
2056 }
2057
2058
2059
2060 var tilesInfo = {
2061 getImgByFaceNum:function (id){
2062 var fi = Faces.getByNum(id,true);
2063 return fi.resource;
2064 }
2065 }
2066
2067
2068 function need_facenum (num){
2069
2070 }
2071
2072
2073 function feed_map_scroll (data,dataAsArray,base64data){
2074
2075 data = data.split(/ /);
2076 data.shift();
2077 dx += parseInt(data.shift());
2078 dy += parseInt(data.shift());
2079
2080
2081 }
2082
2083 function $_(p,o){
2084 if (document.getElementById(p)!=null){
2085 return document.getElementById(p);
2086 }else{
2087 var ret = document.createElement(p);
2088 unselectable(ret);
2089 if (o&&o.css){
2090 var s="";
2091 for (var s in o.css){
2092 if (typeof(o.css[s])==typeof("")||typeof(o.css[s])==typeof(1)){
2093 ret.style[s] = o.css[s];
2094 }
2095 }
2096 }
2097 return ret;
2098 }
2099 }
2100 var tiles = [];
2101
2102
2103 function processExtObj (o){
2104 switch (o[0]){
2105 case "channel_info":
2106 channels[o[1].id] = o[1];
2107 channels.list.push (channels[o[1].id]);
2108 channels[o[1].id].index =channels.length;
2109 channels.length+=1;
2110 return true;
2111 default:
2112 return false;
2113 break;
2114 }
2115 }
2116
2117
2118 function doSend(message)
2119 {
2120 writeToScreen("SENT: " + message);
2121 websocket.send(message);
2122 }
2123
2124 /**
2125 * Command console
2126 */
2127
2128 var xCommandContainer = null;
2129 var xCommandLine = null;
2130 var xCommandLines = null;
2131 var command = "";
2132 var lastCommand = "";
2133 var firstOption = null;
2134 var commandsAll = [];
2135
2136 function commandLineOnKeyDown (e){
2137 if (e.keyCode==13){
2138 skipKeyTest = false;
2139
2140 doSend("command " + this.value);
2141 command = "";
2142 lastCommand = this.value;
2143
2144
2145 document.getElementsByTagName("body")[0].removeChild(xCommandContainer);
2146
2147 } else if (e.keyCode==27){
2148 command = "";
2149 skipKeyTest = false;
2150
2151 document.getElementsByTagName("body")[0].removeChild(xCommandContainer);
2152
2153 } else {
2154 //messageBox(JSON.stringify(commandsAll));
2155 }
2156 }
2157
2158 function autoComplete (keyCode){
2159 if (xCommandContainer==null){
2160 xCommandContainer =$_("div",{css:{position:"absolute",left:(stage.stageWidth/2)+"px",top:(stage.stageHeight/2)+"px"}});
2161
2162 xCommandLine = $_("input");
2163
2164 xCommandLine.addEventListener("keydown",commandLineOnKeyDown);
2165
2166 xCommandContainer.appendChild(xCommandLine);
2167 xCommandContainer.appendChild($_("br"));
2168
2169 xCommandLines = $_("select");
2170 xCommandLines.height = 5;
2171
2172 xCommandContainer.appendChild(xCommandLines);
2173
2174
2175 }
2176 if (command == ""){
2177 skipKeyTest = true;
2178 appendToBody(xCommandContainer);
2179 try {
2180 xCommandLine.focus();
2181 }catch (e){
2182
2183 }
2184 }
2185 command+=String.fromCharCode(keyCode).toLowerCase();
2186 xCommandLine.value = command;
2187 }
2188
2189
2190 /**
2191 * Key up/down handlers
2192 */
2193
2194 function onKeyDown (keyCode){
2195 switch(keyCode){
2196 case 38:
2197 if (keys.ctrl&&!isRunning){
2198 isRunning = true;
2199 doSend("command run 1");
2200 //doSend("command north")
2201 }
2202 else
2203 if (!isFiring&&keys.shift){
2204 doSend("command fire 1");
2205 isFiring = true;
2206 }else
2207 doSend("command north");
2208 break;
2209 case 40:
2210 if (keys.ctrl&&!isRunning){
2211 isRunning = true;
2212 doSend("command run 5" );
2213 //doSend("command souh")
2214 }
2215 else
2216 if (!isFiring&&keys.shift){
2217 doSend("command fire 5" );
2218 isFiring = true;
2219 }else
2220 doSend("command south");
2221 break;
2222 case 37:
2223 if (keys.ctrl&&!isRunning){
2224 isRunning = true;
2225 doSend("command run 7" );
2226 // doSend("command west")
2227 }
2228 else
2229 if (!isFiring&&keys.shift){
2230 doSend("command fire 7");
2231 isFiring = true;
2232 }else
2233 doSend("command west");
2234 break;
2235 case 39:
2236 if (keys.ctrl&&!isRunning){
2237 isRunning = true;
2238 doSend("command run 3" );
2239 //doSend("command west")
2240 }else
2241 if (!isFiring&&keys.shift){
2242 doSend("command fire 3");
2243 isFiring = true;
2244 }else
2245 doSend("command east");
2246 break;
2247 case 49:
2248 case 9:
2249 xPlayerWindow.show(!xPlayerWindow.visible() );
2250 break;
2251 case 67:
2252 skipKeyTest = true;
2253 xCommmandWindow.show(true);
2254
2255 break;
2256
2257 case 32:
2258 doSend("command apply");
2259 break;
2260 case 188:
2261 doSend("command get");
2262 break;
2263 case 16:
2264 keys.shift = 1;
2265 break;
2266 case 18:
2267 keys.alt = 1;
2268 break;
2269 case 17:
2270 keys.ctrl = 1;
2271 break;
2272 case 113:
2273 showPlayerTab({},"statistics");
2274 break;
2275 case 114:
2276 showPlayerTab({},"skills");
2277 break;
2278
2279 case 115:
2280 showPlayerTab({},"spellbook");
2281 break;
2282
2283 case 116:
2284 showPlayerTab({},"inventory");
2285 break;
2286 default:
2287 //messageBox(keyCode);
2288 break;
2289 }
2290 }
2291
2292 function onKeyUp(keyCode){
2293 switch(keyCode){
2294 case 38:
2295 if (isRunning&&!keys.ctrl){
2296 doSend("command run_stop");
2297 isRunning = false;
2298 }
2299 if (isFiring&&!keys.shift){
2300 doSend("command fire_stop");
2301 isFiring = false;
2302 }
2303 break;
2304 case 40:
2305 if (isFiring&&!keys.shift){
2306 doSend("command fire_stop");
2307 isFiring = false;
2308 }
2309 if (isRunning&&!keys.ctrl){
2310 doSend("command run_stop");
2311 isRunning = false;
2312 }
2313 break;
2314 case 37:
2315 if (isFiring&&!keys.shift){
2316 doSend("command fire_stop");
2317 isFiring = false;
2318 }
2319 if (isRunning&&!keys.ctrl){
2320 doSend("command run_stop");
2321 isRunning = false;
2322 }
2323 break;
2324 case 39:
2325 if (isFiring&&!keys.shift){
2326 doSend("command fire_stop");
2327 isFiring = false;
2328 }
2329 if (isRunning&&!keys.ctrl){
2330 doSend("command run_stop");
2331 isRunning = false;
2332 }
2333 break;
2334 case 49:
2335 break;
2336 case 16:
2337 keys.shift = 0;
2338 if (isFiring&&!keys.shift){
2339 doSend("command fire_stop");
2340 isFiring= false;
2341 }
2342 break;
2343 case 18:
2344 keys.alt = 0;
2345 break;
2346 case 17:
2347 keys.ctrl = 0;
2348 if (isRunning&&!keys.ctrl){
2349 doSend("command run_stop");
2350 isRunning = false;
2351 }
2352 break;
2353 default:
2354 //messageBox(e.keyCode);
2355 break;
2356 }
2357 if ((keyCode>="A".charCodeAt(0))&&(keyCode<="Z".charCodeAt(0))){
2358 autoComplete(keyCode); //launch command console
2359 }
2360 }
2361
2362 /*
2363 * UTILS
2364 */
2365
2366 function decode_base64toArray(s) {
2367 var e={},i,k,v=[],r=[],w=String.fromCharCode;
2368 var n=[[65,91],[97,123],[48,58],[43,44],[47,48]];
2369
2370 for(z in n){for(i=n[z][0];i<n[z][1];i++){v.push(w(i));}}
2371 for(i=0;i<64;i++){e[v[i]]=i;}
2372
2373 for(i=0;i<s.length;i+=72){
2374 var b=0,c,x,l=0,o=s.substring(i,i+72);
2375 for(x=0;x<o.length;x++){
2376 c=e[o.charAt(x)];b=(b<<6)+c;l+=6;
2377 while(l>=8){r.push((b>>>(l-=8))%256);}
2378 }
2379 }
2380 return r;
2381 }
2382
2383 function writeToScreen(message)
2384 {
2385 var d = new Date();
2386 //Messages.push(new Message(200,(d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() ) + ":" + message));
2387 output.value = d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + ":" + message + "\n" + output.value;
2388 }
2389
2390 function arr2bytes(arr){
2391 var s = "";
2392 for (var i=0;i<arr.length;++i){
2393 s+=String.fromCharCode(arr[i]);
2394 }
2395 return s;
2396 }
2397 function bytes2arr(s){
2398 var arr = [];
2399 for (var i=0;i<s.length;++i){
2400 arr.push(s.charCodeAt(i));
2401 }
2402 return arr;
2403 }
2404
2405 function imgFromString (s){
2406 var img = $_('img');
2407 img.src = s;
2408 return img;
2409 }
2410
2411 /*
2412 CONSTANTS
2413 */
2414
2415 var TICK = 0.120,
2416 CS_QUERY_YESNO = 0x1,
2417 CS_QUERY_SINGLECHAR = 0x2,
2418 CS_QUERY_HIDEINPUT = 0x4,
2419 CS_SAY_NORMAL = 0x1,
2420 CS_SAY_SHOUT = 0x2,
2421 CS_SAY_GSAY = 0x4,
2422 FLOAT_MULTI = 100000,
2423 FLOAT_MULTF = 100000.0,
2424 CS_STAT_HP = 1,
2425 CS_STAT_MAXHP = 2,
2426 CS_STAT_SP = 3,
2427 CS_STAT_MAXSP = 4,
2428 CS_STAT_STR = 5,
2429 CS_STAT_INT = 6,
2430 CS_STAT_WIS = 7,
2431 CS_STAT_DEX = 8,
2432 CS_STAT_CON = 9,
2433 CS_STAT_CHA = 10,
2434 CS_STAT_EXP = 11,
2435 CS_STAT_LEVEL = 12,
2436 CS_STAT_WC = 13,
2437 CS_STAT_AC = 14,
2438 CS_STAT_DAM = 15,
2439 CS_STAT_ARMOUR = 16,
2440 CS_STAT_SPEED = 17,
2441 CS_STAT_FOOD = 18,
2442 CS_STAT_WEAP_SP = 19,
2443 CS_STAT_RANGE = 20,
2444 CS_STAT_TITLE = 21,
2445 CS_STAT_POW = 22,
2446 CS_STAT_GRACE = 23,
2447 CS_STAT_MAXGRACE = 24,
2448 CS_STAT_FLAGS = 25,
2449 CS_STAT_WEIGHT_LIM = 26,
2450 CS_STAT_EXP64 = 28,
2451 CS_STAT_SPELL_ATTUNE = 29,
2452 CS_STAT_SPELL_REPEL = 30,
2453 CS_STAT_SPELL_DENY = 31,
2454 CS_STAT_RESIST_START = 100,
2455 CS_STAT_RESIST_END = 117,
2456 CS_STAT_RES_PHYS = 100,
2457 CS_STAT_RES_MAG = 101,
2458 CS_STAT_RES_FIRE = 102,
2459 CS_STAT_RES_ELEC = 103,
2460 CS_STAT_RES_COLD = 104,
2461 CS_STAT_RES_CONF = 105,
2462 CS_STAT_RES_ACID = 106,
2463 CS_STAT_RES_DRAIN = 107,
2464 CS_STAT_RES_GHOSTHIT = 108,
2465 CS_STAT_RES_POISON = 109,
2466 CS_STAT_RES_SLOW = 110,
2467 CS_STAT_RES_PARA = 111,
2468 CS_STAT_TURN_UNDEAD = 112,
2469 CS_STAT_RES_FEAR = 113,
2470 CS_STAT_RES_DEPLETE = 114,
2471 CS_STAT_RES_DEATH = 115,
2472 CS_STAT_RES_HOLYWORD = 116,
2473 CS_STAT_RES_BLIND = 117,
2474 CS_STAT_SKILLINFO = 140,
2475 CS_NUM_SKILLS = 50,
2476 SF_FIREON = 0x01,
2477 SF_RUNON = 0x02,
2478 NDI_BLACK = 0,
2479 NDI_WHITE = 1,
2480 NDI_NAVY = 2,
2481 NDI_RED = 3,
2482 NDI_ORANGE = 4,
2483 NDI_BLUE = 5,
2484 NDI_DK_ORANGE = 6,
2485 NDI_GREEN = 7,
2486 NDI_LT_GREEN = 8,
2487 NDI_GREY = 9,
2488 NDI_BROWN = 10,
2489 NDI_GOLD = 11,
2490 NDI_TAN = 12,
2491 NDI_MAX_COLOR = 12,
2492 NDI_COLOR_MASK = 0x1f,
2493 NDI_REPLY = 0x20,
2494 NDI_NOCRATE = 0x40,
2495 NDI_CLEAR = 0x80,
2496 a_none = 0,
2497 a_readied = 1,
2498 a_wielded = 2,
2499 a_worn = 3,
2500 a_active = 4,
2501 a_applied = 5,
2502 F_APPLIED = 0x000F,
2503 F_LOCATION = 0x00F0,
2504 F_UNPAID = 0x0200,
2505 F_MAGIC = 0x0400,
2506 F_CURSED = 0x0800,
2507 F_DAMNED = 0x1000,
2508 F_OPEN = 0x2000,
2509 F_NOPICK = 0x4000,
2510 F_LOCKED = 0x8000,
2511 CF_FACE_NONE = 0,
2512 CF_FACE_BITMAP = 1,
2513 CF_FACE_XPM = 2,
2514 CF_FACE_PNG = 3,
2515 CF_FACE_CACHE = 0x10,
2516 FACE_FLOOR = 0x80,
2517 FACE_COLOR_MASK = 0xf,
2518 UPD_LOCATION = 0x01,
2519 UPD_FLAGS = 0x02,
2520 UPD_WEIGHT = 0x04,
2521 UPD_FACE = 0x08,
2522 UPD_NAME = 0x10,
2523 UPD_ANIM = 0x20,
2524 UPD_ANIMSPEED = 0x40,
2525 UPD_NROF = 0x80,
2526 UPD_SP_MANA = 0x01,
2527 UPD_SP_GRACE = 0x02,
2528 UPD_SP_LEVEL = 0x04,
2529 SOUND_NORMAL = 0,
2530 SOUND_SPELL = 1,
2531
2532 PICKUP_NOTHING = 0x00000000,
2533
2534 PICKUP_DEBUG = 0x10000000,
2535 PICKUP_INHIBIT = 0x20000000,
2536 PICKUP_STOP = 0x40000000,
2537 PICKUP_NEWMODE = 0x80000000,
2538
2539 PICKUP_RATIO = 0x0000000F,
2540
2541 PICKUP_FOOD = 0x00000010,
2542 PICKUP_DRINK = 0x00000020,
2543 PICKUP_VALUABLES = 0x00000040,
2544 PICKUP_BOW = 0x00000080,
2545
2546 PICKUP_ARROW = 0x00000100,
2547 PICKUP_HELMET = 0x00000200,
2548 PICKUP_SHIELD = 0x00000400,
2549 PICKUP_ARMOUR = 0x00000800,
2550
2551 PICKUP_BOOTS = 0x00001000,
2552 PICKUP_GLOVES = 0x00002000,
2553 PICKUP_CLOAK = 0x00004000,
2554 PICKUP_KEY = 0x00008000,
2555
2556 PICKUP_MISSILEWEAPON = 0x00010000,
2557 PICKUP_ALLWEAPON = 0x00020000,
2558 PICKUP_MAGICAL = 0x00040000,
2559 PICKUP_POTION = 0x00080000,
2560
2561 PICKUP_SPELLBOOK = 0x00100000,
2562 PICKUP_SKILLSCROLL = 0x00200000,
2563 PICKUP_READABLES = 0x00400000,
2564 PICKUP_MAGIC_DEVICE = 0x00800000,
2565
2566 PICKUP_NOT_CURSED = 0x01000000,
2567
2568 PICKUP_JEWELS = 0x02000000,
2569 PICKUP_FLESH = 0x04000000;
2570
2571 var stat_32bit = [CS_STAT_WEIGHT_LIM,CS_STAT_SPELL_ATTUNE,CS_STAT_SPELL_REPEL,CS_STAT_SPELL_DENY,CS_STAT_EXP];
2572
2573
2574 isMainScriptLoaded = true;
2575