1 // g_newtrig.c
2 // pmack
3 // october 1997
4 
5 #include "g_local.h"
6 
7 #define TELEPORT_PLAYER_ONLY	1
8 #define TELEPORT_SILENT			2
9 #define TELEPORT_CTF_ONLY		4
10 #define TELEPORT_START_ON		8
11 
12 extern void TeleportEffect (vec3_t origin);
13 
14 /*QUAKED info_teleport_destination (.5 .5 .5) (-16 -16 -24) (16 16 32)
15 Destination marker for a teleporter.
16 */
SP_info_teleport_destination(edict_t * self)17 void SP_info_teleport_destination (edict_t *self)
18 {
19 }
20 
21 /*QUAKED trigger_teleport (.5 .5 .5) ? player_only silent ctf_only start_on
22 Any object touching this will be transported to the corresponding
23 info_teleport_destination entity. You must set the "target" field,
24 and create an object with a "targetname" field that matches.
25 
26 If the trigger_teleport has a targetname, it will only teleport
27 entities when it has been fired.
28 
29 player_only: only players are teleported
30 silent: <not used right now>
31 ctf_only: <not used right now>
32 start_on: when trigger has targetname, start active, deactivate when used.
33 */
trigger_teleport_touch(edict_t * self,edict_t * other,cplane_t * plane,csurface_t * surf)34 void trigger_teleport_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
35 {
36 	edict_t *dest;
37 	int		i;
38 
39 	if(/*(self->spawnflags & TELEPORT_PLAYER_ONLY) &&*/ !(other->client))
40 		return;
41 
42 	if(self->delay)
43 		return;
44 
45 	dest = G_Find (NULL, FOFS(targetname), self->target);
46 	if(!dest)
47 	{
48 		gi.dprintf("Teleport Destination not found!\n");
49 		return;
50 	}
51 
52 	gi.WriteByte (svc_temp_entity);
53 	gi.WriteByte (TE_TELEPORT_EFFECT);
54 	gi.WritePosition (other->s.origin);
55 	gi.multicast (other->s.origin, MULTICAST_PVS);
56 
57 	// unlink to make sure it can't possibly interfere with KillBox
58 	gi.unlinkentity (other);
59 
60 	VectorCopy (dest->s.origin, other->s.origin);
61 	VectorCopy (dest->s.origin, other->s.old_origin);
62 	other->s.origin[2] += 10;
63 
64 	// clear the velocity and hold them in place briefly
65 	VectorClear (other->velocity);
66 	if(other->client)
67 	{
68 		other->client->ps.pmove.pm_time = 160>>3;		// hold time
69 		other->client->ps.pmove.pm_flags |= PMF_TIME_TELEPORT;
70 
71 		// draw the teleport splash at source and on the player
72 //		self->s.event = EV_PLAYER_TELEPORT;
73 		other->s.event = EV_PLAYER_TELEPORT;
74 
75 		// set angles
76 		for (i=0 ; i<3 ; i++)
77 			other->client->ps.pmove.delta_angles[i] = ANGLE2SHORT(dest->s.angles[i] - other->client->resp.cmd_angles[i]);
78 
79 		VectorClear (other->client->ps.viewangles);
80 		VectorClear (other->client->v_angle);
81 	}
82 
83 
84 	VectorClear (other->s.angles);
85 
86 	// kill anything at the destination
87 	KillBox (other);
88 
89 	gi.linkentity (other);
90 }
91 
trigger_teleport_use(edict_t * self,edict_t * other,edict_t * activator)92 void trigger_teleport_use (edict_t *self, edict_t *other, edict_t *activator)
93 {
94 	if(self->delay)
95 		self->delay = 0;
96 	else
97 		self->delay = 1;
98 }
99 
SP_trigger_teleport(edict_t * self)100 void SP_trigger_teleport(edict_t *self)
101 {
102 	if (!self->wait)
103 		self->wait = 0.2;
104 
105 	self->delay = 0;
106 
107 	if (self->targetname)
108 	{
109 		self->use = trigger_teleport_use;
110 		if(!(self->spawnflags & TELEPORT_START_ON))
111 			self->delay = 1;
112 	}
113 
114 	self->touch = trigger_teleport_touch;
115 
116 	self->solid = SOLID_TRIGGER;
117 	self->movetype = MOVETYPE_NONE;
118 //	self->flags |= FL_NOCLIENT;
119 
120 	if (!VectorCompare(self->s.angles, vec3_origin))
121 		G_SetMovedir (self->s.angles, self->movedir);
122 
123 	gi.setmodel (self, self->model);
124 	gi.linkentity (self);
125 }
126 
127 // ***************************
128 // TRIGGER_DISGUISE
129 // ***************************
130 
131 /*QUAKED trigger_disguise (.5 .5 .5) ? TOGGLE START_ON REMOVE
132 Anything passing through this trigger when it is active will
133 be marked as disguised.
134 
135 TOGGLE - field is turned off and on when used.
136 START_ON - field is active when spawned.
137 REMOVE - field removes the disguise
138 */
139 
trigger_disguise_touch(edict_t * self,edict_t * other,cplane_t * plane,csurface_t * surf)140 void trigger_disguise_touch(edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
141 {
142 	if (other->client)
143 	{
144 		if(self->spawnflags & 4)
145 			other->flags &= ~FL_DISGUISED;
146 		else
147 			other->flags |= FL_DISGUISED;
148 	}
149 }
150 
trigger_disguise_use(edict_t * self,edict_t * other,edict_t * activator)151 void trigger_disguise_use (edict_t *self, edict_t *other, edict_t *activator)
152 {
153 	if(self->solid == SOLID_NOT)
154 		self->solid = SOLID_TRIGGER;
155 	else
156 		self->solid = SOLID_NOT;
157 
158 	gi.linkentity(self);
159 }
160 
SP_trigger_disguise(edict_t * self)161 void SP_trigger_disguise (edict_t *self)
162 {
163 	if(self->spawnflags & 2)
164 		self->solid = SOLID_TRIGGER;
165 	else
166 		self->solid = SOLID_NOT;
167 
168 	self->touch = trigger_disguise_touch;
169 	self->use = trigger_disguise_use;
170 	self->movetype = MOVETYPE_NONE;
171 	self->svflags = SVF_NOCLIENT;
172 
173 	gi.setmodel (self, self->model);
174 	gi.linkentity(self);
175 
176 }
177