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 = §ors[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