| Home Page | Recent Changes

VitalOverdose/VehicleTeleporter

UT2004 :: Actor >> Trigger >> VehicleTeleporter (Package: custom)
 

by VitalOverdose

Part of Vital'sPMT

Overview

I've seen quite a few attempts at a vehicle teleporter but none that i was really happy with so i had a go at making one myself.

The thing is with this vehicle teleporter is you only need 1 of them for it to work. at post begin play it scans all the navigationpoints on the level and records any that have 'TP' in their tag property. The vehicle teleporter then picks one at random to teleport you to. The effect is very smooth.

Simulated Function scanTpAct()
{
Local Actor FoundTelPoint;
if (TpAct.Length>0) TpAct.Remove(0,TpAct.Length);
ForEach AllActors( Class'Actor' , FoundTelPoint,'TP' )
   {
   TpAct.Insert(0,1);
   TpAct[0] = FoundTelPoint;
   }
}

There is no real need to have the vectel function and the posttel function separate from each other. the whole thing works quite well in a single function but i have split it up this way so its easyer to understand/modify. The vec collides with the VecTeleporter and the vec teleporter records the speed and rotaion details for the vehicle bfore setting its physics to none.A random spawn point is picked at this point and once the physics has been set to none the vehicle is relocated to its new point in the map.

Simulated function Vectel(Pawn Teleporting)
{
Local Rotator  oldRot,newrot; 
Local Vector   Abf; 
Local EPhysics Entryphysics; 
Local Int      PickedTelPoint;
NewRot         = Teleporting.Rotation;
EntryPhysics   = Teleporting.Physics;
ABF            = Teleporting.Velocity * 500;
PickedTelPoint = Rand(TpAct.Length-1)+1;
Teleporting.SetPhysics(PHYS_None);
Teleporting.setLocation(TpAct[pickedTelPoint].Location);
OldRot         = Teleporting.Rotation;
NewRot.Yaw     = TpAct[pickedTelPoint].Rotation.Yaw + Teleporting.Rotation.Yaw - Self.Rotation.Yaw;
PostTel(Teleporting,pickedTelPoint,Newrot,EntryPhysics,abf);
}

In the posttel function the vehicle is given back its origional physics and a correct viewpoint based on the navigation points direction is set. Also the code makes sure that flying vehicles remain upright. Then to complete the effect a scaled boost is applied to the vehicle in the direction the navigation point is facing.

 
Simulated Function  Posttel( Pawn Teleporting,int telPointnumb,Rotator Newrot,EPhysics EntryPhysics,Vector Abf,optional 
Vector pbf)
{
Teleporting.SetPhysics(EntryPhysics);
Teleporting.Controller.moveTimer = -1.0;
Teleporting.SetmoveTarget(Self);
Teleporting.Controller.SetRotation(newRot);
Teleporting.SetRotation(newRot);
if ( Teleporting.IsA('ONSChopperCraft') ||
     Teleporting.IsA('ONSHoverCraft')   ||  
     Teleporting.IsA('ONSPlaneCraft'))  
   {
    Teleporting.KSetStayUpright( True,True);
   }
Vehicle(Teleporting).KAddImpulse(abf >> Rotation, pbf >> Rotation);
}

Full Script

Here's the complete script:

//=============================================================================
// VehicleTeleporter By vitaloverdose, Feb 2006, http://www.Vitaloverdose.com
// This is part of the 'Vitals Pro Mapping Tools' Mod 
// Full class list http://wiki.beyondunreal.com/wiki/Vital's_Pro_Mapping_Tools
// Direct Download the Mod in zipped format Http://promappingtools.zapto.org
//=============================================================================


class VehicleTeleporter extends trigger
placeable;

var Array<actor> TpAct;

Simulated Function scanTpAct()
{
 Local Actor FoundTelPoint;
 if (TpAct.Length>0) 
    {
     TpAct.Remove(0,TpAct.Length);
    }
 ForEach AllActors( Class'Actor' , FoundTelPoint,'TP' )
                  {
                   TpAct.Insert(0,1);
                   TpAct[0] = FoundTelPoint;
                  }
}

Simulated function Vectel(Pawn Teleporting)
{
Local Rotator  oldRot,newrot; 
Local Vector Abf; 
Local EPhysics Entryphysics; 
Local Int pickedTelPoint;

NewRot         = Teleporting.Rotation;
EntryPhysics   = Teleporting.Physics;
ABF            = Teleporting.Velocity * 500;
PickedTelPoint = rand(TpAct.Length-1)+1;
Teleporting.SetPhysics(PHYS_None);
Teleporting.setLocation(TpAct[pickedTelPoint].Location);
OldRot       = Teleporting.Rotation;
NewRot.Yaw   = TpAct[pickedTelPoint].Rotation.Yaw + Teleporting.Rotation.Yaw - Self.Rotation.Yaw;
Posttel(Teleporting,pickedTelPoint,Newrot,EntryPhysics,abf);
}

Simulated Function PostTel( Pawn Teleporting,int telPointnumb,Rotator Newrot,EPhysics EntryPhysics,Vector Abf,optional Vector pbf)
{
Teleporting.SetPhysics(EntryPhysics);
Teleporting.Controller.moveTimer = -1.0;
Teleporting.SetmoveTarget(Self);
Teleporting.Controller.SetRotation(newRot);
Teleporting.SetRotation(newRot);

if ( Teleporting.IsA('ONSChopperCraft') ||
     Teleporting.IsA('ONSHoverCraft')    ||
     Teleporting.IsA('ONSPlaneCraft'))
     Teleporting.KSetStayUpright( True,True);

Vehicle(Teleporting).KAddImpulse(abf >> Rotation, PBF >> Rotation);
}

In this final revision the vehicle teleporter can be set to rescan the tp point at regular intervals. Quick simply this means you can have 'moving vec telpoints' as long as the actor with 'TP' as a tag is not solid.

Also the teleport will check to see if a spawn point is occupied before attempting to teleport a vehicle to that spot. if that spot is occupied by a solid actor the vehicleteleporter will pick another at random and test to see if that spot is suitable.

Also this version of the script has added fx;- ambiant fx and teleportfx.

the ambiant fx is really there as a visual marker to where the vehicle teleport is while playing.Also the are some sound fx that can be set in Unrealed.

//=============================================================================
// VehicleTeleporter By Vitaloverdose, Feb 2006, http://www.Vitaloverdose.com
// This is part of the 'Vitals Pro Mapping Tools' Mod 
// Full class list http://wiki.beyondunreal.com/wiki/Vital's_Pro_Mapping_Tools
// Direct Download the Mod in zipped format Http://promappingtools.zapto.org
//=============================================================================

class VehicleTeleporter Extends VitalPMToolBox
placeable;

struct                              VecRec
{
 var OnsVehicle                     VevRef;
 Var float                      RecTime;
};Var Array< VecRec >               Tracking;


var Array< Actor >                  TpAct;

Var bool                            bTracking;
var float                           NextRescan;
var Emitter                         SpawnedAmbiantFx;
var Emitter                         SpawnedVecFx;

Var () bool                         bTeleportsEmptyVecs;
Var () bool                         bScanDest;
Var () Sound                        TeleportSound;
Var () float                        CaptureTime;
Var () float                        TimerFrequency;

Var () Float                        ReScanDelay;
var () Array< Class< Emitter > >    VecTagFxPool;
Var () Array< Class< Emitter > >    AmbiantFxPool;
Var () Array< Class< Emitter > >    TeleportFxPool_Vec;
Var () Array< Class< Emitter > >    TeleportFxPool_Self;

Function PostBeginPlay()
{
 ScanTpAct();

 if ( ambiantfxpool.length !=0 )
    {
     SpawnFx( Self.Location , AmbiantFxPool  , self );
    }

 If ( ( bScanDest != false ) && ( (AmbiantFxpool.Length <= 0 ) || ( ReScanDelay <= 0 )) )
    {
     NextRescan = ReScanDelay;

     if ( timerfrequency < 1 )
        {
         timerfrequency = 1;
        }

     SetTimer( 1 , true );
    }
}

Simulated Function ScanTpAct()
{
 Local Actor FoundTelPoint;

 if ( TpAct.Length > 0 )
    {
     TpAct.Remove(0,TpAct.Length);
    }

 foreach AllActors( Class'Actor' , FoundTelPoint,'TP' )
                  {
                   TpAct.Insert( 0 , 1 );
                   TpAct[0] = FoundTelPoint;
                  }
}

function Touch( Actor Other )
{
 if ( Other.IsA('Vehicle') )
    {
     if ( ( vehicle(Other).driver == none ) && ( bTeleportsEmptyVecs == false ) )
        {
         return;
        }
   else
   Vectel( Pawn(Other) );
   }
}

Simulated Function Vectel(Pawn PTele)
{
 local EPhysics      Entryphysics;
 local Vehicle       Teleporting;
 local Array<Actor>  TempTpAct;
 local Rotator       Old_Rot;
 local Rotator       New_Rot;
 local Vector        NewVector;
 Local int           Counter;
 Local int           PickedRNDNo;

 Teleporting       = Vehicle(pTele);
 TempTpAct.Length  = tpact.Length;
 TempTpAct         = tpact;
 New_Rot           = Teleporting.Rotation;
 EntryPhysics      = Teleporting.Physics;
 AppliedBoostForce = Teleporting.Velocity * 500;
 Teleporting.SetPhysics(PHYS_None);

 for ( Counter=0;Counter<tpact.Length;Counter++)       //here i want to pick Numbs at Random from a list
     {                                                 //First west up the Numbs in sequential order and then
      PickedRNDNo = Rand( tempTpAct.Length -1 )+1;      //pick a RND No based on the Length of the list.Once Picked

      if ( !IaNavBlocked(Teleporting.default.CollisionRadius,NewVector) )
         {
          NewVector   = tempTpAct[PickedRNDNo].Location;    //the Numb is removed from the list and anOther Numb is pick
          Teleporting.SetLocation(NewVector);
          Old_Rot       = Teleporting.Rotation;
          New_Rot.Yaw   = TpAct[PickedRNDNo].Rotation.Yaw + Teleporting.Rotation.Yaw - Self.Rotation.Yaw;
          posttel(Teleporting , PickedRNDNo ,NewVector, New_Rot , EntryPhysics  );
         }

      tempTpAct.remove( PickedRNDNo , 1 );                //is Picked based on the new Length of the list
     }
}

Simulated function  VecBoost( OnsVehicle TheVec )
{
 Local Vector PointOfBoostForce;  // if not set defaults to(0,0,0)  ie. the center of the vec.
 Local Actor  RotRelation;        

 if ( bDirectional)
    {
     RotRelation = Self ;
    }
 TheVec.KAddImpulse( AppliedBoostForce >> RotRelation.Rotation, PointOfBoostForce >> RotRelation.Rotation ) ;
 EnterVecRec( TheVec );
}

function Timer()
{
 local int counter;

 if (NextRescan>0)
    {
     NextRescan-=timerfrequency;

     if ( NextRescan < 0 )
        {
         ScanTpAct();
         NextRescan = ReScanDelay;
        }
    }

 for ( Counter=0; Counter<Tracking.Length; Counter++ )
     {
     Tracking[Counter].VevRef.bDriverCannotLeaveVehicle = False ;
     Tracking.remove( Counter , 1);
     if ( Tracking.Length == 0 )
        {
         bTracking = False;
        }
        
     }
}

function enterVecRec( ONSVehicle NewVec )

{
 NewVec.bDriverCannotLeaveVehicle = True;
 
 Tracking.insert(0,1);
 Tracking[0] = NewVec;
 
 if (bTracking == False )
    {
     bTracking = True;
     SetTimer(TimerFrequency,True);        // set Timer to repeatedly be called every 'Timerfrequncy' Seconds.
    }
}


Simulated Function  SpawnFx( Vector SpawnPos ,Array< Class< Emitter > > FxSpawnpool, Actor Hardattachedto )
{
 Local int            PickedNumb;
 local Class<Emitter> ChosenFxClass;
 local Emitter        SpawnedFx;

 if ( FxSpawnpool.Length <= 0 )
    {
     PickedNumb  = FxSpawnpool.Length;
     PickedNumb  = Rand(PickedNumb);
     ChosenFxClass = FxSpawnpool[PickedNumb];
    }

 SpawnedFx         = Spawn( ChosenFxClass , self , , SpawnPos , Rotation );

If ( (SpawnedFx != none ) && ( Hardattachedto != none ) )
   {
    SpawnedFx.SetBase( Hardattachedto );
   }
}

Function Bool IaNavBlocked( Float ScanRadius , Vector NavPointLoc )
{
 Local Bool    bOccupied;
 Local Actor   FoundActoror;

 foreach radiusActors( Class'Actor' , FoundActoror , ScanRadius , NavPointLoc )
      {
      If ( ( FoundActoror != Self ) && ( FoundActoror.bCollideActors == True ) )
         {
          bOccupied = True;
         }
      }

 Return bOccupied;
}

Simulated Function Posttel( Pawn Teleporting , int TelPointNumb , Vector NewVectorLoc , Rotator New_Rot , EPhysics EntryPhysics )
{
 Teleporting.SetPhysics( EntryPhysics );
 Teleporting.Controller.moveTimer = -1.0;
 Teleporting.SetmoveTarget( self );
 Teleporting.Controller.SetRotation( New_Rot );
 Teleporting.SetRotation( New_Rot );

 if ( Teleporting.IsA('ONSChopperCraft')  ||
      Teleporting.IsA('ONSHoverCraft')    ||
      Teleporting.IsA('ONSPlaneCraft'))
      {
       Teleporting.KSetStayUpright( True , True );
      }

 VecBoost(onsVehicle(Teleporting));

 if ( TeleportSound != None )
    {
     PlaySound( TeleportSound );
    }
}

Here is a link to a .uc file for this script;-

[Download This Script]

And Finally..

Here is the VecTel Pakaged up in a single function which should make it nice and easy to patch into your own script . You will have to add an array to hold the telpoints (TpAct) to make it work. The function ScanTp() doesnt have to be there . if you have another way of fillinf the PTAct array then just using the VecTel() function will work fine.

Function scanTp()
{
Local Actor FoundtPoints;
if ( TpAct.Length > 0 ) TpAct.Remove(0,TpAct.Length);
foreach Dynamicactors(Class'actor',FoundtPoints,'TP')
        {
        TpAct.insert(0,1);
        TpAct[0]=FoundtPoints;
        }
}

Simulated Function Vectel(Vehicle telePorting)

{

Local Rotator  oldRot,newrot; Local Vector Abf,pbf; Local EPhysics Entryphysics; Local Int pickedTelPoint;
newRot         = telePorting.Rotation;
EntryPhysics   = telePorting.Physics;
ABF            = telePorting.Velocity * 500;
pickedTelPoint = rand(TpAct.Length-1)+1;
telePorting.SetPhysics(PHYS_None);
telePorting.setLocation(TpAct[pickedTelPoint].Location);
oldRot         = telePorting.Rotation;
newRot.Yaw     = TpAct[pickedTelPoint].Rotation.Yaw + telePorting.Rotation.Yaw - Self.Rotation.Yaw;
telePorting.SetPhysics(EntryPhysics);
telePorting.Controller.moveTimer = -1.0;
telePorting.SetmoveTarget(Self);
telePorting.Controller.SetRotation(newRot);
telePorting.SetRotation(newRot);
if ( telePorting.IsA('ONSChopperCraft') || telePorting.IsA('ONSHoverCraft')   ||  telePorting.IsA('ONSPlaneCraft'))  telePorting.KSetStayUpright( True,True);
telePorting.KAddImpulse(abf >> Rotation, pbf >> Rotation);
}

Related Topics

Discussion

Sweavo: Hi, does this work in Net play?

VitalOverdose: As far as i know yes. I havent had the slightest hiccup with it yet. Bu saying that, im not aa expert at the whole replication thing just yet but so it wouldnt suprise me if it needed a slight modification somewhere. I was thinking about giving it a bit of an update anyway so i'll give it a decent online test to be sure. Let me know if you have any problems with it at all.

Sweavo: have you actually tried it in net play? Not being funny, just trying to clarify

Tarquin: What is a 'moving vec telpoints'? And what do you mean by an actor being 'not solid'? I think this needs a rewrite, starting with using Teleporter as a parent class, and with clearer names for the functions too. It's fine to abbreviate a local variable, especially if it's only a counter or a placeholder you only use a couple of times, but functions should have clear, non-abbreviated names. Who's up for working on this?

Discussion

(Moved from VehicleTeleporter)

Sweavo: Hi, does this work in Net play?

Vitaloverdose Yes it works in net play.

Tarquin: I don't really see the advantage of having only one actor and using tags. Surely it makes it harder for the mapper to clearly see what is going on in the map.

MythOpus: Although I do like having an 'all-on-one' actor like this, it really would be confusing and waht not and possibly slower than using a URL / TAG system with multiple teleporters.

Tarquin: Another point about this – shouldn't it be a subclass of a navigation point, for bots to use it?

Wormbo: The best way to implement it would probably be a subclass of Teleporter so it can take advantage of the native pathing magic in UnrealEd. An yes, having source and destination actors of this class certainly helps mappers understand want's going on.

VitalOverdose: Vitaloverdose originally made the player pawn version of this actor for my level ons-stellacruiser which had a couple of very large (60000uu or more) space ships in it i found using a dedicated teleporter to teleporter it was to easy for a defending team to hold off any invading players by spawn killing everyone as they teleported accross to attack the other sides powerCore. Static teleporters in a confined space can like a space ship can make for some very predictable game play especially with objective based team games. Even if they were placed far away from the start points people very quickly learnt which was the closest to them from their start points and everyone just headed for that point every time they respawned.I found it was very easy to work out which way people would be running once they entered your space ship and was just creating choke points as wave after wave of people enetered the ship in the same place.I know they could just use a vehicle to fly accross to the enemy ship but i always try to make my ONS map's just as playable on foot as when your in a vehicle. Also the idea was to have an anti-Blocking/Telefrag system. As telefragging can be a bit of a problem with static teleporters when you pop out on the other side to find your already under fire from the enemy and the only way out of the teleporter is to run in the direction of the person shooting. Also I didn't want someone to be able to simply block the teleport with a vehicle. and using a large amount of possible teleport locations seemed like the best solution at the time. I haven't got the anti-telefrag system in this script as its supposed to be the most generic version of the system. When i put the script together one of my main goals was to make something they was very easy for people to integrate into their own mods, ill put all the fancy stuff on the next version.Tarquin mentioned before about letting the mapper choose the label to indicate a possible 'teleport Point' but now I'm thinking of having multiple 'TP' points and allowing the mapper to weight the different sets of possible locations.

Remember you don't HAVE to use multiple spawn locations If you use 1 teleporter and 1 spawn location its no more difficult to visualise than using a standard teleporter system. Its just an option ,the system is only as complicated as the mapper decides to make it. Also this should make it very simple to add this actor to any existing maps as they all have path-nodes already set out in places the play is able to navigate to..

Also the whole system works with moving teleport points as well ;)

Using the teleporter as the parent class to make use of the built in navigational properties seems like a good idea , its not something i would have come up with myself . I guess i could just completely overwrite the existing functions from the parent class completly which wouldnt be so bad.

Tarquin: I suggest you try it. Subclassing to inherit behaviour is one of the very basic principles of coding in UnrealScript, after all :)


Category Custom Class

The Unreal Engine Documentation Site

Wiki Community

Topic Categories

Recent Changes

Offline Wiki

Unreal Engine

Console Commands

Terminology

FAQs

Help Desk

Mapping Topics

Mapping Lessons

UnrealEd Interface

UnrealScript Topics

UnrealScript Lessons

Making Mods

Class Tree

Modeling Topics

Chongqing Page

Log In