Legacy:KHoverTank

From Unreal Wiki, The Unreal Engine Documentation Site
Jump to navigation Jump to search
UT2003 :: Actor >> Pawn >> KVehicle >> KCar >> KHoverTank

Adding extra wheels is pretty easy, useful for making tanks or hovercrafts. :] Also, Rear Steering with forward steering allows for some sharp turns and cool looking vehicle :]

<uscript> //============================================================================= // KHoverTank. // Base class for 6-invisible wheeled 'hover' vehicles using Karma // Assumes negative-X is forward, negative-Y is right //============================================================================= class KHoverTank extends KCar abstract;

var KTire midLeft, midRight; var (KHoverTank) class<KTire> MidTireClass; // Wheel positions var const float WheelMidAlong; var const float WheelMidAcross;

replication { // We replicate the Gear for brake-lights etc. unreliable if(Role == ROLE_Authority) CarState, Gear;

reliable if(Role == ROLE_Authority) FlipTimeLeft; }

// When new information is received, see if it's new. If so, pass bits off the wheels. // Each part will then update its rigid body position via the KUpdateState event. // JTODO: This is where clever unpacking would happen. simulated event VehicleStateReceived() { local vector ChassisY, SteerY, ChassisZ, calcPos, WheelY, lPos; local vector chassisPos, chassisLinVel, chassisAngVel, WheelLinVel, wPosRel; local Quat relQ, WheelQ;

// Don't do anything if car isn't started up. // Shouldn't need to worry about Front or Rear as it's done in Super. if( midLeft == None || midRight == None ) return;

Super.VehicleStateReceived()

////////////////////////// MID LEFT ////////////////////////// midLeft.KGetRigidBodyState(midLeft.ReceiveState);

// Position lPos.X = WheelMidAlong; lPos.Y = WheelMidAcross; lPos.Z = CarState.WheelHeight[2]; calcPos = chassisPos + QuatRotateVector(CarState.ChassisQuaternion, lPos); midLeft.ReceiveState.Position = KRBVecFromVector(calcPos);

// Rotation wheelQ = midLeft.KGetRBQuaternion(); WheelY = QuatRotateVector(wheelQ, vect(0, 1, 0)); relQ = QuatFindBetween(WheelY, ChassisY); midLeft.ReceiveState.Quaternion = QuatProduct(relQ, wheelQ);

// Velocity wPosRel = calcPos - chassisPos; WheelLinVel = chassisLinVel + (chassisAngVel Cross wPosRel); WheelLinVel += CarState.WheelVertVel[2] * ChassisZ; midLeft.ReceiveState.LinVel = KRBVecFromVector(WheelLinVel);

midLeft.bReceiveStateNew = true;

////////////////////////// MID RIGHT ////////////////////////// midRight.KGetRigidBodyState(midRight.ReceiveState);

// Position lPos.X = WheelMidAlong; lPos.Y = WheelMidAcross; lPos.Z = CarState.WheelHeight[3]; calcPos = chassisPos + QuatRotateVector(CarState.ChassisQuaternion, lPos); midRight.ReceiveState.Position = KRBVecFromVector(calcPos);

// Rotation wheelQ = midRight.KGetRBQuaternion(); WheelY = QuatRotateVector(wheelQ, vect(0, 1, 0)); relQ = QuatFindBetween(WheelY, ChassisY); midRight.ReceiveState.Quaternion = QuatProduct(relQ, wheelQ);

// Velocity wPosRel = calcPos - chassisPos; WheelLinVel = chassisLinVel + (chassisAngVel Cross wPosRel); WheelLinVel += CarState.WheelVertVel[3] * ChassisZ; midRight.ReceiveState.LinVel = KRBVecFromVector(WheelLinVel);

midRight.bReceiveStateNew = true;

////// OTHER //////

// Update control inputs Steering = CarState.ServerSteering; OutputTorque = CarState.ServerTorque; OutputBrake = CarState.ServerBrake; OutputHandbrakeOn = CarState.ServerHandbrakeOn;

// Update flags

CarState.bNewState = false; bNewCarState = true;

}

// Pack current state of whole car into the state struct, to be sent to the client. // Should only get called on the server. function PackState() { local vector lPos, wPos, chassisPos, chassisLinVel, chassisAngVel, wPosRel, WheelLinVel; local vector ChassisX, ChassisZ, WheelY, oldPos, oldLinVel; local KRigidBodyState ChassisState, WheelState, TurrState;

Super.PackState();


////////////////////////// MID LEFT ////////////////////////// midLeft.KGetRigidBodyState(WheelState); wPos = KRBVecToVector(WheelState.Position); lPos = QuatRotateVector(QuatInvert(CarState.ChassisQuaternion), wPos - chassisPos); CarState.WheelHeight[2] = lPos.Z;

wPosRel = KRBVecToVector(WheelState.Position) - chassisPos; WheelLinVel = chassisLinVel + (chassisAngVel Cross wPosRel);

CarState.WheelVertVel[2] = ((WheelState.LinVel.X - WheelLinVel.X)* ChassisZ.X) + ((WheelState.LinVel.Y - WheelLinVel.Y)* ChassisZ.Y) + ((WheelState.LinVel.Z - WheelLinVel.Z)* ChassisZ.Z);

WheelY = QuatRotateVector(WheelState.Quaternion, vect(0, 1, 0));

////////////////////////// MID RIGHT ////////////////////////// midRight.KGetRigidBodyState(WheelState); wPos = KRBVecToVector(WheelState.Position); lPos = QuatRotateVector(QuatInvert(CarState.ChassisQuaternion), wPos - chassisPos); CarState.WheelHeight[3] = lPos.Z;

wPosRel = KRBVecToVector(WheelState.Position) - chassisPos; WheelLinVel = chassisLinVel + (chassisAngVel Cross wPosRel);

CarState.WheelVertVel[3] = ((WheelState.LinVel.X - WheelLinVel.X)* ChassisZ.X) + ((WheelState.LinVel.Y - WheelLinVel.Y)* ChassisZ.Y) + ((WheelState.LinVel.Z - WheelLinVel.Z)* ChassisZ.Z);


WheelY = QuatRotateVector(WheelState.Quaternion, vect(0, 1, 0));

// OTHER CarState.ServerSteering = Steering; CarState.ServerTorque = OutputTorque; CarState.ServerBrake = OutputBrake; CarState.ServerHandbrakeOn = OutputHandbrakeOn;

// This flag lets the client know this data is new. CarState.bNewState = true;

}

simulated function PostNetBeginPlay() { local vector RotX, RotY, RotZ, lPos;

   Super.PostNetBeginPlay();
   // Set up suspension graphics
   GetAxes(Rotation,RotX,RotY,RotZ);

frontLeft.bHidden = True; // Invisible wheels for hovercrafts frontRight.bHidden = True; // Invisible wheels for hovercrafts rearLeft.bHidden = True; // Invisible wheels for hovercrafts rearRight.bHidden = True; // Invisible wheels for hovercrafts

   midLeft = spawn(MidTireClass, self,, Location + WheelMidAlong*RotX - WheelMidAcross*RotY + (256 /*WheelVert*/)*RotZ, Rotation);
   midLeft.SetDrawScale3D(vect(1, 1, 1));

midLeft.bHidden = True; // Invisible wheels for hovercrafts

   midRight = spawn(MidTireClass, self,, Location + WheelMidAlong*RotX - WheelMidAcross*RotY + (256 /*WheelVert*/)*RotZ, Rotation);
   midRight.SetDrawScale3D(vect(1, -1, 1));

midRight.bHidden = True; // Invisible wheels for hovercrafts

lPos.X = WheelMidAlong; lPos.Y = -WheelMidAcross;

   midRight.WheelJoint = spawn(class'KCarWheelJoint', self);
   midRight.WheelJoint.KPos1 = lPos/50;
   midRight.WheelJoint.KPriAxis1 = vect(0, 0, 1);
   midRight.WheelJoint.KSecAxis1 = vect(0, 1, 0);
   midRight.WheelJoint.KConstraintActor1 = self;
   midRight.WheelJoint.KPos2 = vect(0, 0, 0);
   midRight.WheelJoint.KPriAxis2 = vect(0, 0, 1);
   midRight.WheelJoint.KSecAxis2 = vect(0, 1, 0);
   midRight.WheelJoint.KConstraintActor2 = midRight;
   midRight.WheelJoint.SetPhysics(PHYS_Karma);

lPos.Y = WheelMidAcross;

   midLeft.WheelJoint = spawn(class'KCarWheelJoint', self);
   midLeft.WheelJoint.KPos1 = lPos/50;
   midLeft.WheelJoint.KPriAxis1 = vect(0, 0, 1);
   midLeft.WheelJoint.KSecAxis1 = vect(0, 1, 0);
   midLeft.WheelJoint.KConstraintActor1 = self;
   midLeft.WheelJoint.KPos2 = vect(0, 0, 0);
   midLeft.WheelJoint.KPriAxis2 = vect(0, 0, 1);
   midLeft.WheelJoint.KSecAxis2 = vect(0, 1, 0);
   midLeft.WheelJoint.KConstraintActor2 = midLeft;
   midLeft.WheelJoint.SetPhysics(PHYS_Karma);

// Initially make sure parameters are synced with Karma KVehicleUpdateParams();

}

// Clean up wheels etc. simulated event Destroyed() {

// Destroy joints holding wheels to car midLeft.WheelJoint.Destroy(); midRight.WheelJoint.Destroy();

// Destroy wheels themselves. midLeft.Destroy(); midRight.Destroy();

Super.Destroyed();

}

// Call this if you change any parameters (tire, suspension etc.) and they // will be passed down to each wheel/joint. simulated event KVehicleUpdateParams() {

Super.KVehicleUpdateParams();

   midLeft.WheelJoint.bKSteeringLocked = true;
   midRight.WheelJoint.bKSteeringLocked = true;
   // unlock rear wheels for steering
   rearLeft.WheelJoint.bKSteeringLocked = false;
   rearLeft.WheelJoint.KProportionalGap = SteerPropGap;
   rearLeft.WheelJoint.KMaxSteerTorque = SteerTorque;
   rearLeft.WheelJoint.KMaxSteerSpeed = SteerSpeed;
   // unlock rear wheels for steering
   rearRight.WheelJoint.bKSteeringLocked = false;
   rearRight.WheelJoint.KProportionalGap = SteerPropGap;
   rearRight.WheelJoint.KMaxSteerTorque = SteerTorque;
   rearRight.WheelJoint.KMaxSteerSpeed = SteerSpeed;
   midLeft.WheelJoint.KSuspHighLimit = SuspHighLimit;
   midLeft.WheelJoint.KSuspLowLimit = SuspLowLimit;
   midLeft.WheelJoint.KSuspStiffness = SuspStiffness;
   midLeft.WheelJoint.KSuspDamping = SuspDamping;
   midRight.WheelJoint.KSuspHighLimit = SuspHighLimit;
   midRight.WheelJoint.KSuspLowLimit = SuspLowLimit;
   midRight.WheelJoint.KSuspStiffness = SuspStiffness;
   midRight.WheelJoint.KSuspDamping = SuspDamping;

// Sync parameters with Karma - even front and rear wheels… Just incase. :P frontLeft.WheelJoint.KUpdateConstraintParams(); frontRight.WheelJoint.KUpdateConstraintParams(); midLeft.WheelJoint.KUpdateConstraintParams(); midRight.WheelJoint.KUpdateConstraintParams(); rearLeft.WheelJoint.KUpdateConstraintParams(); rearRight.WheelJoint.KUpdateConstraintParams();


   // Mass
   frontLeft.KSetMass(TireMass+2); // maybe increase front wheels mass to simulte engine weight??
   frontRight.KSetMass(TireMass+2); // maybe increase front wheels mass to simulte engine weight??
   midLeft.KSetMass(TireMass);
   midRight.KSetMass(TireMass);
   midLeft.RollFriction = TireRollFriction;
   midLeft.LateralFriction = TireLateralFriction;
   midLeft.RollSlip = TireRollSlip;
   midLeft.LateralSlip = TireLateralSlip;
   midLeft.MinSlip = TireMinSlip;
   midLeft.SlipRate = TireSlipRate;
   midLeft.Softness = TireSoftness;
   midLeft.Adhesion = TireAdhesion;
   midLeft.Restitution = TireRestitution;
   midRight.RollFriction = TireRollFriction;
   midRight.LateralFriction = TireLateralFriction;
   midRight.RollSlip = TireRollSlip;
   midRight.LateralSlip = TireLateralSlip;
   midRight.MinSlip = TireMinSlip;
   midRight.SlipRate = TireSlipRate;
   midRight.Softness = TireSoftness;
   midRight.Adhesion = TireAdhesion;
   midRight.Restitution = TireRestitution;

}

// Car Simulation simulated function Tick(float Delta) { local float tana, sFactor;

Super.Tick(Delta);

   WheelSpinSpeed = (frontLeft.SpinSpeed 

+ frontRight.SpinSpeed + rearLeft.SpinSpeed + midLeft.SpinSpeed + midRight.SpinSpeed + rearRight.SpinSpeed)/6;

   // Motor

// MID .. make them wheel spin :]

   midLeft.WheelJoint.KMotorTorque = 0.5 * OutputTorque * TorqueSplit;
   midRight.WheelJoint.KMotorTorque = 0.5 * OutputTorque * TorqueSplit;
   // Braking

if(OutputBrake) { midLeft.WheelJoint.KBraking = MaxBrakeTorque; midRight.WheelJoint.KBraking = MaxBrakeTorque; } else { midLeft.WheelJoint.KBraking = 0.0; midRight.WheelJoint.KBraking = 0.0; }

// Steering

   tana = Tan(6.283/65536 * Steering * MaxSteerAngle);
   sFactor = 0.5 * tana * (2 * WheelFrontAcross) / Abs(WheelFrontAlong - WheelRearAlong);
   // Make rear wheel turn in opposite direction to turn properly: -65536/6.283 
   RearLeft.WheelJoint.KSteerAngle = -65536/6.283 * Atan(tana, (1-sFactor));
   RearRight.WheelJoint.KSteerAngle = -65536/6.283 * Atan(tana, (1+sFactor));

// Handbrake if(OutputHandbrakeOn == true) {

midLeft.LateralFriction = TireLateralFriction + TireHandbrakeFriction; midLeft.LateralSlip = TireLateralSlip + TireHandbrakeSlip;

midRight.LateralFriction = TireLateralFriction + TireHandbrakeFriction; midRight.LateralSlip = TireLateralSlip + TireHandbrakeSlip; } else { midLeft.LateralFriction = TireLateralFriction; midLeft.LateralSlip = TireLateralSlip;

midRight.LateralFriction = TireLateralFriction; midRight.LateralSlip = TireLateralSlip; }

}

defaultproperties { } </uscript>