Page MenuHomePhabricator

No OneTemporary

diff --git a/index.html b/index.html
index 3a6d6d0..8cfca13 100644
--- a/index.html
+++ b/index.html
@@ -1,130 +1,131 @@
<!DOCTYPE html>
<html>
<head>
<title id="progtitle">3DCycles</title>
<link rel="icon" type="image/x-icon" href="favicon.ico"/>
<link rel="stylesheet" type="text/css" href="styles/main.css"/>
<link rel="stylesheet" type="text/css" href="styles/arma.css"/>
<script type="text/javascript" src="test.js"></script>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport'/>
<script type="text/javascript" src="scripts/lib/Three.js"></script><!-- webgl framework -->
<script type="text/javascript" src="scripts/lib/legacy/Projector.js"></script><!-- needed for softwarerenderer -->
<script type="text/javascript" src="scripts/lib/legacy/SoftwareRenderer.js"></script><!-- canvas renderer for older browsers -->
<script type="text/javascript" src="scripts/lib/Detector.js"></script><!--//detects webgl renderer -->
<script type="text/javascript" src="scripts/lib/OBJExporter.js"></script>
<script type="text/javascript" src="scripts/lib/OBJLoader.js"></script><!-- webgl framework addon for obj loading -->
<script type="text/javascript" src="scripts/lib/rAF.js"></script><!-- requestAnimationFrame shim/polyfill -->
<script type="text/javascript" src="scripts/lib/OrbitControls.js"></script><!-- camera orbit -->
<script type="text/javascript" src="scripts/lib/SceneUtils.js"></script>
<script type="text/javascript" src="scripts/lib/xmllint.js"></script><!-- XML verification -->
<script type="text/javascript" src="scripts/functions-head.js"></script><!-- predefined functions that can be in head -->
<script type="text/javascript" src="scripts/lib/buffer-loader.js"></script><!-- buffer loader for sound -->
<script type="text/javascript" src="scripts/sound.js"></script><!-- loading sound files -->
</head>
<body>
<div id="input">
<span>Say:</span>&nbsp;<input type="text" class="fakemenu-active" onblur="if(engine.inputState.substr(0,5)=='input')keyboardKeyDown({keyCode:27})"/>
</div>
<div id="menu-tooltip"></div>
<div id="menu" class="noselect mainbg_img"><h1>3DCycles is loading...</div>
<pre id="console"><span><br></span></pre>
<span id="HUD" style="opacity:0">
<div id="gui_stats" class="noselect">
FPS : <span name="current_framerate" precision="0"></span><br>
(<span name="current_pos_x_adj" precision="2"></span>,<span name="current_pos_y_adj" precision="2"></span>)<br>
<!--(<span name="current_angle_x" precision="2"></span>,<span name="current_angle_y" precision="2"></span>)<br>-->
<!--Vel: <span name="player_speed" precision="1"></span><br>-->
<!--Time: <span name="current_time" precision="1"></span><br>-->
F:<span name="dist_to_impact_front" precision="2"></span><br>
F:<span name="time_to_impact_front" precision="2"></span>s<br>
L:<span name="dist_to_impact_left" precision="2"></span><br>
L:<span name="time_to_impact_left" precision="2"></span>s<br>
R:<span name="dist_to_impact_right" precision="2"></span><br>
R:<span name="time_to_impact_right" precision="2"></span>s<br>
<canvas id="canvas" style="position:absolute;right:0;width:200px;" ></canvas>
</div>
<div id="game_stats" class="noselect" style="opacity:0">
<div style="color:white;position:fixed;bottom:4px;left:0;right:0">
<div style="text-align:center">
0
<div class="notprogressbar" style="text-align:center;position:absolute">
<span name="player_speed" toprecision=2></span>
</div>
<div class="progressbar">
<div name="player_speed" class="progress" style="background:white"></div>
</div>
<span name="max_speed" precision=2></span>
<div style="text-align:center">Speed</div>
</div>
</div>
<div style="color:white;position:fixed;bottom:4px;left:1%">
0
<div class="progressbar" style="text-align:center">
<div name="player_rubber" class="progress" bgcolorgrad="0,15,0;15,0,0"></div>
</div>
<span name="cycle_rubber" toprecision=1></span>
<div style="text-align:center"><span name="player_rubber" precision=1 toprecision=2></span></div>
</div>
<div style="color:white;position:fixed;bottom:4px;right:1%">
0
<div class="progressbar" style="text-align:center">
<div name="player_brake" class="progress" bgcolorgrad="15,0,0;0,15,0"></div>
</div>
1
<div style="text-align:center">Brake</span></div>
</div>
</div>
<div id="scoreboard">
<table style="width:100%">
<thead>
- <tr><th>&nbsp;<span style="color:#f80">Name:</span></th><th>Alive:</th><th>Score:</th><th>Ping:</th></tr>
+ <tr><th>&nbsp;<span style="color:#f80">Name:</span></th><th>Alive:</th><th>Score:</th><th>Ping:</th><th>Team:</th></tr>
</thead>
<tbody>
<!--<tr><td>&nbsp;Test</td><td>huh</td><td>0</td><td>0</td><tr>-->
</tbody>
</table>
</div>
</span>
<div id="centerMessage">&nbsp;</div>
<script type="text/javascript" src="scripts/input.js"></script>
<script type="text/javascript" src="scripts/menu.js"></script>
<script type="text/javascript" src="scripts/config.js"></script><!-- configuration + local storage -->
<script type="text/javascript" src="scripts/zone.js"></script>
<script type="text/javascript" src="scripts/player.js"></script>
+ <script type="text/javascript" src="scripts/team.js"></script>
<script type="text/javascript" src="scripts/ai.js"></script>
<script type="text/javascript" src="scripts/functions-body.js"></script><!-- body functions -->
<script type="text/javascript" src="scripts/buildObjects.js"></script><!-- builds usable scene objects -->
<script type="text/javascript" src="scripts/init.js"></script><!-- initializes render -->
<script type="text/javascript" src="scripts/game.js"></script><!-- game -->
<script type="text/javascript" src="scripts/render.js"></script><!-- render loop functions -->
<script type="text/javascript" src="scripts/network.js"></script><!-- network test -->
</body>
</html>
diff --git a/scripts/config.js b/scripts/config.js
index 21e6315..d3e6645 100644
--- a/scripts/config.js
+++ b/scripts/config.js
@@ -1,1458 +1,1462 @@
/*
* 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.
*/
/*class Setting
{
constructor(conf)
{
switch(typeof(conf))
{
case "object": this = conf; break;
}
}
push()
{
settings_work[this.name] = this;
settings[this.name] = this.val;
}
}
//new Setting({name:"VERIFY_COLOR_STRICT",val:false}).push();
var settings_work = {};*/
settings = {
VERIFY_COLOR_STRICT: false,
TEXT_BRIGHTEN: false,
TEXT_DARK_HIGHLIGHT: true,
FONT_MIN_R: 0.5, FONT_MIN_G: 0.5, FONT_MIN_B: 0.5,
FONT_MIN_TOTAL: 0.7,
CHAT_LAYER: 0.5,
TEXT_OUT: function(params=undefined){if(params !== undefined) engine.console.style.display=params?"block":"none"; return engine.console.style.display!="none";},
TEXT_OUT_MODE: 1,
FULLSCREEN: function(params=undefined){
if(params !== undefined)
{
var bd = document.body;
if(params)
{
if(bd.requestFullscreen) bd.requestFullscreen();
else if(bd.webkitRequestFullscreen) bd.webkitRequestFullscreen();
else if(bd.mozRequestFullScreen) bd.mozRequestFullScreen();
else if(bd.msRequestFullscreen) bd.msRequestFullscreen();
else alert("Can't go into fullscreen. Please alert nelg with information on what browser you're using.")
}
else
{
if(bd.exitFullscreen) bd.exitFullscreen();
else if(document.webkitExitFullscreen) document.webkitExitFullscreen();
else if(document.mozCancelFullScreen) document.mozCancelFullScreen();
//else if(document.msCancelFullscreen) bd.msCancelFullscreen();
else alert("Can't exit fullscreen. Please alert nelg with information on what browser you're using")
}
}
return Boolean(window.fullScreen || document.mozFullScreen || document.msFullScreen || document.webkitIsFullScreen || window.outerHeight - window.innerHeight <= 1);
},
//CAMERA
CAMERA_FOV: 60,
CAMERA_NEAR_RENDER: 0.001,
CAMERA_FAR_RENDER: 2000,
//GAME
GRID_SIZE: 1,
/*FLOOR_RED: 0.75,
FLOOR_GREEN: 0.75,
FLOOR_BLUE: 0.98,*/
FLOOR_RED: 0.03,
FLOOR_GREEN: 0.266,
FLOOR_BLUE: 0.8,
FLOOR_TEXTURE: "textures/floor.png",
/*GRID_SIZE: 2,
FLOOR_RED: 1,
FLOOR_GREEN: 1,
FLOOR_BLUE: 1,
FLOOR_TEXTURE: "textures/moviepack_t_r_u_e/floor.png",*/
/*GRID_SIZE: 1,
FLOOR_RED: 0.01,
FLOOR_GREEN: 0.14,
FLOOR_BLUE: 0.35,
FLOOR_TEXTURE: "textures/aaold/floor.png",*/
FLOOR_MIRROR: false,
FLOOR_MIRROR_INT: 1,
CYCLE_TEXTURES: ["textures/cycle_body.png","textures/cycle_wheel.png"],
EXPLOSIONS: true,
HIGH_RIM: false,
LOW_RIM_HEIGHT: 50,
RIM_WALL_RED: 0,
RIM_WALL_GREEN: 0, // 0.533
RIM_WALL_BLUE: 0, // 1
RIM_WALL_ALPHA: 0.9,
RIM_WALL_COLOR_MODE: 3,
RIM_WALL_STRETCH_X: 50,
RIM_WALL_STRETCH_Y: 13.5,
RIM_WALL_WRAP_Y: false,
RIM_WALL_REPEAT_TOP: false,
RIM_WALL_TEXTURE: "textures/futurerim.png",
RIM_WALL_DEPTH: true,
RIM_WALL_LOWEST_HEIGHT: 0,
RIM_WALL_BELOW_HEIGHT_COLOR_R: 0,
RIM_WALL_BELOW_HEIGHT_COLOR_G: 0,
RIM_WALL_BELOW_HEIGHT_COLOR_B: 0,
/*RIM_WALL_RED: 1,
RIM_WALL_GREEN: 1,
RIM_WALL_BLUE: 1,
RIM_WALL_ALPHA: 1,
RIM_WALL_COLOR_MODE: 0,
//RIM_WALL_STRETCH_X: 300,
//RIM_WALL_STRETCH_Y: 50,
RIM_WALL_STRETCH_X: 128,
RIM_WALL_STRETCH_Y: 32,
LOW_RIM_HEIGHT: 32,
RIM_WALL_WRAP_Y: false,
RIM_WALL_TEXTURE: "textures/moviepack_eddkeefe/rim_wall.png",
RIM_WALL_LOWEST_HEIGHT: 32,
RIM_WALL_BELOW_HEIGHT_COLOR_R: 166/255,
RIM_WALL_BELOW_HEIGHT_COLOR_G: 45/255,
RIM_WALL_BELOW_HEIGHT_COLOR_B: 237/255,//*/
RIM_WALL_RED: 1,
RIM_WALL_GREEN: 1,
RIM_WALL_BLUE: 1,
RIM_WALL_ALPHA: 1,
RIM_WALL_COLOR_MODE: 0,
//RIM_WALL_STRETCH_X: 300,
//RIM_WALL_STRETCH_Y: 50,
RIM_WALL_STRETCH_X: 1536,
RIM_WALL_STRETCH_Y: 32,
LOW_RIM_HEIGHT: 32,
RIM_WALL_WRAP_Y: false,
RIM_WALL_TEXTURE: "textures/moviepack_t_r_u_e/movie-rim-wall.png",
RIM_WALL_DEPTH: true,
RIM_WALL_LOWEST_HEIGHT: 32,
/*RIM_WALL_BELOW_HEIGHT_COLOR_R: 188/255,
RIM_WALL_BELOW_HEIGHT_COLOR_G: 206/255,
RIM_WALL_BELOW_HEIGHT_COLOR_B: 250/255,//*/
RIM_WALL_BELOW_HEIGHT_COLOR_R: 0.5,
RIM_WALL_BELOW_HEIGHT_COLOR_G: 0.5,
RIM_WALL_BELOW_HEIGHT_COLOR_B: 0.7,
COLOR_MODE_3_COLORS: "1,0,0;1,1,0;0,1,0;0,1,1;0,0,1;1,0,1",
COLOR_MODE_3_SPEED: 0.2,
ALPHA_BLEND: true,
MENU_RENDER: "img",
REDRAW_MODE: 0,
TARGET_FPS: 1,
MAX_TARGET_FPS: 1000,
//DEDICATED_FPS: Infinity,
DEDICATED_FPS: 40,
GRAB_SENSORS_ON_TURN: true,
CYCLE_SENSORS_RANGE: 100,
GAME_LOOP: 0.5,
TIME_FACTOR: 1,
HUD_MAP: true,
ADMIN_KILL_MESSAGE: true,
//SOUNDS
SOUNDS_INTRO: false,
SOUNDS_EXTRO: false,
SOUNDS_COUNTDOWN: true,
SOUNDS_GO: false,
SOUNDS_ZONES: false,
MUSIC: 0,
//ZONES
ZONE_HEIGHT: 5,
ZONE_SEGMENTS: 11,//arma render only
ZONE_SEG_LENGTH: 0.5,//arma render only
ZONE_ALPHA: 0.7,
ZONE_SPIN_SPEED: 0.05,
ZONE_RENDER_TYPE: 'arma',//cylinder or arma
//player (for armagetron nabs) //can't have people changing these on a server
PLAYER_1: function(val) { if(engine.dedicated) return (settings.PLAYER_1 = "Player 1"); if(typeof(val) != "undefined") {settings.players[0].name=val;} return settings.players[0].name; },
COLOR_R_1: function(r=undefined) { if(engine.dedicated) return (settings.COLOR_R_1=13); return plnumcolors({r:r}).r },
COLOR_G_1: function(g=undefined) { if(engine.dedicated) return (settings.COLOR_G_1=13); return plnumcolors({g:g}).g },
COLOR_B_1: function(b=undefined) { if(engine.dedicated) return (settings.COLOR_B_1=0); return plnumcolors({b:b}).b },
PLAYER_DEL_HIST_PERROUND: true, //what was this?
TIMESTEP_MAX: 0.2,
//debug
DEBUG_EVERYONE_IS_AI: false,
HACK_TURN_LEFT_WHEN_POSSIBLE: 0,
HACK_TURN_RIGHT_WHEN_POSSIBLE: 0,
HACK_TURN_SENSOR_DIST: 5,
CHATBOT_ALWAYS_ACTIVE: false,
//NETWORK
CONNECT_PORT: 5331,
CONNECT_HOST: "armagetron.kevinh.us",
CONNECT_SSL: true,
CYCLE_SMOOTH_TIME: 0.3,
CYCLE_SYNC_INTERVAL: 0.1,
SERVER_PORT: 5331,
SERVER_NAME: "Unnamed Server",
SERVER_DNS: "",
SERVER_SSL_ENABLED: false,
SERVER_SSL_KEY: "",
SERVER_SSL_CERT: "",
};
if(!Detector.webgl)
{
//choose better defaults for the software renderer
settings.HIGH_RIM = false;
settings.LOW_RIM_HEIGHT = 4;
settings.RIM_WALL_TEXTURE = "";
settings.RIM_WALL_DEPTH = false;
settings.ALPHA_BLEND = false;
}
game_settings_default = {
AI_FORCE_BRAKE: false,
+ AI_TEAM: false,
+ AI_DUAL_COLOR_NAME: false,
//CYCLE
CYCLE_ACCEL: 10,
CYCLE_ACCEL_ENEMY: 1,
CYCLE_ACCEL_OFFSET: 2,
CYCLE_ACCEL_RIM: 0,
CYCLE_ACCEL_SELF: 1,
CYCLE_ACCEL_SLINGSHOT: 1,
CYCLE_ACCEL_TEAM: 1,
CYCLE_ACCEL_TUNNEL: 1,
CYCLE_WALL_NEAR: 6,
CYCLE_BRAKE: 30,
CYCLE_BRAKE_DEPLETE: 1,
CYCLE_BRAKE_REFILL: 0.1,
CYCLE_BOOST: 0,
CYCLE_JUMP: 0.5,
CYCLE_JUMP: 0,
CYCLE_MIDAIR_JUMP: false,
CYCLE_MIDAIR_TURN: false,
CYCLE_WALL_RAMP_ENABLE: true,
CYCLE_DELAY: 0.02,
CYCLE_RUBBER: 5,
CYCLE_RUBBER_TIME: 10,
//CYCLE_RUBBER_TIMEBASED: 0,
CYCLE_RUBBER_MINDISTANCE: 0.03,
CYCLE_RUBBER_MINADJUST: 0.05,
CYCLE_RUBBER_DEPLETE_RIM: true,
CYCLE_RUBBER_DEPLETE_SELF: true,
CYCLE_RUBBER_DEPLETE_ENEMY: true,
CYCLE_SOUND_SPEED: 30,
CYCLE_SPEED: 20,
CYCLE_SPEED_DECAY_ABOVE: 0.1,
CYCLE_SPEED_DECAY_BELOW: 5,
CYCLE_SPEED_MAX: 0,
CYCLE_SPEED_MIN: 0.25,
CYCLE_START_SPEED: 20,
CYCLE_TURN_MEMORY: 3,
CYCLE_TURN_SPEED_FACTOR: 0.95,
WALLS_LENGTH: 600,
//WALLS_LENGTH: 30,
RESPAWN_TIME: -1,
CYCLE_FIRST_SPAWN_PROTECTION: false,
CYCLE_WALL_TIME: 5,
CYCLE_INVULNERABILITY_TIME: -1,
WALLS_STAY_UP_DELAY: 1,
+ SP_HUMANS_COUNT: 1,
//TEAMS
TEAMS_MAX_PLAYERS: 1,
TEAMS_MIN_PLAYERS: 1,
TEAMS_MAX: 16,
- TEAMS_MIN: 4,
- //TEAMS_MIN: 2,
- TEAM_ALLOW_SHUFFLE_IP: 0,
+ //TEAMS_MIN: 4,
+ TEAMS_MIN: 2,
+ TEAM_ALLOW_SHUFFLE_UP: 0,
ALLOW_TEAM_NAME_PLAYER: true,
ALLOW_TEAM_NAME_COLOR: true,
MIN_PLAYERS: 1,
NUM_AIS: 0,
+ SP_NUM_AIS: 4,
TEAM_NAME_1: "Team Blue", //name of team 1
TEAM_RED_1: 4, //red portion of team 1's color
TEAM_GREEN_1: 8, //green portion of team 1's color
TEAM_BLUE_1: 15, //blue portion of team 1's color
TEAM_NAME_2: "Team Gold", //name of team 2
TEAM_RED_2: 15, //red portion of team 2's color
TEAM_GREEN_2: 15, //green portion of team 2's color
TEAM_BLUE_2: 4, //blue portion of team 2's color
TEAM_NAME_3: "Team Red", //name of team 3
TEAM_RED_3: 15, //red portion of team 3's color
TEAM_GREEN_3: 4, //green portion of team 3's color
TEAM_BLUE_3: 4, //blue portion of team 3's color
TEAM_NAME_4: "Team Green", //name of team 4
TEAM_RED_4: 4, //red portion of team 4's color
TEAM_GREEN_4: 15, //green portion of team 4's color
TEAM_BLUE_4: 4, //blue portion of team 4's color
TEAM_NAME_5: "Team Violet", //name of team 5
TEAM_RED_5: 15, //red portion of team 5's color
TEAM_GREEN_5: 4, //green portion of team 5's color
TEAM_BLUE_5: 15, //blue portion of team 5's color
TEAM_NAME_6: "Team Cyan", //name of team 6
TEAM_RED_6: 4, //red portion of team 6's color
TEAM_GREEN_6: 15, //green portion of team 6's color
TEAM_BLUE_6: 15, //blue portion of team 6's color
TEAM_NAME_7: "Team White", //name of team 7
TEAM_RED_7: 15, //red portion of team 7's color
TEAM_GREEN_7: 15, //green portion of team 7's color
TEAM_BLUE_7: 15, //blue portion of team 7's color
TEAM_NAME_8: "Team Black", //name of team 8
TEAM_RED_8: 0, //red portion of team 8's color
TEAM_GREEN_8: 0, //green portion of team 8's color
TEAM_BLUE_8: 0, //blue portion of team 8's color
//MAP
ARENA_AXES: 4,
STRICT_AXES_SPAWN: true,
RESOURCE_REPOSITORY_CACHE: './cache/resource/',
MAP_FILE: 'Anonymous/polygon/regular/square-1.0.1.aamap.xml',
MAP_ROTATION: "",
ROTATION_TYPE: 0, //1:round, 2:match
RESOURCE_REPOSITORY_SERVER: 'https://www.armanelgtron.tk/armagetronad/resource/',
//RESOURCE_REPOSITORY_BACKUP: 'http://resource.armagetronad.net/resource/',
SIZE_FACTOR: -3,
ARENA_BOUNDARY: -10,
ARENA_BOUNDARY_KILLS: true,
ZONE_ALPHA_SERVER: 1,
//GAME PLAY
GAME_TYPE: 1,
FINISH_TYPE: 2,
LIMIT_ROUNDS: 10,
LIMIT_TIME: 30,
LIMIT_SCORE: 100,
ROUND_WAIT: false,
//SHOOTING
SHOT_THRESH: 2,
//WIN ZONE
WIN_ZONE_DEATHS: false,
WIN_ZONE_EXPANSION: 1,
WIN_ZONE_INITIAL_SIZE: 5,
WIN_ZONE_RANDOMNESS: 0.8,
WIN_ZONE_MIN_LAST_DEATH: 30,
WIN_ZONE_MIN_ROUND_TIME: Infinity, //60
//FORTRESS
FORTRESS_CONQUEST_RATE: 0.5,
FORTRESS_CONQUEST_DECAY_RATE: 0.1,
//SPAWN
SPAWN_WINGMEN_SIDE: 2.75362,
SPAWN_WINGMEN_BACK: 2.202896,
//ROUNDLY
ROUND_COMMAND: "",
ROUND_CONSOLE_MESSAGE: "",
ROUND_CENTER_MESSAGE: "",
//TARGET
DEFAULT_TARGET_COMMAND: "",
//TARGET_DECLARE_WINNER: true,
//TARGET_LIFETIME: -1,
TARGET_INITIAL_SCORE: 10,
//TARGET_SCORE_DEPLETE: 2,
//TARGET_SURVIVE_TIME: 10,
};
var sets = Object.keys(game_settings_default);
for(var i=0;i<sets.length;i++)
{
settings[sets[i]] = game_settings_default[sets[i]];
}
//possible admin commands (methods)
var commands = {
TOGGLE: function(params)
{
var split = params.split(" ");
if(split.length == 0)
{
engine.console.print("Usage: TOGGLE command <arguments to toggle between, seperated by a space>");
engine.console.print("If no additional arguments, toggles boolean commands between true and false.")
return false;
}
var cmd = split[0].toUpperCase();
if(split.length > 1)
{
var curr = chsetting(cmd,undefined,true), s = 0;
for(var i=0;i<split.length;i++)
{
if(curr = split[i]) s = i+1;
}
chsetting(cmd,split[s]);
}
else
{
chsetting(cmd,!chsetting(cmd,undefined,true));
}
},
CMD_VAL_ADD: function(params)
{
var split = params.split(" ");
split[0] = split[0].toUpperCase();
var from = chsetting(split[0],"",true);
var to = null;
switch(typeof(from))
{
case "number":
to = from+(split[1]*1);
break;
case "string":
to = from+split[1];
break;
}
chsetting(split[0],to);
},
CMD_PASS_FUNC: function(params)
{
params=params.replace(/rand\((\d+),(\d+)\)/g,function(arg,v1,v2)
{
console.log(arg,v1,v2);
return Math.round((Math.random()*(v2-v1))+v1);
});
loadcfg(params);
},
DELAY_COMMAND: function(params)
{
var interval=0,delay=0,cmd="";
var s = params.split(" ");
if(s[0][0] == "r") //assume repeat
{
interval = 1*(s.slice(0,1)[0].substr(1));
}
if(s[0][0] == "+")
{
delay = engine.gtime+(1*(s.slice(0,1)[0].substr(1)));
}
else
{
delay = 1*s.slice(0,1);
}
cmd = s.join(" ");
engine.delayedcommands[delay] = [cmd,interval];
engine.console.print("Delay command: \""+cmd+"\" at "+delay+"s, interval "+interval+"s.");
},
DELAY_COMMAND_CLEAR: function(params)
{
engine.delayedcommands = {};
engine.console.print("Cleared all delayed commands.");
},
MERGE_OBJ: function(params)
{
var pos = params.indexOf(" ");
var name = params.substr(0,pos), cfg = JSON.parse(params.substr(pos+1));
var sets = Object.keys(cfg);
for(var i=0;i<sets.length;i++)
{
if(typeof(settings[name][sets[i]]) != "undefined") settings[name][sets[i]] = cfg[sets[i]];
}
},
FLOOR_RED: updategrid, FLOOR_GREEN: updategrid, FLOOR_BLUE: updategrid, GRID_SIZE: updategrid,
CAMERA_FOV: function() {if(engine.camera){engine.camera.fov=settings.CAMERA_FOV;engine.camera.updateProjectionMatrix()}},
CAMERA_NEAR_RENDER: function() {if(engine.camera){engine.camera.near=settings.CAMERA_NEAR_RENDER;engine.camera.updateProjectionMatrix()}},
CAMERA_FAR_RENDER: function() {if(engine.camera){engine.camera.far=settings.CAMERA_FAR_RENDER;engine.camera.updateProjectionMatrix()}},
HUD_MAP: function()
{
document.getElementById("canvas").style.display = settings.HUD_MAP?"block":"none";
},
START_NEW_MATCH: function()
{
engine.round = 0;
engine.console.print("Resetting scores and starting new match after this round.");
centerMessage("New Match");
},
CONSOLE_MESSAGE: function(param) { engine.console.print(param+"\n") },
CENTER_MESSAGE: function(param) { centerMessage(param) },
SET_CYCLE_SPEED: function(params)
{
var s = params.split(" ");
var p = getPlayer(s[0]);
if(p) p.speed = s[1]*1;
},
SET_CYCLE_RUBBER: function(params)
{
var s = params.split(" ");
var p = getPlayer(s[0]);
if(p) p.rubber = s[1]*1;
},
SET_CYCLE_BRAKING: function(params)
{
var s = params.split(" ");
var p = getPlayer(s[0]);
if(p) p.braking = Boolean(1*s[1]);
},
SET_CYCLE_BRAKE: function(params)
{
var s = params.split(" ");
var p = getPlayer(s[0]);
if(p) p.brakes = s[2]*1;
},
RESPAWN: function(params)
{
var s = params.split(" ")
var p = getPlayer(s[0]);
if(p)
{
var cfg = {x:0,y:0,z:0,dir:0};
if(s.length > 2)
{
cfg.x = s[1]*engine.REAL_ARENA_SIZE_FACTOR; cfg.y = s[2]*engine.REAL_ARENA_SIZE_FACTOR;
if(s.length > 4)
{
cfg.dir = Math.atan2(s[4],s[3]);
if(settings.STRICT_AXES_SPAWN)
{
var deg = (pi(2)/settings.ARENA_AXES);
cfg.dir = Math.round(cfg.dir/deg)*deg;
}
}
}
p.spawn(cfg);
}
},
KILL: function(params)
{
var p = getPlayer(params);
if(p)
{
p.kill();
if(settings.ADMIN_KILL_MESSAGE)
engine.console.print(p.getColoredName()+"0xRESETT has been smitten by an administrator.\n");
}
},
KILL_ALL: function()
{
for(var x=engine.players.length-1;x>=0;--x) if(typeof(engine.players[x]) != "undefined")
{
engine.players[x].kill();
}
},
RESPAWN_ALL: function()
{
for(var x=engine.players.length-1;x>=0;--x) if(typeof(engine.players[x]) != "undefined")
{
var cycle = engine.players[x];
cycle.spawn({x:cycle.position.x||0,y:cycle.position.y||0,z:cycle.position.z||0,dir:cycle.rotation.z||0});
}
},
INCLUDE: function(params,silent=false,callback=undefined)
{
var file = params.replace(/\(.+\)/g,"");
var s = localStorage.getItem(file);
if(s == null && !engine.dedicated)
{
var incfile = settings.RESOURCE_REPOSITORY_CACHE+"../config/"+params;
engine.console.print("Loading CFG from "+incfile+"...\n");
httpGetAsync(incfile,function(txt){loadcfg(txt,silent);if(callback != undefined)callback();});
}
else
{
loadcfg(s,silent); if(callback != undefined)callback();
}
},
SINCLUDE: function(params) { commands.INCLUDE(params,true) },
RINCLUDE: function(params,callback=undefined)
{
var file = params.replace(/\(.+\)/g,"");
var incfile = settings.RESOURCE_REPOSITORY_SERVER+params;
engine.console.print("Downloading CFG from "+incfile+"...\n");
httpGetAsync(incfile,function(txt){loadcfg(txt);if(callback != undefined)callback();});
},
SPAWN_ZONE: function(params)
{
if(params == "")
{
engine.console.print("Usage:\nSPAWN_ZONE <win|death|ball|target|blast|object|koh> <x> <y> <size> <growth> <xdir> <ydir> <interactive> <r> <g> <b>\nSPAWN_ZONE <acceleration|speed> <speed> <x> <y> <size> <growth> <xdir> <ydir> <interactive> <r> <g> <b>\nSPAWN_ZONE <rubber|rubberadjust> <x> <y> <size> <growth> <xdir> <ydir> <rubber> <interactive> <r> <g> <b>\nSPAWN_ZONE <fortress|flag> <x> <y> <size> <growth> <xdir> <ydir> <interactive> <r> <g> <b>\n\nInstead of <x> <y> one can write: L <x1> <y1> <x2> <y2> [...] Z\nInstead of <size> one can write: P <scale> <x1> <y1> <x2> <y2> [...] Z");
}
else
{
var zone = {}, args = params.split(" ");
if(args[0] == "n")
{
zone.name = args.slice(0,2)[1];
}
zone.type = args[0];
if(zone.type == "acceleration" || zone.type == "speed")
{
zone.value = args.slice(1,2)[0];
}
if(args[1] === "L")
{
for(var i=2;args[i]=="Z"||i>args.length;i+=2)
{
if(i == 2)
{
zone.x = args[i] *engine.REAL_ARENA_SIZE_FACTOR;
zone.y = args[i+1]*engine.REAL_ARENA_SIZE_FACTOR;
}
}
args.slice(2,i);
}
else
{
zone.x = args[1]*engine.REAL_ARENA_SIZE_FACTOR;
zone.y = args[2]*engine.REAL_ARENA_SIZE_FACTOR;
}
if(args[3] === "P")
{
engine.console.print("WARNING: ShapePolygon may not currently work. Use at your own risk.\n",false);
for(var i=3;args[i]=="Z"||i>args.length;i+=2)
{
}
args.slice(3,i);
}
else
{
zone.radius = args[3]*engine.REAL_ARENA_SIZE_FACTOR;
}
zone.expansion = args[4]*1;
zone.xdir = args[5]*1; zone.ydir = args[6]*1;
zone.bounce = Boolean(parseInt+(args[7]))&&args[7]!="false";
if(args[7] != undefined)
{
zone.color = new THREE.Color(args[7]/15,args[8]/15,args[9]/15);
}
new Zone(zone).spawn();
console.log("new Zone: "+zone);
}
},
SPAWN_WALL: function(params)
{
if(params == "")
{
engine.console.print("Usage:\nSPAWN_WALL <height> <x1> <y1> <x2> <y2> [...]\n");
}
else
{
var params = params.split(" "), height = params.slice(0,1)[0]*1, points = [];
for(var q=0;q<params.length;q+=2)
{
points.push(
[
params[q]*engine.REAL_ARENA_SIZE_FACTOR,
params[q+1]*engine.REAL_ARENA_SIZE_FACTOR,
0, height
]
);
}
engine.walls.add(buildWall(points,height));
engine.map.walls.push(points);
}
},
SET_ZONE_POSITION: function(params)
{
var args = params.split(" ");
for(var x=engine.zones.children.length-1;x>=0;x--)
{
if(x == args[0])
{
engine.zones.children[x].position.x = args[1]*engine.REAL_ARENA_SIZE_FACTOR;
engine.zones.children[x].position.y = args[2]*engine.REAL_ARENA_SIZE_FACTOR;
return true;
}
}
engine.console.print("Invalid zone ID\n");
},
SET_AI_PATH: function(params)
{
var args = params.split(" ");
if(args[0] == "*")
{
}
else
{
var cycle = getPlayer(args.shift());
if(cycle)
{
for(var x=0,len=args.length;x<0;x+=2)
{
cycle.push([args[x],args[x+1]]);
}
}
else
{
engine.console.print("Usage: <AI Player name> <x1> <y1> <x2> <y2> ...");
}
}
},
CLEAR_AI_POSITION: function(params)
{
},
LIST_ZONES: function(params="")
{
var found = 0;
for(var x=0,len=engine.zones.children.length;x<len;x++)
{
var outputstr = "ID "+x+": ";
if(params == "" || outputstr.indexOf(params))
{
var zone = engine.zones[x];
engine.console.print(outputstr+zone.cfg.type+" zone @ "+zone.position.x/engine.REAL_ARENA_SIZE_FACTOR+","+zone.position.y/engine.REAL_ARENA_SIZE_FACTOR+".\n");
found++;
}
}
engine.console.print("Listed "+found+"/"+len+" zones.\n");
},
};
function updategrid() { if(!window.engine || !engine.scene) return; engine.scene.remove(engine.grid); buildGrid(); engine.scene.add(engine.grid); }
function armaColor(cycl,tail)
{
if(tail > 0.25) return 31-(tail*15);
else return cycl*15;
}
function plnumcolors(o)
{
var r,g,b;
if(typeof(o) == "object")
{
r=o.r; g=o.g; b=o.b;
}
var retr = typeof(r) != "undefined",retb=typeof(g) != "undefined",retg=typeof(b) != "undefined";
var cycl=new THREE.Color(settings.players[0].cycleColor),
tail=new THREE.Color(settings.players[0].tailColor);
if(retr||retb||retg)
{
if(!retr) r=armaColor(cycl.r,tail.r);
if(!retg) g=armaColor(cycl.g,tail.g);
if(!retb) b=armaColor(cycl.r,tail.r);
var c_red=r&15,c_grn=g&15,c_blue=b&15;
var t_red=Math.max(15,r),t_grn=Math.max(15,g),t_blue=Math.max(15,b);
settings.players[0].cycleColor = "#"+(new THREE.Color(c_red,c_grn,c_blue)).getHexString();
settings.players[0].tailColor = "#"+(new THREE.Color(t_red,t_grn,t_blue)).getHexString();
}
return {r:armaColor(cycl.r,tail.r),g:armaColor(cycl.g,tail.g),b:armaColor(cycl.b,tail.b)};
}
function preset(name)
{
var leave = function() { for(var x=2;x--;) menu('exitmenu');
if(settings.TEXT_OUT_MODE == 1)
{
var lines = engine.console.scrollback,lnnum = engine.console.scrollby;
}
else
{
var lines = engine.console.innerText.split("\n"),lnnum = (-(parseFloat(engine.console.style.top)/engine.console.scrollby));
}
engine.console.scroll(lines.length-lnnum-6);
};
if(name != "default")
{
var tmp_settings = JSON.parse(JSON.stringify(game_settings_default));
tmp_settings.CYCLE_SPEED = 20;
tmp_settings.CYCLE_SPEED_DECAY_ABOVE = 0.1;
tmp_settings.CYCLE_SPEED_DECAY_BELOW = 5;
tmp_settings.CYCLE_BRAKE = 30;
tmp_settings.CYCLE_RUBBER = 1;
tmp_settings.WALLS_LENGTH = -1;
tmp_settings.CYCLE_JUMP = 0;
}
switch(name)
{
case "default":
applysettings(game_settings_default);
break;
case "zonetest":
chsetting("MAP_FILE","nelg/test/zonetest-0.1.aamap.xml");
chsetting("SIZE_FACTOR",6);
break;
case "classic":
applysettings(tmp_settings);
break;
case "fort":
applysettings(tmp_settings);
commands.RINCLUDE("vov/configs/fortress.cfg",leave);
break;
case "styball":
applysettings(tmp_settings);
commands.INCLUDE("styball.cfg",false,leave);
break;
case "df":
applysettings(tmp_settings);
var rsrc = settings.RESOURCE_REPOSITORY_SERVER;
commands.RINCLUDE("CFGs/df.cfg",function(){leave();chsetting("RESOURCE_REPOSITORY_SERVER",rsrc)});
break;
case "hr":
applysettings(tmp_settings);
commands.INCLUDE("tilthr_old.cfg",false,leave);
break;
case "ft":
applysettings(tmp_settings);
commands.RINCLUDE("vov/configs/fasttrack.cfg",function(){leave();loadcfg("TEAMS_MIN 4\nALLOW_TEAM_NAME_COLOR 1")});
break;
case "racing":
applysettings(tmp_settings);
settings.CYCLE_JUMP = 0;
settings.ARENA_AXES = 16;
commands.INCLUDE("AoT/AdvancedRacing.cfg",false,leave);
break;
case "snake":
applysettings(tmp_settings);
settings.CYCLE_JUMP = 0;
commands.INCLUDE("nelg/snake.cfg",false,leave);
break;
}
commands.KILL_ALL();
return "";
}
function aamenurender(value)
{
if(typeof(value) != "undefined") settings.MENU_RENDER = ""+value;
var specificState = engine.inputState.split(':');
if(specificState[0] == "menu") document.getElementById('menu').className = "noselect mainbg_"+settings.MENU_RENDER;
document.getElementById('menu').style.backgroundColor = "rgb("+settings.FLOOR_RED*255+","+settings.FLOOR_GREEN*255+","+settings.FLOOR_BLUE*255+")";
return settings.MENU_RENDER;
}
var cmds = Object.keys(settings).concat(Object.keys(commands)).sort();
settings.controls = { //defaults declared
left: [65,68,70,83],//a s d f
right: [74,75,76,186],//j k l ;
north:[], south:[], east:[], west:[],
jump: [73],
brake: [32],//space bar
togglebrake: [86],//v
boost: [],//up arrow or w
toggleboost: [69],//v
chat: [84],//t
console: [192],//~
camera: [67],//c
look_left: [], look_right: [],
look_forward: [], look_back: [],
pause: [13],//enter
// fullscreen: [122],//f11
esc: [27],
score: [9],
scroll_up: [33],
scroll_down: [34],
scroll_end: [35],
//add glancing late
};
settings.instantchats = [
{
input: [49],
text: "Well done!",
},
{
input: [50],
text: "Thank you!",
},
{
input: [51],
text: "Good match!",
},
{
input: [115,52],
text: "LOL!",
},
]
function init_key(x=false) // ?
{
switch(x)
{
case 0:
break;
case 1:
break;
}
return 1*x;
}
settings.players = [];
settings.player = settings.players[0] = {
name: 'Player 1',
cycleColor: '#dddd00',
tailColor: '#dddd00',
engineType: 5,
spectating: false,
};
function applysettings(array1)
{
var sets = Object.keys(array1);
for(i=0;i<sets.length;i++)
{
chsetting(sets[i],array1[i]);
}
}
function loadcfg(str,silent=false,dontforcecase=false)
{
if(str == null) return false;
var lines = str.split("\n");
for(var i=0;i<lines.length;i++)
{
split = lines[i].replace(/\t/," ").trimLeft().split(" ");
var cmd = "";
if(!dontforcecase || (cmd != "FLOOR_RED" && cmd != "FLOOR_GREEN" && cmd != "FLOOR_BLUE" && cmd != "MENU_RENDER")) //HACK for user.cfg
{
cmd = split.shift();
}
chsetting(dontforcecase?cmd:cmd.toUpperCase(),split.join(" ").trimLeft(),silent);
}
}
function importSets()
{
fileOpen(loadcfg);
}
var _aacompatvars = ["PLAYER_1","COLOR_R_1","COLOR_G_1","COLOR_B_1"];
var uservars = [
// "GRID_SIZE","FLOOR_RED","FLOOR_GREEN","FLOOR_BLUE",
"EXPLOSIONS","HIGH_RIM",
/*"MENU_RENDER",*/"REDRAW_MODE","MAX_TARGET_FPS",//"GAME_LOOP",
"ZONE_HEIGHT","ZONE_SEGMENTS","ZONE_SEG_LENGTH","ZONE_ALPHA","ZONE_SPIN_SPEED","ZONE_RENDER_TYPE",
"player","controls"
];
function exportUsrSets()
{
var txt = "# Warning: Do NOT replace user.cfg with this file. This file doesn't directly replace their user.cfg and I claim no reponsibility for lost settings and/or broken clients.\n\n# Armagetron Compatibility\n";
for(var i=0;i<_aacompatvars.length;i++)
{
txt += _aacompatvars[i]+" "+chsetting(_aacompatvars[i],undefined,true)+"\n";
}
for(var i=0;i<settings.instantchats.length;i++)
{
txt += "INSTANT_CHAT_STRING_1_"+(i+1)+" "+settings.instantchats[i].text+"\n";
}
txt += "\n# Native 3DCycles user.cfg settings. Most, but not all, also work with Armagetron.\n";
for(var i=0;i<uservars.length;i++)
{
if(typeof(settings[uservars[i]]) == "object")
{
txt += "MERGE_OBJ "+uservars[i]+" "+JSON.stringify(settings[uservars[i]]);
}
else
{
txt += uservars[i]+" ";
if(typeof(settings[uservars[i]]) == "boolean")
txt += settings[uservars[i]]?1:0;
else
txt += settings[uservars[i]];
}
txt += "\n";
}
fileSave("user_3dcexport.cfg",txt);
}
/*function netcfg(setting,value)
{
setting = setting.toUpperCase();
for(var i=uservars.length;i--;)
{
if(uservars[i] == setting) return false;
}
return chsetting(setting,value,false," on net order");
}*/
var netChanged = [];
function netcfg(setting,value)
{
setting = setting.toUpperCase();
for(var i=sets.length-1;i>=0;--i)
{
if(sets[i] == setting)
{
var settingFound = false;
for(var i=netChanged.length-1;i>=0;--i)
{
if(netChanged[i][0] == setting) settingFound = true;
}
if(!settingFound) netChanged.push([setting,chsetting("CYCLE_SPEED",undefined,true)]);
return "0xff7f7f"+chsetting(setting,value,false," on server order","0x808080");
}
}
return false;
}
function saveusercfg()
{
var usercfg = "";
for(var i=0;i<uservars.length;i++)
{
if(typeof(settings[uservars[i]]) == "object")
{
usercfg += "MERGE_OBJ "+uservars[i]+" "+JSON.stringify(settings[uservars[i]]);
}
else
{
usercfg += uservars[i]+" ";
if(typeof(settings[uservars[i]]) == "boolean")
usercfg += settings[uservars[i]]?1:0;
else
usercfg += settings[uservars[i]];
}
usercfg += "\n";
}
localStorage.setItem("user.cfg",usercfg);
}
function loadsettingcfgs()
{
loadcfg(localStorage.getItem("user.cfg"),true,true);
loadcfg(localStorage.getItem("server_info.cfg"),true);
loadcfg(localStorage.getItem("settings_custom.cfg"),true);
loadcfg(localStorage.getItem("autoexec.cfg"),true);
}
loadsettingcfgs();
window.onbeforeunload = saveusercfg;
function chsetting(setting,value,silent=false,txt="",pretxt="")
{
if(setting[0] == "#" || setting == "") return;
var exec = false, ret = undefined;
var event = getVarFromString(setting);
if(typeof(event[0][event[1]]) != "undefined")
{
var from = event[0][event[1]];
var isfunction = (typeof(from) == "function");
if(isfunction) from = event[0][event[1]]();
if(typeof(value) != "undefined" && value != "")
{
switch(typeof(from))
{
case "number":
var to = parseFloat(value);
if(isNaN(to))
to = 0;
break;
case "string":
var to = ""+value;
break;
case "boolean":
var int = parseInt(value);
if(isNaN(int))
var to = value[0]!="f"&&value[0]!="n";
else
var to = Boolean(int);
break;
case "object":
silent = true;
from = JSON.stringify(settings[uservars[i]]);
var to = JSON.parse(value);
break;
default:
engine.console.print("Unknown/unimplemented setting type "+typeof(event[0][event[1]])+".\n");
//return false;
}
if(isfunction) event[0][event[1]](to);
else event[0][event[1]] = to;
if(from != to)
{
if(!silent) engine.console.print(pretxt+event[1]+" changed from "+from+" to "+to+txt+".\n");
if(window.svr && typeof(game_settings_default[event[1]]) !== "undefined")
{
if(to == Infinity) to = Number.MAX_VALUE;
var data = JSON.stringify({type:"setting",setting:event[1],data:to});
window.svr.clients.forEach(function(ws){ws.send(data);});
}
}
ret = to;
}
else
{
if(!silent) engine.console.print(event[1]+" is currently set to "+from+"\n");
ret = from;
}
var exec = true;
}
if(event[2] && typeof(event[2][event[1]]) == "function")
{
event[2][event[1]](value);
var exec = true;
}
if(exec) return ret==undefined?exec:ret;
if(!silent)
{
engine.console.print("Unknown command "+event[1]+"\n");
if(inround())
{
var len = 0, print="";
for(i=0;i<cmds.length;i++)
{
if(cmds[i].search(setting) > -1)
{
if(len != 0) print += ", ";
len++; print += cmds[i];
}
}
if(len > 0) engine.console.print("Perhaps you meant: "+print+"\n");
}
}
return exec;
}
function mkSettingCallback(setting,stringify=false)
{
if(stringify)
return function(set){return ""+chsetting(setting,set,true)}
else
return function(set){return chsetting(setting,set,true)}
}
function getargs()
{
var s = window.location.hash.replace("#","").split("&");
_GET = {};
for(var i=0,len=s.length;i<len;i++)
{
var e = s[i].split("=");
_GET[e[0]] = e[1];
}
}
if(typeof(_GET) == "undefined")
{
getargs();
}
//variables used by init and the engine - do not touch
engine = {
dedicated: false,
paused: false,//
inputState: '', inputStatePrev: '',
lastRenderTime: 0,//used in rendering loop
lastGameTime: 0,
fpsTime: 0, //render loop
timeStart: 0,
timeEnd: 0,//timer vars
totalPauseTime: 0,
startOfPause: 0,//used to prevent delta from offsetting due to pause
framesCount: 0,
avgTimeStep: 0,
gtime:-Infinity,
lastSyncTime:-Infinity,
lastScoreTime:-Infinity,
cMFadeOutAfter: Infinity,
//net
network: false,
activePlayer: 0,
//game stats
fastestPlayer: 0, fastestSpeed: 0,
deaths: 0,
//render loop toggles
//hasplayed: false,//used for playing again, reinitializing the render for another go (after having gone back to menus from it first)
currrim3clr: 0,
//info
usingWebgl: true,//variable to toggle webgl features
usingPostProcessing: false,//toggle for post processing features
concatch: undefined, msgcatch: undefined,
//fonts
font: 'Armagetronad',//active font face
fonts: ['Armagetronad','Flynn','monospace','nicefont','sans-serif','serif'],
textures: {},
//map data
currrot: 0, //rotation
loadedMap: "Anonymous/polygon/regular/square-1.0.1.aamap.xml",
//default:
mapString: '\<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\>\n\<!DOCTYPE Resource SYSTEM \"AATeam/map-0.2.8.0_rc4.dtd\"\>\n\<Resource type=\"aamap\" name=\"square\" version=\"1.0.1\" author=\"Anonymous\" category=\"polygon/regular\"\>\n\t\<Map version=\"2\"\>\n\t\t\<!-- The original square map, technically created by z-man.\n\t Converted to XML by philippeqc.\n\t License: Public Domain. Do with it what you want.\n --\>\n\n\t\t\<World\>\n\t\t\t\<Field\>\n\t\t\t\t\<Spawn\tx=\"255\"\ty=\"50\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"245\"\ty=\"450\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"50\"\ty=\"245\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"450\"\ty=\"255\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"305\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"195\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"195\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"305\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"205\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"295\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"295\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"205\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Wall\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\</Wall\>\n\t\t\t\</Field\>\n\t\t\</World\>\n\t\</Map\>\n\</Resource\>',
//mapString: '\<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\>\n\<!DOCTYPE Resource SYSTEM \"AATeam/map-0.2.8.0_rc4.dtd\"\>\n\<Resource type=\"aamap\" name=\"square\" version=\"1.0.1\" author=\"Anonymous\" category=\"polygon/regular\"\>\n\t\<Map version=\"2\"\>\n\t\t\<!-- The original square map, technically created by z-man.\n\t Converted to XML by philippeqc.\n\t License: Public Domain. Do with it what you want.\n --\>\n\n\t\t\<World\>\n\t\t\t\<Field\>\n\t\t\t\t\<Spawn\tx=\"255\"\ty=\"50\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"245\"\ty=\"450\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"50\"\ty=\"245\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"450\"\ty=\"255\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"305\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"195\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"195\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"305\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"205\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"295\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"295\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"205\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Wall\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\</Wall\>\n\t\t\t\</Field\>\n\t\t\</World\>\n\t\</Map\>\n\</Resource\>',
//two zones:
//mapString: '\<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\>\n\<!DOCTYPE Resource SYSTEM \"AATeam/map-0.2.8.0_rc4.dtd\"\>\n\<Resource type=\"aamap\" name=\"square\" version=\"1.0.1\" author=\"Anonymous\" category=\"polygon/regular\"\>\n\t\<Map version=\"2\"\>\n\t\t\<!-- The original square map, technically created by z-man.\n\t Converted to XML by philippeqc.\n\t License: Public Domain. Do with it what you want.\n --\>\n\n\t\t\<World\>\n\t\t\t\<Field\>\n\t\t\t\t\<Spawn\tx=\"255\"\ty=\"50\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"245\"\ty=\"450\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"50\"\ty=\"245\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"450\"\ty=\"255\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"305\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"195\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"195\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"305\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"205\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"295\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"295\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"205\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Wall\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\</Wall\>\n\t\t\t\<Zone effect=\"death\"\>\<ShapeCircle radius=\"20\"\>\<Point y=\"275\" x=\"275\"/\>\n\t\t\t\</ShapeCircle\>\n\t\t\t\</Zone\>\n\t\t\t\<Zone effect=\"win\"\>\n\t\t\t\t\<ShapeCircle radius=\"10\"\>\n\t\t\t\t\t\<Point y=\"240\" x=\"250\"/\>\n\t\t\t\t\</ShapeCircle\>\n\t\t\t\</Zone\>\t\t\t\</Field\>\n\t\t\</World\>\n\t\</Map\>\n\</Resource\>',
//one zone:
//mapString: '\<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\>\n\<!DOCTYPE Resource SYSTEM \"AATeam/map-0.2.8.0_rc4.dtd\"\>\n\<Resource type=\"aamap\" name=\"square\" version=\"1.0.1\" author=\"Anonymous\" category=\"polygon/regular\"\>\n\t\<Map version=\"2\"\>\n\t\t\<!-- The original square map, technically created by z-man.\n\t Converted to XML by philippeqc.\n\t License: Public Domain. Do with it what you want.\n --\>\n\n\t\t\<World\>\n\t\t\t\<Field\>\n\t\t\t\t\<Spawn\tx=\"255\"\ty=\"50\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"245\"\ty=\"450\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"50\"\ty=\"245\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"450\"\ty=\"255\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"305\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"195\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"195\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"305\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"205\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"295\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"295\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"205\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Wall\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\</Wall\>\n\t\t\t\<Zone effect=\"win\"\>\n\t\t\t\t\<ShapeCircle radius=\"10\"\>\n\t\t\t\t\t\<Point y=\"240\" x=\"250\"/\>\n\t\t\t\t\</ShapeCircle\>\n\t\t\t\</Zone\>\t\t\t\</Field\>\n\t\t\</World\>\n\t\</Map\>\n\</Resource\>',
//two zones + two walls:
//mapString: '\<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?\>\n\<!DOCTYPE Resource SYSTEM \"AATeam/map-0.2.8.0_rc4.dtd\"\>\n\<Resource type=\"aamap\" name=\"square\" version=\"1.0.1\" author=\"Anonymous\" category=\"polygon/regular\"\>\n\t\<Map version=\"2\"\>\n\t\t\<!-- The original square map, technically created by z-man.\n\t Converted to XML by philippeqc.\n\t License: Public Domain. Do with it what you want.\n --\>\n\n\t\t\<World\>\n\t\t\t\<Field\>\n\t\t\t\t\<Spawn\tx=\"255\"\ty=\"50\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"245\"\ty=\"450\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"50\"\ty=\"245\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"450\"\ty=\"255\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"305\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"195\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"195\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"305\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Spawn\tx=\"205\"\ty=\"100\"\txdir=\"0\"\tydir=\"1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"295\"\ty=\"400\"\txdir=\"0\"\tydir=\"-1\"\t/\>\n\t\t\t\t\<Spawn\tx=\"100\"\ty=\"295\"\txdir=\"1\"\tydir=\"0\"\t/\>\n\t\t\t\t\<Spawn\tx=\"400\"\ty=\"205\"\txdir=\"-1\"\tydir=\"0\"\t/\>\n\n\t\t\t\t\<Wall\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"500\"\t/\>\n\t\t\t\t\t\<Point\tx=\"500\"\ty=\"0\"\t/\>\n\t\t\t\t\t\<Point\tx=\"0\"\ty=\"0\"\t/\>\n\t\t\t\t\</Wall\>\n<Wall height=\"1\"\>\n\t\t\t\t\t\<Point\tx=\"200\"\ty=\"200\"\t/\>\n\t\t\t\t\t\<Point\tx=\"200\"\ty=\"300\"\t/\>\n\t\t\t\t\t\<Point\tx=\"300\"\ty=\"300\"\t/\>\n\t\t\t\t\t\<Point\tx=\"300\"\ty=\"200\"\t/\>\n\t\t\t\t\t\<Point\tx=\"200\"\ty=\"200\"\t/\>\n\t\t\t\t\</Wall\>\n\t\t\t\<Zone effect=\"death\"\>\<ShapeCircle radius=\"20\"\>\<Point y=\"275\" x=\"275\"/\>\n\t\t\t\</ShapeCircle\>\n\t\t\t\</Zone\>\n\t\t\t\<Zone effect=\"win\"\>\n\t\t\t\t\<ShapeCircle radius=\"10\"\>\n\t\t\t\t\t\<Point y=\"240\" x=\"250\"/\>\n\t\t\t\t\</ShapeCircle\>\n\t\t\t\</Zone\>\t\t\t\</Field\>\n\t\t\</World\>\n\t\</Map\>\n\</Resource\>',
mapXML: false,//xmlify(mapString);
//scene vars
renderer: false,
scene: false,
composer: false,//for post processing
//camera stuff
camera: false,//needed or any camera
cameraOrbit: false,//
view: 'smart',
views: ['smart','chase','stationary','track','topdown','birdseye','cockpit'],
cameraEase: 0.08,
viewTarget: 0,
menus: [],
//sound
useSound: true,
retroSound: true,
//
//scene objects (just used for render)
grid: false,
walls: false,
zones: {children:0},
//a_zone: [],//not needed with children?
//is running
gameRunning: false,
renderRunning: false,
uRound: false, //timeout ID for new round
//FOR PLAYER OBJECTS
//game stuff
playersById: [],//array of player objects (info)
playersByScore: [],
teams: [],//array of team objects
round: 0,
delayedcommands: {},
};
if(window.Proxy)
{
engine.players = new Proxy(engine.playersById,{
apply: function(t,arg,ls)
{
return arg[t].apply(this,ls);
},
deleteProperty: function(t,id)
{
if(!isNaN(id))
{
for(var x=engine.playersByScore.length-1;x>=0;--x)
{
if(t[id] == engine.playersByScore[x])
{
engine.playersByScore.splice(x,1);
}
}
}
return true;
},
set: function(t,id,val)
{
if(!isNaN(id))
{
for(var x=engine.playersByScore.length-1;x>=0;--x)
{
if(t[id] == engine.playersByScore[x])
{
- engine.players[x] = val;
+ engine.playersByScore[x] = val;
updateScoreBoard();
- t[id] = value;
+ t[id] = val;
return true;
}
}
engine.playersByScore.push(val);
}
t[id] = val;
return true;
},
});
}
else
{
//hacky workaround, only for browsers without Proxy support (very few)
engine.players = engine.playersById;
engine.players.prevLength = -1;
setInterval(function()
{
if(engine.players.length != engine.players.prevLength)
{
engine.players.prevLength = engine.players.length;
engine.playersByScore.splice(0);
for(var x=engine.playersById.length-1;x>=0;--x)
{
engine.playersByScore.push(engine.playersById[x]);
}
updateScoreBoard();
}
},1000);
}
settings.engine = engine; //hack to allow menu to change engine config. (Potentially insecure?)
//CONSOLE, HUD
if(typeof(document) != "undefined")
{
engine.console = document.getElementById("console");
engine.console.time = 0;
engine.console.time_manual = 0;
engine.console.print = function(str)
{
//this.append(" "+str);
if(engine.concatch)
{
if(engine.concatch.type == "all") engine.concatch.to.append(str);
else engine.concatch.to.innerText = str;
}
if(settings.TEXT_OUT_MODE == 1)
{
this.scrollback.push(str);
}
this.innerHTML += " "+replaceColors(htmlEntities(str));
//console.log(replaceColors(str));
this.time = performance.now()+this.scrolltime;
if(!inround()||!settings.TEXT_OUT()) console.log("[CON] "+str);
}
engine.console.scrollby = 0;
engine.console.scrolltime = 5000;
engine.console.scrolltime_manual = 30000;
engine.console.time_manual -= engine.console.scrolltime_manual;
engine.console.scroll = function(times=1)
{
if(settings.TEXT_OUT_MODE == 1)
{
this.scrollby+=times; this.innerHTML = "";
for(var i=this.scrollby;i<engine.console.scrollback.length;i++)
{
this.innerHTML += " "+replaceColors(htmlEntities(this.scrollback[i]));
}
}
else
{
//this.scrollby = parseFloat(window.getComputedStyle(this).getPropertyValue('font-size'))+6;
//this.scrollby = this.children[0].offsetHeight;
var orig = parseFloat(this.style.top)/this.scrollby;
this.scrollby = this.offsetHeight/this.innerText.split("\n").length;
if(this.style.top == '') this.style.top = 0;
//this.style.top = (parseFloat(this.style.top)-(this.scrollby*times))+"px";
this.style.top = ((this.scrollby*orig)-(this.scrollby*times))+"px";
}
}
if(settings.TEXT_OUT_MODE == 1)
{
engine.console.scrollback = [];
engine.console.style.top = "-16px";
}
engine.console.scroll();
engine.hud = document.getElementById("HUD");
engine.hud.hide = function(){this.style.opacity=0;};
engine.hud.show = function(){this.style.opacity=1;};
engine.hud.basic = document.getElementById("gui_stats");
engine.hud.game = document.getElementById("game_stats");
engine.hud.fadein = true;
}
else
{
engine.console = {style:{}};
engine.console.print = function(str,netSend=true)
{
process.stdout.write(removeColors(str));
if(netSend && global.svr) //send over network
{
var data = JSON.stringify({type:"con",data:str}); //since all clients get the same info
global.svr.clients.forEach(function(ws) //I know this is slow, but I'm not aware of any other way
{
ws.send(data);
});
}
};
}
/*///team objects:
-name
-array of player IDs (order of shuffle)
-team score
/**/
//which controls are pressed down get added to arrays
var temp_items = Object.keys(settings.controls);
engine.controls = {pressed:[]};
for(var i=0;i<temp_items.length;i++)
{
engine.controls[temp_items[i]] = []; //array of keycodes that are pressed within a frame, removed when lifted
}
engine.map = { //virtual map data (used for positions, lines and stuff to calculate)
zones: [],
spawns: [],
walls: [],
};
diff --git a/scripts/functions-body.js b/scripts/functions-body.js
index 58c9931..04a3220 100644
--- a/scripts/functions-body.js
+++ b/scripts/functions-body.js
@@ -1,447 +1,447 @@
/*
* 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.
*/
function getPlayer(name)
{
name = removeColors(name).filter();
var matches = [];
for(var i=engine.players.length;i--;)
{
if(engine.players[i].getBoringName().filter() == name)
{
return engine.players[i];
}
else if(engine.players[i].getBoringName().filter().indexOf(name) > -1)
{
matches.push(i);
}
}
if(matches.length > 1)
{
engine.console.print("Too many matches for "+name+". Try something more exact to narrow down the search.\n");
}
else if(matches.length < 1)
{
engine.console.print("No matches for "+name+". Try a different name.\n");
}
else
{
return engine.players[matches[0]];
}
}
function retToLastSafe(cycle,w1x,w1y,w2x,w2y)
{
var dist = distanceoflines(cycle.position.x,cycle.position.y,cycle.position.x,cycle.position.y,w1x,w1y,w2x,w2y);
console.warn(cycle.name+" phased through a wall "+dist+"m.\n");
//if(dist == 0) return;
dist -= settings.CYCLE_RUBBER_MINDISTANCE;
cycle.position.x -= cycle.lastdir.front[0]*dist; cycle.position.y -= cycle.lastdir.front[1]*dist;
if(lineIntersect(cycle.position.x,cycle.position.y,cycle.lastpos.x,cycle.lastpos.y,w1x,w1y,w2x,w2y))
{
//cycle.position.x += cycle.lastdir.front[0]*(dist*2); cycle.position.y += cycle.lastdir.front[1]*(dist*2);
//if(lineIntersect(cycle.position.x,cycle.position.y,cycle.lastpos.x,cycle.lastpos.y,w1x,w1y,w2x,w2y))
{
var dist = distanceoflines(cycle.lastpos.x,cycle.lastpos.y,cycle.lastpos.x,cycle.lastpos.y,w1x,w1y,w2x,w2y);
dist -= settings.CYCLE_RUBBER_MINDISTANCE;
cycle.position.x = cycle.lastpos.x+
(cycle.lastdir.front[0]*dist)/*+
(cycle.lastsensor.left*cycle.lastdir.left[0])+
(cycle.lastsensor.right*cycle.lastdir.right[0])*/;
cycle.position.y = cycle.lastpos.y+
(cycle.lastdir.front[1]*dist)/*+
(cycle.lastsensor.left*cycle.lastdir.left[1])+
(cycle.lastsensor.right*cycle.lastdir.right[1])*/;
/*while(lineIntersect(cycle.position.x,cycle.position.y,cycle.lastpos.x,cycle.lastpos.y,w1x,w1y,w2x,w2y))
{
cycle.position.x -= (1/1000)*cycle.lastdir.front[0];
cycle.position.y -= (1/1000)*cycle.lastdir.front[1];
}
cycle.collidetime = 0; cycle.lastspeed = 0;*/
if(lineIntersect(cycle.position.x,cycle.position.y,cycle.lastpos.x,cycle.lastpos.y,w1x,w1y,w2x,w2y))
{
if(engine.network)
{
//request new cycle trails
}
else
{
doDeath(cycle);
engine.console.print(cycle.name+" phased through a wall and has been terminated.\n");
}
}
else
{
cycle.rubber += cycle.speed;
cycle.sensor.front = settings.CYCLE_RUBBER_MINDISTANCE;
}
}
}
else
{
cycle.rubber += cycle.speed;
cycle.sensor.front = settings.CYCLE_RUBBER_MINDISTANCE;
}
if(engine.haswall) recalcCurrWall(cycle);
}
function getCycleSensors(full=false)
{
var oneline = "";
var range = settings.CYCLE_SENSORS_RANGE;
for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x] !== undefined)
{
//if(full)
{
engine.players[x].sensor.left = engine.players[x].sensor.right =
engine.players[x].sensor.leftTurn = engine.players[x].sensor.rightTurn =
engine.players[x].sensor.front =
engine.players[x].sensor.rear = Infinity;
engine.players[x].sensor.nearestobj =
engine.players[x].sensor.lnearestobj = false;
engine.players[x].sensor.rnearestobj = false;
}
engine.players[x].sensor.bottom = 0;
engine.players[x].sensor.frontWallHeight = Infinity;
engine.players[x].sensor.objleft =
engine.players[x].sensor.objright =
engine.players[x].sensor.objfront =
engine.players[x].sensor.objrear = false;
engine.players[x].sensor.nearcycle = false;
engine.players[x].dir.front = cdir(engine.players[x].rotation.z);
engine.players[x].dir.left = cdir(engine.players[x].rotation.z+(Math.PI/2));
engine.players[x].dir.right = cdir(engine.players[x].rotation.z-(Math.PI/2));
engine.players[x].dir.leftTurn = cdir(engine.players[x].rotation.z+(Math.PI/(settings.ARENA_AXES*0.5)));
engine.players[x].dir.rightTurn = cdir(engine.players[x].rotation.z-(Math.PI/(settings.ARENA_AXES*0.5)));
}
for(var x=engine.map.zones.length-1;x>=0;--x)
{
engine.zones.children[x].walldist = Infinity;
}
- var campos = engine.camera.position, ppos = engine.players[engine.viewTarget].position;
+ if(!engine.dedicated) var campos = engine.camera.position, ppos = engine.players[engine.viewTarget].position;
for(var y=engine.map.walls.length-1;y>=0;--y)
{
//console.log("ohi");
var lookThroughWall = false;
for(var i=engine.map.walls[y].length-1;i>=0;--i)
{
var w1x = engine.map.walls[y][i][0], w1y = engine.map.walls[y][i][1];
if(engine.map.walls[y][i+1] !== undefined)
{
var w2x = engine.map.walls[y][i+1][0], w2y = engine.map.walls[y][i+1][1];
for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x] !== undefined && engine.players[x].alive)
{
var cycle = engine.players[x];
var posx = cycle.position.x, posy = cycle.position.y, posz = cycle.position.z;
if(lineIntersect(posx,posy,cycle.lastpos.x,cycle.lastpos.y,w1x,w1y,w2x,w2y))
{
retToLastSafe(cycle,w1x,w1y,w2x,w2y);
}
else
{
var dir = engine.players[x].dir.front,
ldir = engine.players[x].dir.left,
rdir = engine.players[x].dir.right
ltdir = engine.players[x].dir.leftTurn,
rtdir = engine.players[x].dir.rightTurn;
var rg = /*cycle.sensor.front==Infinity?*/(cycle.speed*range);//:cycle.sensor.front;
//var output = pointLineDistance(w1x,w1y,w2x,w2y,posx,posy);
//var testx = (w2x-w1x)*dir[0], testy = (w2y-w1y)*dir[1], tpx = posx*(-dir[0]), tpy = posy*(-dir[1]);
//if(cycle == engine.players[engine.viewTarget]) oneline += ""+(w2x-w1x)+"\t\t\t\t\t\t\t"+posx+"\t\t\t\t\t\t\t"+(w2x-w1x)+"\t\t\t\t\t\t\t"+posy+";\n";
//if(((w2x+w1x)/2) >= posy*dir[0] && ((w2y+w1y)/2) >= posx*dir[1])
//if(isinfront(w1x,w1y,w2x,w2y,posx,posy,dir))
coord = [w1x,w1y,w2x,w2y];
if(lineIntersect(posx,posy,posx+(dir[0]*rg),posy+(dir[1]*rg),w1x,w1y,w2x,w2y))
{
//var ff = distanceoflines(posx,posy,posx+(dir[0]/6),posy+(dir[1]/6),w1x,w1y,w2x,w2y);
var ff = distanceoflines(posx,posy,posx,posy,w1x,w1y,w2x,w2y);
/*forward = Math.min(forward,ff);
if(ff == forward) type = "rim";//*/
if(ff < cycle.sensor.front) { cycle.sensor.front=ff; cycle.sensor.nearestobj = "rim";}
}
else if(lineIntersect(posx,posy,posx+(ldir[0]*rg),posy+(ldir[1]*rg),w1x,w1y,w2x,w2y))
{
var ll = distanceoflines(posx,posy,posx,posy,w1x,w1y,w2x,w2y);
if(ll < cycle.sensor.left) { cycle.sensor.left=ll; cycle.sensor.lnearestobj = "rim";}
}
else if(lineIntersect(posx,posy,posx+(rdir[0]*rg),posy+(rdir[1]*rg),w1x,w1y,w2x,w2y))
{
var rr = distanceoflines(posx,posy,posx,posy,w1x,w1y,w2x,w2y);
if(rr < cycle.sensor.right) { cycle.sensor.right=rr; cycle.sensor.rnearestobj = "rim";}
}
if(lineIntersect(posx,posy,posx+(ltdir[0]*rg),posy+(ltdir[1]*rg),w1x,w1y,w2x,w2y))
{
var ll = distanceoflines(posx,posy,posx,posy,w1x,w1y,w2x,w2y);
if(ll < cycle.sensor.leftTurn) { cycle.sensor.leftTurn=ll; }
}
else if(lineIntersect(posx,posy,posx+(rtdir[0]*rg),posy+(rtdir[1]*rg),w1x,w1y,w2x,w2y))
{
var rr = distanceoflines(posx,posy,posx,posy,w1x,w1y,w2x,w2y);
if(rr < cycle.sensor.rightTurn) { cycle.sensor.rightTurn=rr;}
}
/*
if(((w2x+w1x)/2) >= posy*ldir[0] && ((w2y+w1y)/2) >= posx*ldir[1])
{
var ll = distanceoflines(posx,posy,posx+(ldir[0]),posy+(ldir[1]),w1x,w1y,w2x,w2y);
left = Math.min(left,ll);
}
if(((w2x+w1x)/2) >= posy*rdir[0] && ((w2y+w1y)/2) >= posx*rdir[1])
{
var rr = distanceoflines(posx,posy,posx+(rdir[0]),posy+(rdir[1]),w1x,w1y,w2x,w2y);
right = Math.min(right,rr);
}
*/
}
}
for(var x=engine.map.zones.length-1;x>=0;--x)
{
var zone = engine.map.zones[x];
var posx = zone[1], posy = zone[2],w2z = p[2]*1;
var walldist = distanceoflines(posx,posy,posx,posy,w1x,w1y,w2x,w2y)-zone[3];
if(walldist < engine.zones.children[x].walldist)
{
engine.zones.children[x].walldist = walldist;
}
}
- if(!lookThroughWall) lookThroughWall = (engine.walls.children[y]&&engine.walls.children[y].geometry.vertices[engine.walls.children[y].geometry.vertices.length-1].z) > campos.z && lineIntersect(campos.x,campos.y,ppos.x,ppos.y,w1x,w1y,w2x,w2y);
+ if(!engine.dedicated && !lookThroughWall) lookThroughWall = (engine.walls.children[y]&&engine.walls.children[y].geometry.vertices[engine.walls.children[y].geometry.vertices.length-1].z) > campos.z && lineIntersect(campos.x,campos.y,ppos.x,ppos.y,w1x,w1y,w2x,w2y);
}
}
- if(engine.walls.children[y]) engine.walls.children[y].visible = !lookThroughWall;
+ if(!engine.dedicated && engine.walls.children[y]) engine.walls.children[y].visible = !lookThroughWall;
}
for(var a=engine.players.length-1;a>=0;--a) if(engine.players[a] !== undefined)
{
var walls = engine.players[a].walls.map;
var len = walls.length;
for(var i=len-1;i>=0;--i)
{
var p1 = walls[i];
//var w1x = p1[0],w1y = p1[1],w1z = p1[2];
if(walls[i+1] !== undefined)
{
var p2 = walls[i+1];
//var w2x = p2[0],w2y = p2[1],w2z = p2[2];
for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x] !== undefined && engine.players[x].alive)
{
//var cycle = engine.players[x];
//var isplayer = (engine.players[a] == engine.players[x]);
if(engine.players[a] != engine.players[x] || i <= len-(settings.ARENA_AXES))
{
//var posx = engine.players[x].position.x, posy = engine.players[x].position.y, posz = engine.players[x].position.z;
if(p1[2]||0 <= engine.players[x].position.z && (p1[2]||0)+1 >= engine.players[x].position.z)
{
if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].lastpos.x,engine.players[x].lastpos.y,p1[0],p1[1],p2[0],p2[1]))
{
retToLastSafe(engine.players[x],p1[0],p1[1],p2[0],p2[1]);
}
else
{
var dir = engine.players[x].dir.front,
ldir = engine.players[x].dir.left,
rdir = engine.players[x].dir.right,
ltdir = engine.players[x].dir.leftTurn,
rtdir = engine.players[x].dir.rightTurn;
//var rg = engine.players[x].sensor.front==Infinity?(engine.players[x].speed*range):engine.players[x].sensor.front;
//if(engine.players[x].sensor.front==Infinity)
var rg=engine.players[x].speed*range;//else var rg=engine.players[x].sensor.front;
//if(!(engine.players[x].position.x == p2[0] && engine.players[x].position.y == p2[1]))
{
if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x+(dir[0]*rg),engine.players[x].position.y+(dir[1]*rg),p1[0],p1[1],p2[0],p2[1]))
{
var ff=distanceoflines(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x,engine.players[x].position.y,p1[0],p1[1],p2[0],p2[1]);
/*forward = Math.min(forward,ff);
if(ff == forward) type = engine.players[x];//*/
if(ff < engine.players[x].sensor.front)
{
engine.players[x].sensor.front=ff;
engine.players[x].sensor.nearestobj = engine.players[a];
if(engine.players[a] != engine.players[x])
{
engine.players[x].sensor.lastnonselfobj = engine.players[a];
}
}
}
else if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x+(ldir[0]*rg),engine.players[x].position.y+(ldir[1]*rg),p1[0],p1[1],p2[0],p2[1]))
{
var ll = distanceoflines(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x,engine.players[x].position.y,p1[0],p1[1],p2[0],p2[1]);
if(ll < engine.players[x].sensor.left)
{
engine.players[x].sensor.left=ll;
engine.players[x].sensor.lnearestobj = engine.players[a];
engine.players[x].sensor.objleft = engine.players[a];
}
}
else if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x+(rdir[0]*rg),engine.players[x].position.y+(rdir[1]*rg),p1[0],p1[1],p2[0],p2[1]))
{
var rr = distanceoflines(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x,engine.players[x].position.y,p1[0],p1[1],p2[0],p2[1]);
if(rr < engine.players[x].sensor.right)
{
engine.players[x].sensor.right=rr;
engine.players[x].sensor.rnearestobj =
engine.players[x].sensor.objright = engine.players[a];
}
}
else if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x+(-dir[0]*rg),engine.players[x].position.y+(-dir[1]*rg),p1[0],p1[1],p2[0],p2[1]))
{
var bb=distanceoflines(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x,engine.players[x].position.y,p1[0],p1[1],p2[0],p2[1]);
if(bb < engine.players[x].sensor.rear)
{
engine.players[x].sensor.rear=bb;
engine.players[x].sensor.objrear = engine.players[a];
}
}
if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x+(ltdir[0]*rg),engine.players[x].position.y+(ltdir[1]*rg),p1[0],p1[1],p2[0],p2[1]))
{
var ll = distanceoflines(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x,engine.players[x].position.y,p1[0],p1[1],p2[0],p2[1]);
if(ll < engine.players[x].sensor.leftTurn) { engine.players[x].sensor.leftTurn=ll;}
}
else if(lineIntersect(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x+(rtdir[0]*rg),engine.players[x].position.y+(rtdir[1]*rg),p1[0],p1[1],p2[0],p2[1]))
{
var rr = distanceoflines(engine.players[x].position.x,engine.players[x].position.y,engine.players[x].position.x,engine.players[x].position.y,p1[0],p1[1],p2[0],p2[1]);
if(rr < engine.players[x].sensor.rightTurn) { engine.players[x].sensor.rightTurn=rr;}
}
}
}
}
}
}
}
}
}//*/
/*for(var x=engine.map.zones.length-1;x>=0;--x)
{
var zone = engine.map.zones[x];
for(var y=engine.players.length-1;y>=0;--y) if(engine.players[y] !== undefined)
{
var ff = Math.sqrt(((zone[1]-p2x)**2)+((zone[2]-p2y)**2))-zone[3];
if(ff < cycle.sensor.front) { cycle.sensor.front=ff; cycle.sensor.nearestobj = "zone"; }
}
}*/
//console.log(forward);
if(oneline != "") console.log(oneline);
for(var x=engine.players.length-1;x>=0;--x) if((cycle=engine.players[x]) !== undefined && cycle.lastpos)
{
cycle.lastpos.x = cycle.position.x;
cycle.lastpos.y = cycle.position.y;
cycle.lastpos.z = cycle.position.z;
engine.players[x].lastdir = {
front:engine.players[x].dir.front,
left:engine.players[x].dir.left,
right:engine.players[x].dir.right
};
engine.players[x].lastsensor = {
front:engine.players[x].sensor.front,
left:engine.players[x].sensor.left,
right:engine.players[x].sensor.right
};
cycle.intersectTest = [];
}
}
function maxSpeed()
{
if(settings.CYCLE_SPEED_DECAY_ABOVE > 0 )
var max_cs = settings.CYCLE_SPEED / settings.CYCLE_SPEED_DECAY_ABOVE;
else
var max_cs = settings.CYCLE_SPEED * 100;
var max_fastest = engine.fastestSpeed; //
return Math.max(max_cs,max_fastest);
}
function handleChat(cycle,output)
{
var split = output.split(" ");
/*if(split[0][0] == "/")
{
switch(split[0])
{
case "/console": case "/admin":
if(!engine.dedicated || split[0] != "/console")
{
split.shift();
loadcfg(split.join(" "));
break;
}
default:
if(engine.network)
{
}
else
{
engine.console.print('Unknown chat command "'+split[0]+'".\n');
}
break;
}
}*/
if(split[0] == "/console" && !engine.dedicated)
{
split.shift();
loadcfg(split.join(" "));
}
else if(split[0] == "/admin" && !engine.network)
{
split.shift();
var ln = split.join(" ");
loadcfg(ln);
engine.console.print('Remote admin command0x7f7fff: '+ln+'\n');
}
else
{
cycle.doChat(output);
}
}
if(typeof(document) == "undefined")
{
function centerMessage(msg,time=5000)
{
console.log(msg);
if(window.svr)
{
if(time == Infinity) time = Number.MAX_VALUE;
var data = JSON.stringify({type:"cen",data:{msg:msg,time:time}});
window.svr.clients.forEach(function(ws){ws.send(data);});
}
}
}
else
{
function centerMessage(msg,time=5000)
{
var cm = document.getElementById("centerMessage");
cm.innerHTML = replaceColors(htmlEntities(msg));
cm.style.opacity = 1;
cm.style.display = "block";
engine.cMFadeOutAfter = performance.now()+time;
}
}
function toLadderLog(event,params)
{
if(settings["LADDERLOG_WRITE_"+event])
{
}
}
diff --git a/scripts/game.js b/scripts/game.js
index 98fb1e2..ea32096 100644
--- a/scripts/game.js
+++ b/scripts/game.js
@@ -1,963 +1,1081 @@
/*
* 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.
*/
function doNewRound()
{
if(engine.uRound !== false) { clearTimeout(engine.uRound); engine.uRound = false; }
endRound();
setTimeout(newRound,engine.dedicated?300:0); //give clients an opportunity to sync their data
}
function endRound()
{
if(window.svr)
{
window.svr.clients.forEach(function(ws){ws.send('{"type":"endRound"}')});
window.svr.clients.forEach(function(ws){ws.send('{"type":"syncdata","gtime":-4000}')});
}
if(ctx)
{
audioStop();
if(settings.SOUNDS_EXTRO) playSound(bufferLoader.bufferList[bufferLoader.other+2],0.5,1,false,ctx.destination);
}
engine.roundCommencing = true;
//engine.hud.hide();
if(engine.hud) engine.hud.game.style.opacity = 0;
engine.console.print("Deleting objects...\n",false);
if(!engine.network)
{
if(settings.ROUND_CENTER_MESSAGE != "")
{
centerMessage(settings.ROUND_CENTER_MESSAGE);
}
}
engine.gtime = -4000;
for(var x=engine.players.length-1;x>=0;--x) if(typeof(engine.players[x]) != "undefined")
{
engine.players[x].alive = false;
}
while(engine.scene.children.length > 0)
{
engine.scene.remove(engine.scene.children[0]);
}
//if(!engine.network) engine.players.splice(0);
}
function endGame()
{
endRound();
engine.players.splice(0);
engine.round = 0;
}
function playGame()
{
engine.playGame = true;
if(!engine.scene)
{
init();
}
else
{
engine.paused = false;
if(engine.hud) engine.hud.show();
}
hideMenu(); newRound();
engine.inputState = 'game'; //change input state to accept game controls
if(engine.network)
{
document.getElementById("progtitle").innerHTML = tStringify("@progtitleshort@ &bull; Playing online");
}
else
{
document.getElementById("progtitle").innerHTML = tStringify("@progtitleshort@ &bull; Playing locally");
}
}
function revertMap()
{
var mapfile = settings.RESOURCE_REPOSITORY_CACHE+(settings.MAP_FILE.replace(/\(.+\)/,""));
engine.console.print("Downloading map from "+mapfile+"...\n",false);
httpGetAsync(mapfile,loadRound,function()
{
engine.console.print("Unable to load map file. Ignoring for now...",false);
loadRound();
});
}
function newRound()
{
engine.roundCommencing = true;
/////////////LIGHTS
var light1 = new THREE.AmbientLight( 0x666666 ); // soft white light
engine.scene.add( light1 );
var light = new THREE.DirectionalLight( 0xffffff, 1 );
light.castShadow = true;
light.position.set( 4, 1, 0 );
engine.scene.add( light );
var light2 = new THREE.DirectionalLight( 0xffffff, 1 );
light2.castShadow = true;
light2.position.set( -4, -1, 0 );
engine.scene.add( light2 );
//////////end of lights
var aspectRatio = (window.innerWidth / window.innerHeight);
engine.camera = new THREE.PerspectiveCamera( settings.CAMERA_FOV, aspectRatio, settings.CAMERA_NEAR_RENDER, settings.CAMERA_FAR_RENDER );
engine.camera.userViewDir = false;
engine.camera.up = new THREE.Vector3(0,0,1); //Z is up, X and Y is l+r and b+f
//engine.camera.position.set(247, 247, 3);
engine.viewTarget = engine.activePlayer;
//engine.cameraOrbit = new THREE.OrbitControls(engine.camera);
//engine.cameraOrbit.maxDistance = 400;
//BELOW THIS LINE DEPENDS ON GAME TYPE
//MAP
var maps = settings.MAP_ROTATION.split(";");
if(settings.ROTATION_TYPE > 0)
{
switch(settings.ROTATION_TYPE)
{
case 1:
engine.currrot += 1;
break;
case 2: // when matches are implemented
if(engine.rounds == 0) engine.currrot += 1;
break;
}
if(engine.currrot > maps.length) engine.currrot = 0;
settings.MAP_FILE = maps[engine.currrot];
}
if(settings.MAP_FILE != "" && settings.MAP_FILE != engine.loadedMap)
{
var mapfile = settings.RESOURCE_REPOSITORY_SERVER+(settings.MAP_FILE.replace(/\(.+\)/,""));
engine.console.print("Downloading map from "+mapfile+"...\n",false);
httpGetAsync(mapfile,loadRound,revertMap);
//loadRound(httpGet(mapfile));
}
else
{
loadRound();
}
}
function teamColor(id)
{
id += 1;
if(settings["TEAM_NAME_"+id])
{
return new THREE.Color(settings["TEAM_RED_"+id]/15,settings["TEAM_GREEN_"+id]/15,settings["TEAM_BLUE_"+id]/15);
}
return new THREE.Color();
}
-function ensurePlayersSane(removeAIs=true)
+function createAIsettings()
+{
+ var AI_NUM = 1;
+ for(var z=engine.players.length-1;z>=0;--z) if(engine.players[z] && engine.players[z].AI) {AI_NUM++;}
+ var cycleColor = [0x000000,0xff0000,0x00ff00,0x0000ff][Math.round(Math.random()*3)];
+ var tailColor = [0x0000ff,0xff0000,0xffff00,0x00ff00][Math.round(Math.random()*3)];
+ if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(1); }
+ var colorcode = cycleColor.toString(16);
+ colorcode = ("0".repeat(6-colorcode.length))+colorcode;
+ var cycleinfo = { ai:true,
+ cycleColor:cycleColor, tailColor:tailColor,
+ /*engineType: 5,*/ engineType:(settings.players[0])?settings.players[0].engineType:5, spectating:false,
+ name: settings.AI_DUAL_COLOR_NAME?'AI0x'+colorcode+'#'+AI_NUM:'AI#'+AI_NUM
+ };
+ return cycleinfo;
+}
+function calculateSpawn(x)
+{
+ var spawnslength = engine.map.spawns.length;
+ if(!engine.map.spawns[x])
+ {
+ var mult = Math.floor((x/spawnslength));
+ var currspawn = x-(spawnslength*mult);
+ var alt = (mult/2 != Math.floor(mult/2));
+ console.log(mult);
+ if(alt) mult = -Math.ceil(mult/2)
+ else mult = mult/2
+ console.log(mult,currspawn);
+ var spawns = JSON.parse(JSON.stringify(engine.map.spawns[Math.min(currspawn,(spawnslength-1))]||[]));
+ spawns[0] -= mult*settings.SPAWN_WINGMEN_SIDE;
+ spawns[1] -= Math.abs(mult)*settings.SPAWN_WINGMEN_BACK;
+ }
+ else
+ {
+ var spawns = engine.map.spawns[x];
+ }
+ return spawns;
+}
+function processPlayer(x,cfg)
{
- var minplayers = Math.max(settings.TEAMS_MIN,settings.MIN_PLAYERS,settings.NUM_AIS+settings.players.length);
- if(removeAIs) for(var x=minplayers;x<engine.players.length-1;x++)
+ var spawns = calculateSpawn(x);
+ if(engine.players[x])
{
- if(engine.players[x].AI)
+ var cycle = engine.players[x];
+ cycle.engineType = (typeof(cfg)=="undefined")?5:cfg.engineType;
+ if(x == engine.activePlayer && !engine.dedicated)
{
- engine.console.print(engine.players[x].getColoredName()+"0xff7f7f left the game.\n");
- engine.players.splice(x,1);
+ var cycleColor = cfg.cycleColor,tailColor = cfg.tailColor;
+ if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(0); }
+ if(cycle.name != cfg.name)
+ {
+ var out = cycle.getColoredName()+"0x7fff7f renamed to ";
+ cycle.cycleColor = cycleColor;
+ cycle.tailColor = tailColor;
+ cycle.name = cfg.name;
+ engine.console.print(out+cycle.getColoredName()+"\n");
+ }
+ else
+ {
+ cycle.cycleColor = cycleColor;
+ cycle.tailColor = tailColor;
+ }
+ if(cycle.spectating != cfg.spectating)
+ {
+ cycle.spectating = cfg.spectating;
+ if(cycle.spectating)
+ {
+ engine.console.print(cycle.getColoredName()+"0xff7f7f left to spectator mode.\n");
+ }
+ else
+ {
+ engine.console.print(cycle.getColoredName()+"0x7fff7f entered from spectator mode.\n");
+ }
+ }
+ }
+ else
+ {
+ if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(1); }
}
}
- var spawnslength = engine.map.spawns.length;
- for(var x=engine.activePlayer;x<minplayers;x++)
+ else
{
- if(!engine.map.spawns[x])
+ cfg.x = spawns[0]; cfg.y = spawns[1]; cfg.z = spawns[2];
+ engine.players[x] = (new Player(cfg));
+ var cycle = engine.players[x];
+ if(cycle.spectating)
{
- var mult = Math.floor((x/spawnslength));
- var currspawn = x-(spawnslength*mult);
- var alt = (mult/2 != Math.floor(mult/2));
- console.log(mult);
- if(alt) mult = -Math.ceil(mult/2)
- else mult = mult/2
- console.log(mult,currspawn);
- var spawns = JSON.parse(JSON.stringify(engine.map.spawns[Math.min(currspawn,(spawnslength-1))]||[]));
- spawns[0] -= mult*settings.SPAWN_WINGMEN_SIDE;
- spawns[1] -= Math.abs(mult)*settings.SPAWN_WINGMEN_BACK;
+ engine.console.print(cycle.getColoredName()+"0xff7f7f entered as spectator.\n");
}
else
{
- var spawns = engine.map.spawns[x];
+ engine.console.print(cycle.getColoredName()+"0x7fff7f entered the game.\n");
}
- if(engine.players[x])
+ }
+ if(cycle.spectating)
+ {
+ cycle.team = null;
+ }
+ else if(!cycle.team)
+ {
+ if(engine.teams.length < settings.TEAMS_MAX)
{
-
- var cycle = engine.players[x];
- cycle.engineType = (typeof(settings.players[x])=="undefined")?5:settings.players[x].engineType;
- if(x == engine.activePlayer && !engine.dedicated)
+ engine.teams.push(cycle.team = new Team({name:cfg.name,x:spawns[0], y:spawns[1], z:spawns[2], dir:deg2rad(spawns[3])}));
+ }
+ else
+ {
+ var minPCount = 0, minPlayers = Infinity, minTeam;
+ for(var x=engine.teams.length-1;x>=0;--x)
{
- var cycleColor = settings.players[x].cycleColor,tailColor = settings.players[x].tailColor;
- if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(0); }
- if(cycle.name != settings.players[x].name)
- {
- var out = cycle.getColoredName()+"0x7fff7f renamed to ";
- cycle.cycleColor = cycleColor;
- cycle.tailColor = tailColor;
- cycle.name = settings.players[x].name;
- engine.console.print(out+cycle.getColoredName()+"\n");
- }
- else
+ if(engine.teams[x].members.length == minPlayers)
{
- cycle.cycleColor = cycleColor;
- cycle.tailColor = tailColor;
- }
- if(cycle.spectating != settings.players[x].spectating)
- {
- cycle.spectating = settings.players[x].spectating;
- if(cycle.spectating)
+ minPCount++;
+ if(minTeam.push)
{
- engine.console.print(cycle.getColoredName()+"0xff7f7f entered spectator mode.\n");
+ minTeam.push(x);
}
else
{
- engine.console.print(cycle.getColoredName()+"0x7fff7f entered the game.\n");
+ minTeam = [minTeam,x];
}
}
+ else if(engine.teams[x].members.length < minPlayers)
+ {
+ minPlayers = engine.teams[x].members.length;
+ minTeam = x; minPCount = 1;
+ }
}
- else
+ if(minPCount != 1)
{
- if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(1); }
+ minTeam = Math.floor(Math.random()*minTeam.length);
}
+ cycle.team = engine.teams[minTeam];
}
- else
+ cycle.team.members.push(cycle);
+ }
+}
+function ensurePlayersSane(removeAIs=true)
+{
+ var numAIs = 0, numPlay = 0, numSpec = 0, numWantPlay = 0;
+ for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x])
+ {
+ if(engine.players[x].AI) numAIs++;
+ if(engine.players[x].spectating) numSpec++; else numPlay++;
+ //if(engine.players[x].spectating && !settings.players[x].spectating) numWantPlay++;
+ }
+ var numHuman = numPlay-numAIs;
+ if(removeAIs)
+ {
+ for(var x=settings.TEAMS_MAX;x<engine.teams.length;++x) if(engine.teams[x])
{
- //if(x == engine.activePlayer)
- if(settings.players[x])
+ for(var i=engine.teams[x].members.length-1;i>=0;--i)
{
- var cycleColor = settings.players[x].cycleColor,tailColor = settings.players[x].tailColor;
- if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(0); }
- var cycleinfo = { x:spawns[0], y:spawns[1], z:spawns[2], dir:deg2rad(spawns[3]), ai:false,
- cycleColor:cycleColor, tailColor:tailColor,
- engineType:settings.players[x].engineType, spectating:settings.players[x].spectating,
- name:settings.players[x].name
- };
+ engine.console.print(engine.teams[x].members[i].getColoredName()+"0xff7f7f left to spectator mode.\n");
+ engine.teams[x].members[i].spectating = true;
}
- else
+ }
+ engine.teams.splice(settings.TEAMS_MAX);
+ }
+ for(var x=settings.players.length-1;x>=0;--x) if(settings.players[x])
+ {
+ if(engine.players[x] && engine.players[x].AI)
+ {
+ engine.players[engine.players.length-1] = engine.players[x];
+ engine.players[x] = undefined;
+ }
+ if(!engine.players[x])
+ {
+ numPlay++; numHuman++;
+ }
+ processPlayer(x,settings.players[x]);
+ }
+ if(removeAIs)
+ {
+ console.log(numHuman);
+ var shouldAIs = Math.max(0,(settings.MIN_PLAYERS-numHuman));
+ if(!settings.AI_TEAM)
+ {
+ shouldAIs += (numHuman <= settings.SP_HUMANS_COUNT)?settings.SP_NUM_AIS:settings.NUM_AIS;
+ }
+
+ if(shouldAIs > numAIs)
+ {
+ var AIsToAdd = (shouldAIs-numAIs);
+ console.log(numAIs+" AIs in the game, adding "+AIsToAdd+".");
+ for(var x=AIsToAdd;x>0;--x)
{
- var AI_NUM = 1;
- for(var z=engine.players.length-1;z>=0;--z) if(engine.players[z] && engine.players[z].AI) {AI_NUM++;}
- var cycleColor = [0x000000,0xff0000,0x00ff00,0x0000ff][Math.round(Math.random()*3)];
- var tailColor = [0x0000ff,0xff0000,0xffff00,0x00ff00][Math.round(Math.random()*3)];
- if(!settings.ALLOW_TEAM_NAME_COLOR) { cycleColor = tailColor = teamColor(1); }
- var cycleinfo = { x:spawns[0], y:spawns[1], z:spawns[2], dir:deg2rad(spawns[3]), ai:true,
- cycleColor:cycleColor, tailColor:tailColor,
- /*engineType: 5,*/ engineType:(settings.players[0])?settings.players[0].engineType:5, spectating:false,
- name: 'AI#'+AI_NUM
- };
+ var cycleinfo = createAIsettings();
+ processPlayer(engine.players.length,cycleinfo);
}
- engine.players.push(new Player(cycleinfo));
- var cycle = engine.players[x];
- if(cycle.spectating)
+ numAIs += AIsToAdd;
+ }
+ else if(numAIs != 0)
+ {
+ var AIsToDealWith = (numAIs-shouldAIs);
+ console.log(numAIs+" AIs in the game, removing "+AIsToDealWith+".");
+ if(AIsToDealWith != 0)
{
- engine.console.print(cycle.getColoredName()+"0xff7f7f entered as spectator.\n");
+ for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x])
+ {
+ if(engine.players[x].AI)
+ {
+ engine.console.print(engine.players[x].getColoredName()+"0xff7f7f left the game.\n");
+ engine.players.splice(x,1);
+ AIsToDealWith--;
+ if(window.svr)
+ {
+ var data = JSON.stringify({type:"leave",data:x});
+ window.svr.clients.forEach(function(ws){ws.send(data)});
+ }
+ }
+ if(AIsToDealWith == 0) break;
+ }
+ }
+ }
+
+ //clean up teams / remove ghost teams
+ for(var x=engine.teams.length-1;x>=0;--x) if(engine.teams[x])
+ {
+ for(var i=engine.teams[x].members.length-1;i>=0;--i)
+ {
+ if(engine.players.indexOf(engine.teams[x].members[i]) == -1)
+ {
+ engine.teams[x].members.splice(i,1);
+ }
+ }
+ if(engine.teams[x].members.length == 0)
+ {
+ engine.teams.splice(x,1);
}
else
{
- engine.console.print(cycle.getColoredName()+"0x7fff7f entered the game.\n");
+ engine.teams[x].spawn(false,false); //and finally spawn everyone
}
}
- var deg = (360/settings.ARENA_AXES);
- if(cycle.spectating)
- {
- console.log("Spectating");
- minplayers++;
- }
- else if(removeAIs)
- {
- cycle.spawn({x:spawns[0],y:spawns[1],z:spawns[2],dir:deg2rad(settings.STRICT_AXES_SPAWN?(Math.round(spawns[3]/deg)*deg):spawns[3])},false,false);
- }
+ if(!engine.dedicated && !engine.players[engine.activePlayer].alive) changeViewTarget(1);
}
- if(engine.players[engine.activePlayer].spectating) changeViewTarget(1);
if(window.svr) window.svr.clients.forEach(function(ws){ws.senddata(0)});
-}
+}//*/
+
function loadRound(dlmap)
{
if(typeof(dlmap) != "undefined")
{
engine.mapString = dlmap;
engine.loadedMap = settings.MAP_FILE;
}
engine.mapXML = xmlify(engine.mapString);
engine.console.print("Creating objects...\n",false);
if(window.svr) window.svr.clients.forEach(function(ws){ws.send('{"type":"newRound"}')});
//virtual map data (used for positions, lines and stuff to calculate)
engine.map = {zones:[],spawns:[],walls:[]};
engine.expl = []; engine.deaths = 0;
engine.winzone = false;
//GRID
buildGrid();//buildObjects.js
engine.scene.add(engine.grid);
//WALLS
buildWalls();//buildObjects
engine.scene.add(engine.walls);
//ZONES
buildZones();
engine.scene.add(engine.zones);
if(settings.SOUNDS_INTRO)
playSound(bufferLoader.bufferList[bufferLoader.other+1],0.5,1,false,ctx.destination);
if(settings.ROUND_CONSOLE_MESSAGE != "")
{
engine.console.print(settings.ROUND_CONSOLE_MESSAGE+"\n");
}
loadcfg(settings.ROUND_COMMAND.replace(/\\n/g,"\n"));
//GAME
engine.gtime = -4000;
//PLAYERS
//CYCLE
if(!engine.network)
{
ensurePlayersSane();
if(engine.round == 0)
{
engine.console.print("Resetting scores...\n");
- for(var x=engine.players.length-1;x>=0;--x)
+ for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x])
{
engine.players[x].score = 0;
}
}
engine.round++;
engine.console.print("Go (round "+engine.round+" of "+settings.LIMIT_ROUNDS+")!\n");
}
if(!engine.camera)
{
var aspectRatio = (window.innerWidth / window.innerHeight);
engine.camera = new THREE.PerspectiveCamera( settings.CAMERA_FOV, aspectRatio, settings.CAMERA_NEAR_RENDER, settings.CAMERA_FAR_RENDER );
engine.camera.up = new THREE.Vector3(0,0,1); //Z is up, X and Y is l+r and b+f
}
engine.camera.position.set(engine.logicalBox.center.x*engine.REAL_ARENA_SIZE_FACTOR,engine.logicalBox.center.y*engine.REAL_ARENA_SIZE_FACTOR,3);
try{engine.camera.lookAt( new THREE.Vector3(engine.players[engine.viewTarget].position.x,engine.players[engine.viewTarget].position.y,engine.player[engine.viewTarget].position.z) );}
catch(e){engine.camera.lookAt( new THREE.Vector3(engine.logicalBox.center.x*engine.REAL_ARENA_SIZE_FACTOR,engine.logicalBox.center.y*engine.REAL_ARENA_SIZE_FACTOR,0) );}
updateScoreBoard();
engine.lastGameTime = engine.lastRenderTime = engine.fpsTime = engine.timeStart = performance.now();
engine.totalPauseTime = 0;
engine.fastestPlayer = engine.fastestSpeed = 0;
engine.timemult = 1;
engine.asendtm = 0;
engine.winner = undefined;
engine.roundCommencing = false;
getGoing();
}//end of init main
function game(oneoff=false)
{
if(!engine.roundCommencing && !engine.paused)
{
if(engine.network)
{
var cycle = engine.players[engine.activePlayer],data={},len=0;
if(cycle.braking != cycle.brakingPrev) {data.braking=cycle.braking; cycle.brakingPrev=cycle.braking; ++len;}
if(cycle.boosting != cycle.boostingPrev) {data.boosting=cycle.boosting; cycle.boostingPrev=cycle.boosting; ++len;}
if(len > 0)
{
engine.connection.send(JSON.stringify({type:"playdata",data:data}));
}
}
if(!oneoff && settings.GAME_LOOP != 1) {setTimeout(game,1000/settings.DEDICATED_FPS); engine.gameRunning = true;}
//time handlers and delta
var timenow = performance.now()/settings.TIME_FACTOR;
var rDelta = (timenow-engine.lastGameTime);
if(rDelta > settings.TIMESTEP_MAX*1000 && engine.gtime > 0)
{
var more = true;
rDelta = settings.TIMESTEP_MAX*1000;
//engine.timeStart += rDelta;
} else var more = false;
var delta = rDelta*engine.timemult;
var timestep = delta/1000;
engine.totalPauseTime += (timenow-engine.lastGameTime)-delta;
engine.lastGameTime += rDelta;
engine.avgTimeStep += rDelta/1000; engine.avgTimeStep /= 2;
if(!engine.network && !engine.dedicated) engine.players[0].ping = parseInt(engine.avgTimeStep*1000)
//if(!engine.network && timestep > engine.avgTimeStep*10 && rDelta == delta) {engine.totalPauseTime += timestep; console.log("Compensated skip of "+delta+"ms."); timestep = engine.avgTimeStep;}
engine.timemult += (engine.asendtm*timestep);
if(engine.timemult > 100) engine.timemult = 100;
//var timeElapsed = timenow-engine.timeStart-engine.totalPauseTime-4000;
//skipping ahead at the beginning of the round is silly
//engine.gtime = timeElapsed;
var timeElapsed = (engine.gtime += delta);
if(!engine.thread_collisiondetect && (settings.GAME_LOOP != 0.5 || !oneoff)) getCycleSensors();
var pldata = {};
for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x])
{
var cycle = engine.players[x];
if(cycle.alive)
{
if(cycle.newPos) doNetSlide(cycle,timestep);
if(timeElapsed > 0)
{
if(x == engine.activePlayer)
{
if(settings.HACK_TURN_LEFT_WHEN_POSSIBLE > 0)
{
if(cycle.sensor.left > settings.HACK_TURN_SENSOR_DIST)
{
cycle.turn(-1);
settings.HACK_TURN_LEFT_WHEN_POSSIBLE--;
}
}
if(settings.HACK_TURN_RIGHT_WHEN_POSSIBLE > 0)
{
if(cycle.sensor.right > settings.HACK_TURN_SENSOR_DIST)
{
cycle.turn(1);
settings.HACK_TURN_RIGHT_WHEN_POSSIBLE--;
}
}
}
//bot turning
if(cycle.AI)
{
cycle.AI.think(timestep);
}
else if(x==engine.activePlayer && (cycle.chatting || settings.CHATBOT_ALWAYS_ACTIVE))
{
if(timenow > cycle.lastTurnTime+(settings.CYCLE_DELAY*1000) && cycle.sensor.front < Math.min(5,cycle.sensor.left,cycle.sensor.right))
{
if(cycle.sensor.right < cycle.sensor.left) cycle.turn(-1);
else if(cycle.sensor.right > cycle.sensor.left) cycle.turn(1);
else cycle.turn([-1,1][Math.round(Math.random()*1)]);
}
}
//do turning
//if(cycle.turnQueue.length > 0)
{
//if(cycle.turnQueue.length > 0 && x == 0)console.log(JSON.parse(JSON.stringify(cycle.turnQueue)));
if(cycle.turnQueue.length > settings.CYCLE_TURN_MEMORY) cycle.turnQueue.splice(0,cycle.turnQueue.length-settings.CYCLE_TURN_MEMORY);
var shouldTime = cycle.lastTurnTime+(settings.CYCLE_DELAY*1000);
if(cycle.turnQueue.length > 0 && timeElapsed >= shouldTime/*-delta*/)
{
//allow the cycle to turn when it should (???)
//var diff = (shouldTime-timeElapsed)/1000;
//cycle.update(diff);
if(settings.CYCLE_MIDAIR_TURN || cycle.position.z-cycle.sensor.bottom == cycle.model.rotation.y)
{
var dir = cycle.turnQueue[0],dirmult;
var olddir = cdir(cycle.rotation.z);
cycle.dir.front = (dirmult = cdir(cycle.rotation.z -= (pi(2)/settings.ARENA_AXES)*dir));
//cycle.rotation.z = cycle.rotation.z%(Math.PI*2);
//if(cycle.rotation.z < 0) cycle.rotation.z += Math.PI*2;
cycle.rotation.z = normalizeRad(cycle.rotation.z);
cycle.speed *= settings.CYCLE_TURN_SPEED_FACTOR;
cycle.rotation.x = Math.cos(cycle.rotation.z)*0.4*dir; //tilts the cycle
cycle.rotation.y = Math.sin(cycle.rotation.z)*0.4*dir;
//if(settings.GRAB_SENSORS_ON_TURN)
{
getCycleSensors(true);
}
cycle.collidetime = timeElapsed+(((cycle.sensor.front)/cycle.speed)*1000);
var mult = (1-settings.CYCLE_RUBBER_MINADJUST);
cycle.minDistance.front = Math.max(0,Math.min(cycle.sensor.front*mult,settings.CYCLE_RUBBER_MINDISTANCE));
cycle.lastpos = cycle.position.clone(); //redundant, should be handled by getCycleSensors
if(cycle.haswall) cycle.newWallSegment();
if(engine.network)
{
engine.connection.send(JSON.stringify({
type:"turn",data:rad2deg(cycle.rotation.z),gtime:cycle.gameTime,
position:[cycle.position.x,cycle.position.y,cycle.position.z],
speed:cycle.speed, rubber:cycle.rubber, brakes:cycle.brakes
}));
}
if(window.svr) //force a player sync
{
var data = JSON.stringify({type:"griddata",data:[{
position:[cycle.position.x,cycle.position.y,cycle.position.z],
direction:rad2deg(cycle.rotation.z),
speed:cycle.speed, rubber:cycle.rubber,
alive:cycle.alive,
netid:x, wall:cycle.walls.map,
}],gtime:engine.gtime});
window.svr.clients.forEach(function(ws){ws.send(data)});
}
}
cycle.turnQueue.splice(0,1);
cycle.lastTurnTime = timeElapsed;
}
}
cycle.update();
}
if(cycle.rubber > settings.CYCLE_RUBBER+0.0001)
cycle.rubber = settings.CYCLE_RUBBER+0.0001;
else if(cycle.rubber > 0)
cycle.rubber -= (timestep/settings.CYCLE_RUBBER_TIME)*cycle.rubber;
else
cycle.rubber = 0;
//if(timeElapsed/1000 > -3 && cycle.alive)
}
else if(cycle.walls.map.length != 0 && timenow-cycle.dedtime >= settings.WALLS_STAY_UP_DELAY*1000)
{
cycle.walls.map = [];
console.log("DELETE WALLS id "+x);
}
else if(settings.RESPAWN_TIME >= 0 && !cycle.alive && timenow-cycle.dedtime > settings.RESPAWN_TIME*1000)
{
cycle.spawn({x:cycle.position.x||0,y:cycle.position.y||0,z:cycle.position.z||0,dir:cycle.rotation.z||0});
}
}
if(timeElapsed > -3000 && timeElapsed < 1000)
{
//timer
var time=-timeElapsed/1000,gTime = Math.ceil(time);
if(gTime < 0) gTime = 0;
if(typeof(engine.timer)=="undefined" || engine.timer != gTime)
{
engine.timer = gTime;
if(engine.hud) engine.hud.fadein = true;
if(engine.dedicated) console.log(gTime);
else centerMessage(gTime,(gTime-time));
//engine.console.print(gTime+"\n");
}
}
else if(!engine.network && typeof(engine.winner) == "undefined")
{
checkForWinner();
}
if(!engine.network)
{
if(!engine.winzone && settings.WIN_ZONE_MIN_ROUND_TIME+engine.deaths*(settings.WIN_ZONE_MIN_LAST_DEATH) < timeElapsed/1000)
{
var zone = {expansion:settings.WIN_ZONE_EXPANSION};
if(settings.WIN_ZONE_DEATHS)
{
engine.console.print("Death zone activated. Avoid it!\n");
zone.type = "death";
}
else
{
engine.console.print("Win zone activated. Enter it to win the round.\n");
zone.type = "win";
}
zone.radius = Math.min(SMALL_NUM,settings.WIN_ZONE_INITIAL_SIZE)*engine.REAL_ARENA_SIZE_FACTOR;
zone.x = engine.REAL_ARENA_SIZE_FACTOR*(engine.logicalBox.center.x+(settings.WIN_ZONE_RANDOMNESS*(Math.random()-0.5)*2)*engine.logicalBox.center.x);
zone.y = engine.REAL_ARENA_SIZE_FACTOR*(engine.logicalBox.center.y+(settings.WIN_ZONE_RANDOMNESS*(Math.random()-0.5)*2)*engine.logicalBox.center.y);
new Zone(zone).spawn();
console.log("ZONE SPAWNED: "+zone.type);
engine.winzone = true;
}
}
for(var x=engine.zones.children.length-1;x>=0;--x)
{
var zone = engine.zones.children[x].cfg;
//zones expand
if(zone.radius > 0)
{
engine.zones.children[x].scale.x = engine.zones.children[x].scale.y = (zone.radius += zone.expansion*timestep*engine.REAL_ARENA_SIZE_FACTOR);
}
else if(zone.radius < 0) engine.zones.children[x].scale.x = engine.zones.children[x].scale.y = zone.radius = 0;
//zone effect
var inzone = false;
for(var y=engine.players.length-1;y>=0;--y) if(engine.players[y] && engine.players[y].alive)
{
var cycle = engine.players[y];
if(zone.type == "ball" || zone.type == "soccerball")
{
for(var z=engine.zones.children.length-1;z>=0;--z)
{
var z2n = engine.map.zones[z];
if(
(
(zone.type == "ball" && z2n[0] == "fortress") ||
(zone.type == "soccerball" && z2n[0] == "soccergoal")
) &&
is_in_circle(z2n[1],z2n[2],z2n[3],zone.x,zone.y,zone.radius))
{
if(!engine.network && engine.winner == undefined)
{
centerMessage("0x00ff00Goal!");
startNewRound();
}
else
{
zone.xdir *= 1-timestep; zone.ydir *= 1-timestep;
}
}
}
}
//dont handle zones we don't need to
if(!zone.netObject || zone.type.indexOf("ball") >= 0)
{
//var lastdist = zone.distance(cycle.lastpos);
//var dist = zone.distance(cycle.position);
var lastdist = pointDistance(zone.mesh.position.x,zone.mesh.position.y,cycle.lastpos.x,cycle.lastpos.y)-zone.radius;
var dist = pointDistance(zone.mesh.position.x,zone.mesh.position.y,cycle.position.x,cycle.position.y)-zone.radius;
var inZone = (dist <= 0), wasInZone = (lastdist <= 0);
if(inZone)
{
var timediff = cycle.speed*dist;
var hitTime = timeElapsed-timediff;
if(!wasInZone) zone.onEnter(cycle,hitTime,timestep);
if(cycle.alive) zone.onInside(cycle,engine.gtime,timestep);
}
else if(wasInZone) //left zone
{
zone.onLeave(cycle,engine.gtime,timestep); //TODO: figure out "precise" left time
}
else
{
zone.onOutside(cycle,engine.gtime,timestep);
}
}
if(zone.type == "fortress") //fortress recover rate
{
zone.rotationSpeed += (settings.ZONE_SPIN_SPEED-zone.rotationSpeed)*timestep*settings.FORTRESS_CONQUEST_DECAY_RATE;
}
}
if(typeof(zone.xdir)+typeof(zone.ydir) !== "undefinedundefined")
{
if(zone.bounce && zone.walldist <= timestep)
{
var mindirx,mindiry,mindist=Infinity,apc=0;
var px = zone.x+(zone.walldist*zone.xdir), py = zone.y+(zone.walldist*zone.ydir);
for(var i=359;i>0;i--)
{
var xdir = Math.sin(Math.PI*2*(i/360)), ydir=Math.cos(Math.PI*2*(i/360));
var xpos = xdir*zone.radius+zone.x, ypos=ydir*zone.radius+zone.y;
var dist = pointDistance(xpos,ypos,px,py);
if(dist < mindist)
{
//mindist += dist; mindirx += xdir; mindiry += ydir;
//apc++;
mindist=dist;mindirx=xdir;mindiry=ydir;apc=1;
}
}
//mindist /= apc; mindirx /= apc; mindiry /= apc;
var speed = Math.sqrt((zone.xdir*zone.xdir)+(zone.ydir*zone.ydir));
if(mindist != Infinity)
{
var angle = Math.atan2(mindiry,mindirx);
//var angle = Math.atan2(mindiry,mindirx)*2;
//var angle = Math.atan2(mindiry,mindirx)+(Math.PI/2);
//var angle = Math.PI-Math.atan2(mindiry,mindirx);
var dir = cdir(angle);
zone.xdir = dir[0]*speed; zone.ydir = dir[1]*speed;
zone.x -= dir[0]*realzone.walldist; zone.y -= dir[1]*realzone.walldist;
zone.x += dir[0]*speed*timestep; zone.y += dir[1]*speed*timestep;
console.log(zone);
}
else
{
zone.xdir *= -1; zone.ydir *= -1;
}
}
else
{
zone.mesh.position.x += zone.xdir*timestep; zone.mesh.position.y += zone.ydir*timestep;
}
}
}
var dc = Object.keys(engine.delayedcommands);
for(var x=dc.length-1;x>=0;x--)
{
var cmd = engine.delayedcommands[dc[x]];
loadcfg(cmd[0]);
if(dc[x] >= engine.gtime)
{
if(cmd[1] > 0)
{
engine.delayedcommands[dc[x]+cmd[1]] = cmd;
}
delete engine.delayedcommands[dc[x]];
}
}
//if(more) game();
}
else
{
engine.gameRunning = false;
}
}
function doDeath(cycle,escape=false)
{
if(escape || (cycle.sensor.nearestobj == "rim" && !cycle.sensor.lastnonselfobj))
{
if(escape || (
cycle.position.x-cycle.minDistance.front > engine.logicalBox.max.x ||
cycle.position.y-cycle.minDistance.front > engine.logicalBox.max.y ||
cycle.position.x+cycle.minDistance.front < engine.logicalBox.min.x ||
cycle.position.y+cycle.minDistance.front < engine.logicalBox.min.y
))
{
engine.console.print(cycle.getColoredName()+"0xRESETT tried to escape the game grid.\n");
}
else
{
engine.console.print(cycle.getColoredName()+"0xRESETT committed suicide.\n");
}
}
else
{
var objtoaccuse = typeof(cycle.sensor.lastnonselfobj)=="undefined"?cycle.sensor.nearestobj:cycle.sensor.lastnonselfobj;
if(objtoaccuse == cycle)
{
engine.console.print(cycle.getColoredName()+"0xRESETT committed suicide.\n");
}
else if(typeof(objtoaccuse) == "object")
{
engine.console.print(objtoaccuse.getColoredName()+"0xRESETT core dumped "+cycle.getColoredName()+"0xRESETT for 1 point.\n");
objtoaccuse.addScore(1);
}
else
{
engine.console.print(cycle.getColoredName()+"0xRESETT died.\n");
}
}
cycle.kill();
}
function simulatePlayer(cycle,timestep)
{
console.warn("Deprecated call to simulatePlayer");
cycle.update(timestep);
}
function getGoing()
{
if(!engine.gameRunning) game();
if(!engine.renderRunning) render();
}
function pauseRender()
{
engine.paused = true;//cuts off the loop
engine.startOfPause = performance.now();
audioStop();
}
function unpauseRender()
{
for(var ctrl in engine.controls)
{
engine.controls[ctrl] = [];
}
//renderLoop = true;//replaces cutoff
if(engine.paused)
{
engine.paused = false;
audioStart();
engine.lastGameTime = engine.lastRenderTime = engine.fpsTime = performance.now();//resets delta so we don't pretend the game should have been playing the entire time we were paused
var endOfPause = performance.now();
engine.totalPauseTime += (endOfPause - engine.startOfPause);
getGoing();//starts the loop again
}
}
function changeViewTarget(a=1,forcechange=false)
{
+ if(engine.dedicated) return;
if(a != 0)
{
if(!forcechange && engine.players[engine.activePlayer].alive) return;
var first = true; //force the loop to get started
var itcount = 0;
- /*if(alive > 0) */while(first || !engine.players[engine.viewTarget].alive)
+ /*if(alive > 0) */while(first || !engine.players[engine.viewTarget] || !engine.players[engine.viewTarget].alive)
{
first = false;
engine.viewTarget+=a;
if(engine.viewTarget >= engine.players.length) engine.viewTarget = 0;
if(engine.viewTarget < 0) engine.viewTarget = engine.players.length+engine.viewTarget;
itcount++;
if(itcount > engine.players.length) break;
//console.log(engine.viewTarget);
}
}
if(engine.view == 'cockpit')
{
for(var x=0;x>engine.players.length;x++)
{
if(x == engine.viewTarget)
engine.players[x].audio.gain.setTargetAtTime(0.2, ctx.currentTime, 0.02);
else
engine.players[x].audio.gain.setTargetAtTime(6, ctx.currentTime, 1);
}
}
if(!engine.network && !engine.players[engine.activePlayer].spectating && typeof(engine.winner) == "undefined")
{
switch(settings.FINISH_TYPE)
{
case 2:
engine.asendtm = 0.2;
centerMessage("Time Warp!",Infinity);
if(engine.hud) engine.hud.fadein = false;
break;
case 3:
centerMessage("Please wait...",Infinity);
setTimeout(function()
{
engine.timemult = 100;
while(typeof(engine.winner) == "undefined") { game(true) }
engine.timemult = 1;
},100);
break;
}
}
engine.console.print("Watching "+engine.players[engine.viewTarget].name+"...\n");
}
function checkForWinner()
{
var alivecount = aliveaicount = 0;
var alive = [], theplayer = false;
var declareRoundWinner = typeof(engine.declareRoundWinner) != "undefined";
for(var x=engine.players.length-1;x>=0;--x) if(typeof(engine.players[x]) != "undefined")
{
if(engine.players[x].alive)
{
alivecount++;
if(engine.players[x].AI)
aliveaicount++;
alive.push(engine.players[x]);
}
if(declareRoundWinner && engine.players[x].name == engine.declareRoundWinner)
{
engine.winner = engine.players[x];
engine.declareRoundWinner = undefined;
}
}
if(
(declareRoundWinner) ||
(settings.GAME_TYPE == 1 && settings.TEAMS_MIN > 1 && (alivecount <= 1 || (settings.FINISH_TYPE == 1 && aliveaicount == alivecount))) ||
(/*settings.GAME_TYPE == 0 && */(alivecount <= 0))
)
{
if(!declareRoundWinner)
{
engine.winner = (typeof(alive[0]) == "undefined")?{name:undefined}:alive[0];
}
if(settings.RIM_WALL_COLOR_MODE == 2)
{
if(engine.winner && settings.RIM_WALL_COLOR_MODE == 2)
{
var color = new THREE.Color(engine.winner.cycleColor);
settings.RIM_WALL_RED = color.r;
settings.RIM_WALL_GREEN = color.g;
settings.RIM_WALL_BLUE = color.b;
}
}
if(engine.asendtm > 0) {engine.asendtm = 0; engine.timemult = 1; centerMessage("Time Warp!",0);}
setTimeout(function(){centerMessage("Winner: "+engine.winner.name)},1000);
startNewRound();
}//*/
/*if(aliveaicount == alivecount)
{
engine.console.print("Vroom!");
engine.timemult = 2;
engine.asendtm = 1.1;
}//*/
}
function startNewRound()
{
if(typeof(engine.winner) == "undefined") engine.winner = null;
var endin = 4000;
if(engine.round >= settings.LIMIT_ROUNDS)
{
var highscore = -Infinity, highplayer;
for(var x=engine.players.length-1;x>=0;--x) if(typeof(engine.players[x]) != "undefined")
{
var cycle = engine.players[x];
if(cycle.score > highscore)
{
highplayer = cycle;
highscore = cycle.score;
}
else if(cycle.score == highscore)
{
highplayer = null;
}
}
if(highplayer != null)
{
setTimeout(function(){centerMessage("Match Winner: "+highplayer.name);engine.console.print("Match Winner: "+highplayer.name+" with "+highscore+" points.\n")},4000);
}
engine.round = 0;
endin += 4000;
}
if(!settings.ROUND_WAIT) engine.uRound = setTimeout(doNewRound,endin);
}
function updateScoreBoard()
{
if(window.svr)
{
var tmp = [];
- for(var x=engine.players.length-1;x>=0;--x)
+ for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x])
{
tmp.push({netid:x,score:engine.players[x].score,ping:engine.players[x].ping,chatting:engine.players[x].chatting});
}
var data = JSON.stringify({type:"scoredata",data:tmp});
window.svr.clients.forEach(function(ws){ws.send(data);});
}
if(engine.network)
{
engine.connection.send(JSON.stringify({type:"playdata",data:{chatting:engine.players[engine.activePlayer].chatting}}));
}
if(engine.dedicated || scoreboard.style.display == "none") return;
var scoreBoard = document.getElementById("scoreboard").children[0];
var playersSB = scoreBoard.children[1];
var tmp = "";
for(var x=0;x<engine.playersByScore.length;++x) if(typeof(engine.playersByScore[x]) != "undefined")
{
var cycle = engine.playersByScore[x];
- tmp += "<tr class=\"player\"><td>"+(cycle.chatting?"*":"&nbsp;")+replaceColors(cycle.getColoredName())+"</td><td>"+replaceColors(cycle.alive?"0x00ff00Yes":"0xff0000No")+"</td><td>"+cycle.score+"</td><td>"+cycle.ping+"</td><tr>";
+ tmp += "<tr class=\"player\"><td>"+(cycle.chatting?"*":"&nbsp;")+replaceColors(cycle.getColoredName())+"</td><td>"+replaceColors(cycle.alive?"0x00ff00Yes":"0xff0000No")+"</td><td>"+cycle.score+"</td><td>"+cycle.ping+"</td><td>"+(cycle.team?cycle.team.name:"")+"</td><tr>";
}
playersSB.innerHTML = tmp;
}
/*function updateScoreBoard()
{
var scoreboard = "";
for(var x=engine.players.length-1;x>=0;--x) if(typeof(engine.players[x]) != "undefined")
{
var cycle = engine.players[x];
scoreboard += (cycle.chatting?"*":" ")+removeColors(cycle.name)+" "+cycle.alive?"Yes":"No"+" "+cycle.score+" "+cycle.ping+" ";
}
}*/
diff --git a/scripts/player.js b/scripts/player.js
index 9a76980..bc79276 100644
--- a/scripts/player.js
+++ b/scripts/player.js
@@ -1,633 +1,633 @@
/*
* 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.
*/
//if(typeof(THREE) == "undefined") var THREE = require('./lib/Three.js');
class Player extends THREE.Object3D
{
setScore(x)
{
this.score = (x*1)||0;
engine.playersByScore.sort(function(a,b){return b.score-a.score});
if(engine.playersByScore.indexOf(this) > -1) updateScoreBoard();
}
addScore(x)
{
this.setScore(this.score+((x*1)||0));
}
softReset() //! Resets the cycle state to default variables
{
this.speed = 0;
this.lastSpeed = this.speed;
this.rubber = 0;
this.brakes = 1;
this.braking = false;
this.boosting = false;
this.boost = 0;
this.dedtime = 0;
this.alive = false;
this.collidetime = Infinity;
this.sensor = {left:Infinity,right:Infinity,front:Infinity};
this.dir = {front:[0,0],left:[0,0],right:[0,0]};
this.minDistance = {front:settings.CYCLE_RUBBER_MINDISTANCE};
this.turnQueue = [];
this.lastTurnTime = 0;
this.gameTime = 0;
this.handleNetTurn = true;
}
hardReset() //! Same as soft reset but resets all varaibles
{
this.softReset();
this.setScore(0);
this.ping = 0;
}
getColoredName() //! Name with colors...
{
switch(typeof(this.tailColor))
{
case "string":
return this.tailColor.replace("#","0x")+this.name;
case "object":
return "0x"+this.tailColor.getHexString()+this.name;
case "number":
var color = this.tailColor.toString(16);
color = ("0".repeat(6-color.length))+color;
return "0x"+color+this.name;
default:
console.warn("Can't get color");
return "0xRESETT"+this.name;
}
}
getBoringName() //! Name without colors...
{
return removeColors(this.name);
}
newWallSegment() //should be called on turns
{
var adj = 0.7, wmap = this.walls.map, dirmult = this.dir.front;
wmap[wmap.length-1] = [this.position.x,this.position.y,this.position.z];
wmap[wmap.length] = [this.position.x,this.position.y,this.position.z];
this.resetCurrWallSegment(false,1);
var wall = newWall(this.tailColor,this.position.x,this.position.y,this.position.z);
var adjx = (dirmult[0]*adj), adjy = (dirmult[1]*adj);
wall.scale.x -= adjx/wall.size; wall.scale.y -= adjy/wall.size;
this.walls.add(wall);
}
/*recalcCurrWallLength(tocurrpos=false)
{
var adj = 0.7, dirmult = this.dir.front, wall = this.walls.children[this.walls.children.length-1];
var adjx = (dirmult[0]*adj), adjy = (dirmult[1]*adj);
wall.scale.x += adjx/wall.size; wall.scale.y += adjy/wall.size;
this.resetCurrWallSegment(tocurrpos,0,true);
wall.scale.x -= adjx/wall.size; wall.scale.y -= adjy/wall.size;
}*/
resetCurrWallSegment(tocurrpos=false,offset=0,breakWallLength=false) //! Redoes the current 3D wall segment to the actual wall segment.
{
if(this.walls.children.length == 0) return;
var wmap = this.walls.map;
var oldwall = this.walls.children[this.walls.children.length-1];
if(breakWallLength)
{
var sizex = oldwall.scale.x*oldwall.size,sizey = oldwall.scale.y*oldwall.size;
this.walls.netLength -= Math.sqrt((sizex*sizex)+(sizey*sizey));
}
if(typeof(wmap[wmap.length-3]) == "undefined")
{
console.warn("Wall was undefined when trying to calculate wall size");
//console.log();
return;
}
if(tocurrpos)
{
wmap[wmap.length-2] = [this.position.x,this.position.y,this.position.z];
}
var a = 2+offset, b=1+offset;
oldwall.position.set(wmap[wmap.length-a][0],wmap[wmap.length-a][1],wmap[wmap.length-3][2]||0);
oldwall.scale.x = (wmap[wmap.length-b][0]-wmap[wmap.length-a][0])/oldwall.size||1;
oldwall.scale.y = (wmap[wmap.length-b][1]-wmap[wmap.length-a][1])/oldwall.size||1;
if(breakWallLength)
{
var sizex = oldwall.scale.x*oldwall.size,sizey = oldwall.scale.y*oldwall.size;
this.walls.netLength += Math.sqrt((sizex*sizex)+(sizey*sizey));
}
else
{
this.calcWallLength();
}
}
calcWallLength(cycle) //! sets the actual wall length
{
var wmap = this.walls.map;
this.walls.netLength = 0;
for(var x=wmap.length;x>=0;x--)
{
if(wmap[x+1] !== undefined)
{
var p1=wmap[x],p2=wmap[x+1];
this.walls.netLength += pointDistance(p1[0],p1[1],p2[0],p2[1]);
}
}
return this.walls.netLength;
}
resetWall(full=true) //! Completely redoes the 3D wall according to the actual wall
{
if(full === true)
{
for(var x=0,len=this.walls.children.length;x<len;x++)
{
this.walls.remove(this.walls.children[x]);
}
}
var wmap = this.walls.map, wallmod;
for(var x=1,len=wmap.length;x<len;x++)
{
if(full === true)
{
this.walls.add(wallmod = newWall(this.tailColor,wmap[x-1][0],wmap[x-1][1],wmap[x-1][2]));
}
else
{
wallmod = this.walls.children[x-1];
if(wallmod == undefined) break;
wallmod.position.set(wmap[x-1][0],wmap[x-1][1],wmap[x-1][2]||0);
}
wallmod.scale.x = (wmap[x][0]-wmap[x-1][0])/wallmod.size;
wallmod.scale.y = (wmap[x][1]-wmap[x-1][1])/wallmod.size;
}
if(full !== true)
{
for(;x<this.walls.length;x++)
{
this.walls.remove(this.walls.children[x]);
}
}
this.calcWallLength();
}
turn(dir)
{
if(dir != -1 && dir != 1) return false;
this.turnQueue.push(dir);
}
turnAbs(dirX,dirY)
{
var ang = Math.atan2(this.position.y+dirY,this.position.x+dirX);
centerMessage(ang,500);
if(ang > Math.PI)
{
return this.turn(1);
}
else if(ang != 0)
{
return this.turn(-1);
}
}
spawn(cfg,respawn=true,update=true)
{
//configure cycle
this.softReset();
this.position.set(cfg.x,cfg.y,cfg.z);
this.lastpos = this.position.clone();
this.rotation.set(0,0,cfg.dir);
this.lastdir = {front:0};
this.alive = true;
this.speed = settings.CYCLE_START_SPEED;
this.gameTime = this.spawntime = Math.max(0,engine.gtime);
this.haswall = !(respawn||settings.CYCLE_FIRST_SPAWN_PROTECTION);
//walls
if(this.haswall)
{
this.walls = createWall(this,cfg.x,cfg.y,cfg.z);
engine.scene.add(this.walls);
}
if(this.audio) this.audio.panner.connect(ctx.destination);
engine.scene.add(this);
if(update) updateScoreBoard();
if(this == engine.players[engine.activePlayer]) engine.viewTarget = engine.activePlayer;
}
kill()
{
this.resetCurrWallSegment();
this.alive = false; this.dedtime = performance.now();
engine.scene.remove(this);
if(this == engine.players[engine.viewTarget] && !engine.dedicated)
setTimeout(function(){if(!engine.players[engine.viewTarget].alive)changeViewTarget()},3000);
if(this.audio)
{
this.audio.panner.disconnect();
playSound(bufferLoader.bufferList[this.engineType+6],0.5,1,false,ctx.destination);
spawnExplosion(this.position,this.cycleColor,this.tailColor);
}
updateScoreBoard();
if(engine.dedicated)
{
var alive = 0, aliveAI = 0;
for(var x=engine.players.length-1;x>=0;--x) if(engine.players[x])
{
if(engine.players[x].alive)
{
alive++;
if(engine.players[x].AI) aliveAI++;
}
}
if(alive==aliveAI) changeViewTarget(0); //this will handle the finish type stuff
}
}
killAt(position,y=false,z=false)
{
if(y !== false) var x = position;
else var x=position.x,y=position.y,z=position.z;
this.position.set(x,y,z===false?this.position.z:z);
this.kill();
}
killIn(timestep)
{
this.update(timestep);
this.kill();
}
doChat(msg)
{
if(engine.network)
{
engine.connection.send(JSON.stringify({type:"chat",data:msg}));
}
else
{
engine.console.print(this.getColoredName()+"0xffff7f: "+msg+"\n");
if(engine.dedicated) {}
}
}
update(timestep=false) //! Simulates game movement on cycles
{
if(timestep === false) { timestep = (engine.gtime-this.gameTime)/1000; if(timestep < 0) return; }
this.gameTime += timestep*1000;
//var timeElapsed = engine.gtime;
var timeElapsed = this.gameTime;
//movement
var acceleration = 0;
if(this.braking)
{
if(this.brakes > 0)
{
acceleration -= settings.CYCLE_BRAKE;
this.brakes -= timestep*settings.CYCLE_BRAKE_DEPLETE;
}
}
else if(this.brakes < 1)
{
this.brakes += timestep*settings.CYCLE_BRAKE_REFILL;
}
if(this.brakes > 1) this.brakes = 1;
else if(this.brakes < 0) this.brakes = 0;
if(this.boosting)
acceleration += settings.CYCLE_BOOST;
if(this.speed < settings.CYCLE_SPEED)
{
acceleration += (settings.CYCLE_SPEED-this.speed)*settings.CYCLE_SPEED_DECAY_BELOW;
}
else if(this.speed > settings.CYCLE_SPEED)
{
acceleration += (settings.CYCLE_SPEED-this.speed)*settings.CYCLE_SPEED_DECAY_ABOVE;
}
if(this.sensor.left < settings.CYCLE_WALL_NEAR || this.sensor.right < settings.CYCLE_WALL_NEAR)
{
var wallAccel = settings.CYCLE_ACCEL;
if(wallAccel != 0) //don't bother if there's no accel
{
var accelMult = [(settings.CYCLE_WALL_NEAR-this.sensor.left)/settings.CYCLE_WALL_NEAR,(settings.CYCLE_WALL_NEAR-this.sensor.right)/settings.CYCLE_WALL_NEAR];
var accelTargets = [this.sensor.lnearestobj,this.sensor.rnearestobj];
for(var z=2;z--;)
{
if(accelMult[z] > 0)
{
if(accelTargets[z] == "rim")
{
wallAccel *= settings.CYCLE_ACCEL_RIM;
}
else if(typeof(accelTargets[z]) == "object")
{
if(accelTargets[z] == this)
{
wallAccel *= settings.CYCLE_ACCEL_SELF;
}
else
{
wallAccel *= settings.CYCLE_ACCEL_ENEMY;
}
}
else
{
throw "Accel target is unknown.";
}
wallAccel *= accelMult[z];
}
}
//console.log(wallAccel);
acceleration += wallAccel;
}
}
this.speed += acceleration*timestep;
if(this.speed < settings.CYCLE_SPEED*settings.CYCLE_SPEED_MIN)
{
this.speed = settings.CYCLE_SPEED*settings.CYCLE_SPEED_MIN;
}
if(settings.CYCLE_SPEED_MAX != 0 && this.speed > settings.CYCLE_SPEED*settings.CYCLE_SPEED_MIN)
{
this.speed = settings.CYCLE_SPEED*settings.CYCLE_SPEED_MAX;
}
this.accel = acceleration;
if(this.speed < 0) this.speed = 0;
//wheel spin per player
if(!engine.dedicated)
{
this.model.children[1].rotation.y += (deg2rad(this.model.rotaon.front * this.speed) * timestep);//0.5x wheel size
this.model.children[2].rotation.y += (deg2rad(this.model.rotaon.back * this.speed) * timestep);
}
//collision test
var dir = cdir(this.rotation.z);
var posx = this.position.x, posy = this.position.y;
var escape = false;
if(posx+settings.ARENA_BOUNDARY > engine.logicalBox.max.x*engine.REAL_ARENA_SIZE_FACTOR)
{
escape = true;
this.position.x = (engine.logicalBox.max.x*engine.REAL_ARENA_SIZE_FACTOR)-settings.ARENA_BOUNDARY;
}
if(posy+settings.ARENA_BOUNDARY > engine.logicalBox.max.y*engine.REAL_ARENA_SIZE_FACTOR)
{
escape = true;
this.position.y = (engine.logicalBox.max.y*engine.REAL_ARENA_SIZE_FACTOR)-settings.ARENA_BOUNDARY;
}
if(posx-settings.ARENA_BOUNDARY < engine.logicalBox.min.x*engine.REAL_ARENA_SIZE_FACTOR)
{
escape = true;
this.position.x = (engine.logicalBox.min.x*engine.REAL_ARENA_SIZE_FACTOR)+settings.ARENA_BOUNDARY;
}
if(posy-settings.ARENA_BOUNDARY < engine.logicalBox.min.y*engine.REAL_ARENA_SIZE_FACTOR)
{
escape = true;
this.position.y = (engine.logicalBox.min.y*engine.REAL_ARENA_SIZE_FACTOR)+settings.ARENA_BOUNDARY;
}
/*var collided = false;
for(var y=0; y<engine.map.walls.length;y++)
{
for(var i=0;i<engine.map.walls[y].length;i++)
{
var p = engine.map.walls[y][i].split(",");
var w1x = p[0],w1y = p[1];
if(engine.map.walls[y][i+1] !== undefined)
{
var p = engine.map.walls[y][i+1].split(",");
var w2x = p[0],w2y = p[1];
if(lineIntersect(posx,posy,posx+(dir[0]/4),posy+(dir[1]/4),w1x,w1y,w2x,w2y))
{
//console.log("Hitting wall");
collided = true;
}
}
}
}*/
var collided = (this.sensor.front <= this.minDistance.front); //potential replacement for above code
//var collided = false;
/*if(collided || (escape && settings.ARENA_BOUNDARY_KILLS))
{
this.collidetime = Infinity; //we've collided, no need to check
}
else*/
{
//var newx = dir[0]*this.speed*timestep, newy = dir[1]*this.speed*timestep;
var dist = this.speed*timestep, radj = dist;
if(dist < 0) dist = 0;
if(this.collidetime <= timeElapsed)
{
//this.rubber += timestep*(this.lastSpeed);
collided = true;
var adjdist = (((timeElapsed-this.collidetime)/1000)*this.lastSpeed);
radj = timestep;
//radj = adjdist;
radj *= this.lastSpeed;
dist -= adjdist;
//console.warn(x+" should have collided: "+(this.collidetime-timeElapsed)+"ms\n");
}
//if((dir[0]==0?0:(newx/dir[0]))+(dir[1]==0?0:(newx/dir[1])) >= this.sensor.front)
if(dist >= this.sensor.front-(this.minDistance.front))
//if(this.speed*timestep >= this.sensor.front)
{
dist = (this.sensor.front-(this.minDistance.front));
//if(x == engine.viewTarget) console.warn(dist+" "+this.sensor.front+"\n");
collided = true;
}
if(dist > this.sensor.front-(this.minDistance.front)) //shouldn't happen
{
dist = this.minDistance.front;
}
if(collided || (escape && settings.ARENA_BOUNDARY_KILLS))
{
if(this.rubber >= settings.CYCLE_RUBBER)
{
if(!engine.network)
{
doDeath(this,escape);
}
}
else if(
(settings.CYCLE_RUBBER_DEPLETE_RIM && this.sensor.nearestobj == "rim") ||
(settings.CYCLE_RUBBER_DEPLETE_SELF && this.sensor.nearestobj == this) ||
(settings.CYCLE_RUBBER_DEPLETE_ENEMY && this.sensor.nearestobj != this && typeof(this.sensor.nearestobj) == "object")
)
{
this.rubber += radj;
}
}
var move2d = Math.cos(this.model.rotation.y), movez = -this.model.rotation.y;
var dist2d = dist*move2d;
var newx = dist2d*dir[0], newy = dist2d*dir[1], newz = dist*movez;
this.position.x += newx;
this.position.y += newy;
this.position.z += newz;
if(this.newPos)
{
this.newPos.x += newx;
this.newPos.y += newy;
}
if(this.position.z-this.sensor.bottom < this.model.rotation.y)
{
this.model.rotation.y = this.position.z;
if(this.model.rotation.y < 0)
{
this.model.rotation.y = 0;
this.position.z = this.sensor.bottom;
}
}
if(this.position.z > this.sensor.bottom)
{
this.model.rotation.y += timestep*(1-this.model.rotation.y);
}
//if(typeof(this.walls.children) != "undefined")
if(this.haswall)
{
var wallmod = this.walls.children[this.walls.children.length-1];
var wallmap = this.walls.map[this.walls.map.length-1];
wallmap[0]+=(newx); wallmap[1]+=(newy);
wallmod.scale.x += newx/wallmod.size;
wallmod.scale.y += newy/wallmod.size;
this.walls.netLength += dist;
this.sensor.front -= dist; //assume distance until we have new real results.
//this.sensor.front =
var lendiff = this.walls.netLength - settings.WALLS_LENGTH;
while(settings.WALLS_LENGTH > 0 && lendiff > 0)
{
var map = this.walls.map;
var xdir = (map[1][0]-map[0][0]), ydir = (map[1][1]-map[0][1]);
var len = Math.sqrt((xdir*xdir)+(ydir*ydir));
if(len > 1) { xdir /= len; ydir /= len; }
if(isNaN(xdir)) xdir = SMALL_NUM; if(isNaN(ydir)) ydir = SMALL_NUM;
//console.log(lendiff,xdir,ydir);
if(xdir == 0 && ydir == 0 && this.walls.map.length > 2)
{
//this.walls.children.shift();
this.walls.remove(this.walls.children[0]);
this.walls.map.shift();
}
else
{
this.walls.children[0].scale.x -= xdir/wallmod.size;
this.walls.children[0].position.x += xdir;
this.walls.children[0].scale.y -= ydir/wallmod.size;
this.walls.children[0].position.y += ydir;
this.walls.map[0][0] += xdir;
this.walls.map[0][1] += ydir;
this.walls.netLength -= Math.sqrt((xdir*xdir)+(ydir*ydir));
}
lendiff = this.walls.netLength - settings.WALLS_LENGTH;
}//*/
if(this.position.z > 0) this.newWallSegment();
}
else if(engine.gtime > this.spawntime+(settings.CYCLE_WALL_TIME*1000))
{
this.walls = createWall(this,this.position.x,this.position.y,this.position.z);
engine.scene.add(this.walls);
this.haswall = true;
}
this.collidetime = timeElapsed+(((this.sensor.front-this.minDistance.front)/this.speed)*1000);
this.lastSpeed = this.speed;
}
if(this.speed > engine.fastestSpeed)
{
engine.fastestPlayer = this; engine.fastestSpeed = this.speed;
}
}
constructor(cfg)
{
super();
//var dir = cdir(cfg.dir);
//this.cfg = cfg;//carry over the cfg???
//choose model
this.model = cycleModel(cfg.cycleColor);
this.add(this.model);
//this.shadow = cycleShadow();
//this.add(this.shadow);
this.chatarrow = newChatArrow();
this.chatarrow.position.z = 1.20;
this.chatarrow.position.x -= 0.5;
this.chatarrow.scale.set(0.25,0.25,0.25);
this.add(this.chatarrow);
this.cycleColor = cfg.cycleColor;
this.tailColor = cfg.tailColor;
/*this.walls = {};
//this.walls.children = [];
this.walls.netLength = 0;
this.walls.map = [];
this.walls.scale = this.walls.position = new THREE.Vector3();*/
this.walls = createWall(this,0,0,0); //walls are still called upon when spectating
this.chatting = cfg.chatting||false; this.spectating = cfg.spectating||false;
if(cfg.ai||settings.DEBUG_EVERYONE_IS_AI)
{
this.AI = new AI(this);
}
else
{
this.AI = false;
}
// this.playerID = cfg.playerID;
this.name = cfg.name;
- this.team = null;
+ this.team = cfg.team;
this.hardReset();
//audio creation
this.engineType = cfg.engineType;
if(ctx)
{
this.audio = ctx.createGain();
this.audio.gain.value = 0.01;
this.audio.panner = ctx.createPanner();
if(engine.retroSound)
this.audio.panner.panningModel = "HRTF";
else
this.audio.panner.panningModel = "equalpower";
this.audio.connect(this.audio.panner);
this.audio.panner.connect(ctx.destination);
//audio initialization
this.engineSound = playSound(bufferLoader.bufferList[this.engineType], 0.5, 0, true, this.audio);
this.audio.gain.setTargetAtTime(6, ctx.currentTime, 1.0);
}
}
};
if(typeof(module) != "undefined") module.exports = Player;

File Metadata

Mime Type
text/x-diff
Expires
Sun, Aug 3, 1:25 AM (1 w, 1 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
10855

Event Timeline