Subversion Repositories eduke32

Rev

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

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