Subversion Repositories eduke32

Rev

Rev 8700 | 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
#define QUIET
27
#include "build.h"
28
#include "pragmas.h"
29
#include "cache1d.h"
30
 
31
#include "keys.h"
32
#include "names2.h"
33
#include "panel.h"
34
#include "game.h"
35
#include "quake.h"
36
#include "vis.h"
37
 
38
#include "jsector.h"
39
 
40
#include "mytypes.h"
41
#include "control.h"
42
#include "function.h"
7443 hendricks2 43
#include "network.h"
5196 hendricks2 44
#include "pal.h"
45
#include "player.h"
46
#include "jtags.h"
47
#include "parent.h"
48
 
49
#include "cache.h"
50
#include "reserve.h"
51
 
52
#include "text.h"
53
#include "menus.h"
54
#include "interp.h"
55
#include "sector.h"
7511 hendricks2 56
#include "config.h"
5196 hendricks2 57
 
58
static int OverlapDraw = FALSE;
5198 hendricks2 59
extern SWBOOL QuitFlag, LocationInfo, ConPanel, SpriteInfo, PauseKeySet;
60
extern SWBOOL Voxel;
5196 hendricks2 61
extern char buffer[];
5198 hendricks2 62
SWBOOL DrawScreen;
5196 hendricks2 63
extern short f_c;
64
 
5198 hendricks2 65
extern SWBOOL HelpInputMode;
5196 hendricks2 66
extern short HelpPage;
67
extern short HelpPagePic[];
68
extern ParentalStruct aVoxelArray[MAXTILES];
5198 hendricks2 69
extern SWBOOL RedrawScreen;
70
SWBOOL RedrawCompass=FALSE;
5196 hendricks2 71
extern int Follow_posx,Follow_posy;
72
 
6042 hendricks2 73
int ConnectCopySprite(uspritetype const * tsp);
5196 hendricks2 74
void PreDrawStackedWater(void);
5198 hendricks2 75
void DrawCompass(PLAYERp pp);
5196 hendricks2 76
 
77
#if 1
5198 hendricks2 78
void
8519 hendricks2 79
ShadeSprite(tspriteptr_t tsp)
5196 hendricks2 80
{
81
    // set shade of sprite
82
    tsp->shade = sector[tsp->sectnum].floorshade - 25;
83
 
84
    if (tsp->shade > -3)
85
        tsp->shade = -3;
86
 
87
    if (tsp->shade < -30)
88
        tsp->shade = -30;
89
}
90
#else
91
#endif
92
 
93
 
94
short
95
GetRotation(short tSpriteNum, int viewx, int viewy)
96
{
97
    static short RotTable8[] = {0, 7, 6, 5, 4, 3, 2, 1};
98
    static short RotTable5[] = {0, 1, 2, 3, 4, 3, 2, 1};
99
    short rotation;
100
 
8519 hendricks2 101
    tspriteptr_t tsp = &tsprite[tSpriteNum];
5196 hendricks2 102
    USERp tu = User[tsp->owner];
103
    short angle2;
104
 
105
    if (tu->RotNum == 0)
106
        return 0;
107
 
108
    // Get which of the 8 angles of the sprite to draw (0-7)
109
    // rotation ranges from 0-7
110
    angle2 = getangle(tsp->x - viewx, tsp->y - viewy);
111
    rotation = ((tsp->ang + 3072 + 128 - angle2) & 2047);
112
    rotation = (rotation >> 8) & 7;
113
 
114
    if (tu->RotNum == 5)
115
    {
116
        if (TEST(tu->Flags, SPR_XFLIP_TOGGLE))
117
        {
118
            if (rotation <= 4)
119
            {
120
                // leave rotation alone
121
                RESET(tsp->cstat, CSTAT_SPRITE_XFLIP);
122
            }
123
            else
124
            {
125
                rotation = (8 - rotation);
126
                SET(tsp->cstat, CSTAT_SPRITE_XFLIP);    // clear x-flipping bit
127
            }
128
        }
129
        else
130
        {
131
            if (rotation > 3 || rotation == 0)
132
            {
133
                // leave rotation alone
134
                RESET(tsp->cstat, CSTAT_SPRITE_XFLIP);  // clear x-flipping bit
135
            }
136
            else
137
            {
138
                rotation = (8 - rotation);
139
                SET(tsp->cstat, CSTAT_SPRITE_XFLIP);    // set
140
            }
141
        }
142
 
143
        // Special case bunk
144
        if (tu->ID == TOILETGIRL_R0 || tu->ID == WASHGIRL_R0 || tu->ID == TRASHCAN ||
145
            tu->ID == CARGIRL_R0 || tu->ID == MECHANICGIRL_R0 || tu->ID == PRUNEGIRL_R0 ||
146
            tu->ID == SAILORGIRL_R0)
147
            RESET(tsp->cstat, CSTAT_SPRITE_XFLIP);  // clear x-flipping bit
148
 
149
        return RotTable5[rotation];
150
    }
151
 
152
    return RotTable8[rotation];
153
 
154
}
155
 
156
/*
157
 
158
 
159
!AIC - At draw time this is called for actor rotation.  GetRotation() is more
160
complex than needs to be in part because importing of actor rotations and x-flip
161
directions was not standardized.
162
 
163
*/
164
 
165
int
166
SetActorRotation(short tSpriteNum, int viewx, int viewy)
167
{
8519 hendricks2 168
    tspriteptr_t tsp = &tsprite[tSpriteNum];
5196 hendricks2 169
    USERp tu = User[tsp->owner];
170
    short StateOffset, Rotation;
171
 
172
    // don't modify ANY tu vars - back them up!
173
    STATEp State = tu->State;
174
    STATEp StateStart = tu->StateStart;
175
 
176
    if (tu->RotNum == 0)
177
        return 0;
178
 
179
    // Get the offset into the State animation
180
    StateOffset = State - StateStart;
181
 
182
    // Get the rotation angle
183
    Rotation = GetRotation(tSpriteNum, viewx, viewy);
184
 
185
    ASSERT(Rotation < 5);
186
 
187
    // Reset the State animation start based on the Rotation
188
    StateStart = tu->Rot[Rotation];
189
 
190
    // Set the sprites state
191
    State = StateStart + StateOffset;
192
 
193
    // set the picnum here - may be redundant, but we just changed states and
194
    // thats a big deal
195
    tsp->picnum = State->Pic;
196
 
197
    //sprintf(ds,"SetActorRotation:tsp->picnum: %d",tsp->picnum);
198
    //CON_Message(ds);
199
 
200
    /*
201
 
202
     !AIC KEY - For actor states EVERY rotation needs to have the same tics
203
     animators.  The only thing different can be the picnum.  If not then sync bugs
204
     will occur.  This code attempts to check to the best of its ability for this
205
     problem.  Should go away with shipped compile.
206
 
207
    */
208
 
209
#if DEBUG
210
    {
211
        short i;
212
 
213
        for (i = 0; i < tu->RotNum; i++)
214
        {
215
            STATEp TestStateStart, TestState;
216
 
217
            TestStateStart = tu->Rot[i];
218
            TestState = TestStateStart + StateOffset;
219
 
220
            ASSERT(State->Tics == TestState->Tics);
221
            ASSERT(State->Animator == TestState->Animator);
222
        }
223
    }
224
#endif
225
    return 0;
226
}
227
 
228
int
8519 hendricks2 229
DoShadowFindGroundPoint(tspriteptr_t sp)
5196 hendricks2 230
{
231
    // USES TSPRITE !!!!!
232
    USERp u = User[sp->owner];
233
    SPRITEp hsp;
234
    int ceilhit, florhit;
235
    int hiz, loz = u->loz;
236
    short save_cstat, bak_cstat;
237
 
238
    // recursive routine to find the ground - either sector or floor sprite
239
    // skips over enemy and other types of sprites
240
 
241
    // IMPORTANT!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
242
    // This will return invalid FAF ceiling and floor heights inside of analyzesprite
243
    // because the ceiling and floors get moved out of the way for drawing.
244
 
245
    save_cstat = sp->cstat;
246
    RESET(sp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
247
    FAFgetzrangepoint(sp->x, sp->y, sp->z, sp->sectnum, &hiz, &ceilhit, &loz, &florhit);
248
    sp->cstat = save_cstat;
249
 
250
    ASSERT(TEST(florhit, HIT_SPRITE | HIT_SECTOR));
251
 
252
    switch (TEST(florhit, HIT_MASK))
253
    {
254
    case HIT_SPRITE:
255
    {
256
        hsp = &sprite[NORM_SPRITE(florhit)];
257
 
6657 pogokeen 258
        if (TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_FLOOR))
5196 hendricks2 259
        {
260
            // found a sprite floor
261
            return loz;
262
        }
263
        else
264
        {
265
            // reset the blocking bit of what you hit and try again -
266
            // recursive
267
            bak_cstat = hsp->cstat;
268
            RESET(hsp->cstat, CSTAT_SPRITE_BLOCK | CSTAT_SPRITE_BLOCK_HITSCAN);
269
            loz = DoShadowFindGroundPoint(sp);
270
            hsp->cstat = bak_cstat;
271
        }
7533 hendricks2 272
        break;
5196 hendricks2 273
    }
274
 
275
    case HIT_SECTOR:
7533 hendricks2 276
        break;
5196 hendricks2 277
 
278
    default:
279
        ASSERT(TRUE == FALSE);
280
        break;
281
    }
282
 
283
    return loz;
284
}
285
 
286
#if 0
287
#define GENERIC_SHADOW_PIC 66
5198 hendricks2 288
extern SWBOOL bVoxelsOn;
289
void
5196 hendricks2 290
DoVoxelShadow(SPRITEp tspr)
291
{
292
    // Check for voxels
293
    if (bVoxelsOn)
294
    {
295
        switch (tspr->picnum)
296
        {
297
        case ICON_STAR:             // 1793
298
        case ICON_UZI:              // 1797
299
        case ICON_UZIFLOOR:         // 1807
300
        case ICON_LG_UZI_AMMO:      // 1799
301
        case ICON_HEART:            // 1824
302
        case ICON_HEART_LG_AMMO:    // 1820
303
        case ICON_GUARD_HEAD:       // 1814
304
        case ICON_FIREBALL_LG_AMMO: // 3035
305
        case ICON_ROCKET:           // 1843
306
        case ICON_SHOTGUN:          // 1794
307
        case ICON_LG_ROCKET:        // 1796
308
        case ICON_LG_SHOTSHELL:     // 1823
309
        case ICON_MICRO_GUN:        // 1818
310
        case ICON_MICRO_BATTERY:    // 1800
311
        case ICON_GRENADE_LAUNCHER: // 1817
312
        case ICON_LG_GRENADE:       // 1831
313
        case ICON_LG_MINE:          // 1842
314
        case ICON_RAIL_GUN:         // 1811
315
        case ICON_RAIL_AMMO:        // 1812
316
        case ICON_SM_MEDKIT:        // 1802
317
        case ICON_MEDKIT:           // 1803
318
        case ICON_CHEMBOMB:         // 1808
319
        case ICON_FLASHBOMB:        // 1805
320
        case ICON_NUKE:             // 1809
321
        case ICON_CALTROPS:
322
        case ICON_BOOSTER:          // 1810
323
        case ICON_HEAT_CARD:        // 1819
324
        case ICON_REPAIR_KIT:       // 1813
325
        case ICON_EXPLOSIVE_BOX:    // 1801
326
        case ICON_ENVIRON_SUIT:     // 1837
327
        case ICON_FLY:              // 1782
328
        case ICON_CLOAK:            // 1826
329
        case ICON_NIGHT_VISION:     // 3031
330
        case ICON_NAPALM:           // 3046
331
        case ICON_RING:             // 3050
332
        //case ICON_GOROAMMO:       // 3035
333
        //case ICON_HEARTAMMO:      // 1820
334
        case ICON_RINGAMMO:         // 3054
335
        case ICON_NAPALMAMMO:       // 3058
336
        case ICON_GRENADE:          // 3059
337
        //case ICON_OXYGEN:         // 1800
338
        case ICON_ARMOR:            // 3030
339
        case BLUE_KEY:              // 1766
340
        case RED_KEY:               // 1770
341
        case GREEN_KEY:             // 1774
342
        case YELLOW_KEY:            // 1778
343
        case GOLD_SKELKEY:
344
        case SILVER_SKELKEY:
345
        case BRONZE_SKELKEY:
346
        case RED_SKELKEY:
347
        case BLUE_CARD:
348
        case RED_CARD:
349
        case GREEN_CARD:
350
        case YELLOW_CARD:
351
//              tspr->picnum = GENERIC_SHADOW_PIC;
352
            tspr->xrepeat = 0;  // For now, don't do voxel shadows
353
            tspr->yrepeat = 0;
354
//              tspr->xrepeat = 27;
355
//              tspr->yrepeat = 4;
356
            //tspr->z+=(sintable[(rotang*2)%2047]/16);
357
            break;
358
        }
359
    }
360
}
361
#endif
362
 
5198 hendricks2 363
void
8519 hendricks2 364
DoShadows(tspriteptr_t tsp, int viewz)
5196 hendricks2 365
{
8519 hendricks2 366
    tspriteptr_t New = &tsprite[spritesortcnt];
5196 hendricks2 367
    USERp tu = User[tsp->owner];
368
    int ground_dist = 0;
369
    int view_dist = 0;
370
    int loz;
371
    short xrepeat;
372
    short yrepeat;
373
    short sectnum;
374
 
375
    sectnum = tsp->sectnum;
376
    // make sure its the correct sector
377
    // DoShadowFindGroundPoint calls FAFgetzrangepoint and this is sensitive
378
    //updatesectorz(tsp->x, tsp->y, tsp->z, &sectnum);
379
    updatesector(tsp->x, tsp->y, &sectnum);
380
 
381
    if (sectnum < 0)
382
    {
383
        //int cz,fz;
384
        //getzsofslope(tsp->sectnum, tsp->x, tsp->y, &cz, &fz);
385
        ////DSPRINTF(ds,"Shad sect !fnd x%d, y%d, z%d, sect%d, cz %d, fz %d", tsp->x, tsp->y, tsp->z, tsp->sectnum, cz, fz);
386
        //MONO_PRINT(ds);
387
        return;
388
    }
389
 
390
    tsp->sectnum = sectnum;
8519 hendricks2 391
    *New = *tsp;
5196 hendricks2 392
    // shadow is ALWAYS draw last - status is priority
6048 hendricks2 393
    New->statnum = MAXSTATUS;
394
    New->sectnum = sectnum;
5196 hendricks2 395
 
396
    if ((tsp->yrepeat >> 2) > 4)
397
    {
398
        yrepeat = (tsp->yrepeat >> 2) - (SPRITEp_SIZE_Y(tsp) / 64) * 2;
6048 hendricks2 399
        xrepeat = New->xrepeat;
5196 hendricks2 400
    }
401
    else
402
    {
6048 hendricks2 403
        yrepeat = New->yrepeat;
404
        xrepeat = New->xrepeat;
5196 hendricks2 405
    }
406
 
6048 hendricks2 407
    New->shade = 127;
408
    SET(New->cstat, CSTAT_SPRITE_TRANSLUCENT);
5196 hendricks2 409
 
410
    loz = tu->loz;
411
    if (tu->lo_sp)
412
    {
6657 pogokeen 413
        if (!TEST(tu->lo_sp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL | CSTAT_SPRITE_ALIGNMENT_FLOOR))
5196 hendricks2 414
        {
415
            loz = DoShadowFindGroundPoint(tsp);
416
        }
417
    }
418
 
419
#if 0
420
    if (SectUser[tsp->sectnum] && SectUser[tsp->sectnum]->depth)
421
    {
422
        loz -= Z(SectUser[tsp->sectnum]->depth);
423
    }
424
#endif
425
 
426
    // need to find the ground here
6048 hendricks2 427
    New->z = loz;
5196 hendricks2 428
 
429
    // if below or close to sprites z don't bother to draw it
430
    if ((viewz - loz) > -Z(8))
431
        return;
432
 
433
    // if close to shadows z shrink it
434
    view_dist = labs(loz - viewz) >> 8;
435
    if (view_dist < 32)
436
        view_dist = 256/view_dist;
437
    else
438
        view_dist = 0;
439
 
440
    // make shadow smaller depending on height from ground
441
    ground_dist = labs(loz - SPRITEp_BOS(tsp)) >> 8;
442
    ground_dist = DIV16(ground_dist);
443
 
444
    xrepeat = max(xrepeat - ground_dist - view_dist, 4);
445
    yrepeat = max(yrepeat - ground_dist - view_dist, 4);
7501 hendricks2 446
    xrepeat = min(xrepeat, short(255));
447
    yrepeat = min(yrepeat, short(255));
5196 hendricks2 448
 
6048 hendricks2 449
    New->xrepeat = xrepeat;
450
    New->yrepeat = yrepeat;
5196 hendricks2 451
 
452
    // Check for voxel items and use a round generic pic if so
6048 hendricks2 453
    //DoVoxelShadow(New);
5196 hendricks2 454
 
455
    spritesortcnt++;
456
}
457
 
5198 hendricks2 458
void
8519 hendricks2 459
DoMotionBlur(tspritetype const * const tsp)
5196 hendricks2 460
{
461
    USERp tu = User[tsp->owner];
462
    int nx,ny,nz = 0,dx,dy,dz;
463
    short i, ang;
464
    short xrepeat, yrepeat, repeat_adj = 0;
465
    int z_amt_per_pixel;
466
 
467
    ang = NORM_ANGLE(tsp->ang + 1024);
468
 
469
    if (tsp->xvel == 0)
470
    {
471
        return;
472
    }
473
 
474
    if (TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY))
475
    {
476
        z_amt_per_pixel = (((int)-tu->jump_speed * ACTORMOVETICS)<<16)/tsp->xvel;
477
    }
478
    else
479
    {
480
        z_amt_per_pixel = (((int)-tsp->zvel)<<16)/tsp->xvel;
481
    }
482
 
483
    switch (tu->motion_blur_dist)
484
    {
485
    case 64:
486
        dx = nx = MOVEx(64, ang);
487
        dy = ny = MOVEy(64, ang);
488
        nz = (z_amt_per_pixel * 64)>>16;
489
        break;
490
    case 128:
491
        dx = nx = MOVEx(128, ang);
492
        dy = ny = MOVEy(128, ang);
493
        nz = (z_amt_per_pixel * 128)>>16;
494
        break;
495
    case 256:
496
        dx = nx = MOVEx(256, ang);
497
        dy = ny = MOVEy(256, ang);
498
        nz = (z_amt_per_pixel * 256)>>16;
499
        break;
500
    case 512:
501
        dx = nx = MOVEx(512, ang);
502
        dy = ny = MOVEy(512, ang);
503
        nz = (z_amt_per_pixel * 512)>>16;
504
        break;
505
    default:
506
        dx = nx = MOVEx(tu->motion_blur_dist, ang);
507
        dy = ny = MOVEy(tu->motion_blur_dist, ang);
508
        break;
509
    }
510
 
511
    dz = nz;
512
 
513
    xrepeat = tsp->xrepeat;
514
    yrepeat = tsp->yrepeat;
515
 
516
    switch (TEST(tu->Flags2, SPR2_BLUR_TAPER))
517
    {
518
    case 0:
519
        repeat_adj = 0;
520
        break;
521
    case SPR2_BLUR_TAPER_SLOW:
522
        repeat_adj = xrepeat / (tu->motion_blur_num*2);
523
        break;
524
    case SPR2_BLUR_TAPER_FAST:
525
        repeat_adj = xrepeat / tu->motion_blur_num;
526
        break;
527
    }
528
 
529
    for (i = 0; i < tu->motion_blur_num; i++)
530
    {
8519 hendricks2 531
        tspriteptr_t New = &tsprite[spritesortcnt];
532
        *New = *tsp;
6657 pogokeen 533
        SET(New->cstat, CSTAT_SPRITE_TRANSLUCENT|CSTAT_SPRITE_TRANSLUCENT_INVERT);
5196 hendricks2 534
 
6048 hendricks2 535
        New->x += dx;
536
        New->y += dy;
5196 hendricks2 537
        dx += nx;
538
        dy += ny;
539
 
6048 hendricks2 540
        New->z += dz;
5196 hendricks2 541
        dz += nz;
542
 
6048 hendricks2 543
        New->xrepeat = xrepeat;
544
        New->yrepeat = yrepeat;
5196 hendricks2 545
 
546
        xrepeat -= repeat_adj;
547
        yrepeat -= repeat_adj;
548
 
549
        spritesortcnt++;
550
    }
551
 
552
}
553
 
5198 hendricks2 554
void SetVoxelSprite(SPRITEp sp, short pic)
5196 hendricks2 555
{
6657 pogokeen 556
    SET(sp->cstat, CSTAT_SPRITE_ALIGNMENT_SLAB);
5196 hendricks2 557
    sp->picnum = pic;
558
}
559
 
5198 hendricks2 560
void WarpCopySprite(void)
5196 hendricks2 561
{
6042 hendricks2 562
    SPRITEp sp1, sp2, sp;
5196 hendricks2 563
    short sn, nsn;
564
    short sn2, nsn2;
565
    short spnum, next_spnum;
566
    int xoff,yoff,zoff;
567
    short match;
568
    short sect1, sect2;
569
 
570
    // look for the first one
571
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP_COPY_SPRITE1], sn, nsn)
572
    {
573
        sp1 = &sprite[sn];
574
        match = sp1->lotag;
575
 
576
        // look for the second one
577
        TRAVERSE_SPRITE_STAT(headspritestat[STAT_WARP_COPY_SPRITE2], sn2, nsn2)
578
        {
579
            sp = &sprite[sn2];
580
 
581
            if (sp->lotag == match)
582
            {
583
                sp2 = sp;
584
                sect1 = sp1->sectnum;
585
                sect2 = sp2->sectnum;
586
 
587
                TRAVERSE_SPRITE_SECT(headspritesect[sect1], spnum, next_spnum)
588
                {
589
                    if (&sprite[spnum] == sp1)
590
                        continue;
591
 
592
                    if (sprite[spnum].picnum == ST1)
593
                        continue;
594
 
8521 hendricks2 595
                    tspriteptr_t New = renderAddTSpriteFromSprite(spnum);
6048 hendricks2 596
                    New->statnum = 0;
5196 hendricks2 597
 
6048 hendricks2 598
                    xoff = sp1->x - New->x;
599
                    yoff = sp1->y - New->y;
600
                    zoff = sp1->z - New->z;
5196 hendricks2 601
 
6048 hendricks2 602
                    New->x = sp2->x - xoff;
603
                    New->y = sp2->y - yoff;
604
                    New->z = sp2->z - zoff;
605
                    New->sectnum = sp2->sectnum;
5196 hendricks2 606
                }
607
 
608
                TRAVERSE_SPRITE_SECT(headspritesect[sect2], spnum, next_spnum)
609
                {
610
                    if (&sprite[spnum] == sp2)
611
                        continue;
612
 
613
                    if (sprite[spnum].picnum == ST1)
614
                        continue;
615
 
8521 hendricks2 616
                    tspriteptr_t New = renderAddTSpriteFromSprite(spnum);
6048 hendricks2 617
                    New->statnum = 0;
5196 hendricks2 618
 
6048 hendricks2 619
                    xoff = sp2->x - New->x;
620
                    yoff = sp2->y - New->y;
621
                    zoff = sp2->z - New->z;
5196 hendricks2 622
 
6048 hendricks2 623
                    New->x = sp1->x - xoff;
624
                    New->y = sp1->y - yoff;
625
                    New->z = sp1->z - zoff;
626
                    New->sectnum = sp1->sectnum;
5196 hendricks2 627
                }
628
            }
629
        }
630
    }
631
}
632
 
8519 hendricks2 633
void DoStarView(tspriteptr_t tsp, USERp tu, int viewz)
5196 hendricks2 634
{
635
    extern STATE s_Star[], s_StarDown[];
636
    extern STATE s_StarStuck[], s_StarDownStuck[];
637
    int zdiff = viewz - tsp->z;
638
 
639
    if (labs(zdiff) > Z(24))
640
    {
641
        if (tu->StateStart == s_StarStuck)
642
            tsp->picnum = s_StarDownStuck[tu->State - s_StarStuck].Pic;
643
        else
644
            tsp->picnum = s_StarDown[tu->State - s_Star].Pic;
645
 
646
        if (zdiff > 0)
647
            SET(tsp->cstat, CSTAT_SPRITE_YFLIP);
648
    }
649
    else
650
    {
651
        if (zdiff > 0)
652
            SET(tsp->cstat, CSTAT_SPRITE_YFLIP);
653
    }
654
}
655
 
5198 hendricks2 656
void
657
analyzesprites(int viewx, int viewy, int viewz, SWBOOL mirror)
5196 hendricks2 658
{
8685 ny00123 659
    int tSpriteNum;
660
    short SpriteNum;
5196 hendricks2 661
    int smr4, smr2;
662
    USERp tu;
663
    static int ang = 0;
664
    PLAYERp pp = Player + screenpeek;
665
    short newshade=0;
666
 
667
 
668
    ang = NORM_ANGLE(ang + 12);
669
 
670
    smr4 = smoothratio + (((int) MoveSkip4) << 16);
671
    smr2 = smoothratio + (((int) MoveSkip2) << 16);
672
 
673
    for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--)
674
    {
675
        SpriteNum = tsprite[tSpriteNum].owner;
8519 hendricks2 676
        tspriteptr_t tsp = &tsprite[tSpriteNum];
5196 hendricks2 677
        tu = User[SpriteNum];
678
 
679
        //if(tsp->statnum == STAT_GENERIC_QUEUE)
680
        //    CON_ConMessage("tsp->pal = %d",tsp->pal);
681
 
682
#if 0
683
        // Brighten up the sprite if set somewhere else to do so
684
        if (tu && tu->Vis > 0)
685
        {
686
            short tmpshade; // Having this prevent overflow
687
 
688
            tmpshade = tsp->shade  - tu->Vis;
689
            if (tmpshade < -128) tmpshade = -128;
690
 
691
            tsp->shade = tmpshade;
692
            tu->Vis -= 8;
693
        }
694
#endif
695
 
696
        // don't draw these
697
        if (tsp->statnum >= STAT_DONT_DRAW)
698
        {
699
            tsp->owner = -1;
700
            continue;
701
        }
702
 
703
        // Diss any parentally locked sprites
704
        if (gs.ParentalLock || Global_PLock)
705
        {
706
            if (aVoxelArray[tsp->picnum].Parental == 6145)
707
            {
708
                tsp->owner = -1;
709
                tu = NULL;
710
            }
711
            else if (aVoxelArray[tsp->picnum].Parental > 0)
712
            {
713
                ASSERT(aVoxelArray[tsp->picnum].Parental >= 0 && aVoxelArray[tsp->picnum].Parental < 6145);
714
                tsp->picnum=aVoxelArray[tsp->picnum].Parental; // Change the pic
715
            }
716
        }
717
 
718
        if (tu)
719
        {
720
            if (tsp->statnum != STAT_DEFAULT)
721
            {
722
                if (TEST(tu->Flags, SPR_SKIP4))
723
                {
724
                    if (tsp->statnum <= STAT_SKIP4_INTERP_END)
725
                    {
6254 hendricks2 726
                        tsp->x = tu->ox + mulscale18(tsp->x - tu->ox, smr4);
727
                        tsp->y = tu->oy + mulscale18(tsp->y - tu->oy, smr4);
728
                        tsp->z = tu->oz + mulscale18(tsp->z - tu->oz, smr4);
5196 hendricks2 729
                    }
730
                }
731
 
732
                if (TEST(tu->Flags, SPR_SKIP2))
733
                {
734
                    if (tsp->statnum <= STAT_SKIP2_INTERP_END)
735
                    {
6254 hendricks2 736
                        tsp->x = tu->ox + mulscale17(tsp->x - tu->ox, smr2);
737
                        tsp->y = tu->oy + mulscale17(tsp->y - tu->oy, smr2);
738
                        tsp->z = tu->oz + mulscale17(tsp->z - tu->oz, smr2);
5196 hendricks2 739
                    }
740
                }
741
            }
742
 
8598 hendricks2 743
            // workaround for mines and floor decals beneath the floor
744
            if (tsp->picnum == BETTY_R0 || tsp->picnum == FLOORBLOOD1)
8597 hendricks2 745
            {
746
                auto sp = (uspriteptr_t)&sprite[SpriteNum];
747
                int32_t const floorz = getflorzofslope(sp->sectnum, sp->x, sp->y);
748
                if (sp->z > floorz)
749
                    tsp->z = floorz;
750
            }
751
 
5196 hendricks2 752
            if (gs.Shadows && TEST(tu->Flags, SPR_SHADOW))
753
            {
754
                DoShadows(tsp, viewz);
755
            }
756
 
757
            //#define UK_VERSION 1
758
 
759
            //#define DART_REPEAT 6
760
            //#define DART_PIC 2233
8338 hendricks2 761
            if (gs.Darts)
5196 hendricks2 762
                if (tu->ID == 1793 || tsp->picnum == 1793)
763
                {
764
                    tsp->picnum = 2519;
765
                    tsp->xrepeat = 27;
766
                    tsp->yrepeat = 29;
767
                }
768
 
769
#define DART_PIC 2526
770
#define DART_REPEAT 16
771
            if (tu->ID == STAR1)
772
            {
8338 hendricks2 773
                if (gs.Darts)
5196 hendricks2 774
                {
775
                    tsp->picnum = DART_PIC;
776
                    tsp->ang = NORM_ANGLE(tsp->ang - 512 - 24);
777
                    tsp->xrepeat = tsp->yrepeat = DART_REPEAT;
6657 pogokeen 778
                    SET(tsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL);
5196 hendricks2 779
                }
780
                else
781
                    DoStarView(tsp, tu, viewz);
782
            }
783
 
784
            // rotation
785
            if (tu->RotNum > 0)
786
                SetActorRotation(tSpriteNum, viewx, viewy);
787
 
788
            if (tu->motion_blur_num)
789
            {
790
                DoMotionBlur(tsp);
791
            }
792
 
793
            // set palette lookup correctly
794
            if (tsp->pal != sector[tsp->sectnum].floorpal)
795
            {
796
                if (sector[tsp->sectnum].floorpal == PALETTE_DEFAULT)
797
                {
798
                    // default pal for sprite is stored in tu->spal
799
                    // mostly for players and other monster types
800
                    tsp->pal = tu->spal;
801
                }
802
                else
803
                {
804
                    // if sector pal is something other than default
805
                    SECT_USERp sectu = SectUser[tsp->sectnum];
5198 hendricks2 806
                    uint8_t pal = sector[tsp->sectnum].floorpal;
807
                    SWBOOL nosectpal=FALSE;
5196 hendricks2 808
 
809
                    // sprite does not take on the new pal if sector flag is set
810
                    if (sectu && TEST(sectu->flags, SECTFU_DONT_COPY_PALETTE))
811
                    {
812
                        pal = PALETTE_DEFAULT;
813
                        nosectpal = TRUE;
814
                    }
815
 
816
                    //if(tu->spal == PALETTE_DEFAULT)
817
                    if (tsp->hitag != SECTFU_DONT_COPY_PALETTE && tsp->hitag != LUMINOUS
818
                        && !nosectpal
819
                        && pal != PALETTE_FOG && pal != PALETTE_DIVE &&
820
                        pal != PALETTE_DIVE_LAVA)
821
                        tsp->pal = pal;
822
                    else
823
                        tsp->pal = tu->spal;
824
 
825
                }
826
            }
827
 
828
            // Sprite debug information mode
829
            if (tsp->hitag == 9997)
830
            {
831
                tsp->pal = PALETTE_RED_LIGHTING;
832
                // Turn it off, it gets reset by PrintSpriteInfo
833
                sprite[tu->SpriteNum].hitag = 0;
834
            }
835
        }
836
 
8338 hendricks2 837
        if (gs.Darts)
5196 hendricks2 838
            if (tsp->statnum == STAT_STAR_QUEUE)
839
            {
840
                tsp->picnum = DART_PIC;
841
                tsp->ang = NORM_ANGLE(tsp->ang - 512);
842
                tsp->xrepeat = tsp->yrepeat = DART_REPEAT;
6657 pogokeen 843
                SET(tsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL);
5196 hendricks2 844
            }
845
 
846
        // Call my sprite handler
847
        // Does autosizing and voxel handling
848
        JAnalyzeSprites(tsp);
849
 
850
        // only do this of you are a player sprite
851
        //if (tsp->statnum >= STAT_PLAYER0 && tsp->statnum < STAT_PLAYER0 + MAX_SW_PLAYERS)
852
        if (tu && tu->PlayerP)
853
        {
854
            // Shadow spell
855
            if (!TEST(tsp->cstat, CSTAT_SPRITE_TRANSLUCENT))
856
                ShadeSprite(tsp);
857
 
858
            // sw if its your playersprite
859
            //if ((Player + screenpeek)->PlayerSprite == SpriteNum)
860
            if ((Player + screenpeek)->PlayerSprite == tu->SpriteNum)
861
            {
862
                PLAYERp pp = Player + screenpeek;
863
                if (mirror || TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE|PF_VIEW_FROM_CAMERA))
864
                {
865
                    if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE))
866
                        SET(tsp->cstat, CSTAT_SPRITE_TRANSLUCENT);
867
 
868
                    if (TEST(pp->Flags, PF_CLIMBING))
869
                    {
870
                        // move sprite forward some so he looks like he's
871
                        // climbing
872
                        tsp->x = pp->six + MOVEx(128 + 80, tsp->ang);
873
                        tsp->y = pp->siy + MOVEy(128 + 80, tsp->ang);
874
                    }
875
                    else
876
                    {
877
                        tsp->x = pp->six;
878
                        tsp->y = pp->siy;
879
                    }
880
 
881
                    tsp->z = tsp->z + pp->siz;
882
                    tsp->ang = pp->siang;
883
                    //continue;
884
                }
885
                else
886
                {
887
                    // dont draw your sprite
888
                    tsp->owner = -1;
889
                    //SET(tsp->cstat, CSTAT_SPRITE_INVISIBLE);
890
                }
891
            }
892
        }
893
 
894
        if (OverlapDraw && FAF_ConnectArea(tsp->sectnum) && tsp->owner >= 0)
895
        {
8519 hendricks2 896
            EDUKE32_STATIC_ASSERT(sizeof(uspritetype) == sizeof(tspritetype)); // see TSPRITE_SIZE
897
            ConnectCopySprite((uspriteptr_t)tsp);
5196 hendricks2 898
        }
899
 
900
        //
901
        // kens original sprite shade code he moved out of the engine
902
        //
903
 
904
        switch (tsp->statnum)
905
        {
906
        case STAT_ENEMY:
907
        case STAT_DEAD_ACTOR:
908
        case STAT_FAF_COPY:
909
            break;
910
        default:
911
            newshade = tsp->shade;
912
            newshade += 6;
913
            if (newshade > 127) newshade = 127;
914
            tsp->shade = newshade;
915
        }
916
 
917
        if (TEST(sector[tsp->sectnum].ceilingstat, CEILING_STAT_PLAX))
918
        {
919
            newshade = tsp->shade;
920
            newshade += sector[tsp->sectnum].ceilingshade;
921
            if (newshade > 127) newshade = 127;
922
            if (newshade < -128) newshade = -128;
923
            tsp->shade = newshade;
924
        }
925
        else
926
        {
927
            newshade = tsp->shade;
928
            newshade += sector[tsp->sectnum].floorshade;
929
            if (newshade > 127) newshade = 127;
930
            if (newshade < -128) newshade = -128;
931
            tsp->shade = newshade;
932
        }
933
 
934
        if (tsp->hitag == 9998)
935
            tsp->shade = 127; // Invisible enemy ninjas
936
 
937
        // Correct shades for luminous sprites
938
        if (tsp->hitag == LUMINOUS)
939
        {
940
            tsp->shade = -128;
941
        }
942
 
943
        if (pp->NightVision && TEST(tsp->extra, SPRX_PLAYER_OR_ENEMY))
944
        {
945
            if (tu && tu->ID == TRASHCAN) continue; // Don't light up trashcan
946
 
947
            tsp->pal = PALETTE_ILLUMINATE;  // Make sprites REALLY bright green.
948
            tsp->shade = -128;
949
        }
950
 
951
        if (tu && tu->PlayerP)
952
        {
953
            if (TEST(tu->Flags2, SPR2_VIS_SHADING))
954
            {
955
                if ((Player + screenpeek)->PlayerSprite != tu->SpriteNum)
956
                {
957
                    if (!TEST(tu->PlayerP->Flags, PF_VIEW_FROM_OUTSIDE))
958
                    {
959
                        RESET(tsp->cstat, CSTAT_SPRITE_TRANSLUCENT);
960
                    }
961
                }
962
 
963
                tsp->shade = 12 - STD_RANDOM_RANGE(30);
964
            }
965
        }
966
    }
967
 
968
    WarpCopySprite();
969
 
970
}
971
 
972
#if 1
8519 hendricks2 973
tspriteptr_t get_tsprite(short SpriteNum)
5196 hendricks2 974
{
975
    int tSpriteNum;
976
 
977
    for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--)
978
    {
979
        if (tsprite[tSpriteNum].owner == SpriteNum)
980
            return &tsprite[tSpriteNum];
981
    }
982
 
983
    return NULL;
984
}
985
 
5198 hendricks2 986
void
5196 hendricks2 987
post_analyzesprites(void)
988
{
989
    int tSpriteNum;
990
    short SpriteNum;
991
    USERp tu;
992
 
993
    for (tSpriteNum = spritesortcnt - 1; tSpriteNum >= 0; tSpriteNum--)
994
    {
995
        SpriteNum = tsprite[tSpriteNum].owner;
996
        if (SpriteNum < 0) continue;    // JBF: verify this is safe
8519 hendricks2 997
        tspriteptr_t tsp = &tsprite[tSpriteNum];
5196 hendricks2 998
        tu = User[SpriteNum];
999
 
1000
        if (tu)
1001
        {
1002
            if (tu->ID == FIREBALL_FLAMES && tu->Attach >= 0)
1003
            {
6042 hendricks2 1004
                //uspritetype * const atsp = &sprite[tu->Attach];
8519 hendricks2 1005
                tspriteptr_t const atsp = get_tsprite(tu->Attach);
5196 hendricks2 1006
 
1007
                if (!atsp)
1008
                {
1009
                    //DSPRINTF(ds,"Attach not found");
1010
                    MONO_PRINT(ds);
1011
                    continue;
1012
                }
1013
 
1014
                tsp->x = atsp->x;
1015
                tsp->y = atsp->y;
1016
                // statnum is priority - draw this ALWAYS first at 0
1017
                // statnum is priority - draw this ALWAYS last at MAXSTATUS
1018
                if (TEST(atsp->extra, SPRX_BURNABLE))
1019
                {
1020
                    atsp->statnum = 1;
1021
                    tsp->statnum = 0;
1022
                }
1023
                else
1024
                    tsp->statnum = MAXSTATUS;
1025
            }
1026
        }
1027
    }
1028
}
1029
#endif
1030
 
8700 ny00123 1031
static ClockTicks mapzoomclock;
1032
 
5198 hendricks2 1033
void
5196 hendricks2 1034
ResizeView(PLAYERp pp)
1035
{
1036
    if (MenuInputMode || InputMode || HelpInputMode || ConPanel || ConInputMode || PauseKeySet)
1037
        return;
1038
 
1039
    if (dimensionmode == 2 || dimensionmode == 5 || dimensionmode == 6)
1040
    {
8700 ny00123 1041
        int32_t timepassed = (int32_t)(totalclock - mapzoomclock);
1042
        mapzoomclock += timepassed;
5196 hendricks2 1043
        if (PKEY_PRESSED(KEYSC_DASH)||PKEY_PRESSED(KEYSC_GMINUS))
8700 ny00123 1044
            zoom = max<int32_t>(zoom - mulscale7(timepassed * synctics, zoom), 48);
5196 hendricks2 1045
 
1046
        if (PKEY_PRESSED(KEYSC_EQUAL)||PKEY_PRESSED(KEYSC_GPLUS))
8700 ny00123 1047
            zoom = min<int32_t>(zoom + mulscale7(timepassed * synctics, zoom), 4096);
5196 hendricks2 1048
 
1049
        if (KEY_PRESSED(KEYSC_ESC))
1050
        {
5198 hendricks2 1051
            extern SWBOOL ScrollMode2D;
5196 hendricks2 1052
 
1053
            KEY_PRESSED(KEYSC_ESC) = 0;
1054
            dimensionmode = 3;
1055
            ScrollMode2D = FALSE;
1056
            SetRedrawScreen(pp);
1057
        }
1058
    }
1059
    else
1060
    {
1061
        if (BUTTON(gamefunc_Shrink_Screen))      // &&
1062
        // !BUTTONHELD(gamefunc_SizeVi
1063
        // ewDown))
1064
        {
1065
            CONTROL_ClearButton(gamefunc_Shrink_Screen);
1066
            SetBorder(pp, gs.BorderNum + 1);
1067
            SetRedrawScreen(pp);
1068
        }
1069
 
1070
        if (BUTTON(gamefunc_Enlarge_Screen)) // &&
1071
        // !BUTTONHELD(gamefunc_SizeViewUp))
1072
        {
1073
            CONTROL_ClearButton(gamefunc_Enlarge_Screen);
1074
            SetBorder(pp, gs.BorderNum - 1);
1075
            SetRedrawScreen(pp);
1076
        }
1077
    }
1078
}
1079
 
1080
// !JIM! 08/06
5198 hendricks2 1081
extern SWBOOL UsingMenus;
5196 hendricks2 1082
 
1083
#if 0
5198 hendricks2 1084
void
1085
ViewOutsidePlayerRecurse(PLAYERp pp, int32_t* vx, int32_t* vy, int32_t* vz, int16_t* ang, int16_t* vsectnum)
5196 hendricks2 1086
{
1087
    int nx, ny;
1088
    int ret;
1089
 
1090
    *vx = pp->posx;
1091
    *vy = pp->posy;
1092
    *vz = pp->posz;
1093
    *vsectnum = pp->cursectnum;
1094
 
1095
    *ang = pp->pang + pp->view_outside_dang;
1096
 
1097
    nx = sintable[NORM_ANGLE(*ang + 512 + 1024)] << 11;
1098
    ny = sintable[NORM_ANGLE(*ang + 1024)] << 11;
1099
 
5201 hendricks2 1100
    ret = clipmove_old(vx, vy, vz, vsectnum, nx, ny, 64L, 4 << 8, 4 << 8, CLIPMASK_PLAYER);
5196 hendricks2 1101
 
1102
    switch (TEST(ret, HIT_MASK))
1103
    {
1104
    case HIT_SPRITE:
1105
    {
5202 hendricks2 1106
        short hit_sprite;
5196 hendricks2 1107
        SPRITEp sp;
1108
 
5202 hendricks2 1109
        hit_sprite = NORM_SPRITE(ret);
1110
        sp = &sprite[hit_sprite];
5196 hendricks2 1111
 
1112
        // if you hit a sprite that's not a wall sprite - try again
6657 pogokeen 1113
        if (!TEST(sp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
5196 hendricks2 1114
        {
1115
            FLIP(sp->cstat, CSTAT_SPRITE_BLOCK);
1116
            ViewOutsidePlayerRecurse(pp, vx, vy, vz, ang, vsectnum);
1117
            FLIP(sp->cstat, CSTAT_SPRITE_BLOCK);
1118
        }
1119
 
1120
        break;
1121
    }
1122
    }
1123
 
1124
    if (TEST(sector[*vsectnum].floorstat, FLOOR_STAT_SLOPE)|TEST(sector[*vsectnum].ceilingstat, CEILING_STAT_SLOPE))
1125
    {
1126
        int cz, fz;
1127
 
1128
        getzsofslope(*vsectnum, *vx, *vy, &cz, &fz);
1129
 
1130
        if (*vz > fz - Z(12))
1131
            *vz = fz - Z(12);
1132
 
1133
        if (*vz < cz + Z(12))
1134
            *vz = cz + Z(12);
1135
 
1136
    }
1137
}
1138
#endif
1139
 
1140
 
1141
 
1142
void
1143
BackView(int *nx, int *ny, int *nz, short *vsect, short *nang, short horiz)
1144
{
5202 hendricks2 1145
    vec3_t n = { *nx, *ny, *nz };
5196 hendricks2 1146
    SPRITEp sp;
5202 hendricks2 1147
    hitdata_t hitinfo;
8685 ny00123 1148
    int i, vx, vy, vz, hx, hy;
5202 hendricks2 1149
    short bakcstat, daang;
5196 hendricks2 1150
    PLAYERp pp = &Player[screenpeek];
1151
    short ang;
1152
 
1153
    ASSERT(*vsect >= 0 && *vsect < MAXSECTORS);
1154
 
1155
    ang = *nang + pp->view_outside_dang;
1156
 
1157
    // Calculate the vector (nx,ny,nz) to shoot backwards
1158
    vx = (sintable[NORM_ANGLE(ang + 1536)] >> 3);
1159
    vy = (sintable[NORM_ANGLE(ang + 1024)] >> 3);
1160
    vz = (horiz - 100) * 256L;
1161
 
1162
    // Player sprite of current view
1163
    sp = &sprite[pp->PlayerSprite];
1164
 
1165
    bakcstat = sp->cstat;
1166
    RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
1167
 
1168
    // Make sure sector passed to FAFhitscan is correct
1169
    //COVERupdatesector(*nx, *ny, vsect);
1170
 
5202 hendricks2 1171
    hitscan(&n, *vsect, vx, vy, vz,
1172
            &hitinfo, CLIPMASK_PLAYER);
5196 hendricks2 1173
 
1174
    ASSERT(*vsect >= 0 && *vsect < MAXSECTORS);
1175
 
1176
    sp->cstat = bakcstat;              // Restore cstat
1177
 
5202 hendricks2 1178
    hx = hitinfo.pos.x - (*nx);
1179
    hy = hitinfo.pos.y - (*ny);
5196 hendricks2 1180
 
1181
    // If something is in the way, make pp->camera_dist lower if necessary
1182
    if (klabs(vx) + klabs(vy) > klabs(hx) + klabs(hy))
1183
    {
5202 hendricks2 1184
        if (hitinfo.wall >= 0)               // Push you a little bit off the wall
5196 hendricks2 1185
        {
5202 hendricks2 1186
            *vsect = hitinfo.sect;
5196 hendricks2 1187
 
5202 hendricks2 1188
            daang = getangle(wall[wall[hitinfo.wall].point2].x - wall[hitinfo.wall].x,
1189
                             wall[wall[hitinfo.wall].point2].y - wall[hitinfo.wall].y);
5196 hendricks2 1190
 
1191
            i = vx * sintable[daang] + vy * sintable[NORM_ANGLE(daang + 1536)];
1192
            if (klabs(vx) > klabs(vy))
1193
                hx -= mulscale28(vx, i);
1194
            else
1195
                hy -= mulscale28(vy, i);
1196
        }
5202 hendricks2 1197
        else if (hitinfo.sprite < 0)        // Push you off the ceiling/floor
5196 hendricks2 1198
        {
5202 hendricks2 1199
            *vsect = hitinfo.sect;
5196 hendricks2 1200
 
1201
            if (klabs(vx) > klabs(vy))
1202
                hx -= (vx >> 5);
1203
            else
1204
                hy -= (vy >> 5);
1205
        }
1206
        else
1207
        {
5202 hendricks2 1208
            SPRITEp hsp = &sprite[hitinfo.sprite];
5196 hendricks2 1209
            int flag_backup;
1210
 
1211
            // if you hit a sprite that's not a wall sprite - try again
6657 pogokeen 1212
            if (!TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
5196 hendricks2 1213
            {
1214
                flag_backup = hsp->cstat;
1215
                RESET(hsp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
1216
                ASSERT(*vsect >= 0 && *vsect < MAXSECTORS);
1217
                BackView(nx, ny, nz, vsect, nang, horiz);
1218
                hsp->cstat = flag_backup;
1219
                return;
1220
            }
1221
            else
1222
            {
1223
                // same as wall calculation
1224
                daang = NORM_ANGLE(sp->ang-512);
1225
 
1226
                i = vx * sintable[daang] + vy * sintable[NORM_ANGLE(daang + 1536)];
1227
                if (klabs(vx) > klabs(vy))
1228
                    hx -= mulscale28(vx, i);
1229
                else
1230
                    hy -= mulscale28(vy, i);
1231
            }
1232
 
1233
        }
1234
 
1235
        if (klabs(vx) > klabs(vy))
1236
            i = (hx << 16) / vx;
1237
        else
1238
            i = (hy << 16) / vy;
1239
 
1240
        if (i < pp->camera_dist)
1241
            pp->camera_dist = i;
1242
    }
1243
 
1244
    // Actually move you!  (Camerdist is 65536 if nothing is in the way)
1245
    *nx = (*nx) + mulscale16(vx, pp->camera_dist);
1246
    *ny = (*ny) + mulscale16(vy, pp->camera_dist);
1247
    *nz = (*nz) + mulscale16(vz, pp->camera_dist);
1248
 
1249
    // Slowly increase pp->camera_dist until it reaches 65536
1250
    // Synctics is a timer variable so it increases the same rate
1251
    // on all speed computers
1252
    pp->camera_dist = min(pp->camera_dist + (3 << 10), 65536);
1253
    //pp->camera_dist = min(pp->camera_dist + (synctics << 10), 65536);
1254
 
1255
    // Make sure vsect is correct
1256
    updatesectorz(*nx, *ny, *nz, vsect);
1257
 
1258
    *nang = ang;
1259
}
1260
 
1261
void
1262
CircleCamera(int *nx, int *ny, int *nz, short *vsect, short *nang, short horiz)
1263
{
5202 hendricks2 1264
    vec3_t n = { *nx, *ny, *nz };
5196 hendricks2 1265
    SPRITEp sp;
5202 hendricks2 1266
    hitdata_t hitinfo;
8685 ny00123 1267
    int i, vx, vy, vz, hx, hy;
5202 hendricks2 1268
    short bakcstat, daang;
5196 hendricks2 1269
    PLAYERp pp = &Player[screenpeek];
1270
    short ang;
1271
 
1272
    ang = *nang + pp->circle_camera_ang;
1273
 
1274
    // Calculate the vector (nx,ny,nz) to shoot backwards
1275
    vx = (sintable[NORM_ANGLE(ang + 1536)] >> 4);
1276
    vy = (sintable[NORM_ANGLE(ang + 1024)] >> 4);
1277
 
1278
    // lengthen the vector some
1279
    vx += DIV2(vx);
1280
    vy += DIV2(vy);
1281
 
1282
    vz = (horiz - 100) * 256;
1283
 
1284
    // Player sprite of current view
1285
    sp = &sprite[pp->PlayerSprite];
1286
 
1287
    bakcstat = sp->cstat;
1288
    RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
1289
 
1290
    // Make sure sector passed to hitscan is correct
1291
    //COVERupdatesector(*nx, *ny, vsect);
1292
 
5202 hendricks2 1293
    hitscan(&n, *vsect, vx, vy, vz,
1294
            &hitinfo, CLIPMASK_MISSILE);
5196 hendricks2 1295
 
1296
    sp->cstat = bakcstat;              // Restore cstat
5202 hendricks2 1297
    //ASSERT(hitinfo.sect >= 0);
5196 hendricks2 1298
 
5202 hendricks2 1299
    hx = hitinfo.pos.x - (*nx);
1300
    hy = hitinfo.pos.y - (*ny);
5196 hendricks2 1301
 
1302
    // If something is in the way, make pp->circle_camera_dist lower if necessary
1303
    if (klabs(vx) + klabs(vy) > klabs(hx) + klabs(hy))
1304
    {
5202 hendricks2 1305
        if (hitinfo.wall >= 0)               // Push you a little bit off the wall
5196 hendricks2 1306
        {
5202 hendricks2 1307
            *vsect = hitinfo.sect;
5196 hendricks2 1308
 
5202 hendricks2 1309
            daang = getangle(wall[wall[hitinfo.wall].point2].x - wall[hitinfo.wall].x,
1310
                             wall[wall[hitinfo.wall].point2].y - wall[hitinfo.wall].y);
5196 hendricks2 1311
 
1312
            i = vx * sintable[daang] + vy * sintable[NORM_ANGLE(daang + 1536)];
1313
            if (klabs(vx) > klabs(vy))
1314
                hx -= mulscale28(vx, i);
1315
            else
1316
                hy -= mulscale28(vy, i);
1317
        }
5202 hendricks2 1318
        else if (hitinfo.sprite < 0)        // Push you off the ceiling/floor
5196 hendricks2 1319
        {
5202 hendricks2 1320
            *vsect = hitinfo.sect;
5196 hendricks2 1321
 
1322
            if (klabs(vx) > klabs(vy))
1323
                hx -= (vx >> 5);
1324
            else
1325
                hy -= (vy >> 5);
1326
        }
1327
        else
1328
        {
5202 hendricks2 1329
            SPRITEp hsp = &sprite[hitinfo.sprite];
5196 hendricks2 1330
            int flag_backup;
1331
 
1332
            // if you hit a sprite that's not a wall sprite - try again
6657 pogokeen 1333
            if (!TEST(hsp->cstat, CSTAT_SPRITE_ALIGNMENT_WALL))
5196 hendricks2 1334
            {
1335
                flag_backup = hsp->cstat;
1336
                RESET(hsp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
1337
 
1338
                CircleCamera(nx, ny, nz, vsect, nang, horiz);
1339
                hsp->cstat = flag_backup;
1340
                return;
1341
            }
1342
        }
1343
 
1344
        if (klabs(vx) > klabs(vy))
1345
            i = (hx << 16) / vx;
1346
        else
1347
            i = (hy << 16) / vy;
1348
 
1349
        if (i < pp->circle_camera_dist)
1350
            pp->circle_camera_dist = i;
1351
    }
1352
 
1353
    // Actually move you!  (Camerdist is 65536 if nothing is in the way)
1354
    *nx = (*nx) + ((vx * pp->circle_camera_dist) >> 16);
1355
    *ny = (*ny) + ((vy * pp->circle_camera_dist) >> 16);
1356
    *nz = (*nz) + ((vz * pp->circle_camera_dist) >> 16);
1357
 
1358
    // Slowly increase pp->circle_camera_dist until it reaches 65536
1359
    // Synctics is a timer variable so it increases the same rate
1360
    // on all speed computers
1361
    pp->circle_camera_dist = min(pp->circle_camera_dist + (3 << 8), 65536);
1362
    //pp->circle_camera_dist = min(pp->circle_camera_dist + (synctics << 10), 65536);
1363
 
1364
    // Make sure vsect is correct
1365
    updatesectorz(*nx, *ny, *nz, vsect);
1366
 
1367
    *nang = ang;
1368
}
1369
 
5198 hendricks2 1370
void PrintLocationInfo(PLAYERp pp)
5196 hendricks2 1371
{
1372
#define Y_STEP 7
1373
#define AVERAGEFRAMES 16
5984 hendricks2 1374
    int x = windowxy1.x+2;
1375
    int y = windowxy1.y+2;
5196 hendricks2 1376
    static int frameval[AVERAGEFRAMES], framecnt = 0;
1377
    int i;
1378
 
1379
    if (LocationInfo)
1380
    {
1381
 
8050 pogokeen 1382
        i = (int32_t) totalclock;
5196 hendricks2 1383
        if (i != frameval[framecnt])
1384
        {
7505 hendricks2 1385
            sprintf(buffer, "FPS: %d", ((120 * AVERAGEFRAMES) / (i - frameval[framecnt])) + f_c);
1386
            printext256(x, y, 1, -1, buffer, 1);
5196 hendricks2 1387
            frameval[framecnt] = i;
1388
        }
1389
 
1390
        framecnt = ((framecnt + 1) & (AVERAGEFRAMES - 1));
1391
 
1392
        if (LocationInfo > 1)
1393
        {
1394
            y += Y_STEP;
1395
 
1396
            sprintf(buffer, "POSX:%d", pp->posx);
1397
            printext256(x, y, 1, -1, buffer, 1);
1398
            y += Y_STEP;
1399
            sprintf(buffer, "POSY:%d", pp->posy);
1400
            printext256(x, y, 1, -1, buffer, 1);
1401
            y += Y_STEP;
1402
            sprintf(buffer, "POSZ:%d", pp->posz);
1403
            printext256(x, y, 1, -1, buffer, 1);
1404
            y += Y_STEP;
5198 hendricks2 1405
            sprintf(buffer, "ANG:%d", (int32_t) pp->pang);
5196 hendricks2 1406
            printext256(x, y, 1, -1, buffer, 1);
1407
            y += Y_STEP;
1408
        }
1409
    }
1410
}
1411
 
5198 hendricks2 1412
SWBOOL DebugSecret = FALSE;
1413
void SecretInfo(PLAYERp pp)
5196 hendricks2 1414
{
1415
#define Y_STEP 7
1416
#define AVERAGEFRAMES 16
5984 hendricks2 1417
    int x = windowxy1.x+2;
1418
    int y = windowxy1.y+2+8;
5196 hendricks2 1419
    extern short LevelSecrets,TotalKillable;
1420
 
1421
    if (CommEnabled || numplayers > 1)
1422
        return;
1423
 
1424
    x = x / (xdim/320.0);
1425
    y = y / (ydim/200.0);
1426
 
1427
    if (gs.Stats)
1428
    {
1429
        sprintf(ds, "Kills %d/%d", Player->Kills, TotalKillable);
1430
        DisplayMiniBarSmString(pp, x, y, PAL_XLAT_BROWN, ds);
1431
 
1432
        sprintf(ds, "Secrets %d/%d", Player->SecretsFound, LevelSecrets);
1433
        DisplayMiniBarSmString(pp, x, y+10, PAL_XLAT_BROWN, ds);
1434
    }
1435
}
1436
 
5198 hendricks2 1437
void PrintSpriteInfo(PLAYERp pp)
5196 hendricks2 1438
{
1439
#define Y_STEP 7
5984 hendricks2 1440
    int x = windowxy1.x+2;
1441
    int y = windowxy1.y+2;
5196 hendricks2 1442
    SPRITEp sp;
1443
    USERp u;
1444
 
1445
    if (SpriteInfo && !LocationInfo)
1446
    {
5202 hendricks2 1447
        short hit_sprite = DoPickTarget(pp->SpriteP, 32, 2);
5196 hendricks2 1448
 
5202 hendricks2 1449
        sp = &sprite[hit_sprite];
1450
        u = User[hit_sprite];
5196 hendricks2 1451
 
1452
        sp->hitag = 9997; // Special tag to make the actor glow red for one frame
1453
 
1454
        y += Y_STEP;
1455
 
5202 hendricks2 1456
        if (hit_sprite == -1)
5196 hendricks2 1457
        {
1458
            sprintf(buffer, "SPRITENUM: NONE TARGETED");
1459
            printext256(x, y, 1, -1, buffer, 1);
1460
            return;
1461
        }
1462
        else
5202 hendricks2 1463
            sprintf(buffer, "SPRITENUM:%d", hit_sprite);
5196 hendricks2 1464
 
1465
        printext256(x, y, 1, -1, buffer, 1);
1466
        y += Y_STEP;
1467
        if (u)
1468
        {
1469
            sprintf(buffer, "ID:%d", u->ID);
1470
            printext256(x, y, 1, -1, buffer, 1);
1471
            y += Y_STEP;
1472
            sprintf(buffer, "PALETTE:%d", u->spal);
1473
            printext256(x, y, 1, -1, buffer, 1);
1474
            y += Y_STEP;
1475
            sprintf(buffer, "HEALTH:%d", u->Health);
1476
            printext256(x, y, 1, -1, buffer, 1);
1477
            y += Y_STEP;
1478
            sprintf(buffer, "WAITTICS:%d", u->WaitTics);
1479
            printext256(x, y, 1, -1, buffer, 1);
1480
            y += Y_STEP;
1481
            sprintf(buffer, "COUNTER:%d", u->Counter);
1482
            printext256(x, y, 1, -1, buffer, 1);
1483
            y += Y_STEP;
1484
            sprintf(buffer, "COUNTER2:%d", u->Counter);
1485
            printext256(x, y, 1, -1, buffer, 1);
1486
            y += Y_STEP;
1487
        }
1488
        if (SpriteInfo > 1)
1489
        {
7500 hendricks2 1490
            sprintf(buffer, "POSX:%d", TrackerCast(sp->x));
5196 hendricks2 1491
            printext256(x, y, 1, -1, buffer, 1);
1492
            y += Y_STEP;
7500 hendricks2 1493
            sprintf(buffer, "POSY:%d", TrackerCast(sp->y));
5196 hendricks2 1494
            printext256(x, y, 1, -1, buffer, 1);
1495
            y += Y_STEP;
7500 hendricks2 1496
            sprintf(buffer, "POSZ:%d", TrackerCast(sp->z));
5196 hendricks2 1497
            printext256(x, y, 1, -1, buffer, 1);
1498
            y += Y_STEP;
7500 hendricks2 1499
            sprintf(buffer, "ANG:%d", TrackerCast(sp->ang));
5196 hendricks2 1500
            printext256(x, y, 1, -1, buffer, 1);
1501
            y += Y_STEP;
1502
        }
1503
    }
1504
}
1505
 
1506
 
5198 hendricks2 1507
void SpriteSortList2D(int tx, int ty)
5196 hendricks2 1508
{
1509
    SPRITEp sp;
1510
    int i;
1511
    int dist,a,b,c;
1512
 
1513
    spritesortcnt = 0;
1514
    for (i = 0; i < MAXSPRITES; i++)
1515
    {
1516
        if (sprite[i].statnum < MAXSTATUS)
1517
        {
1518
            sp = &sprite[i];
1519
 
1520
            if (!TEST(sp->cstat, CSTAT_SPRITE_INVISIBLE) &&
1521
                (sp->xrepeat > 0) && (sp->yrepeat > 0) &&
1522
                (spritesortcnt < MAXSPRITESONSCREEN))
1523
            {
1524
                DISTANCE(tx,ty,sp->x,sp->y,dist,a,b,c);
1525
 
1526
                if (dist < 22000)
1527
                {
8521 hendricks2 1528
                    renderAddTSpriteFromSprite(i);
5196 hendricks2 1529
                }
1530
            }
1531
        }
1532
    }
1533
}
1534
 
1535
int COVERsetgamemode(int mode, int xdim, int ydim, int bpp)
1536
{
8591 hendricks2 1537
    ud_setup.ScreenHeight = ydim;
1538
    ud_setup.ScreenWidth  = xdim;
1539
    ud_setup.ScreenMode   = mode;
1540
    ud_setup.ScreenBPP    = bpp;
5196 hendricks2 1541
 
7509 hendricks2 1542
    // [JM] Should I be using upscalefactor here, or some SW equivalent to Duke's ud.detail? !CHECKME!
1543
    return (int)videoSetGameMode(mode,xdim,ydim,bpp,upscalefactor);
5196 hendricks2 1544
}
1545
 
1546
void CheatResChange(void)
1547
{
1548
    /*
1549
    extern char permanentupdate;
1550
    int i;
1551
 
1552
    // needs to be called from drawscreen - crashes otherwise
1553
 
1554
    //cycle through all vesa modes, then screen-buffer mode
1555
    if (vidoption == 1)
1556
        {
1557
        for(i=0;i < validmodecnt;i++)
1558
            {
1559
            if ((validmodexdim[i] == xdim) && (validmodeydim[i] == ydim))
1560
                {
1561
                if (i == validmodecnt-1)
1562
                    COVERsetgamemode(2,320L,200L);
1563
                else
1564
                    COVERsetgamemode(1,validmodexdim[i+1],validmodeydim[i+1]);
1565
                break;
1566
                }
1567
            }
1568
        }
1569
    else
1570
        {
1571
        if (validmodecnt > 0)
1572
            COVERsetgamemode(1,validmodexdim[0],validmodeydim[0]);
1573
        }
1574
 
1575
    permanentupdate = 0;
1576
 
1577
    SetupAspectRatio();
1578
    SetRedrawScreen(Player + myconnectindex);
1579
 
1580
    sprintf(ds,"%d x %d mode selected.", xdim, ydim);
1581
    PutStringInfo(Player + myconnectindex, ds);
1582
    */
1583
    PutStringInfo(Player + myconnectindex, "JonoF: Not now");
1584
}
1585
 
1586
#if 0
1587
void ResChange(void)
1588
{
1589
    extern char permanentupdate;
1590
    int i;
1591
 
1592
    static short sw_res[5];
1593
    static short res_ndx=0;
1594
 
1595
    // clear pages before and after res set for good measure
1596
    for (i = 0; i < numpages; i++)
1597
    {
1598
        clearview(0);
1599
        nextpage();
1600
    }
1601
 
1602
    // needs to be called from drawscreen - crashes otherwise
1603
 
1604
    if (res_ndx == 0)
1605
    {
1606
        // choose resolutions for shadow warrior
1607
        for (i=0; i < validmodecnt; i++)
1608
        {
1609
            if (validmodexdim[i] + validmodeydim[i] == 320 + 200)
1610
                sw_res[res_ndx++] = i;
1611
            else if (validmodexdim[i] + validmodeydim[i] == 640 + 400)
1612
                sw_res[res_ndx++] = i;
1613
            else if (validmodexdim[i] + validmodeydim[i] == 640 + 480)
1614
                sw_res[res_ndx++] = i;
1615
            else if (validmodexdim[i] + validmodeydim[i] == 800 + 600)
1616
                sw_res[res_ndx++] = i;
1617
        }
1618
    }
1619
 
1620
    //cycle through all sw modes, then screen-buffer mode
1621
    if (vidoption == 1)
1622
    {
1623
        for (i = 0; i < res_ndx; i++)
1624
        {
1625
            if ((validmodexdim[sw_res[i]] == xdim) && (validmodeydim[sw_res[i]] == ydim))
1626
            {
1627
                if (i >= res_ndx-1)
1628
                    COVERsetgamemode(2, 320L, 200L);
1629
                else
1630
                    COVERsetgamemode(1, validmodexdim[sw_res[i+1]], validmodeydim[sw_res[i+1]]);
1631
                break;
1632
            }
1633
        }
1634
 
1635
 
1636
        // if did not find current res then reset to 320x200
1637
        if (i >= res_ndx)
1638
            COVERsetgamemode(2, 320L, 200L);
1639
    }
1640
    else
1641
    {
1642
        if (validmodecnt > 0)
1643
            COVERsetgamemode(1, validmodexdim[0], validmodeydim[0]);
1644
    }
1645
 
1646
    permanentupdate = 0;
1647
 
1648
    for (i = 0; i < numpages; i++)
1649
    {
1650
        clearview(0);
1651
        nextpage();
1652
    }
1653
 
1654
    SetupAspectRatio();
1655
    SetRedrawScreen(Player + myconnectindex);
1656
 
1657
    sprintf(ds,"%d x %d mode selected.", xdim, ydim);
1658
    PutStringInfo(Player + myconnectindex, ds);
1659
}
1660
#endif
1661
 
5198 hendricks2 1662
void ScreenCaptureKeys(void)
5196 hendricks2 1663
{
1664
    if (ConPanel)
1665
        return;
1666
 
1667
    // screen capture
1668
    if (KEY_PRESSED(KEYSC_F12))
1669
    {
1670
        KEY_PRESSED(KEYSC_F12) = 0;
1671
        PauseAction();
8344 hendricks2 1672
        videoCaptureScreen("swcpxxxx.png", KEY_PRESSED(KEYSC_LSHIFT) | KEY_PRESSED(KEYSC_RSHIFT));
5196 hendricks2 1673
        ResumeAction();
1674
        PutStringInfo(Player + myconnectindex, "Screen Captured");
1675
    }
1676
}
1677
 
5198 hendricks2 1678
void DrawCheckKeys(PLAYERp pp)
5196 hendricks2 1679
{
5198 hendricks2 1680
    extern SWBOOL ResCheat;
5196 hendricks2 1681
 
1682
    /* JonoF: Who really needs this now?
8686 ny00123 1683
    extern SWBOOL PauseKeySet;
5196 hendricks2 1684
    if (KEY_PRESSED(KEYSC_F5) && !(KEY_PRESSED(KEYSC_RSHIFT) || KEY_PRESSED(KEYSC_LSHIFT) || KEY_PRESSED(KEYSC_ALT) || KEY_PRESSED(KEYSC_RALT)) && !PauseKeySet)
1685
        {
1686
        KEY_PRESSED(KEYSC_F5) = 0;
1687
        ResChange();
1688
        }
1689
    */
1690
 
1691
    if (ResCheat)
1692
    {
1693
        ResCheat = FALSE;
1694
        CheatResChange(); // allow all modes when cheating
1695
    }
1696
 
1697
    if (ConPanel) return;
1698
 
1699
    if (!InputMode)
1700
        ResizeView(pp);
1701
 
1702
    ScreenCaptureKeys();
1703
}
1704
 
1705
#if 0
8694 ny00123 1706
void DrawMessageInput(void)
5196 hendricks2 1707
{
1708
    short w,h;
5198 hendricks2 1709
    static SWBOOL cur_show;
5196 hendricks2 1710
    short c;
1711
 
1712
    // Used to make cursor fade in and out
1713
    c = 4-(sintable[(totalclock<<4)&2047]>>11);
1714
 
1715
    if (MessageInputMode)
1716
    {
1717
        MNU_MeasureString(MessageInputString, &w, &h);
1718
 
1719
        cur_show ^= 1;
1720
        if (cur_show)
1721
        {
1722
            MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,ROTATE_SPRITE_SCREEN_CLIP);
1723
            rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),c,0,
1724
                         (ROTATE_SPRITE_SCREEN_CLIP),0,0,xdim-1,ydim-1);
1725
        }
1726
        else
1727
        {
1728
            MNU_DrawString(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,1,ROTATE_SPRITE_SCREEN_CLIP);
1729
            rotatesprite((TEXT_XCENTER(w)+w+7)<<16,(MESSAGE_LINE+3)<<16,64<<9,0,COINCURSOR+((totalclock>>3)%7),c,0,
1730
                         (ROTATE_SPRITE_SCREEN_CLIP),0,0,xdim-1,ydim-1);
1731
        }
1732
    }
1733
}
1734
#else
8694 ny00123 1735
void DrawMessageInput(void)
5196 hendricks2 1736
{
1737
    short w,h;
5198 hendricks2 1738
    static SWBOOL cur_show;
5196 hendricks2 1739
    short c;
1740
 
1741
    // Used to make cursor fade in and out
8050 pogokeen 1742
    c = 4-(sintable[((int32_t) totalclock<<4)&2047]>>11);
5196 hendricks2 1743
 
1744
    if (MessageInputMode)
1745
    {
1746
        MNU_MeasureSmallString(MessageInputString, &w, &h);
1747
 
1748
        cur_show ^= 1;
1749
        if (cur_show)
1750
        {
8694 ny00123 1751
            minigametext(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,ROTATE_SPRITE_SCREEN_CLIP);
8050 pogokeen 1752
            rotatesprite((TEXT_XCENTER(w)+w+2)<<16,(MESSAGE_LINE+1)<<16,20000,0,COINCURSOR+(((int32_t) totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1);
5196 hendricks2 1753
        }
1754
        else
1755
        {
8694 ny00123 1756
            minigametext(TEXT_XCENTER(w), MESSAGE_LINE, MessageInputString,ROTATE_SPRITE_SCREEN_CLIP);
8050 pogokeen 1757
            rotatesprite((TEXT_XCENTER(w)+w+2)<<16,(MESSAGE_LINE+1)<<16,20000,0,COINCURSOR+(((int32_t) totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1);
5196 hendricks2 1758
        }
1759
    }
1760
}
1761
#endif
1762
 
8694 ny00123 1763
void DrawConInput(void)
5196 hendricks2 1764
{
1765
#define PANELINPUTX 30
1766
#define PANELINPUTY 100
1767
    short w,h;
5198 hendricks2 1768
    static SWBOOL cur_show;
5196 hendricks2 1769
    short c;
1770
 
1771
    // Used to make cursor fade in and out
8050 pogokeen 1772
    c = 4-(sintable[((int32_t) totalclock<<4)&2047]>>11);
5196 hendricks2 1773
 
1774
    if (ConInputMode)
1775
    {
1776
        MNU_MeasureSmallString(MessageInputString, &w, &h);
1777
 
1778
        cur_show ^= 1;
1779
        if (cur_show)
1780
        {
1781
            MNU_DrawSmallString(PANELINPUTX, PANELINPUTY, MessageInputString,1,17);
1782
            rotatesprite((PANELINPUTX+w+1)<<16,(PANELINPUTY)<<16,65536L,0,2992,c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1);
1783
            //rotatesprite((PANELINPUTX+w+3)<<16,(PANELINPUTY)<<16,64<<8,0,COINCURSOR+((totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1);
1784
        }
1785
        else
1786
        {
1787
            MNU_DrawSmallString(PANELINPUTX, PANELINPUTY, MessageInputString,1,17);
1788
            rotatesprite((PANELINPUTX+w+1)<<16,(PANELINPUTY)<<16,65536L,0,2992,c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1);
1789
            //rotatesprite((PANELINPUTX+w+3)<<16,(PANELINPUTY)<<16,64<<8,0,COINCURSOR+((totalclock>>3)%7),c,0,ROTATE_SPRITE_SCREEN_CLIP,0,0,xdim-1,ydim-1);
1790
        }
1791
    }
1792
}
1793
 
5198 hendricks2 1794
void DrawCrosshair(PLAYERp pp)
5196 hendricks2 1795
{
5198 hendricks2 1796
    extern SWBOOL DemoMode,CameraTestMode;
5196 hendricks2 1797
 
1798
    if (!gs.Crosshair)
1799
        return;
1800
 
1801
    if (DemoMode || CameraTestMode)
1802
        return;
1803
 
1804
    if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE))
1805
        return;
1806
 
1807
    if (dimensionmode == 6)
1808
        return;
1809
 
1810
//  wdx = 160;
1811
//  wdy = 100;
1812
#if 0
1813
    if (gs.AutoAim)
1814
    {
1815
        int daz;
5202 hendricks2 1816
        short hit_sprite, daang;
8311 hendricks2 1817
        static int handle;
5196 hendricks2 1818
 
1819
        daz = pp->posz + pp->bob_z;
1820
        daang = 32;
5202 hendricks2 1821
        if ((hit_sprite = WeaponAutoAimHitscan(pp->SpriteP, &daz, &daang, FALSE)) != -1)
5196 hendricks2 1822
        {
5202 hendricks2 1823
            SPRITEp hp = &sprite[hit_sprite];
1824
            USERp hu = User[hit_sprite];
5738 hendricks2 1825
            vec2_t const zero = { 0, 0 };
5196 hendricks2 1826
 
1827
            // Find the delta coordinates from player to monster that is targeted
5738 hendricks2 1828
            vec2_t dxy = { hp->x - pp->posx, hp->y - pp->posy };
1829
            int dz = ((hp->z - (SPRITE_SIZE_Z(hit_sprite)/2)) - pp->posz) >> 4;
5196 hendricks2 1830
 
5738 hendricks2 1831
            rotatepoint(zero, dxy, (-pp->pang)&2047, &dxy);
5196 hendricks2 1832
 
5738 hendricks2 1833
            if (dxy.x == 0) return;
5196 hendricks2 1834
 
5984 hendricks2 1835
            wdx = windowxy1.x + ((windowxy2.x-windowxy1.x)/2);
1836
            wdy = windowxy1.y + ((windowxy2.y-windowxy1.y)/2);
5196 hendricks2 1837
 
5738 hendricks2 1838
            x = (dxy.y * wdx << 8) / dxy.x + (wdx << 8);
1839
            y = (dz * wdx << 8) / dxy.x + (wdy << 8);
5196 hendricks2 1840
 
1841
            y -= 100;
1842
            y += (pp->horiz*wdx)/160;
1843
 
1844
            if (pp->CurWpn == pp->Wpn[WPN_RAIL])
1845
            {
8311 hendricks2 1846
                if (!FX_SoundValidAndActive(handle))
5196 hendricks2 1847
                    handle = PlaySound(DIGI_RAILLOCKED, &pp->posx, &pp->posy, &pp->posz, v3df_follow|v3df_dontpan);
1848
            }
1849
        }
1850
        else
1851
        {
1852
            // It didn't target anything.
1853
            if (pp->CurWpn == pp->Wpn[WPN_RAIL])
1854
            {
8311 hendricks2 1855
                if (FX_SoundValidAndActive(handle))
1856
                {
5196 hendricks2 1857
                    FX_StopSound(handle);
8311 hendricks2 1858
                    handle = 0;
1859
                }
5196 hendricks2 1860
            }
1861
            goto NORMALXHAIR;
1862
        }
1863
 
1864
        rotatesprite(x << 8, y << 8, (1 << 16), 0,
1865
                     2326, 10, 0,
8524 hendricks2 1866
                     ROTATE_SPRITE_VIEW_CLIP, 0, 0, xdim - 1, ydim - 1);
5196 hendricks2 1867
    }
1868
    else
1869
#endif
1870
    {
1871
//NORMALXHAIR:
8524 hendricks2 1872
        rotatesprite(160<<16, 100<<16, (1 << 16), 0,
5196 hendricks2 1873
                     2326, 10, 0,
8524 hendricks2 1874
                     ROTATE_SPRITE_VIEW_CLIP, windowxy1.x, windowxy1.y, windowxy2.x, windowxy2.y);
5196 hendricks2 1875
    }
1876
 
1877
    //#define TITLE_ROT_FLAGS (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK)
1878
 
1879
}
1880
 
1881
void CameraView(PLAYERp pp, int *tx, int *ty, int *tz, short *tsectnum, short *tang, int *thoriz)
1882
{
1883
    int i,nexti;
1884
    short ang;
1885
    SPRITEp sp;
5198 hendricks2 1886
    SWBOOL found_camera = FALSE;
1887
    SWBOOL player_in_camera = FALSE;
1888
    SWBOOL FAFcansee_test;
1889
    SWBOOL ang_test;
5196 hendricks2 1890
 
1891
    if (pp == &Player[screenpeek])
1892
    {
1893
        TRAVERSE_SPRITE_STAT(headspritestat[STAT_DEMO_CAMERA], i, nexti)
1894
        {
1895
            sp = &sprite[i];
1896
 
1897
            ang = getangle(*tx - sp->x, *ty - sp->y);
1898
            ang_test  = GetDeltaAngle(sp->ang, ang) < sp->lotag;
1899
 
1900
            FAFcansee_test =
1901
                (FAFcansee(sp->x, sp->y, sp->z, sp->sectnum, *tx, *ty, *tz, pp->cursectnum) ||
1902
                 FAFcansee(sp->x, sp->y, sp->z, sp->sectnum, *tx, *ty, *tz + SPRITEp_SIZE_Z(pp->SpriteP), pp->cursectnum));
1903
 
1904
            player_in_camera = ang_test && FAFcansee_test;
1905
 
1906
            if (player_in_camera || pp->camera_check_time_delay > 0)
1907
            {
1908
 
1909
                // if your not in the camera but are still looking
1910
                // make sure that only the last camera shows you
1911
 
1912
                if (!player_in_camera && pp->camera_check_time_delay > 0)
1913
                {
1914
                    if (pp->last_camera_sp != sp)
1915
                        continue;
1916
                }
1917
 
1918
                switch (sp->clipdist)
1919
                {
1920
                case 1:
1921
                    pp->last_camera_sp = sp;
1922
                    CircleCamera(tx, ty, tz, tsectnum, tang, 100);
1923
                    found_camera = TRUE;
1924
                    break;
1925
 
1926
                default:
1927
                {
1928
                    int xvect,yvect,zvect,zdiff;
1929
 
1930
                    pp->last_camera_sp = sp;
1931
 
1932
                    xvect = sintable[NORM_ANGLE(ang + 512)] >> 3;
1933
                    yvect = sintable[NORM_ANGLE(ang)] >> 3;
1934
 
1935
                    zdiff = sp->z - *tz;
1936
                    if (labs(sp->x - *tx) > 1000)
1937
                        zvect = scale(xvect, zdiff, sp->x - *tx);
1938
                    else if (labs(sp->y - *ty) > 1000)
1939
                        zvect = scale(yvect, zdiff, sp->y - *ty);
1940
                    else if (sp->x - *tx != 0)
1941
                        zvect = scale(xvect, zdiff, sp->x - *tx);
1942
                    else if (sp->y - *ty != 0)
1943
                        zvect = scale(yvect, zdiff, sp->y - *ty);
1944
                    else
1945
                        zvect = 0;
1946
 
1947
                    // new horiz to player
1948
                    *thoriz = 100 - (zvect/256);
1949
                    *thoriz = max(*thoriz, PLAYER_HORIZ_MIN);
1950
                    *thoriz = min(*thoriz, PLAYER_HORIZ_MAX);
1951
 
1952
                    //DSPRINTF(ds,"xvect %d,yvect %d,zvect %d,thoriz %d",xvect,yvect,zvect,*thoriz);
1953
                    MONO_PRINT(ds);
1954
 
1955
                    *tang = ang;
1956
                    *tx = sp->x;
1957
                    *ty = sp->y;
1958
                    *tz = sp->z;
1959
                    *tsectnum = sp->sectnum;
1960
 
1961
                    found_camera = TRUE;
1962
                    break;
1963
                }
1964
                }
1965
            }
1966
 
1967
            if (found_camera)
1968
                break;
1969
        }
1970
    }
1971
 
1972
    // if you player_in_camera you definately have a camera
1973
    if (player_in_camera)
1974
    {
1975
        pp->camera_check_time_delay = 120/2;
1976
        SET(pp->Flags, PF_VIEW_FROM_CAMERA);
1977
 
1978
        ASSERT(found_camera);
1979
    }
1980
    else
1981
    // if you !player_in_camera you still might have a camera
1982
    // for a split second
1983
    {
1984
        if (found_camera)
1985
        {
1986
            SET(pp->Flags, PF_VIEW_FROM_CAMERA);
1987
        }
1988
        else
1989
        {
1990
            pp->circle_camera_ang = 0;
1991
            pp->circle_camera_dist = CIRCLE_CAMERA_DIST_MIN;
1992
            RESET(pp->Flags, PF_VIEW_FROM_CAMERA);
1993
        }
1994
    }
1995
}
1996
 
5198 hendricks2 1997
void
1998
PreDraw(void)
5196 hendricks2 1999
{
2000
    short i, nexti;
2001
 
2002
    PreDrawStackedWater();
2003
 
2004
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_FLOOR_SLOPE_DONT_DRAW], i, nexti)
2005
    {
2006
        RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_SLOPE);
2007
    }
2008
}
2009
 
5198 hendricks2 2010
void
2011
PostDraw(void)
5196 hendricks2 2012
{
2013
    short i, nexti;
2014
 
2015
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_FLOOR_SLOPE_DONT_DRAW], i, nexti)
2016
    {
2017
        SET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_SLOPE);
2018
    }
2019
 
2020
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_FAF_COPY], i, nexti)
2021
    {
2022
        if (User[i])
2023
        {
2024
            FreeMem(User[i]);
2025
            User[i] = NULL;
2026
        }
2027
 
2028
#if DEBUG
8686 ny00123 2029
        SPRITEp sp = &sprite[i];
2030
        short statnum = sp->statnum;
2031
        short sectnum = sp->sectnum;
5196 hendricks2 2032
        memset(sp, 0xCC, sizeof(SPRITE));
2033
        sp->statnum = statnum;
2034
        sp->sectnum = sectnum;
2035
#endif
2036
 
2037
        deletesprite(i);
2038
    }
2039
}
2040
 
6042 hendricks2 2041
int CopySprite(uspritetype const * tsp, short newsector)
5196 hendricks2 2042
{
6048 hendricks2 2043
    short New;
5196 hendricks2 2044
    SPRITEp sp;
2045
 
6048 hendricks2 2046
    New = COVERinsertsprite(newsector, STAT_FAF_COPY);
2047
    sp = &sprite[New];
5196 hendricks2 2048
 
2049
    sp->x = tsp->x;
2050
    sp->y = tsp->y;
2051
    sp->z = tsp->z;
2052
    sp->cstat = tsp->cstat;
2053
    sp->picnum = tsp->picnum;
2054
    sp->pal = tsp->pal;
2055
    sp->xrepeat = tsp->xrepeat;
2056
    sp->yrepeat = tsp->yrepeat;
2057
    sp->xoffset = tsp->xoffset;
2058
    sp->yoffset = tsp->yoffset;
2059
    sp->ang = tsp->ang;
2060
    sp->xvel = tsp->xvel;
2061
    sp->yvel = tsp->yvel;
2062
    sp->zvel = tsp->zvel;
2063
    sp->shade = tsp->shade;
2064
 
2065
    RESET(sp->cstat, CSTAT_SPRITE_BLOCK|CSTAT_SPRITE_BLOCK_HITSCAN);
2066
 
6048 hendricks2 2067
    return New;
5196 hendricks2 2068
}
2069
 
6042 hendricks2 2070
int ConnectCopySprite(uspritetype const * tsp)
5196 hendricks2 2071
{
2072
    short newsector;
2073
    int testz;
2074
 
2075
    if (FAF_ConnectCeiling(tsp->sectnum))
2076
    {
2077
        newsector = tsp->sectnum;
2078
        testz = SPRITEp_TOS(tsp) - Z(10);
2079
 
2080
        if (testz < sector[tsp->sectnum].ceilingz)
2081
            updatesectorz(tsp->x, tsp->y, testz, &newsector);
2082
 
2083
        if (newsector >= 0 && newsector != tsp->sectnum)
2084
        {
2085
            return CopySprite(tsp, newsector);
2086
        }
2087
    }
2088
 
2089
    if (FAF_ConnectFloor(tsp->sectnum))
2090
    {
2091
        newsector = tsp->sectnum;
2092
        testz = SPRITEp_BOS(tsp) + Z(10);
2093
 
2094
        if (testz > sector[tsp->sectnum].floorz)
2095
            updatesectorz(tsp->x, tsp->y, testz, &newsector);
2096
 
2097
        if (newsector >= 0 && newsector != tsp->sectnum)
2098
        {
2099
            return CopySprite(tsp, newsector);
2100
        }
2101
    }
2102
 
2103
    return -1;
2104
}
2105
 
2106
 
2107
void PreDrawStackedWater(void)
2108
{
2109
    short si,snexti;
2110
    short i,nexti;
8685 ny00123 2111
    SPRITEp sp;
5196 hendricks2 2112
    USERp u,nu;
6048 hendricks2 2113
    short New;
5196 hendricks2 2114
 
2115
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], si, snexti)
2116
    {
2117
        TRAVERSE_SPRITE_SECT(headspritesect[sprite[si].sectnum], i, nexti)
2118
        {
2119
            if (User[i])
2120
            {
2121
                if (sprite[i].statnum == STAT_ITEM)
2122
                    continue;
2123
 
2124
                if (sprite[i].statnum <= STAT_DEFAULT || sprite[i].statnum > STAT_PLAYER0 + MAX_SW_PLAYERS)
2125
                    continue;
2126
 
2127
                // code so that a copied sprite will not make another copy
2128
                if (User[i]->xchange == -989898)
2129
                    continue;
2130
 
2131
                sp = &sprite[i];
2132
                u = User[i];
2133
 
6048 hendricks2 2134
                New = ConnectCopySprite((uspritetype const *)sp);
2135
                if (New >= 0)
5196 hendricks2 2136
                {
2137
                    // spawn a user
6048 hendricks2 2138
                    User[New] = nu = (USERp)CallocMem(sizeof(USER), 1);
5196 hendricks2 2139
                    ASSERT(nu != NULL);
2140
 
2141
                    nu->xchange = -989898;
2142
 
2143
                    // copy everything reasonable from the user that
2144
                    // analyzesprites() needs to draw the image
2145
                    nu->State = u->State;
2146
                    nu->Rot = u->Rot;
2147
                    nu->StateStart = u->StateStart;
2148
                    nu->StateEnd = u->StateEnd;
2149
                    nu->ox = u->ox;
2150
                    nu->oy = u->oy;
2151
                    nu->oz = u->oz;
2152
                    nu->Flags = u->Flags;
2153
                    nu->Flags2 = u->Flags2;
2154
                    nu->RotNum = u->RotNum;
2155
                    nu->ID = u->ID;
2156
 
2157
                    // set these to other sprite for players draw
2158
                    nu->SpriteNum = i;
2159
                    nu->SpriteP = sp;
2160
 
2161
                    nu->PlayerP = u->PlayerP;
2162
                    nu->spal = u->spal;
2163
                }
2164
            }
2165
        }
2166
    }
2167
}
2168
 
2169
 
2170
void FAF_DrawRooms(int x, int y, int z, short ang, int horiz, short sectnum)
2171
{
2172
    short i,nexti;
2173
 
2174
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], i, nexti)
2175
    {
2176
        if (SPRITE_TAG3(i) == 0)
2177
        {
2178
            // back up ceilingpicnum and ceilingstat
2179
            SPRITE_TAG5(i) = sector[sprite[i].sectnum].ceilingpicnum;
2180
            sector[sprite[i].sectnum].ceilingpicnum = SPRITE_TAG2(i);
2181
            SPRITE_TAG4(i) = sector[sprite[i].sectnum].ceilingstat;
2182
            //SET(sector[sprite[i].sectnum].ceilingstat, ((int)SPRITE_TAG7(i))<<7);
2183
            SET(sector[sprite[i].sectnum].ceilingstat, SPRITE_TAG6(i));
2184
            RESET(sector[sprite[i].sectnum].ceilingstat, CEILING_STAT_PLAX);
2185
        }
2186
        else if (SPRITE_TAG3(i) == 1)
2187
        {
2188
            SPRITE_TAG5(i) = sector[sprite[i].sectnum].floorpicnum;
2189
            sector[sprite[i].sectnum].floorpicnum = SPRITE_TAG2(i);
2190
            SPRITE_TAG4(i) = sector[sprite[i].sectnum].floorstat;
2191
            //SET(sector[sprite[i].sectnum].floorstat, ((int)SPRITE_TAG7(i))<<7);
2192
            SET(sector[sprite[i].sectnum].floorstat, SPRITE_TAG6(i));
2193
            RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_PLAX);
2194
        }
2195
    }
2196
 
2197
    drawrooms(x,y,z,ang,horiz,sectnum);
2198
 
2199
    TRAVERSE_SPRITE_STAT(headspritestat[STAT_CEILING_FLOOR_PIC_OVERRIDE], i, nexti)
2200
    {
2201
        // manually set gotpic
2202
        if (TEST_GOTSECTOR(sprite[i].sectnum))
2203
        {
2204
            SET_GOTPIC(FAF_MIRROR_PIC);
2205
        }
2206
 
2207
        if (SPRITE_TAG3(i) == 0)
2208
        {
2209
            // restore ceilingpicnum and ceilingstat
2210
            sector[sprite[i].sectnum].ceilingpicnum = SPRITE_TAG5(i);
2211
            sector[sprite[i].sectnum].ceilingstat = SPRITE_TAG4(i);
2212
            //RESET(sector[sprite[i].sectnum].ceilingstat, CEILING_STAT_TYPE_MASK);
2213
            RESET(sector[sprite[i].sectnum].ceilingstat, CEILING_STAT_PLAX);
2214
        }
2215
        else if (SPRITE_TAG3(i) == 1)
2216
        {
2217
            sector[sprite[i].sectnum].floorpicnum = SPRITE_TAG5(i);
2218
            sector[sprite[i].sectnum].floorstat = SPRITE_TAG4(i);
2219
            //RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_TYPE_MASK);
2220
            RESET(sector[sprite[i].sectnum].floorstat, FLOOR_STAT_PLAX);
2221
        }
2222
    }
2223
}
2224
 
2225
short ScreenSavePic = FALSE;
2226
 
5198 hendricks2 2227
void
5196 hendricks2 2228
drawscreen(PLAYERp pp)
2229
{
5198 hendricks2 2230
    extern SWBOOL DemoMode,CameraTestMode;
8685 ny00123 2231
    int tx, ty, tz,thoriz;
5196 hendricks2 2232
    short tang,tsectnum;
2233
    short i,j;
2234
    int bob_amt = 0;
2235
    int quake_z, quake_x, quake_y;
2236
    short quake_ang;
5198 hendricks2 2237
    SWBOOL PicInView(short, SWBOOL);
2238
    extern SWBOOL FAF_DebugView;
5196 hendricks2 2239
    PLAYERp camerapp;                       // prediction player if prediction is on, else regular player
5198 hendricks2 2240
    void DoPlayerDiveMeter(PLAYERp pp);
5196 hendricks2 2241
 
2242
    // last valid stuff
2243
    static short lv_sectnum = -1;
2244
    static int lv_x, lv_y, lv_z;
2245
 
8346 hendricks2 2246
    int const viewingRange = viewingrange;
2247
 
5196 hendricks2 2248
    if (HelpInputMode)
2249
    {
7509 hendricks2 2250
        renderFlushPerms();
5196 hendricks2 2251
        // note - could put Order Info Pages at the top like this also
2252
 
2253
        rotatesprite(0,0,65536L,0,HelpPagePic[HelpPage],0,0,
2254
                     (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST),
2255
                     0, 0, xdim-1, ydim-1);
7509 hendricks2 2256
        videoNextPage();
5196 hendricks2 2257
 
2258
        return;
2259
    }
2260
 
2261
#if 0
2262
    if (TenScreenMode)
2263
    {
2264
#define TEN_PIC 5109
2265
 
2266
        flushperms();
2267
        // note - could put Order Info Pages at the top like this also
2268
        rotatesprite(0,0,65536L,0,TEN_PIC,0,0,
2269
                     (ROTATE_SPRITE_CORNER|ROTATE_SPRITE_SCREEN_CLIP|ROTATE_SPRITE_NON_MASK|ROTATE_SPRITE_IGNORE_START_MOST),
2270
                     0, 0, xdim-1, ydim-1);
2271
 
2272
        nextpage();
2273
        return;
2274
    }
2275
#endif
2276
 
7509 hendricks2 2277
    if (videoGetRenderMode() >= REND_POLYMOST)
5196 hendricks2 2278
        RedrawScreen = TRUE;
2279
 
2280
    DrawScreen = TRUE;
2281
    PreDraw();
2282
    // part of new border refresh method
2283
    if (RedrawScreen)
2284
    {
2285
        RedrawCompass = TRUE;
2286
        RedrawScreen = FALSE;
2287
        // get rid of all PERM sprites!
7509 hendricks2 2288
        renderFlushPerms();
5196 hendricks2 2289
        // get rid of all PANF_KILL_AFTER_SHOW sprites!
2290
        pFlushPerms(pp);
2291
        SetBorder(pp,gs.BorderNum);
2292
    }
2293
 
2294
    PreUpdatePanel();
2295
 
2296
 
8050 pogokeen 2297
    smoothratio = min(max(((int32_t) totalclock - ototalclock) * (65536 / synctics),0),65536);
5196 hendricks2 2298
 
2299
    if (!ScreenSavePic)
2300
    {
2301
        dointerpolations(smoothratio);                      // Stick at beginning of drawscreen
2302
        short_dointerpolations(smoothratio);                      // Stick at beginning of drawscreen
2303
    }
2304
 
2305
    // TENSW: when rendering with prediction, the only thing that counts should
2306
    // be the predicted player.
2307
    if (PredictionOn && CommEnabled && pp == Player+myconnectindex)
2308
        camerapp = ppp;
2309
    else
2310
        camerapp = pp;
2311
 
6254 hendricks2 2312
    tx = camerapp->oposx + mulscale16(camerapp->posx - camerapp->oposx, smoothratio);
2313
    ty = camerapp->oposy + mulscale16(camerapp->posy - camerapp->oposy, smoothratio);
2314
    tz = camerapp->oposz + mulscale16(camerapp->posz - camerapp->oposz, smoothratio);
2315
    tang = camerapp->oang + mulscale16(((camerapp->pang + 1024 - camerapp->oang) & 2047) - 1024, smoothratio);
2316
    thoriz = camerapp->ohoriz + mulscale16(camerapp->horiz - camerapp->ohoriz, smoothratio);
5196 hendricks2 2317
    tsectnum = camerapp->cursectnum;
2318
 
2319
    //ASSERT(tsectnum >= 0 && tsectnum <= MAXSECTORS);
2320
    // if updatesectorz is to sensitive try COVERupdatesector
2321
    //updatesectorz(tx, ty, tz, &tsectnum);
2322
 
2323
    COVERupdatesector(tx, ty, &tsectnum);
2324
 
2325
    if (tsectnum < 0)
2326
    {
8348 hendricks2 2327
#if 0
5196 hendricks2 2328
        // if we hit an invalid sector move to the last valid position for drawing
2329
        tsectnum = lv_sectnum;
2330
        tx = lv_x;
2331
        ty = lv_y;
2332
        tz = lv_z;
8348 hendricks2 2333
#endif
5196 hendricks2 2334
    }
2335
    else
2336
    {
2337
        // last valid stuff
2338
        lv_sectnum = tsectnum;
2339
        lv_x = tx;
2340
        lv_y = ty;
2341
        lv_z = tz;
2342
    }
2343
 
2344
    // with "last valid" code this should never happen
8348 hendricks2 2345
    // ASSERT(tsectnum >= 0 && tsectnum <= MAXSECTORS);
5196 hendricks2 2346
 
2347
    pp->six = tx;
2348
    pp->siy = ty;
2349
    pp->siz = tz - pp->posz;
2350
    pp->siang = tang;
2351
 
2352
    if (pp->sop_riding || pp->sop_control)
2353
    {
2354
        tx = pp->posx;
2355
        ty = pp->posy;
2356
        tz = pp->posz;
2357
        tang = pp->pang;
2358
        tsectnum = pp->cursectnum;
2359
        updatesectorz(tx, ty, tz, &tsectnum);
2360
 
2361
        pp->six = tx;
2362
        pp->siy = ty;
2363
        pp->siz = tz - pp->posz;
2364
        pp->siang = tang;
2365
    }
2366
 
2367
    QuakeViewChange(camerapp, &quake_z, &quake_x, &quake_y, &quake_ang);
5207 hendricks2 2368
    VisViewChange(camerapp, &g_visibility);
5196 hendricks2 2369
    tz = tz + quake_z;
2370
    tx = tx + quake_x;
2371
    ty = ty + quake_y;
2372
    //thoriz = thoriz + quake_x;
2373
    tang = NORM_ANGLE(tang + quake_ang);
2374
 
2375
    if (pp->sop_remote)
2376
    {
2377
        if (TEST_BOOL1(pp->remote_sprite))
2378
            tang = pp->remote_sprite->ang;
2379
        else
2380
            tang = getangle(pp->sop_remote->xmid - tx, pp->sop_remote->ymid - ty);
2381
    }
2382
 
2383
    //if (TEST(camerapp->Flags, PF_VIEW_FROM_OUTSIDE))
2384
    if (TEST(pp->Flags, PF_VIEW_FROM_OUTSIDE))
2385
    {
2386
        BackView(&tx, &ty, &tz, &tsectnum, &tang, thoriz);
2387
    }
2388
    else
2389
    {
2390
        bob_amt = camerapp->bob_amt;
2391
 
2392
        if (DemoMode || CameraTestMode)
2393
            CameraView(camerapp, &tx, &ty, &tz, &tsectnum, &tang, &thoriz);
2394
    }
2395
 
2396
    if (!TEST(pp->Flags, PF_VIEW_FROM_CAMERA|PF_VIEW_FROM_OUTSIDE))
2397
    {
2398
        tz += bob_amt;
2399
        tz += camerapp->bob_z;
2400
 
2401
        // recoil only when not in camera
2402
        //thoriz = thoriz + camerapp->recoil_horizoff;
2403
        thoriz = thoriz + pp->recoil_horizoff;
2404
        thoriz = max(thoriz, PLAYER_HORIZ_MIN);
2405
        thoriz = min(thoriz, PLAYER_HORIZ_MAX);
2406
    }
2407
 
8346 hendricks2 2408
    if (r_usenewaspect)
2409
    {
2410
        newaspect_enable = 1;
2411
        videoSetCorrectedAspect();
2412
    }
2413
 
5196 hendricks2 2414
    if (FAF_DebugView)
7509 hendricks2 2415
        videoClearViewableArea(255L);
5196 hendricks2 2416
 
2417
    OverlapDraw = TRUE;
2418
    DrawOverlapRoom(tx, ty, tz, tang, thoriz, tsectnum);
2419
    OverlapDraw = FALSE;
2420
 
2421
    if (dimensionmode != 6 && !ScreenSavePic)
2422
    {
2423
        // TEST this! Changed to camerapp
2424
        //JS_DrawMirrors(camerapp, tx, ty, tz, tang, thoriz);
2425
        JS_DrawMirrors(pp, tx, ty, tz, tang, thoriz);
2426
    }
2427
 
8766 ny00123 2428
    if (dimensionmode != 6 && !FAF_DebugView)
5196 hendricks2 2429
        FAF_DrawRooms(tx, ty, tz, tang, thoriz, tsectnum);
2430
 
2431
    analyzesprites(tx, ty, tz, FALSE);
2432
    post_analyzesprites();
7509 hendricks2 2433
    renderDrawMasks();
5196 hendricks2 2434
 
8346 hendricks2 2435
    if (r_usenewaspect)
2436
    {
2437
        newaspect_enable = 0;
2438
        renderSetAspect(viewingRange, tabledivide32_noinline(65536 * ydim * 8, xdim * 5));
2439
    }
2440
 
5196 hendricks2 2441
    UpdatePanel();
2442
 
2443
#define SLIME 2305
2444
    // Only animate lava if its picnum is on screen
2445
    // gotpic is a bit array where the tile number's bit is set
2446
    // whenever it is drawn (ceilings, walls, sprites, etc.)
2447
    if ((gotpic[SLIME >> 3] & (1 << (SLIME & 7))) > 0)
2448
    {
2449
        gotpic[SLIME >> 3] &= ~(1 << (SLIME & 7));
2450
 
2451
        if (waloff[SLIME])
2452
            movelava((char *) waloff[SLIME]);
2453
    }
2454
 
2455
 
2456
    i = pp->cursectnum;
2457
 
8348 hendricks2 2458
    if (i >= 0)
5196 hendricks2 2459
    {
2460
        show2dsector[i>>3] |= (1<<(i&7));
8348 hendricks2 2461
        walltype *wal = &wall[sector[i].wallptr];
2462
        for (j=sector[i].wallnum; j>0; j--,wal++)
2463
        {
2464
            i = wal->nextsector;
2465
            if (i < 0) continue;
2466
            if (wal->cstat&0x0071) continue;
2467
            uint16_t const nextwall = wal->nextwall;
2468
            if (nextwall < MAXWALLS && wall[nextwall].cstat&0x0071) continue;
2469
            if (sector[i].lotag == 32767) continue;
2470
            if (sector[i].ceilingz >= sector[i].floorz) continue;
2471
            show2dsector[i>>3] |= (1<<(i&7));
2472
        }
5196 hendricks2 2473
    }
2474
 
2475
    if ((dimensionmode == 5 || dimensionmode == 6) && pp == Player+myconnectindex)
2476
    {
5198 hendricks2 2477
        void MoveScrollMode2D(PLAYERp pp);
2478
        extern SWBOOL ScrollMode2D;
5196 hendricks2 2479
 
2480
        if (ScrollMode2D)
2481
        {
2482
            tx = Follow_posx;
2483
            ty = Follow_posy;
2484
        }
2485
 
2486
        for (j = 0; j < MAXSPRITES; j++)
2487
        {
2488
            // Don't show sprites tagged with 257
2489
            if (sprite[j].lotag == 257)
2490
            {
6657 pogokeen 2491
                if (TEST(sprite[j].cstat, CSTAT_SPRITE_ALIGNMENT_FLOOR))
5196 hendricks2 2492
                {
6657 pogokeen 2493
                    RESET(sprite[j].cstat, CSTAT_SPRITE_ALIGNMENT_FLOOR);
5196 hendricks2 2494
                    sprite[j].owner = -2;
2495
                }
2496
            }
2497
        }
2498
 
2499
        if (dimensionmode == 6)
2500
        {
7509 hendricks2 2501
            videoClearViewableArea(0L);
2502
            renderDrawMapView(tx, ty, zoom, tang);
5196 hendricks2 2503
        }
2504
 
2505
        // Draw the line map on top of texture 2d map or just stand alone
2506
        drawoverheadmap(tx, ty, zoom, tang);
2507
    }
2508
 
2509
    for (j = 0; j < MAXSPRITES; j++)
2510
    {
2511
        // Don't show sprites tagged with 257
2512
        if (sprite[j].lotag == 257 && sprite[j].owner == -2)
6657 pogokeen 2513
            SET(sprite[j].cstat, CSTAT_SPRITE_ALIGNMENT_FLOOR);
5196 hendricks2 2514
    }
2515
 
2516
    // if doing a screen save don't need to process the rest
2517
    if (ScreenSavePic)
2518
    {
2519
        DrawScreen = FALSE;
2520
        return;
2521
    }
2522
 
2523
    PrintLocationInfo(pp);
2524
    PrintSpriteInfo(pp);
2525
 
2526
#if SYNC_TEST
2527
    SyncStatMessage();
2528
#endif
2529
 
2530
    DrawCrosshair(pp);
2531
 
2532
 
2533
    operatefta();           // Draw all the user quotes in the quote array
2534
 
2535
    operateconfta();        // Draw messages in the console
2536
 
2537
    DoPlayerDiveMeter(pp); // Do the underwater breathing bar
2538
 
2539
    // Boss Health Meter, if Boss present
2540
    BossHealthMeter();
2541
 
2542
    if (ConInputMode)
2543
    {
8694 ny00123 2544
        DrawConInput();   // Console panel input mode
5196 hendricks2 2545
    }
2546
    else
8694 ny00123 2547
        DrawMessageInput();   // This is only used for non-multiplayer input now
5196 hendricks2 2548
 
2549
    DrawCompass(pp);
2550
    UpdateMiniBar(pp);
2551
 
2552
    if (UsingMenus)
2553
        MNU_DrawMenu();
2554
    else
2555
        SecretInfo(pp);
2556
 
7509 hendricks2 2557
    videoNextPage();
5196 hendricks2 2558
 
2559
#if SYNC_TEST
2560
    SyncStatMessage();
2561
#endif
2562
 
2563
    // certain input is done here - probably shouldn't be
2564
    DrawCheckKeys(pp);
2565
 
2566
    restoreinterpolations();                 // Stick at end of drawscreen
2567
    short_restoreinterpolations();                 // Stick at end of drawscreen
2568
 
2569
    PostDraw();
2570
    DrawScreen = FALSE;
2571
}
2572
 
5198 hendricks2 2573
void
5196 hendricks2 2574
DrawCompass(PLAYERp pp)
2575
{
2576
#define COMPASS_TIC     2380
2577
#define COMPASS_TIC2    2381
2578
 
2579
#define COMPASS_NORTH   2382
2580
#define COMPASS_NORTH2  2383
2581
 
2582
#define COMPASS_SOUTH   2384
2583
#define COMPASS_SOUTH2  2385
2584
 
2585
#define COMPASS_EAST    2386
2586
#define COMPASS_EAST2   2387
2587
 
2588
#define COMPASS_WEST    2388
2589
#define COMPASS_WEST2   2389
2590
 
2591
#define COMPASS_MID_TIC    2390
2592
#define COMPASS_MID_TIC2   2391
2593
 
2594
#define COMPASS_X   140
2595
#define COMPASS_Y   (162-5)
2596
 
2597
#define NORM_CANG(ang) (((ang) + 32) & 31)
2598
 
2599
    short start_ang,ang;
5204 hendricks2 2600
    short x_size = tilesiz[COMPASS_NORTH].x;
5196 hendricks2 2601
    short x;
2602
    short i;
2603
    int flags;
2604
 
2605
    static short CompassPic[32] =
2606
    {
2607
        COMPASS_EAST, COMPASS_EAST2,
2608
        COMPASS_TIC, COMPASS_TIC2,
2609
        COMPASS_MID_TIC, COMPASS_MID_TIC2,
2610
        COMPASS_TIC, COMPASS_TIC2,
2611
 
2612
        COMPASS_SOUTH, COMPASS_SOUTH2,
2613
        COMPASS_TIC, COMPASS_TIC2,
2614
        COMPASS_MID_TIC, COMPASS_MID_TIC2,
2615
        COMPASS_TIC, COMPASS_TIC2,
2616
 
2617
        COMPASS_WEST, COMPASS_WEST2,
2618
        COMPASS_TIC, COMPASS_TIC2,
2619
        COMPASS_MID_TIC, COMPASS_MID_TIC2,
2620
        COMPASS_TIC, COMPASS_TIC2,
2621
 
2622
        COMPASS_NORTH, COMPASS_NORTH2,
2623
        COMPASS_TIC, COMPASS_TIC2,
2624
        COMPASS_MID_TIC, COMPASS_MID_TIC2,
2625
        COMPASS_TIC, COMPASS_TIC2,
2626
    };
2627
 
2628
    static short CompassShade[10] =
2629
    {
2630
        //20, 16, 11, 6, 1, 1, 6, 11, 16, 20
2631
        25, 19, 15, 9, 1, 1, 9, 15, 19, 25
2632
    };
2633
 
5198 hendricks2 2634
    extern SWBOOL PanelUpdateMode;
5196 hendricks2 2635
 
2636
    if (!PanelUpdateMode)
2637
        return;
2638
 
2639
    if (gs.BorderNum < BORDER_BAR || pp - Player != screenpeek)
2640
        return;
2641
 
2642
    ang = pp->pang;
2643
 
2644
    if (pp->sop_remote)
2645
        ang = 0;
2646
 
2647
    start_ang = (ang + 32) >> 6;
2648
 
2649
    start_ang = NORM_CANG(start_ang - 4);
2650
 
2651
    flags = ROTATE_SPRITE_SCREEN_CLIP | ROTATE_SPRITE_CORNER;
8354 hendricks2 2652
    if (RedrawCompass && !UsingMenus)
5196 hendricks2 2653
    {
2654
        RedrawCompass = FALSE;
2655
        SET(flags, ROTATE_SPRITE_ALL_PAGES);
2656
    }
2657
 
2658
    for (i = 0, x = COMPASS_X; i < 10; i++)
2659
    {
2660
        rotatesprite(x << 16, COMPASS_Y << 16, (1 << 16), 0,
2661
                     CompassPic[NORM_CANG(start_ang + i)], CompassShade[i], 0,
2662
                     flags, 0, 0, xdim - 1, ydim - 1);
2663
        x += x_size;
2664
    }
2665
}
2666
 
2667
 
5198 hendricks2 2668
void ScreenTileLock(void)
5196 hendricks2 2669
{
2670
    walock[SAVE_SCREEN_TILE] = CACHE_LOCK_MAX;
2671
}
2672
 
5198 hendricks2 2673
void ScreenTileUnLock(void)
5196 hendricks2 2674
{
2675
    walock[SAVE_SCREEN_TILE] = CACHE_UNLOCK_MAX;
2676
}
2677
 
2678
int
8694 ny00123 2679
ScreenLoadSaveSetup(void)
5196 hendricks2 2680
{
2681
    // lock and allocate memory
2682
 
2683
    ScreenTileLock();
2684
 
2685
    if (!waloff[SAVE_SCREEN_TILE])
8250 hendricks2 2686
        g_cache.allocateBlock((intptr_t*)&waloff[SAVE_SCREEN_TILE], SAVE_SCREEN_XSIZE * SAVE_SCREEN_YSIZE, &walock[SAVE_SCREEN_TILE]);
5196 hendricks2 2687
 
5204 hendricks2 2688
    tilesiz[SAVE_SCREEN_TILE].x = SAVE_SCREEN_XSIZE;
2689
    tilesiz[SAVE_SCREEN_TILE].x = SAVE_SCREEN_YSIZE;
5196 hendricks2 2690
 
2691
    return SAVE_SCREEN_TILE;
2692
}
2693
 
2694
int
8694 ny00123 2695
ScreenSaveSetup(void)
5196 hendricks2 2696
{
8694 ny00123 2697
    ScreenLoadSaveSetup();
5196 hendricks2 2698
 
7509 hendricks2 2699
    renderSetTarget(SAVE_SCREEN_TILE, SAVE_SCREEN_YSIZE, SAVE_SCREEN_XSIZE);
5196 hendricks2 2700
 
2701
    ScreenSavePic = TRUE;
2702
    drawscreen(Player + myconnectindex);
2703
    ScreenSavePic = FALSE;
2704
 
7509 hendricks2 2705
    renderRestoreTarget();
5196 hendricks2 2706
 
2707
    return SAVE_SCREEN_TILE;
2708
}
2709
 
2710
 
2711
 
2712