drop 'req' from gas macro, not available in binutils 2.16
[kugel-rb.git] / apps / plugins / doom / p_ceilng.c
blobdb5a701b1ade008fc8fdbdfe9d2b77b7aa653805
1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
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.
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.
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.
27 * DESCRIPTION:
28 * Ceiling aninmation (lowering, crushing, raising)
30 *-----------------------------------------------------------------------------*/
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"
43 // the list of ceilings moving currently, including crushers
44 ceilinglist_t *activeceilings;
46 /////////////////////////////////////////////////////////////////
48 // Ceiling action routine and linedef type handler
50 /////////////////////////////////////////////////////////////////
53 // T_MoveCeiling
55 // Action routine that moves ceilings. Called once per tick.
57 // Passed a ceiling_t structure that contains all the info about the move.
58 // see P_SPEC.H for fields. No return.
60 // jff 02/08/98 all cases with labels beginning with gen added to support
61 // generalized line type behaviors.
63 void T_MoveCeiling (ceiling_t* ceiling)
65 result_e res;
67 switch(ceiling->direction)
69 case 0:
70 // If ceiling in stasis, do nothing
71 break;
73 case 1:
74 // Ceiling is moving up
75 res = T_MovePlane
77 ceiling->sector,
78 ceiling->speed,
79 ceiling->topheight,
80 false,
82 ceiling->direction
85 // if not a silent crusher, make moving sound
86 if (!(leveltime&7))
88 switch(ceiling->type)
90 case silentCrushAndRaise:
91 case genSilentCrusher:
92 break;
93 default:
94 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
95 break;
99 // handle reaching destination height
100 if (res == pastdest)
102 switch(ceiling->type)
104 // plain movers are just removed
105 case raiseToHighest:
106 case genCeiling:
107 P_RemoveActiveCeiling(ceiling);
108 break;
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;
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;
131 default:
132 break;
135 break;
137 case -1:
138 // Ceiling moving down
139 res = T_MovePlane
141 ceiling->sector,
142 ceiling->speed,
143 ceiling->bottomheight,
144 ceiling->crush,
146 ceiling->direction
149 // if not silent crusher type make moving sound
150 if (!(leveltime&7))
152 switch(ceiling->type)
154 case silentCrushAndRaise:
155 case genSilentCrusher:
156 break;
157 default:
158 S_StartSound((mobj_t *)&ceiling->sector->soundorg,sfx_stnmov);
162 // handle reaching destination height
163 if (res == pastdest)
165 switch(ceiling->type)
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;
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;
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;
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;
207 default:
208 break;
211 else // ( res != pastdest )
213 // handle the crusher encountering an obstacle
214 if (res == crushed)
216 switch(ceiling->type)
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;
230 default:
231 break;
235 break;
241 // EV_DoCeiling
243 // Move a ceiling up/down or start a crusher
245 // Passed the linedef activating the function and the type of function desired
246 // returns true if a thinker started
248 int EV_DoCeiling
249 ( line_t* line,
250 ceiling_e type )
252 int secnum;
253 int rtn;
254 sector_t* sec;
255 ceiling_t* ceiling;
257 secnum = -1;
258 rtn = 0;
260 // Reactivate in-stasis ceilings...for certain types.
261 // This restarts a crusher after it has been stopped
262 switch(type)
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;
273 // affects all sectors with the same tag as the linedef
274 while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
276 sec = &sectors[secnum];
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;
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;
291 // setup ceiling structure according to type of function
292 switch(type)
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;
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;
315 case raiseToHighest:
316 ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
317 ceiling->direction = 1;
318 ceiling->speed = CEILSPEED;
319 break;
321 case lowerToLowest:
322 ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
323 ceiling->direction = -1;
324 ceiling->speed = CEILSPEED;
325 break;
327 case lowerToMaxFloor:
328 ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
329 ceiling->direction = -1;
330 ceiling->speed = CEILSPEED;
331 break;
333 default:
334 break;
337 // add the ceiling to the active list
338 ceiling->tag = sec->tag;
339 ceiling->type = type;
340 P_AddActiveCeiling(ceiling);
342 return rtn;
345 //////////////////////////////////////////////////////////////////////
347 // Active ceiling list primitives
349 /////////////////////////////////////////////////////////////////////
351 // jff 2/22/98 - modified Lee's plat code to work for ceilings
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.
362 // P_ActivateInStasisCeiling()
364 // Reactivates all stopped crushers with the right tag
366 // Passed the line reactivating the crusher
367 // Returns true if a ceiling reactivated
369 //jff 4/5/98 return if activated
370 int P_ActivateInStasisCeiling(line_t *line)
372 ceilinglist_t *cl;
373 int rtn=0;
375 for (cl=activeceilings; cl; cl=cl->next)
377 ceiling_t *ceiling = cl->ceiling;
378 if (ceiling->tag == line->tag && ceiling->direction == 0)
380 ceiling->direction = ceiling->olddirection;
381 ceiling->thinker.function = T_MoveCeiling;
382 //jff 4/5/98 return if activated
383 rtn=1;
386 return rtn;
390 // EV_CeilingCrushStop()
392 // Stops all active ceilings with the right tag
394 // Passed the linedef stopping the ceilings
395 // Returns true if a ceiling put in stasis
397 int EV_CeilingCrushStop(line_t* line)
399 int rtn=0;
401 ceilinglist_t *cl;
402 for (cl=activeceilings; cl; cl=cl->next)
404 ceiling_t *ceiling = cl->ceiling;
405 if (ceiling->direction != 0 && ceiling->tag == line->tag)
407 ceiling->olddirection = ceiling->direction;
408 ceiling->direction = 0;
409 ceiling->thinker.function = NULL;
410 rtn=1;
413 return rtn;
417 // P_AddActiveCeiling()
419 // Adds a ceiling to the head of the list of active ceilings
421 // Passed the ceiling motion structure
422 // Returns nothing
424 void P_AddActiveCeiling(ceiling_t* ceiling)
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;
436 // P_RemoveActiveCeiling()
438 // Removes a ceiling from the list of active ceilings
440 // Passed the ceiling motion structure
441 // Returns nothing
443 void P_RemoveActiveCeiling(ceiling_t* ceiling)
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);
454 // P_RemoveAllActiveCeilings()
456 // Removes all ceilings from the active ceiling list
458 // Passed nothing, returns nothing
460 void P_RemoveAllActiveCeilings(void)
462 while (activeceilings)
464 ceilinglist_t *next = activeceilings->next;
465 free(activeceilings);
466 activeceilings = next;