Welcome, Please Register or Login

Search Tags

  1. Vehicle physics lab
    Sections: Downloads \ Street Legal Racing: Redline \ Tools
    Tags: Physics, Tool

    Hey. I have created this tool for guys who messing around game's vehicle physic settings. It provides you interface where you can modify car wheels, suspension and pacejka in real time and see the changes immediately.



    I also implemented saving and loading setup files, so you will be able to exchange them together, or just save your own creations.
    Saved settings will be stored in [Game dir]\maps\Addon_Maps\Physic_Lab

    How to install: Copy code below and save is as Physic_Lab_Track.java file in [Game dir]\maps\Addon_Maps\Physic_Lab\scripts\src directory. Yes, you need MWM already installed to do that.

    Then just run the game and go to the Physics Lab track.

    This tool is just for tests and experiments to obtain knowledge about meaning of setup parameters. It is not game editor. If you don't know what to do with it then don't use it.

    The code:

    package java.game;
    import java.io.*;
    import java.util.*;
    import java.util.resource.*;
    import java.game.*;
    import java.render.*;	//Text
    import java.render.osd.*;	//Text
    import java.sound.*;
    import java.render.osd.dialog.*; //Dialog Window
    
    import java.game.parts.*;
    import java.game.parts.enginepart.*;
    
    public class Physic_Lab_Track extends Track
    {	
    	final static String MapName = "Physics Lab";
    	final static String MapDescription = " Developer tool for experimenting \n with vehicle physics.";
    	final static String MapAuthor = "Author: Miran";
    	final static ResourceRef MapImage = new ResourceRef(Maps.Addon_Maps.Physic_Lab:0x0DC2r);
    	final static float	TS_Version = 1.0; // Do not change it!
    
    	String savePath = "maps/Addon_Maps/Physic_Lab/";
    	int saveFileHeader = 0x589363;
    
    	int infolineCount = 16;
    	Button[] infolines = new Button[infolineCount];
    
    	int sliderParamCount = 19;
    	Slider[] slidersParam = new Slider[sliderParamCount];
    	Slider sldRadius, sldWidth, sldPatch1, sldPatch2, sldPatch3, sldFriction, sldFrictionX, sldSliction, sldStiffness, sldRollRes, sldBearing, sldMaxLoad, sldLoadSmooth, sldForce, sldDamping1, sldDamping2, sldRestLen, sldMinLen, sldMaxLen;
    
    	int sliderPacejkaCount = 17;
    	Slider[] slidersPacejka = new Slider[sliderPacejkaCount];
    	int grMain, grPacejka, grParams, grEmpty;
    
    	static int			CMD_END = 200;
    	final static int	CMD_MAIN	 = CMD_END++;
    	final static int	CMD_PARAMS = CMD_END++;
    	final static int	CMD_PACEJKA = CMD_END++;
    	final static int	CMD_HIDE = CMD_END++;
    	final static int	CMD_RESET_CAR = CMD_END++;
    	final static int	CMD_FLIP_CAR = CMD_END++;
    	final static int	CMD_CHANGE_CAR = CMD_END++;
    	final static int	CMD_LOAD = CMD_END++;
    	final static int	CMD_SAVE = CMD_END++;
    
    	final static int	CMD_APPLY_PARAMS = CMD_END++;
    	final static int	CMD_APPLY_PACEJKA = CMD_END++;
    
    	final static int	CMD_RADIUS_SLIDER = CMD_END++;
    	final static int	CMD_WIDTH_SLIDER = CMD_END++;
    	final static int	CMD_CP1_SLIDER = CMD_END++;
    	final static int	CMD_CP2_SLIDER = CMD_END++;
    	final static int	CMD_CP3_SLIDER = CMD_END++;
    	final static int	CMD_FRICTION_SLIDER = CMD_END++;
    	final static int	CMD_FRICTIONX_SLIDER = CMD_END++;
    	final static int	CMD_SLICTION_SLIDER = CMD_END++;
    	final static int	CMD_STIFFNESS_SLIDER = CMD_END++;
    	final static int	CMD_ROLLRES_SLIDER = CMD_END++;
    	final static int	CMD_BEARING_SLIDER = CMD_END++;
    	final static int	CMD_MAXLOAD_SLIDER = CMD_END++;
    	final static int	CMD_LOADSMOOTH_SLIDER = CMD_END++;
    	final static int	CMD_FORCE_SLIDER = CMD_END++;
    	final static int	CMD_DAMPING1_SLIDER = CMD_END++;
    	final static int	CMD_DAMPING2_SLIDER = CMD_END++;
    	final static int	CMD_MINLEN_SLIDER = CMD_END++;
    	final static int	CMD_RESTLEN_SLIDER = CMD_END++;
    	final static int	CMD_MAXLEN_SLIDER = CMD_END++;
    
    	final static int	CMD_PAC_SLIDER = 400;
    
    	public Physic_Lab_Track()
    	{
    		/*posStart = new Vector3( -520.000, 0.000, 390.000 );
    		oriStart = new Ypr( -1.4, 0.0, 0.0 );
    		map = new GroundRef( Maps.Addon_Maps.Top_Gear_Track:0x0001r );
    		nav = new Navigator( 1.922, -1.472, 1.0, Maps.Addon_Maps.Top_Gear_Track:0x0036r, Maps.Addon_Maps.Top_Gear_Track:0x0034r, Maps.Addon_Maps.Top_Gear_Track:0x0035r, 1, 1, 0 );	
    		//*/
    
    		posStart = new Vector3( 300.0, 1.500, -477.000 );
    		oriStart = new Ypr( -0.5, 0.0, 0.0 );
    		map = new GroundRef( maps.ROC_track:0x00000001r );
    		nav = new Navigator( -17.1137, -26.6, 4.9404, maps.ROC_Track.smallmap:0x00000001r, maps.ROC_Track.smallmap:0x00000002r, maps.ROC_Track.smallmap:0x00000005r, 8, 8, 8 );
    		//*/
    		
    
    		GPS_Min_Zoom = 4; 
    		GPS_Max_Zoom = 8;
    	}
    
    	public void StartMap()
    	{ // Track selector run this void when you click "TAKE IT"
    		GameLogic.changeActiveSection( new Physic_Lab_Track() );
    	}
    
    	public void enter( GameState prev_state )
    	{
    		Frontend.loadingScreen.show();
    		GfxEngine.flush();
    
    		super.enter( prev_state );
    
    		enableOsd( 0 ); // hide gauges and ect.
    
    		Input.cursor.enable(1);
    		osd.globalHandler = this;
    		osd.menuKeysCreated = 1;
    
    		Style btnImg = new Style( 0.06, 0.06, Frontend.smallFont, Text.ALIGN_CENTER, null );
    		Style btnSC = new Style( 0.22, 0.08, Frontend.smallFont, Text.ALIGN_CENTER, new ResourceRef(frontend:0x00D8r) );
    		Style btnMC = new Style( 0.6, 0.1, Frontend.mediumFont, Text.ALIGN_CENTER, new ResourceRef(frontend:0x00D8r) );
    		
    		Style sliderStyle, sld1;
    		Style sldk =  new Style( 0.05, 0.05, Frontend.mediumFont, Text.ALIGN_RIGHT, new ResourceRef(Osd.RID_SLD_KNOB) );
    		Menu m;
    
    	// top menu
    		osd.createRectangle( 0.0, -0.96, 2.0, 0.08, -1, new ResourceRef(frontend:0x0028r) );
    
    		osd.createText( "PHYSICS LAB - Miran", Frontend.smallFont, Text.ALIGN_LEFT, -0.98,  -0.98 );
    
    		m = osd.createMenu( btnSC, -0.5, -0.96, 0, Osd.MD_HORIZONTAL );
    		m.addItem( "Main", CMD_MAIN );
    		m.addItem( "Params", CMD_PARAMS );
    		m.addItem( "Pacejka", CMD_PACEJKA );
    		m.addItem( "Hide", CMD_HIDE );
    		m.addSeparator();
    		
    		m.addItem( "Vehicle:", CMD_FLIP_CAR ).disable();
    		m.addItem( "Flip", CMD_FLIP_CAR );
    		m.addItem( "Reset", CMD_RESET_CAR );
    		m.addItem( "Change", CMD_CHANGE_CAR );
    
    	// main group
    		grMain = osd.beginGroup();
    
    		m = osd.createMenu( btnMC, -0.8, -0.85, 0, Osd.MD_HORIZONTAL );
    		m.addItem( "Load settings", CMD_LOAD );
    		m.addItem( "Save settings", CMD_SAVE );
    
    		m = osd.createMenu( btnSC, 0.0, -0.75, 0 );
    		for( int i=0; i<infolineCount; i++ )
    		{
    			infolines[i] = m.addItem( "", CMD_END );
    			
    			infolines[i].disable();
    			infolines[i].label.txt.changeColor( Osd.COLOR_UNSELECTED );
    		}
    
    		osd.hideGroup( grMain );
    
    	// params group
    		grParams = osd.beginGroup();
    
    		sliderStyle = new Style( 0.05, 0.08, Frontend.smallFont, Text.ALIGN_LEFT, null );
    		m = osd.createMenu( sliderStyle, -0.7, -0.85, 0 );
    
    		sld1 = new Style( 1.7, 0.007, Frontend.mediumFont, Text.ALIGN_LEFT, new ResourceRef(frontend:0x0028r/*Osd.RID_SLD_BACK*/) );
    		m.setSliderStyle( sld1, sldk );
    
    		slidersParam[0] = sldRadius = m.addItem( "Radius", CMD_RADIUS_SLIDER, Math.sqrt(0.27), 0, Math.sqrt(2), 0, null );
    		slidersParam[1] = sldWidth = m.addItem( "Width", CMD_WIDTH_SLIDER, Math.sqrt(0.14), 0, Math.sqrt(2), 0, null );
    		m.addItem( "C Patch:", CMD_END ).disable();
    		slidersParam[2] = sldPatch1 = m.addItem( "Half Width", CMD_CP1_SLIDER, Math.sqrt(0.07), -Math.sqrt(4), Math.sqrt(4), 0, null );
    		slidersParam[3] = sldPatch2 = m.addItem( "Angle", CMD_CP2_SLIDER, Math.sqrt(0.2), -Math.sqrt(4), Math.sqrt(4), 0, null );
    		slidersParam[4] = sldPatch3 = m.addItem( " Offset", CMD_CP3_SLIDER, 0, -Math.sqrt(4), Math.sqrt(4), 0, null );
    		m.addSeparator();
    		slidersParam[5] = sldFriction = m.addItem( "Friction", CMD_FRICTION_SLIDER, Math.sqrt(2), -Math.sqrt(6), Math.sqrt(6), 0, null );
    		slidersParam[6] = sldFrictionX = m.addItem( "Friction X", CMD_FRICTIONX_SLIDER, Math.sqrt(1), -Math.sqrt(6), Math.sqrt(6), 0, null );
    		slidersParam[7] = sldSliction = m.addItem( "Sliction", CMD_SLICTION_SLIDER,  Math.sqrt(1), -Math.sqrt(6), Math.sqrt(6), 0, null );
    		slidersParam[8] = sldStiffness = m.addItem( "Stiffness", CMD_STIFFNESS_SLIDER,  Math.sqrt(50), 0, Math.sqrt(1000), 0, null );
    		slidersParam[9] = sldRollRes = m.addItem( "RollRes", CMD_ROLLRES_SLIDER, 0.1, 0, Math.sqrt(15), 0, null );
    		slidersParam[10] = sldBearing = m.addItem( "Bearing", CMD_BEARING_SLIDER, Math.sqrt(8),  0, Math.sqrt(1000), 0, null );
    		slidersParam[11] = sldMaxLoad = m.addItem( "MaxLoad", CMD_MAXLOAD_SLIDER, Math.sqrt(10000), Math.sqrt(0), Math.sqrt(100000), 0, null );
    		slidersParam[12] = sldLoadSmooth = m.addItem( "LdSmooth", CMD_LOADSMOOTH_SLIDER, Math.sqrt(0.5), -Math.sqrt(4), Math.sqrt(4), 0, null );
    		slidersParam[13] = sldForce = m.addItem( "Force", CMD_FORCE_SLIDER, Math.sqrt(100000), Math.sqrt(100), Math.sqrt(500000), 0, null );
    		m.addItem( "Damping:", CMD_END ).disable();
    		slidersParam[14] = sldDamping1 = m.addItem( "Bound", CMD_DAMPING1_SLIDER, Math.sqrt(2500), Math.sqrt(100), Math.sqrt(100000), 0, null );
    		slidersParam[15] = sldDamping2 = m.addItem( "Rebound", CMD_DAMPING2_SLIDER, Math.sqrt(2500), Math.sqrt(100), Math.sqrt(100000), 0, null );
    		m.addSeparator();
    		slidersParam[16] = sldMinLen = m.addItem( "MinLen", CMD_MINLEN_SLIDER, Math.sqrt(0.05), -Math.sqrt(1), Math.sqrt(1), 0, null );
    		slidersParam[17] = sldRestLen = m.addItem( "RestLen", CMD_RESTLEN_SLIDER, Math.sqrt(0.28), -Math.sqrt(1), Math.sqrt(1), 0, null );
    		slidersParam[18] = sldMaxLen = m.addItem( "MaxLen", CMD_MAXLEN_SLIDER, Math.sqrt(0.38), -Math.sqrt(1), Math.sqrt(1), 0, null );
    
    		m = osd.createMenu( btnMC, 0.0, 0.92, 0, Osd.MD_HORIZONTAL );
    		m.addItem( "Apply all params to the car", CMD_APPLY_PARAMS );
    
    		osd.hideGroup( grParams );
    
    	// pacejka group
    		grPacejka = osd.beginGroup();
    
    		sliderStyle = new Style( 0.05, 0.1, Frontend.smallFont, Text.ALIGN_LEFT, null );
    		m = osd.createMenu( sliderStyle, -0.85, -0.85, 0 );
    
    		sld1 = new Style( 1.8, 0.007, Frontend.mediumFont, Text.ALIGN_LEFT, new ResourceRef(frontend:0x0028r/*Osd.RID_SLD_BACK*/) );
    		m.setSliderStyle( sld1, sldk );
    
    		for( int i=0; i<sliderPacejkaCount; i++ )
    			slidersPacejka[i] = m.addItem( "" + i, CMD_PAC_SLIDER+i, 0, -4, 4, 0, null );
    
    		// set default values
    		setPacejkaSliderVal( 0, 0.7937006 ); // 1.0
    		setPacejkaSliderVal( 4, 2.79721590937 ); // 300
    		setPacejkaSliderVal( 8, -0.7937006 ); // -1.0
    		setPacejkaSliderVal( 11, 3.6880850 ); // 20000
    		setPacejkaSliderVal( 12, 0.7937006 ); // 1.0
    		setPacejkaSliderVal( 14, -0.7937006 ); // -1.0
    		setPacejkaSliderVal( 15, 2.3797297 ); // 80.0
    		setPacejkaSliderVal( 16, 0.7937006 ); // 1.0
    
    		m = osd.createMenu( btnMC, 0.0, 0.92, 0, Osd.MD_HORIZONTAL );
    		m.addItem( "Apply all pacejka to the car", CMD_APPLY_PACEJKA );
    		
    		osd.hideGroup( grPacejka );
    
    
    		updateInfo();
    		updateSliderLabels();
    	}
    
    	public void exit( GameState next_state )
    	{
    
    		super.exit( next_state );
    	}
    
    	public void updateInfo()
    	{
    		if( player.car && player.car.chassis )
    		{
    			infolines[0].changeLabelText( player.car.chassis.vehicleName );
    			infolines[1].changeLabelText( "Mass: " + player.car.chassis.getMass() + "kg,          1/4: " + player.car.chassis.getMass()/4 + "kg" );
    			infolines[2].changeLabelText( "Force of weight: " + Config.gravity*player.car.chassis.getMass() + "N,          1/4: " + Config.gravity*player.car.chassis.getMass()/4 + "N" );
    			//infolines[3].changeLabelText( "More..." );
    		}
    	}
    
    	public void updateSliderLabels()
    	{
    		for( int i=0; i<sliderParamCount; i++ )
    		{
    			float val = slidersParam[i].value;
    			int sign = val > 0 ? 1 : -1;
    
    			val = val*val*sign;
    
    			slidersParam[i].printValue( Float.toString(val, "%1.4f") );
    			slidersParam[i].changeVLabelColor( Osd.COLOR_UNSELECTED );
    		}
    
    		for( int i=0; i<sliderPacejkaCount; i++ )
    		{
    			float val = slidersPacejka[i].value;
    
    			if( val > 3 ||  val < -3 )
    			{
    				float x = val > 0 ? val-2 : val+2;
    				val = 512*x*x*x*x*x*x*x;
    			}
    			else
    			if( val > 2 ||  val < -2 )
    			{
    				float x = val > 0 ? val-1 : val+1;
    				val = 16*x*x*x*x*x;
    			}
    			else
    				val = 2*val*val*val;
    
    			slidersPacejka[i].printValue( Float.toString(val, "%1.4f") );
    			slidersPacejka[i].changeVLabelColor( Osd.COLOR_UNSELECTED );
    		}
    	}
    
    	public void setPacejka( int idx )
    	{
    		if( player.car && player.car.chassis )
    		{
    			float val = slidersPacejka[idx].value;
    
    			if( val > 3 ||  val < -3 )
    			{
    				float x = val > 0 ? val-2 : val+2;
    				val = 512*x*x*x*x*x*x*x;
    			}
    			else
    			if( val > 2 ||  val < -2 )
    			{
    				float x = val > 0 ? val-1 : val+1;
    				val = 16*x*x*x*x*x;
    			}
    			else
    				val = 2*val*val*val;
    
    			slidersPacejka[idx].printValue( Float.toString(val, "%1.4f") );
    			slidersPacejka[idx].changeVLabelColor( Osd.COLOR_SELECTED );
    
    			for( int i=0; i<4; i++ )
    			{
    				WheelRef w = player.car.chassis.getWheel( i );
    
    				if( w )
    						w.setPacejka( idx, val );
    			}
    		}
    	}
    
    	public void setPacejkaSliderVal( int idx, float val )
    	{
    		slidersPacejka[idx].setValue( val );
    
    		if( val > 3 ||  val < -3 )
    		{
    			float x = val > 0 ? val-2 : val+2;
    			val = 512*x*x*x*x*x*x*x;
    		}
    		else
    		if( val > 2 ||  val < -2 )
    		{
    			float x = val > 0 ? val-1 : val+1;
    			val = 16*x*x*x*x*x;
    		}
    		else
    			val = 2*val*val*val;
    
    		slidersPacejka[idx].printValue( Float.toString(val, "%1.4f") );
    	}
    
    	public void applyChanges()
    	{
    		for( int i=0; i<sliderPacejkaCount; i++ )
    					setPacejka( i );
    	}
    
    	public void handleMessage( Message m )
    	{
    		int handled = 0;
    
    		if( m.type == Message.MT_EVENT )
    		{
    			int	cmd=m.cmd;
    
    			if( cmd >= CMD_MAIN && cmd <= CMD_HIDE  )
    			{
    				osd.hideGroup( grMain );
    				osd.hideGroup( grPacejka );
    				osd.hideGroup( grParams );
    				osd.hideGroup( grEmpty );
    
    				if( cmd == CMD_MAIN ) 
    				{
    					updateInfo();
    					osd.showGroup( grMain );
    				}
    				else
    				if( cmd == CMD_PARAMS ) osd.showGroup( grParams );
    				else
    				if( cmd == CMD_PACEJKA ) osd.showGroup( grPacejka );
    				else
    				if( cmd == grEmpty ) osd.showGroup( grEmpty );
    
    				handled = 1;
    			}
    			else
    			if( cmd == CMD_LOAD  )
    			{
    				FileRequesterDialog d = new FileRequesterDialog( player.controller, Dialog.DF_FREEZE|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Load physics settings", "Load", savePath, "*.phys" );
    
    				if( d.display() == 0 )
    				{
    					String filename = savePath + d.fileName;
    
    					if( File.exists( filename ) )
    					{
    						File file = new File( filename );
    
    						if( file.open( File.MODE_READ ) )
    						{
    							if( file.readInt() == saveFileHeader ) 
    							{
    								if( file.readInt() == sliderParamCount && file.readInt() == sliderPacejkaCount )
    								{
    									for( int i=0; i<sliderParamCount; i++ )
    										slidersParam[i].setValue( file.readFloat() );
    
    									for( int i=0; i<sliderPacejkaCount; i++ )
    										slidersPacejka[i].setValue( file.readFloat() );
    
    									updateSliderLabels();
    								}
    								else
    									new WarningDialog( player.controller, Dialog.DF_HIGHPRI|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Error", "Unsupported file version!" ).display();
    							}
    							else
    								new WarningDialog( player.controller, Dialog.DF_HIGHPRI|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Error", "Corupted file!" ).display();
    
    							file.close();
    						}
    						else
    							new WarningDialog( player.controller, Dialog.DF_HIGHPRI|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Error", "Can not open the file!" ).display();
    					}
    					else
    						new WarningDialog( player.controller, Dialog.DF_HIGHPRI|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Error", "File not found!" ).display();
    				}
    			}
    			else
    			if( cmd == CMD_SAVE  )
    			{
    				FileRequesterDialog d = new FileRequesterDialog( player.controller, Dialog.DF_FREEZE|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Save physics settings", "Save", savePath, "*.phys" );
    
    				if( d.display() == 0 )
    				{
    					String filename = savePath + d.fileName;
    					
    					if( d.fileName.token( 1, "." ) != "phys" )
    						 filename += ".phys";
    
    					int ok = 1;
    
    					if( File.exists( filename ) )
    					{
    						ok = 0;
    
    						int res = new NoYesDialog(  player.controller, Dialog.DF_HIGHPRI|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Question", "Overwrite existing file?" ).display();
    						
    						if(  res == 0 )
    							ok = 1;
    					}
    
    					if( ok )
    					{
    						if( File.exists( filename ) )
    							File.delete( filename );
    
    						File file = new File( filename );
    
    						if( file.open( File.MODE_WRITE ) )
    						{
    							file.write( saveFileHeader );
    							file.write( sliderParamCount );
    							file.write( sliderPacejkaCount );
    
    							for( int i=0; i<sliderParamCount; i++ )
    								file.write( slidersParam[i].value );
    
    							for( int i=0; i<sliderPacejkaCount; i++ )
    								file.write( slidersPacejka[i].value );
    
    							file.close();
    						}
    						else
    							new WarningDialog( player.controller, Dialog.DF_HIGHPRI|Dialog.DF_MODAL|Dialog.DF_DEFAULTBG, "Error", "Can not open the file!" ).display();
    					}
    				}
    			}
    			else
    			if( cmd >= CMD_RADIUS_SLIDER &&  cmd <= CMD_MAXLEN_SLIDER )
    			{
    				int idx = cmd-CMD_RADIUS_SLIDER;
    
    				float val = slidersParam[idx].value;
    				int sign = val > 0 ? 1 : -1;
    
    				val = val*val*sign;
    
    				slidersParam[idx].printValue( Float.toString(val, "%1.4f") ); // update slider label
    				slidersParam[idx].changeVLabelColor( Osd.COLOR_SELECTED );
    
    				if( player.car && player.car.chassis )
    				{
    					for( int i=0; i<4; i++ )
    					{
    						WheelRef w = player.car.chassis.getWheel( i );
    
    						if( w )
    						{
    							if( cmd == CMD_RADIUS_SLIDER ) w.setRadius( val ); else
    							if( cmd == CMD_WIDTH_SLIDER ) w.setWidth( val ); else
    							if( cmd == CMD_FRICTION_SLIDER ) w.setFriction( val ); else
    							if( cmd == CMD_FRICTIONX_SLIDER ) w.setFrictn_x( val ); else
    							if( cmd == CMD_SLICTION_SLIDER ) w.setSliction( val ); else
    							if( cmd == CMD_STIFFNESS_SLIDER ) w.setStiffness( val ); else
    							if( cmd == CMD_ROLLRES_SLIDER ) w.setRollRes( val ); else
    							if( cmd == CMD_BEARING_SLIDER ) w.setBearing( val ); else
    							if( cmd == CMD_MAXLOAD_SLIDER ) w.setMaxLoad( val ); else
    							if( cmd == CMD_LOADSMOOTH_SLIDER ) w.setLoadSmooth( val ); else
    							if( cmd == CMD_FORCE_SLIDER ) w.setForce( val ); else
    							if( cmd == CMD_MINLEN_SLIDER ) w.setMinLen( val ); else
    							if( cmd == CMD_RESTLEN_SLIDER ) w.setRestLen( val ); else
    							if( cmd == CMD_MAXLEN_SLIDER ) w.setMaxLen( val ); else
    
    							if( cmd >= CMD_CP1_SLIDER && cmd <= CMD_CP3_SLIDER )
    							{
    								sldPatch1.changeVLabelColor( Osd.COLOR_SELECTED );
    								sldPatch2.changeVLabelColor( Osd.COLOR_SELECTED );
    								sldPatch3.changeVLabelColor( Osd.COLOR_SELECTED );
    
    								float width = sldPatch1.value * sldPatch1.value * (sldPatch1.value>0 ? 1 : -1);
    								float angle = sldPatch2.value * sldPatch2.value * (sldPatch2.value>0 ? 1 : -1);
    								float offset = sldPatch3.value * sldPatch3.value * (sldPatch3.value>0 ? 1 : -1);
    								w.setCPatch( width,  angle,  offset );
    							}
    							else
    
    							if( cmd >= CMD_DAMPING1_SLIDER && cmd <= CMD_DAMPING2_SLIDER )
    							{
    								sldDamping1.changeVLabelColor( Osd.COLOR_SELECTED );
    								sldDamping2.changeVLabelColor( Osd.COLOR_SELECTED );
    
    								float bound = sldDamping1.value * sldDamping1.value * (sldDamping1.value>0 ? 1 : -1);
    								float rebound = sldDamping2.value * sldDamping2.value * (sldDamping2.value>0 ? 1 : -1);
    								w.setDamping( bound,  rebound );
    							}
    						}
    					}
    
    					player.car.wakeUp();
    				}
    			}
    			else
    			if( cmd >= CMD_PAC_SLIDER &&  cmd <= CMD_PAC_SLIDER+sliderPacejkaCount )
    			{
    				setPacejka( cmd-CMD_PAC_SLIDER );
    				handled = 1;
    			}
    
    			if( cmd == CMD_APPLY_PARAMS  )
    			{
    				for( int i=0; i<sliderParamCount; i++ )
    					slidersParam[i].sendMessage(); // emulate click
    
    				handled = 1;
    			}
    
    			if( cmd == CMD_APPLY_PACEJKA  )
    			{
    				applyChanges();
    				handled = 1;
    			}
    
    			if( cmd == CMD_FLIP_CAR  )
    			{
    				new SfxRef( GameLogic.SFX_DRAGDROP ).play(); 
    
    				player.car.setMatrix( player.car.getPos(), new Ypr( player.car.getOri().y, 0, 0 ) );
    			}
    
    			if( cmd == CMD_RESET_CAR  )
    			{
    				if( player.car )
    				{
    					updateSliderLabels(); // reset colors
    					new SfxRef( GameLogic.SFX_DRAGDROP ).play(); 
    
    					player.car.setMatrix( player.car.getPos(), new Ypr( player.car.getOri().y, 0, 0 ) );
    					player.car.repair();
    					if( player.car.chassis )player.car.chassis.updatevariables();
    					player.car.command( "reload" );
    					player.car.command( "idle");
    					//player.car.wakeUp();
    				}
    
    				handled = 1;
    			}
    
    			if( cmd == CMD_CHANGE_CAR  )
    			{
    				updateSliderLabels(); // reset colors
    				new SfxRef( GameLogic.SFX_DRAGDROP ).play(); 
    				int old_time = System.timeWarp(-1);
    				System.timeWarp(0.0); // Pause
    
    				Vector3 CarPos = new Vector3( posStart );
    				Ypr CarYpr = new Ypr( oriStart );
    				if ( player.car )
    				{
    					CarPos = new Vector3 (player.car.getPos());
    					CarYpr = new Ypr (player.car.getOri());
    					player.render.destroy(); // Driver destroy
    					
    					if( nav )
    						nav.remMarker( mPlayer );
    
    					player.car.destroy();
    					player.car = null;
    				}
    
    				VehicleDescriptor nee = GameLogic.getVehicleDescriptor( VehicleType.VS_DEMO );
    				player.car = new Vehicle( player, nee.id, nee.colorIndex, 1+Math.random(), 1+Math.random(), 1, 1 );
    					
    				player.car.setParent( map );
    				player.controller.command( "controllable " + player.car.id() );
    				player.car.setMatrix( CarPos, new Ypr(CarYpr.y, 0.0, 0.0) );
    
    				player.render = new RenderRef( map, player.driverID, "player" );
    				player.controller.command( "renderinstance " + player.render.id() );
    
    				player.car.setDefaultTransmission();
    				player.car.setDefaultSteeringHelp();
    
    				changeCamTarget(player.car);
    				changeCamFollow();
    
    				map.command( "obs_add " + player.car.id() );
    
    				player.car.command( "reload");
    				player.car.command( "idle");
    				player.car.wakeUp();
    
    				System.timeWarp( old_time );
    				player.car.wakeUp();
    
    				if (nav)
    					mPlayer = nav.addMarker( player );
    
    				updateInfo();
    				handled = 1;
    			}
    		}
    
    		if( !handled )
    			super.handleMessage( m );
    	}
    
    	/*public void animate()
    	{
    		super.animate();
    
    		if( player.car )
    			setMessage( player.car.getPos().toString() + " | " +  player.car.getOri().toString() );
    	}//*/
    }
    

  2. Forza Studio
    Sections: Downloads \ Other files
    Tags: .net, Application, C#, Extraction, Forza, Open Source, Tool, Utility, Visual Studios, Xbox



    Features
    Forza Studio 4.0 now officially supports the viewing and extraction of most cars (.carbin), wheels, brakes, rotors, calipers, tracks (.rmb.bin), and textures (.xds, .bix) from both versions of Forza 3 and Forza 4.

    Controls
    Its use is fairly straightforward in my opinion. Right-clicking various sections will bring up a context menu specific to that control. When viewing a model in the viewport, use the WASD keys on your keyboard to move the camera position and IJKL to look around. I’ve also included zip extraction functionality that can be found under the utilities menu for those who wish to use it instead of the usual QuickBMS script.

    Requirements
    .NET Framework 2.0 (or greater)
    XNA Framework 3.1 (4.0 is different)

Tags

Several comma-separated tags will be considered as logical AND between them. You can also use semicolon for logical OR. AND has a priority over OR and you cannot use parentheses for logical grouping. Asterisk (*) within a tag will be regarded as a mask for "any string".