Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
298 serge 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
#if 0
43
//
44
// Sliding door frame information
45
//
46
slidename_t	slideFrameNames[MAXSLIDEDOORS] =
47
{
48
    {"GDOORF1","GDOORF2","GDOORF3","GDOORF4",	// front
49
     "GDOORB1","GDOORB2","GDOORB3","GDOORB4"},	// back
50
 
51
    {"\0","\0","\0","\0"}
52
};
53
#endif
54
 
55
 
56
//
57
// VERTICAL DOORS
58
//
59
 
60
//
61
// T_VerticalDoor
62
//
63
void T_VerticalDoor (vldoor_t* door)
64
{
65
    result_e	res;
66
 
67
    switch(door->direction)
68
    {
69
      case 0:
70
	// WAITING
71
	if (!--door->topcountdown)
72
	{
73
	    switch(door->type)
74
	    {
75
	      case blazeRaise:
76
		door->direction = -1; // time to go back down
77
		S_StartSound((mobj_t *)&door->sector->soundorg,
78
			     sfx_bdcls);
79
		break;
80
 
81
	      case normal:
82
		door->direction = -1; // time to go back down
83
		S_StartSound((mobj_t *)&door->sector->soundorg,
84
			     sfx_dorcls);
85
		break;
86
 
87
	      case close30ThenOpen:
88
		door->direction = 1;
89
		S_StartSound((mobj_t *)&door->sector->soundorg,
90
			     sfx_doropn);
91
		break;
92
 
93
	      default:
94
		break;
95
	    }
96
	}
97
	break;
98
 
99
      case 2:
100
	//  INITIAL WAIT
101
	if (!--door->topcountdown)
102
	{
103
	    switch(door->type)
104
	    {
105
	      case raiseIn5Mins:
106
		door->direction = 1;
107
		door->type = normal;
108
		S_StartSound((mobj_t *)&door->sector->soundorg,
109
			     sfx_doropn);
110
		break;
111
 
112
	      default:
113
		break;
114
	    }
115
	}
116
	break;
117
 
118
      case -1:
119
	// DOWN
120
	res = T_MovePlane(door->sector,
121
			  door->speed,
122
			  door->sector->floorheight,
123
			  false,1,door->direction);
124
	if (res == pastdest)
125
	{
126
	    switch(door->type)
127
	    {
128
	      case blazeRaise:
129
	      case blazeClose:
130
		door->sector->specialdata = NULL;
131
		P_RemoveThinker (&door->thinker);  // unlink and free
132
		S_StartSound((mobj_t *)&door->sector->soundorg,
133
			     sfx_bdcls);
134
		break;
135
 
136
	      case normal:
137
	      case close:
138
		door->sector->specialdata = NULL;
139
		P_RemoveThinker (&door->thinker);  // unlink and free
140
		break;
141
 
142
	      case close30ThenOpen:
143
		door->direction = 0;
144
		door->topcountdown = 35*30;
145
		break;
146
 
147
	      default:
148
		break;
149
	    }
150
	}
151
	else if (res == crushed)
152
	{
153
	    switch(door->type)
154
	    {
155
	      case blazeClose:
156
	      case close:		// DO NOT GO BACK UP!
157
		break;
158
 
159
	      default:
160
		door->direction = 1;
161
		S_StartSound((mobj_t *)&door->sector->soundorg,
162
			     sfx_doropn);
163
		break;
164
	    }
165
	}
166
	break;
167
 
168
      case 1:
169
	// UP
170
	res = T_MovePlane(door->sector,
171
			  door->speed,
172
			  door->topheight,
173
			  false,1,door->direction);
174
 
175
	if (res == pastdest)
176
	{
177
	    switch(door->type)
178
	    {
179
	      case blazeRaise:
180
	      case normal:
181
		door->direction = 0; // wait at top
182
		door->topcountdown = door->topwait;
183
		break;
184
 
185
	      case close30ThenOpen:
186
	      case blazeOpen:
187
	      case open:
188
		door->sector->specialdata = NULL;
189
		P_RemoveThinker (&door->thinker);  // unlink and free
190
		break;
191
 
192
	      default:
193
		break;
194
	    }
195
	}
196
	break;
197
    }
198
}
199
 
200
 
201
//
202
// EV_DoLockedDoor
203
// Move a locked door up/down
204
//
205
 
206
int
207
EV_DoLockedDoor
208
( line_t*	line,
209
  vldoor_e	type,
210
  mobj_t*	thing )
211
{
212
    player_t*	p;
213
 
214
    p = thing->player;
215
 
216
    if (!p)
217
	return 0;
218
 
219
    switch(line->special)
220
    {
221
      case 99:	// Blue Lock
222
      case 133:
223
	if ( !p )
224
	    return 0;
225
	if (!p->cards[it_bluecard] && !p->cards[it_blueskull])
226
	{
227
	    p->message = PD_BLUEO;
228
	    S_StartSound(NULL,sfx_oof);
229
	    return 0;
230
	}
231
	break;
232
 
233
      case 134: // Red Lock
234
      case 135:
235
	if ( !p )
236
	    return 0;
237
	if (!p->cards[it_redcard] && !p->cards[it_redskull])
238
	{
239
	    p->message = PD_REDO;
240
	    S_StartSound(NULL,sfx_oof);
241
	    return 0;
242
	}
243
	break;
244
 
245
      case 136:	// Yellow Lock
246
      case 137:
247
	if ( !p )
248
	    return 0;
249
	if (!p->cards[it_yellowcard] &&
250
	    !p->cards[it_yellowskull])
251
	{
252
	    p->message = PD_YELLOWO;
253
	    S_StartSound(NULL,sfx_oof);
254
	    return 0;
255
	}
256
	break;
257
    }
258
 
259
    return EV_DoDoor(line,type);
260
}
261
 
262
 
263
int
264
EV_DoDoor
265
( line_t*	line,
266
  vldoor_e	type )
267
{
268
    int		secnum,rtn;
269
    sector_t*	sec;
270
    vldoor_t*	door;
271
 
272
    secnum = -1;
273
    rtn = 0;
274
 
275
    while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
276
    {
277
	sec = §ors[secnum];
278
	if (sec->specialdata)
279
	    continue;
280
 
281
 
282
	// new door thinker
283
	rtn = 1;
284
	door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
285
	P_AddThinker (&door->thinker);
286
	sec->specialdata = door;
287
 
288
	door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
289
	door->sector = sec;
290
	door->type = type;
291
	door->topwait = VDOORWAIT;
292
	door->speed = VDOORSPEED;
293
 
294
	switch(type)
295
	{
296
	  case blazeClose:
297
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
298
	    door->topheight -= 4*FRACUNIT;
299
	    door->direction = -1;
300
	    door->speed = VDOORSPEED * 4;
301
	    S_StartSound((mobj_t *)&door->sector->soundorg,
302
			 sfx_bdcls);
303
	    break;
304
 
305
	  case close:
306
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
307
	    door->topheight -= 4*FRACUNIT;
308
	    door->direction = -1;
309
	    S_StartSound((mobj_t *)&door->sector->soundorg,
310
			 sfx_dorcls);
311
	    break;
312
 
313
	  case close30ThenOpen:
314
	    door->topheight = sec->ceilingheight;
315
	    door->direction = -1;
316
	    S_StartSound((mobj_t *)&door->sector->soundorg,
317
			 sfx_dorcls);
318
	    break;
319
 
320
	  case blazeRaise:
321
	  case blazeOpen:
322
	    door->direction = 1;
323
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
324
	    door->topheight -= 4*FRACUNIT;
325
	    door->speed = VDOORSPEED * 4;
326
	    if (door->topheight != sec->ceilingheight)
327
		S_StartSound((mobj_t *)&door->sector->soundorg,
328
			     sfx_bdopn);
329
	    break;
330
 
331
	  case normal:
332
	  case open:
333
	    door->direction = 1;
334
	    door->topheight = P_FindLowestCeilingSurrounding(sec);
335
	    door->topheight -= 4*FRACUNIT;
336
	    if (door->topheight != sec->ceilingheight)
337
		S_StartSound((mobj_t *)&door->sector->soundorg,
338
			     sfx_doropn);
339
	    break;
340
 
341
	  default:
342
	    break;
343
	}
344
 
345
    }
346
    return rtn;
347
}
348
 
349
 
350
//
351
// EV_VerticalDoor : open a door manually, no tag value
352
//
353
void
354
EV_VerticalDoor
355
( line_t*	line,
356
  mobj_t*	thing )
357
{
358
    player_t*	player;
359
    int		secnum;
360
    sector_t*	sec;
361
    vldoor_t*	door;
362
    int		side;
363
 
364
    side = 0;	// only front sides can be used
365
 
366
    //	Check for locks
367
    player = thing->player;
368
 
369
    switch(line->special)
370
    {
371
      case 26: // Blue Lock
372
      case 32:
373
	if ( !player )
374
	    return;
375
 
376
	if (!player->cards[it_bluecard] && !player->cards[it_blueskull])
377
	{
378
	    player->message = PD_BLUEK;
379
	    S_StartSound(NULL,sfx_oof);
380
	    return;
381
	}
382
	break;
383
 
384
      case 27: // Yellow Lock
385
      case 34:
386
	if ( !player )
387
	    return;
388
 
389
	if (!player->cards[it_yellowcard] &&
390
	    !player->cards[it_yellowskull])
391
	{
392
	    player->message = PD_YELLOWK;
393
	    S_StartSound(NULL,sfx_oof);
394
	    return;
395
	}
396
	break;
397
 
398
      case 28: // Red Lock
399
      case 33:
400
	if ( !player )
401
	    return;
402
 
403
	if (!player->cards[it_redcard] && !player->cards[it_redskull])
404
	{
405
	    player->message = PD_REDK;
406
	    S_StartSound(NULL,sfx_oof);
407
	    return;
408
	}
409
	break;
410
    }
411
 
412
    // if the sector has an active thinker, use it
413
    sec = sides[ line->sidenum[side^1]] .sector;
414
    secnum = sec-sectors;
415
 
416
    if (sec->specialdata)
417
    {
418
	door = sec->specialdata;
419
	switch(line->special)
420
	{
421
	  case	1: // ONLY FOR "RAISE" DOORS, NOT "OPEN"s
422
	  case	26:
423
	  case	27:
424
	  case	28:
425
	  case	117:
426
	    if (door->direction == -1)
427
		door->direction = 1;	// go back up
428
	    else
429
	    {
430
		if (!thing->player)
431
		    return;		// JDC: bad guys never close doors
432
 
433
		door->direction = -1;	// start going down immediately
434
	    }
435
	    return;
436
	}
437
    }
438
 
439
    // for proper sound
440
    switch(line->special)
441
    {
442
      case 117:	// BLAZING DOOR RAISE
443
      case 118:	// BLAZING DOOR OPEN
444
	S_StartSound((mobj_t *)&sec->soundorg,sfx_bdopn);
445
	break;
446
 
447
      case 1:	// NORMAL DOOR SOUND
448
      case 31:
449
	S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
450
	break;
451
 
452
      default:	// LOCKED DOOR SOUND
453
	S_StartSound((mobj_t *)&sec->soundorg,sfx_doropn);
454
	break;
455
    }
456
 
457
 
458
    // new door thinker
459
    door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
460
    P_AddThinker (&door->thinker);
461
    sec->specialdata = door;
462
    door->thinker.function.acp1 = (actionf_p1) T_VerticalDoor;
463
    door->sector = sec;
464
    door->direction = 1;
465
    door->speed = VDOORSPEED;
466
    door->topwait = VDOORWAIT;
467
 
468
    switch(line->special)
469
    {
470
      case 1:
471
      case 26:
472
      case 27:
473
      case 28:
474
	door->type = normal;
475
	break;
476
 
477
      case 31:
478
      case 32:
479
      case 33:
480
      case 34:
481
	door->type = open;
482
	line->special = 0;
483
	break;
484
 
485
      case 117:	// blazing door raise
486
	door->type = blazeRaise;
487
	door->speed = VDOORSPEED*4;
488
	break;
489
      case 118:	// blazing door open
490
	door->type = blazeOpen;
491
	line->special = 0;
492
	door->speed = VDOORSPEED*4;
493
	break;
494
    }
495
 
496
    // find the top and bottom of the movement range
497
    door->topheight = P_FindLowestCeilingSurrounding(sec);
498
    door->topheight -= 4*FRACUNIT;
499
}
500
 
501
 
502
//
503
// Spawn a door that closes after 30 seconds
504
//
505
void P_SpawnDoorCloseIn30 (sector_t* sec)
506
{
507
    vldoor_t*	door;
508
 
509
    door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
510
 
511
    P_AddThinker (&door->thinker);
512
 
513
    sec->specialdata = door;
514
    sec->special = 0;
515
 
516
    door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
517
    door->sector = sec;
518
    door->direction = 0;
519
    door->type = normal;
520
    door->speed = VDOORSPEED;
521
    door->topcountdown = 30 * 35;
522
}
523
 
524
//
525
// Spawn a door that opens after 5 minutes
526
//
527
void
528
P_SpawnDoorRaiseIn5Mins
529
( sector_t*	sec,
530
  int		secnum )
531
{
532
    vldoor_t*	door;
533
 
534
    door = Z_Malloc ( sizeof(*door), PU_LEVSPEC, 0);
535
 
536
    P_AddThinker (&door->thinker);
537
 
538
    sec->specialdata = door;
539
    sec->special = 0;
540
 
541
    door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
542
    door->sector = sec;
543
    door->direction = 2;
544
    door->type = raiseIn5Mins;
545
    door->speed = VDOORSPEED;
546
    door->topheight = P_FindLowestCeilingSurrounding(sec);
547
    door->topheight -= 4*FRACUNIT;
548
    door->topwait = VDOORWAIT;
549
    door->topcountdown = 5 * 60 * 35;
550
}
551
 
552
 
553
 
554
// UNUSED
555
// Separate into p_slidoor.c?
556
 
557
#if 0		// ABANDONED TO THE MISTS OF TIME!!!
558
//
559
// EV_SlidingDoor : slide a door horizontally
560
// (animate midtexture, then set noblocking line)
561
//
562
 
563
 
564
slideframe_t slideFrames[MAXSLIDEDOORS];
565
 
566
void P_InitSlidingDoorFrames(void)
567
{
568
    int		i;
569
    int		f1;
570
    int		f2;
571
    int		f3;
572
    int		f4;
573
 
574
    // DOOM II ONLY...
575
    if ( gamemode != commercial)
576
	return;
577
 
578
    for (i = 0;i < MAXSLIDEDOORS; i++)
579
    {
580
	if (!slideFrameNames[i].frontFrame1[0])
581
	    break;
582
 
583
	f1 = R_TextureNumForName(slideFrameNames[i].frontFrame1);
584
	f2 = R_TextureNumForName(slideFrameNames[i].frontFrame2);
585
	f3 = R_TextureNumForName(slideFrameNames[i].frontFrame3);
586
	f4 = R_TextureNumForName(slideFrameNames[i].frontFrame4);
587
 
588
	slideFrames[i].frontFrames[0] = f1;
589
	slideFrames[i].frontFrames[1] = f2;
590
	slideFrames[i].frontFrames[2] = f3;
591
	slideFrames[i].frontFrames[3] = f4;
592
 
593
	f1 = R_TextureNumForName(slideFrameNames[i].backFrame1);
594
	f2 = R_TextureNumForName(slideFrameNames[i].backFrame2);
595
	f3 = R_TextureNumForName(slideFrameNames[i].backFrame3);
596
	f4 = R_TextureNumForName(slideFrameNames[i].backFrame4);
597
 
598
	slideFrames[i].backFrames[0] = f1;
599
	slideFrames[i].backFrames[1] = f2;
600
	slideFrames[i].backFrames[2] = f3;
601
	slideFrames[i].backFrames[3] = f4;
602
    }
603
}
604
 
605
 
606
//
607
// Return index into "slideFrames" array
608
// for which door type to use
609
//
610
int P_FindSlidingDoorType(line_t*	line)
611
{
612
    int		i;
613
    int		val;
614
 
615
    for (i = 0;i < MAXSLIDEDOORS;i++)
616
    {
617
	val = sides[line->sidenum[0]].midtexture;
618
	if (val == slideFrames[i].frontFrames[0])
619
	    return i;
620
    }
621
 
622
    return -1;
623
}
624
 
625
void T_SlidingDoor (slidedoor_t*	door)
626
{
627
    switch(door->status)
628
    {
629
      case sd_opening:
630
	if (!door->timer--)
631
	{
632
	    if (++door->frame == SNUMFRAMES)
633
	    {
634
		// IF DOOR IS DONE OPENING...
635
		sides[door->line->sidenum[0]].midtexture = 0;
636
		sides[door->line->sidenum[1]].midtexture = 0;
637
		door->line->flags &= ML_BLOCKING^0xff;
638
 
639
		if (door->type == sdt_openOnly)
640
		{
641
		    door->frontsector->specialdata = NULL;
642
		    P_RemoveThinker (&door->thinker);
643
		    break;
644
		}
645
 
646
		door->timer = SDOORWAIT;
647
		door->status = sd_waiting;
648
	    }
649
	    else
650
	    {
651
		// IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
652
		door->timer = SWAITTICS;
653
 
654
		sides[door->line->sidenum[0]].midtexture =
655
		    slideFrames[door->whichDoorIndex].
656
		    frontFrames[door->frame];
657
		sides[door->line->sidenum[1]].midtexture =
658
		    slideFrames[door->whichDoorIndex].
659
		    backFrames[door->frame];
660
	    }
661
	}
662
	break;
663
 
664
      case sd_waiting:
665
	// IF DOOR IS DONE WAITING...
666
	if (!door->timer--)
667
	{
668
	    // CAN DOOR CLOSE?
669
	    if (door->frontsector->thinglist != NULL ||
670
		door->backsector->thinglist != NULL)
671
	    {
672
		door->timer = SDOORWAIT;
673
		break;
674
	    }
675
 
676
	    //door->frame = SNUMFRAMES-1;
677
	    door->status = sd_closing;
678
	    door->timer = SWAITTICS;
679
	}
680
	break;
681
 
682
      case sd_closing:
683
	if (!door->timer--)
684
	{
685
	    if (--door->frame < 0)
686
	    {
687
		// IF DOOR IS DONE CLOSING...
688
		door->line->flags |= ML_BLOCKING;
689
		door->frontsector->specialdata = NULL;
690
		P_RemoveThinker (&door->thinker);
691
		break;
692
	    }
693
	    else
694
	    {
695
		// IF DOOR NEEDS TO ANIMATE TO NEXT FRAME...
696
		door->timer = SWAITTICS;
697
 
698
		sides[door->line->sidenum[0]].midtexture =
699
		    slideFrames[door->whichDoorIndex].
700
		    frontFrames[door->frame];
701
		sides[door->line->sidenum[1]].midtexture =
702
		    slideFrames[door->whichDoorIndex].
703
		    backFrames[door->frame];
704
	    }
705
	}
706
	break;
707
    }
708
}
709
 
710
 
711
 
712
void
713
EV_SlidingDoor
714
( line_t*	line,
715
  mobj_t*	thing )
716
{
717
    sector_t*		sec;
718
    slidedoor_t*	door;
719
 
720
    // DOOM II ONLY...
721
    if (gamemode != commercial)
722
	return;
723
 
724
    // Make sure door isn't already being animated
725
    sec = line->frontsector;
726
    door = NULL;
727
    if (sec->specialdata)
728
    {
729
	if (!thing->player)
730
	    return;
731
 
732
	door = sec->specialdata;
733
	if (door->type == sdt_openAndClose)
734
	{
735
	    if (door->status == sd_waiting)
736
		door->status = sd_closing;
737
	}
738
	else
739
	    return;
740
    }
741
 
742
    // Init sliding door vars
743
    if (!door)
744
    {
745
	door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0);
746
	P_AddThinker (&door->thinker);
747
	sec->specialdata = door;
748
 
749
	door->type = sdt_openAndClose;
750
	door->status = sd_opening;
751
	door->whichDoorIndex = P_FindSlidingDoorType(line);
752
 
753
	if (door->whichDoorIndex < 0)
754
	    I_Error("EV_SlidingDoor: Can't use texture for sliding door!");
755
 
756
	door->frontsector = sec;
757
	door->backsector = line->backsector;
758
	door->thinker.function = T_SlidingDoor;
759
	door->timer = SWAITTICS;
760
	door->frame = 0;
761
	door->line = line;
762
    }
763
}
764
#endif