Legacy:KHoverTank - Unreal Wiki

# Legacy:KHoverTank

### From Unreal Wiki, The Unreal Engine Documentation Site

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 :]

    //=============================================================================
    // 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
    {
    }

Category: Legacy Custom Class (UT2003)

##### Views

- Legacy
- Discussion
- Current revision

##### Search