diff --git a/scripts/buildObjects.js b/scripts/buildObjects.js index a0f27cd..7695a5e 100644 --- a/scripts/buildObjects.js +++ b/scripts/buildObjects.js @@ -1,1787 +1,1787 @@ /* * 3DCycles - A lightcycle game. * Copyright (C) 2019 Glen Harpring * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ //TODO: neaten up this file, make it so the map isn't parsed a bunch of times //TODO: use an object for the cycles? //lots of Durf code around these parts... //NOTE: these functions depend on the presence of mapSTRING and/or mapXML //RETURNS: scene mesh/object to add into global object function loadTextures() { - engine.textures.floor = new new THREE.TextureLoader().load("images/"+settings.FLOOR_TEXTURE); - engine.textures.rim_wall = new new THREE.TextureLoader().load("images/"+settings.RIM_WALL_TEXTURE); + engine.textures.floor = new new THREE.TextureLoader().load(relPath(settings.FLOOR_TEXTURE,"images")); + engine.textures.rim_wall = new new THREE.TextureLoader().load(relPath(settings.RIM_WALL_TEXTURE,"images")); //engine.textures.cycle_wall = new new THREE.TextureLoader().load('images/textures/dir_wall.png'); - engine.textures.cycle_body = new THREE.TextureLoader().load("images/"+settings.CYCLE_TEXTURES[0]); - engine.textures.cycle_wheel = new THREE.TextureLoader().load("images/"+settings.CYCLE_TEXTURES[1]) + engine.textures.cycle_body = new THREE.TextureLoader().load(relPath(settings.CYCLE_TEXTURES[0],"images")); + engine.textures.cycle_wheel = new THREE.TextureLoader().load(relPath(settings.CYCLE_TEXTURES[1],"images")) engine.textures.cycle_shadow = new THREE.TextureLoader().load('images/textures/shadow.png') } //GRID function buildGrid() { //floor texture stuff engine.grid = new THREE.Object3D();//initialize global object var sizeFactorHandle = settings.SIZE_FACTOR / 2; engine.REAL_ARENA_SIZE_FACTOR = Math.pow(2, sizeFactorHandle); var logicalBox = getLogicalBox(engine.mapString);// x, y, minx, miny, maxx, maxy engine.logicalBox = { center: { x:logicalBox[0], y: logicalBox[1]}, min: { x:logicalBox[2], y: logicalBox[3]}, max: { x:logicalBox[4], y: logicalBox[5]} }; var logicalHeight = ((logicalBox[5]-logicalBox[3]) * engine.REAL_ARENA_SIZE_FACTOR)/* + 10*/;//+10 for outer edge var logicalWidth = ((logicalBox[4]-logicalBox[2]) * engine.REAL_ARENA_SIZE_FACTOR)/* + 10*/; if(!engine.dedicated) { var floorTexture = engine.textures.floor; floorTexture.wrapS = floorTexture.wrapT = THREE.RepeatWrapping; floorTexture.repeat.set(logicalWidth,logicalHeight); //floorTexture.repeat.set( 500, 500 ); var centerOffset_x = (logicalBox[2] * engine.REAL_ARENA_SIZE_FACTOR);//offset from bottom left corner var centerOffset_x2 = Math.round((centerOffset_x % 1)*100000000)/100000000; floorTexture.offset.x = centerOffset_x2; var centerOffset_y = (logicalBox[3] * engine.REAL_ARENA_SIZE_FACTOR);//-5;//not needed since we only take %1 offset var centerOffset_y2 = Math.round((centerOffset_y % 1)*100000000)/100000000; floorTexture.offset.y = centerOffset_y2; if(engine.usingWebgl) { var maxAnisotropy = engine.renderer.capabilities.getMaxAnisotropy(); floorTexture.anisotropy = maxAnisotropy; } var color = new THREE.Color(settings.FLOOR_RED,settings.FLOOR_GREEN,settings.FLOOR_BLUE); var floorMaterial = new THREE.MeshBasicMaterial( { color:color, map: floorTexture,/* transparent: settings.ALPHA_BLEND /*, side: THREE.DoubleSide*/} ); floorMaterial.needsUpdate = true;//is this needed? var floorGeometry = new THREE.PlaneBufferGeometry(logicalWidth*settings.GRID_SIZE,logicalHeight*settings.GRID_SIZE,1,1); floorGeometry.dynamic = true;//is this needed? var grid_object = new THREE.Mesh(floorGeometry, floorMaterial); grid_object.position.x = logicalBox[0] * engine.REAL_ARENA_SIZE_FACTOR; grid_object.position.y = logicalBox[1] * engine.REAL_ARENA_SIZE_FACTOR; grid_object.position.z = -2/100;//move down 2/100 units for render glitch //grid_object.scale.set(settings.GRID_SIZE,settings.GRID_SIZE,1); //console.log("gridx: "+grid_object.position.x+" gridy: "+grid_object.position.y); grid_object.geometry.dynamic = true;//is this needed? if(settings.FLOOR_MIRROR) { engine.grid.mirror = grid_object.clone(); engine.grid.mirror.position.z -= 1/100; engine.grid.reflection = new THREE.CubeCamera(0.01,100000,128); engine.scene.add(engine.grid.reflection); floorMaterial.envMap = engine.grid.reflection.renderTarget; engine.grid.reflection.position.copy(grid_object.position); //engine.grid.reflection.position.z = -250; } } // return grid_object; engine.grid.add(grid_object);//add to global object //SPAWNS add to map data var allSpawns = engine.mapXML.getElementsByTagName("Spawn"); for (s = 0; s < allSpawns.length; s++) { var sXpos = (allSpawns[s].getAttribute("x") * engine.REAL_ARENA_SIZE_FACTOR); var sYpos = (allSpawns[s].getAttribute("y") * engine.REAL_ARENA_SIZE_FACTOR); var sZpos = (allSpawns[s].getAttribute("z") * 1); if(isNaN(sZpos)) sZpos = 0; if ( allSpawns[s].hasAttribute("angle") ) { var sAng = allSpawns[s].getAttribute("angle"); } else { var sAng = gafd( parseFloat(allSpawns[s].getAttribute("xdir")), parseFloat(allSpawns[s].getAttribute("ydir")) ); } var spawn_data = [sXpos, sYpos, sZpos, sAng]; engine.map.spawns.push( spawn_data ); } }//end of grid /////////////////////////////// //WALLS function buildWalls() {//builds all walls in map and returns object to add to scene engine.walls = new THREE.Object3D(); var allWalls = engine.mapXML.getElementsByTagName("Wall"); for (var r = 0; r < allWalls.length; r++) { var wall_points = new Array(); if(settings.HIGH_RIM) var wall_height = Math.pow(2,16); else var wall_height = settings.LOW_RIM_HEIGHT; //4 if (allWalls[r].hasAttribute("height")) { wall_height = allWalls[r].getAttribute("height")*1; } var allWallPoints = allWalls[r].getElementsByTagName("Point"); for (var q = 0; q < allWallPoints.length; q++) { wall_points.push( [ allWallPoints[q].getAttribute("x") * engine.REAL_ARENA_SIZE_FACTOR, allWallPoints[q].getAttribute("y") * engine.REAL_ARENA_SIZE_FACTOR, 0, //wall_bottom wall_height ] ); } wall_object = buildWall(wall_points, wall_height); //wall_object.receiveShadow = true; //wall_object.castShadow = true; engine.walls.add(wall_object);//add complete object to global walls engine.map.walls.push(wall_points);//add to map data } } //this is for buildWalls - builds a single wall out of many var totalWallsLength = 0;//used to line textures like arma does function buildWall(pointArray, height) {//builds a single tag if(!settings.RIM_WALL_REPEAT_TOP && height > settings.RIM_WALL_STRETCH_Y) height = settings.RIM_WALL_STRETCH_Y; var geo = new THREE.Geometry(); for (var n = 0; n < pointArray.length; n++) { var thisPoint = pointArray[n]; geo.vertices.push( new THREE.Vector3( (thisPoint[0]), (thisPoint[1]), 0) ); } for (var m = 0; m < pointArray.length; m++) { var thisPoint = pointArray[m]; geo.vertices.push( new THREE.Vector3( (thisPoint[0]), (thisPoint[1]), height) ); } var totalLength = 0; for (var i = 0; i < (geo.vertices.length/2)-1; i++) { var p1x = geo.vertices[i].x; var p1y = geo.vertices[i].y; var p2x = geo.vertices[i+1].x; var p2y = geo.vertices[i+1].y; var dist = Math.sqrt( (p2x-=p1x)*p2x + (p2y-=p1y)*p2y ); totalLength += dist; totalWallsLength += dist; // console.log(totalLength); // var slope = ( (py2 - py1) / (px2 - px1) ); // var invslope = -( (px2 - px1) / (py2 - py1) ); var normal = new THREE.Vector3( (p2y - p1y), -(p2x - p1x), 0 ); // c d // a b geo.faces.push( new THREE.Face3( (i), (i+1), (i+(geo.vertices.length/2)), normal ), //a,b,c new THREE.Face3( (i+(geo.vertices.length/2)+1), (i+(geo.vertices.length/2)), (i+1), normal ) //d,c,b ); geo.faceVertexUvs[0].push( [new THREE.Vector2((totalWallsLength-dist),0),new THREE.Vector2((totalWallsLength),0),new THREE.Vector2((totalWallsLength-dist),1)], //a,b,c [new THREE.Vector2((totalWallsLength),1),new THREE.Vector2((totalWallsLength-dist),1),new THREE.Vector2((totalWallsLength),0)] //d,c,b ); } if(!engine.dedicated) { geo.uvsNeedUpdate = true; geo.buffersNeedUpdate = true; //apparently isn't needed for desired effect geo.computeFaceNormals();//for lighting geo.computeVertexNormals();//for lighting? if(settings.RIM_WALL_TEXTURE != "") { var wallTexture = engine.textures.rim_wall; wallTexture.wrapS = THREE.RepeatWrapping; if(settings.RIM_WALL_WRAP_Y) wallTexture.wrapT = THREE.RepeatWrapping; wallTexture.repeat.set(1/settings.RIM_WALL_STRETCH_X,height/settings.RIM_WALL_STRETCH_Y); //totalLength, height } if(engine.usingWebgl) { var maxAnisotropy = engine.renderer.getMaxAnisotropy(); wallTexture.anisotropy = maxAnisotropy; } var wallIsTooLow = height c && (c += 360); 360 < c && (c -= 360); return c } function cdir(theta) //! Gets [xdir, ydir] from angle { var x = Math.cos(theta); var y = Math.sin(theta); return [x,y]; } function httpGet(url) //! gets HTTP requests synchroniously. DEPRECATED and wont work in nodejs { var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET",url,false); xmlHttp.send(null); return xmlHttp.responseText; } function httpGetAsync(url,callback,errcb=false) //! gets HTTP requests asynchronously { if(window.XMLHttpRequest) { var req = new XMLHttpRequest(); req.onreadystatechange = function() { if(req.readyState == 4 && req.status == 200) callback(req.responseText); } if(errcb) { req.onerror = errcb; } req.open("GET",url,true); req.send(null); } else if(window.https && url.indexOf("https://") == 0) { var req = https.get(url,function(res) { res.data = ""; res.on('data',function(data) { res.data += data; if(res.statusCode == 200) callback(res.data) }); }); if(errcb) req.on('error',errcb); } else if(window.http) //no https support { var req = http.get(url.replace("https://","http://"),function(res) { res.data = ""; res.on('data',function(data) { res.data += data; if(res.statusCode == 200) callback(res.data) }); }); if(errcb) req.on('error',errcb); } else { throw "No methods to GET file"; } } function xmlify(string) //! Gets XML object from string. { var val; if (window.DOMParser) { val = (new DOMParser).parseFromString(string, "text/xml"); } else { val = new ActiveXObject("Microsoft.XMLDOM"); val.async = !1; val.loadXML(string); } return val; } function getVarFromString(string) //! Find variable parameters from string, used in parsing menus { var splice = string.split("."); var variable = settings, var2 = commands; for(var y=0;y/g,">").replace(/"/g,"""); } function colorIsDark(r,g,b) { return ( ( r < 255*settings.FONT_MIN_R && g < 255*settings.FONT_MIN_G && b < 255*settings.FONT_MIN_B )|| r+g+b < 255*settings.FONT_MIN_TOTAL ); } function getDarkBGFromHex(hex) { var c = new THREE.Color(hex); if(colorIsDark(c.r,c.g,c.b)) return "white"; else return "none"; } function replaceColors(str) { if(typeof(str) == "undefined") return typeof(str); var dark = "class=darktext"; //Capitals are allowed because the processes here can handle them str = str.replace(settings.VERIFY_COLOR_STRICT?/0x([0-9A-Fa-f]{6}|RESETT)(.*?)(?=0x(?:[0-9A-Fa-f]{6}|RESETT)|$)/gm : /0x(.{6})(.*?)(?=0x(?:.{6})|$)/gm, function(x) { if(x.substr(2,6) == "RESETT") { return x.substr(8); } else { //var darkI1="class=lighttext"; var darkI1=""; var r=parseInt(x[2]+x[3],16),g=parseInt(x[4]+x[5],16),b=parseInt(x[6]+x[7],16); //NOTE: unless using regex, javascript only replaces the first occurance if(isNaN(r)){if(isNaN(parseInt(x[2],16)))x=x.replace(x[2],"0");if(isNaN(parseInt(x[3],16)))x=x.replace(x[3],"0");r=parseInt(x[2]+x[3],16)} if(isNaN(g)){if(isNaN(parseInt(x[4],16)))x=x.replace(x[4],"0");if(isNaN(parseInt(x[5],16)))x=x.replace(x[5],"0");g=parseInt(x[4]+x[5],16)} if(isNaN(b)){if(isNaN(parseInt(x[6],16)))x=x.replace(x[6],"0");if(isNaN(parseInt(x[7],16)))x=x.replace(x[7],"0");b=parseInt(x[6]+x[7],16)} if(colorIsDark(r,g,b)) { if(settings.TEXT_DARK_HIGHLIGHT) { darkI1 = dark; } if(settings.TEXT_BRIGHTEN) { if(r < settings.FONT_MIN_R) r += settings.FONT_MIN_R; if(g < settings.FONT_MIN_G) g += settings.FONT_MIN_G; if(b < settings.FONT_MIN_B) b += settings.FONT_MIN_B; if(colorIsDark(r,g,b)) { r += settings.FONT_MIN_TOTAL/3; g += settings.FONT_MIN_TOTAL/3; b += settings.FONT_MIN_TOTAL/3; } } } return ""+x.substr(8)+""; } }); return str; } function removeColors(str) { return str.replace(settings.VERIFY_COLOR_STRICT?/0x([0-9A-Fa-f]{6}|RESETT)(.*?)(?=0x(?:[0-9A-Fa-f]{6}|RESETT)|$)/gm : /0x(.{6})(.*?)(?=0x(?:.{6})|$)/gm,function(x){return x.substr(8)}); } String.prototype.filter = function() //! Filter illegal player characters. Heavily based on ArmagetronAd's filtering. { var char, out="", str = this.toString(); for(var i=0;i 32) //Leave ASCII characters but convert them to lower case { if(char == 48) out += "o"; //map 0 to o because z-man else out += str[i].toLowerCase(); } //! map umlauts and similar to their base characters else if(char >= 0xc0 && char <= 0xc5) out += 'a'; else if(char >= 0xd1 && char <= 0xd6) out += 'o'; else if(char >= 0xd9 && char <= 0xdD) out += 'u'; else if(char == 0xdf) out += 's'; else if(char >= 0xe0 && char <= 0xe5) out += 'a'; else if(char >= 0xe8 && char <= 0xeb) out += 'e'; else if(char >= 0xec && char <= 0xef) out += 'i'; else if(char >= 0xf0 && char <= 0xf6) out += 'o'; else if(char >= 0xf9 && char <= 0xfc) out += 'u'; else if(char >= 0xc0 && char <= 0xc5) out += 'a'; else switch(char) { //some of those are a bit questionable, but still better than lots of underscores case 161: out += '!'; break; case 162: out += 'c'; break; case 163: out += 'l'; break; case 165: out += 'y'; break; case 166: out += '|'; break; case 167: out += 's'; break; case 168: out += '"'; break; case 169: out += 'c'; break; case 170: out += 'a'; break; case 171: out += '"'; break; case 172: out += '!'; break; case 174: out += 'r'; break; case 176: out += 'o'; break; case 177: out += '+'; break; case 178: out += '2'; break; case 179: out += '3'; break; case 182: out += 'p'; break; case 183: out += '.'; break; case 185: out += '1'; break; case 187: out += '"'; break; case 198: out += 'a'; break; case 199: out += 'c'; break; case 208: out += 'd'; break; case 209: out += 'n'; break; case 215: out += 'x'; break; case 216: out += 'o'; break; case 221: out += 'y'; break; case 222: out += 'p'; break; case 231: out += 'c'; break; case 241: out += 'n'; break; case 247: out += '/'; break; case 248: out += 'o'; break; case 253: out += 'y'; break; case 254: out += 'p'; break; case 255: out += 'y'; break; default: out += "_"; break; //unknown character, mapped to underscore } } return out; } function tStringify(str) //! { str = str.replace(/\$\w*/g,function(i){console.log(i.replace("\$",""));}); str = str.replace(new RegExp("@progtitle@",'g'),"3DCycles Web"); str = str.replace(new RegExp("@progtitleshort@",'g'),"3DCycles"); str = str.replace(new RegExp("@progname@",'g'),"webtron"); return str; } function pi(a=1) {return Math.PI*a} //! Finds multiples of PI. function setNewFont(input) //! Gets font from user input. Not used anywhere anymore. { input = input.toLowerCase(); var output = ""; switch(input) { case 'armagetronad':case 'armagetron':case 'arma':case 'tron': output = "Armagetronad"; break; case 'flynn':case 'flyn':case 'flyyn':case 'flin':case 'user':case 'legacy': output = "Flynn"; break; case 'serif':case 'srif':case 'serf':case 'srf':case 'font': output = "serif"; break; case 'sans-serif':case 'sansserif':case 'sans':case 'sanserif':case 'san': output = "sans-serif"; break; case 'nicefont':case 'nice':case 'nfont': output = "nicefont"; break; case 'monospace':case 'mono':case 'fixedwidth':case 'fixed': output = "monospace"; break; default: output = "Armagetronad"; } return output; } function pointDistance(x1,y1,x2,y2) { var xs = x2 - x1, ys = y2 - y1; return Math.sqrt( xs*xs + ys*ys ); } function getLogicalBox(string) //! Parses map file and returns [x, y, minx, miny, maxx, maxy] or false on failure. { var re = /(x|y)\=.-?(\d*.)?\d+/gi; var matches = string.match(re); var temp = 0; var box = [0,0,Infinity,Infinity,-Infinity,-Infinity];// x, y, minx, miny, maxx, maxy if (matches) { for (var i = 0; i < matches.length; i++) { matches[i] = matches[i].replace(/\"|\'/g, ''); //console.log(matches[i]); if (matches[i].indexOf("x") > -1) { // x=250.25 matches[i] = matches[i].replace('x=', ''); temp = parseFloat(matches[i]); if (temp > box[4]) { box[4] = temp; } if (temp < box[2]) { box[2] = temp; } } if (matches[i].indexOf("y") > -1) { // y=-25 matches[i] = matches[i].replace('y=', ''); temp = parseFloat(matches[i]); if (temp > box[5]) { box[5] = temp; } if (temp < box[3]) { box[3] = temp; } } } //get center box[0] = ( box[2] + box[4] ) / 2; box[1] = ( box[3] + box[5] ) / 2; //console.log(box); return box; } else { return false; } } function hasClass(element, cls) {//checks if element has classname, returns true | false return (' ' + element.className + ' ').indexOf(' ' + cls + ' ') > -1; } +function relPath(path,rel="/") +{ + if(rel.indexOf("/") != 0) rel = "/"+rel; + if(rel.indexOf("/",rel.length-1) == -1) rel += "/"; + + if(path.indexOf("://") >= 0 || path.indexOf("/") == 0) return path; + else return rel+path; +} + function inround() //! Tries to determine if we're in a round or not. { return !engine.roundCommencing && engine.gtime >= -4000; } function deg2rad(angle) { if(!isFinite(angle)) return angle; angle %= 360; if(angle < 0) angle += 360; var radians = angle * Math.PI / 180; return radians; } function rad2deg(radians) { if(!isFinite(radians)) return radians; var angle = radians * 180 / Math.PI; angle %= 360; if(angle < 0) angle += 360; return angle; } function normalizeRad(radians) { var pi2 = Math.PI*2; radians = radians%pi2; while(radians < 0) radians += pi2; return radians; } // BEGIN based on code from http://geomalgorithms.com/a07-_distance.html // Copyright 2001 softSurfer, 2012 Dan Sunday // This code may be freely used, distributed and modified for any purpose // providing that this copyright notice is included with it. // SoftSurfer makes no warranty for this code, and cannot be held // liable for any real or imagined damage resulting from its use. // Users of this code must verify correctness for their application. var dot = function(ux,uy,vx,vy) { return ((ux*vx)+(uy*vy)); }; var SMALL_NUM = 0.00000001; // anything that avoids division overflow function distanceoflines(x1,y1, x2,y2, x3,y3, x4,y4) { var ux=x2-x1,uy=y2-y1; var vx=x4-x3,vy=y4-y3 var wx=x1-x3,wy=y1-y3; //var a = dot(ux,uy,ux,uy), b = dot(ux,uy,vx,vy), c = dot(vx,vy,vx,vy), d = dot(ux,uy,wx,wy), e = dot(vx,vy,wx,wy); var a = (ux*ux)+(uy*uy), b = (ux*vx)+(uy*vy), c = (vx*vx)+(vy*vy), d = (ux*wx)+(uy*wy), e = (vx*wx)+(vy*wy); //probably faster var D = a*c - b*b; var sc,sN,sD = D; var tc,tN,tD = D; if(D < SMALL_NUM) //lines almost parallel { sN = 0; //force point p0 on segment s1 sD = 1; //prevent possible division by zero tN = e; tD = c; } else //get closest points on the infinite lines { sN = (b*e - c*d); tN = (a*e - b*d); if(sN < 0) //sc < 0 => the s=0 edge is visible { sN = 0; tN = e; tD = c; } else if(sN > sD) //sc > 1 => the s=1 edge is visible { sN = sD; tN = e + b; tD = c; } } if(tN < 0) // tc < 0 => the t=0 edge is visible { tN = 0; //recompute sc this edge if(d>0) { sN = 0; } else if(d tD) //tc > 1 => the t=1 edge is visible { tN = tD; //recompute sc for this edge if((b-d) < 0) { sN = 0; } else if((b-d) > a) { sN = sD; } else { sN = (b-d); sD = a; } } //finally, do the division to get sc and tc; var sc = (Math.abs(sN) < SMALL_NUM ? 0.0 : sN / sD); var tc = (Math.abs(tN) < SMALL_NUM ? 0.0 : tN / tD); var dPx = wx + (ux * sc) - (vx * tc); var dPy = wy + (uy * sc) - (vy * tc); //console.log(dPx,dPy); //return Math.sqrt(dot(dPx,dPy,dPx,dPy)); return Math.hypot(dPx,dPy); } // END function is_in_circle(p1x, p1y, r1, p2x, p2y, r2=0) { return(r1+r2 > Math.sqrt(Math.pow((p1x-p2x),2)+Math.pow((p1y-p2y),2))) } function lineIntersect(p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) { var s1_x = p1_x - p0_x, s1_y = p1_y - p0_y, s2_x = p3_x - p2_x, s2_y = p3_y - p2_y; var s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y), t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y); return (s >= 0 && s <= 1 && t >= 0 && t <= 1); } ///////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////// //"encrytion" variables, not sure what they were for: String.prototype.toEncodedString = function () { var ostr = this.toString().replace(/\s+/g, ''); if (ostr.length < 8) { alert("Password must be at least 8 characters long with no spaces."); return null; }; var x, nstr = '', len = ostr.length; for (x = 0; x < len; ++x) { nstr += (255 - ostr.charCodeAt(x)).toString(36).toUpperCase().toPaddedString(2, '0'); }; return nstr; }; String.prototype.fromEncodedString = function () { var ostr = this.toString(); var x, nstr = '', len = ostr.length; for (x = 0; x < len; x += 2) { nstr += String.fromCharCode(255 - parseInt(ostr.substr(x, 2), 36)); }; return nstr; }; Number.prototype.toPaddedString = function (len, pad) { len = (len) ? Number(len) : 2; if (isNaN(len)) { alert("Padded String 'length' argument is not numeric."); return null; }; var dflt = (isNaN(this.toString())) ? " " : "0"; pad = (pad) ? pad.toString().substr(0, 1) : dflt; var str = this.toString(); if (dflt == "0") { while (str.length < len) str = pad + str; } else { while (str.length < len) str += pad; }; return str; }; String.prototype.toPaddedString = Number.prototype.toPaddedString; /**/ var encrypt1 = new Date().getTime(); encrypt1 = ""+encrypt1;//##############... //var encrypt2 = encrypt1.toEncodedString(); //var str3 = str2.fromEncodedString(); /**/ function getSuperString() { var superstring = encrypt1.toEncodedString(); superstring = "lightcycle"+superstring; return superstring; } var ss = getSuperString();