Legacy:VitalOverdose/ONSVehicleBooster - Unreal Wiki

# Legacy:VitalOverdose/ONSVehicleBooster

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

< Legacy:VitalOverdose
UT2004 :: Actor >> Trigger >> ONSVehicleBooster (Package: custom )

by VitalOverdose - Updated Oct 2007

## Concept

- The ONSVehicleBooster launches a vehicle when touched by using the KAddImpulse() function.
- The Boost will not directly hurt the vehicle in any way unless it collides with something at high speed.

## User Properties.

### Globals

- Default properties will be used to boost a vehicle but the mapper can also set individual properties for a specific vehicle type.
- To stop the ONSVehicleBooster from boosting a specific vehicle type/types just create a VehicleSpecific set of values for the vehicle/vehicles(in the actor properties in unrealed) and leave the 'AppliedBoostForce' values at (x=0,y=0,z=0).

### Boost Direction

The applied boost force is a vector. Thats a point in space with direction and force.

(x=1.0,y=0.0,z=0.0) = Tiny push forward.

(x=-1,y=0.0,z=0.0) = tiny push backwards.

(x=0.0,y=1.0,z=0.0) = tiny push to the left.

(x=0.0,y=-1.0,z=0.0) = tiny push to the right.

(x=0.0,y=0.0,z=1.0) = tiny push Upwards.

(x=0.0,y=0.0,z=-1.0) = tiny push Downwards.

Note: 1 is way to small to move a vehicle , 1000000 is closer to the kind of values you will need.

Option to apply the boost force in relation to either;

- The direction the vehicle is facing when it touches the Booster (Bdirectional = false)
- The direction the Booster actor is facing (Bdirectional = true)

### BotLock

If a bot is driving when a vehicle is boosted it will instantly try to jump out. To stop this from happening any bot driven vehicle that gets boosted is locked until the vehicle has landed and is traveling under a speed that wont panic non-human players .

- The vehicle will get locked until 2 conditions have been met:-
  - 1 - The vehicle is not airborne
  - 2 - The vehicle is traveling < a certain speed ( ReleaseVelocity : default = 800.000000)
- Option to lock human players the same as bots ( bLockHumanPlayers = true ).

More info on how the BotLock works can be found here: BotLock Info

### Boosting backwards

Option to let vehicles be boosted backwards if they reverse into the booster : bCanBoostBackwards

### Re-Boosting

Option to NOT boost a vehicle if its already in flight from another booster. This is very handy for having 2 boosters facing each other over an obstacle : bReBoosts

### Change the Weight of the vehicles

Option to be able to alter the Gravity scale of a vehicle for the duration of the boost. The same rules apply here as with the BotLock system, the weight will be altered on the boosting vehicle until The vehicle is not airborne && the vehicle is traveling < a specified speed (default 900). The default for this property is -1 this disables the weight altering system. This is only designed to alter the gravity scale of a vehicle very slightly so that all vehicles can be made to travel the same distance before landing.

### Boost Empty vehicles

The default for this property is bBoosts_emptyVechicles = false.

### Change the Size of the vehicles

This could be used to boost a vehicle though a small opening. Its original size will be returned when then vehicle has safely landed.

### Optional Spin

This is for making the vehicle spin during the flight. This works exactly the same way as a boost, you have to specify a direction for the kick and a point on the vehicle to apply the that kick to.

Example;

The center of the vehicle has a vector of (x=0.0,y=0.0,z=0.0).

If a vehicle was 150uu long ;

- The front center of the vehicle would be at (x=75.0,y=0.0,z=0.0)
- The back center of the vehicle would be at (x=-75.0,y=0.0,z=0.0)

If a vehicle was 100uu wide ;

- The Left center of the vehicle would be at (x=0.0,y=-50.0,z=0.0)
- The right center of the vehicle would be at (x=0.0,y=50.0,z=0.0)

So if you wanted to flip an ONSRV completely over backwards during a boost you would need a big upwards push and you need to apply the upwards push to the front of the vehicle.

- Spin_AppliedBoostForce = (x=0,y=50,z=1000000.000000);
- Spin_PointOfBoostForce = (x=0.0,y=75.0,z=0.0);

The vehicles property bEjectPassengersWhenFlipped is set to false for the duration of the jump is spin is used.Used together with the weight changing features in this class you can come up with some awesome looking stunts.

### Note

Some special care has to be taken when boosting near thin smeshes like lampposts.the smeshs collision mesh should be backed up with a blocking volume to avoid vehicles getting stuck inside meshes.

- Using to much boost force can cause a vehicle to vanish when boosted and may cause replication errors during an online game, if you want to boost a long distance try altering the weight of the vehicle to help reduce the amount of boost force needed for the jump.

## The Script

Last Updated : Oct 2007

    class ONSVehicleBooster extends triggers
    placeable;

    // Default values: if a valid vehicle touches the booster and doesn't
    // have any specific properties set for that vehicle type set by the mapper
    // then these values will be used for the boost
    var (BoostGlobalValues) bool   bLockHumanPlayers;
    var (BoostGlobalValues) bool   bDirectionalBoost;
    var (BoostGlobalValues) bool   bCanBoostBackwards;
    var (BoostGlobalValues) bool   bReBoosts;
    var (BoostGlobalValues) float  VehicleDrawscale;
    var (BoostGlobalValues) bool   bBoosts_emptyVechicles;
    var (BoostGlobalValues) float  ReleaseVelocity;
    var (BoostGlobalValues) sound  VOC_Boost;
    var (BoostGlobalValues) int    Actor_gravScale;

    var (BoostGlobalValues) vector AppliedBoostForce;
    var                     vector PointOfBoostForce;

    var (BoostGlobalValues) vector Spin_AppliedBoostForce;
    var (BoostGlobalValues) vector Spin_PointOfBoostForce;

    //var(test) class<emitter>   testfx;
    //var emitter                emittedtestfx;

    // Creating a custom variable type to hold the values for each boost that the mapper sets
    // on a specific vehicle.
    struct VecSpec
    {
    var () class <OnsVehicle>  VecType;
    var () bool                bLockHumanPlayers;
    var () bool                bDirectionalBoost;
    var () bool                bCanBoostBackwards;
    var () bool                bBoosts_emptyVechicles;
    var () bool                bReBoosts;
    var () float               ReleaseVelocity;
    var () float               Actor_gravScale;
    var () float               VehicleDrawscale;
    var () vector              Spin_AppliedBoostForce;
    var () vector              Spin_PointOfBoostForce;
    var () vector              AppliedBoostForce;
    var    vector              PointOfBoostForce;
    var () sound               VOC_Boost;
    };
    // the dynamic array containing the new variable type. this is available to the mapper in
    // Unrealed in the actor properties for this class
    var (BotVecBooster) array<VecSpec>      VehicleSpecific;

    var string BoosterID;

    //The rate at which the timer will check the status of any vehicles it may be tracking
    var (BotVecBooster) float ScanRate;

    // Creating a custom variable type to store some details about each vehicle we are tracking
    struct VRefArray
    {
    var OnsVehicle            AVecRef;
    var int                   VecSpecRecNo;
    var float                 OrigActorGravScale;
    var float                 OrigVehicleDrawScale;
    };
    // the dynamic array of the custom VRefArray variable type.
    // This will be a list of all vecs being tracked by the booster
    var array<VRefArray>      VecRefArray;

    // Generic function -Overwriting
    simulated function PostBeginPlay() // called just after start of game play :takes the default values from the
    {                        // previous class and adds then to the vecspecific array in position 0
    VehicleSpecific.insert(0,1);
    VehicleSpecific[0].AppliedBoostForce      = AppliedBoostForce;  //
    VehicleSpecific[0].PointOfBoostForce      = PointOfBoostForce;  // this now frees up the variables

    VehicleSpecific[0].Spin_AppliedBoostForce = Spin_AppliedBoostForce;
    VehicleSpecific[0].Spin_PointOfBoostForce = Spin_PointOfBoostForce;

    VehicleSpecific[0].bDirectionalBoost      = bDirectionalBoost;  // so we can use the genericvecboost
    VehicleSpecific[0].bBoosts_emptyVechicles = bBoosts_emptyVechicles;
    VehicleSpecific[0].bCanBoostBackwards     = bCanBoostBackwards;

    VehicleSpecific[0].bLockHumanPlayers      = bLockHumanPlayers;  // without having to change the code
    VehicleSpecific[0].ReleaseVelocity        = ReleaseVelocity;
    VehicleSpecific[0].Actor_gravScale        = Actor_gravScale;
    VehicleSpecific[0].VehicleDrawscale       = VehicleDrawscale;
    VehicleSpecific[0].VOC_Boost              = VOC_Boost;
    VehicleSpecific[0].bReBoosts              = bReBoosts;
    super.PostBeginPlay();
    }

    // Generic function -Overwriting
    simulated function Touch( Actor Other )
    {
    super.Touch(Other);                    // adds all the contained code from the parent function to this point.
    if ( Other.isa('ONSVehicle') && ((ONSVehicle(other).Driver != none ) || (bBoosts_emptyVechicles)))         // first checks if its been touched by an onsvehicle
       {
        //log ("--------------touched by a vec with tag "$Other.tag);
        BoostVec( ONSVehicle( Other ) );  // calls BoostVec() and passes the actor ref of what touched
       }
    }                                      // us to the function by 'typecasting' it to onsvehicle

    // New custom function
    function int Match_2_VehicleSpecificRec( ONSVehicle A_Vec )
    {
    local int I;
    for ( i = 1 ; i < VehicleSpecific.length ; I++ )       // cycles though all the vehicle refs in the array
         if ( VehicleSpecific[i].VecType == A_Vec.class )  // if the passed vehicle type matches the one in the current record
              return I;                                    // returns the value stored in I
    return 0;            // if no match is found the default values are used by return in a 0
    }

    // New custom function
    function int Already_Tracking( ONSVehicle A_Vec )  // checks to see if we are already tracking a vehicle
    {                                                  // by checking all the records of the vehicle currently being tracked
    local int I;                                       // for a match in the valid vehicle ref
    for ( i = 0 ; i < VecRefArray.length ; I++ )       // cycles though all the vehicle refs in the array
          if ( VecRefArray[i].AVecRef == A_Vec )
               return i;
    return -1;          // if no match is found a flag of 01 is returned
    }

    // New custom function
    simulated function BoostVec(ONSVehicle AVec)  // this function qualifies any actor that touches us
    {                                   // + files them into an array of vehicles being tracked
    local int VecTypeRecNumb;           // then retrieves any Specific vehicle type data if needed
    //log ("--------------function BoostVec(ONSVehicle AVec)");                                    // checks if botlock is needed

    if ( Already_Tracking(Avec) > -1 )  // then finally calls the boost function to kick the vehicle
        {
         //log ("--------------( Already_Tracking(Avec) > -1 )");
         return;
        }

    VecTypeRecNumb     = Match_2_VehicleSpecificRec(Avec);

    // log ("--------------VecTypeRecNumb = "$VecTypeRecNumb);

    AppliedBoostForce      = VehicleSpecific[VecTypeRecNumb].AppliedBoostForce; // re-using the old values that contained the defaults
    PointOfBoostForce      = VehicleSpecific[VecTypeRecNumb].PointOfBoostForce; // as these values are now being stored in position 0
    bDirectionalBoost      = VehicleSpecific[VecTypeRecNumb].bDirectionalBoost; // of the VecSpecArray.
    bCanBoostBackwards     = VehicleSpecific[VecTypeRecNumb].bCanBoostBackwards;
    Spin_AppliedBoostForce = VehicleSpecific[VecTypeRecNumb].Spin_AppliedBoostForce;
    Spin_PointOfBoostForce = VehicleSpecific[VecTypeRecNumb].Spin_PointOfBoostForce;
    VehicleDrawscale       = VehicleSpecific[VecTypeRecNumb].VehicleDrawscale;
    bLockHumanPlayers      = VehicleSpecific[VecTypeRecNumb].bLockHumanPlayers;
    ReleaseVelocity        = VehicleSpecific[VecTypeRecNumb].ReleaseVelocity;
    VOC_Boost              = VehicleSpecific[VecTypeRecNumb].VOC_Boost;
    Actor_gravScale        = VehicleSpecific[VecTypeRecNumb].Actor_gravScale;
    VehicleDrawscale       = VehicleSpecific[VecTypeRecNumb].VehicleDrawscale;
    bReBoosts              = VehicleSpecific[VecTypeRecNumb].bReBoosts;

            if ( Avec.tag == 'Boosting')
               {
                if ( bReBoosts )
                   {
                    //log ("-------------- ( Avec.tag == 'Boosting')");
                    Avec.tag ='Stolen';          // log (" -------------- bReBoosts Avec.tag ='Stolen'");
                   }
                else
                   return;
                }
           else
             Avec.tag = 'Boosting';

        ////log ("--------------Actor_gravScale"$Actor_gravScale);

        VecRefArray.insert(0,1);                             // Inserts a new blank slot into the array.
        VecRefArray[0].AVecRef            = Avec;            // assigns the valid onsvehicle ref to the array
        VecRefArray[0].VecSpecRecNo       = VecTypeRecNumb;

     if (!Avec.isplayerpawn())
        {
         AVec.bDriverCannotLeaveVehicle    = true;            // lock the vec
         //log ("-------------- (!Avec.isplayerpawn())....locking the vec ");
        }

     if (VehicleDrawscale > 0)
        {
         VecRefArray[0].OrigVehicleDrawScale = Avec.Drawscale;
         Avec.SetDrawscale(VehicleDrawscale);
         //log ("-------------- (VehicleDrawscale > 0) setting actor VehicleDrawscale to "$VehicleDrawscale);
        }

     if (Actor_gravScale > 0)
        {
         VecRefArray[0].OrigActorGravScale = Avec.kGetActorGravScale();
         Avec.kSetActorGravScale(Actor_gravScale);
         //log ("-------------- (Actor_gravScale > 0) setting actor grav scale to "$Actor_gravScale);
        }

     if ( VecRefArray.length == 1 )                    // if this is the only record call the timer() function
        {
         SetTimer( ScanRate , true );                 // call the timer() function in 'timerfrequncy'seconds
        //log ("-------------- ( VecRefArray.length == 1 ) ");
        }

    GenericVehicleBoost(AVec); // calls the boost fuction
    }

    // New custom function                         -+
    function  GenericVehicleBoost(onsvehicle TheTargetVec)
    {
    local float VecThrottle;

    //log ("--------------GenericVehicleBoost(onsvehicle "$TheTargetVec$")");

    if ( VOC_Boost!= None )
         Playsound ( VOC_Boost ) ;                                  // plays the boost sound fx

    VecThrottle = TheTargetVec.Throttle;

    if ( ( VecThrottle < 0 ) && (bCanBoostBackwards))
         AppliedBoostForce.X = AppliedBoostForce.X *(-1);

    if ( bDirectionalBoost == True)
         TheTargetVec.KAddImpulse( AppliedBoostForce >> self.Rotation, PointOfBoostForce >> self.Rotation ) ;   // boosts in the direction the boosters facing
    else
         TheTargetVec.KAddImpulse( AppliedBoostForce >> TheTargetVec.Rotation , PointOfBoostForce >> TheTargetVec.Rotation ) ;  // boosts in the direction the vehicles facing

    if ( Spin_AppliedBoostForce == vect(0,0,0) )
         return;

    TheTargetVec.KAddImpulse( Spin_AppliedBoostForce >> TheTargetVec.Rotation , Spin_PointOfBoostForce >> TheTargetVec.Rotation ) ;  // boosts in the direction the vehicles facing
    TheTargetVec.bEjectPassengersWhenFlipped = False;
    }

    // The Timer function
    // ==================
    // the timer function here is used rather like a radar.
    // The scan rate is the amount of sweeps it does a second.
    //
    // It only gets called if there are vehicles being tracked. Otherwise it shuts down
    //
    // On each sweep it;-
    //                  checks all the vehicles being tracked to see if they are;
    //                    dead : if so the record is removed from the array
    //       On the ground yet : if so
    //                           are they < the (mapper)set velocity
    //                                      if they are < (mapper)set Vellocity
    //                                                    remove from the array
    //                                                    Unlock the vehicle
    // Generic function - Overwriting
    simulated function Timer()
    {
     local int             VecSpecRecNo;
     local bool            bVehicleDead;
     local bool            bVecGrounded;
     local float           VehicleVel;
     local float           VehicleDScale;
     local float           ReleaseVel;
     local ONSVehicle      VehicleRef;
     local int             I;

     //log ("--------------Timer(): Tracking "$VecRefArray.length$" Vehicles).");

     for (I = 0 ; I < VecRefArray.length ; I++ )
         {
         VehicleRef    =  VecRefArray[I].AVecRef;                         // retrieves the Vehicle ref

         //log ("--------------Timer(): Checking status of ":$VecRefArray[I].AVecRef);

         VecSpecRecNo  =  VecRefArray[I].VecSpecRecNo;                    // matches vecspecific rec to the Vehicle ref
         bVecGrounded  =  VehicleRef.bVehicleOnGround;                    // retrieves  ir the vec is airborn or not
         bVehicleDead  =  VehicleRef.bVehicleDestroyed;                   // Assigns status of the vec to bDead
         VehicleVel    =  Vsize(VehicleRef.Velocity);                     // Gets the Vehicle Velocity
         ReleaseVel    =  VehicleSpecific[VecSpecRecNo].ReleaseVelocity;
         VehicleDScale =  VehicleSpecific[VecSpecRecNo].VehicleDrawscale;

         // assigning the values to variables in this way makes the decision making in the rest of this
         // function easier to understand and modify at a later date.

         if (VehicleRef == None || bVehicleDead )      // removes any invalid records (records with no VecRef)
            {
             //log ("-------------- (VehicleRef == none || bVehicleDead ). removing"$I$" from the array");
             VecRefArray.remove(I , 1);                // removes the record from the array
             I -= 1;                                   // adjusts the counter to move back 1 place
            }
       else
          if ( VehicleRef.Tag=='Stolen')
             {
              // log ("-------------- ( VehicleRef.Tag=='Stolen')..removing from the array and setting its tag to BOOSTING ");
              VehicleRef.Tag = 'Boosting';
              VecRefArray.remove(I , 1);                // removes the record from the array
              I -= 1;                                   // adjusts the counter to move back 1 place
             }
      else
         if (( bVecGrounded == true ) && ( VehicleVel < ReleaseVel ) ) // checks if its on the ground and under the
            {                                                          // release velocity
             //log ("-------------- (( bVecGrounded == true ) && ( VehicleVel < ReleaseVel ) )..RETURNING orig properties to the vehicle ");

             if (VehicleRef.KGetActorGravScale() ~= VecRefArray[I].OrigActorGravScale)
                 VehicleRef.kSetActorGravScale(VecRefArray[I].OrigActorGravScale);

             if (VehicleDScale > 0)
                 VehicleRef.SetDrawScale ( VecRefArray[I].OrigVehicleDrawScale );

             VehicleRef.bEjectPassengersWhenFlipped = true;
             VehicleRef.bDriverCannotLeaveVehicle   = false; // unlocks the vec
             VehicleRef.Tag                         = 'tag';
             VecRefArray.remove(I , 1);                                // removes the record from the array
             I -= 1;                                                   // adjusts the counter to move back 1 place
            }
          }

    if ( VecRefArray.length > 0 )
       {
       SetTimer( ScanRate , false );           // will only call the timer() once ,if its tracking
       //log("end of timer function and the vecref array was > 0 so im setting timer again");
       }
    }

    defaultproperties
    {
         bBoosts_emptyVechicles=false
         bCanBoostBackwards=True
         VehicleDrawscale=-1.000000
         ReleaseVelocity=800.000000
         VOC_Boost=Sound'AnnouncerEvil.Booster'
         Actor_gravScale=-1
         AppliedBoostForce=(X=9000000.000000,Z=2000000.000000)
         ScanRate=0.500000
         Texture=Texture'XEffectMat.Shock.Shock_ring_a'
         CollisionRadius=150.000000
         CollisionHeight=150.000000
         bUseCylinderCollision=True
    }

## Easy to embed into a level

You can download this script in .uc or .u format onsvehiclebooster.uc,MyLevel.u

#### Mylevel.u

If you would like to embed this code in your level without having to worry about having to have an extra .u file for people to install before playing the map you can use your actor class browser to import this MyLevel.u file. Once imported it will show up in your class tree under triggers and you can forget about the .u file. Like any resource you save to package mylevel if you dont use the class in the level when you save it you wont have it available when you open the level next time. This is nothing to worry about as you just have to import the mylevel.u file and everything will appear in the class tree again.

## Related Topics

- ONSVehicleBooster
- ONSVehicleTeleporter
- ONSVehicleFxTagger

## Discussion

Category: Legacy Custom Class (UT2004)

##### Views

- Legacy
- Discussion
- Current revision

##### Search