Game Development Community

Creating FlyingVehicle with TGE 1.4

by Norv Brooks · in Torque Game Engine · 09/12/2006 (3:16 pm) · 2 replies

I've been trying to implement a flyingVehicle following Bruno Grieco (Jan 30, 2005) posted thread on Simple/Complex flying vehicles. Since I haven't found anything more current since release of TGE 1.4, I decided to start a new thread. I've been able to get a flying vehicle in the air and it moves, but it doesn't seem to spawn at the location I'm using, doesn't move in the pattern I've set up and moves a short distance and makes a small circle then moves on.
members.dslextreme.com/users/vronsoftware/codeflow.jpg
I'm sure I'm omitting something simple or coded something incorrectly. The following I hope is enough code that someone might see an error:

************* Code Flow *************************

During the mission load "createNewFlyingVehicle()" is called from "levelLoader.cs" and is located in "aircraft.cs"

switch$($FLYINGVEHICLESCLASS[%flyVehType])
	 {
	    // 2a
	    case TWINOTTER:
	       echo("Loading TwinOtter");
	       [b]%twinOtterObj = createNewFlyingVehicle("twinOtter");[/b]
	       echo("%twinOtterObj = ",%twinOtterObj);

	       flyingVehiclesGroup.add(%twinOtterObj);
	 }

From "createNewFlyingVehicle()]/b] within [b]"aircraft.cs" "Aircraft::spawnOnPath()" is called

function createNewFlyingVehicle(%aircraftType)
{
	echo("is %aircraftType a string ",%aircraftType);
	if(%aircraftType $= "twinOtter")
	{
		%dblock = Aircraft;
		%path = "MissionGroup/TwinOtterPath";
		[b]%twinOtter = Aircraft::spawnOnPath(%path,%dblock,%aircraftType);[/b]
		
		// set aircrat position
		%aircraft = %twinOtter;
		
		// Now create pilot
		%num = %twinOtter;
		%spawnName = "TOBot " @ %num;    
		%pathName = "MissionGroup/TwinOtterPath";   	
		%nodeNum = %pathName.getCount();   

		[b]%pilot = TOBot::spawnOnPath(%spawnName, %pathName);[/b]
		%pilot.path = %pathName;   
		%pilot.currentNode = 0;   
		%pilot.targetNode = 2;
		
		[b]Aircraft::onPlayerMount(%pilot,%pilot,%aircraft,0);[/b]
		$pilot = %pilot;
		$moveNode = 1;
		[b]AIPlayer::followPath(%pilot,%pathName,%pilot.targetNode);[/b] 
		%aircraft.player[%num] = $pilot;

		return(%twinOtter);
	}
	else
		return(NULL);
}

From "Aircraft::spawnOnPath()" "Aircraft::spawn() is called

function Aircraft::spawnOnPath(%path,%dblock,%name)
{
   // Spawn a player and place him on the first node of the path
   if (!isObject(%path))
      return;
   %node = %path.getObject(0);
   [b]%plane = Aircraft::spawn(%node.getTransform(),%dblock,%path,%name);[/b]
   return %plane;
}

function Aircraft::spawn(%spawnPoint,%dblock,%path,%name)
{
      // Create the plane object
      %plane = new FlyingVehicle() {
	      dataBlock = %dblock;
	      path = %path;
      };
      //%plane = serverCmdAddFlyer(%name);
      %plane.setTransform(%spawnPoint);
      MissionCleanup.add(%plane);
      
      [b]return %plane;[/b]
}

From "Aircraft::spawn()" %plane is returned back through chain to "createNewFlyingVehicle()
Next, "TOBot::spawnOnPath()" is called which is located in "bot.cs" which then calls "TOBot::spawn()

function TOBot::spawnOnPath( %name, %path )
{
	// Spawn a bot and place him on the first node of the path
	if( !isObject( %path ) )
	{
		echo( "TOBot::spawnOnPath failed - Bad Path!" );
		%this.path = "";
		return;
	}

	%node = %path.getObject(0);
	[b]%player = TOBot::spawn( %name, %node.getTransform() );[/b]

	return %player;
}
function TOBot::spawn( %name, %spawnPoint )
{
	// Create the A.I. driven bot object...
	%player = new AIPlayer()
	{
		dataBlock = DemoPlayer;
		path = "MissionGroup/TwinOtterPath";
	};
	%player.mountable = true;
	MissionCleanup.add( %player );
	%player.setShapeName( %name );
	%player.setTransform( %spawnPoint );

	[b]return %player;[/b]
}

Again, %player is returned up through the chain to "createFlyingVehicle()
Then "Aircraft::onPlayerMount()" is called

function Aircraft::onPlayerMount(%player,%obj,%vehicle,%node)
{
  CommandToClient(%obj.client, 'PopActionMap', moveMap);
  CommandToClient(%obj.client, 'PushActionMap', $Vehicle::moveMaps[%node]);
  CommandToClient(%obj.client,'HideCommandMenuServer');

   %obj.setTransform(%vehicle.getDataBlock().mountPointTransform[%node]);
  %obj.lastWeapon = %obj.getMountedImage($WeaponSlot);
   %obj.unmountImage($WeaponSlot);
   %obj.setActionThread(%vehicle.getDatablock().mountPose[%node],true,true);

   // Are we driving this vehicle?
   if (%node == 0)  {
      %obj.setControlObject(%vehicle);
 }
}

Then returns to "createFlyingVehicle() and calls "AIPlayer::followPath()"

function AIPlayer::followPath(%this,%path,%node)
{
   // Start the player following a path
   %this.setAimLocation($Aircraft::markerLocation[$moveNode]);
   
   %this.stopThread(0);
   if (!isObject(%path)) {
      %this.path = "";
      return;
   }
   if (%node > %path.getCount() - 1)
      %this.targetNode = %path.getCount() - 1;
   else
      %this.targetNode = %node;
 if (%this.path $= %path)
      %this.moveToNode(%this.currentNode,0);
   else {
      %this.path = %path;
      %this.moveToNode(0);
   }
}

function AIPlayer::moveToNode(%this,%index)
{
   // Move to the given path node index
  %node = %this.path.getObject(%this.currentNode+1);
   %this.setMoveDestination(%node.getTransform(), %index == %this.targetNode);
}

Next it returns back through the chain to "layOutFlyingVehicle() in "levelLoader.cs"

The following post has the datablocks used.

#1
09/12/2006 (3:34 pm)
Follow up post with datablocks

************ FlyingVehicle Datablocks ****************

//------------------------------------------------------------------------
// Flying vehicles
datablock FlyingVehicleData(Drone)

{
	spawnOffset = "0 0 2";
	emap	    = true;
	category	= "Vehicles";
	shapeFile	= "~/data/vehicles/buggyGT.dts";
	multipassenger	= false;
	computeCRC	= true;
									
	debrisShapeName		= "~/data/vehicles/buggyGT.dts";
	debris			= DroneShapeDebris;
	renderWhenDestroyed	= false;

	mountPose[0]		= sitting;
	numMountPoints		= 1;
	isProtectedMountPoint[0]	= true;
	cameraMaxDist			= 0.5;
	cameraOffset			= 4.5;
	cameraLag			= 0.0;
   	cameraRoll 			= true; // Roll the camera with the vehicle

  	 // explosion		= DroneVehicleExplosion;
	explosionDamage		= 10.5;
	explosionRadius		= 15.0;

	maxDamage		= 50.40;
	destroyedLevel		= 50.40;
	isShielded		= true; 
	energyPerDamagePoint	= 160;
	maxEnergy		= 280;      // Afterburner and any energy weapon pool
	rechargeRate		= 0.8;

   	integration = 4;           // Physics integration: TickSec/Rate
   	collisionTol = 0.2;        // Collision distance tolerance
   	contactTol = 0.1;

	drag			= 0.6;
	density			= 6.0;
							
	minDrag			= 30;       // Linear Drag (eventually slows you down when not thrusting...constant drag)
	rotationalDrag		= 5;        // Anguler Drag (dampens the drift after you stop moving the mouse...also tumble drag)

	maxAutoSpeed		= 10;       // Autostabilizer kicks in when less than this speed. (meters/second)
	autoAngularForce	= 200;      // Angular stabilizer force (this force levels you out when autostabilizer kicks in)
	autoLinearForce		= 200;      // Linear stabilzer force (this slows you down when autostabilizer kicks in)
	autoInputDamping	= 0.95;     // Dampen control input so you don't' whack out at very slow speeds
   
	// Maneuvering

	maxSteeringAngle	= 0.385;    // -***Max radiens you can rotate the wheel. Smaller number is more maneuverable.
	horizontalSurfaceForce	= 6;        // Horizontal center "wing" (provides "bite" into the wind for climbing/diving and turning)
	verticalSurfaceForce	= 0.5;      // Vertical center "wing" (controls side slip. lower numbers make MORE slide.)
	maneuveringForce	= 1400;     // Horizontal jets (W,S,D,A key thrust)
	steeringForce		= 200;      // Steering jets (force applied when you move the mouse)
	steeringRollForce	= 10;       // Steering jets (how much you heel over when you turn)
	rollForce		= 20;       // Auto-roll (self-correction to right you after you roll/invert)
	hoverHeight		= 45;       // Height off the ground at rest
	createHoverHeight	= 45;       // Height off the ground when created
	maxForwardSpeed		= 100;      // +***speed in which forward thrust force is no longer applied (meters/second)

	// Turbo Jet
	jetForce		= 3000;     // Afterburner thrust (this is in addition to normal thrust)
	minJetEnergy		= 28;       // Afterburner can't be used if below this threshhold.
	jetEnergyDrain		= 2.8;      // Energy use of the afterburners (low number is less drain...can be fractional)                                                                                                                                                                                                                                                                                          // Auto stabilize speed
	vertThrustMultiple	= 3.0;

	// Rigid body
	mass			= 90;       // Mass of the vehicle
	bodyFriction		= 0;        // Don't mess with this.
	bodyRestitution		= 0.4;      // When you hit the ground, how much you rebound. (between 0 and 1)
	minRollSpeed		= 2000;     // Don't mess with this.
	softImpactSpeed		= 3;        // Sound hooks. This is the soft hit.
	hardImpactSpeed		= 15;       // Sound hooks. This is the hard hit.

	// Ground Impact Damage (uses DamageType::Ground)
	minImpactSpeed		= 10;       // If hit ground at speed above this then it's an impact. Meters/second
	speedDamageScale	= 0.06;

	// Object Impact Damage (uses DamageType::Impact)
	collDamageThresholdVel	= 23.0;
	collDamageMultiplier	= 0.02;

	//

	minTrailSpeed		= 15;       // The speed your contrail shows up at.

	triggerDustHeight	= 4.0;
	dustHeight		= 1.0;


	damageEmitterOffset[0]	= "0.0 -3.0 0.0 ";
	damageLevelTolerance[0]	= 0.3;
	damageLevelTolerance[1]	= 0.7;
	numDmgEmitterAreas	= 3;

	minMountDist		= 0.2;	   // -***
	maxMountSpeed 		= 0.1;
	mountDelay 		= 2;
	dismountDelay 		= 1;
	stationaryTreshold 	= 0.5;
	maxDismountSpeed 	= 100;
	mountable 		= true;
	mountPointTransform[0] 	= "1 0 0 0 0 0 0";	
									
	checkRadius		= 5.5;
	observeParameters	= "0 0 0";
									
	shieldEffectScale	= "0.937 1.125 0.60";

};

// Load dts shapes and merge animations
datablock TSShapeConstructor(TwinOtter_rootDts)
{   
	baseShape = "~/data/shapes/aircraft/TwinOtter.dts";   
	sequence0 = "~/data/shapes/aircraft/TwinOtter_root.dsq";
};

// Flying vehicles
datablock FlyingVehicleData(Aircraft : Drone)
{
	numMountPoints	= 3;
};
#2
09/12/2006 (3:34 pm)
Follow up datablocks cont.

*********************** AIPlayer Datablocks ************************
datablock PlayerData(PlayerBody)
{
   renderFirstPerson = false;
   emap = true;
   
   className = SJPlayer;
   shapeFile = "~/data/shapes/player/player.dts";
  
   cameraMaxDist = 3;
   computeCRC = true;
  
   canObserve = true;
   cmdCategory = "Clients";

   cameraDefaultFov = 90.0;
   cameraMinFov = 5.0;
   cameraMaxFov = 120.0;
   
   debrisShapeName = "~/data/shapes/player/debris_player.dts";
   debris = playerDebris;

   aiAvoidThis = true;

   minLookAngle = -1.4;
   maxLookAngle = 1.4;
   maxFreelookAngle = 3.0;

   mass = 90;
   drag = 0.3;
   maxdrag = 0.4;
   density = 10;
   maxDamage = 100;
   maxEnergy =  60;
   repairRate = 0.33;
   energyPerDamagePoint = 75.0;

   rechargeRate = 0.256;

   runForce = 48 * 90;
   runEnergyDrain = 0;
   minRunEnergy = 0;
   maxForwardSpeed = 14;
   maxBackwardSpeed = 13;
   maxSideSpeed = 13;

   maxUnderwaterForwardSpeed = 8.4;
   maxUnderwaterBackwardSpeed = 7.8;
   maxUnderwaterSideSpeed = 7.8;

   jumpForce = 8.3 * 90;
   jumpEnergyDrain = 0;
   minJumpEnergy = 0;
   jumpDelay = 15;

   recoverDelay = 9;
   recoverRunForceScale = 1.2;

   minImpactSpeed = 45;
   speedDamageScale = 0.4;

   boundingBox = "1.2 1.2 2.3";
   pickupRadius = 0.75;
   
   // Damage location details
   boxNormalHeadPercentage       = 0.83;
   boxNormalTorsoPercentage      = 0.49;
   boxHeadLeftPercentage         = 0;
   boxHeadRightPercentage        = 1;
   boxHeadBackPercentage         = 0;
   boxHeadFrontPercentage        = 1;

   // Foot Prints
   decalData   = PlayerFootprint;
   decalOffset = 0.25;
   
   footPuffEmitter = LightPuffEmitter;
   footPuffNumParts = 10;
   footPuffRadius = 0.25;

   dustEmitter = LiftoffDustEmitter;

   splash = PlayerSplash;
   splashVelocity = 4.0;
   splashAngle = 67.0;
   splashFreqMod = 300.0;
   splashVelEpsilon = 0.60;
   bubbleEmitTime = 0.4;
   splashEmitter[0] = PlayerFoamDropletsEmitter;
   splashEmitter[1] = PlayerFoamEmitter;
   splashEmitter[2] = PlayerBubbleEmitter;
   mediumSplashSoundVelocity = 10.0;   
   hardSplashSoundVelocity = 20.0;   
   exitSplashSoundVelocity = 5.0;

   // Controls over slope of runnable/jumpable surfaces
   runSurfaceAngle  = 70;
   jumpSurfaceAngle = 80;

   minJumpSpeed = 20;
   maxJumpSpeed = 30;

   horizMaxSpeed = 68;
   horizResistSpeed = 33;
   horizResistFactor = 0.35;

   upMaxSpeed = 80;
   upResistSpeed = 25;
   upResistFactor = 0.3;
   
   footstepSplashHeight = 0.35;

   //NOTE:  some sounds commented out until wav's are available

   // Footstep Sounds
   FootSoftSound        = FootLightSoftSound;
   FootHardSound        = FootLightHardSound;
   FootMetalSound       = FootLightMetalSound;
   FootSnowSound        = FootLightSnowSound;
   FootShallowSound     = FootLightShallowSplashSound;
   FootWadingSound      = FootLightWadingSound;
   FootUnderwaterSound  = FootLightUnderwaterSound;

   groundImpactMinSpeed    = 10.0;
   groundImpactShakeFreq   = "4.0 4.0 4.0";
   groundImpactShakeAmp    = "1.0 1.0 1.0";
   groundImpactShakeDuration = 0.8;
   groundImpactShakeFalloff = 10.0;
   
   //exitingWater         = ExitingWaterLightSound;
   
   observeParameters = "0.5 4.5 4.5";

   // Allowable Inventory Items
   maxInv[BulletAmmo] = 20;
   maxInv[HealthKit] = 1;
   maxInv[RifleAmmo] = 100;
   maxInv[CrossbowAmmo] = 50;
   maxInv[Crossbow] = 1;
   maxInv[Rifle] = 1;
   maxInv[mountedImage] = 10;
   maxInv[mountedImageAmmo] = 50;
};

datablock PlayerData(DemoPlayer : PlayerBody)
{
   shapeFile	= "~/data/shapes/player/player.dts";
   shootingDelay = 2000;
};


// ----------------Defines in aircraft.cs-------------------
// Defines for TwinOtter marker locations
$Aircraft::markerLocation[0] = "-26.002 -124.037 75.9451 1 0 0 0";
$Aircraft::markerLocation[1] = "-130.406 -123.041 75.9451 1 0 0 0";
$Aircraft::markerLocation[2] = "-138.890 -168.453 75.9451 1 0 0 0";

I'm just using simple prop driven aircraft; so, I probably could omit a good portion of data in these datablocks. However, I didn't know if the terms referring to "jets" was just generic and prop driven planes would still use the same data.

Thanks for any help give.
Norv