1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: p_ceilng.c 1361 2017-10-16 16:26:45Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-2000 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 //
20 // $Log: p_ceilng.c,v $
21 // Revision 1.9  2002/06/14 02:43:43  ssntails
22 // Instant-lower and instant-raise capability for sectors added.
23 //
24 // Revision 1.8  2001/01/25 22:15:43  bpereira
25 // added heretic support
26 //
27 // Revision 1.7  2000/10/21 08:43:30  bpereira
28 // Revision 1.6  2000/09/28 20:57:16  bpereira
29 //
30 // Revision 1.5  2000/04/11 19:07:24  stroggonmeth
31 // Finished my logs, fixed a crashing bug.
32 //
33 // Revision 1.4  2000/04/08 17:29:24  stroggonmeth
34 //
35 // Revision 1.3  2000/04/04 00:32:46  stroggonmeth
36 // Initial Boom compatability plus few misc changes all around.
37 //
38 // Revision 1.2  2000/02/27 00:42:10  hurdler
39 // Revision 1.1.1.1  2000/02/22 20:32:32  hurdler
40 // Initial import into CVS (v1.29 pr3)
41 //
42 //
43 // DESCRIPTION:
44 //      Ceiling aninmation (lowering, crushing, raising)
45 //
46 //-----------------------------------------------------------------------------
47 
48 
49 #include "doomincl.h"
50 #include "p_local.h"
51 #include "p_tick.h"
52   // think
53 #include "r_state.h"
54 #include "s_sound.h"
55 #include "z_zone.h"
56 
57 // ==========================================================================
58 //                              CEILINGS
59 // ==========================================================================
60 
61 
62 // SoM: 3/6/2000: the list of ceilings moving currently, including crushers
63 ceilinglist_t *activeceilings;
64 //ceiling_t*      activeceilings[MAXCEILINGS];
65 int ceilmovesound = sfx_stnmov;
66 
67 //
68 // T_MoveCeiling
69 //
70 
T_MoveCeiling(ceiling_t * ceiling)71 void T_MoveCeiling (ceiling_t* ceiling)
72 {
73     result_e    res;
74 
75     switch(ceiling->direction)
76     {
77       case 0:
78         // IN STASIS
79         break;
80       case 1:
81         // UP
82         res = T_MovePlane(ceiling->sector,
83                           ceiling->speed,
84                           ceiling->topheight,
85                           false,1,ceiling->direction);
86 
87         if (!(leveltime % (8*NEWTICRATERATIO)))
88         {
89             switch(ceiling->type)
90             {
91               case CT_silentCrushAndRaise:
92               case CT_genSilentCrusher:
93                 break;
94               default:
95                 S_StartSecSound(ceiling->sector, ceilmovesound);
96                 // ?
97                 break;
98             }
99         }
100 
101         if (res == MP_pastdest)
102         {
103             switch(ceiling->type)
104             {
105 
106               case CT_raiseToHighest:
107               //SoM: 3/6/2000
108               case CT_genCeiling:  // Boom, general ceiling move
109                 P_RemoveActiveCeiling(ceiling);
110                 break;
111 
112               // SoM: 3/6/2000: movers with texture change, change the texture then get removed
113               case CT_genCeilingChgT:  // Boom, change sector type
114               case CT_genCeilingChg0:  // Boom, zero sector type
115                 ceiling->sector->special = ceiling->new_sec_special;
116                 ceiling->sector->oldspecial = ceiling->old_sec_special;
117                 // change ceilingpic too
118               case CT_genCeilingChg:  // Boom, change only texture
119                 ceiling->sector->ceilingpic = ceiling->new_ceilingpic;
120                 P_RemoveActiveCeiling(ceiling);
121                 break;
122 
123               case CT_silentCrushAndRaise:
124                 S_StartSecSound(ceiling->sector, sfx_pstop);
125               case CT_fastCrushAndRaise:
126               case CT_genCrusher: // SoM: 3/6/2000
127               case CT_genSilentCrusher:
128               case CT_crushAndRaise:
129                 ceiling->direction = -1;
130                 break;
131 
132               default:
133                 break;
134             }
135         }
136         break;
137 
138       case -1:
139         // DOWN
140         res = T_MovePlane(ceiling->sector,
141                           ceiling->speed,
142                           ceiling->bottomheight,
143                           ceiling->crush,1,ceiling->direction);
144 
145         if (!(leveltime % (8*NEWTICRATERATIO)))
146         {
147             switch(ceiling->type)
148             {
149               case CT_silentCrushAndRaise:
150               case CT_genSilentCrusher:
151                 break;
152               default:
153                 S_StartSecSound(ceiling->sector, ceilmovesound);
154             }
155         }
156 
157         if (res == MP_pastdest)
158         {
159             switch(ceiling->type) //SoM: 3/6/2000: Use boom code
160             {
161               case CT_genSilentCrusher:
162               case CT_genCrusher:
163                 if (ceiling->oldspeed<CEILSPEED*3)
164                   ceiling->speed = ceiling->oldspeed;
165                 ceiling->direction = 1;
166                 break;
167 
168               // make platform stop at bottom of all crusher strokes
169               // except generalized ones, reset speed, start back up
170               case CT_silentCrushAndRaise:
171                 S_StartSecSound(ceiling->sector, sfx_pstop);
172               case CT_crushAndRaise:
173                 ceiling->speed = CEILSPEED;
174               case CT_fastCrushAndRaise:
175                 ceiling->direction = 1;
176                 break;
177 
178               // in the case of ceiling mover/changer, change the texture
179               // then remove the active ceiling
180               case CT_genCeilingChgT:  // Boom
181               case CT_genCeilingChg0:  // Boom
182                 ceiling->sector->special = ceiling->new_sec_special;
183                 //jff add to fix bug in special transfers from changes
184                 ceiling->sector->oldspecial = ceiling->old_sec_special;
185               case CT_genCeilingChg:  // Boom
186                 ceiling->sector->ceilingpic = ceiling->new_ceilingpic;
187                 P_RemoveActiveCeiling(ceiling);
188                 break;
189 
190               // all other case, just remove the active ceiling
191               case CT_lowerAndCrush:
192               case CT_lowerToFloor:
193               case CT_lowerToLowest:
194               case CT_lowerToMaxFloor:
195               case CT_genCeiling:
196                 P_RemoveActiveCeiling(ceiling);
197                 break;
198 
199               default:
200                 break;
201             }
202         }
203         else // ( res != MP_pastdest )
204         {
205             if (res == MP_crushed)
206             {
207                 switch(ceiling->type)
208                 {
209                   //SoM: 2/6/2000
210                   // slow down slow crushers on obstacle
211                   case CT_genCrusher:
212                   case CT_genSilentCrusher:
213                     if (ceiling->oldspeed < CEILSPEED*3)
214                       ceiling->speed = CEILSPEED / 8;
215                     break;
216 
217                   case CT_silentCrushAndRaise:
218                   case CT_crushAndRaise:
219                   case CT_lowerAndCrush:
220                     ceiling->speed = CEILSPEED / 8;
221                     break;
222 
223                   default:
224                     break;
225                 }
226             }
227         }
228         break;
229     }
230 }
231 
232 
233 //
234 // EV_DoCeiling
235 // Move a ceiling up/down and all around!
236 //
EV_DoCeiling(line_t * line,ceiling_e type)237 int  EV_DoCeiling ( line_t* line, ceiling_e type )
238 {
239     int         secnum;
240     int         rtn;
241     sector_t*   sec;
242     ceiling_t*  ceiling;
243 
244     secnum = -1;
245     rtn = 0;
246 
247     //  Reactivate in-stasis ceilings...for certain types.
248     // This restarts a crusher after it has been stopped
249     switch(type)
250     {
251       case CT_fastCrushAndRaise:
252       case CT_silentCrushAndRaise:
253       case CT_crushAndRaise:
254         rtn = P_ActivateInStasisCeiling(line); //SoM: Return true if the crusher is activated
255       default:
256         break;
257     }
258 
259     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
260     {
261         sec = &sectors[secnum];
262 
263 
264         if (P_SectorActive( S_ceiling_special, sec))  //SoM: 3/6/2000
265             continue;
266 
267         // new door thinker
268         rtn = 1;
269         ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0);
270         P_AddThinker (&ceiling->thinker);
271         sec->ceilingdata = ceiling;
272         ceiling->thinker.function.acp1 = (actionf_p1) T_MoveCeiling;
273         ceiling->sector = sec;
274         ceiling->crush = false;
275 
276         switch(type)
277         {
278           case CT_fastCrushAndRaise:
279             ceiling->crush = true;
280             ceiling->topheight = sec->ceilingheight;
281             ceiling->bottomheight = sec->floorheight + (8*FRACUNIT);
282             ceiling->direction = -1;
283             ceiling->speed = CEILSPEED * 2;
284             break;
285 
286           case CT_silentCrushAndRaise:
287           case CT_crushAndRaise:
288             ceiling->crush = true;
289             ceiling->topheight = sec->ceilingheight;
290           case CT_lowerAndCrush:
291           case CT_lowerToFloor:
292             ceiling->bottomheight = sec->floorheight;
293             if (type != CT_lowerToFloor)
294                 ceiling->bottomheight += 8*FRACUNIT;
295             ceiling->direction = -1;
296             ceiling->speed = CEILSPEED;
297             break;
298 
299           case CT_raiseToHighest:
300             ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
301             ceiling->direction = 1;
302             ceiling->speed = CEILSPEED;
303             break;
304 
305           //SoM: 3/6/2000: Added Boom types
306           case CT_lowerToLowest:
307             ceiling->bottomheight = P_FindLowestCeilingSurrounding(sec);
308             ceiling->direction = -1;
309             ceiling->speed = CEILSPEED;
310             break;
311 
312           case CT_lowerToMaxFloor:
313             ceiling->bottomheight = P_FindHighestFloorSurrounding(sec);
314             ceiling->direction = -1;
315             ceiling->speed = CEILSPEED;
316             break;
317 
318           // Instant-raise SSNTails 06-13-2002
319           case CT_instantRaise:
320             ceiling->topheight = P_FindHighestCeilingSurrounding(sec);
321             ceiling->direction = 1;
322             ceiling->speed = FIXED_MAX/2; // Go too fast and you'll cause problems...
323             break;
324 
325           default:
326             break;
327 
328         }
329 
330         ceiling->tag = sec->tag;
331         ceiling->type = type;
332         P_AddActiveCeiling(ceiling);
333     }
334     return rtn;
335 }
336 
337 
338 //
339 // Add an active ceiling
340 //
341 //SoM: 3/6/2000: Take advantage of the new Boom method for active ceilings.
P_AddActiveCeiling(ceiling_t * ceiling)342 void P_AddActiveCeiling(ceiling_t* ceiling)
343 {
344   ceilinglist_t *list = malloc(sizeof *list);
345   list->ceiling = ceiling;
346   ceiling->list = list;
347   if ((list->next = activeceilings))
348     list->next->prev = &list->next;
349   list->prev = &activeceilings;
350   activeceilings = list;
351 }
352 
353 
354 
355 //
356 // Remove a ceiling's thinker
357 //
358 // SoM: 3/6/2000 :Use improved Boom code.
P_RemoveActiveCeiling(ceiling_t * ceiling)359 void P_RemoveActiveCeiling(ceiling_t* ceiling)
360 {
361   ceilinglist_t *list = ceiling->list;
362   ceiling->sector->ceilingdata = NULL;  //jff 2/22/98
363   P_RemoveThinker(&ceiling->thinker);
364   if ((*list->prev = list->next))
365     list->next->prev = list->prev;
366   free(list);
367 }
368 
369 
370 
371 //
372 // Restart a ceiling that's in-stasis
373 //
374 //SoM: 3/6/2000: Use improved boom code
P_ActivateInStasisCeiling(line_t * line)375 int P_ActivateInStasisCeiling(line_t *line)
376 {
377   ceilinglist_t *cl;
378   int rtn=0;
379 
380   for (cl=activeceilings; cl; cl=cl->next)
381   {
382     ceiling_t *ceiling = cl->ceiling;
383     if (ceiling->tag == line->tag && ceiling->direction == 0)
384     {
385       ceiling->direction = ceiling->olddirection;
386       ceiling->thinker.function.acp1 = (actionf_p1) T_MoveCeiling;
387       rtn=1;
388     }
389   }
390   return rtn;
391 }
392 
393 
394 
395 //
396 // EV_CeilingCrushStop
397 // Stop a ceiling from crushing!
398 //
399 //SoM: 3/6/2000: use improved Boom code
EV_CeilingCrushStop(line_t * line)400 int EV_CeilingCrushStop(line_t* line)
401 {
402   int rtn=0;
403 
404   ceilinglist_t *cl;
405   for (cl=activeceilings; cl; cl=cl->next)
406   {
407     ceiling_t *ceiling = cl->ceiling;
408     if (ceiling->direction != 0 && ceiling->tag == line->tag)
409     {
410       ceiling->olddirection = ceiling->direction;
411       ceiling->direction = 0;
412       ceiling->thinker.function.acv = NULL;
413       rtn=1;
414     }
415   }
416   return rtn;
417 }
418 
419 
420 
421 // SoM: 3/6/2000: Extra, boom only function.
422 //
423 // P_Remove_AllActiveCeilings()
424 //
425 // Removes all ceilings from the active ceiling list
426 //
427 // Passed nothing, returns nothing
428 //
P_Remove_AllActiveCeilings(void)429 void P_Remove_AllActiveCeilings(void)
430 {
431   while (activeceilings)
432   {
433     ceilinglist_t *next = activeceilings->next;
434     free(activeceilings);
435     activeceilings = next;
436   }
437 }
438