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