BraveTree Tank Port to T3D
by John "Mythic" Henry · in Torque 3D Professional · 05/21/2011 (6:11 am) · 34 replies
Okay to start with, This is not the Complete Port instructions to T3D.
I figured I'd pass on somethings I ran into when I took a different way
on the port to T3D of this Add-On..
I originally started along the same lines as this post:
www.garagegames.com/community/resources/view/17217/1#comment-175349
But as you can see in my posts, I decided to try it a different way.
I went along the lines that the following is true:
A tank is nothing more then a Wheeled vehicle...
So I created a new class [ treadvehicle ]
based off of the [wheeledvehicle] and adapted it to the following:
Multiple wheels beyond [8]
Wheels did not do the steering directly
Changed to [Left/Right] keys for turning
Adjust Wheel speeds on the side to turn towards (Slow down the turn side)
Multiple mount points (Passengers/Weapons]
As I LOVE inheritance, this meant I could setup some Basic functions
that ALL vehicles would have and could then do tests like isMemberofClass(Vehicle)
and know I would get all my vehicle types :)
It works so far, Can move forward/backwards turn left/right AND fire the main turret.
I split the Turret/Gun from the shape and mounted the whole thing as a weaponImage.
This is where I ran into an issue...
Vehicle class deals with the trigger[x] in a simple way,
Trigger[0] activates the Image in Slot[0] (mountpoint[0])..
NOT GOOD..
For consistency we need the same thing across the board.
Basic Vehicle system was assuming Driver Slot [0]
And was dismounting Player.weaponslot[0] on driver being put in vehicle.slot[0]
So what was there for the Vehicle class to Trigger?? Nada.
(This is all simplified info remember, not the actual code, heres some of the actual code)
vehicle.cpp
Script code : ../scripts/server/vehicle.cs
Very simple system, but just doesn't work out of the box if the Vehicle has weapons
as well as Driver/Passengers.
So for any vehicle type with weapons as well as passengers we have to overide the
XXX::updateMove(...)
and deal with our weapons...
But to do this you need to track what slot the weapons are mounted in.
There are alot of more complex issues and ideas to deal with as well, but for
simplicity, just create a few datablock vars that can be set for any vehicle.
example:
Then you have to add them to the vehicle class you've created like so...
That is only part of adding it, you have to do the full monty and add those in just
like the variable engineTorque, etc...
Then when do an ::updateMove(...)
This last bit was the final tie into the ShapeBaseImage so we could now
get Fire/Recoil/ShellCasings all now function Whoopiee!!
Next parts to do...
Fire the 2 machineguns on the front (Dealing with Sherman tank at moment)
Plan to fire these as one adjusting the aim so they point together.
Connect the Turret/Gun to mouse movement so we get a rotating turret and elevating gun.
As I explained in the posts I did previously (see link above)
I hope to be able to Adjust the animation of the Tread materials on the fly
according to speed / direction of tank and turning.
More to come..
By the way, the reason the Wheels function correctly with this setup is due to the following:
I modified the Original shape and removed the Turret / wheels
I then created 2 wheels, Idler / Inner
I also created a new skeleton with hubs for each wheel
I havent done the springs yet, but wont be hard to do now.
This is also where I modified the Mountpoints for Driver/weapons
The Treads are not included in the Body Collision shape, (same in original), so the
tires ignore the Treads and collide with the ground, thus getting traction. When I
do the springs, I'll connect the tread shapes to those and will be able to get some
tread deformation with the springs during movement.
**EDIT**
Successfully completed... I used the following resource to solve Rotation/Elevation..
www.garagegames.com/community/blogs/view/17759
I slightly modified it to allow me to use the mCameraRot so it should work networked.
That is for a bit later testing. Still some fine tuning needed...
I figured I'd pass on somethings I ran into when I took a different way
on the port to T3D of this Add-On..
I originally started along the same lines as this post:
www.garagegames.com/community/resources/view/17217/1#comment-175349
But as you can see in my posts, I decided to try it a different way.
I went along the lines that the following is true:
A tank is nothing more then a Wheeled vehicle...
So I created a new class [ treadvehicle ]
based off of the [wheeledvehicle] and adapted it to the following:
Multiple wheels beyond [8]
Wheels did not do the steering directly
Changed to [Left/Right] keys for turning
Adjust Wheel speeds on the side to turn towards (Slow down the turn side)
Multiple mount points (Passengers/Weapons]
As I LOVE inheritance, this meant I could setup some Basic functions
that ALL vehicles would have and could then do tests like isMemberofClass(Vehicle)
and know I would get all my vehicle types :)
It works so far, Can move forward/backwards turn left/right AND fire the main turret.
I split the Turret/Gun from the shape and mounted the whole thing as a weaponImage.
This is where I ran into an issue...
Vehicle class deals with the trigger[x] in a simple way,
Trigger[0] activates the Image in Slot[0] (mountpoint[0])..
NOT GOOD..
For consistency we need the same thing across the board.
Basic Vehicle system was assuming Driver Slot [0]
And was dismounting Player.weaponslot[0] on driver being put in vehicle.slot[0]
So what was there for the Vehicle class to Trigger?? Nada.
(This is all simplified info remember, not the actual code, heres some of the actual code)
vehicle.cpp
void Vehicle::updateMove(const Move* move)
{
PROFILE_SCOPE( Vehicle_UpdateMove );
mDelta.move = *move;
// Image Triggers
if (mDamageState == Enabled) {
setImageTriggerState(0,move->trigger[0]);
setImageTriggerState(1,move->trigger[1]);
}
// Throttle
if(!mDisableMove)
mThrottle = move->y;
......Script code : ../scripts/server/vehicle.cs
function VehicleData::setMountVehicle(%this, %vehicle, %player)
{
//echo("c4VehicleData::setMountVehicle("@ %this.getName() @", "@ %vehicle @", "@ %player.client.nameBase @")");
if (isObject(%vehicle) && %vehicle.getDamageState() !$= "Destroyed")
{
%node = %this.findEmptySeat(%vehicle, %player);
if (%node >= 0)
{
//echo("c4Mount Node: "@ %node);
%vehicle.mountObject(%player, %node);
//%player.playAudio(0, MountVehicleSound);
%player.mVehicle = %vehicle;
}
}
}Very simple system, but just doesn't work out of the box if the Vehicle has weapons
as well as Driver/Passengers.
So for any vehicle type with weapons as well as passengers we have to overide the
XXX::updateMove(...)
and deal with our weapons...
But to do this you need to track what slot the weapons are mounted in.
There are alot of more complex issues and ideas to deal with as well, but for
simplicity, just create a few datablock vars that can be set for any vehicle.
example:
[a Datablock for a vehicle] .... numMountPoints = 2; //Actually 5 but 3 are for Parts/Guns mountPose[0] = sitting; mountPose[1] = sitting; wheelCount = 12; //2Front / 2Rear / 4*2 Inner //Lets Make it easier to deal with Multiple weapon types numWeaponPoints = 2; startWepMountPoint = 2; ...
Then you have to add them to the vehicle class you've created like so...
void TreadVehicleData::initPersistFields()
{
...
...
//Due to Vehicle Checking and Setting Slots 0/1 as the default
//We have to Know what slots to set for Weapons
// mNumMountPoints = Driver/Passenger1/Pass..x (How many passengers including Driver
// mNumWeaponPoints = Main/Sec(x) How many weapon mount points
// mStartWepMountPoint = Main/Sec(x) Starting Slot for weapons mounted
addField("numMountPoints", TypeS32, Offset(mNumMountPoints, TreadVehicleData),
"Driver/Passengers [Driver Node/Slot == 0], How many seats?" );
addField("numWeaponPoints", TypeS32, Offset(mNumWeaponPoints, TreadVehicleData),
"How many weapons mountpoints?" );
addField("startWepMountPoint", TypeS32, Offset(mStartWepMountPoint, TreadVehicleData),
"starting slot (Node) for first weapon mounted." );
...
...That is only part of adding it, you have to do the full monty and add those in just
like the variable engineTorque, etc...
Then when do an ::updateMove(...)
void TreadVehicle::updateMove(const Move* move)
{
//Mythic DEBUG
// For Treaded Vehicles we have to take over the movement to Steer by
// Adjusting the Speed of one set of wheels or the other
Parent::updateMove(move);
// Trigger images
if (mDamageState == Enabled)
{
// Drivers / Passenger -- mNumMountPoints
// Number of possible weapons -- mNumWeaponPoints
// First Node for weapons -- mStartWepMountPoint);
//
// This is going to be a bit tricky...
// Do we just leave it as [2] Triggers?
// Or do we get fancy? Such as Changing Which one
// is our current Main Weapon?
// For the moment Keep it simple
//
// Have to be carefull here...
// Anything can be mounted, so we should do a check that it is a Weapon
//
// Do we have any Weapons??
if( mDataBlock->mNumWeaponPoints > 0 )
{
bool altTriggerFired = false;
S32 triggerNum = 0;
S32 start = mDataBlock->mStartWepMountPoint;
S32 end = start + mDataBlock->mNumWeaponPoints;
for( S32 mWeap=start; mWeap<end; mWeap++)
{
// If Weapon is mounted Activate Trigger Sequence YEAH!!
// VERY SIMPLE, First Image Mounted is Sent Trigger[0]
// If other weapons, they Get trigger[1]
// Or Else trigger[1] goes to Main as well
//
if ( getMountedImage( mWeap ) )
{
setImageTriggerState( mWeap, move->trigger[triggerNum] );
triggerNum = 1;
}
}
// Here we Send trigger[1] to Main Weapon
// This ALSO allows us to Just fire on the AltTrigger interestingly
if(!altTriggerFired)
{
if ( getMountedImage( start ) )
setImageTriggerState( start, move->trigger[triggerNum] );
}
}
...
...This last bit was the final tie into the ShapeBaseImage so we could now
get Fire/Recoil/ShellCasings all now function Whoopiee!!
Next parts to do...
Fire the 2 machineguns on the front (Dealing with Sherman tank at moment)
Plan to fire these as one adjusting the aim so they point together.
Connect the Turret/Gun to mouse movement so we get a rotating turret and elevating gun.
As I explained in the posts I did previously (see link above)
I hope to be able to Adjust the animation of the Tread materials on the fly
according to speed / direction of tank and turning.
More to come..
By the way, the reason the Wheels function correctly with this setup is due to the following:
I modified the Original shape and removed the Turret / wheels
I then created 2 wheels, Idler / Inner
I also created a new skeleton with hubs for each wheel
I havent done the springs yet, but wont be hard to do now.
This is also where I modified the Mountpoints for Driver/weapons
The Treads are not included in the Body Collision shape, (same in original), so the
tires ignore the Treads and collide with the ground, thus getting traction. When I
do the springs, I'll connect the tread shapes to those and will be able to get some
tread deformation with the springs during movement.
**EDIT**
Successfully completed... I used the following resource to solve Rotation/Elevation..
www.garagegames.com/community/blogs/view/17759
I slightly modified it to allow me to use the mCameraRot so it should work networked.
That is for a bit later testing. Still some fine tuning needed...
About the author
Recent Threads
#2
Not the most efficient way, but it works at the moment.
This all needs more testing with it networked later.
The mSteerControl was added so I could leave the yaw/pitch
alone and use for moving the turret itself.
.... (cont)
05/21/2011 (6:30 am)
For the Steering at the moment I deal with it during the processTick()void TreadVehicle::processTick(const Move* move)
{
Parent::processTick(move);
//Mythic DEBUG
// We catch the Changes to the treads here
//Point3F leftTread0;
//Point3F rightTread0;
//if (isClientObject())
//markTreads(leftTread0,rightTread0,getTransform());
// Heres the tougher one...
// We have to let the Parent process first so it can fill
// [move] with the Delta or Null it
//
// SOOooo we use the Left and Right Keys to Steer so we
// Can control the Turret with the Mouse
// Steering
if(move != NULL)
{
mSteerControl = 0;
if( move->x != 0.0 )
mSteerControl = ( move->x > 0.0 ) ? 1 : -1;
}
}Not the most efficient way, but it works at the moment.
This all needs more testing with it networked later.
The mSteerControl was added so I could leave the yaw/pitch
alone and use for moving the turret itself.
.... (cont)
#3
Then using that [mSteerControl] here:
....(cont)
05/21/2011 (6:32 am)
(cont)...Then using that [mSteerControl] here:
void TreadVehicle::updateForces(F32 dt)
{
PROFILE_SCOPE( TreadVehicle_UpdateForces );
extendWheels();
F32 aMomentum = mMass / mDataBlock->wheelCount;
// Get the current matrix and extact vectors
MatrixF currMatrix;
mRigid.getTransform(&currMatrix);
Point3F bx,by,bz;
currMatrix.getColumn(0,&bx);
currMatrix.getColumn(1,&by);
currMatrix.getColumn(2,&bz);
// Steering angles from current steering wheel position
F32 quadraticSteering = -(mSteering.x * mFabs(mSteering.x));
F32 cosSteering,sinSteering;
mSinCos(quadraticSteering, sinSteering, cosSteering);
// Calculate Engine and brake torque values used later by in
// wheel calculations.
F32 engineTorque,brakeVel;
//Mythic DEBUG
// Attempt to Manage Steering by Reducing Wheel Speed
// Simple adjustment of Speed for the moment
// Left == mSteering.x == -1 / Right == mSteering.x == 1
//
F32 engineTorqueLeft,engineTorqueRight,brakeVelLeft,brakeVelRight;
if (mBraking)
{
brakeVel = (mDataBlock->brakeTorque / aMomentum) * dt;
engineTorque = engineTorqueLeft = engineTorqueRight = 0;
if( mSteerControl == 0 )
{
brakeVelLeft = brakeVelRight = brakeVel;
}
else
{
brakeVelLeft = (mSteerControl == -1) ? brakeVel : (brakeVel * 0.25);
brakeVelRight = (mSteerControl == 1) ? brakeVel : (brakeVel * 0.25);
}
}
else
{
if (mThrottle)
{
engineTorque = mDataBlock->engineTorque * mThrottle;
brakeVel = 0;
// Double the engineTorque to help out the jets
if (mThrottle > 0 && mJetting)
engineTorque *= 2;
brakeVelLeft = brakeVelRight = brakeVel;
if( mSteerControl == 0 )
{
engineTorqueLeft = engineTorqueRight = engineTorque;
}
else
{
engineTorqueLeft = (mSteerControl == -1) ? (engineTorque * 0.25) : engineTorque;
engineTorqueRight = (mSteerControl == 1) ? (engineTorque * 0.25) : engineTorque;
}
}
else
{
// Engine brake.
brakeVel = (mDataBlock->engineBrake / aMomentum) * dt;
engineTorque = engineTorqueLeft = engineTorqueRight = 0;
if( mSteerControl == 0 )
{
brakeVelLeft = brakeVelRight = brakeVel;
}
else
{
brakeVelLeft = (mSteerControl == -1) ? brakeVel : (brakeVel * 0.25);
brakeVelRight = (mSteerControl == 1) ? brakeVel : (brakeVel * 0.25);
}
}
}
.......(cont)
#4
Its not very pretty, but it works... The Wheels do NOT add any
direction to the Turn as Steering is Turned OFF on all wheels.
05/21/2011 (6:34 am)
(cont)...//Mythic DEBUG
// Change to Torque / Brakeing to do Left Right turns
// Instead of Tire Deformations :)
if( mSteerControl == 0 )
wheel->avel += (((wheel->torqueScale * engineTorque) - Fy * wheel->tire->radius) / aMomentum) * dt;
else //Turn Baby
{
//Track Speed Modifications
F32 tempTorque = engineTorqueLeft;
for(int i=0; i<mDataBlock->wheelCount; i++)
{
if(wheel == &mWheel[i])
{
tempTorque = (i<6) ? engineTorqueRight : engineTorqueLeft;
wheel->avel += (((wheel->torqueScale * tempTorque) - Fy * wheel->tire->radius) / aMomentum) * dt;
}
}
}
// Adjust the wheel's angular velocity based on brake torque.
// This is done after avel update to make sure we come to a
// complete stop.
if (brakeVel > mFabs(wheel->avel))
wheel->avel = 0;
else
{
if( mSteerControl == 0 )
{
if (wheel->avel > 0)
wheel->avel -= brakeVel;
else
wheel->avel += brakeVel;
}
else //Turn Baby
{
//Track Speed Modifications
F32 tempBrake = brakeVelLeft;
for(int i=0; i<mDataBlock->wheelCount; i++)
{
if(wheel == &mWheel[i])
{
tempBrake = (i<6) ? brakeVelLeft : brakeVelRight;
if (wheel->avel > 0)
wheel->avel -= tempBrake;
else
wheel->avel += tempBrake;
}
}
}
}
}
// Jet Force
if (mJetting)
....Its not very pretty, but it works... The Wheels do NOT add any
direction to the Turn as Steering is Turned OFF on all wheels.
#5
Before I discuss the issue, I'll bring ya up to speed with what
I've done so far...
The current state of it is as follows:
-------------------------------------------
TankVehicle Class (Based of WheeledVehicle)
Wheels are Instantiated during onAdd with Steering off
Steering uses the move->x value clamped to -1/+1 slowing down
the one set of wheels (Works like a champ).
A few things were moved into Vehicle.cpp :
VehicleData::
-----------------
These were added to Base [datablock xxxVehicleData(xxx)]
so we could reuse code for other vehicles later..
mNumMountPoints --> Number of Mount Points (Players)
mNumWeaponPoints --> Number of Weapon Points
mStartWepMountPoint --> Starting Mountpoint for weapons
(This allows us to Mount Players up to that mount point)
Example:
TankVehicle: 2 Players, 3 weapons
---------------------------------
mNumMountPoints = 2;
startWepMountPoint = 2; // First MountPoint for weapons (Turret)
numWeaponPoints = 3; // 3 weapons Turret / MiniGun / MiniGun
mountTrigger[0] = 0; //Trigger[0] assigned to this weapon
mountTrigger[1] = 1; //Trigger[1] assigned to this weapon
mountTrigger[2] = 1; //Trigger[1] assigned to this weapon
------------------------------
The mountTrigger[x] system takes over when the Fire system activates
and sends the trigger signal to the correct weapon Image.
The primary reason I'm trying to do it this way is to use the current
system of weapon Images that works so well.
Everything is working fine even in multi-player at the moment except
for turning/elevating the turret/barrel.
I have tried a few things:
1: Turret Shape (Dts) has 3 sequences (fire/rotate/elevate)
2: Firing sequence / image system works well, ejects shells/flash
3: turret / barrel Nodes for manually rotating as alternative
So i first tried it this way:
=============================
TreadVehicle.cpp
mTurretMount == the specific Mount Point for Turret (Temp setup)
sRotateSeq / sBarrelSeq are in the Datablock for easy changing
These get sent in the pack/unpackData()
I'm using a single Rotation Variable for testing (mRot) in TreadVehicle
I only use the mRot.x / mRot.z for testing this out as thats
all we care about to get it rotating/elevating.
Now we have a small issue here with trying to use Animation Threads...
When the Tank is Added it doesn't have a Turret. I tried a setup
where the TurretImage Datablock was in stored in the TreadVehicle
Datablock and then loaded during the onAdd() call. This worked
the same with it Mounted afterwards from script, so I dropped that
for the moment.
(continued)....
05/29/2011 (11:41 am)
After alot more work I've run into a snag with Animating the Mounted Turret.Before I discuss the issue, I'll bring ya up to speed with what
I've done so far...
The current state of it is as follows:
-------------------------------------------
TankVehicle Class (Based of WheeledVehicle)
Wheels are Instantiated during onAdd with Steering off
Steering uses the move->x value clamped to -1/+1 slowing down
the one set of wheels (Works like a champ).
A few things were moved into Vehicle.cpp :
VehicleData::
-----------------
//Mythic DEBUG --> mNumMountPoints = 0; mNumWeaponPoints = 0; mStartWepMountPoint = 0; for( S32 i = 0; i<MaxTriggerKeys; i++) mMountTrigger[i] = -1; //Mythic DEBUG <----------------------------
These were added to Base [datablock xxxVehicleData(xxx)]
so we could reuse code for other vehicles later..
mNumMountPoints --> Number of Mount Points (Players)
mNumWeaponPoints --> Number of Weapon Points
mStartWepMountPoint --> Starting Mountpoint for weapons
(This allows us to Mount Players up to that mount point)
Example:
TankVehicle: 2 Players, 3 weapons
---------------------------------
mNumMountPoints = 2;
startWepMountPoint = 2; // First MountPoint for weapons (Turret)
numWeaponPoints = 3; // 3 weapons Turret / MiniGun / MiniGun
mountTrigger[0] = 0; //Trigger[0] assigned to this weapon
mountTrigger[1] = 1; //Trigger[1] assigned to this weapon
mountTrigger[2] = 1; //Trigger[1] assigned to this weapon
------------------------------
The mountTrigger[x] system takes over when the Fire system activates
and sends the trigger signal to the correct weapon Image.
The primary reason I'm trying to do it this way is to use the current
system of weapon Images that works so well.
Everything is working fine even in multi-player at the moment except
for turning/elevating the turret/barrel.
I have tried a few things:
1: Turret Shape (Dts) has 3 sequences (fire/rotate/elevate)
2: Firing sequence / image system works well, ejects shells/flash
3: turret / barrel Nodes for manually rotating as alternative
So i first tried it this way:
=============================
TreadVehicle.cpp
TreadVehicleData::TreadVehicleData()
{
tireEmitter = 0;
....
....
mTurretMount = -1;
sRotateSeq = "";
sBarrelSeq = "";
}mTurretMount == the specific Mount Point for Turret (Temp setup)
sRotateSeq / sBarrelSeq are in the Datablock for easy changing
These get sent in the pack/unpackData()
I'm using a single Rotation Variable for testing (mRot) in TreadVehicle
TreadVehicle::TreadVehicle()
{
...
...
mRot.zero();
}I only use the mRot.x / mRot.z for testing this out as thats
all we care about to get it rotating/elevating.
Now we have a small issue here with trying to use Animation Threads...
When the Tank is Added it doesn't have a Turret. I tried a setup
where the TurretImage Datablock was in stored in the TreadVehicle
Datablock and then loaded during the onAdd() call. This worked
the same with it Mounted afterwards from script, so I dropped that
for the moment.
(continued)....
#6
the following:
In Script:
in TreadVehicle.cpp
(continued)......
05/29/2011 (11:43 am)
To get the Threads / Sequences sorted out during load up I createdthe following:
In Script:
function TreadVehicleData::onAdd(%this, %obj)
{
Parent::onAdd(%this, %obj);
//Modified by Tank Type
//We need to Add the Front/Inner/Rear tire types
//As we have a Left/Right side of even wheels :)
%countTot = %obj.getDataBlock().wheelCount;
%countSide = %countTot / 2;
//Right Side
for(%i=0; %i<=%countSide-1; %i++)
{
%tire = (%i==0 || %i==%countSide-1) ? TankFrontTire : TankInnerTire;
%spring = (%i==0 || %i==%countSide-1) ? OuterTankSpring : InnerTankSpring;
%obj.setWheelTire(%i, %tire);
%obj.setWheelSpring(%i, %spring);
%obj.setWheelPowered(%i, true);
%obj.setWheelSteering(%i, false);
}
//Left Side
....
....
//Now we mount the Turrent w/Gun
%obj.mountImage(TurrentGunImage, 2);
%obj.setInventory(TankPrimaryTurret, 1);
%obj.setInventory(TankPrimaryTurretAmmo, 1000);
%obj.mountable = true;
%obj.onTurretMounted();
}in TreadVehicle.cpp
//--------------------------------------------------------------
// Turret System Controls
//--------------------------------------------------------------
void TreadVehicle::onTurretMounted()
{
//Checking things here
Con::printf("TreadVehicle::onTurretMounted() ... [ %s ]", isServerObject()?"ServerCall":"ClientCall");
//Here goes..
TSShape* turretShape = getMountedImage(mDataBlock->mTurretMount)->shape;
if( turretShape != NULL )
{
//Checking things here
Con::printf("Valid (turretShape) ...");
mRotateSequence = turretShape->findSequence(mDataBlock->sRotateSeq);
mElevateSequence = turretShape->findSequence(mDataBlock->sBarrelSeq);
}
if( mRotateSequence && mElevateSequence )
{
//Checking things here
Con::printf("Valid (mRotateSequence) && (mElevateSequence) ...");
TSShapeInstance* turretInst = getImageShapeInstance(mDataBlock->mTurretMount);
if( turretInst != NULL )
{
//Checking things here
Con::printf("Valid (turretInst) ...");
mRotateThread = turretInst->addThread();
turretInst->setSequence(mRotateThread,mRotateSequence,0);
turretInst->setTimeScale(mRotateThread, 1.0);
turretInst->setBlendEnabled(mRotateThread, true);
mElevateThread = turretInst->addThread();
turretInst->setSequence(mElevateThread,mElevateSequence,0);
turretInst->setTimeScale(mElevateThread, 1.0);
turretInst->setBlendEnabled(mElevateThread, true);
}
}
}
//----------------------------------------------
DefineEngineMethod( TreadVehicle, onTurretMounted, void, ( ),,
"Activate the mounted Turret.")
{
object->onTurretMounted();
}
//----------------------------------------------(continued)......
#7
It fires (uses the Fire Sequence)
It decrements Ammo (Which gets displayed on screen)
It ejects a shell / Creates a Flash etc...
No Probems there...
For the firing sequence to work we did the following:
Turret DataBlocks:
(continued)....
05/29/2011 (11:50 am)
This works just fine. Its mounts the Turret and it stays with Vehicle.It fires (uses the Fire Sequence)
It decrements Ammo (Which gets displayed on screen)
It ejects a shell / Creates a Flash etc...
No Probems there...
For the firing sequence to work we did the following:
Turret DataBlocks:
//-----------------------------------------------------
// Ammo Item
datablock ItemData(TankPrimaryTurretAmmo)
{
category = "Ammo";
className = "Ammo";
shapeFile = "art/shapes/vehicles/Sherman/tankshell.dts";
mass = 1;
elasticity = 0.2;
friction = 0.6;
pickUpName = "tank primary ammo";
maxInventory = 1000;
};
//-----------------------------------------------------
// Weapon Item.
datablock ItemData(TankPrimaryTurret)
{
category = "Weapon";
className = "Weapon";
shapeFile = "art/shapes/vehicles/Sherman/sherman_top.dts";
mass = 1;
elasticity = 0.2;
friction = 0.6;
emap = true;
pickUpName = "primary tank weapon";
image = TurrentGunImage;
maxInventory = 1;
// weaponHUD
previewImage = 'turret.png';
reticle = '';
zoomReticle = '';
itemType = "tklauncher";
trayIcon = "tklauncher01.png";
};(continued)....
#8
(continued)....
05/29/2011 (11:53 am)
Main Image://-----------------------------------------------------
datablock ShapeBaseImageData(TurrentGunImage)
{
className = "WeaponImage";
shapefile = "art/shapes/vehicles/Sherman/sherman_top.dts";
emap = true;
// Specify mount point & offset for 3rd person, and eye offset
// for first person rendering.
mountPoint = 2;
//offset = "0.0 0.15 0.025";
eyeOffset = "0.25 0.6 -0.4"; // 0.25=right/left 0.5=forward/backward, -0.5=up/down
// When firing from a point offset from the eye, muzzle correction
// will adjust the muzzle vector to point to the eye LOS point.
correctMuzzleVector = true;
MeleeWeapon = false;
// Crosshair
maxSpread = 6.0;
minSpread = 4.0;
// Projectile && Ammo.
Item = TankPrimaryTurret;
ammo = TankPrimaryTurretAmmo;
projectile = TankPrimaryProjectile;
projectileType = Projectile;
// shell casings
casing = TankShellCasing;
shellExitDir = "0.5 0.1 0.3";
shellExitOffset = "0.25 0.2 0.1";
shellExitVariance = 10.0;
shellVelocity = 8.0;
// Let there be light - NoLight, ConstantLight, PulsingLight, WeaponFireLight.
lightType = "WeaponFireLight";
lightColor = "1.0 1.0 0.9";
lightDuration = 200;
lightRadius = 10;
// Images have a state system which controls how the animations
// are run, which sounds are played, script callbacks, etc. This
// state system is downloaded to the client so that clients can
// predict state changes and animate accordingly. The following
// system supports basic ready->fire->reload transitions as
// well as a no-ammo->dryfire idle state.
// Initial start up state
stateName[0] = "Preactivate";
stateTransitionOnLoaded[0] = "Activate";
stateTransitionOnNoAmmo[0] = "NoAmmo";
// Activating the gun.
// Called when the weapon is first mounted and there is ammo.
stateName[1] = "Activate";
stateTransitionOnTimeout[1] = "Ready";
stateTimeoutValue[1] = 0.6;
stateSequence[1] = "Activate";
// Ready to fire, just waiting for the trigger
stateName[2] = "Ready";
stateTransitionOnNoAmmo[2] = "NoAmmo";
stateTransitionOnTriggerDown[2] = "Fire";
stateSequence[2] = "Ready";
// Fire the weapon. Calls the fire script which does the actual work.
stateName[3] = "Fire";
stateTransitionOnTimeout[3] = "PostFire";
stateTimeoutValue[3] = 1.9;
stateFire[3] = true;
stateRecoil[3] = LightRecoil;
stateAllowImageChange[3] = false;
stateSequence[3] = "Fire";
stateScript[3] = "onFire";
stateSound[3] = TankPrimaryFireSound;
stateEmitterNode[3] = TankSmokeEmitterNodeData;
stateEmitter[3] = TankFireSmokeEmitter;
stateEmitterTime[3] = 0.9;
....
....(continued)....
#9
I modified Vehicle.cpp this way:
Which solved it quite nicely and is flexible as well..
05/29/2011 (11:55 am)
To get it to actually Fire correctly with the Builtin ImageSystemI modified Vehicle.cpp this way:
void Vehicle::updateMove(const Move* move)
{
PROFILE_SCOPE( Vehicle_UpdateMove );
mDelta.move = *move;
//Mythic DEBUG -->
// Image Triggers
// if (mDamageState == Enabled) {
// setImageTriggerState(0,move->trigger[0]);
// setImageTriggerState(1,move->trigger[1]);
// }
// Trigger images
if (mDamageState == Enabled)
{
//
// Drivers / Passenger -- mNumMountPoints
// Number of possible weapons -- mNumWeaponPoints
// First Node for weapons -- mStartWepMountPoint);
// Trigger to Mount Assignment -- mMountTrigger[x]
// Defaults to [-1] to Skip it example: mountTrigger[x] = -1;
// Thus we can assign ANY of the [19] Triggers to Any Mount point
//
// (Not So tricky now) (ADDED mMountTrigger[x])
//
// Have to be carefull here...
// Anything can be mounted, so we should do a check that it is a Weapon
//
// Do we have any Weapons??
if( mDataBlock->mNumWeaponPoints > 0 )
{
// With Trigger Assignment We loop thru the Triggers :)
//
S32 start = mDataBlock->mStartWepMountPoint;
for( S32 trigAssign=0; trigAssign<MaxTriggerKeys; trigAssign++)
{
// If Weapon is mounted Activate Trigger Sequence YEAH!!
// Very Simple system, if ImageSlot[ mMountTrigger[x]]
// Image Mounted is Sent trigger[ x ]
//
if( mDataBlock->mMountTrigger[trigAssign] >=0 )
{
S32 mWeap = start + mDataBlock->mMountTrigger[trigAssign];
if ( getMountedImage( mWeap ) )
setImageTriggerState( mWeap, move->trigger[trigAssign] );
}
}
}
// Throttle
if(!mDisableMove)
mThrottle = move->y;
...
...Which solved it quite nicely and is flexible as well..
#10
to where we now have to Change the Animation on the Turret to
allow the player to control it (Aim the Turret)...
So we have a Player
Controlling a Vehicle (TreadVehicle Class)
With a Weapon Image Mounted as well..
Tank with the following Mounted:
Mount0 = Player
Mount1 = empty (Passenger)
Mount2 = Turret (WeaponImage)
Mount3 / Mount4 (Currently empty)
So we catch the Update Move either in ::ProcessTick()
or ::updateMove()
It works the same in both (meaning it hasnt worked at all lol).
by doing the following...
TreadVehicle.cpp
The mSteerControl is a basically a duplicate for testing as we
dont use the full range of move->x, we leave mSteering alone and
use this for the Tank Tread turning... Works fine this way.
We catch the yaw/pitch changes and store in mRot and added a flag
(MoveMask) that causes the changes to be networked...
the updateTurretAnimation() is where I have tried many different things
to get the Turret to move..
(continued)...
05/29/2011 (12:05 pm)
Now for the Final Problem, you should be able to follow the aboveto where we now have to Change the Animation on the Turret to
allow the player to control it (Aim the Turret)...
So we have a Player
Controlling a Vehicle (TreadVehicle Class)
With a Weapon Image Mounted as well..
Tank with the following Mounted:
Mount0 = Player
Mount1 = empty (Passenger)
Mount2 = Turret (WeaponImage)
Mount3 / Mount4 (Currently empty)
So we catch the Update Move either in ::ProcessTick()
or ::updateMove()
It works the same in both (meaning it hasnt worked at all lol).
by doing the following...
TreadVehicle.cpp
void TreadVehicle::updateMove(const Move* move)
{
//Mythic DEBUG
// For Treaded Vehicles we have to take over the movement to
// Adjust the Speed to Steer of one set of wheels or the other
Parent::updateMove(move);
// Trigger images
if( mDamageState == Enabled ) //&& getControllingObject() != NULL )
{
//Checking things here
//Con::printf("TreadVehicle::updateMove() ... [ %s ]", isServerObject()?"ServerCall":"ClientCall");
// Brake on trigger
mBraking = move->trigger[2];
// Set the tail brake light thread direction based on the brake state.
if (mTailLightThread)
mShapeInstance->setTimeScale(mTailLightThread, mBraking? 1.0f : -1.0f);
// Can control the Turret with the Mouse
// Steering
if(move != NULL)
{
//Checking things here
//Con::printf("Active Move ... ");
mSteerControl = 0;
if( move->x != 0.0 )
mSteerControl = ( move->x > 0.0 ) ? 1 : -1;
// get Turret values
mRot.x += (move->yaw / M_PI_F);
mRot.z += (move->pitch / M_PI_F);
mRot.x = mClampF(mRot.x,-1.0f,1.0f);
mRot.z = mClampF(mRot.z,-1.0f,1.0f);
updateTurretAnimation();
setMaskBits(MoveMask);
}
}
}The mSteerControl is a basically a duplicate for testing as we
dont use the full range of move->x, we leave mSteering alone and
use this for the Tank Tread turning... Works fine this way.
We catch the yaw/pitch changes and store in mRot and added a flag
(MoveMask) that causes the changes to be networked...
the updateTurretAnimation() is where I have tried many different things
to get the Turret to move..
(continued)...
#11
to Move..
TO no avail at any point.. I know I must be missing something
simple here, but I have banged my head against this for too long.
Time I asked for help :)
05/29/2011 (12:08 pm)
And here are some of the things I have Tried to get that Dang Turretto Move..
//-----------------------------------------------------
void TreadVehicle::updateTurretAnimation()
{
//Checking things here
//Con::printf("TreadVehicle::updateTurretAnimation() ... [ %s ]", isServerObject()?"ServerCall":"ClientCall");
//Turret / Weapon Movement
//---------------------------------
// Attempt 1
//--------------------------------
/*
TSShape* turretShape = getImageShapeInstance(mDataBlock->mTurretMount)->getShape();
if( turretShape != NULL )
{
TSShapeInstance* turretInst = getImageShapeInstance(mDataBlock->mTurretMount);
if( turretInst != NULL )
{
S32 node = turretShape->findNode("turret");
MatrixF * mat = &turretInst->mNodeTransforms[node];
Point3F defaultPos = turretShape->defaultTranslations[node];
mat->set(EulerF(mRot.x,0,0));
mat->setColumn(3,defaultPos);
}
}
*/
//--------------------------------
// Attempt 2
//--------------------------------
TSShapeInstance* turretInst = getImageShapeInstance(mDataBlock->mTurretMount);
if( turretInst != NULL )
{
if( mRotateThread )
{
U8 posTurret = (mRot.x > 0 )? U8(mRot.x / 0.04) + 25 : U8(abs(mRot.x / 0.04));
turretInst->setPos(mRotateThread, posTurret);
turretInst->setDirty(TSShapeInstance::TransformDirty);
turretInst->animate();
}
if( mElevateThread )
{
U8 posBarrel = (mRot.z > 0 )? U8(mRot.z / 0.1) + 10 : U8(abs(mRot.z / 0.1));
turretInst->setPos(mElevateThread, posBarrel);
turretInst->setDirty(TSShapeInstance::TransformDirty);
turretInst->animate();
}
}
/*
//--------------------------------
// Attempt 3
//--------------------------------
TSShapeInstance* turretInst = getImageShapeInstance(mDataBlock->mTurretMount);
if( turretInst != NULL )
{
//Checking things here
Con::printf("Valid (turretInst) ... ");
TSShape* turretShape = turretInst->getShape();
if( turretShape != NULL )
{
//Checking things here
Con::printf("Valid (turretShape) ... ");
// set turret... [Use Root]
S32 node = turretShape->findNode("turret");
MatrixF * mat = &turretInst->mNodeTransforms[node];
Point3F defaultPos = turretShape->defaultTranslations[node];
mat->set(EulerF(0,0,mRot.z));
mat->setColumn(3,defaultPos);
// set weapon... [Use turretpivot]
node = turretShape->findNode("barrel");
mat = &turretInst->mNodeTransforms[node];
defaultPos = turretShape->defaultTranslations[node];
mat->set(EulerF(mRot.x,0,0));
mat->setColumn(3,defaultPos);
}
}
*/
//mShapeInstance->setDirty(TSShapeInstance::TransformDirty);
//mShapeInstance->animate();
//setMaskBits(ImageMaskN << mDataBlock->mTurretMount);
}TO no avail at any point.. I know I must be missing something
simple here, but I have banged my head against this for too long.
Time I asked for help :)
#12
----------------------------------------
Bones:
ejectPoint / mountPoint (these arent connected to root)
Root -> turret -> barrel -> muzzle -> muzzlePoint
----------------------------------------
The Sequences are timed so I should be able to just set it to a
specific point in the thread that roughly matches the angle of
mRot.x, Not the most accurate, but good enough for testing.
The Rotate sequence is 50 frames, 25 on one side (180)
The Elevate is 20 frames, going from lowest to Highest point,
frame 1 lowest, frame 10 center, highest elevation 20.
I've checked these in the Editor and they have come through from
MS3D just fine and all work except for actually in game :(
Altho the (fire) sequence works just fine.
So any questions I'll be happy to answer, but Help would be
greatly appreciated...
05/29/2011 (12:17 pm)
(3) sequences ( fire / rotate / elevate)----------------------------------------
Bones:
ejectPoint / mountPoint (these arent connected to root)
Root -> turret -> barrel -> muzzle -> muzzlePoint
----------------------------------------
The Sequences are timed so I should be able to just set it to a
specific point in the thread that roughly matches the angle of
mRot.x, Not the most accurate, but good enough for testing.
The Rotate sequence is 50 frames, 25 on one side (180)
The Elevate is 20 frames, going from lowest to Highest point,
frame 1 lowest, frame 10 center, highest elevation 20.
I've checked these in the Editor and they have come through from
MS3D just fine and all work except for actually in game :(
Altho the (fire) sequence works just fine.
So any questions I'll be happy to answer, but Help would be
greatly appreciated...
#13
Something I hadnt understood before...
The basic shapeinstance with a mounted object checks the base shape
for sequences when you try to add threads (Which is why I had been
accessing the MountedImage shapeinstance instead), and for mounted
WeaponImages it takes over the animation and doesnt properly work with
adding threads???
One possible solution would be to add another 1-2 animation threads
to weaponImages?
Or perhaps I just need to tie it into the camera somehow?
Im lost and need a short break...
05/29/2011 (1:59 pm)
Alrite, I think I have found part of the problem...void ShapeBase::setImage( U32 imageSlot,
ShapeBaseImageData* imageData,
...
...
// The server needs the shape loaded for muzzle mount nodes
// but it doesn't need to run any of the animations.
image.ambientThread = 0;
image.animThread = 0;
image.flashThread = 0;
image.spinThread = 0;
if (isGhost()) {
if (image.dataBlock->isAnimated) {
image.animThread = image.shapeInstance->addThread();
image.shapeInstance->setTimeScale(image.animThread,0);
}
...
..Something I hadnt understood before...
The basic shapeinstance with a mounted object checks the base shape
for sequences when you try to add threads (Which is why I had been
accessing the MountedImage shapeinstance instead), and for mounted
WeaponImages it takes over the animation and doesnt properly work with
adding threads???
One possible solution would be to add another 1-2 animation threads
to weaponImages?
Or perhaps I just need to tie it into the camera somehow?
Im lost and need a short break...
#14
As I added to the Main Section at top, using that Camera resource
I was then able to use the following to Rotate/Elevate, basically
used parts of the original code but matched it to use with the
Vehicle Class:
Barrel.
Interestingly I ran into what is either an Issue with my MS3D
versions or I dont know what, but I had switch which ones
I used for Pitch/Yaw as they weren't working the way I expected,
seemed like they were reversed.
I'll post some of the changes to Vehicle Class as well..
06/11/2011 (7:53 am)
Solved...As I added to the Main Section at top, using that Camera resource
I was then able to use the following to Rotate/Elevate, basically
used parts of the original code but matched it to use with the
Vehicle Class:
//----------------------------------------------
void TankVehicle::updateAnimation(bool muzzleOnly)
{
S32 node;
MatrixF * mat;
Point3F defaultPos;
Point3F tCameraRot = getCameraRotation();
// set Turret...
node = mDataBlock->mTurretNode;
mat = &mShapeInstance->mNodeTransforms[node];
defaultPos = mDataBlock->mShape->defaultTranslations[node];
mat->set(EulerF(0,0,tCameraRot.z));
mat->setColumn(3,defaultPos);
// set Barrel...
node = mDataBlock->mWeaponNode;
mat = &mShapeInstance->mNodeTransforms[node];
defaultPos = mDataBlock->mShape->defaultTranslations[node];
mat->set(EulerF(tCameraRot.x,0,0));
mat->setColumn(3,defaultPos);
if( isGhost() )
{
if( muzzleOnly )
{
// tank suspension...
node = mDataBlock->mSuspensionNode;
mat = &mShapeInstance->mNodeTransforms[node];
defaultPos = mDataBlock->mShape->defaultTranslations[node];
mat->identity();
mat->setColumn(3,defaultPos);
}
else
{
// wheel suspension...
for (S32 i = 0; i < mDataBlock->tankWheelCount; i++)
{
if( mTankWheel[i].data->treadNode != -1 )
{
node = mTankWheel[i].data->treadNode;
mat = &mShapeInstance->mNodeTransforms[node];
defaultPos = mDataBlock->mShape->defaultTranslations[node];
defaultPos.z -= mTankWheel[i].spring->length * mTankWheel[i].extension;
mat->identity();
mat->setColumn(3,defaultPos);
}
}
// tank suspension...
/* node = mDataBlock->mSuspensionNode;
mat = &mShapeInstance->mNodeTransforms[node];
defaultPos = mDataBlock->mShape->defaultTranslations[node];
defaultPos.z -= mTankSpringPos.z;
Point3F z = mTankSpringPos;
z.z=1.0f;
z.normalize();
Point3F x,y;
mCross(Point3F(0,1,0),z,&x);
x.normalize();
mCross(z,x,&y);
mat->setColumn(0,x);
mat->setColumn(1,y);
mat->setColumn(2,z);
mat->setColumn(3,defaultPos);
*/
}
}
mShapeInstance->setDirty(TSShapeInstance::TransformDirty);
mShapeInstance->animate();
}This gives me a properly rotating Turret and ElevatingBarrel.
Interestingly I ran into what is either an Issue with my MS3D
versions or I dont know what, but I had switch which ones
I used for Pitch/Yaw as they weren't working the way I expected,
seemed like they were reversed.
I'll post some of the changes to Vehicle Class as well..
#15
At the moment the Treads now stick to the bottom of the wheels (Inner),
it was the easiest way to go in the above code.
As it works just like the other vehicles, it uses a Rigid Body
that is handled by the wheels/vehicle parent so collides nicely.
This is still a rough working code, but it's doing the job so far.
I still have to look at the code that checks the Image is a weapon image.
That little bit is commented out until I get back to it.
06/11/2011 (7:59 am)
I still need to finish the Recoil system and add in a Fire Animation.At the moment the Treads now stick to the bottom of the wheels (Inner),
it was the easiest way to go in the above code.
As it works just like the other vehicles, it uses a Rigid Body
that is handled by the wheels/vehicle parent so collides nicely.
//----------------------------------------------------------------------------
void Vehicle::updateMove(const Move* move)
{
PROFILE_SCOPE( Vehicle_UpdateMove );
mDelta.move = *move;
// Mythic DEBUG -->
// New Weapon System
if (mDamageState == Enabled)
{
//
// Drivers / Passenger -- mNumMountPoints
// Number of possible weapons -- mNumWeaponPoints
// First Node for weapons -- mStartWepMountPoint);
// Trigger to Mount Assignment -- mMountTrigger[x]
// Defaults to [-1] to Skip it
// Thus we can assign ANY of the [19] Triggers to Any Mount point
// Have to be carefull here...
// Anything can be mounted, so we should do a check that it is a Weapon
//
// If Weapon is mounted Activate Trigger Sequence YEAH!!
// Very Simple system, if ImageSlot[ mMountTrigger[x]]
// Image Mounted is Sent trigger[ x ]
// We also ONLY activate on a WeaponImage, So mounted Item
// MUST be a WeaponImage Class Type!
// Reduce Calls / Reduce CPU cycles / Speed up Game
//
// Do we have any Weapons??
if( mDataBlock->mNumWeaponPoints > 0 )
{
S32 start = mDataBlock->mStartWepMountPoint;
for( S32 trigAssign=0; trigAssign<MaxTriggerKeys; trigAssign++)
{
S32 setTrigger = mDataBlock->mMountTrigger[trigAssign];
if( setTrigger >=0 )
{
S32 mWeap = start + trigAssign;
ShapeBaseImageData* tempWeapon = getMountedImage( mWeap );
if ( tempWeapon != NULL ) // &&
//( (SimObject*)tempWeapon->getClassRep()->isClass( AbstractClassRep::findClassRep("WeaponImage"))) )
setImageTriggerState( mWeap, move->trigger[setTrigger] );
}
}
}
}
// Mythic DEBUG <--
// Throttle
if(!mDisableMove)
mThrottle = move->y;
// Steering Mythic DEBUG -->
if (move != &NullMove)
{
// DataBlock Control of the Turn/Rotate/Elevate speed limiters
// So Vehicles can behave differently
// Have to reset mSteeringLR as move->x is only : -1 / 0 / 1
//
// [ <- | -> ] steering system [keys A-S ] -->
if( move->x != 0.0f )
{
F32 lr = (move->x * M_PI_F/mDataBlock->mMaxTurnSpeed); //move->x is the A/D keys!
mSteeringLR = mClampF(mSteeringLR + lr,-mDataBlock->maxSteeringAngle, mDataBlock->maxSteeringAngle);
}
else
mSteeringLR = 0.0f;
// [ <- | -> ] steering system [keys A-S ] <--
// Flying/HoverCraft steering -->
F32 y = move->yaw;
mSteering.x = mClampF(mSteering.x + y,-mDataBlock->maxSteeringAngle,
mDataBlock->maxSteeringAngle);
F32 p = move->pitch;
mSteering.y = mClampF(mSteering.y + p,-mDataBlock->maxSteeringAngle,
mDataBlock->maxSteeringAngle);
// Flying/HoverCraft steering <--
// Camera/Vehicle Rotation/Elevation -->
// Pitch [Up-Down]
mDelta.cameraRotVec = mCameraRot;
p = (p * M_PI_F/mDataBlock->mMaxPitchSpeed);
if (p > M_PI_F)
p -= M_2PI_F;
if (mDataBlock->freeCamPitch)
mCameraRot.x = mClampF(mCameraRot.x + p, -M_PI_F, M_PI_F);
else
mCameraRot.x = mClampF(mCameraRot.x + p, mDataBlock->minCamPitchAngle, mDataBlock->maxCamPitchAngle); //constrain to datablock values
// Yaw [Left-Right]
y = (y * M_PI_F/mDataBlock->mMaxYawSpeed);
if (y > M_PI_F)
y -= M_2PI_F;
if (mDataBlock->freeCamYaw)
mCameraRot.z = mClampF(mCameraRot.z + y, -M_PI_F, M_PI_F);
else
mCameraRot.z = mClampF(mCameraRot.z + y, mDataBlock->minCamYawAngle, mDataBlock->maxCamYawAngle); //constrain to datablock values
mDelta.cameraRot = mCameraRot;
mDelta.cameraRotVec -= mCameraRot;
// Camera/Vehicle Rotation/Elevation <--
}
// Steering Mythic DEBUG <--
else
{
mSteering.x = 0;
mSteering.y = 0;
mSteeringLR = 0.0f;
}
// Jetting flag
if (move->trigger[3]) {
if (!mJetting && getEnergyLevel() >= mDataBlock->minJetEnergy)
mJetting = true;
if (mJetting) {
F32 newEnergy = getEnergyLevel() - mDataBlock->jetEnergyDrain;
if (newEnergy < 0) {
newEnergy = 0;
mJetting = false;
}
setEnergyLevel(newEnergy);
}
}
else
mJetting = false;
}This is still a rough working code, but it's doing the job so far.
I still have to look at the code that checks the Image is a weapon image.
That little bit is commented out until I get back to it.
#16
turret/barrel system. To try and make it a bit more flexible
I added a bit to Vehicle Datablocks so I could stick with one
Call for onAdd()... (Alot of these Vars are now in all Vehicles)
Heres one of the DataBlocks:
cont..
06/11/2011 (8:03 am)
It turned out fairly simple once I figured out the issue with theturret/barrel system. To try and make it a bit more flexible
I added a bit to Vehicle Datablocks so I could stick with one
Call for onAdd()... (Alot of these Vars are now in all Vehicles)
Heres one of the DataBlocks:
// Sherman Tank
//-----------------------------------------------------------------------
datablock TankVehicleData(ShermanTank)
{
category = "Tanks";
shapeFile = "art/shapes/vehicles/sherman/sherman_hull.dts";
emap = 1;
totalMountPoints = 4; //Dynamic ALL MountPounts script use only
numMountPoints = 1;
pilotNode = 0;
mountPose[0] = sitting;
// All Vehicles can Declare these for Weapon Mounting
startWepMountPoint = 1;
numWeaponPoints = 3;
mountTrigger[0] = 0; //Trigger[0] assigned to MountPoint[ startWepMountPoint + mountTrigger[0] ]
mountTrigger[1] = 1; //Trigger[1] assigned to MountPoint[ startWepMountPoint + mountTrigger[1] ]
mountTrigger[2] = 1; //Trigger[1] assigned to MountPoint[ startWepMountPoint + mountTrigger[2] ]
//Wheels
numInnerWheelsPerSide = 6; // in addition to the 2 outer wheels per side
tankWheelCount = 16; // 2Front / 2Rear / numInnerWheelsPerSide * 2
useEyePoint = true; // Use the vehicle's camera node rather than the player's
shadowEnable = true;
shadowSize = 256;
shadowProjectionDistance = 14.0;
freeCamPitch = false; // true = ignore values and rotate 360 degrees.
minCamPitchAngle = -1.0; // Lowest angle (radians) the player can look
maxCamPitchAngle = 0.4; // Highest angle (radians) the player can look
freeCamYaw = false; // true = ignore values and rotate 360 degrees.
minCamYawAngle = -2.0; // Left turn (radians) the player can look
maxCamYawAngle = 2.0; // Right turn (radians) the player can look
maxTurnSpeed = 10.0; // degrees/second
maxPitchSpeed = 20.0;
maxYawSpeed = 20.0;
maxSteeringAngle = 0.585; // Maximum steering angle, should match animation
//Suspension Settings
primaryRecoil = 10.0; // Recoil amount for the primary weapon
suspensionRange = 0.95; // proportion of wheel size for wheel to move up/down
springRangeX = 0.02; // How much the tank can rock back and forth
springRangeY = 0.02; // How much the tank can rock side to side
springVelScale = 1.0; // How fast the springs rock
springLooseness = 0.8; // How "tight" the springs are (0 = loose, 1.0 = tight)
// 3rd person camera settings
cameraRoll = false; // Roll the camera with the vehicle
cameraMaxDist = 7.8; // Far distance from vehicle
cameraOffset = 1.0; // Vertical offset from camera mount point
cameraLag = "0.3"; // Velocity lag of camera
cameraDecay = 1.25; // Decay per sec. rate of velocity lag
// Rigid Body
mass = "800";
massCenter = "0 -0.2 0"; // Center of mass for rigid body
massBox = "0 0 0"; // Size of box used for moment of inertia,
// if zero it defaults to object bounding box
drag = 0.6; // Drag coefficient
bodyFriction = 0.6;
bodyRestitution = 0.4;
minImpactSpeed = 5; // Impacts over this invoke the script callback
softImpactSpeed = 5; // Play SoftImpact Sound
hardImpactSpeed = 15; // Play HardImpact Sound
integration = 8; // Physics integration: TickSec/Rate
collisionTol = "0.1"; // Collision distance tolerance
contactTol = "0.1"; // Contact velocity tolerance....cont..
#17
So now I'm gonna have to finalize this :)
Then I have to deal with the Striker....
06/11/2011 (8:05 am)
cont..// Engine engineTorque = 4300; // Engine power engineBrake = "1000"; // Braking when throttle is 0 brakeTorque = "8000"; // When brakes are applied maxWheelSpeed = 50; // Engine scale by current speed / max speed // Energy / Damage maxEnergy = 100; maxDamage = 100; destroyedLevel = 100; engineSoundA = ShermanIdleSound; engineSoundB = ShermanEngineSound; softImpactSound = softImpact; hardImpactSound = hardImpact; // Dynamic fields accessed via script nameTag = 'Sherman'; maxDismountSpeed = 10; maxMountSpeed = 5; tireEmitter = "TankTireEmitter"; dustEmitter = "TankTireEmitter"; dustHeight = "1"; // Weapons List.. Interesting and Flexible weaponImage[0] = TankPrimaryWeaponImage; weaponSlot[0] = TankPrimaryWeapon; weaponAmmo[0] = TankPrimaryWeaponAmmo; weaponAmmoCnt[0] = 10; weaponImage[1] = TankSecondaryWeaponImage; weaponSlot[1] = TankSecondaryWeapon; weaponAmmo[1] = TankSecondaryWeaponAmmo; weaponAmmoCnt[1] = 500; weaponImage[2] = TankTertiaryWeaponImage; weaponSlot[2] = TankTertiaryWeapon; weaponAmmo[2] = TankTertiaryWeaponAmmo; weaponAmmoCnt[2] = 500; // Allowable Inventory Items maxInv[TankPrimaryWeapon] = 1; maxInv[TankPrimaryWeaponAmmo] = 100; maxInv[TankSecondaryWeapon] = 1; maxInv[TankSecondaryWeaponAmmo] = 1000; // This tank has 2 machine guns on the front maxInv[TankTertiaryWeapon] = 1; maxInv[TankTertiaryWeaponAmmo] = 1000; };
So now I'm gonna have to finalize this :)
Then I have to deal with the Striker....
#18
Is the correct way to do it.. Totally forgot the weaponImages
declare their MountPoints in the DataBlock and its not the slot
you specify in the setImage ... *chuckle* I think I was working
too hard on this before lol
06/17/2011 (7:04 am)
I just spotted a [Brain Fart] I had with Weapon Images and MountPoints :)if( mDataBlock->mNumWeaponPoints > 0 )
{
for( S32 trigAssign=0; trigAssign<MaxTriggerKeys; trigAssign++)
{
S32 mWeap = mDataBlock->mMountTrigger[trigAssign];
//Have to deal with the HardCoded Limit of [4] Mounted Images MAX
//Will look into wether or not we need more later
if( mWeap >= 0 && mWeap < 3)
{
ShapeBaseImageData* tempWeapon = getMountedImage( mWeap );
if ( tempWeapon != NULL )
setImageTriggerState( mWeap, move->trigger[trigAssign] );
}
}
}Is the correct way to do it.. Totally forgot the weaponImages
declare their MountPoints in the DataBlock and its not the slot
you specify in the setImage ... *chuckle* I think I was working
too hard on this before lol
#19
Do you think it"s would be possible to get a copy of your TreadVehicle.ccp and TreadVehicle.h?
Thanks,
Sylvain
08/08/2011 (1:36 pm)
Hello John,Do you think it"s would be possible to get a copy of your TreadVehicle.ccp and TreadVehicle.h?
Thanks,
Sylvain
#20
of the Main system (Bravetree tank) and I can't really give out their
work. If I'm able to set it up fully without any of the original code,
I have been thinking of just posting it as a resource later.
So for the moment I can't post the full files :(
The main feature that would be lost is the turret control/fire system
so it kinda makes it a bit useless without those bits. Sorry, but I do
believe in people being able to make money from their hard work..
My original work tried to do it without using any of the tank code. I was
able to do all but the Turret movement.
That is why I've tried not to post any of the original code. With the
several posts I've done, you should be able to piece it together. I've
posted alot of the work I've tried.
You also need to slightly modify the base vehicle class to mix this one
in the way I did it.
08/08/2011 (3:38 pm)
Part of the problem with giving out those two is that they do use partsof the Main system (Bravetree tank) and I can't really give out their
work. If I'm able to set it up fully without any of the original code,
I have been thinking of just posting it as a resource later.
So for the moment I can't post the full files :(
The main feature that would be lost is the turret control/fire system
so it kinda makes it a bit useless without those bits. Sorry, but I do
believe in people being able to make money from their hard work..
My original work tried to do it without using any of the tank code. I was
able to do all but the Turret movement.
That is why I've tried not to post any of the original code. With the
several posts I've done, you should be able to piece it together. I've
posted alot of the work I've tried.
You also need to slightly modify the base vehicle class to mix this one
in the way I did it.
Torque 3D Owner John "Mythic" Henry
EveronWorlds
in Vehicle.cpp so ALL types inherting from it have the ability
to define weapon points.