Cogito, ergo sum
Legacy:VitalOverdose/ONSVehicleTeleporter
Contents
Overview[edit]
This class will teleport a vehicle without it exploding when it pops out on the other side.
There is only 1 actor to this teleport system as any actor that has it collision switched off can be a teleport exit point as long as its tagname matches the one specified by the mapper in the vehicle teleporters properties. Vehicle nodes and path nodes are ideal for teleport exits.
If you link more than one actor to the the vehicle teleporter then one will be picked at random at the time of teleportation.This is so you can add a vehicle teleporter to existing maps very quickly as most maps have pathnodes/vehiclePathnodes already set out in roughly the right places.
- Remember you don't HAVE to use multiple spawn locations If you use 1 teleporter and 1 spawn location its no more difficult to visualize than using a standard teleporter system.
Skeleton script[edit]
This is the basic script need to teleport vehicles
class ONSVehicleTeleporter extends Triggers placeable; var Array<Actor> TeleportExitList; Simulated function postbeginplay() { scanTeleportExitList(); } Simulated function Touch(Actor Other) { if (Other.IsA('ONSVehicle')) VehicleTeleport(ONSVehicle(Other)); super.Touch(Other); } Simulated function scanTeleportExitList() { local Actor FoundTeleportExit; if (TeleportExitList.Length > 0 ) TeleportExitList.Remove( 0 , TeleportExitList.Length ); foreach AllActors( Class'Actor' , FoundTeleportExit,'TeleportExit' ) { TeleportExitList.Insert( 0 , 1 ); TeleportExitList[0] = FoundTeleportExit; } } Simulated function VehicleTeleport(ONSVehicle Teleporting) { local Rotator NewRotation; local Vector BoostForce; local EPhysics VehiclePhysicsOnEntry; Local int PickedTeleportExit; NewRotation = Teleporting.Rotation; VehiclePhysicsOnEntry = Teleporting.Physics; BoostForce = Teleporting.Velocity * 500; PickedTeleportExit = rand(TeleportExitList.Length-1)+1; Teleporting.SetPhysics(PHYS_None); Teleporting.setLocation(TeleportExitList[PickedTeleportExit].Location); NewRotation.Yaw = TeleportExitList[PickedTeleportExit].Rotation.Yaw + Teleporting.Rotation.Yaw - Self.Rotation.Yaw; PostVehicleTeleport(Teleporting,PickedTeleportExit,NewRotation,VehiclePhysicsOnEntry,BoostForce); } Simulated function PostVehicleTeleport( ONSVehicle Teleporting,int TeleportExitnumb,Rotator NewRotation,EPhysics VehiclePhysicsOnEntry,Vector BoostForce,optional Vector PointOfBoostForce) { Teleporting.SetPhysics(VehiclePhysicsOnEntry); Teleporting.Controller.moveTimer = -1.0; Teleporting.SetmoveTarget(Self); Teleporting.Controller.SetRotation(NewRotation); Teleporting.SetRotation(NewRotation); if ( Teleporting.IsA('ONSChopperCraft') || Teleporting.IsA('ONSHoverCraft') || Teleporting.IsA('ONSPlaneCraft')) Teleporting.KSetStayUpright( True,True); Teleporting.KAddImpulse(BoostForce >> Rotation, PointOfBoostForce >> Rotation); }
A single function[edit]
Here the whole thing is squashed down into a single function. The teleporting itself is very smooth (blink and you'll miss it) and the system is calibrated to give you the same exit speed as you entered with.
- Any actor can be used as a 'teleport exit' as long as it has its collision turned off
- If VecTel is called without having a valid ONS Vehicle ref passed to it then the function will scan the level for
TeleportExits with a name tag that matches the name specified by the mapper and record them in a dynamic array.
- If VecTel() is called and a valid vehicle reference is passed to it then the function will teleport the vehicle to
the teleportexit.
- If more than 1 actor has the same tagname that the vehicle teleporter is looking for then an exit will be picked at random from those actors at the time of teleporting.
Note[edit]
- Bots are likley to bail out of the vec after teleporting.
class ONSVehicleTeleporter extends Trigger placeable; var name TeleportingToName; var array <Actor> TeleportExitList; Simulated function Vectel(Vehicle VehicleToTeleport) { local Actor FoundTeleportExitActor; local EPhysics VehiclePhysicsOnEntry; local Rotator NewRotation; local Vector BoostForce; local Vector PointOfBoostForce; Local int ChosenTeleportExitPoint; if (VehicleToTeleport == none) { // this clears out the array if it has anything in it if ( TeleportExitList.Length > 0 ) TeleportExitList.Remove(0,TeleportExitList.Length); // this scans for any dynamic actor with the tag name TeleportExitPoint; foreach AllActors(Class'actor',FoundTeleportExitActor,TeleportingToName) { TeleportExitList.insert(0,1); TeleportExitList[0]=FoundTeleportExitActor; } } // grabs some properties from the vehicle and stores them NewRotation = VehicleToTeleport.Rotation; VehiclePhysicsOnEntry = VehicleToTeleport.Physics; BoostForce = VehicleToTeleport.Velocity * 500; //Picks a random number based on the length of the array holding the teleport exit points ChosenTeleportExitPoint = rand(TeleportExitList.Length-1)+1; // Switches off the physics for the vehicle while it is teleported VehicleToTeleport.SetPhysics(PHYS_None); VehicleToTeleport.setLocation(TeleportExitList[ChosenTeleportExitPoint].Location); // The vehicles original physics is now returned to the way it was on entry VehicleToTeleport.SetPhysics(VehiclePhysicsOnEntry); VehicleToTeleport.Controller.moveTimer = -1.0; VehicleToTeleport.SetmoveTarget(Self); // Now the vehicle has been teleported it has to rotated to the direction it was facing // when it entered the vehicle teleporter. NewRotation.Yaw = TeleportExitList[ChosenTeleportExitPoint].Rotation.Yaw + VehicleToTeleport.Rotation.Yaw - Self.Rotation.Yaw; VehicleToTeleport.Controller.SetRotation(NewRotation); VehicleToTeleport.SetRotation(NewRotation); // if its a flying vehicle that just got teleported then we have to make sure it stays upright if ( VehicleToTeleport.IsA('ONSChopperCraft') || VehicleToTeleport.IsA('ONSHoverCraft') || VehicleToTeleport.IsA('ONSPlaneCraft')) VehicleToTeleport.KSetStayUpright( True,True); // To make sure the vehicle pops out the other side at the same speed it went into the // teleporter we have to give it a bit of a nudge VehicleToTeleport.KAddImpulse(BoostForce >> Rotation, PointOfBoostForce >> Rotation); }
Latest Version[edit]
New in this version:
* Options to destroy vehicles blocking teleport exits * Options to Boost Vehicles blocking teleport exits out the way. * vehicles blocking the teleporter exit can be boosted in the direction the teleporter exit is facing (recomended) or in the direction they are facing , controled by property bUseExitRotationWhenClearing. * The teleport exit points can be rescaned for thier locations so you could have a moving object as a teleporter exit if you wanted. * Theres a global value bEnabled with can be use to switch the teleporter exit on/off which can be toggled by triggering the vehicle teleport.
//============================================================================= // VehicleTeleporter By vitaloverdose, Updated sept 2007 // http://www.Vitaloverdose.com // This is part of the 'Vitals Pro Mapping Tools' Mod // Download //============================================================================= class ONSVehicleTeleporter extends Triggers placeable; var() bool bEnabled; // Teleporter is turned on; var(TeleportExit) class<DamageType> BlockingVehicle_DamageType; var(TeleportExit) float ReScan_TeleportExitLocations; var(TeleportExit) bool bUseExitRotationWhenClearing; var(TeleportExit) bool bDestroyVehiclesBlockingExits; var(TeleportExit) bool bBoostVehiclesBlockingExits; var(TeleportExit) vector ClearTeleportExitBoostForce; var(TeleportExit) name TeleportExitTag; //The tag name for the teleport exits var (BotLock) float BotCaptureTime; var (BotLock) float ScanRate; var float ReScan_Counter; // keeps track of time till next rescan //Creating a custom variable type to store some details about each vehicle we are tracking struct VRefArray { var OnsVehicle ONSVehicleRef; var float CaptureTime; }; // the dynamic array of the custom VRefArray variable type. // This will be a list of all Vehicles being tracked by the teleporter var array <VRefArray> VehicleRefArray< SEMI > var array <Actor> TeleportExitList; // Generic function -Overwriting function Postbeginplay() { ScanForTeleportExitList(); if (ReScan_TeleportExitLocations > 0 ) ReScan_Counter = ReScan_TeleportExitLocations; super.Postbeginplay(); } // Generic function -Overwriting function Touch( Actor Other ) { super.Touch(Other); // adds all the contained code from the parent function to this point. if ((bEnabled==true) && ( Other.isa('ONSVehicle'))) // first checks if its been touched by an onsvehicle TeleportVehicle(ONSVehicle(Other)); } // Generic function -Overwriting function Trigger( actor Other, pawn EventInstigator ) { if (bEnabled) bEnabled = false; else bEnabled = true; super.Trigger(other,EventInstigator); } // New custom function // This function scans all the actor in the level to find a tag name that matches the one // set by the mapper in unrealed. Simulated function ScanForTeleportExitList() { local Actor FoundTeleportExit; // the array is emptied if (TeleportExitList.Length > 0 ) TeleportExitList.Remove( 0 , TeleportExitList.Length ); foreach AllActors( Class'Actor' , FoundTeleportExit,TeleportExitTag ) { TeleportExitList.Insert( 0 , 1 ); // makes a space in the array TeleportExitList[0] = FoundTeleportExit; // inserts the valid actor ref of any actor found } //log("------------------TeleportExitList.Length"$TeleportExitList.Length); } // New custom function // this checks the array with the vehcile refs to find a match with a valid vehicle // ref that gets passed to it. The function will return -1 if there is no match or // the position in the array of any matching valid onsvehicle reference function int Already_Tracking( ONSVehicle A_Vehicle ) { local int I; for ( i = 0 ; i < VehicleRefArray.length ; I++ ) if ( VehicleRefArray[i].ONSVehicleRef == A_Vehicle ) return i; return -1; // if no match is found a flag of -1 is returned } // Generic function - Overwriting // the timer has to functions here // checks if a rescan is needed // checks each bot being tracked to see if they have been locked in fot the time specified // by the mapper in unrealed. function Timer() { local int I; local float VehicleTime; local ONSVehicle VehicleRef; local bool bVehicleDead; //take care of the rescan if (ReScan_TeleportExitLocations > 0 ) if ( ReScan_Counter < 0 ) ScanForTeleportExitList(); else ReScan_Counter -= ScanRate; // checks the bots capture times if (VehicleRefArray.length > 0) { for (i = 0 ; i < VehicleRefArray.length ; I++ ) { VehicleRef = VehicleRefArray[i].ONSVehicleRef; // retrieves the Vehicle ref bVehicleDead = VehicleRef.bVehicleDestroyed; // Assigns status of the Vehicle to bDead VehicleTime = VehicleRefArray[i].CaptureTime; // asigns the capture time rom the array to a variable VehicleTime = VehicleTime - ScanRate; // takes off the scan rate time VehicleRefArray[i].CaptureTime = VehicleTime; // assigns value back to the array if (VehicleRef == None || bVehicleDead ) // removes any invalid records (records with no VehicleRef) { VehicleRefArray.remove(i , 1); // removes the record from the array i -= 1; // adjusts the counter to move back 1 place } else if ( VehicleTime < 0 ) { // release velocity VehicleRefArray[i].ONSVehicleRef.bDriverCannotLeaveVehicle = false; // unlocks the Vehicle VehicleRefArray.remove(i , 1); // removes the record from the array i -= 1; // adjusts the counter to move back 1 place } } } // the timer isnt set to repeate:- This is to help optimization by only having it // running if there is anything being tracked if ( VehicleRefArray.length > 0 ) SetTimer( ScanRate , false ); // will only call the timer() once ,if its tracking else if ( ReScan_TeleportExitLocations > 0 ) // if theres no bots to track set the timer to the SetTimer( ReScan_TeleportExitLocations - ReScan_Counter , false ); // next rescan rime ..if any super.Timer(); } // New custom function // this takes care of the teleporting of the vehicle. // the vehicles physics are switched of until it reaches the teleport Destination // the vehicle has to be kicked to get it moving at the same speed as it entered // the vehicle teleporter , this is done using KaddImpulse() // the direction of the vehicle is the same on exit as when it entered the teleporter // Bots are captured by locking the vehicle to stop them from jumping out after teleporting Simulated function TeleportVehicle(ONSVehicle Teleporting) { local Vector TeleportExit_Location; // the vector location of the picked teleport exit local Rotator NewRotation; // the rotion to set the vehicle after teleporting local Vector BoostForce; // the power and direction of the kick on exit local EPhysics VehiclePhysicsOnEntry; // the vehicle cant be teleported with its physics on local actor TeleportExit; // so the physics are backed up prior to the teleport if (!Teleporting.IsPlayerPawn() && Already_Tracking(Teleporting) == -1) { VehicleRefArray.insert(0,1); // Inserts a new blank slot into the array. Teleporting.bDriverCannotLeaveVehicle = true; // locks the vehicle VehicleRefArray[0].ONSVehicleRef = Teleporting; // assigns the valid onsvehicle ref to the array VehicleRefArray[0].CaptureTime = BotCaptureTime; // assigns the botcapturetime // this switchs on the timer function to keep track of the boosted vehicles when there // are any vehicle to track if ( VehicleRefArray.length > 0 ) SetTimer( ScanRate , false ); } // backs up the current vehcile rotation and physics NewRotation = Teleporting.Rotation; VehiclePhysicsOnEntry = Teleporting.Physics; // calculates the amount of 'kick' to give the vehicle so its travleing the same speed on // exit as it was when it touched the vehicle teleporter. BoostForce = Teleporting.Velocity * 500; // the vector location of the teleport exit is used to teleport the vehicle to TeleportExit = PickAVehicleTeleportExit() ; // switches of the vehicle physics ready to teleport Teleporting.SetPhysics(PHYS_None); // gets the vector location of the teleport exit actor TeleportExit_Location = TeleportExit.Location; // uses the vector location of the picked teleport point to set the new position of the vehicle Teleporting.setLocation(TeleportExit_Location); //calculates new rotation for the vehicle in relation to the vehicle exit NewRotation.Yaw = TeleportExit.Rotation.Yaw + TeleportExit.Rotation.Yaw - Self.Rotation.Yaw; // sets the vehicles physics back the way it was before the teleport Teleporting.SetPhysics(VehiclePhysicsOnEntry); Teleporting.Controller.moveTimer = -1.0; Teleporting.SetmoveTarget(Self); // The new rotation is applied to the vehicle Teleporting.Controller.SetRotation(NewRotation); Teleporting.SetRotation(NewRotation); // this makes sure all none ground based vehicle are the right way up on exit if ( Teleporting.IsA('ONSChopperCraft') || Teleporting.IsA('ONSHoverCraft') || Teleporting.IsA('ONSPlaneCraft')) Teleporting.KSetStayUpright( True,True); // the vehicle wont exit moving unless its given a kick VehicleBoost(Teleporting,BoostForce,NewRotation); } // New custom function // used to get the vehicles moving again when they pop out of the vehicle exit // used to clear the vehicleteleporter exits. function VehicleBoost(ONSVehicle AVehicle,optional vector BForce,optional rotator NewRotation) { local rotator BoostRotation; local vector PointOfBoostForce; if (NewRotation == BoostRotation) BoostRotation = AVehicle.rotation; else BoostRotation = NewRotation; AVehicle.KAddImpulse( BForce >> BoostRotation , PointOfBoostForce >> BoostRotation ); } // New custom function // a short function for picking an actor/random actor from the list of available // teleporter exit list function actor PickAVehicleTeleportExit() { local int PickedTeleport_ExitNunb; if (TeleportExitList.Length>1) rand(TeleportExitList.Length); else PickedTeleport_ExitNunb = 1; if (PickedTeleport_ExitNunb != 0 ) PickedTeleport_ExitNunb–; return TeleportExitList[PickedTeleport_ExitNunb]; } // New custom function function ClearTeleportExitOfVehicles(Actor TeleportExit) { local array<ONSVehicle> FoundVehicles; local int inc; local rotator BoostRotation; if (TeleportExit == none) { log ("ClearTeleportExitOfVehicles(Actor TeleportExit) : passed no exit"); return; } FoundVehicles = ScanTeleportExitForBlockage(TeleportExit); if (FoundVehicles.length < 1 ) return; for (inc=0;inc < FoundVehicles.length;inc++) { if (bUseExitRotationWhenClearing) { BoostRotation = TeleportExit.rotation; VehicleBoost(FoundVehicles[inc],ClearTeleportExitBoostForce,BoostRotation); } else if (bDestroyVehiclesBlockingExits) FoundVehicles[inc].TakeDamage(10000, None, FoundVehicles[inc].Location, vect(0,0,0), BlockingVehicle_DamageType); } } // New custom function function array<ONSVehicle> ScanTeleportExitForBlockage(actor TeleportExit) { local ONSVehicle FoundVehicle; local array<ONSVehicle> FoundVehicles; local array<VRefArray> TrackingVehiclesCopy; local int inc; TrackingVehiclesCopy = VehicleRefArray< SEMI > foreach TouchingActors(class'ONSVehicle',FoundVehicle) { for (inc = 0 ;inc < TrackingVehiclesCopy.length;inc ++) { if (TrackingVehiclesCopy[inc].CaptureTime < (BotCaptureTime-1.00)) { FoundVehicles.insert(0,1); FoundVehicles[0] = FoundVehicle; } else TrackingVehiclesCopy.remove(inc,1); } } return FoundVehicles; } defaultproperties { bEnabled=True BlockingVehicle_DamageType=Class'Engine.Crushed' ReScan_TeleportExitLocations=-1.000000 bUseExitRotationWhenClearing=True bBoostVehiclesBlockingExits=True ClearTeleportExitBoostForce=(X=2000000.000000,Z=500000.000000) TeleportExitTag="TeleportExit" ScanRate=0.500000 RemoteRole=ROLE_SimulatedProxy Texture=Texture'XEffectMat.Shock.Shock_ring_a' CollisionRadius=150.000000 CollisionHeight=150.000000 }