diff options
Diffstat (limited to 'apps/plugins/doom/p_genlin.c')
-rw-r--r-- | apps/plugins/doom/p_genlin.c | 1154 |
1 files changed, 1154 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_genlin.c b/apps/plugins/doom/p_genlin.c new file mode 100644 index 0000000000..a521210c64 --- /dev/null +++ b/apps/plugins/doom/p_genlin.c | |||
@@ -0,0 +1,1154 @@ | |||
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 | * Generalized linedef type handlers | ||
29 | * Floors, Ceilings, Doors, Locked Doors, Lifts, Stairs, Crushers | ||
30 | * | ||
31 | *-----------------------------------------------------------------------------*/ | ||
32 | |||
33 | #include "doomstat.h" //jff 6/19/98 for demo_compatibility | ||
34 | #include "r_main.h" | ||
35 | #include "p_spec.h" | ||
36 | #include "p_tick.h" | ||
37 | #include "m_random.h" | ||
38 | #include "s_sound.h" | ||
39 | #include "sounds.h" | ||
40 | |||
41 | ////////////////////////////////////////////////////////// | ||
42 | // | ||
43 | // Generalized Linedef Type handlers | ||
44 | // | ||
45 | ////////////////////////////////////////////////////////// | ||
46 | |||
47 | // | ||
48 | // EV_DoGenFloor() | ||
49 | // | ||
50 | // Handle generalized floor types | ||
51 | // | ||
52 | // Passed the line activating the generalized floor function | ||
53 | // Returns true if a thinker is created | ||
54 | // | ||
55 | // jff 02/04/98 Added this routine (and file) to handle generalized | ||
56 | // floor movers using bit fields in the line special type. | ||
57 | // | ||
58 | int EV_DoGenFloor | ||
59 | ( line_t* line ) | ||
60 | { | ||
61 | int secnum; | ||
62 | int rtn; | ||
63 | boolean manual; | ||
64 | sector_t* sec; | ||
65 | floormove_t* floor; | ||
66 | unsigned value = (unsigned)line->special - GenFloorBase; | ||
67 | |||
68 | // parse the bit fields in the line's special type | ||
69 | |||
70 | int Crsh = (value & FloorCrush) >> FloorCrushShift; | ||
71 | int ChgT = (value & FloorChange) >> FloorChangeShift; | ||
72 | int Targ = (value & FloorTarget) >> FloorTargetShift; | ||
73 | int Dirn = (value & FloorDirection) >> FloorDirectionShift; | ||
74 | int ChgM = (value & FloorModel) >> FloorModelShift; | ||
75 | int Sped = (value & FloorSpeed) >> FloorSpeedShift; | ||
76 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
77 | |||
78 | rtn = 0; | ||
79 | |||
80 | // check if a manual trigger, if so do just the sector on the backside | ||
81 | manual = false; | ||
82 | if (Trig==PushOnce || Trig==PushMany) | ||
83 | { | ||
84 | if (!(sec = line->backsector)) | ||
85 | return rtn; | ||
86 | secnum = sec-sectors; | ||
87 | manual = true; | ||
88 | goto manual_floor; | ||
89 | } | ||
90 | |||
91 | secnum = -1; | ||
92 | // if not manual do all sectors tagged the same as the line | ||
93 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
94 | { | ||
95 | sec = §ors[secnum]; | ||
96 | |||
97 | manual_floor: | ||
98 | // Do not start another function if floor already moving | ||
99 | if (P_SectorActive(floor_special,sec)) | ||
100 | { | ||
101 | if (!manual) | ||
102 | continue; | ||
103 | else | ||
104 | return rtn; | ||
105 | } | ||
106 | |||
107 | // new floor thinker | ||
108 | rtn = 1; | ||
109 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
110 | P_AddThinker (&floor->thinker); | ||
111 | sec->floordata = floor; | ||
112 | floor->thinker.function = T_MoveFloor; | ||
113 | floor->crush = Crsh; | ||
114 | floor->direction = Dirn? 1 : -1; | ||
115 | floor->sector = sec; | ||
116 | floor->texture = sec->floorpic; | ||
117 | floor->newspecial = sec->special; | ||
118 | //jff 3/14/98 transfer old special field too | ||
119 | floor->oldspecial = sec->oldspecial; | ||
120 | floor->type = genFloor; | ||
121 | |||
122 | // set the speed of motion | ||
123 | switch (Sped) | ||
124 | { | ||
125 | case SpeedSlow: | ||
126 | floor->speed = FLOORSPEED; | ||
127 | break; | ||
128 | case SpeedNormal: | ||
129 | floor->speed = FLOORSPEED*2; | ||
130 | break; | ||
131 | case SpeedFast: | ||
132 | floor->speed = FLOORSPEED*4; | ||
133 | break; | ||
134 | case SpeedTurbo: | ||
135 | floor->speed = FLOORSPEED*8; | ||
136 | break; | ||
137 | default: | ||
138 | break; | ||
139 | } | ||
140 | |||
141 | // set the destination height | ||
142 | switch(Targ) | ||
143 | { | ||
144 | case FtoHnF: | ||
145 | floor->floordestheight = P_FindHighestFloorSurrounding(sec); | ||
146 | break; | ||
147 | case FtoLnF: | ||
148 | floor->floordestheight = P_FindLowestFloorSurrounding(sec); | ||
149 | break; | ||
150 | case FtoNnF: | ||
151 | floor->floordestheight = Dirn? | ||
152 | P_FindNextHighestFloor(sec,sec->floorheight) : | ||
153 | P_FindNextLowestFloor(sec,sec->floorheight); | ||
154 | break; | ||
155 | case FtoLnC: | ||
156 | floor->floordestheight = P_FindLowestCeilingSurrounding(sec); | ||
157 | break; | ||
158 | case FtoC: | ||
159 | floor->floordestheight = sec->ceilingheight; | ||
160 | break; | ||
161 | case FbyST: | ||
162 | floor->floordestheight = (floor->sector->floorheight>>FRACBITS) + | ||
163 | floor->direction * (P_FindShortestTextureAround(secnum)>>FRACBITS); | ||
164 | if (floor->floordestheight>32000) //jff 3/13/98 prevent overflow | ||
165 | floor->floordestheight=32000; // wraparound in floor height | ||
166 | if (floor->floordestheight<-32000) | ||
167 | floor->floordestheight=-32000; | ||
168 | floor->floordestheight<<=FRACBITS; | ||
169 | break; | ||
170 | case Fby24: | ||
171 | floor->floordestheight = floor->sector->floorheight + | ||
172 | floor->direction * 24*FRACUNIT; | ||
173 | break; | ||
174 | case Fby32: | ||
175 | floor->floordestheight = floor->sector->floorheight + | ||
176 | floor->direction * 32*FRACUNIT; | ||
177 | break; | ||
178 | default: | ||
179 | break; | ||
180 | } | ||
181 | |||
182 | // set texture/type change properties | ||
183 | if (ChgT) // if a texture change is indicated | ||
184 | { | ||
185 | if (ChgM) // if a numeric model change | ||
186 | { | ||
187 | sector_t *sec; | ||
188 | |||
189 | //jff 5/23/98 find model with ceiling at target height if target | ||
190 | //is a ceiling type | ||
191 | sec = (Targ==FtoLnC || Targ==FtoC)? | ||
192 | P_FindModelCeilingSector(floor->floordestheight,secnum) : | ||
193 | P_FindModelFloorSector(floor->floordestheight,secnum); | ||
194 | if (sec) | ||
195 | { | ||
196 | floor->texture = sec->floorpic; | ||
197 | switch(ChgT) | ||
198 | { | ||
199 | case FChgZero: // zero type | ||
200 | floor->newspecial = 0; | ||
201 | //jff 3/14/98 change old field too | ||
202 | floor->oldspecial = 0; | ||
203 | floor->type = genFloorChg0; | ||
204 | break; | ||
205 | case FChgTyp: // copy type | ||
206 | floor->newspecial = sec->special; | ||
207 | //jff 3/14/98 change old field too | ||
208 | floor->oldspecial = sec->oldspecial; | ||
209 | floor->type = genFloorChgT; | ||
210 | break; | ||
211 | case FChgTxt: // leave type be | ||
212 | floor->type = genFloorChg; | ||
213 | break; | ||
214 | default: | ||
215 | break; | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | else // else if a trigger model change | ||
220 | { | ||
221 | floor->texture = line->frontsector->floorpic; | ||
222 | switch (ChgT) | ||
223 | { | ||
224 | case FChgZero: // zero type | ||
225 | floor->newspecial = 0; | ||
226 | //jff 3/14/98 change old field too | ||
227 | floor->oldspecial = 0; | ||
228 | floor->type = genFloorChg0; | ||
229 | break; | ||
230 | case FChgTyp: // copy type | ||
231 | floor->newspecial = line->frontsector->special; | ||
232 | //jff 3/14/98 change old field too | ||
233 | floor->oldspecial = line->frontsector->oldspecial; | ||
234 | floor->type = genFloorChgT; | ||
235 | break; | ||
236 | case FChgTxt: // leave type be | ||
237 | floor->type = genFloorChg; | ||
238 | default: | ||
239 | break; | ||
240 | } | ||
241 | } | ||
242 | } | ||
243 | if (manual) return rtn; | ||
244 | } | ||
245 | return rtn; | ||
246 | } | ||
247 | |||
248 | |||
249 | // | ||
250 | // EV_DoGenCeiling() | ||
251 | // | ||
252 | // Handle generalized ceiling types | ||
253 | // | ||
254 | // Passed the linedef activating the ceiling function | ||
255 | // Returns true if a thinker created | ||
256 | // | ||
257 | // jff 02/04/98 Added this routine (and file) to handle generalized | ||
258 | // floor movers using bit fields in the line special type. | ||
259 | // | ||
260 | int EV_DoGenCeiling | ||
261 | ( line_t* line ) | ||
262 | { | ||
263 | int secnum; | ||
264 | int rtn; | ||
265 | boolean manual; | ||
266 | fixed_t targheight; | ||
267 | sector_t* sec; | ||
268 | ceiling_t* ceiling; | ||
269 | unsigned value = (unsigned)line->special - GenCeilingBase; | ||
270 | |||
271 | // parse the bit fields in the line's special type | ||
272 | |||
273 | int Crsh = (value & CeilingCrush) >> CeilingCrushShift; | ||
274 | int ChgT = (value & CeilingChange) >> CeilingChangeShift; | ||
275 | int Targ = (value & CeilingTarget) >> CeilingTargetShift; | ||
276 | int Dirn = (value & CeilingDirection) >> CeilingDirectionShift; | ||
277 | int ChgM = (value & CeilingModel) >> CeilingModelShift; | ||
278 | int Sped = (value & CeilingSpeed) >> CeilingSpeedShift; | ||
279 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
280 | |||
281 | rtn = 0; | ||
282 | |||
283 | // check if a manual trigger, if so do just the sector on the backside | ||
284 | manual = false; | ||
285 | if (Trig==PushOnce || Trig==PushMany) | ||
286 | { | ||
287 | if (!(sec = line->backsector)) | ||
288 | return rtn; | ||
289 | secnum = sec-sectors; | ||
290 | manual = true; | ||
291 | goto manual_ceiling; | ||
292 | } | ||
293 | |||
294 | secnum = -1; | ||
295 | // if not manual do all sectors tagged the same as the line | ||
296 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
297 | { | ||
298 | sec = §ors[secnum]; | ||
299 | |||
300 | manual_ceiling: | ||
301 | // Do not start another function if ceiling already moving | ||
302 | if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 | ||
303 | { | ||
304 | if (!manual) | ||
305 | continue; | ||
306 | else | ||
307 | return rtn; | ||
308 | } | ||
309 | |||
310 | // new ceiling thinker | ||
311 | rtn = 1; | ||
312 | ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); | ||
313 | P_AddThinker (&ceiling->thinker); | ||
314 | sec->ceilingdata = ceiling; //jff 2/22/98 | ||
315 | ceiling->thinker.function = T_MoveCeiling; | ||
316 | ceiling->crush = Crsh; | ||
317 | ceiling->direction = Dirn? 1 : -1; | ||
318 | ceiling->sector = sec; | ||
319 | ceiling->texture = sec->ceilingpic; | ||
320 | ceiling->newspecial = sec->special; | ||
321 | //jff 3/14/98 change old field too | ||
322 | ceiling->oldspecial = sec->oldspecial; | ||
323 | ceiling->tag = sec->tag; | ||
324 | ceiling->type = genCeiling; | ||
325 | |||
326 | // set speed of motion | ||
327 | switch (Sped) | ||
328 | { | ||
329 | case SpeedSlow: | ||
330 | ceiling->speed = CEILSPEED; | ||
331 | break; | ||
332 | case SpeedNormal: | ||
333 | ceiling->speed = CEILSPEED*2; | ||
334 | break; | ||
335 | case SpeedFast: | ||
336 | ceiling->speed = CEILSPEED*4; | ||
337 | break; | ||
338 | case SpeedTurbo: | ||
339 | ceiling->speed = CEILSPEED*8; | ||
340 | break; | ||
341 | default: | ||
342 | break; | ||
343 | } | ||
344 | |||
345 | // set destination target height | ||
346 | targheight = sec->ceilingheight; | ||
347 | switch(Targ) | ||
348 | { | ||
349 | case CtoHnC: | ||
350 | targheight = P_FindHighestCeilingSurrounding(sec); | ||
351 | break; | ||
352 | case CtoLnC: | ||
353 | targheight = P_FindLowestCeilingSurrounding(sec); | ||
354 | break; | ||
355 | case CtoNnC: | ||
356 | targheight = Dirn? | ||
357 | P_FindNextHighestCeiling(sec,sec->ceilingheight) : | ||
358 | P_FindNextLowestCeiling(sec,sec->ceilingheight); | ||
359 | break; | ||
360 | case CtoHnF: | ||
361 | targheight = P_FindHighestFloorSurrounding(sec); | ||
362 | break; | ||
363 | case CtoF: | ||
364 | targheight = sec->floorheight; | ||
365 | break; | ||
366 | case CbyST: | ||
367 | targheight = (ceiling->sector->ceilingheight>>FRACBITS) + | ||
368 | ceiling->direction * (P_FindShortestUpperAround(secnum)>>FRACBITS); | ||
369 | if (targheight>32000) //jff 3/13/98 prevent overflow | ||
370 | targheight=32000; // wraparound in ceiling height | ||
371 | if (targheight<-32000) | ||
372 | targheight=-32000; | ||
373 | targheight<<=FRACBITS; | ||
374 | break; | ||
375 | case Cby24: | ||
376 | targheight = ceiling->sector->ceilingheight + | ||
377 | ceiling->direction * 24*FRACUNIT; | ||
378 | break; | ||
379 | case Cby32: | ||
380 | targheight = ceiling->sector->ceilingheight + | ||
381 | ceiling->direction * 32*FRACUNIT; | ||
382 | break; | ||
383 | default: | ||
384 | break; | ||
385 | } | ||
386 | if (Dirn) ceiling->topheight = targheight; | ||
387 | else ceiling->bottomheight = targheight; | ||
388 | |||
389 | // set texture/type change properties | ||
390 | if (ChgT) // if a texture change is indicated | ||
391 | { | ||
392 | if (ChgM) // if a numeric model change | ||
393 | { | ||
394 | sector_t *sec; | ||
395 | |||
396 | //jff 5/23/98 find model with floor at target height if target | ||
397 | //is a floor type | ||
398 | sec = (Targ==CtoHnF || Targ==CtoF)? | ||
399 | P_FindModelFloorSector(targheight,secnum) : | ||
400 | P_FindModelCeilingSector(targheight,secnum); | ||
401 | if (sec) | ||
402 | { | ||
403 | ceiling->texture = sec->ceilingpic; | ||
404 | switch (ChgT) | ||
405 | { | ||
406 | case CChgZero: // type is zeroed | ||
407 | ceiling->newspecial = 0; | ||
408 | //jff 3/14/98 change old field too | ||
409 | ceiling->oldspecial = 0; | ||
410 | ceiling->type = genCeilingChg0; | ||
411 | break; | ||
412 | case CChgTyp: // type is copied | ||
413 | ceiling->newspecial = sec->special; | ||
414 | //jff 3/14/98 change old field too | ||
415 | ceiling->oldspecial = sec->oldspecial; | ||
416 | ceiling->type = genCeilingChgT; | ||
417 | break; | ||
418 | case CChgTxt: // type is left alone | ||
419 | ceiling->type = genCeilingChg; | ||
420 | break; | ||
421 | default: | ||
422 | break; | ||
423 | } | ||
424 | } | ||
425 | } | ||
426 | else // else if a trigger model change | ||
427 | { | ||
428 | ceiling->texture = line->frontsector->ceilingpic; | ||
429 | switch (ChgT) | ||
430 | { | ||
431 | case CChgZero: // type is zeroed | ||
432 | ceiling->newspecial = 0; | ||
433 | //jff 3/14/98 change old field too | ||
434 | ceiling->oldspecial = 0; | ||
435 | ceiling->type = genCeilingChg0; | ||
436 | break; | ||
437 | case CChgTyp: // type is copied | ||
438 | ceiling->newspecial = line->frontsector->special; | ||
439 | //jff 3/14/98 change old field too | ||
440 | ceiling->oldspecial = line->frontsector->oldspecial; | ||
441 | ceiling->type = genCeilingChgT; | ||
442 | break; | ||
443 | case CChgTxt: // type is left alone | ||
444 | ceiling->type = genCeilingChg; | ||
445 | break; | ||
446 | default: | ||
447 | break; | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | P_AddActiveCeiling(ceiling); // add this ceiling to the active list | ||
452 | if (manual) return rtn; | ||
453 | } | ||
454 | return rtn; | ||
455 | } | ||
456 | |||
457 | // | ||
458 | // EV_DoGenLift() | ||
459 | // | ||
460 | // Handle generalized lift types | ||
461 | // | ||
462 | // Passed the linedef activating the lift | ||
463 | // Returns true if a thinker is created | ||
464 | // | ||
465 | int EV_DoGenLift | ||
466 | ( line_t* line ) | ||
467 | { | ||
468 | plat_t* plat; | ||
469 | int secnum; | ||
470 | int rtn; | ||
471 | boolean manual; | ||
472 | sector_t* sec; | ||
473 | unsigned value = (unsigned)line->special - GenLiftBase; | ||
474 | |||
475 | // parse the bit fields in the line's special type | ||
476 | |||
477 | int Targ = (value & LiftTarget) >> LiftTargetShift; | ||
478 | int Dely = (value & LiftDelay) >> LiftDelayShift; | ||
479 | int Sped = (value & LiftSpeed) >> LiftSpeedShift; | ||
480 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
481 | |||
482 | secnum = -1; | ||
483 | rtn = 0; | ||
484 | |||
485 | // Activate all <type> plats that are in_stasis | ||
486 | |||
487 | if (Targ==LnF2HnF) | ||
488 | P_ActivateInStasis(line->tag); | ||
489 | |||
490 | // check if a manual trigger, if so do just the sector on the backside | ||
491 | manual = false; | ||
492 | if (Trig==PushOnce || Trig==PushMany) | ||
493 | { | ||
494 | if (!(sec = line->backsector)) | ||
495 | return rtn; | ||
496 | secnum = sec-sectors; | ||
497 | manual = true; | ||
498 | goto manual_lift; | ||
499 | } | ||
500 | |||
501 | // if not manual do all sectors tagged the same as the line | ||
502 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
503 | { | ||
504 | sec = §ors[secnum]; | ||
505 | |||
506 | manual_lift: | ||
507 | // Do not start another function if floor already moving | ||
508 | if (P_SectorActive(floor_special,sec)) | ||
509 | { | ||
510 | if (!manual) | ||
511 | continue; | ||
512 | else | ||
513 | return rtn; | ||
514 | } | ||
515 | |||
516 | // Setup the plat thinker | ||
517 | rtn = 1; | ||
518 | plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); | ||
519 | P_AddThinker(&plat->thinker); | ||
520 | |||
521 | plat->sector = sec; | ||
522 | plat->sector->floordata = plat; | ||
523 | plat->thinker.function = T_PlatRaise; | ||
524 | plat->crush = false; | ||
525 | plat->tag = line->tag; | ||
526 | |||
527 | plat->type = genLift; | ||
528 | plat->high = sec->floorheight; | ||
529 | plat->status = down; | ||
530 | |||
531 | // setup the target destination height | ||
532 | switch(Targ) | ||
533 | { | ||
534 | case F2LnF: | ||
535 | plat->low = P_FindLowestFloorSurrounding(sec); | ||
536 | if (plat->low > sec->floorheight) | ||
537 | plat->low = sec->floorheight; | ||
538 | break; | ||
539 | case F2NnF: | ||
540 | plat->low = P_FindNextLowestFloor(sec,sec->floorheight); | ||
541 | break; | ||
542 | case F2LnC: | ||
543 | plat->low = P_FindLowestCeilingSurrounding(sec); | ||
544 | if (plat->low > sec->floorheight) | ||
545 | plat->low = sec->floorheight; | ||
546 | break; | ||
547 | case LnF2HnF: | ||
548 | plat->type = genPerpetual; | ||
549 | plat->low = P_FindLowestFloorSurrounding(sec); | ||
550 | if (plat->low > sec->floorheight) | ||
551 | plat->low = sec->floorheight; | ||
552 | plat->high = P_FindHighestFloorSurrounding(sec); | ||
553 | if (plat->high < sec->floorheight) | ||
554 | plat->high = sec->floorheight; | ||
555 | plat->status = P_Random(pr_genlift)&1; | ||
556 | break; | ||
557 | default: | ||
558 | break; | ||
559 | } | ||
560 | |||
561 | // setup the speed of motion | ||
562 | switch(Sped) | ||
563 | { | ||
564 | case SpeedSlow: | ||
565 | plat->speed = PLATSPEED * 2; | ||
566 | break; | ||
567 | case SpeedNormal: | ||
568 | plat->speed = PLATSPEED * 4; | ||
569 | break; | ||
570 | case SpeedFast: | ||
571 | plat->speed = PLATSPEED * 8; | ||
572 | break; | ||
573 | case SpeedTurbo: | ||
574 | plat->speed = PLATSPEED * 16; | ||
575 | break; | ||
576 | default: | ||
577 | break; | ||
578 | } | ||
579 | |||
580 | // setup the delay time before the floor returns | ||
581 | switch(Dely) | ||
582 | { | ||
583 | case 0: | ||
584 | plat->wait = 1*35; | ||
585 | break; | ||
586 | case 1: | ||
587 | plat->wait = PLATWAIT*35; | ||
588 | break; | ||
589 | case 2: | ||
590 | plat->wait = 5*35; | ||
591 | break; | ||
592 | case 3: | ||
593 | plat->wait = 10*35; | ||
594 | break; | ||
595 | } | ||
596 | |||
597 | S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); | ||
598 | P_AddActivePlat(plat); // add this plat to the list of active plats | ||
599 | |||
600 | if (manual) | ||
601 | return rtn; | ||
602 | } | ||
603 | return rtn; | ||
604 | } | ||
605 | |||
606 | // | ||
607 | // EV_DoGenStairs() | ||
608 | // | ||
609 | // Handle generalized stair building | ||
610 | // | ||
611 | // Passed the linedef activating the stairs | ||
612 | // Returns true if a thinker is created | ||
613 | // | ||
614 | int EV_DoGenStairs | ||
615 | ( line_t* line ) | ||
616 | { | ||
617 | int secnum; | ||
618 | int osecnum; //jff 3/4/98 preserve loop index | ||
619 | int height; | ||
620 | int i; | ||
621 | int newsecnum; | ||
622 | int texture; | ||
623 | int ok; | ||
624 | int rtn; | ||
625 | boolean manual; | ||
626 | |||
627 | sector_t* sec; | ||
628 | sector_t* tsec; | ||
629 | |||
630 | floormove_t* floor; | ||
631 | |||
632 | fixed_t stairsize; | ||
633 | fixed_t speed; | ||
634 | |||
635 | unsigned value = (unsigned)line->special - GenStairsBase; | ||
636 | |||
637 | // parse the bit fields in the line's special type | ||
638 | |||
639 | int Igno = (value & StairIgnore) >> StairIgnoreShift; | ||
640 | int Dirn = (value & StairDirection) >> StairDirectionShift; | ||
641 | int Step = (value & StairStep) >> StairStepShift; | ||
642 | int Sped = (value & StairSpeed) >> StairSpeedShift; | ||
643 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
644 | |||
645 | rtn = 0; | ||
646 | |||
647 | // check if a manual trigger, if so do just the sector on the backside | ||
648 | manual = false; | ||
649 | if (Trig==PushOnce || Trig==PushMany) | ||
650 | { | ||
651 | if (!(sec = line->backsector)) | ||
652 | return rtn; | ||
653 | secnum = sec-sectors; | ||
654 | manual = true; | ||
655 | goto manual_stair; | ||
656 | } | ||
657 | |||
658 | secnum = -1; | ||
659 | // if not manual do all sectors tagged the same as the line | ||
660 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
661 | { | ||
662 | sec = §ors[secnum]; | ||
663 | |||
664 | manual_stair: | ||
665 | //Do not start another function if floor already moving | ||
666 | //jff 2/26/98 add special lockout condition to wait for entire | ||
667 | //staircase to build before retriggering | ||
668 | if (P_SectorActive(floor_special,sec) || sec->stairlock) | ||
669 | { | ||
670 | if (!manual) | ||
671 | continue; | ||
672 | else | ||
673 | return rtn; | ||
674 | } | ||
675 | |||
676 | // new floor thinker | ||
677 | rtn = 1; | ||
678 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
679 | P_AddThinker (&floor->thinker); | ||
680 | sec->floordata = floor; | ||
681 | floor->thinker.function = T_MoveFloor; | ||
682 | floor->direction = Dirn? 1 : -1; | ||
683 | floor->sector = sec; | ||
684 | |||
685 | // setup speed of stair building | ||
686 | switch(Sped) | ||
687 | { | ||
688 | default: | ||
689 | case SpeedSlow: | ||
690 | floor->speed = FLOORSPEED/4; | ||
691 | break; | ||
692 | case SpeedNormal: | ||
693 | floor->speed = FLOORSPEED/2; | ||
694 | break; | ||
695 | case SpeedFast: | ||
696 | floor->speed = FLOORSPEED*2; | ||
697 | break; | ||
698 | case SpeedTurbo: | ||
699 | floor->speed = FLOORSPEED*4; | ||
700 | break; | ||
701 | } | ||
702 | |||
703 | // setup stepsize for stairs | ||
704 | switch(Step) | ||
705 | { | ||
706 | default: | ||
707 | case 0: | ||
708 | stairsize = 4*FRACUNIT; | ||
709 | break; | ||
710 | case 1: | ||
711 | stairsize = 8*FRACUNIT; | ||
712 | break; | ||
713 | case 2: | ||
714 | stairsize = 16*FRACUNIT; | ||
715 | break; | ||
716 | case 3: | ||
717 | stairsize = 24*FRACUNIT; | ||
718 | break; | ||
719 | } | ||
720 | |||
721 | speed = floor->speed; | ||
722 | height = sec->floorheight + floor->direction * stairsize; | ||
723 | floor->floordestheight = height; | ||
724 | texture = sec->floorpic; | ||
725 | floor->crush = false; | ||
726 | floor->type = genBuildStair; // jff 3/31/98 do not leave uninited | ||
727 | |||
728 | sec->stairlock = -2; // jff 2/26/98 set up lock on current sector | ||
729 | sec->nextsec = -1; | ||
730 | sec->prevsec = -1; | ||
731 | |||
732 | osecnum = secnum; //jff 3/4/98 preserve loop index | ||
733 | // Find next sector to raise | ||
734 | // 1. Find 2-sided line with same sector side[0] | ||
735 | // 2. Other side is the next sector to raise | ||
736 | do | ||
737 | { | ||
738 | ok = 0; | ||
739 | for (i = 0;i < sec->linecount;i++) | ||
740 | { | ||
741 | if ( !((sec->lines[i])->backsector) ) | ||
742 | continue; | ||
743 | |||
744 | tsec = (sec->lines[i])->frontsector; | ||
745 | newsecnum = tsec-sectors; | ||
746 | |||
747 | if (secnum != newsecnum) | ||
748 | continue; | ||
749 | |||
750 | tsec = (sec->lines[i])->backsector; | ||
751 | newsecnum = tsec - sectors; | ||
752 | |||
753 | if (!Igno && tsec->floorpic != texture) | ||
754 | continue; | ||
755 | |||
756 | /* jff 6/19/98 prevent double stepsize */ | ||
757 | if (compatibility_level < boom_202_compatibility) | ||
758 | height += floor->direction * stairsize; | ||
759 | |||
760 | //jff 2/26/98 special lockout condition for retriggering | ||
761 | if (P_SectorActive(floor_special,tsec) || tsec->stairlock) | ||
762 | continue; | ||
763 | |||
764 | /* jff 6/19/98 increase height AFTER continue */ | ||
765 | if (compatibility_level >= boom_202_compatibility) | ||
766 | height += floor->direction * stairsize; | ||
767 | |||
768 | // jff 2/26/98 | ||
769 | // link the stair chain in both directions | ||
770 | // lock the stair sector until building complete | ||
771 | sec->nextsec = newsecnum; // link step to next | ||
772 | tsec->prevsec = secnum; // link next back | ||
773 | tsec->nextsec = -1; // set next forward link as end | ||
774 | tsec->stairlock = -2; // lock the step | ||
775 | |||
776 | sec = tsec; | ||
777 | secnum = newsecnum; | ||
778 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
779 | |||
780 | P_AddThinker (&floor->thinker); | ||
781 | |||
782 | sec->floordata = floor; | ||
783 | floor->thinker.function = T_MoveFloor; | ||
784 | floor->direction = Dirn? 1 : -1; | ||
785 | floor->sector = sec; | ||
786 | floor->speed = speed; | ||
787 | floor->floordestheight = height; | ||
788 | floor->crush = false; | ||
789 | floor->type = genBuildStair; // jff 3/31/98 do not leave uninited | ||
790 | |||
791 | ok = 1; | ||
792 | break; | ||
793 | } | ||
794 | } while(ok); | ||
795 | if (manual) | ||
796 | return rtn; | ||
797 | secnum = osecnum; //jff 3/4/98 restore old loop index | ||
798 | } | ||
799 | // retriggerable generalized stairs build up or down alternately | ||
800 | if (rtn) | ||
801 | line->special ^= StairDirection; // alternate dir on succ activations | ||
802 | return rtn; | ||
803 | } | ||
804 | |||
805 | // | ||
806 | // EV_DoGenCrusher() | ||
807 | // | ||
808 | // Handle generalized crusher types | ||
809 | // | ||
810 | // Passed the linedef activating the crusher | ||
811 | // Returns true if a thinker created | ||
812 | // | ||
813 | int EV_DoGenCrusher | ||
814 | ( line_t* line ) | ||
815 | { | ||
816 | int secnum; | ||
817 | int rtn; | ||
818 | boolean manual; | ||
819 | sector_t* sec; | ||
820 | ceiling_t* ceiling; | ||
821 | unsigned value = (unsigned)line->special - GenCrusherBase; | ||
822 | |||
823 | // parse the bit fields in the line's special type | ||
824 | |||
825 | int Slnt = (value & CrusherSilent) >> CrusherSilentShift; | ||
826 | int Sped = (value & CrusherSpeed) >> CrusherSpeedShift; | ||
827 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
828 | |||
829 | //jff 2/22/98 Reactivate in-stasis ceilings...for certain types. | ||
830 | //jff 4/5/98 return if activated | ||
831 | rtn = P_ActivateInStasisCeiling(line); | ||
832 | |||
833 | // check if a manual trigger, if so do just the sector on the backside | ||
834 | manual = false; | ||
835 | if (Trig==PushOnce || Trig==PushMany) | ||
836 | { | ||
837 | if (!(sec = line->backsector)) | ||
838 | return rtn; | ||
839 | secnum = sec-sectors; | ||
840 | manual = true; | ||
841 | goto manual_crusher; | ||
842 | } | ||
843 | |||
844 | secnum = -1; | ||
845 | // if not manual do all sectors tagged the same as the line | ||
846 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
847 | { | ||
848 | sec = §ors[secnum]; | ||
849 | |||
850 | manual_crusher: | ||
851 | // Do not start another function if ceiling already moving | ||
852 | if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 | ||
853 | { | ||
854 | if (!manual) | ||
855 | continue; | ||
856 | else | ||
857 | return rtn; | ||
858 | } | ||
859 | |||
860 | // new ceiling thinker | ||
861 | rtn = 1; | ||
862 | ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); | ||
863 | P_AddThinker (&ceiling->thinker); | ||
864 | sec->ceilingdata = ceiling; //jff 2/22/98 | ||
865 | ceiling->thinker.function = T_MoveCeiling; | ||
866 | ceiling->crush = true; | ||
867 | ceiling->direction = -1; | ||
868 | ceiling->sector = sec; | ||
869 | ceiling->texture = sec->ceilingpic; | ||
870 | ceiling->newspecial = sec->special; | ||
871 | ceiling->tag = sec->tag; | ||
872 | ceiling->type = Slnt? genSilentCrusher : genCrusher; | ||
873 | ceiling->topheight = sec->ceilingheight; | ||
874 | ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); | ||
875 | |||
876 | // setup ceiling motion speed | ||
877 | switch (Sped) | ||
878 | { | ||
879 | case SpeedSlow: | ||
880 | ceiling->speed = CEILSPEED; | ||
881 | break; | ||
882 | case SpeedNormal: | ||
883 | ceiling->speed = CEILSPEED*2; | ||
884 | break; | ||
885 | case SpeedFast: | ||
886 | ceiling->speed = CEILSPEED*4; | ||
887 | break; | ||
888 | case SpeedTurbo: | ||
889 | ceiling->speed = CEILSPEED*8; | ||
890 | break; | ||
891 | default: | ||
892 | break; | ||
893 | } | ||
894 | ceiling->oldspeed=ceiling->speed; | ||
895 | |||
896 | P_AddActiveCeiling(ceiling); // add to list of active ceilings | ||
897 | if (manual) return rtn; | ||
898 | } | ||
899 | return rtn; | ||
900 | } | ||
901 | |||
902 | // | ||
903 | // EV_DoGenLockedDoor() | ||
904 | // | ||
905 | // Handle generalized locked door types | ||
906 | // | ||
907 | // Passed the linedef activating the generalized locked door | ||
908 | // Returns true if a thinker created | ||
909 | // | ||
910 | int EV_DoGenLockedDoor | ||
911 | ( line_t* line ) | ||
912 | { | ||
913 | int secnum,rtn; | ||
914 | sector_t* sec; | ||
915 | vldoor_t* door; | ||
916 | boolean manual; | ||
917 | unsigned value = (unsigned)line->special - GenLockedBase; | ||
918 | |||
919 | // parse the bit fields in the line's special type | ||
920 | |||
921 | int Kind = (value & LockedKind) >> LockedKindShift; | ||
922 | int Sped = (value & LockedSpeed) >> LockedSpeedShift; | ||
923 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
924 | |||
925 | rtn = 0; | ||
926 | |||
927 | // check if a manual trigger, if so do just the sector on the backside | ||
928 | manual = false; | ||
929 | if (Trig==PushOnce || Trig==PushMany) | ||
930 | { | ||
931 | if (!(sec = line->backsector)) | ||
932 | return rtn; | ||
933 | secnum = sec-sectors; | ||
934 | manual = true; | ||
935 | goto manual_locked; | ||
936 | } | ||
937 | |||
938 | secnum = -1; | ||
939 | rtn = 0; | ||
940 | |||
941 | // if not manual do all sectors tagged the same as the line | ||
942 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
943 | { | ||
944 | sec = §ors[secnum]; | ||
945 | manual_locked: | ||
946 | // Do not start another function if ceiling already moving | ||
947 | if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 | ||
948 | { | ||
949 | if (!manual) | ||
950 | continue; | ||
951 | else | ||
952 | return rtn; | ||
953 | } | ||
954 | |||
955 | // new door thinker | ||
956 | rtn = 1; | ||
957 | door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); | ||
958 | P_AddThinker (&door->thinker); | ||
959 | sec->ceilingdata = door; //jff 2/22/98 | ||
960 | |||
961 | door->thinker.function = T_VerticalDoor; | ||
962 | door->sector = sec; | ||
963 | door->topwait = VDOORWAIT; | ||
964 | door->line = line; | ||
965 | door->topheight = P_FindLowestCeilingSurrounding(sec); | ||
966 | door->topheight -= 4*FRACUNIT; | ||
967 | door->direction = 1; | ||
968 | |||
969 | /* killough 10/98: implement gradual lighting */ | ||
970 | door->lighttag = !comp[comp_doorlight] && | ||
971 | (line->special&6) == 6 && | ||
972 | line->special > GenLockedBase ? line->tag : 0; | ||
973 | |||
974 | // setup speed of door motion | ||
975 | switch(Sped) | ||
976 | { | ||
977 | default: | ||
978 | case SpeedSlow: | ||
979 | door->type = Kind? genOpen : genRaise; | ||
980 | door->speed = VDOORSPEED; | ||
981 | break; | ||
982 | case SpeedNormal: | ||
983 | door->type = Kind? genOpen : genRaise; | ||
984 | door->speed = VDOORSPEED*2; | ||
985 | break; | ||
986 | case SpeedFast: | ||
987 | door->type = Kind? genBlazeOpen : genBlazeRaise; | ||
988 | door->speed = VDOORSPEED*4; | ||
989 | break; | ||
990 | case SpeedTurbo: | ||
991 | door->type = Kind? genBlazeOpen : genBlazeRaise; | ||
992 | door->speed = VDOORSPEED*8; | ||
993 | |||
994 | break; | ||
995 | } | ||
996 | |||
997 | // killough 4/15/98: fix generalized door opening sounds | ||
998 | // (previously they always had the blazing door close sound) | ||
999 | |||
1000 | S_StartSound((mobj_t *)&door->sector->soundorg, // killough 4/15/98 | ||
1001 | door->speed >= VDOORSPEED*4 ? sfx_bdopn : sfx_doropn); | ||
1002 | |||
1003 | if (manual) | ||
1004 | return rtn; | ||
1005 | } | ||
1006 | return rtn; | ||
1007 | } | ||
1008 | |||
1009 | // | ||
1010 | // EV_DoGenDoor() | ||
1011 | // | ||
1012 | // Handle generalized door types | ||
1013 | // | ||
1014 | // Passed the linedef activating the generalized door | ||
1015 | // Returns true if a thinker created | ||
1016 | // | ||
1017 | int EV_DoGenDoor | ||
1018 | ( line_t* line ) | ||
1019 | { | ||
1020 | int secnum,rtn; | ||
1021 | sector_t* sec; | ||
1022 | boolean manual; | ||
1023 | vldoor_t* door; | ||
1024 | unsigned value = (unsigned)line->special - GenDoorBase; | ||
1025 | |||
1026 | // parse the bit fields in the line's special type | ||
1027 | |||
1028 | int Dely = (value & DoorDelay) >> DoorDelayShift; | ||
1029 | int Kind = (value & DoorKind) >> DoorKindShift; | ||
1030 | int Sped = (value & DoorSpeed) >> DoorSpeedShift; | ||
1031 | int Trig = (value & TriggerType) >> TriggerTypeShift; | ||
1032 | |||
1033 | rtn = 0; | ||
1034 | |||
1035 | // check if a manual trigger, if so do just the sector on the backside | ||
1036 | manual = false; | ||
1037 | if (Trig==PushOnce || Trig==PushMany) | ||
1038 | { | ||
1039 | if (!(sec = line->backsector)) | ||
1040 | return rtn; | ||
1041 | secnum = sec-sectors; | ||
1042 | manual = true; | ||
1043 | goto manual_door; | ||
1044 | } | ||
1045 | |||
1046 | |||
1047 | secnum = -1; | ||
1048 | rtn = 0; | ||
1049 | |||
1050 | // if not manual do all sectors tagged the same as the line | ||
1051 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
1052 | { | ||
1053 | sec = §ors[secnum]; | ||
1054 | manual_door: | ||
1055 | // Do not start another function if ceiling already moving | ||
1056 | if (P_SectorActive(ceiling_special,sec)) //jff 2/22/98 | ||
1057 | { | ||
1058 | if (!manual) | ||
1059 | continue; | ||
1060 | else | ||
1061 | return rtn; | ||
1062 | } | ||
1063 | |||
1064 | // new door thinker | ||
1065 | rtn = 1; | ||
1066 | door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); | ||
1067 | P_AddThinker (&door->thinker); | ||
1068 | sec->ceilingdata = door; //jff 2/22/98 | ||
1069 | |||
1070 | door->thinker.function = T_VerticalDoor; | ||
1071 | door->sector = sec; | ||
1072 | // setup delay for door remaining open/closed | ||
1073 | switch(Dely) | ||
1074 | { | ||
1075 | default: | ||
1076 | case 0: | ||
1077 | door->topwait = 35; | ||
1078 | break; | ||
1079 | case 1: | ||
1080 | door->topwait = VDOORWAIT; | ||
1081 | break; | ||
1082 | case 2: | ||
1083 | door->topwait = 2*VDOORWAIT; | ||
1084 | break; | ||
1085 | case 3: | ||
1086 | door->topwait = 7*VDOORWAIT; | ||
1087 | break; | ||
1088 | } | ||
1089 | |||
1090 | // setup speed of door motion | ||
1091 | switch(Sped) | ||
1092 | { | ||
1093 | default: | ||
1094 | case SpeedSlow: | ||
1095 | door->speed = VDOORSPEED; | ||
1096 | break; | ||
1097 | case SpeedNormal: | ||
1098 | door->speed = VDOORSPEED*2; | ||
1099 | break; | ||
1100 | case SpeedFast: | ||
1101 | door->speed = VDOORSPEED*4; | ||
1102 | break; | ||
1103 | case SpeedTurbo: | ||
1104 | door->speed = VDOORSPEED*8; | ||
1105 | break; | ||
1106 | } | ||
1107 | door->line = line; // jff 1/31/98 remember line that triggered us | ||
1108 | |||
1109 | /* killough 10/98: implement gradual lighting */ | ||
1110 | door->lighttag = !comp[comp_doorlight] && | ||
1111 | (line->special&6) == 6 && | ||
1112 | line->special > GenLockedBase ? line->tag : 0; | ||
1113 | |||
1114 | // set kind of door, whether it opens then close, opens, closes etc. | ||
1115 | // assign target heights accordingly | ||
1116 | switch(Kind) | ||
1117 | { | ||
1118 | case OdCDoor: | ||
1119 | door->direction = 1; | ||
1120 | door->topheight = P_FindLowestCeilingSurrounding(sec); | ||
1121 | door->topheight -= 4*FRACUNIT; | ||
1122 | if (door->topheight != sec->ceilingheight) | ||
1123 | S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn); | ||
1124 | door->type = Sped>=SpeedFast? genBlazeRaise : genRaise; | ||
1125 | break; | ||
1126 | case ODoor: | ||
1127 | door->direction = 1; | ||
1128 | door->topheight = P_FindLowestCeilingSurrounding(sec); | ||
1129 | door->topheight -= 4*FRACUNIT; | ||
1130 | if (door->topheight != sec->ceilingheight) | ||
1131 | S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast || comp[comp_sound] ? sfx_bdopn : sfx_doropn); | ||
1132 | door->type = Sped>=SpeedFast? genBlazeOpen : genOpen; | ||
1133 | break; | ||
1134 | case CdODoor: | ||
1135 | door->topheight = sec->ceilingheight; | ||
1136 | door->direction = -1; | ||
1137 | S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls); | ||
1138 | door->type = Sped>=SpeedFast? genBlazeCdO : genCdO; | ||
1139 | break; | ||
1140 | case CDoor: | ||
1141 | door->topheight = P_FindLowestCeilingSurrounding(sec); | ||
1142 | door->topheight -= 4*FRACUNIT; | ||
1143 | door->direction = -1; | ||
1144 | S_StartSound((mobj_t *)&door->sector->soundorg,Sped>=SpeedFast && !comp[comp_sound] ? sfx_bdcls : sfx_dorcls); | ||
1145 | door->type = Sped>=SpeedFast? genBlazeClose : genClose; | ||
1146 | break; | ||
1147 | default: | ||
1148 | break; | ||
1149 | } | ||
1150 | if (manual) | ||
1151 | return rtn; | ||
1152 | } | ||
1153 | return rtn; | ||
1154 | } | ||