Mostly Harmless
Legacy:VitalOverdose/ONSVehicleBooster
by VitalOverdose - Updated Oct 2007
Contents
Concept[edit]
- 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.[edit]
Globals[edit]
- 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[edit]
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[edit]
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[edit]
Var bCanBoostBackwards : Option to let vehicles be boosted backwards if they reverse into the booster.
Re-Boosting[edit]
Var bReBoosts : Is an 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.
Change the Weight of the vehicles[edit]
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[edit]
The default for this property is bBoosts_emptyVechicles = false.
Change the Size of the vehicles[edit]
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[edit]
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[edit]
- Some special care has to be taken when boosting near thin static meshes like lampposts and trees etc .The static meshe default collision mesh should be reinforced by adding a blocking volume to avoid vehicles getting stuck inside static 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[edit]
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< SEMI > // 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 }
Related Topics[edit]
- Vehicles
- ONSVehicle
- AllMapVehicleFactory
- QuickVehicleSpawner
- ONSVehicleTeleporter
- ONSVehicleEjectionTrigger
- ONSVehicleSpeedTrap
- ONSVehicleFXTagger