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