aboutsummaryrefslogtreecommitdiff
path: root/src/p_ceilng.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/p_ceilng.c')
-rw-r--r--src/p_ceilng.c467
1 files changed, 467 insertions, 0 deletions
diff --git a/src/p_ceilng.c b/src/p_ceilng.c
new file mode 100644
index 0000000..7b45ba5
--- /dev/null
+++ b/src/p_ceilng.c
@@ -0,0 +1,467 @@
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 * 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 * Ceiling aninmation (lowering, crushing, raising)
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "r_main.h"
36#include "p_spec.h"
37#include "p_tick.h"
38#include "s_sound.h"
39#include "sounds.h"
40
41// the list of ceilings moving currently, including crushers
42ceilinglist_t *activeceilings;
43
44/////////////////////////////////////////////////////////////////
45//
46// Ceiling action routine and linedef type handler
47//
48/////////////////////////////////////////////////////////////////
49
50//
51// T_MoveCeiling
52//
53// Action routine that moves ceilings. Called once per tick.
54//
55// Passed a ceiling_t structure that contains all the info about the move.
56// see P_SPEC.H for fields. No return.
57//
58// jff 02/08/98 all cases with labels beginning with gen added to support
59// generalized line type behaviors.
60//
61void T_MoveCeiling (ceiling_t* ceiling)
62{
63 result_e res;
64
65 switch(ceiling->direction)
66 {
67 case 0:
68 // If ceiling in stasis, do nothing
69 break;
70
71 case 1:
72 // Ceiling is moving up
73 res = T_MovePlane
74 (
75 ceiling->sector,
76 ceiling->speed,
77 ceiling->topheight,
78 false,
79 1,
80 ceiling->direction
81 );
82
83 // if not a silent crusher, make moving sound
84 if (!(leveltime&7))
85 {
86 switch(ceiling->type)
87 {
88 case silentCrushAndRaise:
89 case genSilentCrusher:
90 break;
91 default:
92 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
93 break;
94 }
95 }
96
97 // handle reaching destination height
98 if (res == pastdest)
99 {
100 switch(ceiling->type)
101 {
102 // plain movers are just removed
103 case raiseToHighest:
104 case genCeiling:
105 P_RemoveActiveCeiling(ceiling);
106 break;
107
108 // movers with texture change, change the texture then get removed
109 case genCeilingChgT:
110 case genCeilingChg0:
111 ceiling->sector->special = ceiling->newspecial;
112 //jff 3/14/98 transfer old special field as well
113 ceiling->sector->oldspecial = ceiling->oldspecial;
114 case genCeilingChg:
115 ceiling->sector->ceilingpic = ceiling->texture;
116 P_RemoveActiveCeiling(ceiling);
117 break;
118
119 // crushers reverse direction at the top
120 case silentCrushAndRaise:
121 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
122 case genSilentCrusher:
123 case genCrusher:
124 case fastCrushAndRaise:
125 case crushAndRaise:
126 ceiling->direction = -1;
127 break;
128
129 default:
130 break;
131 }
132 }
133 break;
134
135 case -1:
136 // Ceiling moving down
137 res = T_MovePlane
138 (
139 ceiling->sector,
140 ceiling->speed,
141 ceiling->bottomheight,
142 ceiling->crush,
143 1,
144 ceiling->direction
145 );
146
147 // if not silent crusher type make moving sound
148 if (!(leveltime&7))
149 {
150 switch(ceiling->type)
151 {
152 case silentCrushAndRaise:
153 case genSilentCrusher:
154 break;
155 default:
156 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
157 }
158 }
159
160 // handle reaching destination height
161 if (res == pastdest)
162 {
163 switch(ceiling->type)
164 {
165 // 02/09/98 jff change slow crushers' speed back to normal
166 // start back up
167 case genSilentCrusher:
168 case genCrusher:
169 if (ceiling->oldspeed<CEILSPEED*3)
170 ceiling->speed = ceiling->oldspeed;
171 ceiling->direction = 1; //jff 2/22/98 make it go back up!
172 break;
173
174 // make platform stop at bottom of all crusher strokes
175 // except generalized ones, reset speed, start back up
176 case silentCrushAndRaise:
177 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_pstop);
178 case crushAndRaise:
179 ceiling->speed = CEILSPEED;
180 case fastCrushAndRaise:
181 ceiling->direction = 1;
182 break;
183
184 // in the case of ceiling mover/changer, change the texture
185 // then remove the active ceiling
186 case genCeilingChgT:
187 case genCeilingChg0:
188 ceiling->sector->special = ceiling->newspecial;
189 //jff add to fix bug in special transfers from changes
190 ceiling->sector->oldspecial = ceiling->oldspecial;
191 case genCeilingChg:
192 ceiling->sector->ceilingpic = ceiling->texture;
193 P_RemoveActiveCeiling(ceiling);
194 break;
195
196 // all other case, just remove the active ceiling
197 case lowerAndCrush:
198 case lowerToFloor:
199 case lowerToLowest:
200 case lowerToMaxFloor:
201 case genCeiling:
202 P_RemoveActiveCeiling(ceiling);
203 break;
204
205 default:
206 break;
207 }
208 }
209 else // ( res != pastdest )
210 {
211 // handle the crusher encountering an obstacle
212 if (res == crushed)
213 {
214 switch(ceiling->type)
215 {
216 //jff 02/08/98 slow down slow crushers on obstacle
217 case genCrusher:
218 case genSilentCrusher:
219 if (ceiling->oldspeed < CEILSPEED*3)
220 ceiling->speed = CEILSPEED / 8;
221 break;
222 case silentCrushAndRaise:
223 case crushAndRaise:
224 case lowerAndCrush:
225 ceiling->speed = CEILSPEED / 8;
226 break;
227
228 default:
229 break;
230 }
231 }
232 }
233 break;
234 }
235}
236
237
238//
239// EV_DoCeiling
240//
241// Move a ceiling up/down or start a crusher
242//
243// Passed the linedef activating the function and the type of function desired
244// returns true if a thinker started
245//
246int EV_DoCeiling
247( line_t* line,
248 ceiling_e type )
249{
250 int secnum;
251 int rtn;
252 sector_t* sec;
253 ceiling_t* ceiling;
254
255 secnum = -1;
256 rtn = 0;
257
258 // Reactivate in-stasis ceilings...for certain types.
259 // This restarts a crusher after it has been stopped
260 switch(type)
261 {
262 case fastCrushAndRaise:
263 case silentCrushAndRaise:
264 case crushAndRaise:
265 //jff 4/5/98 return if activated
266 rtn = P_ActivateInStasisCeiling(line);
267 default:
268 break;
269 }
270
271 // affects all sectors with the same tag as the linedef
272 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
273 {
274 sec = &sectors[secnum];
275
276 // if ceiling already moving, don't start a second function on it
277 if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98
278 continue;
279
280 // create a new ceiling thinker
281 rtn = 1;
282 ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
283 memset(ceiling, 0, sizeof(*ceiling));
284 P_AddThinker (&ceiling->thinker);
285 sec->ceilingdata = ceiling; //jff 2/22/98
286 ceiling->thinker.function = T_MoveCeiling;
287 ceiling->sector = sec;
288 ceiling->crush = false;
289
290 // setup ceiling structure according to type of function
291 switch(type)
292 {
293 case fastCrushAndRaise:
294 ceiling->crush = true;
295 ceiling->topheight = sec->ceilingheight;
296 ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
297 ceiling->direction = -1;
298 ceiling->speed = CEILSPEED * 2;
299 break;
300
301 case silentCrushAndRaise:
302 case crushAndRaise:
303 ceiling->crush = true;
304 ceiling->topheight = sec->ceilingheight;
305 case lowerAndCrush:
306 case lowerToFloor:
307 ceiling->bottomheight = sec->floorheight;
308 if (type != lowerToFloor)
309 ceiling->bottomheight += 8*FRACUNIT;
310 ceiling->direction = -1;
311 ceiling->speed = CEILSPEED;
312 break;
313
314 case raiseToHighest:
315 ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
316 ceiling->direction = 1;
317 ceiling->speed = CEILSPEED;
318 break;
319
320 case lowerToLowest:
321 ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
322 ceiling->direction = -1;
323 ceiling->speed = CEILSPEED;
324 break;
325
326 case lowerToMaxFloor:
327 ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
328 ceiling->direction = -1;
329 ceiling->speed = CEILSPEED;
330 break;
331
332 default:
333 break;
334 }
335
336 // add the ceiling to the active list
337 ceiling->tag = sec->tag;
338 ceiling->type = type;
339 P_AddActiveCeiling(ceiling);
340 }
341 return rtn;
342}
343
344//////////////////////////////////////////////////////////////////////
345//
346// Active ceiling list primitives
347//
348/////////////////////////////////////////////////////////////////////
349
350// jff 2/22/98 - modified Lee's plat code to work for ceilings
351//
352// The following were all rewritten by Lee Killough
353// to use the new structure which places no limits
354// on active ceilings. It also avoids spending as much
355// time searching for active ceilings. Previously a
356// fixed-size array was used, with NULL indicating
357// empty entries, while now a doubly-linked list
358// is used.
359
360//
361// P_ActivateInStasisCeiling()
362//
363// Reactivates all stopped crushers with the right tag
364//
365// Passed the line reactivating the crusher
366// Returns true if a ceiling reactivated
367//
368//jff 4/5/98 return if activated
369int P_ActivateInStasisCeiling(line_t *line)
370{
371 ceilinglist_t *cl;
372 int rtn=0;
373
374 for (cl=activeceilings; cl; cl=cl->next)
375 {
376 ceiling_t *ceiling = cl->ceiling;
377 if (ceiling->tag == line->tag && ceiling->direction == 0)
378 {
379 ceiling->direction = ceiling->olddirection;
380 ceiling->thinker.function = T_MoveCeiling;
381 //jff 4/5/98 return if activated
382 rtn=1;
383 }
384 }
385 return rtn;
386}
387
388//
389// EV_CeilingCrushStop()
390//
391// Stops all active ceilings with the right tag
392//
393// Passed the linedef stopping the ceilings
394// Returns true if a ceiling put in stasis
395//
396int EV_CeilingCrushStop(line_t* line)
397{
398 int rtn=0;
399
400 ceilinglist_t *cl;
401 for (cl=activeceilings; cl; cl=cl->next)
402 {
403 ceiling_t *ceiling = cl->ceiling;
404 if (ceiling->direction != 0 && ceiling->tag == line->tag)
405 {
406 ceiling->olddirection = ceiling->direction;
407 ceiling->direction = 0;
408 ceiling->thinker.function = NULL;
409 rtn=1;
410 }
411 }
412 return rtn;
413}
414
415//
416// P_AddActiveCeiling()
417//
418// Adds a ceiling to the head of the list of active ceilings
419//
420// Passed the ceiling motion structure
421// Returns nothing
422//
423void P_AddActiveCeiling(ceiling_t* ceiling)
424{
425 ceilinglist_t *list = malloc(sizeof *list);
426 list->ceiling = ceiling;
427 ceiling->list = list;
428 if ((list->next = activeceilings))
429 list->next->prev = &list->next;
430 list->prev = &activeceilings;
431 activeceilings = list;
432}
433
434//
435// P_RemoveActiveCeiling()
436//
437// Removes a ceiling from the list of active ceilings
438//
439// Passed the ceiling motion structure
440// Returns nothing
441//
442void P_RemoveActiveCeiling(ceiling_t* ceiling)
443{
444 ceilinglist_t *list = ceiling->list;
445 ceiling->sector->ceilingdata = NULL; //jff 2/22/98
446 P_RemoveThinker(&ceiling->thinker);
447 if ((*list->prev = list->next))
448 list->next->prev = list->prev;
449 free(list);
450}
451
452//
453// P_RemoveAllActiveCeilings()
454//
455// Removes all ceilings from the active ceiling list
456//
457// Passed nothing, returns nothing
458//
459void P_RemoveAllActiveCeilings(void)
460{
461 while (activeceilings)
462 {
463 ceilinglist_t *next = activeceilings->next;
464 free(activeceilings);
465 activeceilings = next;
466 }
467}