Subversion Repositories eduke32

Rev

Rev 5207 | Rev 6042 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5196 hendricks2 1
//-------------------------------------------------------------------------
2
/*
3
Copyright (C) 1997, 2005 - 3D Realms Entertainment
4
 
5
This file is part of Shadow Warrior version 1.2
6
 
7
Shadow Warrior is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License
9
as published by the Free Software Foundation; either version 2
10
of the License, or (at your option) any later version.
11
 
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
 
16
See the GNU General Public License for more details.
17
 
18
You should have received a copy of the GNU General Public License
19
along with this program; if not, write to the Free Software
20
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21
 
22
Original Source: 1997 - Frank Maddin and Jim Norwood
23
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24
*/
25
//-------------------------------------------------------------------------
26
 
27
// JSECTOR.C
28
// This is all Jim's programming having to do with sectors.
29
 
30
#include "build.h"
31
 
32
#include "keys.h"
33
#include "names2.h"
34
#include "jnames.h"
35
#include "panel.h"
36
#include "game.h"
37
#include "tags.h"
38
#include "sector.h"
39
#include "player.h"
40
#include "sprite.h"
41
#include "reserve.h"
42
#include "jsector.h"
43
#include "jtags.h"
44
#include "lists.h"
45
#include "pal.h"
46
#include "parent.h"
47
 
48
 
49
// V A R I A B L E   D E C L A R A T I O N S //////////////////////////////////////////////////////
50
 
51
MIRRORTYPE mirror[MAXMIRRORS];
52
 
53
short mirrorcnt; //, floormirrorcnt;
54
//short floormirrorsector[MAXMIRRORS];
5198 hendricks2 55
SWBOOL mirrorinview;
5196 hendricks2 56
 
57
static char tempbuf[/*max(576, */ MAXXDIM /*)*/];
58
 
5198 hendricks2 59
SWBOOL MirrorMoveSkip16 = 0;
5196 hendricks2 60
 
61
// Voxel stuff
5198 hendricks2 62
//SWBOOL bVoxelsOn = TRUE;                  // Turn voxels on by default
63
SWBOOL bSpinBobVoxels = FALSE;            // Do twizzly stuff to voxels, but
5196 hendricks2 64
// not by default
5198 hendricks2 65
SWBOOL bAutoSize = TRUE;                  // Autosizing on/off
5196 hendricks2 66
 
67
//extern int chainnumpages;
68
extern AMB_INFO ambarray[];
69
extern short NormalVisibility;
70
 
71
extern ParentalStruct aVoxelArray[MAXTILES];
72
 
73
// F U N C T I O N S //////////////////////////////////////////////////////////////////////////////
74
 
75
 
76
/////////////////////////////////////////////////////
77
//  SpawnWallSound
78
/////////////////////////////////////////////////////
5198 hendricks2 79
void
5196 hendricks2 80
SpawnWallSound(short sndnum, short i)
81
{
82
    short SpriteNum;
5201 hendricks2 83
    vec3_t mid;
5196 hendricks2 84
    SPRITEp sp;
85
    int handle;
86
 
87
    SpriteNum = COVERinsertsprite(0, STAT_DEFAULT);
88
    if (SpriteNum < 0)
89
        return;
90
 
91
    sp = &sprite[SpriteNum];
92
    sp->cstat = 0;
93
    sp->extra = 0;
94
    // Get wall midpoint for offset in mirror view
5201 hendricks2 95
    mid.x = (wall[i].x + wall[wall[i].point2].x) / 2;
96
    mid.y = (wall[i].y + wall[wall[i].point2].y) / 2;
97
    mid.z = (sector[wall[i].nextsector].ceilingz + sector[wall[i].nextsector].floorz) / 2;
98
    setspritez(SpriteNum, &mid);
5196 hendricks2 99
    sp = &sprite[SpriteNum];
100
 
101
    handle = PlaySound(sndnum, &sp->x, &sp->y, &sp->z, v3df_dontpan | v3df_doppler);
102
    if (handle != -1)
103
        Set3DSoundOwner(SpriteNum);
104
}
105
 
106
short
107
CheckTileSound(short picnum)
108
{
109
    short sndnum = -1;
110
 
111
    switch (picnum)
112
    {
113
    case 163:                           // Sizzly Lava
114
    case 167:
115
        sndnum = DIGI_VOLCANOSTEAM1;
116
        break;
117
    case 175:                           // Flowing Lava
118
        sndnum = DIGI_ERUPTION;
119
        break;
120
    case 179:                           // Bubbly lava
121
        sndnum = DIGI_LAVAFLOW1;
122
        break;
123
    case 300:                           // Water fall tile
124
        sndnum = DIGI_WATERFALL1;
125
        break;
126
    case 334:                           // Teleporter Pad
127
        sndnum = DIGI_ENGROOM1;
128
        break;
129
    case 2690:                          // Jet engine fan
130
        sndnum = DIGI_JET;
131
        break;
132
    case 2672:                          // X-Ray Machine engine
133
        sndnum = DIGI_ENGROOM5;
134
        break;
135
    case 768:                           // Electricity
136
//          sndnum = DIGI_;
137
        break;
138
    case 2714:                          // Pachinko Machine
139
//          sndnum = DIGI_;
140
        break;
141
    case 2782:                          // Telepad
142
        sndnum = DIGI_ENGROOM4;
143
        break;
144
    case 3382:                          // Gears
145
        sndnum = DIGI_ENGROOM5;
146
        break;
147
    case 2801:                          // Computers
148
    case 2804:
149
    case 2807:
150
    case 3352:
151
    case 3385:
152
    case 3389:
153
    case 3393:
154
    case 3397:
155
    case 3401:
156
    case 3405:
157
//          sndnum = DIGI_;
158
        break;
159
    case 3478:                          // Radar screen
160
//          sndnum = DIGI_;
161
        break;
162
    default:
163
        sndnum = -1;
164
        break;
165
    }
166
    return sndnum;
167
}
168
 
169
/////////////////////////////////////////////////////
170
//  Initialize any of my special use sprites
171
/////////////////////////////////////////////////////
172
void
173
JS_SpriteSetup(void)
174
{
175
    SPRITEp sp;
176
    short SpriteNum = 0, NextSprite, ndx;
177
    USERp u;
178
    short i, num;
179
    int handle;
180
 
181
 
182
    TRAVERSE_SPRITE_STAT(headspritestat[0], SpriteNum, NextSprite)
183
    {
184
        short tag;
185
        short bit;
186
 
187
        sp = &sprite[SpriteNum];
188
        tag = sp->hitag;
189
 
190
        // Non static camera. Camera sprite will be drawn!
191
        if (tag == MIRROR_CAM && sprite[SpriteNum].picnum != ST1)
192
        {
193
            // Just change it to static, sprite has all the info I need
194
//          u = SpawnUser(SpriteNum, sp->picnum, NULL);
195
//          RESET(sp->cstat, CSTAT_SPRITE_BLOCK);
196
//          SET(sp->cstat, CSTAT_SPRITE_BLOCK_HITSCAN);
197
            change_sprite_stat(SpriteNum, STAT_SPAWN_SPOT);
198
        }
199
 
200
        switch (sprite[SpriteNum].picnum)
201
        {
202
        case ST1:
203
            if (tag == MIRROR_CAM)
204
            {
205
                // Just change it to static, sprite has all the info I need
206
                // ST1 cameras won't move with SOBJ's!
207
                change_sprite_stat(SpriteNum, STAT_ST1);
208
            }
209
            else if (tag == MIRROR_SPAWNSPOT)
210
            {
211
                // Just change it to static, sprite has all the info I need
212
                change_sprite_stat(SpriteNum, STAT_ST1);
213
            }
214
            else if (tag == AMBIENT_SOUND)
215
            {
216
                change_sprite_stat(SpriteNum, STAT_AMBIENT);
217
                // PlaySound(sp->lotag, &sp->x, &sp->y, &sp->z, v3df_ambient
218
                // | v3df_init | v3df_doppler);
219
            }
220
            else if (tag == TAG_ECHO_SOUND)
221
            {
222
                change_sprite_stat(SpriteNum, STAT_ECHO);
223
            }
224
            else if (tag == TAG_DRIPGEN)
225
            {
226
                ANIMATOR GenerateDrips;
227
 
228
                u = SpawnUser(SpriteNum, 0, NULL);
229
 
230
                ASSERT(u != NULL);
231
                u->RotNum = 0;
232
                u->WaitTics = sp->lotag * 120;
233
 
234
                u->ActorActionFunc = GenerateDrips;
235
 
236
                change_sprite_stat(SpriteNum, STAT_NO_STATE);
237
                SET(sp->cstat, CSTAT_SPRITE_INVISIBLE);
238
            }
239
            break;
240
        // Sprites in editart that should play ambient sounds
241
        // automatically
242
        case 380:
243
        case 396:
244
        case 430:
245
        case 443:
246
        case 512:
247
        case 521:
248
        case 541:
249
        case 2720:
250
        case 3143:
251
        case 3157:
252
            handle = PlaySound(DIGI_FIRE1, &sp->x, &sp->y, &sp->z, v3df_follow|v3df_dontpan|v3df_doppler);
253
            if (handle != -1)
254
                Set3DSoundOwner(SpriteNum);
255
            break;
256
        case 795:
257
        case 880:
258
            handle = PlaySound(DIGI_WATERFLOW1, &sp->x, &sp->y, &sp->z, v3df_follow|v3df_dontpan|v3df_doppler);
259
            if (handle != -1)
260
                Set3DSoundOwner(SpriteNum);
261
            break;
262
        case 460:  // Wind Chimes
263
            handle = PlaySound(79, &sp->x, &sp->y, &sp->z, v3df_ambient | v3df_init
264
                               | v3df_doppler | v3df_follow);
265
            if (handle != -1)
266
                Set3DSoundOwner(SpriteNum);
267
            break;
268
 
269
        }
270
    }
271
    // Check for certain walls to make sounds
272
    for (i = 0; i < numwalls; i++)
273
    {
274
        short picnum;
275
        short sndnum;
276
 
277
 
278
        picnum = wall[i].picnum;
279
 
280
        // Set the don't stick bit for liquid tiles
281
        switch (picnum)
282
        {
283
        case 175:
284
        case 179:
285
        case 300:
286
        case 320:
287
        case 330:
288
        case 352:
289
        case 780:
290
        case 890:
291
        case 2608:
292
        case 2616:
293
            //case 3834:
294
            SET(wall[i].extra, WALLFX_DONT_STICK);
295
            break;
296
        }
297
 
298
#if 0
299
        if ((sndnum = CheckTileSound(picnum)) != -1)
300
        {
301
            SpawnWallSound(sndnum, i);
302
        }
303
        picnum = wall[i].overpicnum;
304
        if ((sndnum = CheckTileSound(picnum)) != -1)
305
        {
306
            SpawnWallSound(sndnum, i);
307
        }
308
#endif
309
    }
310
}
311
 
312
 
313
/////////////////////////////////////////////////////
314
//  Initialize the mirrors
315
/////////////////////////////////////////////////////
316
void
317
JS_InitMirrors(void)
318
{
319
    short startwall, endwall, dasector;
320
    int i, j, k, s, dax, day, daz, dax2, day2;
321
    short SpriteNum = 0, NextSprite;
322
    SPRITEp sp;
323
    static short on_cam = 0;
5198 hendricks2 324
    SWBOOL Found_Cam = FALSE;
5196 hendricks2 325
 
326
 
327
    // Set all the mirror struct values to -1
328
    memset(mirror, 0xFF, sizeof(mirror));
329
 
330
    mirrorinview = FALSE;               // Initially set global mirror flag
331
    // to no mirrors seen
332
 
333
    // Scan wall tags for mirrors
334
    mirrorcnt = 0;
5204 hendricks2 335
    tilesiz[MIRROR].x = 0;
336
    tilesiz[MIRROR].y = 0;
5196 hendricks2 337
 
338
    for (i = 0; i < MAXMIRRORS; i++)
339
    {
5204 hendricks2 340
        tilesiz[i + MIRRORLABEL].x = 0;
341
        tilesiz[i + MIRRORLABEL].y = 0;
5196 hendricks2 342
        mirror[i].campic = -1;
343
        mirror[i].camsprite = -1;
344
        mirror[i].camera = -1;
345
        mirror[i].ismagic = FALSE;
346
    }
347
 
348
    for (i = 0; i < numwalls; i++)
349
    {
350
        s = wall[i].nextsector;
351
        if ((s >= 0) && (wall[i].overpicnum == MIRROR) && (wall[i].cstat & 32))
352
        {
353
            if ((sector[s].floorstat & 1) == 0)
354
            {
355
                wall[i].overpicnum = MIRRORLABEL + mirrorcnt;
356
                wall[i].picnum = MIRRORLABEL + mirrorcnt;
357
                sector[s].ceilingpicnum = MIRRORLABEL + mirrorcnt;
358
                sector[s].floorpicnum = MIRRORLABEL + mirrorcnt;
359
                sector[s].floorstat |= 1;
360
                mirror[mirrorcnt].mirrorwall = i;
361
                mirror[mirrorcnt].mirrorsector = s;
362
                mirror[mirrorcnt].numspawnspots = 0;
363
                mirror[mirrorcnt].ismagic = FALSE;
364
                if (wall[i].lotag == TAG_WALL_MAGIC_MIRROR)
365
                {
366
                    short ii, nextii;
367
                    SPRITEp sp;
368
                    USERp u;
369
 
370
                    mirror[mirrorcnt].ismagic = TRUE;
371
                    Found_Cam = FALSE;
372
                    TRAVERSE_SPRITE_STAT(headspritestat[STAT_ST1], ii, nextii)
373
                    {
374
                        sp = &sprite[ii];
375
                        // if correct type and matches
376
                        if (sp->hitag == MIRROR_CAM && sp->lotag == wall[i].hitag)
377
                        {
378
                            mirror[mirrorcnt].camera = ii;
379
                            // Set up camera varialbes
380
                            SP_TAG5(sp) = sp->ang;      // Set current angle to
381
                            // sprite angle
382
                            Found_Cam = TRUE;
383
                        }
384
                    }
385
 
386
                    ii = nextii = 0;
387
                    TRAVERSE_SPRITE_STAT(headspritestat[STAT_SPAWN_SPOT], ii, nextii)
388
                    {
389
 
390
                        sp = &sprite[ii];
391
 
392
                        // if correct type and matches
393
                        if (sp->hitag == MIRROR_CAM && sp->lotag == wall[i].hitag)
394
                        {
395
                            mirror[mirrorcnt].camera = ii;
396
                            // Set up camera varialbes
397
                            SP_TAG5(sp) = sp->ang;      // Set current angle to
398
                            // sprite angle
399
                            Found_Cam = TRUE;
400
                        }
401
                    }
402
 
403
                    if (!Found_Cam)
404
                    {
405
                        printf("Cound not find the camera view sprite for match %d\n",wall[i].hitag);
406
                        printf("Map Coordinates: x = %d, y = %d\n",wall[i].x,wall[i].y);
407
                        exit(0);
408
                    }
409
 
410
                    Found_Cam = FALSE;
411
                    if (TEST_BOOL1(&sprite[mirror[mirrorcnt].camera]))
412
                    {
413
                        TRAVERSE_SPRITE_STAT(headspritestat[0], SpriteNum, NextSprite)
414
                        {
415
                            sp = &sprite[SpriteNum];
416
                            if (sp->picnum >= CAMSPRITE && sp->picnum < CAMSPRITE + 8 &&
417
                                sp->hitag == wall[i].hitag)
418
                            {
419
                                mirror[mirrorcnt].campic = sp->picnum;
420
                                mirror[mirrorcnt].camsprite = SpriteNum;
421
 
422
                                // JBF: commenting out this line results in the screen in $BULLET being visible
5204 hendricks2 423
                                tilesiz[mirror[mirrorcnt].campic].x = tilesiz[mirror[mirrorcnt].campic].y = 0;
5196 hendricks2 424
 
425
                                Found_Cam = TRUE;
426
                            }
427
                        }
428
 
429
                        if (!Found_Cam)
430
                        {
431
                            printf("Did not find drawtotile for camera number %d\n",mirrorcnt);
432
                            printf("wall[%d].hitag == %d\n",i,wall[i].hitag);
433
                            printf("Map Coordinates: x = %d, y = %d\n",wall[i].x,wall[i].y);
434
                            exit(0);
435
                        }
436
                    }
437
 
438
                    // For magic mirrors, set allowable viewing time to 30
439
                    // secs
440
                    // Base rate is supposed to be 120, but time is double
441
                    // what I expect
442
                    mirror[mirrorcnt].maxtics = 60 * 30;
443
 
444
                }
445
 
446
                mirror[mirrorcnt].mstate = m_normal;
447
 
448
                // Set tics used to none
449
                mirror[mirrorcnt].tics = 0;
450
 
451
                if (mirror[mirrorcnt].ismagic)
452
                {
453
                    //DSPRINTF(ds, "mirror.mirrorwall %d", mirror[mirrorcnt].mirrorwall);
454
                    MONO_PRINT(ds);
455
                    //DSPRINTF(ds, "mirror.mirrorsector %d", mirror[mirrorcnt].mirrorsector);
456
                    MONO_PRINT(ds);
457
                    //DSPRINTF(ds, "mirror.camera %d", mirror[mirrorcnt].camera);
458
                    MONO_PRINT(ds);
459
                }
460
 
461
                mirrorcnt++;
462
                ASSERT(mirrorcnt < MAXMIRRORS);
463
            }
464
            else
465
                wall[i].overpicnum = sector[s].ceilingpicnum;
466
        }
467
    }
468
 
469
    // Invalidate textures in sector behind mirror
470
    for (i = 0; i < mirrorcnt; i++)
471
    {
472
        startwall = sector[mirror[i].mirrorsector].wallptr;
473
        endwall = startwall + sector[mirror[i].mirrorsector].wallnum;
474
        for (j = startwall; j < endwall; j++)
475
        {
476
            wall[j].picnum = MIRROR;
477
            wall[j].overpicnum = MIRROR;
478
        }
479
    }
480
 
481
}                                   // InitMirrors
482
 
483
/////////////////////////////////////////////////////
484
//  Draw a 3d screen to a specific tile
485
/////////////////////////////////////////////////////
486
#if 1
487
void drawroomstotile(int daposx, int daposy, int daposz,
488
                     short daang, int dahoriz, short dacursectnum, short tilenume)
489
{
490
    if (waloff[tilenume] == 0)
491
        loadtile(tilenume);
492
 
493
    PRODUCTION_ASSERT(waloff[tilenume]);
494
 
5204 hendricks2 495
    setviewtotile(tilenume, tilesiz[tilenume].x, tilesiz[tilenume].y);
5196 hendricks2 496
 
497
    drawrooms(daposx, daposy, daposz, daang, dahoriz, dacursectnum);
498
    analyzesprites(daposx, daposy, daposz, FALSE);
499
    drawmasks();
500
 
501
    setviewback();
502
 
503
    squarerotatetile(tilenume);
504
 
505
    invalidatetile(tilenume, -1, -1);
506
}
507
#else
508
void
509
drawroomstotile(int daposx, int daposy, int daposz,
510
                short daang, int dahoriz, short dacursectnum, short tilenume)
511
{
512
 
513
    int i, j, k, bakchainnumpages, bakvidoption;
514
    intptr_t bakframeplace;
5984 hendricks2 515
    vec2_t bakwindowxy1, bakwindowxy2;
516
    int xsiz, ysiz;
5196 hendricks2 517
    char *ptr1, *ptr2;
518
 
519
    // DRAWROOMS TO TILE BACKUP&SET CODE
5204 hendricks2 520
    xsiz = tilesiz[tilenume].x;
521
    ysiz = tilesiz[tilenume].y;
5196 hendricks2 522
    // bakchainnumpages = chainnumpages;
523
    bakchainnumpages = numpages;
524
    // chainnumpages = 0;
525
    numpages = 0;
526
    bakvidoption = vidoption;
527
    vidoption = 1;
528
    if (waloff[tilenume] == 0)
529
        loadtile(tilenume);
530
    bakframeplace = frameplace;
531
    frameplace = waloff[tilenume];
5984 hendricks2 532
    bakwindowxy1 = windowxy1;
533
    bakwindowxy2 = windowxy2;
5196 hendricks2 534
    setview(0, 0, xsiz - 1, ysiz - 1);
535
    setvlinebpl(xsiz);
536
    j = 0;
537
    for (i = 0; i <= ysiz; i++)
538
    {
539
        ylookup[i] = j, j += xsiz;
540
    }
541
 
542
    // DRAWS TO TILE HERE
543
    drawrooms(daposx, daposy, daposz, daang, dahoriz, dacursectnum + MAXSECTORS);
544
    analyzesprites(daposx, daposy, daposz, FALSE);
545
    drawmasks();
546
 
547
    setviewback();
548
 
549
    // ROTATE TILE (supports square tiles only for rotation part)
550
    if (xsiz == ysiz)
551
    {
552
        k = (xsiz << 1);
553
        for (i = xsiz - 1; i >= 0; i--)
554
        {
555
            ptr1 = (char *)(waloff[tilenume] + i * (xsiz + 1));
556
            ptr2 = ptr1;
557
            if ((i & 1) != 0)
558
            {
559
                ptr1--;
560
                ptr2 -= xsiz;
561
                swapchar(ptr1, ptr2);
562
            }
563
            for (j = (i >> 1) - 1; j >= 0; j--)
564
            {
565
                ptr1 -= 2;
566
                ptr2 -= k;
567
                swapchar2(ptr1, ptr2, xsiz);
568
                // swapchar(ptr1,ptr2);
569
                // swapchar(ptr1+1,ptr2+xsiz);
570
            }
571
        }
572
    }
573
 
574
    // DRAWROOMS TO TILE RESTORE CODE
5984 hendricks2 575
    setview(bakwindowxy1.x, bakwindowxy1.y, bakwindowxy2.x, bakwindowxy2.y);
5196 hendricks2 576
    // chainnumpages = bakchainnumpages;
577
    numpages = bakchainnumpages;
578
    vidoption = bakvidoption;
579
    frameplace = bakframeplace;
580
    j = 0;
581
    // if (chainnumpages >= 2)
582
    if (numpages >= 2)
583
    {
584
        for (i = 0; i <= ysiz; i++)
585
            ylookup[i] = j, j += (xdim >> 2);
586
    }
587
    else
588
    {
589
        for (i = 0; i <= ysiz; i++)
590
            ylookup[i] = j, j += xdim;
591
    }
592
    setvlinebpl(ylookup[1]);
593
}
594
#endif
595
 
596
void
597
JS_ProcessEchoSpot()
598
{
599
    short i,nexti;
600
    SPRITEp tp;
601
    int j,dist;
602
    PLAYERp pp = Player+screenpeek;
5198 hendricks2 603
    int16_t reverb;
604
    SWBOOL reverb_set = FALSE;
5196 hendricks2 605
 
606
    // Process echo sprites
607
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_ECHO], i, nexti)
608
    {
609
        dist = 0x7fffffff;
610
 
611
        tp = &sprite[i];
612
 
613
        j = klabs(tp->x - pp->posx);
614
        j += klabs(tp->y - pp->posy);
615
        if (j < dist)
616
            dist = j;
617
 
618
        if (dist <= SP_TAG4(tp)) // tag4 = ang
619
        {
620
            reverb = SP_TAG2(tp);
621
            if (reverb > 200) reverb = 200;
622
            if (reverb < 100) reverb = 100;
623
 
624
            COVER_SetReverb(reverb);
625
            reverb_set = TRUE;
626
        }
627
    }
628
    if (!TEST(pp->Flags, PF_DIVING) && !reverb_set && pp->Reverb <= 0)
629
        COVER_SetReverb(0);
630
}
631
 
632
/////////////////////////////////////////////////////
633
//  Draw one mirror, the one closest to player
634
//  Cams and see to teleporters do NOT support room above room!
635
/////////////////////////////////////////////////////
636
#define MAXCAMDIST 8000
637
 
638
int camloopcnt = 0;                    // Timer to cycle through player
639
// views
640
short camplayerview = 1;                // Don't show yourself!
641
 
642
void
643
JS_DrawMirrors(PLAYERp pp, int tx, int ty, int tz, short tpang, int tphoriz)
644
{
645
    int j, dx, dy, top, bot, cnt;
646
    int x1, y1, x2, y2, ox1, oy1, ox2, oy2, dist, maxdist;
647
    int tposx, tposy, thoriz;
648
    int tcx, tcy, tcz;                 // Camera
649
    int tiltlock, *longptr;
650
    short tang;
651
    char ch, *ptr, *ptr2, *ptr3, *ptr4;
652
    char tvisibility, palok;
653
 
654
//    long tx, ty, tz, tpang;             // Interpolate so mirror doesn't
655
    // drift!
5198 hendricks2 656
    SWBOOL bIsWallMirror = FALSE;
5196 hendricks2 657
 
658
    MirrorMoveSkip16 = (MirrorMoveSkip16 + 1) & 15;
659
 
660
    camloopcnt += (totalclock - ototalclock);
661
    if (camloopcnt > (60 * 5))          // 5 seconds per player view
662
    {
663
        camloopcnt = 0;
664
        camplayerview++;
665
        if (camplayerview >= numplayers)
666
            camplayerview = 1;
667
    }
668
 
669
    // WARNING!  Assuming (MIRRORLABEL&31) = 0 and MAXMIRRORS = 64 <-- JBF: wrong
670
    longptr = (int *)&gotpic[MIRRORLABEL >> 3];
671
    if (longptr && (longptr[0] || longptr[1]))
672
    {
673
        for (cnt = MAXMIRRORS - 1; cnt >= 0; cnt--)
674
            //if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(cnt + CAMSPRITE))
675
            if (TEST_GOTPIC(cnt + MIRRORLABEL) || TEST_GOTPIC(mirror[cnt].campic))
676
            {
677
                bIsWallMirror = FALSE;
678
                if (TEST_GOTPIC(cnt + MIRRORLABEL))
679
                {
680
                    bIsWallMirror = TRUE;
681
                    RESET_GOTPIC(cnt + MIRRORLABEL);
682
                }
683
                //else if (TEST_GOTPIC(cnt + CAMSPRITE))
684
                else if (TEST_GOTPIC(mirror[cnt].campic))
685
                {
686
                    //RESET_GOTPIC(cnt + CAMSPRITE);
687
                    RESET_GOTPIC(mirror[cnt].campic);
688
                }
689
 
690
                mirrorinview = TRUE;
691
 
692
//                tx = pp->oposx + mulscale(pp->posx - pp->oposx, smoothratio, 16);
693
//                ty = pp->oposy + mulscale(pp->posy - pp->oposy, smoothratio, 16);
694
//                tz = pp->oposz + mulscale(pp->posz - pp->oposz, smoothratio, 16);
695
//                tpang = pp->oang + mulscale(((pp->pang + 1024 - pp->oang) & 2047) - 1024, smoothratio, 16);
696
 
697
 
698
                dist = 0x7fffffff;
699
 
700
                if (bIsWallMirror)
701
                {
702
                    j = klabs(wall[mirror[cnt].mirrorwall].x - tx);
703
                    j += klabs(wall[mirror[cnt].mirrorwall].y - ty);
704
                    if (j < dist)
705
                        dist = j;
706
                }
707
                else
708
                {
709
                    SPRITEp tp;
710
 
711
                    tp = &sprite[mirror[cnt].camsprite];
712
 
713
                    j = klabs(tp->x - tx);
714
                    j += klabs(tp->y - ty);
715
                    if (j < dist)
716
                        dist = j;
717
                }
718
 
719
 
720
 
721
//              //DSPRINTF(ds,"mirror.tics == %ul", mirror[i].tics);
722
//              MONO_PRINT(ds);
723
 
724
 
725
                if (mirror[cnt].ismagic)
726
                {
727
                    SPRITEp sp=NULL;
728
                    int camhoriz;
729
                    short wall_ang, w, nw, da, tda;
730
                    int dx, dy, dz, tdx, tdy, tdz, midx, midy;
731
 
732
 
733
                    ASSERT(mirror[cnt].camera != -1);
734
 
735
                    sp = &sprite[mirror[cnt].camera];
736
 
737
                    ASSERT(sp);
738
 
5207 hendricks2 739
                    // tvisibility = g_visibility;
740
//                  g_visibility <<= 1;       // Make mirror darker
5196 hendricks2 741
 
742
                    // Make TV cam style mirror seem to shimmer
743
//                  if (mirror[cnt].ismagic && STD_RANDOM_P2(256) > 128)
5207 hendricks2 744
//                      g_visibility -= STD_RANDOM_P2(128);
5196 hendricks2 745
 
746
                    // Calculate the angle of the mirror wall
747
                    w = mirror[cnt].mirrorwall;
748
                    nw = wall[w].point2;
749
 
750
                    // Get wall midpoint for offset in mirror view
751
                    midx = (wall[w].x + wall[wall[w].point2].x) / 2;
752
                    midy = (wall[w].y + wall[wall[w].point2].y) / 2;
753
 
754
                    // Finish finding offsets
755
                    tdx = klabs(midx - tx);
756
                    tdy = klabs(midy - ty);
757
 
758
                    if (midx >= tx)
759
                        dx = sp->x - tdx;
760
                    else
761
                        dx = sp->x + tdx;
762
 
763
                    if (midy >= ty)
764
                        dy = sp->y - tdy;
765
                    else
766
                        dy = sp->y + tdy;
767
 
768
                    tdz = klabs(tz - sp->z);
769
                    if (tz >= sp->z)
770
                        dz = sp->z + tdz;
771
                    else
772
                        dz = sp->z - tdz;
773
 
774
 
775
                    // Is it a TV cam or a teleporter that shows destination?
776
                    // TRUE = It's a TV cam
777
                    mirror[cnt].mstate = m_normal;
778
                    if (TEST_BOOL1(sp))
779
                        mirror[cnt].mstate = m_viewon;
780
 
781
                    // Show teleport destination
782
                    // NOTE: Adding MAXSECTORS lets you draw a room, even if
783
                    // you are outside of it!
784
                    if (!mirror[cnt].mstate == m_viewon)
785
                    {
5204 hendricks2 786
                        tilesiz[MIRROR].x = tilesiz[MIRROR].y = 0;
5196 hendricks2 787
                        // Set TV camera sprite size to 0 to show mirror
788
                        // behind in this case!
789
 
790
                        if (mirror[cnt].campic != -1)
5204 hendricks2 791
                            tilesiz[mirror[cnt].campic].x = tilesiz[mirror[cnt].campic].y = 0;
5196 hendricks2 792
                        drawrooms(dx, dy, dz, tpang, tphoriz, sp->sectnum + MAXSECTORS);
793
                        analyzesprites(dx, dy, dz, FALSE);
794
                        drawmasks();
795
                    }
796
                    else
797
                    {
5198 hendricks2 798
                        SWBOOL DoCam = FALSE;
5196 hendricks2 799
 
800
                        if (mirror[cnt].campic == -1)
801
                        {
802
                            TerminateGame();
803
                            printf("Missing campic for mirror %d\n",cnt);
804
                            printf("Map Coordinates: x = %d, y = %d\n",midx,midy);
805
                            exit(0);
806
                        }
807
 
808
                        // BOOL2 = Oscilate camera
809
                        if (TEST_BOOL2(sp) && MoveSkip2 == 0)
810
                        {
811
                            if (TEST_BOOL3(sp)) // If true add increment to
812
                            // angle else subtract
813
                            {
814
                                // Store current angle in TAG5
815
                                SP_TAG5(sp) = NORM_ANGLE((SP_TAG5(sp) + 4));
816
 
817
                                // TAG6 = Turn radius
818
                                if (klabs(GetDeltaAngle(SP_TAG5(sp), sp->ang)) >= SP_TAG6(sp))
819
                                {
820
                                    RESET_BOOL3(sp);    // Reverse turn
821
                                    // direction.
822
                                }
823
                            }
824
                            else
825
                            {
826
                                // Store current angle in TAG5
827
                                SP_TAG5(sp) = NORM_ANGLE((SP_TAG5(sp) - 4));
828
 
829
                                // TAG6 = Turn radius
830
                                if (klabs(GetDeltaAngle(SP_TAG5(sp), sp->ang)) >= SP_TAG6(sp))
831
                                {
832
                                    SET_BOOL3(sp);      // Reverse turn
833
                                    // direction.
834
                                }
835
                            }
836
                        }
837
                        else if (!TEST_BOOL2(sp))
838
                        {
839
                            SP_TAG5(sp) = sp->ang;      // Copy sprite angle to
840
                            // tag5
841
                        }
842
 
843
                        // See if there is a horizon value.  0 defaults to
844
                        // 100!
845
                        if (SP_TAG7(sp) != 0)
846
                        {
847
                            camhoriz = SP_TAG7(sp);
848
                            if (camhoriz > PLAYER_HORIZ_MAX)
849
                                camhoriz = PLAYER_HORIZ_MAX;
850
                            else if (camhoriz < PLAYER_HORIZ_MIN)
851
                                camhoriz = PLAYER_HORIZ_MIN;
852
                        }
853
                        else
854
                            camhoriz = 100;     // Default
855
 
856
                        // If player is dead still then update at MoveSkip4
857
                        // rate.
858
                        if (pp->posx == pp->oposx && pp->posy == pp->oposy && pp->posz == pp->oposz)
859
                            DoCam = TRUE;
860
 
861
 
862
                        // Set up the tile for drawing
5204 hendricks2 863
                        tilesiz[mirror[cnt].campic].x = tilesiz[mirror[cnt].campic].y = 128;
5196 hendricks2 864
 
865
                        if (MirrorMoveSkip16 == 0 || (DoCam && (MoveSkip4 == 0)))
866
                        {
867
                            if (dist < MAXCAMDIST)
868
                            {
869
                                PLAYERp cp = Player + camplayerview;
870
 
871
                                if (TEST_BOOL11(sp) && numplayers > 1)
872
                                {
873
                                    drawroomstotile(cp->posx, cp->posy, cp->posz, cp->pang, cp->horiz, cp->cursectnum, mirror[cnt].campic);
874
                                }
875
                                else
876
                                {
877
                                    drawroomstotile(sp->x, sp->y, sp->z, SP_TAG5(sp), camhoriz, sp->sectnum, mirror[cnt].campic);
878
                                }
879
                            }
880
                        }
881
                    }
882
                }
883
                else
884
                {
885
                    // It's just a mirror
886
                    // Prepare drawrooms for drawing mirror and calculate
887
                    // reflected
888
                    // position into tposx, tposy, and tang (tposz == cposz)
889
                    // Must call preparemirror before drawrooms and
890
                    // completemirror after drawrooms
891
 
5201 hendricks2 892
                    preparemirror(tx, ty, /*tz,*/ tpang, /*tphoriz,*/
893
                                  mirror[cnt].mirrorwall, /*mirror[cnt].mirrorsector,*/ &tposx, &tposy, &tang);
5196 hendricks2 894
 
895
                    drawrooms(tposx, tposy, tz, tang, tphoriz, mirror[cnt].mirrorsector + MAXSECTORS);
896
 
897
                    analyzesprites(tposx, tposy, tz, TRUE);
898
                    drawmasks();
899
 
900
                    completemirror();   // Reverse screen x-wise in this
901
                    // function
902
                }
903
 
904
 
5207 hendricks2 905
                // g_visibility = tvisibility;
906
                // g_visibility = NormalVisibility;
5196 hendricks2 907
 
908
                // drawrooms(tx, ty, tz, tpang, tphoriz, pp->cursectnum);
909
                // Clean up anything that the camera view might have done
910
                SetFragBar(pp);
5204 hendricks2 911
                tilesiz[MIRROR].x = tilesiz[MIRROR].y = 0;
5196 hendricks2 912
                wall[mirror[cnt].mirrorwall].overpicnum = MIRRORLABEL + cnt;
913
            }
914
            else
915
                mirrorinview = FALSE;
916
    }
917
}
918
 
919
void
920
DoAutoSize(SPRITEp tspr)
921
{
922
    short i;
923
 
924
    if (!bAutoSize)
925
        return;
926
 
927
    switch (tspr->picnum)
928
    {
929
    case ICON_STAR:                     // 1793
930
        break;
931
    case ICON_UZI:                      // 1797
932
        tspr->xrepeat = 43;
933
        tspr->yrepeat = 40;
934
        break;
935
    case ICON_UZIFLOOR:         // 1807
936
        tspr->xrepeat = 43;
937
        tspr->yrepeat = 40;
938
        break;
939
    case ICON_LG_UZI_AMMO:              // 1799
940
        break;
941
    case ICON_HEART:                    // 1824
942
        break;
943
    case ICON_HEART_LG_AMMO:            // 1820
944
        break;
945
    case ICON_GUARD_HEAD:               // 1814
946
        break;
947
    case ICON_FIREBALL_LG_AMMO: // 3035
948
        break;
949
    case ICON_ROCKET:                   // 1843
950
        break;
951
    case ICON_SHOTGUN:                  // 1794
952
        tspr->xrepeat = 57;
953
        tspr->yrepeat = 58;
954
        break;
955
    case ICON_LG_ROCKET:                // 1796
956
        break;
957
    case ICON_LG_SHOTSHELL:             // 1823
958
        break;
959
    case ICON_MICRO_GUN:                // 1818
960
        break;
961
    case ICON_MICRO_BATTERY:            // 1800
962
        break;
963
    case ICON_GRENADE_LAUNCHER: // 1817
964
        tspr->xrepeat = 54;
965
        tspr->yrepeat = 52;
966
        break;
967
    case ICON_LG_GRENADE:               // 1831
968
        break;
969
    case ICON_LG_MINE:                  // 1842
970
        break;
971
    case ICON_RAIL_GUN:         // 1811
972
        tspr->xrepeat = 50;
973
        tspr->yrepeat = 54;
974
        break;
975
    case ICON_RAIL_AMMO:                // 1812
976
        break;
977
    case ICON_SM_MEDKIT:                // 1802
978
        break;
979
    case ICON_MEDKIT:                   // 1803
980
        break;
981
    case ICON_CHEMBOMB:
982
        tspr->xrepeat = 64;
983
        tspr->yrepeat = 47;
984
        break;
985
    case ICON_FLASHBOMB:
986
        tspr->xrepeat = 32;
987
        tspr->yrepeat = 34;
988
        break;
989
    case ICON_NUKE:
990
        break;
991
    case ICON_CALTROPS:
992
        tspr->xrepeat = 37;
993
        tspr->yrepeat = 30;
994
        break;
995
    case ICON_BOOSTER:                  // 1810
996
        tspr->xrepeat = 30;
997
        tspr->yrepeat = 38;
998
        break;
999
    case ICON_HEAT_CARD:                // 1819
1000
        tspr->xrepeat = 46;
1001
        tspr->yrepeat = 47;
1002
        break;
1003
    case ICON_REPAIR_KIT:               // 1813
1004
        break;
1005
    case ICON_EXPLOSIVE_BOX:            // 1801
1006
        break;
1007
    case ICON_ENVIRON_SUIT:             // 1837
1008
        break;
1009
    case ICON_FLY:                      // 1782
1010
        break;
1011
    case ICON_CLOAK:                    // 1826
1012
        break;
1013
    case ICON_NIGHT_VISION:             // 3031
1014
        tspr->xrepeat = 59;
1015
        tspr->yrepeat = 71;
1016
        break;
1017
    case ICON_NAPALM:                   // 3046
1018
        break;
1019
    case ICON_RING:                     // 3050
1020
        break;
1021
    case ICON_RINGAMMO:         // 3054
1022
        break;
1023
    case ICON_NAPALMAMMO:               // 3058
1024
        break;
1025
    case ICON_GRENADE:                  // 3059
1026
        break;
1027
    case ICON_ARMOR:                    // 3030
1028
        tspr->xrepeat = 82;
1029
        tspr->yrepeat = 84;
1030
        break;
1031
    case BLUE_KEY:                      // 1766
1032
        break;
1033
    case RED_KEY:                       // 1770
1034
        break;
1035
    case GREEN_KEY:                     // 1774
1036
        break;
1037
    case YELLOW_KEY:                    // 1778
1038
        break;
1039
    case BLUE_CARD:
1040
    case RED_CARD:
1041
    case GREEN_CARD:
1042
    case YELLOW_CARD:
1043
        tspr->xrepeat = 36;
1044
        tspr->yrepeat = 33;
1045
        break;
1046
    case GOLD_SKELKEY:
1047
    case SILVER_SKELKEY:
1048
    case BRONZE_SKELKEY:
1049
    case RED_SKELKEY:
1050
        tspr->xrepeat = 39;
1051
        tspr->yrepeat = 45;
1052
        break;
1053
    case SKEL_LOCKED:
1054
    case SKEL_UNLOCKED:
1055
        tspr->xrepeat = 47;
1056
        tspr->yrepeat = 40;
1057
        break;
1058
    case RAMCARD_LOCKED:
1059
    case RAMCARD_UNLOCKED:
1060
    case CARD_LOCKED:
1061
    case CARD_UNLOCKED:
1062
        break;
1063
    default:
1064
        break;
1065
    }
1066
}
1067
 
1068
// Rotation angles for sprites
1069
short rotang = 0;
1070
 
1071
void
1072
JAnalyzeSprites(SPRITEp tspr)
1073
{
1074
    int i, currsprite;
1075
 
1076
    rotang += 4;
1077
    if (rotang > 2047)
1078
        rotang = 0;
1079
 
1080
 
1081
    // Take care of autosizing
1082
    DoAutoSize(tspr);
1083
 
5201 hendricks2 1084
    if (getrendermode() == 3 && md_tilehasmodel(tspr->picnum, 0) >= 0 && usemodels) return;
5196 hendricks2 1085
 
1086
    // Check for voxels
1087
    //if (bVoxelsOn)
1088
    if (gs.Voxels)
1089
    {
1090
        if (aVoxelArray[tspr->picnum].Voxel >= 0)
1091
        {
1092
            // Turn on voxels
1093
            tspr->picnum = aVoxelArray[tspr->picnum].Voxel;     // Get the voxel number
1094
            tspr->cstat |= 48;          // Set stat to voxelize sprite
1095
        }
1096
    }
1097
    else
1098
    {
1099
        switch (tspr->picnum)
1100
        {
1101
        case 764: // Gun barrel
1102
 
1103
            if (aVoxelArray[tspr->picnum].Voxel >= 0)
1104
            {
1105
                // Turn on voxels
1106
                tspr->picnum = aVoxelArray[tspr->picnum].Voxel;     // Get the voxel number
1107
                tspr->cstat |= 48;          // Set stat to voxelize sprite
1108
            }
1109
            break;
1110
        }
1111
    }
1112
}
1113
 
1114
//////////////////////////////////////////////////////////////////////////////////////////////
1115
// Parental Lockout Stuff
1116
//////////////////////////////////////////////////////////////////////////////////////////////
1117
OrgTileList orgwalllist;                // The list containing orginal wall
1118
// pics
1119
OrgTileList orgwalloverlist;            // The list containing orginal wall
1120
// over pics
1121
OrgTileList orgsectorceilinglist;       // The list containing orginal sector
1122
// ceiling pics
1123
OrgTileList orgsectorfloorlist;         // The list containing orginal sector
1124
// floor pics
1125
 
1126
void
1127
InsertOrgTile(OrgTileP tp, OrgTileListP thelist)
1128
{
1129
    OrgTileP cur, nxt;
1130
 
1131
    ASSERT(tp);
1132
    ASSERT(ValidPtr(tp));
1133
 
1134
    // if list is empty, insert at front
1135
    if (EMPTY(thelist))
1136
    {
1137
        INSERT(thelist, tp);
1138
        return;
1139
    }
1140
 
1141
    // Otherwise insert it at end
1142
    INSERT_TAIL(thelist, tp);
1143
    return;
1144
}
1145
 
1146
 
1147
OrgTileP
1148
InitOrgTile(OrgTileListP thelist)
1149
{
1150
    int i;
1151
    OrgTileP tp;
1152
 
1153
 
1154
    tp = CallocMem(sizeof(OrgTile), 1);
1155
 
1156
    ASSERT(tp);
1157
 
1158
    InsertOrgTile(tp, thelist);
1159
 
1160
    return tp;
1161
}
1162
 
5198 hendricks2 1163
void
5196 hendricks2 1164
KillOrgTile(OrgTileP tp)
1165
{
1166
    ASSERT(tp);
1167
    ASSERT(ValidPtr(tp));
1168
 
5200 hendricks2 1169
    REMOVE(tp);
5196 hendricks2 1170
 
1171
    FreeMem(tp);
1172
}
1173
 
1174
OrgTileP
1175
FindOrgTile(short index, OrgTileListP thelist)
1176
{
1177
    OrgTileP tp, next_tp;
1178
 
1179
    if (EMPTY(thelist))
1180
        return NULL;
1181
 
1182
    TRAVERSE(thelist, tp, next_tp)
1183
    {
1184
        if (tp->index == index)
1185
            return tp;
1186
    }
1187
 
1188
    return NULL;
1189
}
1190
 
1191
// Call this at terminate game time
5198 hendricks2 1192
void
5196 hendricks2 1193
JS_UnInitLockouts(void)
1194
{
1195
    OrgTileP tp=NULL, next_tp=NULL;
1196
 
1197
 
1198
    TRAVERSE(&orgwalllist, tp, next_tp)
1199
    {
1200
        KillOrgTile(tp);
1201
    }
1202
    TRAVERSE(&orgwalloverlist, tp, next_tp)
1203
    {
1204
        KillOrgTile(tp);
1205
    }
1206
    TRAVERSE(&orgsectorceilinglist, tp, next_tp)
1207
    {
1208
        KillOrgTile(tp);
1209
    }
1210
    TRAVERSE(&orgsectorfloorlist, tp, next_tp)
1211
    {
1212
        KillOrgTile(tp);
1213
    }
1214
}
1215
 
1216
/////////////////////////////////////////////////////
1217
//  Initialize the original tiles list
1218
//  Creates a list of all orginal tiles and their
1219
//  replacements.  Several tiles can use the same
1220
//  replacement tilenum, so the list is built
1221
//  using the original tilenums as a basis for
1222
//  memory allocation
1223
//  t == 1 - wall
1224
//  t == 2 - overpicnum
1225
//  t == 3 - ceiling
1226
//  t == 4 - floor
1227
/////////////////////////////////////////////////////
1228
void
1229
JS_PlockError(short wall_num, short t)
1230
{
1231
    TerminateGame();
1232
    printf("ERROR: JS_InitLockouts(), out of range tile number\n");
1233
    switch (t)
1234
    {
1235
    case 1:
1236
        printf("wall %d, x %d, y %d, pic %d\n", wall_num, wall[wall_num].x, wall[wall_num].y, wall[wall_num].picnum);
1237
        break;
1238
    case 2:
1239
        printf("wall %d, x %d, y %d, OVERpic %d\n", wall_num, wall[wall_num].x, wall[wall_num].y, wall[wall_num].overpicnum);
1240
        break;
1241
    case 3:
1242
        printf("sector %d, ceiling %d\n", wall_num, sector[wall_num].ceilingpicnum);
1243
        break;
1244
    case 4:
1245
        printf("sector %d, floor %d\n", wall_num, sector[wall_num].floorpicnum);
1246
        break;
1247
    }
1248
    exit(0);
1249
}
1250
 
1251
void
1252
JS_InitLockouts(void)
1253
{
1254
    SPRITEp sp;
1255
    short i, num;
1256
    OrgTileP tp;
1257
 
1258
    INITLIST(&orgwalllist);             // The list containing orginal wall
1259
    // pics
1260
    INITLIST(&orgwalloverlist);         // The list containing orginal wall
1261
    // over pics
1262
    INITLIST(&orgsectorceilinglist);    // The list containing orginal sector
1263
    // ceiling pics
1264
    INITLIST(&orgsectorfloorlist);      // The list containing orginal sector
1265
    // floor pics
1266
 
1267
    // Check all walls
1268
    for (i = 0; i < numwalls; i++)
1269
    {
1270
        short picnum;
1271
 
1272
        picnum = wall[i].picnum;
1273
        if (aVoxelArray[picnum].Parental >= INVISTILE)
1274
            JS_PlockError(i,1);
1275
 
1276
        if (aVoxelArray[picnum].Parental >= 0)
1277
        {
1278
            if ((tp = FindOrgTile(i, &orgwalllist)) == NULL)
1279
                tp = InitOrgTile(&orgwalllist);
1280
            tp->index = i;
1281
            tp->orgpicnum = wall[i].picnum;
1282
        }
1283
 
1284
        picnum = wall[i].overpicnum;
1285
        if (aVoxelArray[picnum].Parental >= INVISTILE)
1286
            JS_PlockError(i,2);
1287
 
1288
        if (aVoxelArray[picnum].Parental >= 0)
1289
        {
1290
            if ((tp = FindOrgTile(i, &orgwalloverlist)) == NULL)
1291
                tp = InitOrgTile(&orgwalloverlist);
1292
            tp->index = i;
1293
            tp->orgpicnum = wall[i].overpicnum;
1294
        }
1295
    }
1296
    // Check all ceilings and floors
1297
    for (i = 0; i < numsectors; i++)
1298
    {
1299
        short picnum;
1300
 
1301
        picnum = sector[i].ceilingpicnum;
1302
        if (aVoxelArray[picnum].Parental >= INVISTILE)
1303
            JS_PlockError(i,3);
1304
 
1305
        if (aVoxelArray[picnum].Parental >= 0)
1306
        {
1307
            if ((tp = FindOrgTile(i, &orgsectorceilinglist)) == NULL)
1308
                tp = InitOrgTile(&orgsectorceilinglist);
1309
            tp->index = i;
1310
            tp->orgpicnum = sector[i].ceilingpicnum;
1311
        }
1312
 
1313
        picnum = sector[i].floorpicnum;
1314
        if (aVoxelArray[picnum].Parental >= INVISTILE)
1315
            JS_PlockError(i,2);
1316
 
1317
        if (aVoxelArray[picnum].Parental >= 0)
1318
        {
1319
            if ((tp = FindOrgTile(i, &orgsectorfloorlist)) == NULL)
1320
                tp = InitOrgTile(&orgsectorfloorlist);
1321
            tp->index = i;
1322
            tp->orgpicnum = sector[i].floorpicnum;
1323
        }
1324
    }
1325
}
1326
 
1327
/////////////////////////////////////////////////////
1328
//  Switch back and forth between locked out stuff
1329
/////////////////////////////////////////////////////
1330
void
1331
JS_ToggleLockouts(void)
1332
{
1333
    SPRITEp sp;
1334
    short i, num;
1335
    OrgTileP tp;
1336
 
1337
 
1338
    // Check all walls
1339
    for (i = 0; i < numwalls; i++)
1340
    {
1341
        short picnum;
1342
 
1343
        if (gs.ParentalLock)
1344
        {
1345
            picnum = wall[i].picnum;
1346
            ASSERT(aVoxelArray[picnum].Parental < INVISTILE);   // Invalid, walls can't
1347
            // be invisible
1348
            if (aVoxelArray[picnum].Parental >= 0)
1349
            {
1350
                wall[i].picnum = aVoxelArray[picnum].Parental;
1351
            }
1352
        }
1353
        else if ((tp = FindOrgTile(i, &orgwalllist)) != NULL)
1354
            wall[i].picnum = tp->orgpicnum;     // Restore them
1355
 
1356
 
1357
        if (gs.ParentalLock)
1358
        {
1359
            picnum = wall[i].overpicnum;
1360
            ASSERT(aVoxelArray[picnum].Parental < INVISTILE);   // Invalid, walls can't
1361
            // be invisible
1362
            if (aVoxelArray[picnum].Parental >= 0)
1363
            {
1364
                wall[i].overpicnum = aVoxelArray[picnum].Parental;
1365
            }
1366
        }
1367
        else if ((tp = FindOrgTile(i, &orgwalloverlist)) != NULL)
1368
            wall[i].overpicnum = tp->orgpicnum; // Restore them
1369
    }
1370
 
1371
    // Check all sectors
1372
    for (i = 0; i < numsectors; i++)
1373
    {
1374
        short picnum;
1375
 
1376
        if (gs.ParentalLock)
1377
        {
1378
            picnum = sector[i].ceilingpicnum;
1379
            ASSERT(aVoxelArray[picnum].Parental < INVISTILE);   // Invalid, walls can't
1380
            // be invisible
1381
            if (aVoxelArray[picnum].Parental >= 0)
1382
            {
1383
                sector[i].ceilingpicnum = aVoxelArray[picnum].Parental;
1384
            }
1385
        }
1386
        else if ((tp = FindOrgTile(i, &orgsectorceilinglist)) != NULL)
1387
            sector[i].ceilingpicnum = tp->orgpicnum;    // Restore them
1388
 
1389
 
1390
        if (gs.ParentalLock)
1391
        {
1392
            picnum = sector[i].floorpicnum;
1393
            ASSERT(aVoxelArray[picnum].Parental < INVISTILE);   // Invalid, walls can't
1394
            // be invisible
1395
            if (aVoxelArray[picnum].Parental >= 0)
1396
            {
1397
                sector[i].floorpicnum = aVoxelArray[picnum].Parental;
1398
            }
1399
        }
1400
        else if ((tp = FindOrgTile(i, &orgsectorfloorlist)) != NULL)
1401
            sector[i].floorpicnum = tp->orgpicnum;      // Restore them
1402
    }
1403
}
1404
 
1405
////////////////////////////////////////////////////////////////////////////////////////////////
1406
 
1407
void
5202 hendricks2 1408
UnlockKeyLock(short key_num, short hit_sprite)
5196 hendricks2 1409
{
1410
    SPRITEp sp;
1411
    int SpriteNum = 0, NextSprite = 0, color = 0;
1412
 
1413
    // Get palette by looking at key number
1414
    switch (key_num - 1)
1415
    {
1416
    case 0:                             // RED_KEY
1417
        color = PALETTE_PLAYER9;
1418
        break;
1419
    case 1:                             // BLUE_KEY
1420
        color = PALETTE_PLAYER7;
1421
        break;
1422
    case 2:                             // GREEN_KEY
1423
        color = PALETTE_PLAYER6;
1424
        break;
1425
    case 3:                             // YELLOW_KEY
1426
        color = PALETTE_PLAYER4;
1427
        break;
1428
    case 4:                             // SILVER_SKELKEY
1429
        color = PALETTE_PLAYER4;
1430
        break;
1431
    case 5:                             // GOLD_SKELKEY
1432
        color = PALETTE_PLAYER1;
1433
        break;
1434
    case 6:                             // BRONZE_SKELKEY
1435
        color = PALETTE_PLAYER8;
1436
        break;
1437
    case 7:                             // RED_SKELKEY
1438
        color = PALETTE_PLAYER9;
1439
        break;
1440
    }
1441
 
1442
    TRAVERSE_SPRITE_STAT(headspritestat[0], SpriteNum, NextSprite)
1443
    {
1444
        sp = &sprite[SpriteNum];
1445
 
1446
        switch (sp->picnum)
1447
        {
1448
        case SKEL_LOCKED:
1449
            if (sp->pal == color)
1450
            {
1451
                PlaySound(DIGI_UNLOCK, &sp->x, &sp->y, &sp->z, v3df_doppler | v3df_dontpan);
5202 hendricks2 1452
                if (SpriteNum == hit_sprite)
5196 hendricks2 1453
                    sp->picnum = SKEL_UNLOCKED;
1454
            }
1455
            break;
1456
        case RAMCARD_LOCKED:
1457
            if (sp->pal == color)
1458
            {
1459
                PlaySound(DIGI_CARDUNLOCK, &sp->x, &sp->y, &sp->z, v3df_doppler | v3df_dontpan);
1460
                sp->picnum = RAMCARD_UNLOCKED;
1461
            }
1462
            break;
1463
        case CARD_LOCKED:
1464
            if (sp->pal == color)
1465
            {
1466
                PlaySound(DIGI_RAMUNLOCK, &sp->x, &sp->y, &sp->z, v3df_doppler | v3df_dontpan);
5202 hendricks2 1467
                if (SpriteNum == hit_sprite)
5196 hendricks2 1468
                    sp->picnum = CARD_UNLOCKED;
1469
                else
1470
                    sp->picnum = CARD_UNLOCKED+1;
1471
            }
1472
            break;
1473
        }
1474
 
1475
    }
1476
}