Subversion Repositories eduke32

Rev

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