]> git.lizzy.rs Git - plan9front.git/blob - sys/src/games/doom/p_doors.c
games/doom: fix mips
[plan9front.git] / sys / src / games / doom / p_doors.c
1 // Emacs style mode select   -*- C++ -*- 
2 //-----------------------------------------------------------------------------
3 //
4 // $Id:$
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 //
8 // This source is available for distribution and/or modification
9 // only under the terms of the DOOM Source Code License as
10 // published by id Software. All rights reserved.
11 //
12 // The source is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
15 // for more details.
16 //
17 // $Log:$
18 //
19 // DESCRIPTION: Door animation code (opening/closing)
20 //
21 //-----------------------------------------------------------------------------
22
23 static const char
24 rcsid[] = "$Id: p_doors.c,v 1.4 1997/02/03 16:47:53 b1 Exp $";
25
26
27 #include "z_zone.h"
28 #include "doomdef.h"
29 #include "p_local.h"
30
31 #include "s_sound.h"
32
33
34 // State.
35 #include "doomstat.h"
36 #include "r_state.h"
37
38 // Data.
39 #include "dstrings.h"
40 #include "sounds.h"
41
42
43 //
44 // VERTICAL DOORS
45 //
46
47 //
48 // T_VerticalDoor
49 //
50 void T_VerticalDoor (void *_door, void*)
51 {
52     vldoor_t *door = (vldoor_t*)_door;
53     result_e    res;
54         
55     switch(door->direction)
56     {
57       case 0:
58         // WAITING
59         if (!--door->topcountdown)
60         {
61             switch(door->type)
62             {
63               case BlazeRaise:
64                 door->direction = -1; // time to go back down
65                 S_StartSound((mobj_t *)&door->sector->soundorg,
66                              sfx_bdcls);
67                 break;
68                 
69               case Normal:
70                 door->direction = -1; // time to go back down
71                 S_StartSound((mobj_t *)&door->sector->soundorg,
72                              sfx_dorcls);
73                 break;
74                 
75               case Close30ThenOpen:
76                 door->direction = 1;
77                 S_StartSound((mobj_t *)&door->sector->soundorg,
78                              sfx_doropn);
79                 break;
80                 
81               default:
82                 break;
83             }
84         }
85         break;
86         
87       case 2:
88         //  INITIAL WAIT
89         if (!--door->topcountdown)
90         {
91             switch(door->type)
92             {
93               case RaiseIn5Mins:
94                 door->direction = 1;
95                 door->type = Normal;
96                 S_StartSound((mobj_t *)&door->sector->soundorg,
97                              sfx_doropn);
98                 break;
99                 
100               default:
101                 break;
102             }
103         }
104         break;
105         
106       case -1:
107         // DOWN
108         res = T_MovePlane(door->sector,
109                           door->speed,
110                           door->sector->floorheight,
111                           false,1,door->direction);
112         if (res == pastdest)
113         {
114             switch(door->type)
115             {
116               case BlazeRaise:
117               case BlazeClose:
118                 door->sector->specialdata = NULL;
119                 P_RemoveThinker (&door->thinker);  // unlink and free
120                 S_StartSound((mobj_t *)&door->sector->soundorg,
121                              sfx_bdcls);
122                 break;
123                 
124               case Normal:
125               case Close:
126                 door->sector->specialdata = NULL;
127                 P_RemoveThinker (&door->thinker);  // unlink and free
128                 break;
129                 
130               case Close30ThenOpen:
131                 door->direction = 0;
132                 door->topcountdown = 35*30;
133                 break;
134                 
135               default:
136                 break;
137             }
138         }
139         else if (res == crushed)
140         {
141             switch(door->type)
142             {
143               case BlazeClose:
144               case Close:               // DO NOT GO BACK UP!
145                 break;
146                 
147               default:
148                 door->direction = 1;
149                 S_StartSound((mobj_t *)&door->sector->soundorg,
150                              sfx_doropn);
151                 break;
152             }
153         }
154         break;
155         
156       case 1:
157         // UP
158         res = T_MovePlane(door->sector,
159                           door->speed,
160                           door->topheight,
161                           false,1,door->direction);
162         
163         if (res == pastdest)
164         {
165             switch(door->type)
166             {
167               case BlazeRaise:
168               case Normal:
169                 door->direction = 0; // wait at top
170                 door->topcountdown = door->topwait;
171                 break;
172                 
173               case Close30ThenOpen:
174               case BlazeOpen:
175               case Open:
176                 door->sector->specialdata = NULL;
177                 P_RemoveThinker (&door->thinker);  // unlink and free
178                 break;
179                 
180               default:
181                 break;
182             }
183         }
184         break;
185     }
186 }
187
188
189 //
190 // EV_DoLockedDoor
191 // Move a locked door up/down
192 //
193
194 int
195 EV_DoLockedDoor
196 ( line_t*       line,
197   vldoor_e      type,
198   mobj_t*       thing )
199 {
200     player_t*   p;
201         
202     p = thing->player;
203         
204     if (!p)
205         return 0;
206                 
207     switch(line->special)
208     {
209       case 99:  // Blue Lock
210       case 133:
211         if ( !p )
212             return 0;
213         if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
214         {
215             p->message = PD_BLUEO;
216             S_StartSound(NULL,sfx_oof);
217             return 0;
218         }
219         break;
220         
221       case 134: // Red Lock
222       case 135:
223         if ( !p )
224             return 0;
225         if (!p->cards[it_redcard] && !p->cards[it_redskull])
226         {
227             p->message = PD_REDO;
228             S_StartSound(NULL,sfx_oof);
229             return 0;
230         }
231         break;
232         
233       case 136: // Yellow Lock
234       case 137:
235         if ( !p )
236             return 0;
237         if (!p->cards[it_yellowcard] &&
238             !p->cards[it_yellowskull])
239         {
240             p->message = PD_YELLOWO;
241             S_StartSound(NULL,sfx_oof);
242             return 0;
243         }
244         break;  
245     }
246
247     return EV_DoDoor(line,type);
248 }
249
250
251 int
252 EV_DoDoor
253 ( line_t*       line,
254   vldoor_e      type )
255 {
256     int         secnum,rtn;
257     sector_t*   sec;
258     vldoor_t*   door;
259         
260     secnum = -1;
261     rtn = 0;
262     
263     while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
264     {
265         sec = &sectors[secnum];
266         if (sec->specialdata)
267             continue;
268                 
269         
270         // new door thinker
271         rtn = 1;
272         door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
273         P_AddThinker (&door->thinker);
274         sec->specialdata = door;
275
276         door->thinker.function = T_VerticalDoor;
277         door->sector = sec;
278         door->type = type;
279         door->topwait = VDOORWAIT;
280         door->speed = VDOORSPEED;
281                 
282         switch(type)
283         {
284           case BlazeClose:
285             door->topheight = P_FindLowestCeilingSurrounding(sec);
286             door->topheight -= 4*FRACUNIT;
287             door->direction = -1;
288             door->speed = VDOORSPEED * 4;
289             S_StartSound((mobj_t *)&door->sector->soundorg,
290                          sfx_bdcls);
291             break;
292             
293           case Close:
294             door->topheight = P_FindLowestCeilingSurrounding(sec);
295             door->topheight -= 4*FRACUNIT;
296             door->direction = -1;
297             S_StartSound((mobj_t *)&door->sector->soundorg,
298                          sfx_dorcls);
299             break;
300             
301           case Close30ThenOpen:
302             door->topheight = sec->ceilingheight;
303             door->direction = -1;
304             S_StartSound((mobj_t *)&door->sector->soundorg,
305                          sfx_dorcls);
306             break;
307             
308           case BlazeRaise:
309           case BlazeOpen:
310             door->direction = 1;
311             door->topheight = P_FindLowestCeilingSurrounding(sec);
312             door->topheight -= 4*FRACUNIT;
313             door->speed = VDOORSPEED * 4;
314             if (door->topheight != sec->ceilingheight)
315                 S_StartSound((mobj_t *)&door->sector->soundorg,
316                              sfx_bdopn);
317             break;
318             
319           case Normal:
320           case Open:
321             door->direction = 1;
322             door->topheight = P_FindLowestCeilingSurrounding(sec);
323             door->topheight -= 4*FRACUNIT;
324             if (door->topheight != sec->ceilingheight)
325                 S_StartSound((mobj_t *)&door->sector->soundorg,
326                              sfx_doropn);
327             break;
328             
329           default:
330             break;
331         }
332                 
333     }
334     return rtn;
335 }
336
337
338 //
339 // EV_VerticalDoor : open a door manually, no tag value
340 //
341 void
342 EV_VerticalDoor
343 ( line_t*       line,
344   mobj_t*       thing )
345 {
346     player_t*   player;
347     sector_t*   sec;
348     vldoor_t*   door;
349     int         side;
350         
351     side = 0;   // only front sides can be used
352
353     //  Check for locks
354     player = thing->player;
355                 
356     switch(line->special)
357     {
358       case 26: // Blue Lock
359       case 32:
360         if ( !player )
361             return;
362         
363         if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
364         {
365             player->message = PD_BLUEK;
366             S_StartSound(NULL,sfx_oof);
367             return;
368         }
369         break;
370         
371       case 27: // Yellow Lock
372       case 34:
373         if ( !player )
374             return;
375         
376         if (!player->cards[it_yellowcard] &&
377             !player->cards[it_yellowskull])
378         {
379             player->message = PD_YELLOWK;
380             S_StartSound(NULL,sfx_oof);
381             return;
382         }
383         break;
384         
385       case 28: // Red Lock
386       case 33:
387         if ( !player )
388             return;
389         
390         if (!player->cards[it_redcard] && !player->cards[it_redskull])
391         {
392             player->message = PD_REDK;
393             S_StartSound(NULL,sfx_oof);
394             return;
395         }
396         break;
397     }
398         
399     // if the sector has an active thinker, use it
400     sec = sides[ line->sidenum[side^1]] .sector;
401
402     if (sec->specialdata)
403     {
404         door = sec->specialdata;
405         switch(line->special)
406         {
407           case  1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
408           case  26:
409           case  27:
410           case  28:
411           case  117:
412             if (door->direction == -1)
413                 door->direction = 1;    // go back up
414             else
415             {
416                 if (!thing->player)
417                     return;             // JDC: bad guys never close doors
418                 
419                 door->direction = -1;   // start going down immediately
420             }
421             return;
422         }
423     }
424         
425     // for proper sound
426     switch(line->special)
427     {
428       case 117: // BLAZING DOOR RAISE
429       case 118: // BLAZING DOOR OPEN
430         S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
431         break;
432         
433       case 1:   // NORMAL DOOR SOUND
434       case 31:
435         S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
436         break;
437         
438       default:  // LOCKED DOOR SOUND
439         S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
440         break;
441     }
442         
443     
444     // new door thinker
445     door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
446     P_AddThinker (&door->thinker);
447     sec->specialdata = door;
448     door->thinker.function = T_VerticalDoor;
449     door->sector = sec;
450     door->direction = 1;
451     door->speed = VDOORSPEED;
452     door->topwait = VDOORWAIT;
453
454     switch(line->special)
455     {
456       case 1:
457       case 26:
458       case 27:
459       case 28:
460         door->type = Normal;
461         break;
462         
463       case 31:
464       case 32:
465       case 33:
466       case 34:
467         door->type = Open;
468         line->special = 0;
469         break;
470         
471       case 117: // blazing door raise
472         door->type = BlazeRaise;
473         door->speed = VDOORSPEED*4;
474         break;
475       case 118: // blazing door open
476         door->type = BlazeOpen;
477         line->special = 0;
478         door->speed = VDOORSPEED*4;
479         break;
480     }
481     
482     // find the top and bottom of the movement range
483     door->topheight = P_FindLowestCeilingSurrounding(sec);
484     door->topheight -= 4*FRACUNIT;
485 }
486
487
488 //
489 // Spawn a door that closes after 30 seconds
490 //
491 void P_SpawnDoorCloseIn30 (sector_t* sec)
492 {
493     vldoor_t*   door;
494         
495     door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
496
497     P_AddThinker (&door->thinker);
498
499     sec->specialdata = door;
500     sec->special = 0;
501
502     door->thinker.function = T_VerticalDoor;
503     door->sector = sec;
504     door->direction = 0;
505     door->type = Normal;
506     door->speed = VDOORSPEED;
507     door->topcountdown = 30 * 35;
508 }
509
510 //
511 // Spawn a door that opens after 5 minutes
512 //
513 void
514 P_SpawnDoorRaiseIn5Mins
515 ( sector_t*     sec )
516 {
517     vldoor_t*   door;
518         
519     door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
520     
521     P_AddThinker (&door->thinker);
522
523     sec->specialdata = door;
524     sec->special = 0;
525
526     door->thinker.function = T_VerticalDoor;
527     door->sector = sec;
528     door->direction = 2;
529     door->type = RaiseIn5Mins;
530     door->speed = VDOORSPEED;
531     door->topheight = P_FindLowestCeilingSurrounding(sec);
532     door->topheight -= 4*FRACUNIT;
533     door->topwait = VDOORWAIT;
534     door->topcountdown = 5 * 60 * 35;
535 }