Personal Teleporter

 

I designed this so I didn't have to go through most of a level when I was playing coop and my friend 'accidentally' killed me [generally by shoving me into a pit of lava]. It uses Major Bitch's random spawn point code in a slightly modifided format (it checks to see if the point is within 400 units of the other player and also if you will telefrag anything)

Currently it will only teleport you to the first other player it finds. while this suited my purposes fine, you will probably want to modify this so it teleports you to people on a team, or allow you to choose a target player. I'd also suggest putting a timer in, to limit how often people can teleport, or make it cost something. I'll mark the areas to do this.

On to the code. I'll put a file with everything in it at the bottom, but heres the code with an explanation of everything


Add all of this code to a new file and add it to your project (to make sure you don't have typos i'd suggest grabbing the code from below)

#include "g_local.h"                  // Gives the file all the access to definitions it needs. required line
 
 
/* BossTeleport is a helper function that I created to allow the easy creation of a teleport effect
It creates a cloud of particles that moves upwards and disapates. 
If you have downloaded my tempent files you don't need this. (it might even cause conflicts) */ 
 
void BossTeleport(edict_t *ent)                              
 
{                                                    
        gi.WriteByte (svc_temp_entity);
        gi.WriteByte (TE_BOSSTPORT);
        gi.WritePosition (ent->s.origin);
        gi.multicast (ent->s.origin, MULTICAST_PVS);
}
 
 
/* This is a modified version of Major Bitch's findrandomspawnpoint code.
I changed it so it takes the player to be teleported, the player to be teleported to and a return value for 
the new location. (not sure why the return val works, I thought it wouldn't) */
 
qboolean findteleportpoint (edict_t *ent,edict_t *targent,vec3_t returnval)
{
  vec3_t loc = {0,0,0};
  vec3_t floor;
        vec3_t v;
  int i;
  int j = 0;
  int k = 0;
  int jmax = 1000;
  int kmax = (int)(jmax/2);
  qboolean found = false;
  trace_t tr;
        float distance;
  do {
    if (found || j >= jmax || k >= kmax)
      break;
    j++;
    for (i = 0; i < 3; i++)
      loc[i] = rand() % (8192 + 1) - 4096;
    if (gi.pointcontents(loc) == 0)
    {
      VectorCopy(loc, floor);
      floor[2] = -4096;
      tr = gi.trace (loc, ent->maxs, ent->mins, floor, NULL, MASK_SOLID|MASK_WATER);
      k++;
      if (tr.contents & MASK_WATER)
        found = false;
      else
      {
        VectorCopy (tr.endpos, loc);
        loc[2] += ent->maxs[2] - ent->mins[2]; // make sure the entity can fit!
        found = (gi.pointcontents(loc) == 0 ? true : false);
        if (found)
        {
               VectorSubtract (loc, targent->s.origin, v);          // this bit checks to see if the target
               distance = VectorLength (v);                         // player is within 400 units
               if (distance>400)
                       found=false;
               tr = gi.trace (loc, ent->mins, ent->maxs, loc, NULL, MASK_PLAYERSOLID); // this is to make sure you don't telefrag anyone
               if (tr.ent)
                       found=false;
        }
      }
    }
    else
      found = false;
  } while (!found && j < jmax && k < kmax);
  if (!found && (j >= jmax || k >= kmax))
    return false;
  VectorCopy(loc,returnval);
  return true;
}
 
 
 
 
void Cmd_Teleport_f(edict_t *ent)
{
        int            n;
        edict_t        *player;
        vec3_t         spot;
        int            iter=0;
        int found=0;
 
/*  The for loop below goes through the list of plaers looking for one that exists and is ready to be a teleport 
target. You will probably want to change this so it also checks that team against the teleportees team.
another possible idea is to use a menu and generate the menu to list all the players you can teleport to. 
you would want to move all the code below the loop to the menu results function. I'm not going to put up instructions
on how to do this here. Mail me and I may get round to sending you instructions. 
(for my menu tut only as I don't know the others as well) */
 
 
        for (n = 1; n <= maxclients->value; n++)
        {
               player = &g_edicts[n];
 
               if (!player->inuse)
                       continue;
 
               if (player->health <= 0)
                       continue;
 
               if (player==ent)
                       continue;
               found=1;
               break;
               
        }
        if (!found)
        {
               gi.centerprintf(ent,"No Other Players for teleport\n");
               return;
        }       
 
// Checks for a new spawnpoint. the iter section is to make sure it doesn't hang the system if no point exists
        while ((findspawnpoint(ent,player,spot) == false) & (iter<10000))
               {iter++;}      
 
        if (iter==10000)
        {
        gi.cprintf(ent,PRINT_HIGH,"No teleport spot available\n");
        return;
        }
 
 
        BossTeleport(ent);
        gi.unlinkentity (ent); 
 
        VectorCopy(spot,ent->s.origin);
        ent->s.event = EV_PLAYER_TELEPORT;
        gi.sound (ent, CHAN_ITEM, gi.soundindex ("world/blackhole.wav"), 1, ATTN_NORM, 0);
        gi.linkentity (ent);
}

To use this code, add a command to the command parser in g_cmds.c that calls Cmd_Teleport_f(ent); you should know how. If you don't, check out other tuts on this site. Remember to prototype it.

As another though, maybe having a command that does a trace forward and store a pointer to a player entity as a teleport link would be an idea. Again, mail me if you want to do it and can't


Resources


Skunkworks Tutorial