aboutsummaryrefslogtreecommitdiff
path: root/src/p_telept.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/p_telept.c')
-rw-r--r--src/p_telept.c345
1 files changed, 345 insertions, 0 deletions
diff --git a/src/p_telept.c b/src/p_telept.c
new file mode 100644
index 0000000..744e901
--- /dev/null
+++ b/src/p_telept.c
@@ -0,0 +1,345 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2002 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Teleportation.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomdef.h"
35#include "doomstat.h"
36#include "p_spec.h"
37#include "p_maputl.h"
38#include "p_map.h"
39#include "r_main.h"
40#include "p_tick.h"
41#include "s_sound.h"
42#include "sounds.h"
43#include "p_user.h"
44#include "r_demo.h"
45
46static mobj_t* P_TeleportDestination(line_t* line)
47{
48 int i;
49 for (i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) {
50 register thinker_t* th = NULL;
51 while ((th = P_NextThinker(th,th_misc)) != NULL)
52 if (th->function == P_MobjThinker) {
53 register mobj_t* m = (mobj_t*)th;
54 if (m->type == MT_TELEPORTMAN &&
55 m->subsector->sector-sectors == i)
56 return m;
57 }
58 }
59 return NULL;
60}
61//
62// TELEPORTATION
63//
64// killough 5/3/98: reformatted, cleaned up
65
66int EV_Teleport(line_t *line, int side, mobj_t *thing)
67{
68 mobj_t *m;
69
70 // don't teleport missiles
71 // Don't teleport if hit back of line,
72 // so you can get out of teleporter.
73 if (side || thing->flags & MF_MISSILE)
74 return 0;
75
76 // killough 1/31/98: improve performance by using
77 // P_FindSectorFromLineTag instead of simple linear search.
78
79 if ((m = P_TeleportDestination(line)) != NULL)
80 {
81 fixed_t oldx = thing->x, oldy = thing->y, oldz = thing->z;
82 player_t *player = thing->player;
83
84 // killough 5/12/98: exclude voodoo dolls:
85 if (player && player->mo != thing)
86 player = NULL;
87
88 if (!P_TeleportMove(thing, m->x, m->y, false)) /* killough 8/9/98 */
89 return 0;
90
91 if (compatibility_level != finaldoom_compatibility)
92 thing->z = thing->floorz;
93
94 if (player)
95 player->viewz = thing->z + player->viewheight;
96
97 // spawn teleport fog and emit sound at source
98 S_StartSound(P_SpawnMobj(oldx, oldy, oldz, MT_TFOG), sfx_telept);
99
100 // spawn teleport fog and emit sound at destination
101 S_StartSound(P_SpawnMobj(m->x +
102 20*finecosine[m->angle>>ANGLETOFINESHIFT],
103 m->y +
104 20*finesine[m->angle>>ANGLETOFINESHIFT],
105 thing->z, MT_TFOG),
106 sfx_telept);
107
108 /* don't move for a bit
109 * cph - DEMOSYNC - BOOM had (player) here? */
110 if (thing->player)
111 thing->reactiontime = 18;
112
113 thing->angle = m->angle;
114
115 thing->momx = thing->momy = thing->momz = 0;
116
117 /* killough 10/98: kill all bobbing momentum too */
118 if (player)
119 player->momx = player->momy = 0;
120
121 // e6y
122 if (player && player->mo == thing)
123 R_ResetAfterTeleport(player);
124
125 return 1;
126 }
127 return 0;
128}
129
130//
131// Silent TELEPORTATION, by Lee Killough
132// Primarily for rooms-over-rooms etc.
133//
134
135int EV_SilentTeleport(line_t *line, int side, mobj_t *thing)
136{
137 mobj_t *m;
138
139 // don't teleport missiles
140 // Don't teleport if hit back of line,
141 // so you can get out of teleporter.
142
143 if (side || thing->flags & MF_MISSILE)
144 return 0;
145
146 if ((m = P_TeleportDestination(line)) != NULL)
147 {
148 // Height of thing above ground, in case of mid-air teleports:
149 fixed_t z = thing->z - thing->floorz;
150
151 // Get the angle between the exit thing and source linedef.
152 // Rotate 90 degrees, so that walking perpendicularly across
153 // teleporter linedef causes thing to exit in the direction
154 // indicated by the exit thing.
155 angle_t angle =
156 R_PointToAngle2(0, 0, line->dx, line->dy) - m->angle + ANG90;
157
158 // Sine, cosine of angle adjustment
159 fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
160 fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
161
162 // Momentum of thing crossing teleporter linedef
163 fixed_t momx = thing->momx;
164 fixed_t momy = thing->momy;
165
166 // Whether this is a player, and if so, a pointer to its player_t
167 player_t *player = thing->player;
168
169 // Attempt to teleport, aborting if blocked
170 if (!P_TeleportMove(thing, m->x, m->y, false)) /* killough 8/9/98 */
171 return 0;
172
173 // Rotate thing according to difference in angles
174 thing->angle += angle;
175
176 // Adjust z position to be same height above ground as before
177 thing->z = z + thing->floorz;
178
179 // Rotate thing's momentum to come out of exit just like it entered
180 thing->momx = FixedMul(momx, c) - FixedMul(momy, s);
181 thing->momy = FixedMul(momy, c) + FixedMul(momx, s);
182
183 // Adjust player's view, in case there has been a height change
184 // Voodoo dolls are excluded by making sure player->mo == thing.
185 if (player && player->mo == thing)
186 {
187 // Save the current deltaviewheight, used in stepping
188 fixed_t deltaviewheight = player->deltaviewheight;
189
190 // Clear deltaviewheight, since we don't want any changes
191 player->deltaviewheight = 0;
192
193 // Set player's view according to the newly set parameters
194 P_CalcHeight(player);
195
196 // Reset the delta to have the same dynamics as before
197 player->deltaviewheight = deltaviewheight;
198 }
199
200 // e6y
201 if (player && player->mo == thing)
202 R_ResetAfterTeleport(player);
203
204 return 1;
205 }
206 return 0;
207}
208
209//
210// Silent linedef-based TELEPORTATION, by Lee Killough
211// Primarily for rooms-over-rooms etc.
212// This is the complete player-preserving kind of teleporter.
213// It has advantages over the teleporter with thing exits.
214//
215
216// maximum fixed_t units to move object to avoid hiccups
217#define FUDGEFACTOR 10
218
219int EV_SilentLineTeleport(line_t *line, int side, mobj_t *thing,
220 boolean reverse)
221{
222 int i;
223 line_t *l;
224
225 if (side || thing->flags & MF_MISSILE)
226 return 0;
227
228 for (i = -1; (i = P_FindLineFromLineTag(line, i)) >= 0;)
229 if ((l=lines+i) != line && l->backsector)
230 {
231 // Get the thing's position along the source linedef
232 fixed_t pos = D_abs(line->dx) > D_abs(line->dy) ?
233 FixedDiv(thing->x - line->v1->x, line->dx) :
234 FixedDiv(thing->y - line->v1->y, line->dy) ;
235
236 // Get the angle between the two linedefs, for rotating
237 // orientation and momentum. Rotate 180 degrees, and flip
238 // the position across the exit linedef, if reversed.
239 angle_t angle = (reverse ? pos = FRACUNIT-pos, 0 : ANG180) +
240 R_PointToAngle2(0, 0, l->dx, l->dy) -
241 R_PointToAngle2(0, 0, line->dx, line->dy);
242
243 // Interpolate position across the exit linedef
244 fixed_t x = l->v2->x - FixedMul(pos, l->dx);
245 fixed_t y = l->v2->y - FixedMul(pos, l->dy);
246
247 // Sine, cosine of angle adjustment
248 fixed_t s = finesine[angle>>ANGLETOFINESHIFT];
249 fixed_t c = finecosine[angle>>ANGLETOFINESHIFT];
250
251 // Maximum distance thing can be moved away from interpolated
252 // exit, to ensure that it is on the correct side of exit linedef
253 int fudge = FUDGEFACTOR;
254
255 // Whether this is a player, and if so, a pointer to its player_t.
256 // Voodoo dolls are excluded by making sure thing->player->mo==thing.
257 player_t *player = thing->player && thing->player->mo == thing ?
258 thing->player : NULL;
259
260 // Whether walking towards first side of exit linedef steps down
261 int stepdown =
262 l->frontsector->floorheight < l->backsector->floorheight;
263
264 // Height of thing above ground
265 fixed_t z = thing->z - thing->floorz;
266
267 // Side to exit the linedef on positionally.
268 //
269 // Notes:
270 //
271 // This flag concerns exit position, not momentum. Due to
272 // roundoff error, the thing can land on either the left or
273 // the right side of the exit linedef, and steps must be
274 // taken to make sure it does not end up on the wrong side.
275 //
276 // Exit momentum is always towards side 1 in a reversed
277 // teleporter, and always towards side 0 otherwise.
278 //
279 // Exiting positionally on side 1 is always safe, as far
280 // as avoiding oscillations and stuck-in-wall problems,
281 // but may not be optimum for non-reversed teleporters.
282 //
283 // Exiting on side 0 can cause oscillations if momentum
284 // is towards side 1, as it is with reversed teleporters.
285 //
286 // Exiting on side 1 slightly improves player viewing
287 // when going down a step on a non-reversed teleporter.
288
289 int side = reverse || (player && stepdown);
290
291 // Make sure we are on correct side of exit linedef.
292 while (P_PointOnLineSide(x, y, l) != side && --fudge>=0)
293 if (D_abs(l->dx) > D_abs(l->dy))
294 y -= l->dx < 0 != side ? -1 : 1;
295 else
296 x += l->dy < 0 != side ? -1 : 1;
297
298 // Attempt to teleport, aborting if blocked
299 if (!P_TeleportMove(thing, x, y, false)) /* killough 8/9/98 */
300 return 0;
301
302 // e6y
303 if (player && player->mo == thing)
304 R_ResetAfterTeleport(player);
305
306 // Adjust z position to be same height above ground as before.
307 // Ground level at the exit is measured as the higher of the
308 // two floor heights at the exit linedef.
309 thing->z = z + sides[l->sidenum[stepdown]].sector->floorheight;
310
311 // Rotate thing's orientation according to difference in linedef angles
312 thing->angle += angle;
313
314 // Momentum of thing crossing teleporter linedef
315 x = thing->momx;
316 y = thing->momy;
317
318 // Rotate thing's momentum to come out of exit just like it entered
319 thing->momx = FixedMul(x, c) - FixedMul(y, s);
320 thing->momy = FixedMul(y, c) + FixedMul(x, s);
321
322 // Adjust a player's view, in case there has been a height change
323 if (player)
324 {
325 // Save the current deltaviewheight, used in stepping
326 fixed_t deltaviewheight = player->deltaviewheight;
327
328 // Clear deltaviewheight, since we don't want any changes now
329 player->deltaviewheight = 0;
330
331 // Set player's view according to the newly set parameters
332 P_CalcHeight(player);
333
334 // Reset the delta to have the same dynamics as before
335 player->deltaviewheight = deltaviewheight;
336 }
337
338 // e6y
339 if (player && player->mo == thing)
340 R_ResetAfterTeleport(player);
341
342 return 1;
343 }
344 return 0;
345}