shithub: qk2

ref: 7c0675ccfd6cf7c7d37be11f86ecb11c363b0962
dir: /rogue/g_newtrig.c/

View raw version
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include "../dat.h"
#include "../fns.h"

#define TELEPORT_PLAYER_ONLY	1
#define TELEPORT_SILENT			2
#define TELEPORT_CTF_ONLY		4
#define TELEPORT_START_ON		8

extern void TeleportEffect (vec3_t origin);

/*QUAKED info_teleport_destination (.5 .5 .5) (-16 -16 -24) (16 16 32)
Destination marker for a teleporter.
*/
void SP_info_teleport_destination (edict_t *)
{
}

/*QUAKED trigger_teleport (.5 .5 .5) ? player_only silent ctf_only start_on
Any object touching this will be transported to the corresponding 
info_teleport_destination entity. You must set the "target" field, 
and create an object with a "targetname" field that matches.

If the trigger_teleport has a targetname, it will only teleport 
entities when it has been fired.

player_only: only players are teleported
silent: <not used right now>
ctf_only: <not used right now>
start_on: when trigger has targetname, start active, deactivate when used.
*/
void trigger_teleport_touch(edict_t *self, edict_t *other, cplane_t *, csurface_t *)
{
	edict_t *dest;
	int		i;

	if(/*(self->spawnflags & TELEPORT_PLAYER_ONLY) &&*/ !(other->client))
		return;

	if(self->delay)
		return;

	dest = G_Find (NULL, FOFS(targetname), self->target);
	if(!dest)
	{
		gi.dprintf("Teleport Destination not found!\n");
		return;
	}

	gi.WriteByte (svc_temp_entity);
	gi.WriteByte (TE_TELEPORT_EFFECT);
	gi.WritePosition (other->s.origin);
	gi.multicast (other->s.origin, MULTICAST_PVS);

	// unlink to make sure it can't possibly interfere with KillBox
	gi.unlinkentity (other);

	VectorCopy (dest->s.origin, other->s.origin);
	VectorCopy (dest->s.origin, other->s.old_origin);
	other->s.origin[2] += 10;

	// clear the velocity and hold them in place briefly
	VectorClear (other->velocity);
	if(other->client)
	{
		other->client->ps.pmove.pm_time = 160>>3;		// hold time
		other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;

		// draw the teleport splash at source and on the player
//		self->s.event = EV_PLAYER_TELEPORT;
		other->s.event = EV_PLAYER_TELEPORT;

		// set angles
		for (i=0 ; i<3 ; i++)
			other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(dest->s.angles[i] - other->client->resp.cmd_angles[i]);

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


	VectorClear (other->s.angles);

	// kill anything at the destination
	KillBox (other);

	gi.linkentity (other);
}

void trigger_teleport_use (edict_t *self, edict_t *, edict_t *)
{
	if(self->delay)
		self->delay = 0;
	else
		self->delay = 1;
}

void SP_trigger_teleport(edict_t *self)
{
	if (!self->wait)
		self->wait = 0.2;

	self->delay = 0;
		
	if (self->targetname)
	{
		self->use = trigger_teleport_use;
		if(!(self->spawnflags & TELEPORT_START_ON))
			self->delay = 1;
	}

	self->touch = trigger_teleport_touch;

	self->solid = SOLID_TRIGGER;
	self->movetype = MOVETYPE_NONE;
//	self->flags |= FL_NOCLIENT;

	if (!VectorCompare(self->s.angles, vec3_origin))
		G_SetMovedir (self->s.angles, self->movedir);

	gi.setmodel (self, self->model);
	gi.linkentity (self);
}

// ***************************
// TRIGGER_DISGUISE
// ***************************

/*QUAKED trigger_disguise (.5 .5 .5) ? TOGGLE START_ON REMOVE
Anything passing through this trigger when it is active will
be marked as disguised.

TOGGLE - field is turned off and on when used.
START_ON - field is active when spawned.
REMOVE - field removes the disguise
*/

void trigger_disguise_touch(edict_t *self, edict_t *other, cplane_t *, csurface_t *)
{
	if (other->client)
	{
		if(self->spawnflags & 4)
			other->flags &= ~FL_DISGUISED;
		else
			other->flags |= FL_DISGUISED;
	}
}

void trigger_disguise_use (edict_t *self, edict_t *, edict_t *)
{
	if(self->solid == SOLID_NOT)
		self->solid = SOLID_TRIGGER;
	else
		self->solid = SOLID_NOT;

	gi.linkentity(self);
}

void SP_trigger_disguise (edict_t *self)
{
	if(self->spawnflags & 2)
		self->solid = SOLID_TRIGGER;
	else
		self->solid = SOLID_NOT;

	self->touch = trigger_disguise_touch;
	self->use = trigger_disguise_use;
	self->movetype = MOVETYPE_NONE;
	self->svflags = SVF_NOCLIENT;

	gi.setmodel (self, self->model);
	gi.linkentity(self);

}