The online racing simulator
Nauseacam - PHP camera motion script
I know a similar program has been done better in a different language (Camlevel), but I did this for practice anyhow. I am not a programmist, I don't know how to write clean code, script is provided as is, no support, etc. PHP module php_sockets must be enabled.

Nauseacam is a PHP script that uses InSim and OutSim to adjust (exaggerate) camera motion. Works in in-car view and own car only in single player, multiplayer and SPR.

Standard look-to-side buttons do not work while the script is in operation, but there is a workaround:
- assign /o nc_left and /o nc_right to chat binds to use those keys to look to the side.

Demo video: http://www.youtube.com/watch?v=in4MkHxsCHo&hd=1

<?php

// Nauseacam, feel motion sickness like a boss.
// Version: 0.1.1
// Date: 09-Oct-13

/* Assign "/o nc_left" and "/o nc_right" to chat binds to use for looking to the sides */

// Connection settings. OutSim does NOT need to be enabled in cfg.txt.
$ip = '127.0.0.1';
$insim = 29999;
$outsim = 30000;
$admin = 'nimda';

// Smoothness settings
$ointerval = 2; // Receive camera packets every X ms. Decrease for smoothness. Default: 2.
$pinterval = 2000; // Main loop (socket) polling time-out in us. Too low value may hurt CPU usage. Default: 2000.
$cinterval = 200; // Time taken in ms to reach new camera angle. Increase for smoothness. Default: 200.

// Camera settings
$looktime = 60; // Time in ms to reach maximum side look angle. Default: 60.
$lookangle = 10000; // 10000 is ~45 degrees. Default: 10000.
// These affect the amount of camera movement
$pitchmult = 8000; // See insim.txt. Default: 8000.
$rollmult = 10000; // See insim.txt. Default: 10000.
$accelzmult = 100; // See insim.txt. Default: 100.


/* Code starts here */


// Create InSim socket
if( !($tsock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) ) {
die('Could not create InSim socket. Already in use?');
}

// Connect InSim socket
if(!socket_connect($tsock, $ip, $insim)) {
die('Could not connect to InSim');
}

socket_set_nonblock($tsock);

// Create OutSim socket
if( !($usock = stream_socket_server("udp://$ip:$outsim", $errno, $errstr, STREAM_SERVER_BIND)) ) {
die('Could not create OutSim socket. Already in use?');
}

stream_set_read_buffer($usock, 512);
stream_set_blocking($usock, false);

// Init InSim and send initial STA
socket_write($tsock, pack('CCCCSSCCSa16a16', 44, 1, 0, 0, $outsim, 0, 0, NULL, 0, $admin, 'ncam'));
socket_write($tsock, pack('CCCC', 4, 3, 1, 7));

$pingtimer = microtime(true);
$camtimer = microtime(true);
$enabled = 0;
$lookside = 0;
$udp = 0;

while(1) {
if($lookside) $lookside--;

// Receive OutSim packets
if($buf = fread($usock, 512)) {
$udp = unpack('Ltime/fangvelx/fangvely/fangvelz/fheading/fpitch/froll/faccelx/faccely/faccelz/fvelx/fvely/fvelz/iposx/iposy/iposz', $buf);
}

// InSim keep-alive
if( (microtime(true) - $pingtimer) >= 30) {
socket_write($tsock, pack('CCCC', 4, 3, 0, 0));
$pingtimer = microtime(true);
}

// Receive InSim packets
while($data = socket_read($tsock, 4)) {
$header = unpack('Csize/Ctype/Creqi/Cdata', $data);
$data = socket_read($tsock, $header['size'] - 4);

switch($header['type']) {
case 5: // sta
$sta = unpack('freplayspeed/Sflags/Cingamecam/Cviewplid', $data);

// Turn OutSim off when we don't need it
if($sta['ingamecam'] == 3 && ($sta['flags'] & 0x1 || $sta['flags'] & 0x2) ) {
if(!$enabled) {
$enabled = 1;
socket_write($tsock, pack('CCCCI', 8, 4, 0, 1, $ointerval));
}

} else {
if($enabled) {
$enabled = 0;
socket_write($tsock, pack('CCCCI', 8, 4, 0, 1, 0));
}
}

break;

// Normal look keys don't work. Hack fix: chat binds are used to send silent look commands.
case 11: //mso
$mso = unpack('Cucid/Cplid/Cusertype/Ctextstart/a128message', $data);

if($mso['usertype'] == 3) {
if(substr($mso['message'], 0, 7) == 'nc_left') {
$lookside = $looktime;
socket_write($tsock, pack('CCCCiiiSSSCCfSS', 32, 9, 0, 0, 0, 0, 0, $lookangle, 0, 0, 0, 255, 0, $looktime, 8192));

} else if(substr($mso['message'], 0, 8) == 'nc_right') {
$lookside = $looktime;
socket_write($tsock, pack('CCCCiiiSSSCCfSS', 32, 9, 0, 0, 0, 0, 0, -$lookangle, 0, 0, 0, 255, 0, $looktime, 8192));
}
}

break;
}
}

// Handle game/InSim exit
if(socket_last_error($tsock) == 10053 || socket_last_error($tsock) == 10054) break;

// Send camera packets
if( (microtime(true) - $camtimer >= 0.2) && $enabled) {
if(!$lookside) {
socket_write($tsock, pack('CCCCiiiSSSCCfSS', 32, 9, 0, 0, 0, 0, 0, 0, (-round($udp['pitch']*$pitchmult)) + (-round($udp['accelz']*$accelzmult)), -round($udp['roll']*$rollmult), 255, 255, 0, $cinterval, 8192));
$camtimer = microtime(true);
}
}

usleep($pinterval);
}

echo "Lost connection to InSim. Bye, bye.\r\n";

@socket_close($tsock);
@socket_close($usock);

?>

Download: http://www.mediafire.com/?c6dr56oiapg46mq

e: video link fixed, added camlevel link.
I've only watched the preview video and it looks pretty good, I'll definitely give it a go when I get to my PC
The code looks alright for being completely procedural

FGED GREDG RDFGDR GSFDG