Adding DM spawnspots to teleporter destinations


 

Posted by Maj.Bitch (24.95.222.*) at 7:39 PM, 5/8/2001:


If you want to add the regular DM spawnspots to the array of possible random
teleporter destinations AND conversely, add any teleporter target destinations
to the list of possible regular DM spawnpoints, then here is what you need to do..

Add these to your g_local.h file..

#define maxspots 64
extern int numspots;
extern edict_t *telespot[maxspots];

This will be the array of both DM spawnspots and teleporter spawnspots (if any) that
are in any given map..

Now we need to formally declare these someplace.  Find these functions in your source
and comment those out and substitute these in their place.  Those using my PureDMRev2A
will find these in g_spawn.c


//=====================================================
//=====================================================

int numspots=0;
edict_t *telespot[maxspots]; // array of ALL spawnpoints in map

//=====================================================
void AddDMSpawnSpots(void) {
edict_t *spot=NULL;
  while ((spot=G_Find(spot,FOFS(classname),"info_player_deathmatch")))
    telespot[numspots++]=spot; // add this DM spawnspot to array
}

//=====================================================
void SelectRandomDeathmatchSpawnPoint(vec3_t spawn_origin,vec3_t spawn_angles) {
edict_t *spot=NULL;
  spot=telespot[(int)(rand()%numspots)-1]; // select a random entry
  VectorCopy(spot->s.origin,spawn_origin);
  VectorCopy(spot->s.angles,spawn_angles);
}

//=====================================================
void SelectFarthestDeathmatchSpawnPoint(vec3_t spawn_origin,vec3_t spawn_angles) {
edict_t *spot=NULL;
edict_t *bestspot=NULL;
float bestdistanceSqr=0;
float bestplayerdistanceSqr=0;
int i;

  for (i=0;i<numspots;i++) {
    spot=telespot[i]; // use stored telespots!
    bestplayerdistanceSqr=PlayersRangeSqrFromSpot(spot);
    if (bestplayerdistanceSqr>bestdistanceSqr) {
      bestspot=spot;
      bestdistanceSqr=bestplayerdistanceSqr; } }

  VectorCopy(bestspot->s.origin,spawn_origin);
  VectorCopy(bestspot->s.angles,spawn_angles);
}

//NOTE: My use of dmflags is really (int)dmflags->value so make the change
// if you aren't using my DM source.
//=====================================================
void SelectSpawnPoint(vec3_t spawn_origin,vec3_t spawn_angles) {
  if (dmflags & DF_SPAWN_FARTHEST)
    SelectFarthestDeathmatchSpawnPoint(spawn_origin,spawn_angles);
  else
    SelectRandomDeathmatchSpawnPoint(spawn_origin,spawn_angles);
}

These will work exactly the same as the normal spawnpoint selection routines 
only that we handled things differently.

Now, add this to the very top of your SpawnEntities() function

  numspots=0;
  for (i=0;i<64;i++)
    telespot[i]=NULL;

This will force a reset of the entire telespot array at the start of each 
level (before any teleporter entities are spawned into the game).

Now, add this at the bottom of SpawnEntities() like so:

  G_FindTeams();

  AddDMSpawnSpots(); // ADD THIS LINE RIGHT HERE

This will add the DM spawnpoints into the array (after the teleporter points have been
added in SP_misc_teleporter by SpawnEntities ).  The end result is that the telespot 
array will contain both the teleporter destinations, if any, and the regular DM spawnpoints.

Okay, now find your SP_misc_teleporter() function and substitute these new functions 
for the corresponding one..


//==================================================
void teleporter_touch(edict_t *teleporter,edict_t *other,cplane_t *plane,csurface_t *surf) {
edict_t *dest;

  dest=telespot[(int)(rand()%numspots)-1]; // dest is random telespot entry
  if (!dest) return;

  VectorCopy(dest->s.origin,other->s.origin);
  if (!other->client) {
    VectorSet(other->s.angles,0,dest->s.angles[1],0);
    gi.linkentity(other);
    return; }

  VectorCopy(dest->s.origin,other->s.old_origin);

  if (!other->client) {
    VectorSet(other->s.angles,0,dest->s.angles[1],0);
    gi.linkentity(other);
    return; }

  other->s.origin[2]+=10;

  VectorClear(other->velocity);
  other->client->ps.pmove.pm_time=160>>3;
  other->client->ps.pmove.pm_flags|=PMF_time_TELEPORT;

  teleporter->owner->s.event|=EV_PLAYER_TELEPORT;
  other->s.event|=EV_PLAYER_TELEPORT;

  other->client->ps.pmove.delta_angles[0]=ANGLE2SHORT(dest->s.angles[0]-other->client->resp.cmd_angles[0]);
  other->client->ps.pmove.delta_angles[1]=ANGLE2SHORT(dest->s.angles[1]-other->client->resp.cmd_angles[1]);
  other->client->ps.pmove.delta_angles[2]=ANGLE2SHORT(dest->s.angles[2]-other->client->resp.cmd_angles[2]);

  VectorClear(other->s.angles);
  VectorClear(other->client->ps.viewangles);
  VectorClear(other->client->v_angle);

  KillBox(other);

  gi.linkentity(other);
}

//==================================================
void SP_misc_teleporter(edict_t *teleporter) {
edict_t *trig,*dest;

  if (!teleporter->target) {
    G_FreeEdict(teleporter);
    return; }

  gi.setmodel(teleporter,"models/objects/dmspot/tris.md2");
  teleporter->s.skinnum=1;
  teleporter->s.effects|=EF_TELEPORTER;
  teleporter->s.sound=snd[64];
  teleporter->solid=SOLID_BBOX;

  // Grab the target destination ent and put in telespot[] array
  if ((dest=G_Find(NULL,FOFS(targetname),teleporter->target)))
    if (dest && (numspots+1<maxspots))
      telespot[numspots++]=dest;

  VectorSet(teleporter->mins,-32,-32,-24);
  VectorSet(teleporter->maxs,+32,+32,-16);
  gi.linkentity(teleporter);

  trig=G_Spawn();
  trig->touch=teleporter_touch;
  trig->solid=SOLID_TRIGGER;
  trig->target=teleporter->target;
  trig->owner=teleporter;
  VectorCopy(teleporter->s.origin,trig->s.origin);
  VectorSet(trig->mins,-8,-8,+8);
  VectorSet(trig->maxs,+8,+8,+24);
  gi.linkentity(trig);
}


Now, when you step into a teleporter particle beam, you'll get teleported to a random
selection taken from the possible teleporter target destinations AND the regular DM
spawnpoints.

That should add a bit more variety to teleporting around the map and to normal respawning!

That's it!!

Have fun!

Maj.Bitch