Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
5611 terminx 3
Copyright (C) 2016 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
5 Plagman 20
*/
21
//-------------------------------------------------------------------------
22
 
5529 hendricks2 23
#define game_c_
24
 
110 terminx 25
#include "duke3d.h"
5611 terminx 26
#include "compat.h"
3221 hendricks2 27
#include "renderlayer.h"
5 Plagman 28
#include "osdfuncs.h"
29
#include "osdcmds.h"
1552 terminx 30
#include "crc32.h"
7443 hendricks2 31
#include "network.h"
1677 terminx 32
#include "menus.h"
33
#include "savegame.h"
34
#include "anim.h"
35
#include "demo.h"
2728 hendricks2 36
#include "input.h"
5359 hendricks2 37
#include "colmatch.h"
5611 terminx 38
#include "cheats.h"
5613 terminx 39
#include "sbar.h"
5618 terminx 40
#include "screens.h"
41
#include "cmdline.h"
5789 terminx 42
#include "palette.h"
5614 terminx 43
 
4989 terminx 44
#ifdef __ANDROID__
45
#include "android.h"
46
#endif
47
 
2721 helixhorne 48
#ifdef LUNATIC
3148 helixhorne 49
# include "lunatic_game.h"
2034 helixhorne 50
#endif
51
 
7359 hendricks2 52
#include "vfs.h"
53
 
3726 helixhorne 54
// Uncomment to prevent anything except mirrors from drawing. It is sensible to
4875 helixhorne 55
// also uncomment ENGINE_CLEAR_SCREEN in build/src/engine_priv.h.
3726 helixhorne 56
//#define DEBUG_MIRRORS_ONLY
57
 
1595 helixhorne 58
#if KRANDDEBUG
59
# define GAME_INLINE
60
# define GAME_STATIC
61
#else
62
# define GAME_INLINE inline
63
# define GAME_STATIC static
64
#endif
65
 
418 terminx 66
#ifdef _WIN32
3221 hendricks2 67
# include <shellapi.h>
68
# define UPDATEINTERVAL 604800 // 1w
69
# include "winbits.h"
933 terminx 70
#else
3221 hendricks2 71
# ifndef GEKKO
72
#  include <sys/ioctl.h>
73
# endif
1008 hnt_ts 74
#endif /* _WIN32 */
1587 terminx 75
 
6467 hendricks2 76
const char* AppProperName = APPNAME;
77
const char* AppTechnicalName = APPBASENAME;
4538 hendricks2 78
 
1587 terminx 79
int32_t g_quitDeadline = 0;
418 terminx 80
 
3405 helixhorne 81
#ifdef LUNATIC
82
camera_t g_camera;
83
#else
1205 terminx 84
int32_t g_cameraDistance = 0, g_cameraClock = 0;
3405 helixhorne 85
#endif
1587 terminx 86
static int32_t g_quickExit;
1632 terminx 87
 
1068 terminx 88
char boardfilename[BMAX_PATH] = {0}, currentboardfilename[BMAX_PATH] = {0};
1587 terminx 89
 
1205 terminx 90
int32_t voting = -1;
91
int32_t vote_map = -1, vote_episode = -1;
147 terminx 92
 
7729 pogokeen 93
int32_t g_BenchmarkMode = BENCHMARKMODE_OFF;
94
 
5611 terminx 95
int32_t g_Debug = 0;
249 terminx 96
 
7897 hendricks2 97
#ifndef EDUKE32_STANDALONE
98
static const char *defaultrtsfilename[GAMECOUNT] = { "DUKE.RTS", "NAM.RTS", "NAPALM.RTS", "WW2GI.RTS" };
99
#endif
1205 terminx 100
 
101
int32_t g_Shareware = 0;
102
 
1658 terminx 103
// This was 32 for a while, but I think lowering it to 24 will help things like the Dingoo.
104
// Ideally, we would look at our memory usage on our most cramped platform and figure out
105
// how much of that is needed for the underlying OS and things like SDL instead of guessing
2628 helixhorne 106
#ifndef GEKKO
6875 hendricks2 107
int32_t MAXCACHE1DSIZE = (96*1024*1024);
2628 helixhorne 108
#else
6875 hendricks2 109
int32_t MAXCACHE1DSIZE = (8*1024*1024);
2628 helixhorne 110
#endif
253 terminx 111
 
1205 terminx 112
int32_t tempwallptr;
249 terminx 113
 
1205 terminx 114
static int32_t nonsharedtimer;
249 terminx 115
 
1552 terminx 116
int32_t ticrandomseed;
117
 
1595 helixhorne 118
GAME_STATIC GAME_INLINE int32_t G_MoveLoop(void);
395 terminx 119
 
1205 terminx 120
int32_t hud_showmapname = 1;
937 terminx 121
 
1205 terminx 122
int32_t g_levelTextTime = 0;
1068 terminx 123
 
5922 terminx 124
int32_t r_maxfps = 60;
7287 terminx 125
int32_t r_maxfpsoffset = 0;
7304 terminx 126
double g_frameDelay = 0.0;
1086 terminx 127
 
1176 terminx 128
#if defined(RENDERTYPEWIN) && defined(USE_OPENGL)
1120 terminx 129
extern char forcegl;
130
#endif
131
 
1652 terminx 132
void M32RunScript(const char *s) { UNREFERENCED_PARAMETER(s); };  // needed for linking since it's referenced from build/src/osd.c
1649 helixhorne 133
 
2726 hendricks2 134
const char *G_DefaultRtsFile(void)
1909 terminx 135
{
7897 hendricks2 136
#ifndef EDUKE32_STANDALONE
2726 hendricks2 137
    if (DUKE)
138
        return defaultrtsfilename[GAME_DUKE];
139
    else if (WW2GI)
140
        return defaultrtsfilename[GAME_WW2GI];
141
    else if (NAPALM)
142
    {
2752 helixhorne 143
        if (!testkopen(defaultrtsfilename[GAME_NAPALM],0) && testkopen(defaultrtsfilename[GAME_NAM],0))
3618 hendricks2 144
            return defaultrtsfilename[GAME_NAM]; // NAM/NAPALM Sharing
2726 hendricks2 145
        else
146
            return defaultrtsfilename[GAME_NAPALM];
147
    }
148
    else if (NAM)
149
    {
2752 helixhorne 150
        if (!testkopen(defaultrtsfilename[GAME_NAM],0) && testkopen(defaultrtsfilename[GAME_NAPALM],0))
3618 hendricks2 151
            return defaultrtsfilename[GAME_NAPALM]; // NAM/NAPALM Sharing
2726 hendricks2 152
        else
153
            return defaultrtsfilename[GAME_NAM];
154
    }
7897 hendricks2 155
#endif
1909 terminx 156
 
7897 hendricks2 157
    return "";
1909 terminx 158
}
159
 
1677 terminx 160
enum gametokens
335 terminx 161
{
505 terminx 162
    T_INCLUDE = 0,
249 terminx 163
    T_INTERFACE = 0,
505 terminx 164
    T_LOADGRP = 1,
249 terminx 165
    T_MODE = 1,
505 terminx 166
    T_CACHESIZE = 2,
626 terminx 167
    T_ALLOW = 2,
168
    T_NOAUTOLOAD,
1909 terminx 169
    T_INCLUDEDEFAULT,
634 terminx 170
    T_MUSIC,
171
    T_SOUND,
172
    T_FILE,
4987 terminx 173
    T_CUTSCENE,
2242 helixhorne 174
    T_ANIMSOUNDS,
2517 helixhorne 175
    T_NOFLOORPALRANGE,
4987 terminx 176
    T_ID,
7116 terminx 177
    T_MINPITCH,
178
    T_MAXPITCH,
179
    T_PRIORITY,
180
    T_TYPE,
181
    T_DISTANCE,
182
    T_VOLUME,
5140 hendricks2 183
    T_DELAY,
184
    T_RENAMEFILE,
5161 hendricks2 185
    T_GLOBALGAMEFLAGS,
6551 hendricks2 186
    T_ASPECT,
6552 hendricks2 187
    T_FORCEFILTER,
188
    T_FORCENOFILTER,
189
    T_TEXTUREFILTER,
7930 hendricks2 190
    T_NEWGAMECHOICES,
191
    T_CHOICE,
192
    T_NAME,
193
    T_LOCKED,
194
    T_HIDDEN,
249 terminx 195
};
196
 
1143 terminx 197
void G_HandleSpecialKeys(void)
5 Plagman 198
{
7211 terminx 199
    auto &myplayer = *g_player[myconnectindex].ps;
200
 
1552 terminx 201
    // we need CONTROL_GetInput in order to pick up joystick button presses
7211 terminx 202
    if (CONTROL_Started && !(myplayer.gm & MODE_GAME))
1552 terminx 203
    {
204
        ControlInfo noshareinfo;
205
        CONTROL_GetInput(&noshareinfo);
206
    }
207
 
1632 terminx 208
//    CONTROL_ProcessBinds();
808 terminx 209
 
1802 terminx 210
    if (g_networkMode != NET_DEDICATED_SERVER && ALT_IS_PRESSED && KB_KeyPressed(sc_Enter))
114 terminx 211
    {
7221 terminx 212
        if (videoSetGameMode(!ud.setup.fullscreen, ud.setup.xdim, ud.setup.ydim, ud.setup.bpp, ud.detail))
335 terminx 213
        {
909 terminx 214
            OSD_Printf(OSD_ERROR "Failed setting fullscreen video mode.\n");
7219 terminx 215
            if (videoSetGameMode(ud.setup.fullscreen, ud.setup.xdim, ud.setup.ydim, ud.setup.bpp, ud.detail))
1143 terminx 216
                G_GameExit("Failed to recover from failure to set fullscreen video mode.\n");
114 terminx 217
        }
7219 terminx 218
        else ud.setup.fullscreen = !ud.setup.fullscreen;
114 terminx 219
        KB_ClearKeyDown(sc_Enter);
1143 terminx 220
        g_restorePalette = 1;
221
        G_UpdateScreenArea();
114 terminx 222
    }
223
 
824 terminx 224
    if (KB_UnBoundKeyPressed(sc_F12))
472 terminx 225
    {
226
        KB_ClearKeyDown(sc_F12);
6831 terminx 227
        videoCaptureScreen(
6268 terminx 228
#ifndef EDUKE32_STANDALONE
6365 terminx 229
        "duke0000.tga"
6121 terminx 230
#else
6365 terminx 231
        "capt0000.tga"
6121 terminx 232
#endif
6365 terminx 233
        ,
234
        0);
7211 terminx 235
        P_DoQuote(QUOTE_SCREEN_SAVED, &myplayer);
472 terminx 236
    }
237
 
5 Plagman 238
    // only dispatch commands here when not in a game
7211 terminx 239
    if ((myplayer.gm & MODE_GAME) != MODE_GAME)
335 terminx 240
        OSD_DispatchQueued();
5 Plagman 241
 
7774 terminx 242
    if (g_quickExit == 0 && KB_KeyPressed(sc_LeftControl) && KB_KeyPressed(sc_LeftAlt) && KB_KeyPressed(sc_End))
5 Plagman 243
    {
1587 terminx 244
        g_quickExit = 1;
1143 terminx 245
        G_GameExit("Quick Exit.");
5 Plagman 246
    }
1143 terminx 247
}
5 Plagman 248
 
1571 terminx 249
void G_GameQuit(void)
1552 terminx 250
{
1574 terminx 251
    if (numplayers < 2)
252
        G_GameExit(" ");
253
 
254
    if (g_gameQuit == 0)
1552 terminx 255
    {
1593 terminx 256
        g_gameQuit = 1;
257
        g_quitDeadline = totalclock+120;
258
        g_netDisconnect = 1;
1552 terminx 259
    }
260
 
1587 terminx 261
    if ((totalclock > g_quitDeadline) && (g_gameQuit == 1))
1552 terminx 262
        G_GameExit("Timed out.");
263
}
264
 
5 Plagman 265
 
1205 terminx 266
int32_t A_CheckInventorySprite(spritetype *s)
5 Plagman 267
{
2297 helixhorne 268
    switch (DYNAMICTILEMAP(s->picnum))
5 Plagman 269
    {
337 terminx 270
    case FIRSTAID__STATIC:
271
    case STEROIDS__STATIC:
272
    case HEATSENSOR__STATIC:
273
    case BOOTS__STATIC:
274
    case JETPACK__STATIC:
275
    case HOLODUKE__STATIC:
276
    case AIRTANK__STATIC:
277
        return 1;
1672 terminx 278
    default:
279
        return 0;
5 Plagman 280
    }
281
}
282
 
283
 
7070 terminx 284
 
2723 helixhorne 285
void G_GameExit(const char *msg)
5 Plagman 286
{
2842 helixhorne 287
#ifdef LUNATIC
288
    El_PrintTimes();
4107 helixhorne 289
    El_DestroyState(&g_ElState);
2842 helixhorne 290
#endif
7162 terminx 291
    if (*msg != 0 && g_player[myconnectindex].ps != NULL)
292
        g_player[myconnectindex].ps->palette = BASEPAL;
5 Plagman 293
 
2995 helixhorne 294
    if (ud.recstat == 1)
295
        G_CloseDemoWrite();
335 terminx 296
    else if (ud.recstat == 2)
2995 helixhorne 297
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
298
    // JBF: fixes crash on demo playback
299
    // PK: modified from original
5 Plagman 300
 
1587 terminx 301
    if (!g_quickExit)
77 terminx 302
    {
6584 hendricks2 303
        if (VM_OnEventWithReturn(EVENT_EXITGAMESCREEN, g_player[myconnectindex].ps->i, myconnectindex, 0) == 0 &&
7211 terminx 304
           g_mostConcurrentPlayers > 1 && g_player[myconnectindex].ps->gm & MODE_GAME && GTFLAGS(GAMETYPE_SCORESHEET) && *msg == ' ')
77 terminx 305
        {
1143 terminx 306
            G_BonusScreen(1);
7221 terminx 307
            videoSetGameMode(ud.setup.fullscreen, ud.setup.xdim, ud.setup.ydim, ud.setup.bpp, ud.detail);
77 terminx 308
        }
5 Plagman 309
 
6584 hendricks2 310
        // shareware and TEN screens
311
        if (VM_OnEventWithReturn(EVENT_EXITPROGRAMSCREEN, g_player[myconnectindex].ps->i, myconnectindex, 0) == 0 &&
312
           *msg != 0 && *(msg+1) != 'V' && *(msg+1) != 'Y')
1143 terminx 313
            G_DisplayExtraScreens();
5 Plagman 314
    }
315
 
2723 helixhorne 316
    if (*msg != 0) initprintf("%s\n",msg);
1089 terminx 317
 
3823 helixhorne 318
    if (in3dmode())
1143 terminx 319
        G_Shutdown();
5 Plagman 320
 
2723 helixhorne 321
    if (*msg != 0)
5 Plagman 322
    {
2723 helixhorne 323
        if (!(msg[0] == ' ' && msg[1] == 0))
335 terminx 324
        {
1119 terminx 325
            char titlebuf[256];
1821 terminx 326
            Bsprintf(titlebuf,HEAD2 " %s",s_buildRev);
4558 hendricks2 327
            wm_msgbox(titlebuf, "%s", msg);
5 Plagman 328
        }
329
    }
330
 
2725 hendricks2 331
    Bfflush(NULL);
332
 
5 Plagman 333
    exit(0);
334
}
335
 
85 terminx 336
 
1892 helixhorne 337
#ifdef YAX_DEBUG
338
// ugh...
339
char m32_debugstr[64][128];
340
int32_t m32_numdebuglines=0;
341
 
342
static void M32_drawdebug(void)
343
{
6831 terminx 344
    int i, col=paletteGetClosestColor(255,255,255);
1892 helixhorne 345
    int x=4, y=8;
346
 
347
    if (m32_numdebuglines>0)
348
    {
6828 terminx 349
        videoBeginDrawing();
1892 helixhorne 350
        for (i=0; i<m32_numdebuglines && y<ydim-8; i++, y+=8)
351
            printext256(x,y,col,0,m32_debugstr[i],xdim>640?0:1);
6828 terminx 352
        videoEndDrawing();
1892 helixhorne 353
    }
354
    m32_numdebuglines=0;
355
}
356
#endif
357
 
2954 helixhorne 358
 
6725 terminx 359
static int32_t G_DoThirdPerson(const DukePlayer_t *pp, vec3_t *vect, int16_t *vsectnum, int16_t ang, int16_t horiz)
5 Plagman 360
{
7776 terminx 361
    auto const sp = &sprite[pp->i];
1208 terminx 362
    int32_t i, hx, hy;
1490 terminx 363
    int32_t bakcstat = sp->cstat;
2877 helixhorne 364
    hitdata_t hit;
6725 terminx 365
 
4369 helixhorne 366
    vec3_t n = {
367
        sintable[(ang+1536)&2047]>>4,
368
        sintable[(ang+1024)&2047]>>4,
6725 terminx 369
        (horiz-100) * 128
4226 helixhorne 370
    };
5 Plagman 371
 
1208 terminx 372
    updatesectorz(vect->x,vect->y,vect->z,vsectnum);
5 Plagman 373
 
4369 helixhorne 374
    sp->cstat &= ~0x101;
375
    hitscan(vect, *vsectnum, n.x,n.y,n.z, &hit, CLIPMASK1);
376
    sp->cstat = bakcstat;
377
 
331 terminx 378
    if (*vsectnum < 0)
4369 helixhorne 379
        return -1;
5 Plagman 380
 
2877 helixhorne 381
    hx = hit.pos.x-(vect->x);
382
    hy = hit.pos.y-(vect->y);
4369 helixhorne 383
 
1625 terminx 384
    if (klabs(n.x)+klabs(n.y) > klabs(hx)+klabs(hy))
5 Plagman 385
    {
2877 helixhorne 386
        *vsectnum = hit.sect;
4369 helixhorne 387
 
2877 helixhorne 388
        if (hit.wall >= 0)
5 Plagman 389
        {
6725 terminx 390
            int32_t daang = getangle(wall[wall[hit.wall].point2].x-wall[hit.wall].x,
2877 helixhorne 391
                             wall[wall[hit.wall].point2].y-wall[hit.wall].y);
5 Plagman 392
 
4369 helixhorne 393
            i = n.x*sintable[daang] + n.y*sintable[(daang+1536)&2047];
394
 
395
            if (klabs(n.x) > klabs(n.y))
396
                hx -= mulscale28(n.x,i);
1625 terminx 397
            else hy -= mulscale28(n.y,i);
5 Plagman 398
        }
2877 helixhorne 399
        else if (hit.sprite < 0)
5 Plagman 400
        {
4369 helixhorne 401
            if (klabs(n.x) > klabs(n.y))
402
                hx -= (n.x>>5);
1625 terminx 403
            else hy -= (n.y>>5);
5 Plagman 404
        }
4369 helixhorne 405
 
406
        if (klabs(n.x) > klabs(n.y))
407
            i = divscale16(hx,n.x);
1625 terminx 408
        else i = divscale16(hy,n.y);
4369 helixhorne 409
 
410
        if (i < CAMERADIST)
411
            CAMERADIST = i;
5 Plagman 412
    }
4369 helixhorne 413
 
3405 helixhorne 414
    vect->x += mulscale16(n.x,CAMERADIST);
415
    vect->y += mulscale16(n.y,CAMERADIST);
416
    vect->z += mulscale16(n.z,CAMERADIST);
5 Plagman 417
 
3405 helixhorne 418
    CAMERADIST = min(CAMERADIST+((totalclock-CAMERACLOCK)<<10),65536);
419
    CAMERACLOCK = totalclock;
5 Plagman 420
 
1208 terminx 421
    updatesectorz(vect->x,vect->y,vect->z,vsectnum);
5 Plagman 422
 
4369 helixhorne 423
    return 0;
5 Plagman 424
}
425
 
4228 helixhorne 426
#ifdef LEGACY_ROR
427
char ror_protectedsectors[MAXSECTORS];
428
static int32_t drawing_ror = 0;
1450 terminx 429
static int32_t ror_sprite = -1;
5 Plagman 430
 
7776 terminx 431
static void G_OROR_DupeSprites(spritetype const *sp)
4228 helixhorne 432
{
433
    // dupe the sprites touching the portal to the other sector
434
    int32_t k;
7776 terminx 435
    spritetype const *refsp;
5 Plagman 436
 
5835 terminx 437
    if ((unsigned)sp->yvel >= (unsigned)g_mostConcurrentPlayers)
4228 helixhorne 438
        return;
5 Plagman 439
 
4228 helixhorne 440
    refsp = &sprite[sp->yvel];
441
 
442
    for (SPRITES_OF_SECT(sp->sectnum, k))
443
    {
6347 terminx 444
        if (spritesortcnt >= maxspritesonscreen)
4228 helixhorne 445
            break;
446
 
447
        if (sprite[k].picnum != SECTOREFFECTOR && sprite[k].z >= sp->z)
448
        {
449
            Bmemcpy(&tsprite[spritesortcnt], &sprite[k], sizeof(spritetype));
450
 
451
            tsprite[spritesortcnt].x += (refsp->x - sp->x);
452
            tsprite[spritesortcnt].y += (refsp->y - sp->y);
453
            tsprite[spritesortcnt].z = tsprite[spritesortcnt].z - sp->z + actor[sp->yvel].ceilingz;
454
            tsprite[spritesortcnt].sectnum = refsp->sectnum;
455
            tsprite[spritesortcnt].owner = k;
5400 terminx 456
            tsprite[spritesortcnt].extra = 0;
4228 helixhorne 457
 
458
//            OSD_Printf("duped sprite of pic %d at %d %d %d\n",tsprite[spritesortcnt].picnum,tsprite[spritesortcnt].x,tsprite[spritesortcnt].y,tsprite[spritesortcnt].z);
459
            spritesortcnt++;
460
        }
461
    }
462
}
463
 
6998 terminx 464
static int16_t SE40backupStat[MAXSECTORS];
465
static int32_t SE40backupZ[MAXSECTORS];
466
 
2265 helixhorne 467
static void G_SE40(int32_t smoothratio)
5 Plagman 468
{
4228 helixhorne 469
    if ((unsigned)ror_sprite < MAXSPRITES)
1450 terminx 470
    {
471
        int32_t x, y, z;
472
        int16_t sect;
473
        int32_t level = 0;
7776 terminx 474
        auto const sp = &sprite[ror_sprite];
4228 helixhorne 475
        const int32_t sprite2 = sp->yvel;
5 Plagman 476
 
4228 helixhorne 477
        if ((unsigned)sprite2 >= MAXSPRITES)
478
            return;
479
 
1450 terminx 480
        if (klabs(sector[sp->sectnum].floorz - sp->z) < klabs(sector[sprite[sprite2].sectnum].floorz - sprite[sprite2].z))
481
            level = 1;
5 Plagman 482
 
3405 helixhorne 483
        x = CAMERA(pos.x) - sp->x;
484
        y = CAMERA(pos.y) - sp->y;
485
        z = CAMERA(pos.z) - (level ? sector[sp->sectnum].floorz : sector[sp->sectnum].ceilingz);
5 Plagman 486
 
1450 terminx 487
        sect = sprite[sprite2].sectnum;
488
        updatesector(sprite[sprite2].x + x, sprite[sprite2].y + y, &sect);
5 Plagman 489
 
1450 terminx 490
        if (sect != -1)
491
        {
492
            int32_t renderz, picnum;
4228 helixhorne 493
            // XXX: PK: too large stack allocation for my taste
1450 terminx 494
            int32_t i;
495
            int32_t pix_diff, newz;
496
            //                initprintf("drawing ror\n");
5 Plagman 497
 
1450 terminx 498
            if (level)
499
            {
500
                // renderz = sector[sprite[sprite2].sectnum].ceilingz;
4623 terminx 501
                renderz = sprite[sprite2].z - (sprite[sprite2].yrepeat * tilesiz[sprite[sprite2].picnum].y<<1);
1450 terminx 502
                picnum = sector[sprite[sprite2].sectnum].ceilingpicnum;
503
                sector[sprite[sprite2].sectnum].ceilingpicnum = 562;
4623 terminx 504
                tilesiz[562].x = tilesiz[562].y = 0;
5 Plagman 505
 
1450 terminx 506
                pix_diff = klabs(z) >> 8;
507
                newz = - ((pix_diff / 128) + 1) * (128<<8);
5 Plagman 508
 
1450 terminx 509
                for (i = 0; i < numsectors; i++)
510
                {
6998 terminx 511
                    SE40backupStat[i] = sector[i].ceilingstat;
512
                    SE40backupZ[i] = sector[i].ceilingz;
7046 terminx 513
                    if (!ror_protectedsectors[i] || sp->lotag == 41)
1450 terminx 514
                    {
515
                        sector[i].ceilingstat = 1;
516
                        sector[i].ceilingz += newz;
517
                    }
518
                }
519
            }
520
            else
521
            {
522
                // renderz = sector[sprite[sprite2].sectnum].floorz;
523
                renderz = sprite[sprite2].z;
524
                picnum = sector[sprite[sprite2].sectnum].floorpicnum;
525
                sector[sprite[sprite2].sectnum].floorpicnum = 562;
4623 terminx 526
                tilesiz[562].x = tilesiz[562].y = 0;
5 Plagman 527
 
1450 terminx 528
                pix_diff = klabs(z) >> 8;
529
                newz = ((pix_diff / 128) + 1) * (128<<8);
5 Plagman 530
 
1450 terminx 531
                for (i = 0; i < numsectors; i++)
532
                {
6998 terminx 533
                    SE40backupStat[i] = sector[i].floorstat;
534
                    SE40backupZ[i] = sector[i].floorz;
7046 terminx 535
                    if (!ror_protectedsectors[i] || sp->lotag == 41)
1450 terminx 536
                    {
537
                        sector[i].floorstat = 1;
538
                        sector[i].floorz = +newz;
539
                    }
540
                }
541
            }
5 Plagman 542
 
1642 terminx 543
#ifdef POLYMER
6829 terminx 544
            if (videoGetRenderMode() == REND_POLYMER)
6725 terminx 545
                polymer_setanimatesprites(G_DoSpriteAnimations, CAMERA(pos.x), CAMERA(pos.y), fix16_to_int(CAMERA(q16ang)), smoothratio);
1642 terminx 546
#endif
6831 terminx 547
            renderDrawRoomsQ16(sprite[sprite2].x + x, sprite[sprite2].y + y,
6725 terminx 548
                      z + renderz, CAMERA(q16ang), CAMERA(q16horiz), sect);
1450 terminx 549
            drawing_ror = 1 + level;
5 Plagman 550
 
1450 terminx 551
            if (drawing_ror == 2) // viewing from top
4228 helixhorne 552
                G_OROR_DupeSprites(sp);
5 Plagman 553
 
6725 terminx 554
            G_DoSpriteAnimations(CAMERA(pos.x),CAMERA(pos.y),fix16_to_int(CAMERA(q16ang)),smoothratio);
6831 terminx 555
            renderDrawMasks();
1450 terminx 556
 
557
            if (level)
5 Plagman 558
            {
1450 terminx 559
                sector[sprite[sprite2].sectnum].ceilingpicnum = picnum;
560
                for (i = 0; i < numsectors; i++)
561
                {
6998 terminx 562
                    sector[i].ceilingstat = SE40backupStat[i];
563
                    sector[i].ceilingz = SE40backupZ[i];
1450 terminx 564
                }
5 Plagman 565
            }
566
            else
567
            {
1450 terminx 568
                sector[sprite[sprite2].sectnum].floorpicnum = picnum;
5 Plagman 569
 
1450 terminx 570
                for (i = 0; i < numsectors; i++)
5 Plagman 571
                {
6998 terminx 572
                    sector[i].floorstat = SE40backupStat[i];
573
                    sector[i].floorz = SE40backupZ[i];
5 Plagman 574
                }
1450 terminx 575
            }
5 Plagman 576
        }
577
    }
578
}
4228 helixhorne 579
#endif
5 Plagman 580
 
6725 terminx 581
void G_HandleMirror(int32_t x, int32_t y, int32_t z, fix16_t a, fix16_t q16horiz, int32_t smoothratio)
2217 helixhorne 582
{
7876 terminx 583
    if ((gotpic[MIRROR>>3]&pow2char[MIRROR&7])
2217 helixhorne 584
#ifdef POLYMER
6829 terminx 585
        && (videoGetRenderMode() != REND_POLYMER)
2217 helixhorne 586
#endif
587
        )
588
    {
4879 helixhorne 589
        if (g_mirrorCount == 0)
590
        {
591
            // NOTE: We can have g_mirrorCount==0 but gotpic'd MIRROR,
592
            // for example in LNGA2.
7876 terminx 593
            gotpic[MIRROR>>3] &= ~pow2char[MIRROR&7];
7734 pogokeen 594
 
595
            //give scripts the chance to reset gotpics for effects that run in EVENT_DISPLAYROOMS
596
            //EVENT_RESETGOTPICS must be called after the last call to EVENT_DISPLAYROOMS in a frame, but before any engine-side renderDrawRoomsQ16
597
            VM_OnEvent(EVENT_RESETGOTPICS, -1, -1);
4879 helixhorne 598
            return;
599
        }
600
 
4861 helixhorne 601
        int32_t i = 0, dst = INT32_MAX;
2217 helixhorne 602
 
5829 terminx 603
        for (bssize_t k=g_mirrorCount-1; k>=0; k--)
2387 helixhorne 604
        {
6887 pogokeen 605
            if (!wallvisible(x, y, g_mirrorWall[k]))
606
                continue;
607
 
4861 helixhorne 608
            const int32_t j =
609
                klabs(wall[g_mirrorWall[k]].x - x) +
610
                klabs(wall[g_mirrorWall[k]].y - y);
2387 helixhorne 611
 
4861 helixhorne 612
            if (j < dst)
613
                dst = j, i = k;
2217 helixhorne 614
        }
615
 
2387 helixhorne 616
        if (wall[g_mirrorWall[i]].overpicnum != MIRROR)
617
        {
4861 helixhorne 618
            // Try to find a new mirror wall in case the original one was broken.
2387 helixhorne 619
 
620
            int32_t startwall = sector[g_mirrorSector[i]].wallptr;
621
            int32_t endwall = startwall + sector[g_mirrorSector[i]].wallnum;
622
 
5829 terminx 623
            for (bssize_t k=startwall; k<endwall; k++)
2387 helixhorne 624
            {
4861 helixhorne 625
                int32_t j = wall[k].nextwall;
2387 helixhorne 626
                if (j >= 0 && (wall[j].cstat&32) && wall[j].overpicnum==MIRROR)  // cmp. premap.c
627
                {
628
                    g_mirrorWall[i] = j;
629
                    break;
630
                }
631
            }
632
        }
633
 
2217 helixhorne 634
        if (wall[g_mirrorWall[i]].overpicnum == MIRROR)
635
        {
3719 helixhorne 636
            int32_t tposx, tposy;
6725 terminx 637
            fix16_t tang;
2217 helixhorne 638
 
7733 pogokeen 639
            //prepare to render any scripted EVENT_DISPLAYROOMS extras as mirrored
7736 pogokeen 640
            renderPrepareMirror(x, y, z, a, q16horiz, g_mirrorWall[i], &tposx, &tposy, &tang);
2217 helixhorne 641
 
4861 helixhorne 642
            int32_t j = g_visibility;
3287 helixhorne 643
            g_visibility = (j>>1) + (j>>2);
2217 helixhorne 644
 
7733 pogokeen 645
            //backup original camera position
646
            int32_t origCamX = CAMERA(pos.x);
647
            int32_t origCamY = CAMERA(pos.y);
648
            int32_t origCamZ = CAMERA(pos.z);
649
            fix16_t origCamq16ang = CAMERA(q16ang);
650
            fix16_t origCamq16horiz = CAMERA(q16horiz);
651
            //set the camera inside the mirror facing out
652
            CAMERA(pos.x) = tposx;
653
            CAMERA(pos.y) = tposy;
654
            CAMERA(pos.z) = z;
655
            CAMERA(q16ang) = tang;
656
            CAMERA(q16horiz) = q16horiz;
657
            display_mirror = 1;
658
            VM_OnEventWithReturn(EVENT_DISPLAYROOMS, g_player[0].ps->i, 0, 0);
659
            display_mirror = 0;
660
            //reset the camera position
661
            CAMERA(pos.x) = origCamX;
662
            CAMERA(pos.y) = origCamY;
663
            CAMERA(pos.z) = origCamZ;
664
            CAMERA(q16ang) = origCamq16ang;
665
            CAMERA(q16horiz) = origCamq16horiz;
666
 
7734 pogokeen 667
            //give scripts the chance to reset gotpics for effects that run in EVENT_DISPLAYROOMS
668
            //EVENT_RESETGOTPICS must be called after the last call to EVENT_DISPLAYROOMS in a frame, but before any engine-side renderDrawRoomsQ16
669
            VM_OnEvent(EVENT_RESETGOTPICS, -1, -1);
670
 
7733 pogokeen 671
            //prepare to render the mirror
7736 pogokeen 672
            renderPrepareMirror(x, y, z, a, q16horiz, g_mirrorWall[i], &tposx, &tposy, &tang);
7733 pogokeen 673
 
7493 hendricks2 674
            if (videoGetRenderMode() != REND_POLYMER)
2217 helixhorne 675
            {
2810 helixhorne 676
                int32_t didmirror;
677
 
2217 helixhorne 678
                yax_preparedrawrooms();
6831 terminx 679
                didmirror = renderDrawRoomsQ16(tposx,tposy,z,tang,q16horiz,g_mirrorSector[i]+MAXSECTORS);
7733 pogokeen 680
                //POGO: if didmirror == 0, we may simply wish to abort instead of rendering with yax_drawrooms (which may require cleaning yax state)
7803 pogokeen 681
                if (videoGetRenderMode() != REND_CLASSIC || didmirror)
682
                    yax_drawrooms(G_DoSpriteAnimations, g_mirrorSector[i], didmirror, smoothratio);
2217 helixhorne 683
            }
684
#ifdef USE_OPENGL
685
            else
6831 terminx 686
                renderDrawRoomsQ16(tposx,tposy,z,tang,q16horiz,g_mirrorSector[i]+MAXSECTORS);
2217 helixhorne 687
            // XXX: Sprites don't get drawn with TROR/Polymost
688
#endif
689
            display_mirror = 1;
6725 terminx 690
            G_DoSpriteAnimations(tposx,tposy,fix16_to_int(tang),smoothratio);
2217 helixhorne 691
            display_mirror = 0;
692
 
6831 terminx 693
            renderDrawMasks();
694
            renderCompleteMirror();   //Reverse screen x-wise in this function
3287 helixhorne 695
            g_visibility = j;
2217 helixhorne 696
        }
7733 pogokeen 697
    }
698
}
2217 helixhorne 699
 
7733 pogokeen 700
static void G_ClearGotMirror()
701
{
4249 hendricks2 702
#ifdef SPLITSCREEN_MOD_HACKS
7733 pogokeen 703
    if (!g_fakeMultiMode)
4249 hendricks2 704
#endif
7733 pogokeen 705
    {
706
        // HACK for splitscreen mod: this is so that mirrors will be drawn
707
        // from showview commands. Ugly, because we'll attempt do draw mirrors
708
        // each frame then. But it's better than not drawing them, I guess.
709
        // XXX: fix the sequence of setting/clearing this bit. Right now,
710
        // we always draw one frame without drawing the mirror, after which
711
        // the bit gets set and drawn subsequently.
7876 terminx 712
        gotpic[MIRROR>>3] &= ~pow2char[MIRROR&7];
2217 helixhorne 713
    }
714
}
715
 
3425 helixhorne 716
#ifdef USE_OPENGL
3420 helixhorne 717
static void G_ReadGLFrame(void)
718
{
719
    // Save OpenGL screenshot with Duke3D palette
720
    // NOTE: maybe need to move this to the engine...
6949 hendricks2 721
    palette_t *const frame = (palette_t *)Xcalloc(xdim * ydim, sizeof(palette_t));
3983 terminx 722
    char *const pic = (char *) waloff[TILE_SAVESHOT];
3420 helixhorne 723
 
3983 terminx 724
    int32_t x, y;
6593 hendricks2 725
    const int32_t xf = divscale16(ydim*4/3, 320);
3983 terminx 726
    const int32_t yf = divscale16(ydim, 200);  // (ydim<<16)/200
3420 helixhorne 727
 
4780 hendricks2 728
    tilesiz[TILE_SAVESHOT].x = 200;
729
    tilesiz[TILE_SAVESHOT].y = 320;
730
 
3983 terminx 731
    if (!frame)
732
    {
733
        Bmemset(pic, 0, 320 * 200);
734
        return;
735
    }
3420 helixhorne 736
 
6828 terminx 737
    videoBeginDrawing();
6656 pogokeen 738
    glReadPixels(0, 0, xdim, ydim, GL_RGBA, GL_UNSIGNED_BYTE, frame);
6828 terminx 739
    videoEndDrawing();
3420 helixhorne 740
 
3983 terminx 741
    for (y = 0; y < 200; y++)
742
    {
743
        const int32_t base = mulscale16(200 - y - 1, yf)*xdim;
3420 helixhorne 744
 
3983 terminx 745
        for (x = 0; x < 320; x++)
746
        {
6593 hendricks2 747
            const palette_t *pix = &frame[base + mulscale16(x, xf) + (xdim-(ydim*4/3))/2];
6831 terminx 748
            pic[320 * y + x] = paletteGetClosestColor(pix->r, pix->g, pix->b);
3420 helixhorne 749
        }
750
    }
3983 terminx 751
 
7705 terminx 752
    Xfree(frame);
3420 helixhorne 753
}
3425 helixhorne 754
#endif
3420 helixhorne 755
 
5979 hendricks2 756
void G_DrawRooms(int32_t playerNum, int32_t smoothRatio)
5 Plagman 757
{
7776 terminx 758
    auto const pPlayer = g_player[playerNum].ps;
5 Plagman 759
 
7349 terminx 760
    int const viewingRange = viewingrange;
1712 helixhorne 761
 
1802 terminx 762
    if (g_networkMode == NET_DEDICATED_SERVER) return;
763
 
5020 helixhorne 764
    totalclocklock = totalclock;
765
 
6829 terminx 766
    if (pub > 0 || videoGetRenderMode() >= REND_POLYMOST) // JBF 20040101: redraw background always
5 Plagman 767
    {
4852 hendricks2 768
#ifndef EDUKE32_TOUCH_DEVICES
2914 helixhorne 769
        if (ud.screen_size >= 8)
4602 terminx 770
#endif
1143 terminx 771
            G_DrawBackground();
5 Plagman 772
        pub = 0;
773
    }
774
 
5828 terminx 775
    VM_OnEvent(EVENT_DISPLAYSTART, pPlayer->i, playerNum);
5047 hendricks2 776
 
7881 terminx 777
    if ((ud.overhead_on == 2 && !automapping) || ud.show_help || (pPlayer->cursectnum == -1 && videoGetRenderMode() != REND_CLASSIC))
5 Plagman 778
        return;
779
 
1712 helixhorne 780
    if (r_usenewaspect)
781
    {
782
        newaspect_enable = 1;
6828 terminx 783
        videoSetCorrectedAspect();
1712 helixhorne 784
    }
785
 
5828 terminx 786
    if (ud.pause_on || pPlayer->on_crane > -1)
787
        smoothRatio = 65536;
3143 helixhorne 788
    else
5828 terminx 789
        smoothRatio = calc_smoothratio(totalclock, ototalclock);
5 Plagman 790
 
5828 terminx 791
    int const playerVis = pPlayer->visibility;
792
    g_visibility        = (playerVis <= 0) ? 0 : (int32_t)(playerVis * (numplayers > 1 ? 1.f : r_ambientlightrecip));
5 Plagman 793
 
5828 terminx 794
    CAMERA(sect) = pPlayer->cursectnum;
324 terminx 795
 
5828 terminx 796
    G_DoInterpolations(smoothRatio);
797
    G_AnimateCamSprite(smoothRatio);
5 Plagman 798
 
331 terminx 799
    if (ud.camerasprite >= 0)
5 Plagman 800
    {
7776 terminx 801
        auto const pSprite = &sprite[ud.camerasprite];
5 Plagman 802
 
7728 pogokeen 803
        pSprite->yvel = clamp(TrackerCast(pSprite->yvel), -100, 300);
5 Plagman 804
 
6725 terminx 805
        CAMERA(q16ang) = fix16_from_int(actor[ud.camerasprite].tempang
806
                                      + mulscale16(((pSprite->ang + 1024 - actor[ud.camerasprite].tempang) & 2047) - 1024, smoothRatio));
5047 hendricks2 807
 
7732 pogokeen 808
        renderSetRollAngle(0);
809
 
7313 hendricks2 810
        int const noDraw = VM_OnEventWithReturn(EVENT_DISPLAYROOMSCAMERA, ud.camerasprite, playerNum, 0);
5047 hendricks2 811
 
5828 terminx 812
        if (noDraw != 1)  // event return values other than 0 and 1 are reserved
5047 hendricks2 813
        {
7313 hendricks2 814
#ifdef DEBUGGINGAIDS
5828 terminx 815
            if (EDUKE32_PREDICT_FALSE(noDraw != 0))
5047 hendricks2 816
                OSD_Printf(OSD_ERROR "ERROR: EVENT_DISPLAYROOMSCAMERA return value must be 0 or 1, "
817
                           "other values are reserved.\n");
7313 hendricks2 818
#endif
5047 hendricks2 819
 
4228 helixhorne 820
#ifdef LEGACY_ROR
5828 terminx 821
            G_SE40(smoothRatio);
4228 helixhorne 822
#endif
723 terminx 823
#ifdef POLYMER
6829 terminx 824
            if (videoGetRenderMode() == REND_POLYMER)
6725 terminx 825
                polymer_setanimatesprites(G_DoSpriteAnimations, pSprite->x, pSprite->y, fix16_to_int(CAMERA(q16ang)), smoothRatio);
723 terminx 826
#endif
5047 hendricks2 827
            yax_preparedrawrooms();
6831 terminx 828
            renderDrawRoomsQ16(pSprite->x, pSprite->y, pSprite->z - ZOFFSET6, CAMERA(q16ang), fix16_from_int(pSprite->yvel), pSprite->sectnum);
5828 terminx 829
            yax_drawrooms(G_DoSpriteAnimations, pSprite->sectnum, 0, smoothRatio);
6725 terminx 830
            G_DoSpriteAnimations(pSprite->x, pSprite->y, fix16_to_int(CAMERA(q16ang)), smoothRatio);
6831 terminx 831
            renderDrawMasks();
5047 hendricks2 832
        }
5 Plagman 833
    }
834
    else
835
    {
5828 terminx 836
        int32_t floorZ, ceilZ;
2697 helixhorne 837
        int32_t tiltcx, tiltcy, tiltcs=0;    // JBF 20030807
1712 helixhorne 838
 
7349 terminx 839
        int vr            = divscale22(1, sprite[pPlayer->i].yrepeat + 28);
840
        int screenTilting = (videoGetRenderMode() == REND_CLASSIC
841
                             && ((ud.screen_tilting && pPlayer->rotscrnang
842
 
4249 hendricks2 843
#ifdef SPLITSCREEN_MOD_HACKS
7349 terminx 844
                                  && !g_fakeMultiMode
4249 hendricks2 845
#endif
7349 terminx 846
                                  )));
2697 helixhorne 847
 
7349 terminx 848
        vr = Blrintf(float(vr) * tanf(ud.fov * (fPI/360.f)));
7329 terminx 849
 
1712 helixhorne 850
        if (!r_usenewaspect)
7349 terminx 851
            renderSetAspect(vr, yxaspect);
1712 helixhorne 852
        else
7349 terminx 853
            renderSetAspect(mulscale16(vr, viewingrange), yxaspect);
1960 helixhorne 854
 
1143 terminx 855
        if (g_screenCapture)
5 Plagman 856
        {
857
            walock[TILE_SAVESHOT] = 199;
858
            if (waloff[TILE_SAVESHOT] == 0)
6830 terminx 859
                cacheAllocateBlock(&waloff[TILE_SAVESHOT],200*320,&walock[TILE_SAVESHOT]);
2567 helixhorne 860
 
6829 terminx 861
            if (videoGetRenderMode() == REND_CLASSIC)
6831 terminx 862
                renderSetTarget(TILE_SAVESHOT, 200, 320);
5 Plagman 863
        }
5828 terminx 864
        else if (screenTilting)
5 Plagman 865
        {
7349 terminx 866
            int32_t oviewingrange = viewingrange;  // save it from renderSetAspect()
5828 terminx 867
            const int16_t tang = (ud.screen_tilting) ? pPlayer->rotscrnang : 0;
1962 helixhorne 868
 
4364 helixhorne 869
            if (tang == 1024)
5828 terminx 870
                screenTilting = 2;
2698 helixhorne 871
            else
4364 helixhorne 872
            {
4965 helixhorne 873
                // Maximum possible allocation size passed to allocache() below
874
                // since there is no equivalent of free() for allocache().
875
#if MAXYDIM >= 640
5828 terminx 876
                int const maxTiltSize = 640*640;
4965 helixhorne 877
#else
5828 terminx 878
                int const maxTiltSize = 320*320;
4965 helixhorne 879
#endif
4364 helixhorne 880
                // To render a tilted screen in high quality, we need at least
881
                // 640 pixels of *Y* dimension.
882
#if MAXYDIM >= 640
4935 helixhorne 883
                // We also need
884
                //  * xdim >= 640 since tiltcx will be passed as setview()'s x2
885
                //    which must be less than xdim.
886
                //  * ydim >= 640 (sic!) since the tile-to-draw-to will be set
887
                //    up with dimension 400x640, but the engine's arrays like
888
                //    lastx[] are alloc'd with *xdim* elements! (This point is
889
                //    the dynamic counterpart of the #if above since we now
890
                //    allocate these engine arrays tightly.)
891
                // XXX: The engine should be in charge of setting up everything
892
                // so that no oob access occur.
893
                if (xdim >= 640 && ydim >= 640)
4364 helixhorne 894
                {
895
                    tiltcs = 2;
896
                    tiltcx = 640;
897
                    tiltcy = 400;
898
                }
899
                else
2698 helixhorne 900
#endif
4364 helixhorne 901
                {
902
                    // JBF 20030807: Increased tilted-screen quality
903
                    tiltcs = 1;
4935 helixhorne 904
 
905
                    // NOTE: The same reflections as above apply here, too.
4965 helixhorne 906
                    // TILT_SETVIEWTOTILE_320.
907
                    tiltcx = 320;
908
                    tiltcy = 200;
4364 helixhorne 909
                }
5 Plagman 910
 
5828 terminx 911
                // If the view is rotated (not 0 or 180 degrees modulo 360 degrees),
912
                // we render onto a square tile and display a portion of that
913
                // rotated on-screen later on.
914
                const int32_t viewtilexsiz = (tang&1023) ? tiltcx : tiltcy;
915
                const int32_t viewtileysiz = tiltcx;
2700 helixhorne 916
 
5828 terminx 917
                walock[TILE_TILT] = 255;
918
                if (waloff[TILE_TILT] == 0)
6830 terminx 919
                    cacheAllocateBlock(&waloff[TILE_TILT], maxTiltSize, &walock[TILE_TILT]);
2700 helixhorne 920
 
6831 terminx 921
                renderSetTarget(TILE_TILT, viewtilexsiz, viewtileysiz);
2700 helixhorne 922
 
4364 helixhorne 923
                if ((tang&1023) == 512)
5 Plagman 924
                {
4364 helixhorne 925
                    //Block off unscreen section of 90ΓΈ tilted screen
5828 terminx 926
                    int const j = tiltcx-(60*tiltcs);
5829 terminx 927
                    for (bssize_t i=(60*tiltcs)-1; i>=0; i--)
4364 helixhorne 928
                    {
929
                        startumost[i] = 1;
930
                        startumost[i+j] = 1;
931
                        startdmost[i] = 0;
932
                        startdmost[i+j] = 0;
933
                    }
5 Plagman 934
                }
935
 
5828 terminx 936
                int vRange = (tang & 511);
2697 helixhorne 937
 
5828 terminx 938
                if (vRange > 256)
939
                    vRange = 512 - vRange;
1712 helixhorne 940
 
5828 terminx 941
                vRange = sintable[vRange + 512] * 8 + sintable[vRange] * 5;
6831 terminx 942
                renderSetAspect(mulscale16(oviewingrange, vRange >> 1), yxaspect);
4364 helixhorne 943
            }
335 terminx 944
        }
7732 pogokeen 945
        else if (videoGetRenderMode() >= REND_POLYMOST)
946
        {
947
            if (ud.screen_tilting
4249 hendricks2 948
#ifdef SPLITSCREEN_MOD_HACKS
949
        && !g_fakeMultiMode
950
#endif
7732 pogokeen 951
            )
952
            {
1820 terminx 953
#ifdef USE_OPENGL
7732 pogokeen 954
                renderSetRollAngle(pPlayer->orotscrnang + mulscale16(((pPlayer->rotscrnang - pPlayer->orotscrnang + 1024)&2047)-1024, smoothRatio));
895 terminx 955
#endif
7732 pogokeen 956
                pPlayer->orotscrnang = pPlayer->rotscrnang;
957
            }
958
            else
959
            {
960
                renderSetRollAngle(0);
961
            }
5 Plagman 962
        }
963
 
5828 terminx 964
        if (pPlayer->newowner < 0)
5 Plagman 965
        {
5828 terminx 966
            vec3_t const camVect = { pPlayer->opos.x + mulscale16(pPlayer->pos.x - pPlayer->opos.x, smoothRatio),
967
                                     pPlayer->opos.y + mulscale16(pPlayer->pos.y - pPlayer->opos.y, smoothRatio),
968
                                     pPlayer->opos.z + mulscale16(pPlayer->pos.z - pPlayer->opos.z, smoothRatio) };
1490 terminx 969
 
6790 terminx 970
            CAMERA(pos)      = camVect;
971
            CAMERA(q16ang)   = pPlayer->oq16ang
972
                             + mulscale16(((pPlayer->q16ang + F16(1024) - pPlayer->oq16ang) & 0x7FFFFFF) - F16(1024), smoothRatio)
973
                             + fix16_from_int(pPlayer->look_ang);
6725 terminx 974
            CAMERA(q16horiz) = pPlayer->oq16horiz + pPlayer->oq16horizoff
6790 terminx 975
                             + mulscale16((pPlayer->q16horiz + pPlayer->q16horizoff - pPlayer->oq16horiz - pPlayer->oq16horizoff), smoothRatio);
3143 helixhorne 976
 
977
            if (ud.viewbob)
978
            {
5828 terminx 979
                int zAdd = (pPlayer->opyoff + mulscale16(pPlayer->pyoff-pPlayer->opyoff, smoothRatio));
3143 helixhorne 980
 
5828 terminx 981
                if (pPlayer->over_shoulder_on)
982
                    zAdd >>= 3;
983
 
984
                CAMERA(pos.z) += zAdd;
3143 helixhorne 985
            }
986
 
5828 terminx 987
            if (pPlayer->over_shoulder_on)
3143 helixhorne 988
            {
3405 helixhorne 989
                CAMERA(pos.z) -= 3072;
5828 terminx 990
 
6725 terminx 991
                if (G_DoThirdPerson(pPlayer, &CAMERA(pos), &CAMERA(sect), fix16_to_int(CAMERA(q16ang)), fix16_to_int(CAMERA(q16horiz))) < 0)
4369 helixhorne 992
                {
993
                    CAMERA(pos.z) += 3072;
6725 terminx 994
                    G_DoThirdPerson(pPlayer, &CAMERA(pos), &CAMERA(sect), fix16_to_int(CAMERA(q16ang)), fix16_to_int(CAMERA(q16horiz)));
4369 helixhorne 995
                }
3143 helixhorne 996
            }
5 Plagman 997
        }
3143 helixhorne 998
        else
5 Plagman 999
        {
5828 terminx 1000
            vec3_t const camVect = G_GetCameraPosition(pPlayer->newowner, smoothRatio);
4847 helixhorne 1001
 
3143 helixhorne 1002
            // looking through viewscreen
6790 terminx 1003
            CAMERA(pos)      = camVect;
6725 terminx 1004
            CAMERA(q16ang)   = pPlayer->q16ang + fix16_from_int(pPlayer->look_ang);
1005
            CAMERA(q16horiz) = fix16_from_int(100 + sprite[pPlayer->newowner].shade);
6790 terminx 1006
            CAMERA(sect)     = sprite[pPlayer->newowner].sectnum;
5 Plagman 1007
        }
2697 helixhorne 1008
 
5828 terminx 1009
        ceilZ  = actor[pPlayer->i].ceilingz;
1010
        floorZ = actor[pPlayer->i].floorz;
5 Plagman 1011
 
5828 terminx 1012
        if (g_earthquakeTime > 0 && pPlayer->on_ground == 1)
5 Plagman 1013
        {
5828 terminx 1014
            CAMERA(pos.z) += 256 - (((g_earthquakeTime)&1) << 9);
6725 terminx 1015
            CAMERA(q16ang)   += fix16_from_int((2 - ((g_earthquakeTime)&2)) << 2);
5 Plagman 1016
        }
1017
 
5828 terminx 1018
        if (sprite[pPlayer->i].pal == 1)
3405 helixhorne 1019
            CAMERA(pos.z) -= (18<<8);
5 Plagman 1020
 
5828 terminx 1021
        if (pPlayer->newowner < 0 && pPlayer->spritebridge == 0)
5 Plagman 1022
        {
2939 helixhorne 1023
            // NOTE: when shrunk, p->pos.z can be below the floor.  This puts the
1024
            // camera into the sector again then.
1025
 
5828 terminx 1026
            if (CAMERA(pos.z) < (pPlayer->truecz + ZOFFSET6))
1027
                CAMERA(pos.z) = ceilZ + ZOFFSET6;
1028
            else if (CAMERA(pos.z) > (pPlayer->truefz - ZOFFSET6))
1029
                CAMERA(pos.z) = floorZ - ZOFFSET6;
5 Plagman 1030
        }
1031
 
3405 helixhorne 1032
        while (CAMERA(sect) >= 0)  // if, really
5 Plagman 1033
        {
5828 terminx 1034
            getzsofslope(CAMERA(sect),CAMERA(pos.x),CAMERA(pos.y),&ceilZ,&floorZ);
1877 helixhorne 1035
#ifdef YAX_ENABLE
3405 helixhorne 1036
            if (yax_getbunch(CAMERA(sect), YAX_CEILING) >= 0)
1882 helixhorne 1037
            {
5828 terminx 1038
                if (CAMERA(pos.z) < ceilZ)
2269 helixhorne 1039
                {
3405 helixhorne 1040
                    updatesectorz(CAMERA(pos.x), CAMERA(pos.y), CAMERA(pos.z), &CAMERA(sect));
1041
                    break;  // since CAMERA(sect) might have been updated to -1
2269 helixhorne 1042
                    // NOTE: fist discovered in WGR2 SVN r134, til' death level 1
1043
                    //  (Lochwood Hollow).  A problem REMAINS with Polymost, maybe classic!
1044
                }
1882 helixhorne 1045
            }
1046
            else
1877 helixhorne 1047
#endif
5828 terminx 1048
                if (CAMERA(pos.z) < ceilZ+ZOFFSET6)
1049
                    CAMERA(pos.z) = ceilZ+ZOFFSET6;
1882 helixhorne 1050
 
1877 helixhorne 1051
#ifdef YAX_ENABLE
3405 helixhorne 1052
            if (yax_getbunch(CAMERA(sect), YAX_FLOOR) >= 0)
1882 helixhorne 1053
            {
5828 terminx 1054
                if (CAMERA(pos.z) > floorZ)
3405 helixhorne 1055
                    updatesectorz(CAMERA(pos.x), CAMERA(pos.y), CAMERA(pos.z), &CAMERA(sect));
1882 helixhorne 1056
            }
1057
            else
1877 helixhorne 1058
#endif
5828 terminx 1059
                if (CAMERA(pos.z) > floorZ-ZOFFSET6)
1060
                    CAMERA(pos.z) = floorZ-ZOFFSET6;
2269 helixhorne 1061
 
1062
            break;
5 Plagman 1063
        }
1064
 
2706 helixhorne 1065
        // NOTE: might be rendering off-screen here, so CON commands that draw stuff
1066
        //  like showview must cope with that situation or bail out!
5828 terminx 1067
        int const noDraw = VM_OnEventWithReturn(EVENT_DISPLAYROOMS, pPlayer->i, playerNum, 0);
491 terminx 1068
 
6725 terminx 1069
        CAMERA(q16horiz) = fix16_clamp(CAMERA(q16horiz), F16(HORIZ_MIN), F16(HORIZ_MAX));
2410 helixhorne 1070
 
5828 terminx 1071
        if (noDraw != 1)  // event return values other than 0 and 1 are reserved
2889 helixhorne 1072
        {
7313 hendricks2 1073
#ifdef DEBUGGINGAIDS
1074
            if (EDUKE32_PREDICT_FALSE(noDraw != 0))
2889 helixhorne 1075
                OSD_Printf(OSD_ERROR "ERROR: EVENT_DISPLAYROOMS return value must be 0 or 1, "
1076
                           "other values are reserved.\n");
7313 hendricks2 1077
#endif
5 Plagman 1078
 
6725 terminx 1079
            G_HandleMirror(CAMERA(pos.x), CAMERA(pos.y), CAMERA(pos.z), CAMERA(q16ang), CAMERA(q16horiz), smoothRatio);
7733 pogokeen 1080
            G_ClearGotMirror();
4228 helixhorne 1081
#ifdef LEGACY_ROR
5828 terminx 1082
            G_SE40(smoothRatio);
4228 helixhorne 1083
#endif
723 terminx 1084
#ifdef POLYMER
6829 terminx 1085
            if (videoGetRenderMode() == REND_POLYMER)
6725 terminx 1086
                polymer_setanimatesprites(G_DoSpriteAnimations, CAMERA(pos.x),CAMERA(pos.y),fix16_to_int(CAMERA(q16ang)),smoothRatio);
723 terminx 1087
#endif
2889 helixhorne 1088
            // for G_PrintCoords
1089
            dr_viewingrange = viewingrange;
1090
            dr_yxaspect = yxaspect;
3726 helixhorne 1091
#ifdef DEBUG_MIRRORS_ONLY
7876 terminx 1092
            gotpic[MIRROR>>3] |= pow2char[MIRROR&7];
3726 helixhorne 1093
#else
2889 helixhorne 1094
            yax_preparedrawrooms();
6831 terminx 1095
            renderDrawRoomsQ16(CAMERA(pos.x),CAMERA(pos.y),CAMERA(pos.z),CAMERA(q16ang),CAMERA(q16horiz),CAMERA(sect));
5828 terminx 1096
            yax_drawrooms(G_DoSpriteAnimations, CAMERA(sect), 0, smoothRatio);
4228 helixhorne 1097
#ifdef LEGACY_ROR
1098
            if ((unsigned)ror_sprite < MAXSPRITES && drawing_ror == 1)  // viewing from bottom
1099
                G_OROR_DupeSprites(&sprite[ror_sprite]);
1100
#endif
6725 terminx 1101
            G_DoSpriteAnimations(CAMERA(pos.x),CAMERA(pos.y),fix16_to_int(CAMERA(q16ang)),smoothRatio);
4228 helixhorne 1102
#ifdef LEGACY_ROR
2889 helixhorne 1103
            drawing_ror = 0;
4228 helixhorne 1104
#endif
6831 terminx 1105
            renderDrawMasks();
3726 helixhorne 1106
#endif
2889 helixhorne 1107
        }
5 Plagman 1108
 
2567 helixhorne 1109
        if (g_screenCapture)
5 Plagman 1110
        {
1143 terminx 1111
            g_screenCapture = 0;
2567 helixhorne 1112
 
6831 terminx 1113
            tileInvalidate(TILE_SAVESHOT, 0, 255);
6703 hendricks2 1114
 
6829 terminx 1115
            if (videoGetRenderMode() == REND_CLASSIC)
2567 helixhorne 1116
            {
6831 terminx 1117
                renderRestoreTarget();
2567 helixhorne 1118
//                walock[TILE_SAVESHOT] = 1;
1119
            }
1120
#ifdef USE_OPENGL
1121
            else
3420 helixhorne 1122
                G_ReadGLFrame();
2567 helixhorne 1123
#endif
5 Plagman 1124
        }
5828 terminx 1125
        else if (screenTilting)
5 Plagman 1126
        {
5828 terminx 1127
            const int16_t tang = (ud.screen_tilting) ? pPlayer->rotscrnang : 0;
5 Plagman 1128
 
5828 terminx 1129
            if (screenTilting == 2)  // tang == 1024
4364 helixhorne 1130
            {
6828 terminx 1131
                videoBeginDrawing();
4364 helixhorne 1132
                {
5800 terminx 1133
                    const int32_t height = windowxy2.y-windowxy1.y+1;
1134
                    const int32_t width = windowxy2.x-windowxy1.x+1;
2697 helixhorne 1135
 
5800 terminx 1136
                    uint8_t *f = (uint8_t *)(frameplace + ylookup[windowxy1.y]);
4364 helixhorne 1137
                    int32_t x, y;
2697 helixhorne 1138
 
4364 helixhorne 1139
                    for (y=0; y < (height>>1); y++)
5800 terminx 1140
                        swapbufreverse(f + y*bytesperline + windowxy2.x,
1141
                                       f + (height-1-y)*bytesperline + windowxy1.x,
4364 helixhorne 1142
                                       width);
1143
 
5800 terminx 1144
                    f += (height>>1)*bytesperline + windowxy1.x;
4364 helixhorne 1145
 
1146
                    if (height&1)
1147
                        for (x=0; x<(width>>1); x++)
1148
                            swapchar(&f[x], &f[width-1-x]);
1149
                }
6828 terminx 1150
                videoEndDrawing();
4364 helixhorne 1151
            }
1152
            else
1153
            {
6831 terminx 1154
                renderRestoreTarget();
4364 helixhorne 1155
                picanm[TILE_TILT].xofs = picanm[TILE_TILT].yofs = 0;
1156
 
5828 terminx 1157
                int tiltZoom = (tang&511);
4364 helixhorne 1158
 
5828 terminx 1159
                if (tiltZoom > 256)
1160
                    tiltZoom = 512 - tiltZoom;
1161
 
1162
                tiltZoom = sintable[tiltZoom + 512] * 8 + sintable[tiltZoom] * 5;
1163
                tiltZoom >>= tiltcs;  // JBF 20030807
1164
 
1165
                rotatesprite_win(160 << 16, 100 << 16, tiltZoom, tang + 512, TILE_TILT, 0, 0, 4 + 2 + 64 + 1024);
7875 terminx 1166
                walock[TILE_TILT] = 1;
4364 helixhorne 1167
            }
5 Plagman 1168
        }
3378 helixhorne 1169
    }
1170
 
1143 terminx 1171
    G_RestoreInterpolations();
5 Plagman 1172
 
1173
    {
3960 helixhorne 1174
        // Totalclock count of last step of p->visibility converging towards
1175
        // ud.const_visibility.
1176
        static int32_t lastvist;
5828 terminx 1177
        const int32_t visdif = ud.const_visibility-pPlayer->visibility;
3960 helixhorne 1178
 
1179
        // Check if totalclock was cleared (e.g. restarted game).
1180
        if (totalclock < lastvist)
1181
            lastvist = 0;
1182
 
1183
        // Every 2nd totalclock increment (each 1/60th second), ...
1184
        while (totalclock >= lastvist+2)
1185
        {
1186
            // ... approximately three-quarter the difference between
1187
            // p->visibility and ud.const_visibility.
1188
            const int32_t visinc = visdif>>2;
1189
 
1190
            if (klabs(visinc) == 0)
4401 helixhorne 1191
            {
5828 terminx 1192
                pPlayer->visibility = ud.const_visibility;
3960 helixhorne 1193
                break;
4401 helixhorne 1194
            }
3960 helixhorne 1195
 
5828 terminx 1196
            pPlayer->visibility += visinc;
3960 helixhorne 1197
            lastvist = totalclock;
1198
        }
5 Plagman 1199
    }
1712 helixhorne 1200
 
1201
    if (r_usenewaspect)
1202
    {
1203
        newaspect_enable = 0;
7349 terminx 1204
        renderSetAspect(viewingRange, tabledivide32_noinline(65536 * ydim * 8, xdim * 5));
1712 helixhorne 1205
    }
6512 hendricks2 1206
 
1207
    VM_OnEvent(EVENT_DISPLAYROOMSEND, g_player[screenpeek].ps->i, screenpeek);
5 Plagman 1208
}
1209
 
5611 terminx 1210
void G_DumpDebugInfo(void)
332 terminx 1211
{
3373 helixhorne 1212
#if !defined LUNATIC
6140 hendricks2 1213
    static char const s_WEAPON[] = "WEAPON";
1205 terminx 1214
    int32_t i,j,x;
7359 hendricks2 1215
    //    buildvfs_FILE fp = buildvfs_fopen_write("condebug.log");
1228 terminx 1216
 
5513 terminx 1217
    VM_ScriptInfo(insptr, 64);
6140 hendricks2 1218
    buildprint("\nCurrent gamevar values:\n");
2229 hendricks2 1219
 
1229 terminx 1220
    for (i=0; i<MAX_WEAPONS; i++)
332 terminx 1221
    {
1229 terminx 1222
        for (j=0; j<numplayers; j++)
332 terminx 1223
        {
6140 hendricks2 1224
            buildprint("Player ", j, "\n\n");
1225
            buildprint(s_WEAPON, i, "_CLIP ", PWEAPON(j, i, Clip), "\n");
1226
            buildprint(s_WEAPON, i, "_RELOAD ", PWEAPON(j, i, Reload), "\n");
1227
            buildprint(s_WEAPON, i, "_FIREDELAY ", PWEAPON(j, i, FireDelay), "\n");
1228
            buildprint(s_WEAPON, i, "_TOTALTIME ", PWEAPON(j, i, TotalTime), "\n");
1229
            buildprint(s_WEAPON, i, "_HOLDDELAY ", PWEAPON(j, i, HoldDelay), "\n");
1230
            buildprint(s_WEAPON, i, "_FLAGS ", PWEAPON(j, i, Flags), "\n");
1231
            buildprint(s_WEAPON, i, "_SHOOTS ", PWEAPON(j, i, Shoots), "\n");
1232
            buildprint(s_WEAPON, i, "_SPAWNTIME ", PWEAPON(j, i, SpawnTime), "\n");
1233
            buildprint(s_WEAPON, i, "_SPAWN ", PWEAPON(j, i, Spawn), "\n");
1234
            buildprint(s_WEAPON, i, "_SHOTSPERBURST ", PWEAPON(j, i, ShotsPerBurst), "\n");
1235
            buildprint(s_WEAPON, i, "_WORKSLIKE ", PWEAPON(j, i, WorksLike), "\n");
1236
            buildprint(s_WEAPON, i, "_INITIALSOUND ", PWEAPON(j, i, InitialSound), "\n");
1237
            buildprint(s_WEAPON, i, "_FIRESOUND ", PWEAPON(j, i, FireSound), "\n");
1238
            buildprint(s_WEAPON, i, "_SOUND2TIME ", PWEAPON(j, i, Sound2Time), "\n");
1239
            buildprint(s_WEAPON, i, "_SOUND2SOUND ", PWEAPON(j, i, Sound2Sound), "\n");
1240
            buildprint(s_WEAPON, i, "_RELOADSOUND1 ", PWEAPON(j, i, ReloadSound1), "\n");
1241
            buildprint(s_WEAPON, i, "_RELOADSOUND2 ", PWEAPON(j, i, ReloadSound2), "\n");
1242
            buildprint(s_WEAPON, i, "_SELECTSOUND ", PWEAPON(j, i, SelectSound), "\n");
1243
            buildprint(s_WEAPON, i, "_FLASHCOLOR ", PWEAPON(j, i, FlashColor), "\n");
332 terminx 1244
        }
6140 hendricks2 1245
        buildprint("\n");
332 terminx 1246
    }
3354 helixhorne 1247
 
1229 terminx 1248
    for (x=0; x<MAXSTATUS; x++)
332 terminx 1249
    {
1250
        j = headspritestat[x];
1251
        while (j >= 0)
1252
        {
6140 hendricks2 1253
            buildprint("Sprite ", j, " (", TrackerCast(sprite[j].x), ",", TrackerCast(sprite[j].y), ",", TrackerCast(sprite[j].z),
1254
                ") (picnum: ", TrackerCast(sprite[j].picnum), ")\n");
1229 terminx 1255
            for (i=0; i<g_gameVarCount; i++)
332 terminx 1256
            {
5825 terminx 1257
                if (aGameVars[i].flags & (GAMEVAR_PERACTOR))
332 terminx 1258
                {
5825 terminx 1259
                    if (aGameVars[i].pValues[j] != aGameVars[i].defaultValue)
332 terminx 1260
                    {
6140 hendricks2 1261
                        buildprint("gamevar ", aGameVars[i].szLabel, " ", aGameVars[i].pValues[j], " GAMEVAR_PERACTOR");
5825 terminx 1262
                        if (aGameVars[i].flags != GAMEVAR_PERACTOR)
332 terminx 1263
                        {
6140 hendricks2 1264
                            buildprint(" // ");
5825 terminx 1265
                            if (aGameVars[i].flags & (GAMEVAR_SYSTEM))
332 terminx 1266
                            {
6140 hendricks2 1267
                                buildprint(" (system)");
332 terminx 1268
                            }
1269
                        }
6140 hendricks2 1270
                        buildprint("\n");
332 terminx 1271
                    }
1272
                }
1273
            }
6140 hendricks2 1274
            buildprint("\n");
332 terminx 1275
            j = nextspritestat[j];
1276
        }
1277
    }
1221 terminx 1278
    Gv_DumpValues();
7359 hendricks2 1279
//    buildvfs_fclose(fp);
3354 helixhorne 1280
#endif
6725 terminx 1281
    saveboard("debug.map", &g_player[myconnectindex].ps->pos, fix16_to_int(g_player[myconnectindex].ps->q16ang),
3042 helixhorne 1282
              g_player[myconnectindex].ps->cursectnum);
332 terminx 1283
}
1284
 
3322 helixhorne 1285
// if <set_movflag_uncond> is true, set the moveflag unconditionally,
1286
// else only if it equals 0.
1287
static int32_t G_InitActor(int32_t i, int32_t tilenum, int32_t set_movflag_uncond)
1288
{
3456 helixhorne 1289
#if !defined LUNATIC
3322 helixhorne 1290
    if (g_tile[tilenum].execPtr)
1291
    {
5825 terminx 1292
        SH(i) = *(g_tile[tilenum].execPtr);
3920 helixhorne 1293
        AC_ACTION_ID(actor[i].t_data) = *(g_tile[tilenum].execPtr+1);
1294
        AC_MOVE_ID(actor[i].t_data) = *(g_tile[tilenum].execPtr+2);
3456 helixhorne 1295
 
5825 terminx 1296
        if (set_movflag_uncond || SHT(i) == 0)  // AC_MOVFLAGS
1297
            SHT(i) = *(g_tile[tilenum].execPtr+3);
3322 helixhorne 1298
 
1299
        return 1;
1300
    }
3456 helixhorne 1301
#else
1302
    if (El_HaveActor(tilenum))
3322 helixhorne 1303
    {
1304
        // ^^^ C-CON takes precedence for now.
1305
        const el_actor_t *a = &g_elActors[tilenum];
6581 hendricks2 1306
        auto movflagsptr = &AC_MOVFLAGS(&sprite[i], &actor[i]);
3322 helixhorne 1307
 
5825 terminx 1308
        SH(i) = a->strength;
3920 helixhorne 1309
        AC_ACTION_ID(actor[i].t_data) = a->act.id;
1310
        AC_MOVE_ID(actor[i].t_data) = a->mov.id;
3322 helixhorne 1311
        Bmemcpy(&actor[i].ac, &a->act.ac, sizeof(struct action));
1312
        Bmemcpy(&actor[i].mv, &a->mov.mv, sizeof(struct move));
1313
 
3922 helixhorne 1314
        if (set_movflag_uncond || *movflagsptr == 0)
1315
            *movflagsptr = a->movflags;
3322 helixhorne 1316
 
1317
        return 1;
1318
    }
1319
#endif
1320
 
1321
    return 0;
1322
}
1323
 
5567 terminx 1324
int32_t A_InsertSprite(int16_t whatsect,int32_t s_x,int32_t s_y,int32_t s_z,int16_t s_pn,int8_t s_s,
1325
                       uint8_t s_xr,uint8_t s_yr,int16_t s_a,int16_t s_ve,int16_t s_zv,int16_t s_ow,int16_t s_ss)
5 Plagman 1326
{
3270 terminx 1327
 
7242 seventyfiv 1328
 
1329
    int32_t newSprite;
7304 terminx 1330
 
7242 seventyfiv 1331
#ifdef NETCODE_DISABLE
1332
    newSprite = insertsprite(whatsect, s_ss);
1333
#else
1334
    newSprite = Net_InsertSprite(whatsect, s_ss);
1335
 
1336
#endif
1337
 
7234 terminx 1338
    if (EDUKE32_PREDICT_FALSE((unsigned)newSprite >= MAXSPRITES))
3270 terminx 1339
    {
1143 terminx 1340
        G_DumpDebugInfo();
4763 hendricks2 1341
        OSD_Printf("Failed spawning pic %d spr from pic %d spr %d at x:%d,y:%d,z:%d,sect:%d\n",
3334 hendricks2 1342
                          s_pn,s_ow < 0 ? -1 : TrackerCast(sprite[s_ow].picnum),s_ow,s_x,s_y,s_z,whatsect);
1143 terminx 1343
        G_GameExit("Too many sprites spawned.");
332 terminx 1344
    }
5 Plagman 1345
 
3808 helixhorne 1346
#ifdef DEBUGGINGAIDS
1347
    g_spriteStat.numins++;
1348
#endif
1349
 
7234 terminx 1350
    sprite[newSprite] = { s_x, s_y, s_z, 0, s_pn, s_s, 0, 0, 0, s_xr, s_yr, 0, 0, whatsect, s_ss, s_a, s_ow, s_ve, 0, s_zv, 0, 0, 0 };
3322 helixhorne 1351
 
7234 terminx 1352
    auto &a = actor[newSprite];
1353
    a = {};
1354
    a.bpos = { s_x, s_y, s_z };
1355
 
2205 helixhorne 1356
    if ((unsigned)s_ow < MAXSPRITES)
919 terminx 1357
    {
7234 terminx 1358
        a.picnum   = sprite[s_ow].picnum;
1359
        a.floorz   = actor[s_ow].floorz;
1360
        a.ceilingz = actor[s_ow].ceilingz;
919 terminx 1361
    }
5 Plagman 1362
 
7234 terminx 1363
    a.stayput = -1;
1364
    a.extra   = -1;
6239 terminx 1365
#ifdef POLYMER
7234 terminx 1366
    a.lightId = -1;
6239 terminx 1367
#endif
7234 terminx 1368
    a.owner = s_ow;
5 Plagman 1369
 
7234 terminx 1370
    G_InitActor(newSprite, s_pn, 1);
5 Plagman 1371
 
7234 terminx 1372
    spriteext[newSprite]    = {};
1373
    spritesmooth[newSprite] = {};
3830 helixhorne 1374
 
1375
#if defined LUNATIC
1376
    if (!g_noResetVars)
3354 helixhorne 1377
#endif
7234 terminx 1378
        A_ResetVars(newSprite);
3830 helixhorne 1379
#if defined LUNATIC
1380
    g_noResetVars = 0;
1381
#endif
1382
 
4680 terminx 1383
    if (VM_HaveEvent(EVENT_EGS))
753 terminx 1384
    {
7234 terminx 1385
        int32_t p, pl = A_FindPlayer(&sprite[newSprite], &p);
1138 terminx 1386
 
1387
        block_deletesprite++;
7636 terminx 1388
        VM_ExecuteEvent(EVENT_EGS, newSprite, pl, p);
1138 terminx 1389
        block_deletesprite--;
753 terminx 1390
    }
610 terminx 1391
 
7234 terminx 1392
    return newSprite;
5 Plagman 1393
}
1394
 
1924 helixhorne 1395
#ifdef YAX_ENABLE
1396
void Yax_SetBunchZs(int32_t sectnum, int32_t cf, int32_t daz)
1397
{
1398
    int32_t i, bunchnum = yax_getbunch(sectnum, cf);
1399
 
1400
    if (bunchnum < 0 || bunchnum >= numyaxbunches)
1401
        return;
1402
 
1403
    for (SECTORS_OF_BUNCH(bunchnum, YAX_CEILING, i))
1404
        SECTORFLD(i,z, YAX_CEILING) = daz;
1405
    for (SECTORS_OF_BUNCH(bunchnum, YAX_FLOOR, i))
1406
        SECTORFLD(i,z, YAX_FLOOR) = daz;
1407
}
1408
 
1409
static void Yax_SetBunchInterpolation(int32_t sectnum, int32_t cf)
1410
{
1411
    int32_t i, bunchnum = yax_getbunch(sectnum, cf);
1412
 
1413
    if (bunchnum < 0 || bunchnum >= numyaxbunches)
1414
        return;
5768 hendricks2 1415
 
1924 helixhorne 1416
    for (SECTORS_OF_BUNCH(bunchnum, YAX_CEILING, i))
1417
        G_SetInterpolation(&sector[i].ceilingz);
1418
    for (SECTORS_OF_BUNCH(bunchnum, YAX_FLOOR, i))
1419
        G_SetInterpolation(&sector[i].floorz);
1420
}
1421
#else
1422
# define Yax_SetBunchInterpolation(sectnum, cf)
1423
#endif
1424
 
3322 helixhorne 1425
// A_Spawn has two forms with arguments having different meaning:
1426
//
6499 terminx 1427
// 1. spriteNum>=0: Spawn from parent sprite <spriteNum> with picnum <tileNum>
1428
// 2. spriteNum<0: Spawn from already *existing* sprite <tileNum>
5827 terminx 1429
int A_Spawn(int spriteNum, int tileNum)
5 Plagman 1430
{
5827 terminx 1431
    int         newSprite;
6500 terminx 1432
    spritetype *pSprite;
1433
    actor_t *   pActor;
5827 terminx 1434
    int         sectNum;
5 Plagman 1435
 
5827 terminx 1436
    if (spriteNum >= 0)
5 Plagman 1437
    {
3322 helixhorne 1438
        // spawn from parent sprite <j>
5827 terminx 1439
        newSprite = A_InsertSprite(sprite[spriteNum].sectnum,sprite[spriteNum].x,sprite[spriteNum].y,sprite[spriteNum].z,
1440
                           tileNum,0,0,0,0,0,0,spriteNum,0);
1441
        actor[newSprite].picnum = sprite[spriteNum].picnum;
5 Plagman 1442
    }
1443
    else
1444
    {
3322 helixhorne 1445
        // spawn from already existing sprite <pn>
7234 terminx 1446
        newSprite = tileNum;
1447
        auto &s = sprite[newSprite];
1448
        auto &a = actor[newSprite];
1490 terminx 1449
 
7234 terminx 1450
        a = { };
1451
        a.bpos = { s.x, s.y, s.z };
1490 terminx 1452
 
7234 terminx 1453
        a.picnum = s.picnum;
5 Plagman 1454
 
7234 terminx 1455
        if (s.picnum == SECTOREFFECTOR && s.lotag == 50)
1456
            a.picnum = s.owner;
1527 terminx 1457
 
7751 pogokeen 1458
        if (s.picnum == LOCATORS && s.owner != -1)
1459
            a.owner = s.owner;
1460
        else
7738 pogokeen 1461
            s.owner = a.owner = newSprite;
1527 terminx 1462
 
7234 terminx 1463
        a.floorz   = sector[s.sectnum].floorz;
1464
        a.ceilingz = sector[s.sectnum].ceilingz;
5 Plagman 1465
 
7234 terminx 1466
        a.stayput = a.extra = -1;
6500 terminx 1467
 
6239 terminx 1468
#ifdef POLYMER
7234 terminx 1469
        a.lightId = -1;
6239 terminx 1470
#endif
5 Plagman 1471
 
7234 terminx 1472
        if ((s.cstat & 48)
6799 terminx 1473
#ifndef EDUKE32_STANDALONE
7234 terminx 1474
            && s.picnum != SPEAKER && s.picnum != LETTER && s.picnum != DUCK && s.picnum != TARGET && s.picnum != TRIPBOMB
6799 terminx 1475
#endif
7234 terminx 1476
            && s.picnum != VIEWSCREEN && s.picnum != VIEWSCREEN2 && (!(s.picnum >= CRACK1 && s.picnum <= CRACK4)))
5827 terminx 1477
        {
7234 terminx 1478
            if (s.shade == 127)
5827 terminx 1479
                goto SPAWN_END;
1480
 
6799 terminx 1481
#ifndef EDUKE32_STANDALONE
7234 terminx 1482
            if (A_CheckSwitchTile(newSprite) && (s.cstat & 16))
5 Plagman 1483
            {
7234 terminx 1484
                if (s.pal && s.picnum != ACCESSSWITCH && s.picnum != ACCESSSWITCH2)
5 Plagman 1485
                {
5827 terminx 1486
                    if (((!g_netServer && ud.multimode < 2)) || ((g_netServer || ud.multimode > 1) && !GTFLAGS(GAMETYPE_DMSWITCHES)))
5 Plagman 1487
                    {
7234 terminx 1488
                        s.xrepeat = s.yrepeat = 0;
1489
                        s.lotag = s.hitag = 0;
1490
                        s.cstat = 32768;
5827 terminx 1491
                        goto SPAWN_END;
5 Plagman 1492
                    }
5827 terminx 1493
                }
4346 helixhorne 1494
 
7234 terminx 1495
                s.cstat |= 257;
4346 helixhorne 1496
 
7234 terminx 1497
                if (s.pal && s.picnum != ACCESSSWITCH && s.picnum != ACCESSSWITCH2)
1498
                    s.pal = 0;
6500 terminx 1499
 
5827 terminx 1500
                goto SPAWN_END;
1501
            }
6799 terminx 1502
#endif
5 Plagman 1503
 
7234 terminx 1504
            if (s.hitag)
5827 terminx 1505
            {
1506
                changespritestat(newSprite, STAT_FALLER);
7234 terminx 1507
                s.cstat |= 257;
1508
                s.extra = g_impactDamage;
5827 terminx 1509
                goto SPAWN_END;
5 Plagman 1510
            }
5827 terminx 1511
        }
5 Plagman 1512
 
7234 terminx 1513
        if (s.cstat & 1)
1514
            s.cstat |= 256;
5 Plagman 1515
 
7234 terminx 1516
        if (!G_InitActor(newSprite, s.picnum, 0))
5827 terminx 1517
            T2(newSprite) = T5(newSprite) = 0;  // AC_MOVE_ID, AC_ACTION_ID
5 Plagman 1518
    }
1519
 
5827 terminx 1520
    pSprite = &sprite[newSprite];
6500 terminx 1521
    pActor  = &actor[newSprite];
5827 terminx 1522
    sectNum = pSprite->sectnum;
5 Plagman 1523
 
1524
    //some special cases that can't be handled through the dynamictostatic system.
6810 terminx 1525
 
1526
    if (pSprite->picnum >= CAMERA1 && pSprite->picnum <= CAMERA1 + 4)
1527
        pSprite->picnum = CAMERA1;
6799 terminx 1528
#ifndef EDUKE32_STANDALONE
6810 terminx 1529
    else if (pSprite->picnum >= BOLT1 && pSprite->picnum <= BOLT1 + 3)
1530
        pSprite->picnum = BOLT1;
1531
    else if (pSprite->picnum >= SIDEBOLT1 && pSprite->picnum <= SIDEBOLT1 + 3)
1532
        pSprite->picnum = SIDEBOLT1;
6799 terminx 1533
#endif
5827 terminx 1534
        switch (DYNAMICTILEMAP(pSprite->picnum))
5 Plagman 1535
        {
337 terminx 1536
        default:
5827 terminx 1537
            if (G_HaveActor(pSprite->picnum))
337 terminx 1538
            {
5827 terminx 1539
                if (spriteNum == -1 && pSprite->lotag > ud.player_skill)
5 Plagman 1540
                {
5827 terminx 1541
                    pSprite->xrepeat = pSprite->yrepeat = 0;
1542
                    changespritestat(newSprite, STAT_MISC);
337 terminx 1543
                    break;
1544
                }
1545
 
1546
                //  Init the size
5827 terminx 1547
                if (pSprite->xrepeat == 0 || pSprite->yrepeat == 0)
1548
                    pSprite->xrepeat = pSprite->yrepeat = 1;
337 terminx 1549
 
5827 terminx 1550
                if (A_CheckSpriteFlags(newSprite, SFLAG_BADGUY))
337 terminx 1551
                {
1552
                    if (ud.monsters_off == 1)
5 Plagman 1553
                    {
5827 terminx 1554
                        pSprite->xrepeat = pSprite->yrepeat = 0;
1555
                        changespritestat(newSprite, STAT_MISC);
5 Plagman 1556
                        break;
1557
                    }
1558
 
5827 terminx 1559
                    A_Fall(newSprite);
5 Plagman 1560
 
5827 terminx 1561
                    if (A_CheckSpriteFlags(newSprite, SFLAG_BADGUYSTAYPUT))
7169 terminx 1562
                        pActor->stayput = pSprite->sectnum;
5 Plagman 1563
 
564 terminx 1564
                    g_player[myconnectindex].ps->max_actors_killed++;
5827 terminx 1565
                    pSprite->clipdist = 80;
1566
 
1567
                    if (spriteNum >= 0)
5 Plagman 1568
                    {
5827 terminx 1569
                        if (sprite[spriteNum].picnum == RESPAWN)
6500 terminx 1570
                            pActor->tempang = sprite[newSprite].pal = sprite[spriteNum].pal;
5827 terminx 1571
 
6517 hendricks2 1572
                        A_PlayAlertSound(newSprite);
5827 terminx 1573
                        changespritestat(newSprite, STAT_ACTOR);
5 Plagman 1574
                    }
5827 terminx 1575
                    else
1576
                        changespritestat(newSprite, STAT_ZOMBIEACTOR);
5 Plagman 1577
                }
337 terminx 1578
                else
5 Plagman 1579
                {
5827 terminx 1580
                    pSprite->clipdist = 40;
1581
                    pSprite->owner    = newSprite;
1582
                    changespritestat(newSprite, STAT_ACTOR);
5 Plagman 1583
                }
1584
 
6500 terminx 1585
                pActor->timetosleep = 0;
337 terminx 1586
 
5827 terminx 1587
                if (spriteNum >= 0)
1588
                    pSprite->ang = sprite[spriteNum].ang;
337 terminx 1589
            }
1590
            break;
1591
        case FOF__STATIC:
5827 terminx 1592
            pSprite->xrepeat = pSprite->yrepeat = 0;
1593
            changespritestat(newSprite, STAT_MISC);
337 terminx 1594
            break;
6810 terminx 1595
        case CAMERA1__STATIC:
1596
            pSprite->extra = 1;
1597
            pSprite->cstat &= 32768;
1598
 
1599
            if (g_damageCameras)
1600
                pSprite->cstat |= 257;
1601
 
1602
            if ((!g_netServer && ud.multimode < 2) && pSprite->pal != 0)
1603
            {
1604
                pSprite->xrepeat = pSprite->yrepeat = 0;
1605
                changespritestat(newSprite, STAT_MISC);
1606
            }
1607
            else
1608
            {
1609
                pSprite->pal = 0;
1610
                changespritestat(newSprite, STAT_ACTOR);
1611
            }
1612
            break;
6942 terminx 1613
#ifndef EDUKE32_STANDALONE
6810 terminx 1614
        case CAMERAPOLE__STATIC:
1615
            pSprite->extra = 1;
1616
            pSprite->cstat &= 32768;
1617
 
1618
            if (g_damageCameras)
1619
                pSprite->cstat |= 257;
1620
            fallthrough__;
1621
        case GENERICPOLE__STATIC:
1622
            if ((!g_netServer && ud.multimode < 2) && pSprite->pal != 0)
1623
            {
1624
                pSprite->xrepeat = pSprite->yrepeat = 0;
1625
                changespritestat(newSprite, STAT_MISC);
1626
            }
1627
            else
1628
                pSprite->pal = 0;
1629
            break;
1630
 
1631
        case BOLT1__STATIC:
1632
        case SIDEBOLT1__STATIC:
1633
            T1(newSprite) = pSprite->xrepeat;
1634
            T2(newSprite) = pSprite->yrepeat;
1635
            pSprite->yvel = 0;
1636
 
1637
            changespritestat(newSprite, STAT_STANDABLE);
1638
            break;
1639
 
337 terminx 1640
        case WATERSPLASH2__STATIC:
5827 terminx 1641
            if (spriteNum >= 0)
337 terminx 1642
            {
7973 terminx 1643
                setsprite(newSprite, &sprite[spriteNum].pos);
5827 terminx 1644
                pSprite->xrepeat = pSprite->yrepeat = 8+(krand()&7);
337 terminx 1645
            }
5827 terminx 1646
            else pSprite->xrepeat = pSprite->yrepeat = 16+(krand()&15);
337 terminx 1647
 
5827 terminx 1648
            pSprite->shade = -16;
1649
            pSprite->cstat |= 128;
1650
 
1651
            if (spriteNum >= 0)
337 terminx 1652
            {
5827 terminx 1653
                if (sector[sprite[spriteNum].sectnum].lotag == ST_2_UNDERWATER)
5 Plagman 1654
                {
6500 terminx 1655
                    pSprite->z = getceilzofslope(sectNum, pSprite->x, pSprite->y) + (16 << 8);
5827 terminx 1656
                    pSprite->cstat |= 8;
5 Plagman 1657
                }
5827 terminx 1658
                else if (sector[sprite[spriteNum].sectnum].lotag == ST_1_ABOVE_WATER)
6500 terminx 1659
                    pSprite->z = getflorzofslope(sectNum, pSprite->x, pSprite->y);
337 terminx 1660
            }
5 Plagman 1661
 
5827 terminx 1662
            if (sector[sectNum].floorpicnum == FLOORSLIME || sector[sectNum].ceilingpicnum == FLOORSLIME)
1663
                pSprite->pal = 7;
6370 terminx 1664
            fallthrough__;
1625 terminx 1665
        case DOMELITE__STATIC:
5827 terminx 1666
            if (pSprite->picnum == DOMELITE)
1667
                pSprite->cstat |= 257;
6370 terminx 1668
            fallthrough__;
337 terminx 1669
        case NEON1__STATIC:
1670
        case NEON2__STATIC:
1671
        case NEON3__STATIC:
1672
        case NEON4__STATIC:
1673
        case NEON5__STATIC:
1674
        case NEON6__STATIC:
5827 terminx 1675
            if (pSprite->picnum != WATERSPLASH2)
1676
                pSprite->cstat |= 257;
6370 terminx 1677
            fallthrough__;
337 terminx 1678
        case NUKEBUTTON__STATIC:
1679
        case JIBS1__STATIC:
1680
        case JIBS2__STATIC:
1681
        case JIBS3__STATIC:
1682
        case JIBS4__STATIC:
1683
        case JIBS5__STATIC:
1684
        case JIBS6__STATIC:
1685
        case HEADJIB1__STATIC:
1686
        case ARMJIB1__STATIC:
1687
        case LEGJIB1__STATIC:
1688
        case LIZMANHEAD1__STATIC:
1689
        case LIZMANARM1__STATIC:
1690
        case LIZMANLEG1__STATIC:
1691
        case DUKETORSO__STATIC:
1692
        case DUKEGUN__STATIC:
1693
        case DUKELEG__STATIC:
5827 terminx 1694
            changespritestat(newSprite, STAT_MISC);
337 terminx 1695
            break;
1696
        case TONGUE__STATIC:
5827 terminx 1697
            if (spriteNum >= 0)
1698
                pSprite->ang = sprite[spriteNum].ang;
1699
            pSprite->z -= 38<<8;
1700
            pSprite->zvel = 256-(krand()&511);
1701
            pSprite->xvel = 64-(krand()&127);
1702
            changespritestat(newSprite, STAT_PROJECTILE);
337 terminx 1703
            break;
1704
        case NATURALLIGHTNING__STATIC:
5827 terminx 1705
            pSprite->cstat &= ~257;
1706
            pSprite->cstat |= 32768;
337 terminx 1707
            break;
1708
        case TRANSPORTERSTAR__STATIC:
1709
        case TRANSPORTERBEAM__STATIC:
5827 terminx 1710
            if (spriteNum == -1) break;
1711
            if (pSprite->picnum == TRANSPORTERBEAM)
337 terminx 1712
            {
5827 terminx 1713
                pSprite->xrepeat = 31;
1714
                pSprite->yrepeat = 1;
1715
                pSprite->z = sector[sprite[spriteNum].sectnum].floorz-PHEIGHT;
337 terminx 1716
            }
1717
            else
1718
            {
5827 terminx 1719
                if (sprite[spriteNum].statnum == STAT_PROJECTILE)
1720
                    pSprite->xrepeat = pSprite->yrepeat = 8;
5 Plagman 1721
                else
1722
                {
5827 terminx 1723
                    pSprite->xrepeat = 48;
1724
                    pSprite->yrepeat = 64;
1725
                    if (sprite[spriteNum].statnum == STAT_PLAYER || A_CheckEnemySprite(&sprite[spriteNum]))
1726
                        pSprite->z -= ZOFFSET5;
5 Plagman 1727
                }
337 terminx 1728
            }
5 Plagman 1729
 
5827 terminx 1730
            pSprite->shade = -127;
1731
            pSprite->cstat = 128|2;
1732
            pSprite->ang = sprite[spriteNum].ang;
5 Plagman 1733
 
5827 terminx 1734
            pSprite->xvel = 128;
1735
            changespritestat(newSprite, STAT_MISC);
1736
            A_SetSprite(newSprite,CLIPMASK0);
7697 terminx 1737
            setsprite(newSprite,&pSprite->pos);
337 terminx 1738
            break;
1739
        case FEMMAG1__STATIC:
1740
        case FEMMAG2__STATIC:
5827 terminx 1741
            pSprite->cstat &= ~257;
1742
            changespritestat(newSprite, STAT_DEFAULT);
337 terminx 1743
            break;
1744
        case DUKETAG__STATIC:
1745
        case SIGN1__STATIC:
1746
        case SIGN2__STATIC:
5827 terminx 1747
            if ((!g_netServer && ud.multimode < 2) && pSprite->pal)
337 terminx 1748
            {
5827 terminx 1749
                pSprite->xrepeat = pSprite->yrepeat = 0;
1750
                changespritestat(newSprite, STAT_MISC);
337 terminx 1751
            }
5827 terminx 1752
            else pSprite->pal = 0;
337 terminx 1753
            break;
5827 terminx 1754
 
337 terminx 1755
        case MASKWALL1__STATIC:
1756
        case MASKWALL2__STATIC:
1757
        case MASKWALL3__STATIC:
1758
        case MASKWALL4__STATIC:
1759
        case MASKWALL5__STATIC:
1760
        case MASKWALL6__STATIC:
1761
        case MASKWALL7__STATIC:
1762
        case MASKWALL8__STATIC:
1763
        case MASKWALL9__STATIC:
1764
        case MASKWALL10__STATIC:
1765
        case MASKWALL11__STATIC:
1766
        case MASKWALL12__STATIC:
1767
        case MASKWALL13__STATIC:
1768
        case MASKWALL14__STATIC:
1769
        case MASKWALL15__STATIC:
5827 terminx 1770
        {
1771
            int const j    = pSprite->cstat & SPAWN_PROTECT_CSTAT_MASK;
1772
            pSprite->cstat = j | CSTAT_SPRITE_BLOCK;
1773
            changespritestat(newSprite, STAT_DEFAULT);
337 terminx 1774
            break;
5827 terminx 1775
        }
5 Plagman 1776
 
1625 terminx 1777
        case PODFEM1__STATIC:
5827 terminx 1778
            pSprite->extra <<= 1;
6370 terminx 1779
            fallthrough__;
337 terminx 1780
        case FEM1__STATIC:
1781
        case FEM2__STATIC:
1782
        case FEM3__STATIC:
1783
        case FEM4__STATIC:
1784
        case FEM5__STATIC:
1785
        case FEM6__STATIC:
1786
        case FEM7__STATIC:
1787
        case FEM8__STATIC:
1788
        case FEM9__STATIC:
1789
        case FEM10__STATIC:
1790
        case NAKED1__STATIC:
1791
        case STATUE__STATIC:
1792
        case TOUGHGAL__STATIC:
5827 terminx 1793
            pSprite->yvel  = pSprite->hitag;
1794
            pSprite->hitag = -1;
6370 terminx 1795
            fallthrough__;
337 terminx 1796
        case BLOODYPOLE__STATIC:
5827 terminx 1797
            pSprite->cstat   |= 257;
1798
            pSprite->clipdist = 32;
1799
            changespritestat(newSprite, STAT_ZOMBIEACTOR);
1625 terminx 1800
            break;
337 terminx 1801
 
1802
        case QUEBALL__STATIC:
1803
        case STRIPEBALL__STATIC:
5827 terminx 1804
            pSprite->cstat    = 256;
1805
            pSprite->clipdist = 8;
1806
            changespritestat(newSprite, STAT_ZOMBIEACTOR);
337 terminx 1807
            break;
1808
 
1809
        case DUKELYINGDEAD__STATIC:
5827 terminx 1810
            if (spriteNum >= 0 && sprite[spriteNum].picnum == APLAYER)
337 terminx 1811
            {
5827 terminx 1812
                pSprite->xrepeat = sprite[spriteNum].xrepeat;
1813
                pSprite->yrepeat = sprite[spriteNum].yrepeat;
1814
                pSprite->shade   = sprite[spriteNum].shade;
1815
                pSprite->pal     = g_player[P_Get(spriteNum)].ps->palookup;
337 terminx 1816
            }
6370 terminx 1817
            fallthrough__;
337 terminx 1818
        case DUKECAR__STATIC:
1819
        case HELECOPT__STATIC:
1820
            //                if(sp->picnum == HELECOPT || sp->picnum == DUKECAR) sp->xvel = 1024;
5827 terminx 1821
            pSprite->cstat = 0;
1822
            pSprite->extra = 1;
1823
            pSprite->xvel  = 292;
1824
            pSprite->zvel  = 360;
6370 terminx 1825
            fallthrough__;
337 terminx 1826
        case BLIMP__STATIC:
5827 terminx 1827
            pSprite->cstat   |= 257;
1828
            pSprite->clipdist = 128;
1829
            changespritestat(newSprite, STAT_ACTOR);
1625 terminx 1830
            break;
337 terminx 1831
 
1625 terminx 1832
        case RESPAWNMARKERRED__STATIC:
5827 terminx 1833
            pSprite->xrepeat = pSprite->yrepeat = 24;
1834
            if (spriteNum >= 0)
1835
                pSprite->z = actor[spriteNum].floorz;  // -(1<<4);
1836
            changespritestat(newSprite, STAT_ACTOR);
1625 terminx 1837
            break;
1838
 
337 terminx 1839
        case MIKE__STATIC:
5827 terminx 1840
            pSprite->yvel  = pSprite->hitag;
1841
            pSprite->hitag = 0;
1842
            changespritestat(newSprite, STAT_ACTOR);
1625 terminx 1843
            break;
337 terminx 1844
        case WEATHERWARN__STATIC:
5827 terminx 1845
            changespritestat(newSprite, STAT_ACTOR);
337 terminx 1846
            break;
5 Plagman 1847
 
337 terminx 1848
        case SPOTLITE__STATIC:
5827 terminx 1849
            T1(newSprite) = pSprite->x;
1850
            T2(newSprite) = pSprite->y;
337 terminx 1851
            break;
1852
        case BULLETHOLE__STATIC:
5827 terminx 1853
            pSprite->xrepeat = 3;
1854
            pSprite->yrepeat = 3;
1855
            pSprite->cstat   = 16 + (krand() & 12);
1856
 
1857
            A_AddToDeleteQueue(newSprite);
1858
            changespritestat(newSprite, STAT_MISC);
1625 terminx 1859
            break;
1860
 
337 terminx 1861
        case MONEY__STATIC:
1862
        case MAIL__STATIC:
1863
        case PAPER__STATIC:
6500 terminx 1864
            pActor->t_data[0] = krand() & 2047;
5827 terminx 1865
 
1866
            pSprite->cstat   = krand() & 12;
1867
            pSprite->xrepeat = 8;
1868
            pSprite->yrepeat = 8;
1869
            pSprite->ang     = krand() & 2047;
1870
 
1871
            changespritestat(newSprite, STAT_MISC);
337 terminx 1872
            break;
6800 terminx 1873
 
337 terminx 1874
        case SHELL__STATIC: //From the player
1875
        case SHOTGUNSHELL__STATIC:
5827 terminx 1876
            if (spriteNum >= 0)
337 terminx 1877
            {
5827 terminx 1878
                int shellAng;
337 terminx 1879
 
5827 terminx 1880
                if (sprite[spriteNum].picnum == APLAYER)
5 Plagman 1881
                {
7776 terminx 1882
                    int const  playerNum = P_Get(spriteNum);
1883
                    auto const pPlayer   = g_player[playerNum].ps;
337 terminx 1884
 
6725 terminx 1885
                    shellAng = fix16_to_int(pPlayer->q16ang) - (krand() & 63) + 8;  // Fine tune
4226 helixhorne 1886
 
5827 terminx 1887
                    T1(newSprite) = krand() & 1;
1888
 
6725 terminx 1889
                    pSprite->z = (3 << 8) + pPlayer->pyoff + pPlayer->pos.z - (fix16_to_int((pPlayer->q16horizoff + pPlayer->q16horiz - F16(100))) << 4);
5827 terminx 1890
 
1891
                    if (pSprite->picnum == SHOTGUNSHELL)
1892
                        pSprite->z += (3 << 8);
1893
 
1894
                    pSprite->zvel = -(krand() & 255);
5 Plagman 1895
                }
1896
                else
1897
                {
5827 terminx 1898
                    shellAng          = pSprite->ang;
1899
                    pSprite->z = sprite[spriteNum].z - PHEIGHT + (3 << 8);
5 Plagman 1900
                }
1901
 
5827 terminx 1902
                pSprite->x     = sprite[spriteNum].x + (sintable[(shellAng + 512) & 2047] >> 7);
1903
                pSprite->y     = sprite[spriteNum].y + (sintable[shellAng & 2047] >> 7);
1904
                pSprite->shade = -8;
5 Plagman 1905
 
5827 terminx 1906
                if (pSprite->yvel == 1 || NAM_WW2GI)
5 Plagman 1907
                {
5827 terminx 1908
                    pSprite->ang  = shellAng + 512;
1909
                    pSprite->xvel = 30;
5 Plagman 1910
                }
1911
                else
1912
                {
5827 terminx 1913
                    pSprite->ang  = shellAng - 512;
1914
                    pSprite->xvel = 20;
5 Plagman 1915
                }
1916
 
5827 terminx 1917
                pSprite->xrepeat = pSprite->yrepeat = 4;
1918
 
1919
                changespritestat(newSprite, STAT_MISC);
337 terminx 1920
            }
1921
            break;
5 Plagman 1922
 
337 terminx 1923
        case WATERBUBBLE__STATIC:
5827 terminx 1924
            if (spriteNum >= 0)
337 terminx 1925
            {
5827 terminx 1926
                if (sprite[spriteNum].picnum == APLAYER)
1927
                    pSprite->z -= (16 << 8);
1928
 
1929
                pSprite->ang = sprite[spriteNum].ang;
337 terminx 1930
            }
5 Plagman 1931
 
5827 terminx 1932
            pSprite->xrepeat = pSprite->yrepeat = 4;
1933
            changespritestat(newSprite, STAT_MISC);
337 terminx 1934
            break;
5 Plagman 1935
 
337 terminx 1936
        case CRANE__STATIC:
5 Plagman 1937
 
5827 terminx 1938
            pSprite->cstat |= 64|257;
5 Plagman 1939
 
5827 terminx 1940
            pSprite->picnum += 2;
1941
            pSprite->z = sector[sectNum].ceilingz+(48<<8);
1942
            T5(newSprite) = tempwallptr;
5 Plagman 1943
 
7905 terminx 1944
            g_origins[tempwallptr] = pSprite->pos.vec2;
5827 terminx 1945
            g_origins[tempwallptr+2].x = pSprite->z;
5 Plagman 1946
 
5827 terminx 1947
 
1948
            if (headspritestat[STAT_DEFAULT] != -1)
337 terminx 1949
            {
5827 terminx 1950
                int findSprite = headspritestat[STAT_DEFAULT];
1951
 
1952
                do
5 Plagman 1953
                {
6500 terminx 1954
                    if (sprite[findSprite].picnum == CRANEPOLE && pSprite->hitag == (sprite[findSprite].hitag))
5827 terminx 1955
                    {
1956
                        g_origins[tempwallptr + 2].y = findSprite;
5 Plagman 1957
 
5827 terminx 1958
                        T2(newSprite) = sprite[findSprite].sectnum;
5 Plagman 1959
 
5827 terminx 1960
                        sprite[findSprite].xrepeat = 48;
1961
                        sprite[findSprite].yrepeat = 128;
5 Plagman 1962
 
7905 terminx 1963
                        g_origins[tempwallptr + 1] = sprite[findSprite].pos.vec2;
7697 terminx 1964
                        sprite[findSprite].pos     = pSprite->pos;
1965
                        sprite[findSprite].shade   = pSprite->shade;
5 Plagman 1966
 
7973 terminx 1967
                        setsprite(findSprite, &sprite[findSprite].pos);
5827 terminx 1968
                        break;
1969
                    }
1970
                    findSprite = nextspritestat[findSprite];
1971
                } while (findSprite >= 0);
337 terminx 1972
            }
5 Plagman 1973
 
337 terminx 1974
            tempwallptr += 3;
5827 terminx 1975
            pSprite->owner = -1;
1976
            pSprite->extra = 8;
1977
            changespritestat(newSprite, STAT_STANDABLE);
337 terminx 1978
            break;
5 Plagman 1979
 
1625 terminx 1980
        case TRASH__STATIC:
5827 terminx 1981
            pSprite->ang = krand()&2047;
1982
            pSprite->xrepeat = pSprite->yrepeat = 24;
1983
            changespritestat(newSprite, STAT_STANDABLE);
1625 terminx 1984
            break;
1985
 
337 terminx 1986
        case WATERDRIP__STATIC:
5827 terminx 1987
            if (spriteNum >= 0 && (sprite[spriteNum].statnum == STAT_PLAYER || sprite[spriteNum].statnum == STAT_ACTOR))
337 terminx 1988
            {
5827 terminx 1989
                if (sprite[spriteNum].pal != 1)
5 Plagman 1990
                {
5827 terminx 1991
                    pSprite->pal = 2;
1992
                    pSprite->z -= (18<<8);
5 Plagman 1993
                }
5827 terminx 1994
                else pSprite->z -= (13<<8);
1995
 
1996
                pSprite->shade = 32;
1997
                pSprite->ang   = getangle(g_player[0].ps->pos.x - pSprite->x, g_player[0].ps->pos.y - pSprite->y);
1998
                pSprite->xvel  = 48 - (krand() & 31);
1999
 
6800 terminx 2000
                A_SetSprite(newSprite, CLIPMASK0);
337 terminx 2001
            }
5827 terminx 2002
            else if (spriteNum == -1)
337 terminx 2003
            {
5828 terminx 2004
                pSprite->z += ZOFFSET6;
5827 terminx 2005
                T1(newSprite) = pSprite->z;
2006
                T2(newSprite) = krand()&127;
337 terminx 2007
            }
6370 terminx 2008
            fallthrough__;
337 terminx 2009
        case WATERDRIPSPLASH__STATIC:
5827 terminx 2010
            pSprite->xrepeat = pSprite->yrepeat = 24;
2011
            changespritestat(newSprite, STAT_STANDABLE);
337 terminx 2012
            break;
5 Plagman 2013
 
337 terminx 2014
        case PLUG__STATIC:
5827 terminx 2015
            pSprite->lotag = 9999;
2016
            changespritestat(newSprite, STAT_STANDABLE);
337 terminx 2017
            break;
2018
        case TARGET__STATIC:
2019
        case DUCK__STATIC:
2020
        case LETTER__STATIC:
5827 terminx 2021
            pSprite->extra = 1;
2022
            pSprite->cstat |= 257;
2023
            changespritestat(newSprite, STAT_ACTOR);
337 terminx 2024
            break;
5827 terminx 2025
 
337 terminx 2026
        case OCTABRAINSTAYPUT__STATIC:
2027
        case LIZTROOPSTAYPUT__STATIC:
2028
        case PIGCOPSTAYPUT__STATIC:
2029
        case LIZMANSTAYPUT__STATIC:
2030
        case BOSS1STAYPUT__STATIC:
2031
        case PIGCOPDIVE__STATIC:
2032
        case COMMANDERSTAYPUT__STATIC:
2033
        case BOSS4STAYPUT__STATIC:
7169 terminx 2034
            pActor->stayput = pSprite->sectnum;
6370 terminx 2035
            fallthrough__;
337 terminx 2036
        case BOSS1__STATIC:
2037
        case BOSS2__STATIC:
2038
        case BOSS3__STATIC:
2039
        case BOSS4__STATIC:
2040
        case ROTATEGUN__STATIC:
2041
        case GREENSLIME__STATIC:
5827 terminx 2042
            if (pSprite->picnum == GREENSLIME)
2043
                pSprite->extra = 1;
6370 terminx 2044
            fallthrough__;
337 terminx 2045
        case DRONE__STATIC:
2046
        case LIZTROOPONTOILET__STATIC:
2047
        case LIZTROOPJUSTSIT__STATIC:
2048
        case LIZTROOPSHOOT__STATIC:
2049
        case LIZTROOPJETPACK__STATIC:
2050
        case LIZTROOPDUCKING__STATIC:
2051
        case LIZTROOPRUNNING__STATIC:
2052
        case LIZTROOP__STATIC:
2053
        case OCTABRAIN__STATIC:
2054
        case COMMANDER__STATIC:
2055
        case PIGCOP__STATIC:
2056
        case LIZMAN__STATIC:
2057
        case LIZMANSPITTING__STATIC:
2058
        case LIZMANFEEDING__STATIC:
2059
        case LIZMANJUMP__STATIC:
2060
        case ORGANTIC__STATIC:
2061
        case RAT__STATIC:
2062
        case SHARK__STATIC:
5 Plagman 2063
 
5827 terminx 2064
            if (pSprite->pal == 0)
337 terminx 2065
            {
5827 terminx 2066
                switch (DYNAMICTILEMAP(pSprite->picnum))
5 Plagman 2067
                {
6800 terminx 2068
                case LIZTROOPONTOILET__STATIC:
2069
                case LIZTROOPSHOOT__STATIC:
2070
                case LIZTROOPJETPACK__STATIC:
2071
                case LIZTROOPDUCKING__STATIC:
2072
                case LIZTROOPRUNNING__STATIC:
2073
                case LIZTROOPSTAYPUT__STATIC:
2074
                case LIZTROOPJUSTSIT__STATIC:
2075
                case LIZTROOP__STATIC: pSprite->pal = 22; break;
5 Plagman 2076
                }
337 terminx 2077
            }
3102 terminx 2078
            else
2079
            {
4366 terminx 2080
                if (!PLUTOPAK)
5827 terminx 2081
                    pSprite->extra <<= 1;
3102 terminx 2082
            }
5 Plagman 2083
 
5827 terminx 2084
            if (pSprite->picnum == BOSS4STAYPUT || pSprite->picnum == BOSS1 || pSprite->picnum == BOSS2 ||
2085
                pSprite->picnum == BOSS1STAYPUT || pSprite->picnum == BOSS3 || pSprite->picnum == BOSS4)
337 terminx 2086
            {
5827 terminx 2087
                if (spriteNum >= 0 && sprite[spriteNum].picnum == RESPAWN)
2088
                    pSprite->pal = sprite[spriteNum].pal;
2089
 
2090
                if (pSprite->pal)
5 Plagman 2091
                {
5827 terminx 2092
                    pSprite->clipdist = 80;
2093
                    pSprite->xrepeat  = pSprite->yrepeat = 40;
5 Plagman 2094
                }
2095
                else
2096
                {
5827 terminx 2097
                    pSprite->xrepeat  = pSprite->yrepeat = 80;
2098
                    pSprite->clipdist = 164;
5 Plagman 2099
                }
337 terminx 2100
            }
2101
            else
2102
            {
5827 terminx 2103
                if (pSprite->picnum != SHARK)
5 Plagman 2104
                {
5827 terminx 2105
                    pSprite->xrepeat  = pSprite->yrepeat = 40;
2106
                    pSprite->clipdist = 80;
5 Plagman 2107
                }
2108
                else
2109
                {
5827 terminx 2110
                    pSprite->xrepeat  = pSprite->yrepeat = 60;
2111
                    pSprite->clipdist = 40;
5 Plagman 2112
                }
337 terminx 2113
            }
5 Plagman 2114
 
3922 helixhorne 2115
            // If spawned from parent sprite (as opposed to 'from premap'),
2116
            // ignore skill.
5827 terminx 2117
            if (spriteNum >= 0)
2118
                pSprite->lotag = 0;
5 Plagman 2119
 
5827 terminx 2120
            if ((pSprite->lotag > ud.player_skill) || ud.monsters_off == 1)
337 terminx 2121
            {
5827 terminx 2122
                pSprite->xrepeat=pSprite->yrepeat=0;
2123
                changespritestat(newSprite, STAT_MISC);
5 Plagman 2124
                break;
337 terminx 2125
            }
2126
            else
2127
            {
5827 terminx 2128
                A_Fall(newSprite);
5 Plagman 2129
 
5827 terminx 2130
                if (pSprite->picnum == RAT)
337 terminx 2131
                {
5827 terminx 2132
                    pSprite->ang = krand()&2047;
2133
                    pSprite->xrepeat = pSprite->yrepeat = 48;
2134
                    pSprite->cstat = 0;
337 terminx 2135
                }
2136
                else
2137
                {
5827 terminx 2138
                    pSprite->cstat |= 257;
5 Plagman 2139
 
5827 terminx 2140
                    if (pSprite->picnum != SHARK)
564 terminx 2141
                        g_player[myconnectindex].ps->max_actors_killed++;
337 terminx 2142
                }
5 Plagman 2143
 
5827 terminx 2144
                if (pSprite->picnum == ORGANTIC) pSprite->cstat |= 128;
5 Plagman 2145
 
5827 terminx 2146
                if (spriteNum >= 0)
5 Plagman 2147
                {
6500 terminx 2148
                    pActor->timetosleep = 0;
5827 terminx 2149
                    A_PlayAlertSound(newSprite);
2150
                    changespritestat(newSprite, STAT_ACTOR);
5 Plagman 2151
                }
5827 terminx 2152
                else changespritestat(newSprite, STAT_ZOMBIEACTOR);
337 terminx 2153
            }
5 Plagman 2154
 
5827 terminx 2155
            if (pSprite->picnum == ROTATEGUN)
2156
                pSprite->zvel = 0;
5 Plagman 2157
 
337 terminx 2158
            break;
5 Plagman 2159
 
1625 terminx 2160
        case REACTOR2__STATIC:
2161
        case REACTOR__STATIC:
5827 terminx 2162
            pSprite->extra = g_impactDamage;
6500 terminx 2163
            pSprite->cstat |= 257;
5827 terminx 2164
            if ((!g_netServer && ud.multimode < 2) && pSprite->pal != 0)
2951 helixhorne 2165
            {
5827 terminx 2166
                pSprite->xrepeat = pSprite->yrepeat = 0;
2167
                changespritestat(newSprite, STAT_MISC);
2951 helixhorne 2168
                break;
2169
            }
1662 terminx 2170
 
6500 terminx 2171
            pSprite->pal   = 0;
2172
            pSprite->shade = -17;
2173
 
5827 terminx 2174
            changespritestat(newSprite, STAT_ZOMBIEACTOR);
1662 terminx 2175
            break;
2176
 
337 terminx 2177
        case HEAVYHBOMB__STATIC:
5827 terminx 2178
            if (spriteNum >= 0)
2179
                pSprite->owner = spriteNum;
2180
            else pSprite->owner = newSprite;
1625 terminx 2181
 
5827 terminx 2182
            pSprite->xrepeat = pSprite->yrepeat = 9;
2183
            pSprite->yvel = 4;
6500 terminx 2184
            pSprite->cstat |= 257;
1625 terminx 2185
 
5827 terminx 2186
            if ((!g_netServer && ud.multimode < 2) && pSprite->pal != 0)
1625 terminx 2187
            {
5827 terminx 2188
                pSprite->xrepeat = pSprite->yrepeat = 0;
2189
                changespritestat(newSprite, STAT_MISC);
1625 terminx 2190
                break;
2191
            }
6500 terminx 2192
            pSprite->pal   = 0;
2193
            pSprite->shade = -17;
1625 terminx 2194
 
5827 terminx 2195
            changespritestat(newSprite, STAT_ZOMBIEACTOR);
1625 terminx 2196
            break;
2197
 
337 terminx 2198
        case RECON__STATIC:
5827 terminx 2199
            if (pSprite->lotag > ud.player_skill)
1662 terminx 2200
            {
5827 terminx 2201
                pSprite->xrepeat = pSprite->yrepeat = 0;
2202
                changespritestat(newSprite, STAT_MISC);
1662 terminx 2203
                goto SPAWN_END;
2204
            }
2205
            g_player[myconnectindex].ps->max_actors_killed++;
6500 terminx 2206
            pActor->t_data[5] = 0;
1662 terminx 2207
            if (ud.monsters_off == 1)
2208
            {
5827 terminx 2209
                pSprite->xrepeat = pSprite->yrepeat = 0;
2210
                changespritestat(newSprite, STAT_MISC);
1662 terminx 2211
                break;
2212
            }
5827 terminx 2213
            pSprite->extra = 130;
6500 terminx 2214
            pSprite->cstat |= 256; // Make it hitable
5 Plagman 2215
 
5827 terminx 2216
            if ((!g_netServer && ud.multimode < 2) && pSprite->pal != 0)
337 terminx 2217
            {
5827 terminx 2218
                pSprite->xrepeat = pSprite->yrepeat = 0;
2219
                changespritestat(newSprite, STAT_MISC);
5 Plagman 2220
                break;
337 terminx 2221
            }
6500 terminx 2222
            pSprite->pal   = 0;
2223
            pSprite->shade = -17;
5 Plagman 2224
 
5827 terminx 2225
            changespritestat(newSprite, STAT_ZOMBIEACTOR);
337 terminx 2226
            break;
5 Plagman 2227
 
337 terminx 2228
        case ATOMICHEALTH__STATIC:
2229
        case STEROIDS__STATIC:
2230
        case HEATSENSOR__STATIC:
2231
        case SHIELD__STATIC:
2232
        case AIRTANK__STATIC:
2233
        case TRIPBOMBSPRITE__STATIC:
2234
        case JETPACK__STATIC:
2235
        case HOLODUKE__STATIC:
5 Plagman 2236
 
337 terminx 2237
        case FIRSTGUNSPRITE__STATIC:
2238
        case CHAINGUNSPRITE__STATIC:
2239
        case SHOTGUNSPRITE__STATIC:
2240
        case RPGSPRITE__STATIC:
2241
        case SHRINKERSPRITE__STATIC:
2242
        case FREEZESPRITE__STATIC:
2243
        case DEVISTATORSPRITE__STATIC:
5 Plagman 2244
 
337 terminx 2245
        case SHOTGUNAMMO__STATIC:
2246
        case FREEZEAMMO__STATIC:
2247
        case HBOMBAMMO__STATIC:
2248
        case CRYSTALAMMO__STATIC:
2249
        case GROWAMMO__STATIC:
2250
        case BATTERYAMMO__STATIC:
2251
        case DEVISTATORAMMO__STATIC:
2252
        case RPGAMMO__STATIC:
2253
        case BOOTS__STATIC:
2254
        case AMMO__STATIC:
2255
        case AMMOLOTS__STATIC:
2256
        case COLA__STATIC:
2257
        case FIRSTAID__STATIC:
2258
        case SIXPAK__STATIC:
2259