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