diff options
author | Dave Chapman <dave@dchapman.com> | 2006-03-28 15:44:01 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-03-28 15:44:01 +0000 |
commit | 47f4a458d636a889e955e68f896708f1276febc0 (patch) | |
tree | 99f770c02ef606f0abbdcd332ac39e69830d8007 /apps/plugins/doom/p_floor.c | |
parent | fff7d6157d56f233cad5c2003475e47a5ff809a7 (diff) | |
download | rockbox-47f4a458d636a889e955e68f896708f1276febc0.tar.gz rockbox-47f4a458d636a889e955e68f896708f1276febc0.zip |
Patch #2969 - Doom! Currently only working on the H300.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9312 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/doom/p_floor.c')
-rw-r--r-- | apps/plugins/doom/p_floor.c | 1035 |
1 files changed, 1035 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_floor.c b/apps/plugins/doom/p_floor.c new file mode 100644 index 0000000000..bbcf2bc358 --- /dev/null +++ b/apps/plugins/doom/p_floor.c | |||
@@ -0,0 +1,1035 @@ | |||
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 | * General plane mover and floor mover action routines | ||
29 | * Floor motion, pure changer types, raising stairs. donuts, elevators | ||
30 | * | ||
31 | *-----------------------------------------------------------------------------*/ | ||
32 | |||
33 | #include "doomstat.h" | ||
34 | #include "r_main.h" | ||
35 | #include "p_map.h" | ||
36 | #include "p_spec.h" | ||
37 | #include "p_tick.h" | ||
38 | #include "s_sound.h" | ||
39 | #include "sounds.h" | ||
40 | |||
41 | #include "rockmacros.h" | ||
42 | |||
43 | /////////////////////////////////////////////////////////////////////// | ||
44 | // | ||
45 | // Plane (floor or ceiling), Floor motion and Elevator action routines | ||
46 | // | ||
47 | /////////////////////////////////////////////////////////////////////// | ||
48 | |||
49 | // | ||
50 | // T_MovePlane() | ||
51 | // | ||
52 | // Move a plane (floor or ceiling) and check for crushing. Called | ||
53 | // every tick by all actions that move floors or ceilings. | ||
54 | // | ||
55 | // Passed the sector to move a plane in, the speed to move it at, | ||
56 | // the dest height it is to achieve, whether it crushes obstacles, | ||
57 | // whether it moves a floor or ceiling, and the direction up or down | ||
58 | // to move. | ||
59 | // | ||
60 | // Returns a result_e: | ||
61 | // ok - plane moved normally, has not achieved destination yet | ||
62 | // pastdest - plane moved normally and is now at destination height | ||
63 | // crushed - plane encountered an obstacle, is holding until removed | ||
64 | // | ||
65 | result_e T_MovePlane | ||
66 | ( sector_t* sector, | ||
67 | fixed_t speed, | ||
68 | fixed_t dest, | ||
69 | boolean crush, | ||
70 | int floorOrCeiling, | ||
71 | int direction ) | ||
72 | { | ||
73 | boolean flag; | ||
74 | fixed_t lastpos; | ||
75 | fixed_t destheight; //jff 02/04/98 used to keep floors/ceilings | ||
76 | // from moving thru each other | ||
77 | |||
78 | switch(floorOrCeiling) | ||
79 | { | ||
80 | case 0: | ||
81 | // Moving a floor | ||
82 | switch(direction) | ||
83 | { | ||
84 | case -1: | ||
85 | // Moving a floor down | ||
86 | if (sector->floorheight - speed < dest) | ||
87 | { | ||
88 | lastpos = sector->floorheight; | ||
89 | sector->floorheight = dest; | ||
90 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
91 | if (flag == true) | ||
92 | { | ||
93 | sector->floorheight =lastpos; | ||
94 | P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
95 | } | ||
96 | return pastdest; | ||
97 | } | ||
98 | else | ||
99 | { | ||
100 | lastpos = sector->floorheight; | ||
101 | sector->floorheight -= speed; | ||
102 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
103 | /* cph - make more compatible with original Doom, by | ||
104 | * reintroducing this code. This means floors can't lower | ||
105 | * if objects are stuck in the ceiling */ | ||
106 | if ((flag == true) && comp[comp_floors]) { | ||
107 | sector->floorheight = lastpos; | ||
108 | P_ChangeSector(sector,crush); | ||
109 | return crushed; | ||
110 | } | ||
111 | } | ||
112 | break; | ||
113 | |||
114 | case 1: | ||
115 | // Moving a floor up | ||
116 | // jff 02/04/98 keep floor from moving thru ceilings | ||
117 | // jff 2/22/98 weaken check to demo_compatibility | ||
118 | destheight = (comp[comp_floors] || dest<sector->ceilingheight)? | ||
119 | dest : sector->ceilingheight; | ||
120 | if (sector->floorheight + speed > destheight) | ||
121 | { | ||
122 | lastpos = sector->floorheight; | ||
123 | sector->floorheight = destheight; | ||
124 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
125 | if (flag == true) | ||
126 | { | ||
127 | sector->floorheight = lastpos; | ||
128 | P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
129 | } | ||
130 | return pastdest; | ||
131 | } | ||
132 | else | ||
133 | { | ||
134 | // crushing is possible | ||
135 | lastpos = sector->floorheight; | ||
136 | sector->floorheight += speed; | ||
137 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
138 | if (flag == true) | ||
139 | { | ||
140 | /* jff 1/25/98 fix floor crusher */ | ||
141 | if (comp[comp_floors]) { | ||
142 | if (crush == true) | ||
143 | return crushed; | ||
144 | } | ||
145 | sector->floorheight = lastpos; | ||
146 | P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
147 | return crushed; | ||
148 | } | ||
149 | } | ||
150 | break; | ||
151 | } | ||
152 | break; | ||
153 | |||
154 | case 1: | ||
155 | // moving a ceiling | ||
156 | switch(direction) | ||
157 | { | ||
158 | case -1: | ||
159 | // moving a ceiling down | ||
160 | // jff 02/04/98 keep ceiling from moving thru floors | ||
161 | // jff 2/22/98 weaken check to demo_compatibility | ||
162 | destheight = (comp[comp_floors] || dest>sector->floorheight)? | ||
163 | dest : sector->floorheight; | ||
164 | if (sector->ceilingheight - speed < destheight) | ||
165 | { | ||
166 | lastpos = sector->ceilingheight; | ||
167 | sector->ceilingheight = destheight; | ||
168 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
169 | |||
170 | if (flag == true) | ||
171 | { | ||
172 | sector->ceilingheight = lastpos; | ||
173 | P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
174 | } | ||
175 | return pastdest; | ||
176 | } | ||
177 | else | ||
178 | { | ||
179 | // crushing is possible | ||
180 | lastpos = sector->ceilingheight; | ||
181 | sector->ceilingheight -= speed; | ||
182 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
183 | |||
184 | if (flag == true) | ||
185 | { | ||
186 | if (crush == true) | ||
187 | return crushed; | ||
188 | sector->ceilingheight = lastpos; | ||
189 | P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
190 | return crushed; | ||
191 | } | ||
192 | } | ||
193 | break; | ||
194 | |||
195 | case 1: | ||
196 | // moving a ceiling up | ||
197 | if (sector->ceilingheight + speed > dest) | ||
198 | { | ||
199 | lastpos = sector->ceilingheight; | ||
200 | sector->ceilingheight = dest; | ||
201 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
202 | if (flag == true) | ||
203 | { | ||
204 | sector->ceilingheight = lastpos; | ||
205 | P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
206 | } | ||
207 | return pastdest; | ||
208 | } | ||
209 | else | ||
210 | { | ||
211 | lastpos = sector->ceilingheight; | ||
212 | sector->ceilingheight += speed; | ||
213 | flag = P_CheckSector(sector,crush); //jff 3/19/98 use faster chk | ||
214 | } | ||
215 | break; | ||
216 | } | ||
217 | break; | ||
218 | } | ||
219 | return ok; | ||
220 | } | ||
221 | |||
222 | // | ||
223 | // T_MoveFloor() | ||
224 | // | ||
225 | // Move a floor to it's destination (up or down). | ||
226 | // Called once per tick for each moving floor. | ||
227 | // | ||
228 | // Passed a floormove_t structure that contains all pertinent info about the | ||
229 | // move. See P_SPEC.H for fields. | ||
230 | // No return. | ||
231 | // | ||
232 | // jff 02/08/98 all cases with labels beginning with gen added to support | ||
233 | // generalized line type behaviors. | ||
234 | void T_MoveFloor(floormove_t* floor) | ||
235 | { | ||
236 | result_e res; | ||
237 | |||
238 | res = T_MovePlane // move the floor | ||
239 | ( | ||
240 | floor->sector, | ||
241 | floor->speed, | ||
242 | floor->floordestheight, | ||
243 | floor->crush, | ||
244 | 0, | ||
245 | floor->direction | ||
246 | ); | ||
247 | |||
248 | if (!(leveltime&7)) // make the floormove sound | ||
249 | S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_stnmov); | ||
250 | |||
251 | if (res == pastdest) // if destination height is reached | ||
252 | { | ||
253 | if (floor->direction == 1) // going up | ||
254 | { | ||
255 | switch(floor->type) // handle texture/type changes | ||
256 | { | ||
257 | case donutRaise: | ||
258 | floor->sector->special = floor->newspecial; | ||
259 | floor->sector->floorpic = floor->texture; | ||
260 | break; | ||
261 | case genFloorChgT: | ||
262 | case genFloorChg0: | ||
263 | floor->sector->special = floor->newspecial; | ||
264 | //jff add to fix bug in special transfers from changes | ||
265 | floor->sector->oldspecial = floor->oldspecial; | ||
266 | //fall thru | ||
267 | case genFloorChg: | ||
268 | floor->sector->floorpic = floor->texture; | ||
269 | break; | ||
270 | default: | ||
271 | break; | ||
272 | } | ||
273 | } | ||
274 | else if (floor->direction == -1) // going down | ||
275 | { | ||
276 | switch(floor->type) // handle texture/type changes | ||
277 | { | ||
278 | case lowerAndChange: | ||
279 | floor->sector->special = floor->newspecial; | ||
280 | //jff add to fix bug in special transfers from changes | ||
281 | floor->sector->oldspecial = floor->oldspecial; | ||
282 | floor->sector->floorpic = floor->texture; | ||
283 | break; | ||
284 | case genFloorChgT: | ||
285 | case genFloorChg0: | ||
286 | floor->sector->special = floor->newspecial; | ||
287 | //jff add to fix bug in special transfers from changes | ||
288 | floor->sector->oldspecial = floor->oldspecial; | ||
289 | //fall thru | ||
290 | case genFloorChg: | ||
291 | floor->sector->floorpic = floor->texture; | ||
292 | break; | ||
293 | default: | ||
294 | break; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | floor->sector->floordata = NULL; //jff 2/22/98 | ||
299 | P_RemoveThinker(&floor->thinker);//remove this floor from list of movers | ||
300 | |||
301 | //jff 2/26/98 implement stair retrigger lockout while still building | ||
302 | // note this only applies to the retriggerable generalized stairs | ||
303 | |||
304 | if (floor->sector->stairlock==-2) // if this sector is stairlocked | ||
305 | { | ||
306 | sector_t *sec = floor->sector; | ||
307 | sec->stairlock=-1; // thinker done, promote lock to -1 | ||
308 | |||
309 | while (sec->prevsec!=-1 && sectors[sec->prevsec].stairlock!=-2) | ||
310 | sec = §ors[sec->prevsec]; // search for a non-done thinker | ||
311 | if (sec->prevsec==-1) // if all thinkers previous are done | ||
312 | { | ||
313 | sec = floor->sector; // search forward | ||
314 | while (sec->nextsec!=-1 && sectors[sec->nextsec].stairlock!=-2) | ||
315 | sec = §ors[sec->nextsec]; | ||
316 | if (sec->nextsec==-1) // if all thinkers ahead are done too | ||
317 | { | ||
318 | while (sec->prevsec!=-1) // clear all locks | ||
319 | { | ||
320 | sec->stairlock = 0; | ||
321 | sec = §ors[sec->prevsec]; | ||
322 | } | ||
323 | sec->stairlock = 0; | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | |||
328 | // make floor stop sound | ||
329 | S_StartSound((mobj_t *)&floor->sector->soundorg, sfx_pstop); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | // | ||
334 | // T_MoveElevator() | ||
335 | // | ||
336 | // Move an elevator to it's destination (up or down) | ||
337 | // Called once per tick for each moving floor. | ||
338 | // | ||
339 | // Passed an elevator_t structure that contains all pertinent info about the | ||
340 | // move. See P_SPEC.H for fields. | ||
341 | // No return. | ||
342 | // | ||
343 | // jff 02/22/98 added to support parallel floor/ceiling motion | ||
344 | // | ||
345 | void T_MoveElevator(elevator_t* elevator) | ||
346 | { | ||
347 | result_e res; | ||
348 | |||
349 | if (elevator->direction<0) // moving down | ||
350 | { | ||
351 | res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor | ||
352 | ( | ||
353 | elevator->sector, | ||
354 | elevator->speed, | ||
355 | elevator->ceilingdestheight, | ||
356 | 0, | ||
357 | 1, // move floor | ||
358 | elevator->direction | ||
359 | ); | ||
360 | if (res==ok || res==pastdest) // jff 4/7/98 don't move ceil if blocked | ||
361 | T_MovePlane | ||
362 | ( | ||
363 | elevator->sector, | ||
364 | elevator->speed, | ||
365 | elevator->floordestheight, | ||
366 | 0, | ||
367 | 0, // move ceiling | ||
368 | elevator->direction | ||
369 | ); | ||
370 | } | ||
371 | else // up | ||
372 | { | ||
373 | res = T_MovePlane //jff 4/7/98 reverse order of ceiling/floor | ||
374 | ( | ||
375 | elevator->sector, | ||
376 | elevator->speed, | ||
377 | elevator->floordestheight, | ||
378 | 0, | ||
379 | 0, // move ceiling | ||
380 | elevator->direction | ||
381 | ); | ||
382 | if (res==ok || res==pastdest) // jff 4/7/98 don't move floor if blocked | ||
383 | T_MovePlane | ||
384 | ( | ||
385 | elevator->sector, | ||
386 | elevator->speed, | ||
387 | elevator->ceilingdestheight, | ||
388 | 0, | ||
389 | 1, // move floor | ||
390 | elevator->direction | ||
391 | ); | ||
392 | } | ||
393 | |||
394 | // make floor move sound | ||
395 | if (!(leveltime&7)) | ||
396 | S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_stnmov); | ||
397 | |||
398 | if (res == pastdest) // if destination height acheived | ||
399 | { | ||
400 | elevator->sector->floordata = NULL; //jff 2/22/98 | ||
401 | elevator->sector->ceilingdata = NULL; //jff 2/22/98 | ||
402 | P_RemoveThinker(&elevator->thinker); // remove elevator from actives | ||
403 | |||
404 | // make floor stop sound | ||
405 | S_StartSound((mobj_t *)&elevator->sector->soundorg, sfx_pstop); | ||
406 | } | ||
407 | } | ||
408 | |||
409 | /////////////////////////////////////////////////////////////////////// | ||
410 | // | ||
411 | // Floor motion linedef handlers | ||
412 | // | ||
413 | /////////////////////////////////////////////////////////////////////// | ||
414 | |||
415 | // | ||
416 | // EV_DoFloor() | ||
417 | // | ||
418 | // Handle regular and extended floor types | ||
419 | // | ||
420 | // Passed the line that activated the floor and the type of floor motion | ||
421 | // Returns true if a thinker was created. | ||
422 | // | ||
423 | int EV_DoFloor | ||
424 | ( line_t* line, | ||
425 | floor_e floortype ) | ||
426 | { | ||
427 | int secnum; | ||
428 | int rtn; | ||
429 | int i; | ||
430 | sector_t* sec; | ||
431 | floormove_t* floor; | ||
432 | |||
433 | secnum = -1; | ||
434 | rtn = 0; | ||
435 | // move all floors with the same tag as the linedef | ||
436 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
437 | { | ||
438 | sec = §ors[secnum]; | ||
439 | |||
440 | // Don't start a second thinker on the same floor | ||
441 | if (P_SectorActive(floor_special,sec)) //jff 2/23/98 | ||
442 | continue; | ||
443 | |||
444 | // new floor thinker | ||
445 | rtn = 1; | ||
446 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
447 | P_AddThinker (&floor->thinker); | ||
448 | sec->floordata = floor; //jff 2/22/98 | ||
449 | floor->thinker.function = T_MoveFloor; | ||
450 | floor->type = floortype; | ||
451 | floor->crush = false; | ||
452 | |||
453 | // setup the thinker according to the linedef type | ||
454 | switch(floortype) | ||
455 | { | ||
456 | case lowerFloor: | ||
457 | floor->direction = -1; | ||
458 | floor->sector = sec; | ||
459 | floor->speed = FLOORSPEED; | ||
460 | floor->floordestheight = P_FindHighestFloorSurrounding(sec); | ||
461 | break; | ||
462 | |||
463 | //jff 02/03/30 support lowering floor by 24 absolute | ||
464 | case lowerFloor24: | ||
465 | floor->direction = -1; | ||
466 | floor->sector = sec; | ||
467 | floor->speed = FLOORSPEED; | ||
468 | floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; | ||
469 | break; | ||
470 | |||
471 | //jff 02/03/30 support lowering floor by 32 absolute (fast) | ||
472 | case lowerFloor32Turbo: | ||
473 | floor->direction = -1; | ||
474 | floor->sector = sec; | ||
475 | floor->speed = FLOORSPEED*4; | ||
476 | floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT; | ||
477 | break; | ||
478 | |||
479 | case lowerFloorToLowest: | ||
480 | floor->direction = -1; | ||
481 | floor->sector = sec; | ||
482 | floor->speed = FLOORSPEED; | ||
483 | floor->floordestheight = P_FindLowestFloorSurrounding(sec); | ||
484 | break; | ||
485 | |||
486 | //jff 02/03/30 support lowering floor to next lowest floor | ||
487 | case lowerFloorToNearest: | ||
488 | floor->direction = -1; | ||
489 | floor->sector = sec; | ||
490 | floor->speed = FLOORSPEED; | ||
491 | floor->floordestheight = | ||
492 | P_FindNextLowestFloor(sec,floor->sector->floorheight); | ||
493 | break; | ||
494 | |||
495 | case turboLower: | ||
496 | floor->direction = -1; | ||
497 | floor->sector = sec; | ||
498 | floor->speed = FLOORSPEED * 4; | ||
499 | floor->floordestheight = P_FindHighestFloorSurrounding(sec); | ||
500 | if (floor->floordestheight != sec->floorheight) | ||
501 | floor->floordestheight += 8*FRACUNIT; | ||
502 | break; | ||
503 | |||
504 | case raiseFloorCrush: | ||
505 | floor->crush = true; | ||
506 | case raiseFloor: | ||
507 | floor->direction = 1; | ||
508 | floor->sector = sec; | ||
509 | floor->speed = FLOORSPEED; | ||
510 | floor->floordestheight = P_FindLowestCeilingSurrounding(sec); | ||
511 | if (floor->floordestheight > sec->ceilingheight) | ||
512 | floor->floordestheight = sec->ceilingheight; | ||
513 | floor->floordestheight -= (8*FRACUNIT)*(floortype == raiseFloorCrush); | ||
514 | break; | ||
515 | |||
516 | case raiseFloorTurbo: | ||
517 | floor->direction = 1; | ||
518 | floor->sector = sec; | ||
519 | floor->speed = FLOORSPEED*4; | ||
520 | floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); | ||
521 | break; | ||
522 | |||
523 | case raiseFloorToNearest: | ||
524 | floor->direction = 1; | ||
525 | floor->sector = sec; | ||
526 | floor->speed = FLOORSPEED; | ||
527 | floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); | ||
528 | break; | ||
529 | |||
530 | case raiseFloor24: | ||
531 | floor->direction = 1; | ||
532 | floor->sector = sec; | ||
533 | floor->speed = FLOORSPEED; | ||
534 | floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; | ||
535 | break; | ||
536 | |||
537 | // jff 2/03/30 support straight raise by 32 (fast) | ||
538 | case raiseFloor32Turbo: | ||
539 | floor->direction = 1; | ||
540 | floor->sector = sec; | ||
541 | floor->speed = FLOORSPEED*4; | ||
542 | floor->floordestheight = floor->sector->floorheight + 32 * FRACUNIT; | ||
543 | break; | ||
544 | |||
545 | case raiseFloor512: | ||
546 | floor->direction = 1; | ||
547 | floor->sector = sec; | ||
548 | floor->speed = FLOORSPEED; | ||
549 | floor->floordestheight = floor->sector->floorheight + 512 * FRACUNIT; | ||
550 | break; | ||
551 | |||
552 | case raiseFloor24AndChange: | ||
553 | floor->direction = 1; | ||
554 | floor->sector = sec; | ||
555 | floor->speed = FLOORSPEED; | ||
556 | floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; | ||
557 | sec->floorpic = line->frontsector->floorpic; | ||
558 | sec->special = line->frontsector->special; | ||
559 | //jff 3/14/98 transfer both old and new special | ||
560 | sec->oldspecial = line->frontsector->oldspecial; | ||
561 | break; | ||
562 | |||
563 | case raiseToTexture: | ||
564 | { | ||
565 | int minsize = INT_MAX; | ||
566 | side_t* side; | ||
567 | |||
568 | /* jff 3/13/98 no ovf */ | ||
569 | if (!comp[comp_model]) minsize = 32000<<FRACBITS; | ||
570 | floor->direction = 1; | ||
571 | floor->sector = sec; | ||
572 | floor->speed = FLOORSPEED; | ||
573 | for (i = 0; i < sec->linecount; i++) | ||
574 | { | ||
575 | if (twoSided (secnum, i) ) | ||
576 | { | ||
577 | side = getSide(secnum,i,0); | ||
578 | // jff 8/14/98 don't scan texture 0, its not real | ||
579 | if (side->bottomtexture > 0 || | ||
580 | (comp[comp_model] && !side->bottomtexture)) | ||
581 | if (textureheight[side->bottomtexture] < minsize) | ||
582 | minsize = textureheight[side->bottomtexture]; | ||
583 | side = getSide(secnum,i,1); | ||
584 | // jff 8/14/98 don't scan texture 0, its not real | ||
585 | if (side->bottomtexture > 0 || | ||
586 | (comp[comp_model] && !side->bottomtexture)) | ||
587 | if (textureheight[side->bottomtexture] < minsize) | ||
588 | minsize = textureheight[side->bottomtexture]; | ||
589 | } | ||
590 | } | ||
591 | if (comp[comp_model]) | ||
592 | floor->floordestheight = floor->sector->floorheight + minsize; | ||
593 | else | ||
594 | { | ||
595 | floor->floordestheight = | ||
596 | (floor->sector->floorheight>>FRACBITS) + (minsize>>FRACBITS); | ||
597 | if (floor->floordestheight>32000) | ||
598 | floor->floordestheight = 32000; //jff 3/13/98 do not | ||
599 | floor->floordestheight<<=FRACBITS; // allow height overflow | ||
600 | } | ||
601 | } | ||
602 | break; | ||
603 | |||
604 | case lowerAndChange: | ||
605 | floor->direction = -1; | ||
606 | floor->sector = sec; | ||
607 | floor->speed = FLOORSPEED; | ||
608 | floor->floordestheight = P_FindLowestFloorSurrounding(sec); | ||
609 | floor->texture = sec->floorpic; | ||
610 | |||
611 | // jff 1/24/98 make sure floor->newspecial gets initialized | ||
612 | // in case no surrounding sector is at floordestheight | ||
613 | // --> should not affect compatibility <-- | ||
614 | floor->newspecial = sec->special; | ||
615 | //jff 3/14/98 transfer both old and new special | ||
616 | floor->oldspecial = sec->oldspecial; | ||
617 | |||
618 | //jff 5/23/98 use model subroutine to unify fixes and handling | ||
619 | sec = P_FindModelFloorSector(floor->floordestheight,sec-sectors); | ||
620 | if (sec) | ||
621 | { | ||
622 | floor->texture = sec->floorpic; | ||
623 | floor->newspecial = sec->special; | ||
624 | //jff 3/14/98 transfer both old and new special | ||
625 | floor->oldspecial = sec->oldspecial; | ||
626 | } | ||
627 | break; | ||
628 | default: | ||
629 | break; | ||
630 | } | ||
631 | } | ||
632 | return rtn; | ||
633 | } | ||
634 | |||
635 | // | ||
636 | // EV_DoChange() | ||
637 | // | ||
638 | // Handle pure change types. These change floor texture and sector type | ||
639 | // by trigger or numeric model without moving the floor. | ||
640 | // | ||
641 | // The linedef causing the change and the type of change is passed | ||
642 | // Returns true if any sector changes | ||
643 | // | ||
644 | // jff 3/15/98 added to better support generalized sector types | ||
645 | // | ||
646 | int EV_DoChange | ||
647 | ( line_t* line, | ||
648 | change_e changetype ) | ||
649 | { | ||
650 | int secnum; | ||
651 | int rtn; | ||
652 | sector_t* sec; | ||
653 | sector_t* secm; | ||
654 | |||
655 | secnum = -1; | ||
656 | rtn = 0; | ||
657 | // change all sectors with the same tag as the linedef | ||
658 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
659 | { | ||
660 | sec = §ors[secnum]; | ||
661 | |||
662 | rtn = 1; | ||
663 | |||
664 | // handle trigger or numeric change type | ||
665 | switch(changetype) | ||
666 | { | ||
667 | case trigChangeOnly: | ||
668 | sec->floorpic = line->frontsector->floorpic; | ||
669 | sec->special = line->frontsector->special; | ||
670 | sec->oldspecial = line->frontsector->oldspecial; | ||
671 | break; | ||
672 | case numChangeOnly: | ||
673 | secm = P_FindModelFloorSector(sec->floorheight,secnum); | ||
674 | if (secm) // if no model, no change | ||
675 | { | ||
676 | sec->floorpic = secm->floorpic; | ||
677 | sec->special = secm->special; | ||
678 | sec->oldspecial = secm->oldspecial; | ||
679 | } | ||
680 | break; | ||
681 | default: | ||
682 | break; | ||
683 | } | ||
684 | } | ||
685 | return rtn; | ||
686 | } | ||
687 | |||
688 | /* | ||
689 | * EV_BuildStairs() | ||
690 | * | ||
691 | * Handles staircase building. A sequence of sectors chosen by algorithm | ||
692 | * rise at a speed indicated to a height that increases by the stepsize | ||
693 | * each step. | ||
694 | * | ||
695 | * Passed the linedef triggering the stairs and the type of stair rise | ||
696 | * Returns true if any thinkers are created | ||
697 | * | ||
698 | * cph 2001/09/21 - compatibility nightmares again | ||
699 | * There are three different ways this function has, during its history, stepped | ||
700 | * through all the stairs to be triggered by the single switch | ||
701 | * - original Doom used a linear P_FindSectorFromLineTag, but failed to preserve | ||
702 | * the index of the previous sector found, so instead it would restart its | ||
703 | * linear search from the last sector of the previous staircase | ||
704 | * - MBF/PrBoom with comp_stairs fail to emulate this, because their | ||
705 | * P_FindSectorFromLineTag is a chained hash table implementation. Instead they | ||
706 | * start following the hash chain from the last sector of the previous | ||
707 | * staircase, which will (probably) have the wrong tag, so they miss any further | ||
708 | * stairs | ||
709 | * - Boom fixed the bug, and MBF/PrBoom without comp_stairs work right | ||
710 | */ | ||
711 | static inline int P_FindSectorFromLineTagWithLowerBound | ||
712 | (line_t* l, int start, int min) | ||
713 | { | ||
714 | /* Emulate original Doom's linear lower-bounded P_FindSectorFromLineTag | ||
715 | * as needed */ | ||
716 | do { | ||
717 | start = P_FindSectorFromLineTag(l,start); | ||
718 | } while (start >= 0 && start <= min); | ||
719 | return start; | ||
720 | } | ||
721 | |||
722 | int EV_BuildStairs | ||
723 | ( line_t* line, | ||
724 | stair_e type ) | ||
725 | { | ||
726 | /* cph 2001/09/22 - cleaned up this function to save my sanity. A separate | ||
727 | * outer loop index makes the logic much cleared, and local variables moved | ||
728 | * into the inner blocks helps too */ | ||
729 | int ssec = -1; | ||
730 | int minssec = -1; | ||
731 | int rtn = 0; | ||
732 | |||
733 | // start a stair at each sector tagged the same as the linedef | ||
734 | while ((ssec = P_FindSectorFromLineTagWithLowerBound(line,ssec,minssec)) >= 0) | ||
735 | { | ||
736 | int secnum = ssec; | ||
737 | sector_t* sec = §ors[secnum]; | ||
738 | |||
739 | // don't start a stair if the first step's floor is already moving | ||
740 | if (!P_SectorActive(floor_special,sec)) { //jff 2/22/98 | ||
741 | floormove_t* floor; | ||
742 | int texture, height; | ||
743 | fixed_t stairsize; | ||
744 | fixed_t speed; | ||
745 | int ok; | ||
746 | |||
747 | // create new floor thinker for first step | ||
748 | rtn = 1; | ||
749 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
750 | P_AddThinker (&floor->thinker); | ||
751 | sec->floordata = floor; | ||
752 | floor->thinker.function = T_MoveFloor; | ||
753 | floor->direction = 1; | ||
754 | floor->sector = sec; | ||
755 | floor->type = buildStair; //jff 3/31/98 do not leave uninited | ||
756 | |||
757 | // set up the speed and stepsize according to the stairs type | ||
758 | switch(type) | ||
759 | { | ||
760 | default: // killough -- prevent compiler warning | ||
761 | case build8: | ||
762 | speed = FLOORSPEED/4; | ||
763 | stairsize = 8*FRACUNIT; | ||
764 | if (!demo_compatibility) | ||
765 | floor->crush = false; //jff 2/27/98 fix uninitialized crush field | ||
766 | break; | ||
767 | case turbo16: | ||
768 | speed = FLOORSPEED*4; | ||
769 | stairsize = 16*FRACUNIT; | ||
770 | if (!demo_compatibility) | ||
771 | floor->crush = true; //jff 2/27/98 fix uninitialized crush field | ||
772 | break; | ||
773 | } | ||
774 | floor->speed = speed; | ||
775 | height = sec->floorheight + stairsize; | ||
776 | floor->floordestheight = height; | ||
777 | |||
778 | texture = sec->floorpic; | ||
779 | |||
780 | // Find next sector to raise | ||
781 | // 1. Find 2-sided line with same sector side[0] (lowest numbered) | ||
782 | // 2. Other side is the next sector to raise | ||
783 | // 3. Unless already moving, or different texture, then stop building | ||
784 | do | ||
785 | { | ||
786 | int i; | ||
787 | ok = 0; | ||
788 | |||
789 | for (i = 0;i < sec->linecount;i++) | ||
790 | { | ||
791 | sector_t* tsec = (sec->lines[i])->frontsector; | ||
792 | int newsecnum; | ||
793 | if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) | ||
794 | continue; | ||
795 | |||
796 | newsecnum = tsec-sectors; | ||
797 | |||
798 | if (secnum != newsecnum) | ||
799 | continue; | ||
800 | |||
801 | tsec = (sec->lines[i])->backsector; | ||
802 | if (!tsec) continue; //jff 5/7/98 if no backside, continue | ||
803 | newsecnum = tsec - sectors; | ||
804 | |||
805 | // if sector's floor is different texture, look for another | ||
806 | if (tsec->floorpic != texture) | ||
807 | continue; | ||
808 | |||
809 | /* jff 6/19/98 prevent double stepsize | ||
810 | * killough 10/98: intentionally left this way [MBF comment] | ||
811 | * cph 2001/02/06: stair bug fix should be controlled by comp_stairs, | ||
812 | * except if we're emulating MBF which perversly reverted the fix | ||
813 | */ | ||
814 | if (comp[comp_stairs] || (compatibility_level == mbf_compatibility)) | ||
815 | height += stairsize; // jff 6/28/98 change demo compatibility | ||
816 | |||
817 | // if sector's floor already moving, look for another | ||
818 | if (P_SectorActive(floor_special,tsec)) //jff 2/22/98 | ||
819 | continue; | ||
820 | |||
821 | /* cph - see comment above - do this iff we didn't do so above */ | ||
822 | if (!comp[comp_stairs] && (compatibility_level != mbf_compatibility)) | ||
823 | height += stairsize; | ||
824 | |||
825 | sec = tsec; | ||
826 | secnum = newsecnum; | ||
827 | |||
828 | // create and initialize a thinker for the next step | ||
829 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
830 | P_AddThinker (&floor->thinker); | ||
831 | |||
832 | sec->floordata = floor; //jff 2/22/98 | ||
833 | floor->thinker.function = T_MoveFloor; | ||
834 | floor->direction = 1; | ||
835 | floor->sector = sec; | ||
836 | floor->speed = speed; | ||
837 | floor->floordestheight = height; | ||
838 | floor->type = buildStair; //jff 3/31/98 do not leave uninited | ||
839 | //jff 2/27/98 fix uninitialized crush field | ||
840 | if (!demo_compatibility) | ||
841 | floor->crush = type==build8? false : true; | ||
842 | ok = 1; | ||
843 | break; | ||
844 | } | ||
845 | } while(ok); // continue until no next step is found | ||
846 | |||
847 | } | ||
848 | /* killough 10/98: compatibility option */ | ||
849 | if (comp[comp_stairs]) { | ||
850 | /* cph 2001/09/22 - emulate buggy MBF comp_stairs for demos, with logic | ||
851 | * reversed since we now have a separate outer loop index. | ||
852 | * DEMOSYNC - what about boom_compatibility_compatibility? | ||
853 | */ | ||
854 | if ((compatibility_level >= mbf_compatibility) && (compatibility_level < | ||
855 | prboom_3_compatibility)) ssec = secnum; /* Trash outer loop index */ | ||
856 | else { | ||
857 | /* cph 2001/09/22 - now the correct comp_stairs - Doom used a linear | ||
858 | * search from the last secnum, so we set that as a minimum value and do | ||
859 | * a fresh tag search | ||
860 | */ | ||
861 | ssec = -1; minssec = secnum; | ||
862 | } | ||
863 | } | ||
864 | } | ||
865 | return rtn; | ||
866 | } | ||
867 | |||
868 | // | ||
869 | // EV_DoDonut() | ||
870 | // | ||
871 | // Handle donut function: lower pillar, raise surrounding pool, both to height, | ||
872 | // texture and type of the sector surrounding the pool. | ||
873 | // | ||
874 | // Passed the linedef that triggered the donut | ||
875 | // Returns whether a thinker was created | ||
876 | // | ||
877 | int EV_DoDonut(line_t* line) | ||
878 | { | ||
879 | sector_t* s1; | ||
880 | sector_t* s2; | ||
881 | sector_t* s3; | ||
882 | int secnum; | ||
883 | int rtn; | ||
884 | int i; | ||
885 | floormove_t* floor; | ||
886 | |||
887 | secnum = -1; | ||
888 | rtn = 0; | ||
889 | // do function on all sectors with same tag as linedef | ||
890 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
891 | { | ||
892 | s1 = §ors[secnum]; // s1 is pillar's sector | ||
893 | |||
894 | // do not start the donut if the pillar is already moving | ||
895 | if (P_SectorActive(floor_special,s1)) //jff 2/22/98 | ||
896 | continue; | ||
897 | |||
898 | s2 = getNextSector(s1->lines[0],s1); // s2 is pool's sector | ||
899 | if (!s2) continue; // note lowest numbered line around | ||
900 | // pillar must be two-sided | ||
901 | |||
902 | /* do not start the donut if the pool is already moving | ||
903 | * cph - DEMOSYNC - was !compatibility */ | ||
904 | if (!comp[comp_floors] && P_SectorActive(floor_special,s2)) | ||
905 | continue; //jff 5/7/98 | ||
906 | |||
907 | // find a two sided line around the pool whose other side isn't the pillar | ||
908 | for (i = 0;i < s2->linecount;i++) | ||
909 | { | ||
910 | //jff 3/29/98 use true two-sidedness, not the flag | ||
911 | // killough 4/5/98: changed demo_compatibility to compatibility | ||
912 | if (comp[comp_model]) | ||
913 | { | ||
914 | if ((!s2->lines[i]->flags & ML_TWOSIDED) || | ||
915 | (s2->lines[i]->backsector == s1)) | ||
916 | continue; | ||
917 | } | ||
918 | else if (!s2->lines[i]->backsector || s2->lines[i]->backsector == s1) | ||
919 | continue; | ||
920 | |||
921 | rtn = 1; //jff 1/26/98 no donut action - no switch change on return | ||
922 | |||
923 | s3 = s2->lines[i]->backsector; // s3 is model sector for changes | ||
924 | |||
925 | // Spawn rising slime | ||
926 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
927 | P_AddThinker (&floor->thinker); | ||
928 | s2->floordata = floor; //jff 2/22/98 | ||
929 | floor->thinker.function = T_MoveFloor; | ||
930 | floor->type = donutRaise; | ||
931 | floor->crush = false; | ||
932 | floor->direction = 1; | ||
933 | floor->sector = s2; | ||
934 | floor->speed = FLOORSPEED / 2; | ||
935 | floor->texture = s3->floorpic; | ||
936 | floor->newspecial = 0; | ||
937 | floor->floordestheight = s3->floorheight; | ||
938 | |||
939 | // Spawn lowering donut-hole pillar | ||
940 | floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); | ||
941 | P_AddThinker (&floor->thinker); | ||
942 | s1->floordata = floor; //jff 2/22/98 | ||
943 | floor->thinker.function = T_MoveFloor; | ||
944 | floor->type = lowerFloor; | ||
945 | floor->crush = false; | ||
946 | floor->direction = -1; | ||
947 | floor->sector = s1; | ||
948 | floor->speed = FLOORSPEED / 2; | ||
949 | floor->floordestheight = s3->floorheight; | ||
950 | break; | ||
951 | } | ||
952 | } | ||
953 | return rtn; | ||
954 | } | ||
955 | |||
956 | // | ||
957 | // EV_DoElevator | ||
958 | // | ||
959 | // Handle elevator linedef types | ||
960 | // | ||
961 | // Passed the linedef that triggered the elevator and the elevator action | ||
962 | // | ||
963 | // jff 2/22/98 new type to move floor and ceiling in parallel | ||
964 | // | ||
965 | int EV_DoElevator | ||
966 | ( line_t* line, | ||
967 | elevator_e elevtype ) | ||
968 | { | ||
969 | int secnum; | ||
970 | int rtn; | ||
971 | sector_t* sec; | ||
972 | elevator_t* elevator; | ||
973 | |||
974 | secnum = -1; | ||
975 | rtn = 0; | ||
976 | // act on all sectors with the same tag as the triggering linedef | ||
977 | while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) | ||
978 | { | ||
979 | sec = §ors[secnum]; | ||
980 | |||
981 | // If either floor or ceiling is already activated, skip it | ||
982 | if (sec->floordata || sec->ceilingdata) //jff 2/22/98 | ||
983 | continue; | ||
984 | |||
985 | // create and initialize new elevator thinker | ||
986 | rtn = 1; | ||
987 | elevator = Z_Malloc (sizeof(*elevator), PU_LEVSPEC, 0); | ||
988 | P_AddThinker (&elevator->thinker); | ||
989 | sec->floordata = elevator; //jff 2/22/98 | ||
990 | sec->ceilingdata = elevator; //jff 2/22/98 | ||
991 | elevator->thinker.function = T_MoveElevator; | ||
992 | elevator->type = elevtype; | ||
993 | |||
994 | // set up the fields according to the type of elevator action | ||
995 | switch(elevtype) | ||
996 | { | ||
997 | // elevator down to next floor | ||
998 | case elevateDown: | ||
999 | elevator->direction = -1; | ||
1000 | elevator->sector = sec; | ||
1001 | elevator->speed = ELEVATORSPEED; | ||
1002 | elevator->floordestheight = | ||
1003 | P_FindNextLowestFloor(sec,sec->floorheight); | ||
1004 | elevator->ceilingdestheight = | ||
1005 | elevator->floordestheight + sec->ceilingheight - sec->floorheight; | ||
1006 | break; | ||
1007 | |||
1008 | // elevator up to next floor | ||
1009 | case elevateUp: | ||
1010 | elevator->direction = 1; | ||
1011 | elevator->sector = sec; | ||
1012 | elevator->speed = ELEVATORSPEED; | ||
1013 | elevator->floordestheight = | ||
1014 | P_FindNextHighestFloor(sec,sec->floorheight); | ||
1015 | elevator->ceilingdestheight = | ||
1016 | elevator->floordestheight + sec->ceilingheight - sec->floorheight; | ||
1017 | break; | ||
1018 | |||
1019 | // elevator to floor height of activating switch's front sector | ||
1020 | case elevateCurrent: | ||
1021 | elevator->sector = sec; | ||
1022 | elevator->speed = ELEVATORSPEED; | ||
1023 | elevator->floordestheight = line->frontsector->floorheight; | ||
1024 | elevator->ceilingdestheight = | ||
1025 | elevator->floordestheight + sec->ceilingheight - sec->floorheight; | ||
1026 | elevator->direction = | ||
1027 | elevator->floordestheight>sec->floorheight? 1 : -1; | ||
1028 | break; | ||
1029 | |||
1030 | default: | ||
1031 | break; | ||
1032 | } | ||
1033 | } | ||
1034 | return rtn; | ||
1035 | } | ||