Subversion Repositories eduke32

Rev

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

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