Subversion Repositories Kolibri OS

Rev

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:
20
//	Implements special effects:
21
//	Texture animation, height or lighting changes
22
//	 according to adjacent sectors, respective
23
//	 utility functions, etc.
24
//	Line Tag handling. Line and Sector triggers.
25
//
26
//-----------------------------------------------------------------------------
27
 
28
static const char
29
rcsid[] = "$Id: p_spec.c,v 1.6 1997/02/03 22:45:12 b1 Exp $";
30
 
31
#include 
32
 
33
#include "doomdef.h"
34
#include "doomstat.h"
35
 
36
#include "i_system.h"
37
#include "z_zone.h"
38
#include "m_argv.h"
39
#include "m_random.h"
40
#include "w_wad.h"
41
 
42
#include "r_local.h"
43
#include "p_local.h"
44
 
45
#include "g_game.h"
46
 
47
#include "s_sound.h"
48
 
49
// State.
50
#include "r_state.h"
51
 
52
// Data.
53
#include "sounds.h"
54
 
55
 
56
//
57
// Animating textures and planes
58
// There is another anim_t used in wi_stuff, unrelated.
59
//
60
typedef struct
61
{
62
    boolean	istexture;
63
    int		picnum;
64
    int		basepic;
65
    int		numpics;
66
    int		speed;
67
 
68
} anim_t;
69
 
70
//
71
//      source animation definition
72
//
73
typedef struct
74
{
75
    boolean	istexture;	// if false, it is a flat
76
    char	endname[9];
77
    char	startname[9];
78
    int		speed;
79
} animdef_t;
80
 
81
 
82
 
83
#define MAXANIMS                32
84
 
85
extern anim_t	anims[MAXANIMS];
86
extern anim_t*	lastanim;
87
 
88
//
89
// P_InitPicAnims
90
//
91
 
92
// Floor/ceiling animation sequences,
93
//  defined by first and last frame,
94
//  i.e. the flat (64x64 tile) name to
95
//  be used.
96
// The full animation sequence is given
97
//  using all the flats between the start
98
//  and end entry, in the order found in
99
//  the WAD file.
100
//
101
animdef_t		animdefs[] =
102
{
103
    {false,	"NUKAGE3",	"NUKAGE1",	8},
104
    {false,	"FWATER4",	"FWATER1",	8},
105
    {false,	"SWATER4",	"SWATER1", 	8},
106
    {false,	"LAVA4",	"LAVA1",	8},
107
    {false,	"BLOOD3",	"BLOOD1",	8},
108
 
109
    // DOOM II flat animations.
110
    {false,	"RROCK08",	"RROCK05",	8},
111
    {false,	"SLIME04",	"SLIME01",	8},
112
    {false,	"SLIME08",	"SLIME05",	8},
113
    {false,	"SLIME12",	"SLIME09",	8},
114
 
115
    {true,	"BLODGR4",	"BLODGR1",	8},
116
    {true,	"SLADRIP3",	"SLADRIP1",	8},
117
 
118
    {true,	"BLODRIP4",	"BLODRIP1",	8},
119
    {true,	"FIREWALL",	"FIREWALA",	8},
120
    {true,	"GSTFONT3",	"GSTFONT1",	8},
121
    {true,	"FIRELAVA",	"FIRELAV3",	8},
122
    {true,	"FIREMAG3",	"FIREMAG1",	8},
123
    {true,	"FIREBLU2",	"FIREBLU1",	8},
124
    {true,	"ROCKRED3",	"ROCKRED1",	8},
125
 
126
    {true,	"BFALL4",	"BFALL1",	8},
127
    {true,	"SFALL4",	"SFALL1",	8},
128
    {true,	"WFALL4",	"WFALL1",	8},
129
    {true,	"DBRAIN4",	"DBRAIN1",	8},
130
 
131
    {-1}
132
};
133
 
134
anim_t		anims[MAXANIMS];
135
anim_t*		lastanim;
136
 
137
 
138
//
139
//      Animating line specials
140
//
141
#define MAXLINEANIMS            64
142
 
143
extern  short	numlinespecials;
144
extern  line_t*	linespeciallist[MAXLINEANIMS];
145
 
146
 
147
 
148
void P_InitPicAnims (void)
149
{
150
    int		i;
151
 
152
 
153
    //	Init animation
154
    lastanim = anims;
155
    for (i=0 ; animdefs[i].istexture != -1 ; i++)
156
    {
157
	if (animdefs[i].istexture)
158
	{
159
	    // different episode ?
160
	    if (R_CheckTextureNumForName(animdefs[i].startname) == -1)
161
		continue;
162
 
163
	    lastanim->picnum = R_TextureNumForName (animdefs[i].endname);
164
	    lastanim->basepic = R_TextureNumForName (animdefs[i].startname);
165
	}
166
	else
167
	{
168
	    if (W_CheckNumForName(animdefs[i].startname) == -1)
169
		continue;
170
 
171
	    lastanim->picnum = R_FlatNumForName (animdefs[i].endname);
172
	    lastanim->basepic = R_FlatNumForName (animdefs[i].startname);
173
	}
174
 
175
	lastanim->istexture = animdefs[i].istexture;
176
	lastanim->numpics = lastanim->picnum - lastanim->basepic + 1;
177
 
178
	if (lastanim->numpics < 2)
179
	    I_Error ("P_InitPicAnims: bad cycle from %s to %s",
180
		     animdefs[i].startname,
181
		     animdefs[i].endname);
182
 
183
	lastanim->speed = animdefs[i].speed;
184
	lastanim++;
185
    }
186
 
187
}
188
 
189
 
190
 
191
//
192
// UTILITIES
193
//
194
 
195
 
196
 
197
//
198
// getSide()
199
// Will return a side_t*
200
//  given the number of the current sector,
201
//  the line number, and the side (0/1) that you want.
202
//
203
side_t*
204
getSide
205
( int		currentSector,
206
  int		line,
207
  int		side )
208
{
209
    return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ];
210
}
211
 
212
 
213
//
214
// getSector()
215
// Will return a sector_t*
216
//  given the number of the current sector,
217
//  the line number and the side (0/1) that you want.
218
//
219
sector_t*
220
getSector
221
( int		currentSector,
222
  int		line,
223
  int		side )
224
{
225
    return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector;
226
}
227
 
228
 
229
//
230
// twoSided()
231
// Given the sector number and the line number,
232
//  it will tell you whether the line is two-sided or not.
233
//
234
int
235
twoSided
236
( int	sector,
237
  int	line )
238
{
239
    return (sectors[sector].lines[line])->flags & ML_TWOSIDED;
240
}
241
 
242
 
243
 
244
 
245
//
246
// getNextSector()
247
// Return sector_t * of sector next to current.
248
// NULL if not two-sided line
249
//
250
sector_t*
251
getNextSector
252
( line_t*	line,
253
  sector_t*	sec )
254
{
255
    if (!(line->flags & ML_TWOSIDED))
256
	return NULL;
257
 
258
    if (line->frontsector == sec)
259
	return line->backsector;
260
 
261
    return line->frontsector;
262
}
263
 
264
 
265
 
266
//
267
// P_FindLowestFloorSurrounding()
268
// FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS
269
//
270
fixed_t	P_FindLowestFloorSurrounding(sector_t* sec)
271
{
272
    int			i;
273
    line_t*		check;
274
    sector_t*		other;
275
    fixed_t		floor = sec->floorheight;
276
 
277
    for (i=0 ;i < sec->linecount ; i++)
278
    {
279
	check = sec->lines[i];
280
	other = getNextSector(check,sec);
281
 
282
	if (!other)
283
	    continue;
284
 
285
	if (other->floorheight < floor)
286
	    floor = other->floorheight;
287
    }
288
    return floor;
289
}
290
 
291
 
292
 
293
//
294
// P_FindHighestFloorSurrounding()
295
// FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS
296
//
297
fixed_t	P_FindHighestFloorSurrounding(sector_t *sec)
298
{
299
    int			i;
300
    line_t*		check;
301
    sector_t*		other;
302
    fixed_t		floor = -500*FRACUNIT;
303
 
304
    for (i=0 ;i < sec->linecount ; i++)
305
    {
306
	check = sec->lines[i];
307
	other = getNextSector(check,sec);
308
 
309
	if (!other)
310
	    continue;
311
 
312
	if (other->floorheight > floor)
313
	    floor = other->floorheight;
314
    }
315
    return floor;
316
}
317
 
318
 
319
 
320
//
321
// P_FindNextHighestFloor
322
// FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS
323
// Note: this should be doable w/o a fixed array.
324
 
325
// 20 adjoining sectors max!
326
#define MAX_ADJOINING_SECTORS    	20
327
 
328
fixed_t
329
P_FindNextHighestFloor
330
( sector_t*	sec,
331
  int		currentheight )
332
{
333
    int			i;
334
    int			h;
335
    int			min;
336
    line_t*		check;
337
    sector_t*		other;
338
    fixed_t		height = currentheight;
339
 
340
 
341
    fixed_t		heightlist[MAX_ADJOINING_SECTORS];
342
 
343
    for (i=0, h=0 ;i < sec->linecount ; i++)
344
    {
345
	check = sec->lines[i];
346
	other = getNextSector(check,sec);
347
 
348
	if (!other)
349
	    continue;
350
 
351
	if (other->floorheight > height)
352
	    heightlist[h++] = other->floorheight;
353
 
354
	// Check for overflow. Exit.
355
	if ( h >= MAX_ADJOINING_SECTORS )
356
	{
357
//	    __libclog_printf("Sector with more than 20 adjoining sectors\n" );
358
	    break;
359
	}
360
    }
361
 
362
    // Find lowest height in list
363
    if (!h)
364
	return currentheight;
365
 
366
    min = heightlist[0];
367
 
368
    // Range checking?
369
    for (i = 1;i < h;i++)
370
	if (heightlist[i] < min)
371
	    min = heightlist[i];
372
 
373
    return min;
374
}
375
 
376
 
377
//
378
// FIND LOWEST CEILING IN THE SURROUNDING SECTORS
379
//
380
fixed_t
381
P_FindLowestCeilingSurrounding(sector_t* sec)
382
{
383
    int			i;
384
    line_t*		check;
385
    sector_t*		other;
386
    fixed_t		height = MAXINT;
387
 
388
    for (i=0 ;i < sec->linecount ; i++)
389
    {
390
	check = sec->lines[i];
391
	other = getNextSector(check,sec);
392
 
393
	if (!other)
394
	    continue;
395
 
396
	if (other->ceilingheight < height)
397
	    height = other->ceilingheight;
398
    }
399
    return height;
400
}
401
 
402
 
403
//
404
// FIND HIGHEST CEILING IN THE SURROUNDING SECTORS
405
//
406
fixed_t	P_FindHighestCeilingSurrounding(sector_t* sec)
407
{
408
    int		i;
409
    line_t*	check;
410
    sector_t*	other;
411
    fixed_t	height = 0;
412
 
413
    for (i=0 ;i < sec->linecount ; i++)
414
    {
415
	check = sec->lines[i];
416
	other = getNextSector(check,sec);
417
 
418
	if (!other)
419
	    continue;
420
 
421
	if (other->ceilingheight > height)
422
	    height = other->ceilingheight;
423
    }
424
    return height;
425
}
426
 
427
 
428
 
429
//
430
// RETURN NEXT SECTOR # THAT LINE TAG REFERS TO
431
//
432
int
433
P_FindSectorFromLineTag
434
( line_t*	line,
435
  int		start )
436
{
437
    int	i;
438
 
439
    for (i=start+1;i
440
	if (sectors[i].tag == line->tag)
441
	    return i;
442
 
443
    return -1;
444
}
445
 
446
 
447
 
448
 
449
//
450
// Find minimum light from an adjacent sector
451
//
452
int
453
P_FindMinSurroundingLight
454
( sector_t*	sector,
455
  int		max )
456
{
457
    int		i;
458
    int		min;
459
    line_t*	line;
460
    sector_t*	check;
461
 
462
    min = max;
463
    for (i=0 ; i < sector->linecount ; i++)
464
    {
465
	line = sector->lines[i];
466
	check = getNextSector(line,sector);
467
 
468
	if (!check)
469
	    continue;
470
 
471
	if (check->lightlevel < min)
472
	    min = check->lightlevel;
473
    }
474
    return min;
475
}
476
 
477
 
478
 
479
//
480
// EVENTS
481
// Events are operations triggered by using, crossing,
482
// or shooting special lines, or by timed thinkers.
483
//
484
 
485
//
486
// P_CrossSpecialLine - TRIGGER
487
// Called every time a thing origin is about
488
//  to cross a line with a non 0 special.
489
//
490
void
491
P_CrossSpecialLine
492
( int		linenum,
493
  int		side,
494
  mobj_t*	thing )
495
{
496
    line_t*	line;
497
    int		ok;
498
 
499
    line = &lines[linenum];
500
 
501
    //	Triggers that other things can activate
502
    if (!thing->player)
503
    {
504
	// Things that should NOT trigger specials...
505
	switch(thing->type)
506
	{
507
	  case MT_ROCKET:
508
	  case MT_PLASMA:
509
	  case MT_BFG:
510
	  case MT_TROOPSHOT:
511
	  case MT_HEADSHOT:
512
	  case MT_BRUISERSHOT:
513
	    return;
514
	    break;
515
 
516
	  default: break;
517
	}
518
 
519
	ok = 0;
520
	switch(line->special)
521
	{
522
	  case 39:	// TELEPORT TRIGGER
523
	  case 97:	// TELEPORT RETRIGGER
524
	  case 125:	// TELEPORT MONSTERONLY TRIGGER
525
	  case 126:	// TELEPORT MONSTERONLY RETRIGGER
526
	  case 4:	// RAISE DOOR
527
	  case 10:	// PLAT DOWN-WAIT-UP-STAY TRIGGER
528
	  case 88:	// PLAT DOWN-WAIT-UP-STAY RETRIGGER
529
	    ok = 1;
530
	    break;
531
	}
532
	if (!ok)
533
	    return;
534
    }
535
 
536
 
537
    // Note: could use some const's here.
538
    switch (line->special)
539
    {
540
	// TRIGGERS.
541
	// All from here to RETRIGGERS.
542
      case 2:
543
	// Open Door
544
	EV_DoDoor(line,open);
545
	line->special = 0;
546
	break;
547
 
548
      case 3:
549
	// Close Door
550
	EV_DoDoor(line,close);
551
	line->special = 0;
552
	break;
553
 
554
      case 4:
555
	// Raise Door
556
	EV_DoDoor(line,normal);
557
	line->special = 0;
558
	break;
559
 
560
      case 5:
561
	// Raise Floor
562
	EV_DoFloor(line,raiseFloor);
563
	line->special = 0;
564
	break;
565
 
566
      case 6:
567
	// Fast Ceiling Crush & Raise
568
	EV_DoCeiling(line,fastCrushAndRaise);
569
	line->special = 0;
570
	break;
571
 
572
      case 8:
573
	// Build Stairs
574
	EV_BuildStairs(line,build8);
575
	line->special = 0;
576
	break;
577
 
578
      case 10:
579
	// PlatDownWaitUp
580
	EV_DoPlat(line,downWaitUpStay,0);
581
	line->special = 0;
582
	break;
583
 
584
      case 12:
585
	// Light Turn On - brightest near
586
	EV_LightTurnOn(line,0);
587
	line->special = 0;
588
	break;
589
 
590
      case 13:
591
	// Light Turn On 255
592
	EV_LightTurnOn(line,255);
593
	line->special = 0;
594
	break;
595
 
596
      case 16:
597
	// Close Door 30
598
	EV_DoDoor(line,close30ThenOpen);
599
	line->special = 0;
600
	break;
601
 
602
      case 17:
603
	// Start Light Strobing
604
	EV_StartLightStrobing(line);
605
	line->special = 0;
606
	break;
607
 
608
      case 19:
609
	// Lower Floor
610
	EV_DoFloor(line,lowerFloor);
611
	line->special = 0;
612
	break;
613
 
614
      case 22:
615
	// Raise floor to nearest height and change texture
616
	EV_DoPlat(line,raiseToNearestAndChange,0);
617
	line->special = 0;
618
	break;
619
 
620
      case 25:
621
	// Ceiling Crush and Raise
622
	EV_DoCeiling(line,crushAndRaise);
623
	line->special = 0;
624
	break;
625
 
626
      case 30:
627
	// Raise floor to shortest texture height
628
	//  on either side of lines.
629
	EV_DoFloor(line,raiseToTexture);
630
	line->special = 0;
631
	break;
632
 
633
      case 35:
634
	// Lights Very Dark
635
	EV_LightTurnOn(line,35);
636
	line->special = 0;
637
	break;
638
 
639
      case 36:
640
	// Lower Floor (TURBO)
641
	EV_DoFloor(line,turboLower);
642
	line->special = 0;
643
	break;
644
 
645
      case 37:
646
	// LowerAndChange
647
	EV_DoFloor(line,lowerAndChange);
648
	line->special = 0;
649
	break;
650
 
651
      case 38:
652
	// Lower Floor To Lowest
653
	EV_DoFloor( line, lowerFloorToLowest );
654
	line->special = 0;
655
	break;
656
 
657
      case 39:
658
	// TELEPORT!
659
	EV_Teleport( line, side, thing );
660
	line->special = 0;
661
	break;
662
 
663
      case 40:
664
	// RaiseCeilingLowerFloor
665
	EV_DoCeiling( line, raiseToHighest );
666
	EV_DoFloor( line, lowerFloorToLowest );
667
	line->special = 0;
668
	break;
669
 
670
      case 44:
671
	// Ceiling Crush
672
	EV_DoCeiling( line, lowerAndCrush );
673
	line->special = 0;
674
	break;
675
 
676
      case 52:
677
	// EXIT!
678
	G_ExitLevel ();
679
	break;
680
 
681
      case 53:
682
	// Perpetual Platform Raise
683
	EV_DoPlat(line,perpetualRaise,0);
684
	line->special = 0;
685
	break;
686
 
687
      case 54:
688
	// Platform Stop
689
	EV_StopPlat(line);
690
	line->special = 0;
691
	break;
692
 
693
      case 56:
694
	// Raise Floor Crush
695
	EV_DoFloor(line,raiseFloorCrush);
696
	line->special = 0;
697
	break;
698
 
699
      case 57:
700
	// Ceiling Crush Stop
701
	EV_CeilingCrushStop(line);
702
	line->special = 0;
703
	break;
704
 
705
      case 58:
706
	// Raise Floor 24
707
	EV_DoFloor(line,raiseFloor24);
708
	line->special = 0;
709
	break;
710
 
711
      case 59:
712
	// Raise Floor 24 And Change
713
	EV_DoFloor(line,raiseFloor24AndChange);
714
	line->special = 0;
715
	break;
716
 
717
      case 104:
718
	// Turn lights off in sector(tag)
719
	EV_TurnTagLightsOff(line);
720
	line->special = 0;
721
	break;
722
 
723
      case 108:
724
	// Blazing Door Raise (faster than TURBO!)
725
	EV_DoDoor (line,blazeRaise);
726
	line->special = 0;
727
	break;
728
 
729
      case 109:
730
	// Blazing Door Open (faster than TURBO!)
731
	EV_DoDoor (line,blazeOpen);
732
	line->special = 0;
733
	break;
734
 
735
      case 100:
736
	// Build Stairs Turbo 16
737
	EV_BuildStairs(line,turbo16);
738
	line->special = 0;
739
	break;
740
 
741
      case 110:
742
	// Blazing Door Close (faster than TURBO!)
743
	EV_DoDoor (line,blazeClose);
744
	line->special = 0;
745
	break;
746
 
747
      case 119:
748
	// Raise floor to nearest surr. floor
749
	EV_DoFloor(line,raiseFloorToNearest);
750
	line->special = 0;
751
	break;
752
 
753
      case 121:
754
	// Blazing PlatDownWaitUpStay
755
	EV_DoPlat(line,blazeDWUS,0);
756
	line->special = 0;
757
	break;
758
 
759
      case 124:
760
	// Secret EXIT
761
	G_SecretExitLevel ();
762
	break;
763
 
764
      case 125:
765
	// TELEPORT MonsterONLY
766
	if (!thing->player)
767
	{
768
	    EV_Teleport( line, side, thing );
769
	    line->special = 0;
770
	}
771
	break;
772
 
773
      case 130:
774
	// Raise Floor Turbo
775
	EV_DoFloor(line,raiseFloorTurbo);
776
	line->special = 0;
777
	break;
778
 
779
      case 141:
780
	// Silent Ceiling Crush & Raise
781
	EV_DoCeiling(line,silentCrushAndRaise);
782
	line->special = 0;
783
	break;
784
 
785
	// RETRIGGERS.  All from here till end.
786
      case 72:
787
	// Ceiling Crush
788
	EV_DoCeiling( line, lowerAndCrush );
789
	break;
790
 
791
      case 73:
792
	// Ceiling Crush and Raise
793
	EV_DoCeiling(line,crushAndRaise);
794
	break;
795
 
796
      case 74:
797
	// Ceiling Crush Stop
798
	EV_CeilingCrushStop(line);
799
	break;
800
 
801
      case 75:
802
	// Close Door
803
	EV_DoDoor(line,close);
804
	break;
805
 
806
      case 76:
807
	// Close Door 30
808
	EV_DoDoor(line,close30ThenOpen);
809
	break;
810
 
811
      case 77:
812
	// Fast Ceiling Crush & Raise
813
	EV_DoCeiling(line,fastCrushAndRaise);
814
	break;
815
 
816
      case 79:
817
	// Lights Very Dark
818
	EV_LightTurnOn(line,35);
819
	break;
820
 
821
      case 80:
822
	// Light Turn On - brightest near
823
	EV_LightTurnOn(line,0);
824
	break;
825
 
826
      case 81:
827
	// Light Turn On 255
828
	EV_LightTurnOn(line,255);
829
	break;
830
 
831
      case 82:
832
	// Lower Floor To Lowest
833
	EV_DoFloor( line, lowerFloorToLowest );
834
	break;
835
 
836
      case 83:
837
	// Lower Floor
838
	EV_DoFloor(line,lowerFloor);
839
	break;
840
 
841
      case 84:
842
	// LowerAndChange
843
	EV_DoFloor(line,lowerAndChange);
844
	break;
845
 
846
      case 86:
847
	// Open Door
848
	EV_DoDoor(line,open);
849
	break;
850
 
851
      case 87:
852
	// Perpetual Platform Raise
853
	EV_DoPlat(line,perpetualRaise,0);
854
	break;
855
 
856
      case 88:
857
	// PlatDownWaitUp
858
	EV_DoPlat(line,downWaitUpStay,0);
859
	break;
860
 
861
      case 89:
862
	// Platform Stop
863
	EV_StopPlat(line);
864
	break;
865
 
866
      case 90:
867
	// Raise Door
868
	EV_DoDoor(line,normal);
869
	break;
870
 
871
      case 91:
872
	// Raise Floor
873
	EV_DoFloor(line,raiseFloor);
874
	break;
875
 
876
      case 92:
877
	// Raise Floor 24
878
	EV_DoFloor(line,raiseFloor24);
879
	break;
880
 
881
      case 93:
882
	// Raise Floor 24 And Change
883
	EV_DoFloor(line,raiseFloor24AndChange);
884
	break;
885
 
886
      case 94:
887
	// Raise Floor Crush
888
	EV_DoFloor(line,raiseFloorCrush);
889
	break;
890
 
891
      case 95:
892
	// Raise floor to nearest height
893
	// and change texture.
894
	EV_DoPlat(line,raiseToNearestAndChange,0);
895
	break;
896
 
897
      case 96:
898
	// Raise floor to shortest texture height
899
	// on either side of lines.
900
	EV_DoFloor(line,raiseToTexture);
901
	break;
902
 
903
      case 97:
904
	// TELEPORT!
905
	EV_Teleport( line, side, thing );
906
	break;
907
 
908
      case 98:
909
	// Lower Floor (TURBO)
910
	EV_DoFloor(line,turboLower);
911
	break;
912
 
913
      case 105:
914
	// Blazing Door Raise (faster than TURBO!)
915
	EV_DoDoor (line,blazeRaise);
916
	break;
917
 
918
      case 106:
919
	// Blazing Door Open (faster than TURBO!)
920
	EV_DoDoor (line,blazeOpen);
921
	break;
922
 
923
      case 107:
924
	// Blazing Door Close (faster than TURBO!)
925
	EV_DoDoor (line,blazeClose);
926
	break;
927
 
928
      case 120:
929
	// Blazing PlatDownWaitUpStay.
930
	EV_DoPlat(line,blazeDWUS,0);
931
	break;
932
 
933
      case 126:
934
	// TELEPORT MonsterONLY.
935
	if (!thing->player)
936
	    EV_Teleport( line, side, thing );
937
	break;
938
 
939
      case 128:
940
	// Raise To Nearest Floor
941
	EV_DoFloor(line,raiseFloorToNearest);
942
	break;
943
 
944
      case 129:
945
	// Raise Floor Turbo
946
	EV_DoFloor(line,raiseFloorTurbo);
947
	break;
948
    }
949
}
950
 
951
 
952
 
953
//
954
// P_ShootSpecialLine - IMPACT SPECIALS
955
// Called when a thing shoots a special line.
956
//
957
void
958
P_ShootSpecialLine
959
( mobj_t*	thing,
960
  line_t*	line )
961
{
962
    int		ok;
963
 
964
    //	Impacts that other things can activate.
965
    if (!thing->player)
966
    {
967
	ok = 0;
968
	switch(line->special)
969
	{
970
	  case 46:
971
	    // OPEN DOOR IMPACT
972
	    ok = 1;
973
	    break;
974
	}
975
	if (!ok)
976
	    return;
977
    }
978
 
979
    switch(line->special)
980
    {
981
      case 24:
982
	// RAISE FLOOR
983
	EV_DoFloor(line,raiseFloor);
984
	P_ChangeSwitchTexture(line,0);
985
	break;
986
 
987
      case 46:
988
	// OPEN DOOR
989
	EV_DoDoor(line,open);
990
	P_ChangeSwitchTexture(line,1);
991
	break;
992
 
993
      case 47:
994
	// RAISE FLOOR NEAR AND CHANGE
995
	EV_DoPlat(line,raiseToNearestAndChange,0);
996
	P_ChangeSwitchTexture(line,0);
997
	break;
998
    }
999
}
1000
 
1001
 
1002
 
1003
//
1004
// P_PlayerInSpecialSector
1005
// Called every tic frame
1006
//  that the player origin is in a special sector
1007
//
1008
void P_PlayerInSpecialSector (player_t* player)
1009
{
1010
    sector_t*	sector;
1011
 
1012
    sector = player->mo->subsector->sector;
1013
 
1014
    // Falling, not all the way down yet?
1015
    if (player->mo->z != sector->floorheight)
1016
	return;
1017
 
1018
    // Has hitten ground.
1019
    switch (sector->special)
1020
    {
1021
      case 5:
1022
	// HELLSLIME DAMAGE
1023
	if (!player->powers[pw_ironfeet])
1024
	    if (!(leveltime&0x1f))
1025
		P_DamageMobj (player->mo, NULL, NULL, 10);
1026
	break;
1027
 
1028
      case 7:
1029
	// NUKAGE DAMAGE
1030
	if (!player->powers[pw_ironfeet])
1031
	    if (!(leveltime&0x1f))
1032
		P_DamageMobj (player->mo, NULL, NULL, 5);
1033
	break;
1034
 
1035
      case 16:
1036
	// SUPER HELLSLIME DAMAGE
1037
      case 4:
1038
	// STROBE HURT
1039
	if (!player->powers[pw_ironfeet]
1040
	    || (P_Random()<5) )
1041
	{
1042
	    if (!(leveltime&0x1f))
1043
		P_DamageMobj (player->mo, NULL, NULL, 20);
1044
	}
1045
	break;
1046
 
1047
      case 9:
1048
	// SECRET SECTOR
1049
	player->secretcount++;
1050
	sector->special = 0;
1051
	break;
1052
 
1053
      case 11:
1054
	// EXIT SUPER DAMAGE! (for E1M8 finale)
1055
	player->cheats &= ~CF_GODMODE;
1056
 
1057
	if (!(leveltime&0x1f))
1058
	    P_DamageMobj (player->mo, NULL, NULL, 20);
1059
 
1060
	if (player->health <= 10)
1061
	    G_ExitLevel();
1062
	break;
1063
 
1064
      default:
1065
	I_Error ("P_PlayerInSpecialSector: "
1066
		 "unknown special %i",
1067
		 sector->special);
1068
	break;
1069
    };
1070
}
1071
 
1072
 
1073
 
1074
 
1075
//
1076
// P_UpdateSpecials
1077
// Animate planes, scroll walls, etc.
1078
//
1079
boolean		levelTimer;
1080
int		levelTimeCount;
1081
 
1082
void P_UpdateSpecials (void)
1083
{
1084
    anim_t*	anim;
1085
    int		pic;
1086
    int		i;
1087
    line_t*	line;
1088
 
1089
 
1090
    //	LEVEL TIMER
1091
    if (levelTimer == true)
1092
    {
1093
	levelTimeCount--;
1094
	if (!levelTimeCount)
1095
	    G_ExitLevel();
1096
    }
1097
 
1098
    //	ANIMATE FLATS AND TEXTURES GLOBALLY
1099
    for (anim = anims ; anim < lastanim ; anim++)
1100
    {
1101
	for (i=anim->basepic ; ibasepic+anim->numpics ; i++)
1102
	{
1103
	    pic = anim->basepic + ( (leveltime/anim->speed + i)%anim->numpics );
1104
	    if (anim->istexture)
1105
		texturetranslation[i] = pic;
1106
	    else
1107
		flattranslation[i] = pic;
1108
	}
1109
    }
1110
 
1111
 
1112
    //	ANIMATE LINE SPECIALS
1113
    for (i = 0; i < numlinespecials; i++)
1114
    {
1115
	line = linespeciallist[i];
1116
	switch(line->special)
1117
	{
1118
	  case 48:
1119
	    // EFFECT FIRSTCOL SCROLL +
1120
	    sides[line->sidenum[0]].textureoffset += FRACUNIT;
1121
	    break;
1122
	}
1123
    }
1124
 
1125
 
1126
    //	DO BUTTONS
1127
    for (i = 0; i < MAXBUTTONS; i++)
1128
	if (buttonlist[i].btimer)
1129
	{
1130
	    buttonlist[i].btimer--;
1131
	    if (!buttonlist[i].btimer)
1132
	    {
1133
		switch(buttonlist[i].where)
1134
		{
1135
		  case top:
1136
		    sides[buttonlist[i].line->sidenum[0]].toptexture =
1137
			buttonlist[i].btexture;
1138
		    break;
1139
 
1140
		  case middle:
1141
		    sides[buttonlist[i].line->sidenum[0]].midtexture =
1142
			buttonlist[i].btexture;
1143
		    break;
1144
 
1145
		  case bottom:
1146
		    sides[buttonlist[i].line->sidenum[0]].bottomtexture =
1147
			buttonlist[i].btexture;
1148
		    break;
1149
		}
1150
		S_StartSound((mobj_t *)&buttonlist[i].soundorg,sfx_swtchn);
1151
		memset(&buttonlist[i],0,sizeof(button_t));
1152
	    }
1153
	}
1154
 
1155
}
1156
 
1157
 
1158
 
1159
//
1160
// Special Stuff that can not be categorized
1161
//
1162
int EV_DoDonut(line_t*	line)
1163
{
1164
    sector_t*		s1;
1165
    sector_t*		s2;
1166
    sector_t*		s3;
1167
    int			secnum;
1168
    int			rtn;
1169
    int			i;
1170
    floormove_t*	floor;
1171
 
1172
    secnum = -1;
1173
    rtn = 0;
1174
    while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0)
1175
    {
1176
	s1 = §ors[secnum];
1177
 
1178
	// ALREADY MOVING?  IF SO, KEEP GOING...
1179
	if (s1->specialdata)
1180
	    continue;
1181
 
1182
	rtn = 1;
1183
	s2 = getNextSector(s1->lines[0],s1);
1184
	for (i = 0;i < s2->linecount;i++)
1185
	{
1186
	    if ((!s2->lines[i]->flags & ML_TWOSIDED) ||
1187
		(s2->lines[i]->backsector == s1))
1188
		continue;
1189
	    s3 = s2->lines[i]->backsector;
1190
 
1191
	    //	Spawn rising slime
1192
	    floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
1193
	    P_AddThinker (&floor->thinker);
1194
	    s2->specialdata = floor;
1195
	    floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
1196
	    floor->type = donutRaise;
1197
	    floor->crush = false;
1198
	    floor->direction = 1;
1199
	    floor->sector = s2;
1200
	    floor->speed = FLOORSPEED / 2;
1201
	    floor->texture = s3->floorpic;
1202
	    floor->newspecial = 0;
1203
	    floor->floordestheight = s3->floorheight;
1204
 
1205
	    //	Spawn lowering donut-hole
1206
	    floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0);
1207
	    P_AddThinker (&floor->thinker);
1208
	    s1->specialdata = floor;
1209
	    floor->thinker.function.acp1 = (actionf_p1) T_MoveFloor;
1210
	    floor->type = lowerFloor;
1211
	    floor->crush = false;
1212
	    floor->direction = -1;
1213
	    floor->sector = s1;
1214
	    floor->speed = FLOORSPEED / 2;
1215
	    floor->floordestheight = s3->floorheight;
1216
	    break;
1217
	}
1218
    }
1219
    return rtn;
1220
}
1221
 
1222
 
1223
 
1224
//
1225
// SPECIAL SPAWNING
1226
//
1227
 
1228
//
1229
// P_SpawnSpecials
1230
// After the map has been loaded, scan for specials
1231
//  that spawn thinkers
1232
//
1233
short		numlinespecials;
1234
line_t*		linespeciallist[MAXLINEANIMS];
1235
 
1236
 
1237
// Parses command line parameters.
1238
void P_SpawnSpecials (void)
1239
{
1240
    sector_t*	sector;
1241
    int		i;
1242
    int		episode;
1243
 
1244
    episode = 1;
1245
    if (W_CheckNumForName("texture2") >= 0)
1246
	episode = 2;
1247
 
1248
 
1249
    // See if -TIMER needs to be used.
1250
    levelTimer = false;
1251
 
1252
    i = M_CheckParm("-avg");
1253
    if (i && deathmatch)
1254
    {
1255
	levelTimer = true;
1256
	levelTimeCount = 20 * 60 * 35;
1257
    }
1258
 
1259
    i = M_CheckParm("-timer");
1260
    if (i && deathmatch)
1261
    {
1262
	int	time;
1263
	time = atoi(myargv[i+1]) * 60 * 35;
1264
	levelTimer = true;
1265
	levelTimeCount = time;
1266
    }
1267
 
1268
    //	Init special SECTORs.
1269
    sector = sectors;
1270
    for (i=0 ; i
1271
    {
1272
	if (!sector->special)
1273
	    continue;
1274
 
1275
	switch (sector->special)
1276
	{
1277
	  case 1:
1278
	    // FLICKERING LIGHTS
1279
	    P_SpawnLightFlash (sector);
1280
	    break;
1281
 
1282
	  case 2:
1283
	    // STROBE FAST
1284
	    P_SpawnStrobeFlash(sector,FASTDARK,0);
1285
	    break;
1286
 
1287
	  case 3:
1288
	    // STROBE SLOW
1289
	    P_SpawnStrobeFlash(sector,SLOWDARK,0);
1290
	    break;
1291
 
1292
	  case 4:
1293
	    // STROBE FAST/DEATH SLIME
1294
	    P_SpawnStrobeFlash(sector,FASTDARK,0);
1295
	    sector->special = 4;
1296
	    break;
1297
 
1298
	  case 8:
1299
	    // GLOWING LIGHT
1300
	    P_SpawnGlowingLight(sector);
1301
	    break;
1302
	  case 9:
1303
	    // SECRET SECTOR
1304
	    totalsecret++;
1305
	    break;
1306
 
1307
	  case 10:
1308
	    // DOOR CLOSE IN 30 SECONDS
1309
	    P_SpawnDoorCloseIn30 (sector);
1310
	    break;
1311
 
1312
	  case 12:
1313
	    // SYNC STROBE SLOW
1314
	    P_SpawnStrobeFlash (sector, SLOWDARK, 1);
1315
	    break;
1316
 
1317
	  case 13:
1318
	    // SYNC STROBE FAST
1319
	    P_SpawnStrobeFlash (sector, FASTDARK, 1);
1320
	    break;
1321
 
1322
	  case 14:
1323
	    // DOOR RAISE IN 5 MINUTES
1324
	    P_SpawnDoorRaiseIn5Mins (sector, i);
1325
	    break;
1326
 
1327
	  case 17:
1328
	    P_SpawnFireFlicker(sector);
1329
	    break;
1330
	}
1331
    }
1332
 
1333
 
1334
    //	Init line EFFECTs
1335
    numlinespecials = 0;
1336
    for (i = 0;i < numlines; i++)
1337
    {
1338
	switch(lines[i].special)
1339
	{
1340
	  case 48:
1341
	    // EFFECT FIRSTCOL SCROLL+
1342
	    linespeciallist[numlinespecials] = &lines[i];
1343
	    numlinespecials++;
1344
	    break;
1345
	}
1346
    }
1347
 
1348
 
1349
    //	Init other misc stuff
1350
    for (i = 0;i < MAXCEILINGS;i++)
1351
	activeceilings[i] = NULL;
1352
 
1353
    for (i = 0;i < MAXPLATS;i++)
1354
	activeplats[i] = NULL;
1355
 
1356
    for (i = 0;i < MAXBUTTONS;i++)
1357
	memset(&buttonlist[i],0,sizeof(button_t));
1358
 
1359
    // UNUSED: no horizonal sliders.
1360
    //	P_InitSlidingDoorFrames();
1361
}