Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
5611 terminx 3
Copyright (C) 2016 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
5 Plagman 20
*/
21
//-------------------------------------------------------------------------
1652 terminx 22
 
5529 hendricks2 23
#define actors_c_
24
 
5 Plagman 25
#include "duke3d.h"
26
 
1595 helixhorne 27
#if KRANDDEBUG
28
# define ACTOR_STATIC
29
#else
30
# define ACTOR_STATIC static
31
#endif
32
 
8103 terminx 33
uint8_t g_radiusDmgStatnums[(MAXSTATUS+7)>>3];
34
 
5830 terminx 35
#define DELETE_SPRITE_AND_CONTINUE(KX) do { A_DeleteSprite(KX); goto next_sprite; } while (0)
1595 helixhorne 36
 
3678 helixhorne 37
int32_t otherp;
38
 
5835 terminx 39
int G_SetInterpolation(int32_t *const posptr)
5 Plagman 40
{
5835 terminx 41
    if (g_interpolationCnt >= MAXINTERPOLATIONS)
3486 helixhorne 42
        return 1;
43
 
5835 terminx 44
    for (bssize_t i = 0; i < g_interpolationCnt; ++i)
3486 helixhorne 45
        if (curipos[i] == posptr)
46
            return 0;
47
 
5835 terminx 48
    curipos[g_interpolationCnt] = posptr;
49
    oldipos[g_interpolationCnt] = *posptr;
50
    g_interpolationCnt++;
3486 helixhorne 51
    return 0;
5 Plagman 52
}
53
 
7070 terminx 54
void G_StopInterpolation(const int32_t * const posptr)
5 Plagman 55
{
5835 terminx 56
    for (bssize_t i = 0; i < g_interpolationCnt; ++i)
5 Plagman 57
        if (curipos[i] == posptr)
58
        {
5835 terminx 59
            g_interpolationCnt--;
60
            oldipos[i] = oldipos[g_interpolationCnt];
61
            bakipos[i] = bakipos[g_interpolationCnt];
62
            curipos[i] = curipos[g_interpolationCnt];
5 Plagman 63
        }
64
}
65
 
5835 terminx 66
void G_DoInterpolations(int smoothRatio)
5 Plagman 67
{
1531 plagman 68
    if (g_interpolationLock++)
69
        return;
70
 
7047 terminx 71
    int32_t ndelta = 0;
5067 terminx 72
 
5835 terminx 73
    for (bssize_t i = 0, j = 0; i < g_interpolationCnt; ++i)
5 Plagman 74
    {
7047 terminx 75
        int32_t const odelta = ndelta;
5 Plagman 76
        bakipos[i] = *curipos[i];
5067 terminx 77
        ndelta = (*curipos[i]) - oldipos[i];
78
        if (odelta != ndelta)
5835 terminx 79
            j = mulscale16(ndelta, smoothRatio);
5067 terminx 80
        *curipos[i] = oldipos[i] + j;
5 Plagman 81
    }
82
}
83
 
2853 helixhorne 84
void G_ClearCameraView(DukePlayer_t *ps)
85
{
86
    ps->newowner = -1;
5067 terminx 87
    ps->pos = ps->opos;
6725 terminx 88
    ps->q16ang = ps->oq16ang;
2853 helixhorne 89
 
90
    updatesector(ps->pos.x, ps->pos.y, &ps->cursectnum);
91
    P_UpdateScreenPal(ps);
92
 
5829 terminx 93
    for (bssize_t SPRITES_OF(STAT_ACTOR, k))
2853 helixhorne 94
        if (sprite[k].picnum==CAMERA1)
95
            sprite[k].yvel = 0;
96
}
97
 
8079 terminx 98
void A_RadiusDamageObject_Internal(int const spriteNum, int const otherSprite, int const blastRadius, int spriteDist,
99
                                   int const zOffset, int const dmg1, int dmg2, int dmg3, int dmg4)
4204 helixhorne 100
{
7603 terminx 101
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
8079 terminx 102
    auto const pOther  = &sprite[otherSprite];
6796 terminx 103
 
8079 terminx 104
    // DEFAULT, ZOMBIEACTOR, MISC
105
    if (pOther->statnum == STAT_DEFAULT || pOther->statnum == STAT_ZOMBIEACTOR || pOther->statnum == STAT_MISC || AFLAMABLE(pOther->picnum))
106
    {
107
#ifndef EDUKE32_STANDALONE
108
        if (pSprite->picnum != SHRINKSPARK || (pOther->cstat&257))
109
#endif
110
        {
111
            if (A_CheckEnemySprite(pOther) && !cansee(pOther->x, pOther->y, pOther->z+zOffset, pOther->sectnum, pSprite->x, pSprite->y, pSprite->z+zOffset, pSprite->sectnum))
112
                return;
6796 terminx 113
 
8089 terminx 114
#ifndef EDUKE32_STANDALONE
115
            if (!FURY)
116
                A_DamageObject_Duke3D(otherSprite, spriteNum);
117
            else
118
#endif
119
                A_DamageObject_Generic(otherSprite, spriteNum);
8079 terminx 120
        }
121
    }
122
    else if (pOther->extra >= 0 && (uspriteptr_t)pOther != pSprite && ((pOther->cstat & 257) ||
6796 terminx 123
#ifndef EDUKE32_STANDALONE
8079 terminx 124
        pOther->picnum == TRIPBOMB || pOther->picnum == QUEBALL || pOther->picnum == STRIPEBALL || pOther->picnum == DUKELYINGDEAD ||
6796 terminx 125
#endif
8079 terminx 126
        A_CheckEnemySprite(pOther)))
5 Plagman 127
    {
8079 terminx 128
#ifndef EDUKE32_STANDALONE
129
        if ((pSprite->picnum == SHRINKSPARK && pOther->picnum != SHARK && (otherSprite == pSprite->owner || pOther->xrepeat < 24))
130
            || (pSprite->picnum == MORTER && otherSprite == pSprite->owner))
131
            return;
132
#endif
133
        if (pOther->picnum == APLAYER)
134
            spriteDist = FindDistance3D(pSprite->x - pOther->x, pSprite->y - pOther->y, pSprite->z - (pOther->z - PHEIGHT));
3679 helixhorne 135
 
8079 terminx 136
        if (spriteDist >= blastRadius || !cansee(pOther->x, pOther->y, pOther->z - ZOFFSET3, pOther->sectnum,
137
                                                 pSprite->x, pSprite->y, pSprite->z - ZOFFSET4, pSprite->sectnum))
138
            return;
5 Plagman 139
 
8079 terminx 140
        if (A_CheckSpriteFlags(otherSprite, SFLAG_DAMAGEEVENT))
141
            if (VM_OnEventWithReturn(EVENT_DAMAGESPRITE, spriteNum, -1, otherSprite) < 0)
142
                return;
6796 terminx 143
 
8079 terminx 144
        auto &dmgActor = actor[otherSprite];
145
 
146
        dmgActor.ang = getangle(pOther->x - pSprite->x, pOther->y - pSprite->y);
147
 
148
        if ((pOther->extra > 0 && ((A_CheckSpriteFlags(spriteNum, SFLAG_PROJECTILE) && SpriteProjectile[spriteNum].workslike & PROJECTILE_RADIUS_PICNUM)
149
#ifndef EDUKE32_STANDALONE
150
            || pSprite->picnum == RPG
151
#endif
152
            ))
153
#ifndef EDUKE32_STANDALONE
154
            || (pSprite->picnum == SHRINKSPARK)
155
#endif
156
            )
157
            dmgActor.picnum = pSprite->picnum;
158
        else dmgActor.picnum = RADIUSEXPLOSION;
159
 
160
#ifndef EDUKE32_STANDALONE
161
        if (pSprite->picnum != SHRINKSPARK)
162
#endif
5 Plagman 163
        {
8079 terminx 164
            // this is really weird
165
            int const k = blastRadius/3;
8528 hendricks2 166
            int dmgBase = 0, dmgFuzz = 1;
4205 helixhorne 167
 
8079 terminx 168
            if (spriteDist < k)
8085 terminx 169
                dmgBase = dmg3, dmgFuzz = dmg4;
8079 terminx 170
            else if (spriteDist < k*2)
8085 terminx 171
                dmgBase = dmg2, dmgFuzz = dmg3;
8079 terminx 172
            else if (spriteDist < blastRadius)
8085 terminx 173
                dmgBase = dmg1, dmgFuzz = dmg2;
5 Plagman 174
 
8085 terminx 175
            if (dmgBase == dmgFuzz)
176
                ++dmgFuzz;
177
 
178
            dmgActor.extra = dmgBase + (krand()%(dmgFuzz-dmgBase));
179
 
8079 terminx 180
            if (!A_CheckSpriteFlags(otherSprite, SFLAG_NODAMAGEPUSH))
5825 terminx 181
            {
8079 terminx 182
                if (pOther->xvel < 0) pOther->xvel = 0;
183
                pOther->xvel += (pSprite->extra<<2);
184
            }
3679 helixhorne 185
 
8079 terminx 186
            if (A_CheckSpriteFlags(otherSprite, SFLAG_DAMAGEEVENT))
187
                VM_OnEventWithReturn(EVENT_POSTDAMAGESPRITE, spriteNum, -1, otherSprite);
5825 terminx 188
 
8079 terminx 189
#ifndef EDUKE32_STANDALONE
190
            if (!FURY)
191
            {
192
                switch (DYNAMICTILEMAP(pOther->picnum))
6796 terminx 193
                {
8079 terminx 194
                    case PODFEM1__STATIC:
195
                    case FEM1__STATIC:
196
                    case FEM2__STATIC:
197
                    case FEM3__STATIC:
198
                    case FEM4__STATIC:
199
                    case FEM5__STATIC:
200
                    case FEM6__STATIC:
201
                    case FEM7__STATIC:
202
                    case FEM8__STATIC:
203
                    case FEM9__STATIC:
204
                    case FEM10__STATIC:
205
                    case STATUE__STATIC:
206
                    case STATUEFLASH__STATIC:
207
                    case SPACEMARINE__STATIC:
208
                    case QUEBALL__STATIC:
209
                    case STRIPEBALL__STATIC:
8089 terminx 210
                        A_DamageObject_Duke3D(otherSprite, spriteNum);
8079 terminx 211
                        break;
6796 terminx 212
                }
213
            }
8079 terminx 214
#endif
215
        }
216
#ifndef EDUKE32_STANDALONE
217
        else if (!FURY && pSprite->extra == 0) dmgActor.extra = 0;
218
#endif
3679 helixhorne 219
 
8079 terminx 220
        if (pOther->picnum != RADIUSEXPLOSION &&
221
            pSprite->owner >= 0 && sprite[pSprite->owner].statnum < MAXSTATUS)
222
        {
223
            if (pOther->picnum == APLAYER)
224
            {
225
                auto pPlayer = g_player[P_GetP(pOther)].ps;
3679 helixhorne 226
 
8079 terminx 227
                if (pPlayer->newowner >= 0)
228
                    G_ClearCameraView(pPlayer);
229
            }
3679 helixhorne 230
 
8079 terminx 231
            dmgActor.owner = pSprite->owner;
5 Plagman 232
        }
233
    }
8079 terminx 234
}
5 Plagman 235
 
8558 terminx 236
#define MAXDAMAGESECTORS 128
5 Plagman 237
 
8079 terminx 238
void A_RadiusDamage(int const spriteNum, int const blastRadius, int const dmg1, int const dmg2, int const dmg3, int const dmg4)
239
{
240
    // Allow checking for radius damage in EVENT_DAMAGE(SPRITE/WALL/FLOOR/CEILING) events.
241
    decltype(ud.returnvar) const parms = { blastRadius, dmg1, dmg2, dmg3, dmg4 };
242
    Bmemcpy(ud.returnvar, parms, sizeof(parms));
5 Plagman 243
 
8079 terminx 244
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
6796 terminx 245
 
8079 terminx 246
    int16_t sectorList[MAXDAMAGESECTORS];
247
    uint8_t sectorMap[(MAXSECTORS+7)>>3];
248
    int16_t numSectors;
6081 hendricks2 249
 
8079 terminx 250
    bfirst_search_init(sectorList, sectorMap, &numSectors, MAXSECTORS, pSprite->sectnum);
5 Plagman 251
 
6796 terminx 252
#ifndef EDUKE32_STANDALONE
8086 terminx 253
    if (!FURY && (pSprite->picnum == RPG && pSprite->xrepeat < 11))
8079 terminx 254
        goto SKIPWALLCHECK;
6796 terminx 255
#endif
256
 
8079 terminx 257
    for (int sectorCount=0; sectorCount < numSectors; ++sectorCount)
258
    {
8558 terminx 259
        int const   sectorNum  = sectorList[sectorCount];
8085 terminx 260
        auto const &listSector = sector[sectorNum];
8558 terminx 261
        vec2_t      closest;
6796 terminx 262
 
8101 terminx 263
        if (getsectordist(pSprite->pos.vec2, sectorNum, &closest) >= blastRadius)
8079 terminx 264
            continue;
5 Plagman 265
 
8085 terminx 266
        int const startWall = listSector.wallptr;
267
        int const endWall   = listSector.wallnum + startWall;
5 Plagman 268
 
8101 terminx 269
        int32_t floorZ, ceilZ;
270
        getzsofslope(sectorNum, closest.x, closest.y, &ceilZ, &floorZ);
271
 
272
        if (((ceilZ - pSprite->z) >> 8) < blastRadius)
8079 terminx 273
            Sect_DamageCeiling_Internal(spriteNum, sectorNum);
5825 terminx 274
 
8101 terminx 275
        if (((pSprite->z - floorZ) >> 8) < blastRadius)
8079 terminx 276
            Sect_DamageFloor_Internal(spriteNum, sectorNum);
5825 terminx 277
 
8079 terminx 278
        int w = startWall;
279
 
8085 terminx 280
        for (auto pWall = (uwallptr_t)&wall[startWall]; w < endWall; ++w, ++pWall)
8079 terminx 281
        {
282
            if (getwalldist(pSprite->pos.vec2, w, &closest) >= blastRadius)
283
                continue;
5 Plagman 284
 
8558 terminx 285
            int16_t aSector = sectorNum;
286
            vec3_t  vect    = { (((pWall->x + wall[pWall->point2].x) >> 1) + pSprite->x) >> 1,
287
                                (((pWall->y + wall[pWall->point2].y) >> 1) + pSprite->y) >> 1, pSprite->z };
5 Plagman 288
 
8558 terminx 289
            updatesector(vect.x, vect.y, &aSector);
290
 
291
            if (aSector == -1)
8079 terminx 292
            {
8558 terminx 293
                vect.vec2 = closest;
294
                aSector   = sectorNum;
295
            }
8085 terminx 296
 
8558 terminx 297
            if (cansee(vect.x, vect.y, vect.z, aSector, pSprite->x, pSprite->y, pSprite->z, pSprite->sectnum))
298
                A_DamageWall_Internal(spriteNum, w, { closest.x, closest.y, pSprite->z }, pSprite->picnum);
8099 terminx 299
 
8558 terminx 300
            int const nextSector = pWall->nextsector;
8090 terminx 301
 
8558 terminx 302
            if (nextSector >= 0)
303
                bfirst_search_try(sectorList, sectorMap, &numSectors, nextSector);
304
 
305
            if (numSectors == MAXDAMAGESECTORS)
306
            {
307
                OSD_Printf("Sprite %d tried to damage more than %d sectors!\n", spriteNum, MAXDAMAGESECTORS);
308
                goto SKIPWALLCHECK;
8079 terminx 309
            }
310
        }
311
    }
5 Plagman 312
 
8079 terminx 313
SKIPWALLCHECK:
314
    int const randomZOffset = -ZOFFSET2 + (krand()&(ZOFFSET5-1));
2853 helixhorne 315
 
8079 terminx 316
    for (int sectorCount=0; sectorCount < numSectors; ++sectorCount)
317
    {
318
        int damageSprite = headspritesect[sectorList[sectorCount]];
319
 
320
        while (damageSprite >= 0)
321
        {
322
            int const nextSprite = nextspritesect[damageSprite];
8085 terminx 323
            auto      pDamage    = &sprite[damageSprite];
8079 terminx 324
 
8103 terminx 325
            if (bitmap_test(g_radiusDmgStatnums, pDamage->statnum))
8079 terminx 326
            {
327
                int const spriteDist = dist(pSprite, pDamage);
328
 
329
                if (spriteDist < blastRadius)
330
                    A_RadiusDamageObject_Internal(spriteNum, damageSprite, blastRadius, spriteDist, randomZOffset, dmg1, dmg2, dmg3, dmg4);
5 Plagman 331
            }
8079 terminx 332
 
333
            damageSprite = nextSprite;
5 Plagman 334
        }
335
    }
336
}
337
 
3678 helixhorne 338
// Maybe do a projectile transport via an SE7.
339
// <spritenum>: the projectile
340
// <i>: the SE7
341
// <fromunderp>: below->above change?
7603 terminx 342
static int32_t Proj_MaybeDoTransport(int32_t spriteNum, uspriteptr_t const pSEffector, int32_t fromunderp, int32_t daz)
3678 helixhorne 343
{
8050 pogokeen 344
    if (((int32_t) totalclock & UINT8_MAX) == actor[spriteNum].lasttransport)
5067 terminx 345
        return 0;
3678 helixhorne 346
 
7603 terminx 347
    auto const pSprite = &sprite[spriteNum];
348
    auto const otherse = (uspriteptr_t)&sprite[pSEffector->owner];
3678 helixhorne 349
 
8050 pogokeen 350
    actor[spriteNum].lasttransport = ((int32_t) totalclock & UINT8_MAX);
7603 terminx 351
 
5825 terminx 352
    pSprite->x += (otherse->x - pSEffector->x);
353
    pSprite->y += (otherse->y - pSEffector->y);
3678 helixhorne 354
 
5825 terminx 355
    // above->below
356
    pSprite->z = (!fromunderp) ? sector[otherse->sectnum].ceilingz - daz + sector[pSEffector->sectnum].floorz
357
                               : sector[otherse->sectnum].floorz - daz + sector[pSEffector->sectnum].ceilingz;
358
    // below->above
3682 helixhorne 359
 
7697 terminx 360
    actor[spriteNum].bpos = sprite[spriteNum].pos;
5825 terminx 361
    changespritesect(spriteNum, otherse->sectnum);
3682 helixhorne 362
 
5067 terminx 363
    return 1;
3678 helixhorne 364
}
365
 
366
// Check whether sprite <s> is on/in a non-SE7 water sector.
367
// <othersectptr>: if not NULL, the sector on the other side.
7603 terminx 368
int A_CheckNoSE7Water(uspriteptr_t const pSprite, int sectNum, int sectLotag, int32_t *pOther)
3678 helixhorne 369
{
5825 terminx 370
    if (sectLotag == ST_1_ABOVE_WATER || sectLotag == ST_2_UNDERWATER)
3678 helixhorne 371
    {
5825 terminx 372
        int const otherSect =
373
        yax_getneighborsect(pSprite->x, pSprite->y, sectNum, sectLotag == ST_1_ABOVE_WATER ? YAX_FLOOR : YAX_CEILING);
374
        int const otherLotag = (sectLotag == ST_1_ABOVE_WATER) ? ST_2_UNDERWATER : ST_1_ABOVE_WATER;
3678 helixhorne 375
 
376
        // If submerging, the lower sector MUST have lotag 2.
377
        // If emerging, the upper sector MUST have lotag 1.
378
        // This way, the x/y coordinates where above/below water
379
        // changes can happen are the same.
5825 terminx 380
        if (otherSect >= 0 && sector[otherSect].lotag == otherLotag)
3678 helixhorne 381
        {
5825 terminx 382
            if (pOther)
383
                *pOther = otherSect;
3678 helixhorne 384
            return 1;
385
        }
386
    }
387
 
388
    return 0;
389
}
390
 
391
// Check whether to do a z position update of sprite <spritenum>.
392
// Returns:
393
//  0 if no.
394
//  1 if yes, but stayed inside [actor[].ceilingz+1, actor[].floorz].
3683 helixhorne 395
// <0 if yes, but passed a TROR no-SE7 water boundary. -returnvalue-1 is the
396
//       other-side sector number.
7794 hendricks2 397
static int32_t A_CheckNeedZUpdate(int32_t spriteNum, int32_t zChange, int32_t *pZcoord,
398
    int32_t *ceilhit, int32_t *florhit)
3678 helixhorne 399
{
5825 terminx 400
    if (zChange == 0)
401
        return 0;
3678 helixhorne 402
 
7603 terminx 403
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
404
    int const  newZ    = pSprite->z + (zChange >> 1);
3678 helixhorne 405
 
5825 terminx 406
    *pZcoord = newZ;
3678 helixhorne 407
 
7667 terminx 408
    int const clipDist = A_GetClipdist(spriteNum, -1);
7436 terminx 409
 
7794 hendricks2 410
    VM_GetZRange(spriteNum, ceilhit, florhit, pSprite->statnum == STAT_PROJECTILE ? clipDist << 3 : clipDist);
7667 terminx 411
 
5825 terminx 412
    if (newZ > actor[spriteNum].ceilingz && newZ <= actor[spriteNum].floorz)
3678 helixhorne 413
        return 1;
414
 
415
#ifdef YAX_ENABLE
5825 terminx 416
    int const sectNum   = pSprite->sectnum;
417
    int const sectLotag = sector[sectNum].lotag;
418
    int32_t   otherSect;
3678 helixhorne 419
 
5798 terminx 420
    // Non-SE7 water.
421
    // PROJECTILE_CHSECT
5825 terminx 422
    if ((zChange < 0 && sectLotag == ST_2_UNDERWATER) || (zChange > 0 && sectLotag == ST_1_ABOVE_WATER))
423
    {
424
        if (A_CheckNoSE7Water(pSprite, sprite[spriteNum].sectnum, sectLotag, &otherSect))
5798 terminx 425
        {
5825 terminx 426
            A_Spawn(spriteNum, WATERSPLASH2);
5798 terminx 427
            // NOTE: Don't tweak its z position afterwards like with
428
            // SE7-induced projectile teleportation. It doesn't look good
429
            // with TROR water.
3683 helixhorne 430
 
5825 terminx 431
            actor[spriteNum].flags |= SFLAG_DIDNOSE7WATER;
432
            return -otherSect-1;
5798 terminx 433
        }
5825 terminx 434
    }
3678 helixhorne 435
#endif
436
 
7794 hendricks2 437
    return 2;
3678 helixhorne 438
}
439
 
7436 terminx 440
int A_GetClipdist(int spriteNum, int clipDist)
5 Plagman 441
{
7436 terminx 442
    if (clipDist < 0)
5 Plagman 443
    {
7776 terminx 444
        auto const pSprite = &sprite[spriteNum];
8104 terminx 445
        int const  isEnemy = A_CheckEnemySprite(pSprite);
3075 helixhorne 446
 
7409 terminx 447
        if (A_CheckSpriteFlags(spriteNum, SFLAG_REALCLIPDIST))
448
            clipDist = pSprite->clipdist << 2;
7932 terminx 449
        else if ((pSprite->cstat & 48) == 16)
450
            clipDist = 0;
7409 terminx 451
        else if (isEnemy)
452
        {
453
            if (pSprite->xrepeat > 60)
454
                clipDist = 1024;
7406 terminx 455
#ifndef EDUKE32_STANDALONE
8559 terminx 456
            else if (!FURY && pSprite->picnum == LIZMAN)
7409 terminx 457
                clipDist = 292;
7406 terminx 458
#endif
7409 terminx 459
            else if (A_CheckSpriteFlags(spriteNum, SFLAG_BADGUY))
460
                clipDist = pSprite->clipdist << 2;
461
            else
462
                clipDist = 192;
463
        }
5 Plagman 464
        else
7409 terminx 465
        {
466
            if (pSprite->statnum == STAT_PROJECTILE && (SpriteProjectile[spriteNum].workslike & PROJECTILE_REALCLIPDIST) == 0)
7436 terminx 467
                clipDist = 16;
7409 terminx 468
            else
469
                clipDist = pSprite->clipdist << 2;
470
        }
3075 helixhorne 471
    }
472
 
7436 terminx 473
    return clipDist;
474
}
475
 
476
int32_t A_MoveSpriteClipdist(int32_t spriteNum, vec3_t const * const change, uint32_t clipType, int32_t clipDist)
477
{
8104 terminx 478
    auto const   pSprite = &sprite[spriteNum];
479
    int const    isEnemy = A_CheckEnemySprite(pSprite);
480
    vec2_t const oldPos  = pSprite->pos.vec2;
7436 terminx 481
 
482
    // check to make sure the netcode didn't leave a deleted sprite in the sprite lists.
483
    Bassert(pSprite->sectnum < MAXSECTORS);
484
 
485
#ifndef EDUKE32_STANDALONE
8559 terminx 486
    if (!FURY && (pSprite->statnum == STAT_MISC || (isEnemy && pSprite->xrepeat < 4)))
7436 terminx 487
    {
488
        pSprite->x += change->x;
489
        pSprite->y += change->y;
490
        pSprite->z += change->z;
491
 
492
        if (isEnemy)
7697 terminx 493
            setsprite(spriteNum, &pSprite->pos);
7436 terminx 494
 
495
        return 0;
496
    }
497
#endif
498
 
7697 terminx 499
    setsprite(spriteNum, &pSprite->pos);
7436 terminx 500
 
8546 terminx 501
    if (!(change->x|change->y|change->z))
502
        return 0;
503
 
7436 terminx 504
    clipDist = A_GetClipdist(spriteNum, clipDist);
505
 
5825 terminx 506
    int16_t   newSectnum = pSprite->sectnum;
6806 terminx 507
#ifndef EDUKE32_STANDALONE
6805 terminx 508
    int const oldSectnum = newSectnum;
6806 terminx 509
#endif
5021 helixhorne 510
 
4974 helixhorne 511
    // Handle horizontal movement first.
512
 
7409 terminx 513
    int returnValue;
7461 terminx 514
    int32_t diffZ;
8117 terminx 515
    spriteheightofs(spriteNum, &diffZ, 1);
7409 terminx 516
 
8117 terminx 517
    if (pSprite->statnum == STAT_PROJECTILE)
518
        returnValue = clipmovex(&pSprite->pos, &newSectnum, change->x << 13, change->y << 13, clipDist, diffZ >> 3, diffZ >> 3, clipType, 1);
519
    else
7409 terminx 520
    {
8117 terminx 521
        pSprite->z -= diffZ >> 1;
522
        returnValue = clipmove(&pSprite->pos, &newSectnum, change->x << 13, change->y << 13, clipDist, ZOFFSET6, ZOFFSET6, clipType);
523
        pSprite->z += diffZ >> 1;
7409 terminx 524
    }
525
 
7242 seventyfiv 526
    // Testing: For some reason the assert below this was tripping for clients
527
    EDUKE32_UNUSED int16_t   dbg_ClipMoveSectnum = newSectnum;
528
 
5825 terminx 529
    if (isEnemy)
3075 helixhorne 530
    {
4974 helixhorne 531
        // Handle potential stayput condition (map-provided or hard-coded).
7409 terminx 532
        if (newSectnum < 0 || ((actor[spriteNum].stayput >= 0 && actor[spriteNum].stayput != newSectnum)
8106 terminx 533
                || ((g_tile[pSprite->picnum].flags & SFLAG_NOWATERSECTOR) && sector[newSectnum].lotag == ST_1_ABOVE_WATER)
6798 terminx 534
#ifndef EDUKE32_STANDALONE
8559 terminx 535
                || (!FURY && pSprite->picnum == BOSS2 && pSprite->pal == 0 && sector[newSectnum].lotag != ST_3)
536
                || (!FURY && (pSprite->picnum == BOSS1 || pSprite->picnum == BOSS2) && sector[newSectnum].lotag == ST_1_ABOVE_WATER)
537
                || (!FURY && sector[oldSectnum].lotag != ST_1_ABOVE_WATER && sector[newSectnum].lotag == ST_1_ABOVE_WATER
6798 terminx 538
                    && (pSprite->picnum == LIZMAN || (pSprite->picnum == LIZTROOP && pSprite->zvel == 0)))
539
#endif
540
                ))
5 Plagman 541
        {
7905 terminx 542
            pSprite->pos.vec2 = oldPos;
4974 helixhorne 543
 
544
            // NOTE: in Duke3D, LIZMAN on water takes on random angle here.
545
 
7697 terminx 546
            setsprite(spriteNum, &pSprite->pos);
3075 helixhorne 547
 
5825 terminx 548
            if (newSectnum < 0)
549
                newSectnum = 0;
3075 helixhorne 550
 
5825 terminx 551
            return 16384+newSectnum;
5 Plagman 552
        }
1210 terminx 553
 
5825 terminx 554
        if ((returnValue&49152) >= 32768 && actor[spriteNum].cgg==0)
555
            pSprite->ang += 768;
1490 terminx 556
    }
1210 terminx 557
 
7242 seventyfiv 558
    EDUKE32_UNUSED int16_t   dbg_newSectnum2 = newSectnum;
559
 
5825 terminx 560
    if (newSectnum == -1)
1490 terminx 561
    {
5825 terminx 562
        newSectnum = pSprite->sectnum;
1736 helixhorne 563
//        OSD_Printf("%s:%d wtf\n",__FILE__,__LINE__);
5 Plagman 564
    }
5825 terminx 565
    else if (newSectnum != pSprite->sectnum)
1490 terminx 566
    {
5825 terminx 567
        changespritesect(spriteNum, newSectnum);
3094 terminx 568
        // A_GetZLimits(spritenum);
1490 terminx 569
    }
570
 
5825 terminx 571
    Bassert(newSectnum == pSprite->sectnum);
3075 helixhorne 572
 
8117 terminx 573
    int newZ = pSprite->z;
7794 hendricks2 574
    int32_t ceilhit, florhit;
575
    int const doZUpdate = change->z ? A_CheckNeedZUpdate(spriteNum, change->z, &newZ, &ceilhit, &florhit) : 0;
1490 terminx 576
 
3678 helixhorne 577
    // Update sprite's z positions and (for TROR) maybe the sector number.
7794 hendricks2 578
    if (doZUpdate == 2)
7795 hendricks2 579
    {
580
        if (returnValue == 0)
581
            returnValue = change->z < 0 ? ceilhit : florhit;
582
    }
7794 hendricks2 583
    else if (doZUpdate)
1877 helixhorne 584
    {
5825 terminx 585
        pSprite->z = newZ;
1877 helixhorne 586
#ifdef YAX_ENABLE
5825 terminx 587
        if (doZUpdate < 0)
3678 helixhorne 588
        {
589
            // If we passed a TROR no-SE7 water boundary, signal to the outside
590
            // that the ceiling/floor was not hit. However, this is not enough:
591
            // later, code checks for (retval&49152)!=49152
592
            // [i.e. not "was ceiling or floor hit", but "was no sprite hit"]
593
            // and calls G_WeaponHitCeilingOrFloor() then, so we need to set
4351 helixhorne 594
            // actor[].flags |= SFLAG_DIDNOSE7WATER in A_CheckNeedZUpdate()
3678 helixhorne 595
            // previously.
596
            // XXX: Why is this contrived data flow necessary? (If at all.)
5825 terminx 597
            changespritesect(spriteNum, -doZUpdate-1);
3683 helixhorne 598
            return 0;
3678 helixhorne 599
        }
3683 helixhorne 600
 
5825 terminx 601
        if (yax_getbunch(newSectnum, (change->z>0))>=0
602
                && (SECTORFLD(newSectnum,stat, (change->z>0))&yax_waltosecmask(clipType))==0)
3683 helixhorne 603
        {
7697 terminx 604
            setspritez(spriteNum, &pSprite->pos);
3683 helixhorne 605
        }
1877 helixhorne 606
#endif
607
    }
5825 terminx 608
    else if (change->z != 0 && returnValue == 0)
609
        returnValue = 16384+newSectnum;
5 Plagman 610
 
5825 terminx 611
    if (returnValue == 16384 + newSectnum)
612
    {
613
        if (pSprite->statnum == STAT_PROJECTILE)
1450 terminx 614
        {
3682 helixhorne 615
            // Projectile sector changes due to transport SEs (SE7_PROJECTILE).
616
            // PROJECTILE_CHSECT
5829 terminx 617
            for (bssize_t SPRITES_OF(STAT_TRANSPORT, otherSpriteNum))
5825 terminx 618
            {
619
                if (sprite[otherSpriteNum].sectnum == newSectnum)
1450 terminx 620
                {
5825 terminx 621
                    int const sectLotag = sector[newSectnum].lotag;
3682 helixhorne 622
 
5825 terminx 623
                    if (sectLotag == ST_1_ABOVE_WATER && newZ >= actor[spriteNum].floorz)
7603 terminx 624
                        if (Proj_MaybeDoTransport(spriteNum, (uspriteptr_t)&sprite[otherSpriteNum], 0, newZ))
5825 terminx 625
                            return 0;
3678 helixhorne 626
 
5825 terminx 627
                    if (sectLotag == ST_2_UNDERWATER && newZ <= actor[spriteNum].ceilingz)
7603 terminx 628
                        if (Proj_MaybeDoTransport(spriteNum, (uspriteptr_t)&sprite[otherSpriteNum], 1, newZ))
5825 terminx 629
                            return 0;
1450 terminx 630
                }
5825 terminx 631
            }
1450 terminx 632
        }
5825 terminx 633
    }
1450 terminx 634
 
5825 terminx 635
    return returnValue;
5 Plagman 636
}
637
 
1205 terminx 638
int32_t block_deletesprite = 0;
1138 terminx 639
 
2006 helixhorne 640
#ifdef POLYMER
3053 terminx 641
static void A_DeleteLight(int32_t s)
2006 helixhorne 642
{
2169 helixhorne 643
    if (actor[s].lightId >= 0)
644
        polymer_deletelight(actor[s].lightId);
2006 helixhorne 645
    actor[s].lightId = -1;
646
    actor[s].lightptr = NULL;
647
}
648
 
649
void G_Polymer_UnInit(void)
650
{
651
    int32_t i;
652
 
653
    for (i=0; i<MAXSPRITES; i++)
3053 terminx 654
        A_DeleteLight(i);
2006 helixhorne 655
}
656
#endif
657
 
2452 helixhorne 658
// deletesprite() game wrapper
5825 terminx 659
void A_DeleteSprite(int spriteNum)
587 terminx 660
{
4699 terminx 661
    if (EDUKE32_PREDICT_FALSE(block_deletesprite))
1138 terminx 662
    {
5825 terminx 663
        OSD_Printf(OSD_ERROR "A_DeleteSprite(): tried to remove sprite %d in EVENT_EGS\n", spriteNum);
1138 terminx 664
        return;
665
    }
1399 terminx 666
 
4680 terminx 667
    if (VM_HaveEvent(EVENT_KILLIT))
610 terminx 668
    {
5825 terminx 669
        int32_t playerDist;
670
        int playerNum = A_FindPlayer(&sprite[spriteNum], &playerDist);
1198 terminx 671
 
7636 terminx 672
        if (VM_ExecuteEvent(EVENT_KILLIT, spriteNum, playerNum, playerDist))
610 terminx 673
            return;
674
    }
1399 terminx 675
 
676
#ifdef POLYMER
6829 terminx 677
    if (actor[spriteNum].lightptr != NULL && videoGetRenderMode() == REND_POLYMER)
5825 terminx 678
        A_DeleteLight(spriteNum);
1399 terminx 679
#endif
680
 
4745 terminx 681
    // AMBIENT_SFX_PLAYING
5825 terminx 682
    if (sprite[spriteNum].picnum == MUSICANDSFX && actor[spriteNum].t_data[0] == 1)
683
        S_StopEnvSound(sprite[spriteNum].lotag, spriteNum);
3822 helixhorne 684
 
7242 seventyfiv 685
#ifdef NETCODE_DISABLE
5825 terminx 686
    deletesprite(spriteNum);
7242 seventyfiv 687
#else
688
    Net_DeleteSprite(spriteNum);
689
#endif
587 terminx 690
}
691
 
5835 terminx 692
void A_AddToDeleteQueue(int spriteNum)
5 Plagman 693
{
7242 seventyfiv 694
    if (g_netClient || (g_deleteQueueSize == 0)) // [75] Clients should not use SpriteDeletionQueue[] and just set the sprites invisible immediately in A_DeleteSprite
5 Plagman 695
    {
5825 terminx 696
        A_DeleteSprite(spriteNum);
612 terminx 697
        return;
5 Plagman 698
    }
699
 
7604 terminx 700
    auto &deleteSpriteNum = SpriteDeletionQueue[g_spriteDeleteQueuePos];
7275 terminx 701
 
7604 terminx 702
    if (deleteSpriteNum >= 0 && actor[deleteSpriteNum].flags & SFLAG_QUEUEDFORDELETE)
703
        A_DeleteSprite(deleteSpriteNum);
704
 
705
    deleteSpriteNum = spriteNum;
706
    actor[spriteNum].flags |= SFLAG_QUEUEDFORDELETE;
5825 terminx 707
    g_spriteDeleteQueuePos = (g_spriteDeleteQueuePos+1)%g_deleteQueueSize;
5 Plagman 708
}
709
 
5835 terminx 710
void A_SpawnMultiple(int spriteNum, int tileNum, int spawnCnt)
5 Plagman 711
{
7776 terminx 712
    auto const pSprite = &sprite[spriteNum];
522 terminx 713
 
5825 terminx 714
    for (; spawnCnt>0; spawnCnt--)
5 Plagman 715
    {
5825 terminx 716
        int const j = A_InsertSprite(pSprite->sectnum, pSprite->x, pSprite->y, pSprite->z - (krand() % (47 << 8)), tileNum, -32, 8,
717
                               8, krand() & 2047, 0, 0, spriteNum, 5);
1143 terminx 718
        A_Spawn(-1, j);
719
        sprite[j].cstat = krand()&12;
5 Plagman 720
    }
721
}
722
 
6911 terminx 723
#ifndef EDUKE32_STANDALONE
5835 terminx 724
void A_DoGuts(int spriteNum, int tileNum, int spawnCnt)
5 Plagman 725
{
7603 terminx 726
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
727
    vec2_t     repeat  = { 32, 32 };
5 Plagman 728
 
5825 terminx 729
    if (A_CheckEnemySprite(pSprite) && pSprite->xrepeat < 16)
730
        repeat.x = repeat.y = 8;
3679 helixhorne 731
 
5825 terminx 732
    int gutZ   = pSprite->z - ZOFFSET3;
733
    int floorz = getflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y);
5 Plagman 734
 
5825 terminx 735
    if (gutZ > (floorz-ZOFFSET3))
736
        gutZ = floorz-ZOFFSET3;
5 Plagman 737
 
5825 terminx 738
    if (pSprite->picnum == COMMANDER)
739
        gutZ -= (24<<8);
5 Plagman 740
 
5829 terminx 741
    for (bssize_t j=spawnCnt; j>0; j--)
5825 terminx 742
    {
743
        int const i = A_InsertSprite(pSprite->sectnum, pSprite->x + (krand() & 255) - 128,
744
                                     pSprite->y + (krand() & 255) - 128, gutZ - (krand() & 8191), tileNum, -32, repeat.x,
745
                                     repeat.y, krand() & 2047, 48 + (krand() & 31), -512 - (krand() & 2047), spriteNum, 5);
5 Plagman 746
 
5825 terminx 747
        if (PN(i) == JIBS2)
5 Plagman 748
        {
749
            sprite[i].xrepeat >>= 2;
750
            sprite[i].yrepeat >>= 2;
751
        }
3679 helixhorne 752
 
5825 terminx 753
        sprite[i].pal = pSprite->pal;
5 Plagman 754
    }
755
}
756
 
5835 terminx 757
void A_DoGutsDir(int spriteNum, int tileNum, int spawnCnt)
5 Plagman 758
{
7603 terminx 759
    auto const s      = (uspriteptr_t)&sprite[spriteNum];
760
    vec2_t     repeat = { 32, 32 };
522 terminx 761
 
1143 terminx 762
    if (A_CheckEnemySprite(s) && s->xrepeat < 16)
5825 terminx 763
        repeat.x = repeat.y = 8;
5 Plagman 764
 
5825 terminx 765
    int gutZ = s->z-ZOFFSET3;
766
    int floorZ = getflorzofslope(s->sectnum,s->x,s->y);
5 Plagman 767
 
5825 terminx 768
    if (gutZ > (floorZ-ZOFFSET3))
769
        gutZ = floorZ-ZOFFSET3;
5 Plagman 770
 
331 terminx 771
    if (s->picnum == COMMANDER)
5825 terminx 772
        gutZ -= (24<<8);
5 Plagman 773
 
5829 terminx 774
    for (bssize_t j=spawnCnt; j>0; j--)
5 Plagman 775
    {
5825 terminx 776
        int const i = A_InsertSprite(s->sectnum, s->x, s->y, gutZ, tileNum, -32, repeat.x, repeat.y, krand() & 2047,
777
                                     256 + (krand() & 127), -512 - (krand() & 2047), spriteNum, 5);
935 terminx 778
        sprite[i].pal = s->pal;
5 Plagman 779
    }
780
}
6911 terminx 781
#endif
5 Plagman 782
 
5825 terminx 783
LUNATIC_EXTERN int32_t G_ToggleWallInterpolation(int32_t wallNum, int32_t setInterpolation)
5 Plagman 784
{
5825 terminx 785
    if (setInterpolation)
5 Plagman 786
    {
5825 terminx 787
        return G_SetInterpolation(&wall[wallNum].x) || G_SetInterpolation(&wall[wallNum].y);
5 Plagman 788
    }
3486 helixhorne 789
    else
790
    {
5825 terminx 791
        G_StopInterpolation(&wall[wallNum].x);
792
        G_StopInterpolation(&wall[wallNum].y);
3486 helixhorne 793
        return 0;
794
    }
5 Plagman 795
}
796
 
5825 terminx 797
void Sect_ToggleInterpolation(int sectNum, int setInterpolation)
5 Plagman 798
{
5829 terminx 799
    for (bssize_t j = sector[sectNum].wallptr, endwall = sector[sectNum].wallptr + sector[sectNum].wallnum; j < endwall; j++)
5 Plagman 800
    {
5825 terminx 801
        G_ToggleWallInterpolation(j, setInterpolation);
3486 helixhorne 802
 
5825 terminx 803
        int const nextWall = wall[j].nextwall;
804
 
805
        if (nextWall >= 0)
5 Plagman 806
        {
5825 terminx 807
            G_ToggleWallInterpolation(nextWall, setInterpolation);
808
            G_ToggleWallInterpolation(wall[nextWall].point2, setInterpolation);
5 Plagman 809
        }
810
    }
811
}
812
 
5825 terminx 813
static int32_t move_rotfixed_sprite(int32_t spriteNum, int32_t pivotSpriteNum, int32_t pivotAngle)
1913 helixhorne 814
{
5825 terminx 815
    if ((ROTFIXSPR_STATNUMP(sprite[spriteNum].statnum) ||
816
         ((sprite[spriteNum].statnum == STAT_ACTOR || sprite[spriteNum].statnum == STAT_ZOMBIEACTOR) &&
817
          A_CheckSpriteFlags(spriteNum, SFLAG_ROTFIXED))) &&
818
        actor[spriteNum].t_data[7] == (ROTFIXSPR_MAGIC | pivotSpriteNum))
1913 helixhorne 819
    {
7905 terminx 820
        rotatepoint(zerovec, *(vec2_t *)&actor[spriteNum].t_data[8], pivotAngle & 2047, &sprite[spriteNum].pos.vec2);
5825 terminx 821
        sprite[spriteNum].x += sprite[pivotSpriteNum].x;
822
        sprite[spriteNum].y += sprite[pivotSpriteNum].y;
1913 helixhorne 823
        return 0;
824
    }
825
 
826
    return 1;
827
}
828
 
5825 terminx 829
void A_MoveSector(int spriteNum)
5 Plagman 830
{
4745 terminx 831
    // T1,T2 and T3 are used for all the sector moving stuff!!!
5578 terminx 832
 
7776 terminx 833
    int32_t    playerDist;
834
    auto const pSprite     = &sprite[spriteNum];
835
    int const  playerNum   = A_FindPlayer(pSprite, &playerDist);
836
    int const  rotateAngle = VM_OnEvent(EVENT_MOVESECTOR, spriteNum, playerNum, playerDist, T3(spriteNum));
837
    int        originIdx   = T2(spriteNum);
5 Plagman 838
 
5825 terminx 839
    pSprite->x += (pSprite->xvel * (sintable[(pSprite->ang + 512) & 2047])) >> 14;
840
    pSprite->y += (pSprite->xvel * (sintable[pSprite->ang & 2047])) >> 14;
5 Plagman 841
 
5825 terminx 842
    int const endWall = sector[pSprite->sectnum].wallptr + sector[pSprite->sectnum].wallnum;
5 Plagman 843
 
5829 terminx 844
    for (bssize_t wallNum = sector[pSprite->sectnum].wallptr; wallNum < endWall; wallNum++)
5 Plagman 845
    {
5825 terminx 846
        vec2_t const origin = g_origins[originIdx];
847
        vec2_t result;
848
        rotatepoint(zerovec, origin, rotateAngle & 2047, &result);
849
        dragpoint(wallNum, pSprite->x + result.x, pSprite->y + result.y, 0);
511 terminx 850
 
5825 terminx 851
        originIdx++;
5 Plagman 852
    }
853
}
854
 
3680 helixhorne 855
#if !defined LUNATIC
3920 helixhorne 856
// NOTE: T5 is AC_ACTION_ID
5833 terminx 857
# define LIGHTRAD_PICOFS(i) (T5(i) ? *(apScript + T5(i)) + (*(apScript + T5(i) + 2)) * AC_CURFRAME(actor[i].t_data) : 0)
2669 helixhorne 858
#else
2864 helixhorne 859
// startframe + viewtype*[cyclic counter]
5833 terminx 860
# define LIGHTRAD_PICOFS(i) (actor[i].ac.startframe + actor[i].ac.viewtype * AC_CURFRAME(actor[i].t_data))
2669 helixhorne 861
#endif
2185 helixhorne 862
 
1409 terminx 863
// this is the same crap as in game.c's tspr manipulation.  puke.
3920 helixhorne 864
// XXX: may access tilesizy out-of-bounds by bad user code.
5833 terminx 865
#define LIGHTRAD(spriteNum, s) (s->yrepeat * tilesiz[s->picnum + LIGHTRAD_PICOFS(spriteNum)].y)
866
#define LIGHTRAD2(spriteNum, s) ((s->yrepeat + ((rand() % s->yrepeat)>>2)) * tilesiz[s->picnum + LIGHTRAD_PICOFS(spriteNum)].y)
1409 terminx 867
 
5835 terminx 868
void G_AddGameLight(int lightRadius, int spriteNum, int zOffset, int lightRange, int lightColor, int lightPrio)
1402 terminx 869
{
870
#ifdef POLYMER
7776 terminx 871
    auto const s = &sprite[spriteNum];
1423 terminx 872
 
6829 terminx 873
    if (videoGetRenderMode() != REND_POLYMER || pr_lighting != 1)
1414 plagman 874
        return;
875
 
5835 terminx 876
    if (actor[spriteNum].lightptr == NULL)
1402 terminx 877
    {
4745 terminx 878
#pragma pack(push, 1)
1402 terminx 879
        _prlight mylight;
1457 terminx 880
#pragma pack(pop)
1941 helixhorne 881
        Bmemset(&mylight, 0, sizeof(mylight));
1402 terminx 882
 
883
        mylight.sector = s->sectnum;
884
        mylight.x = s->x;
885
        mylight.y = s->y;
5835 terminx 886
        mylight.z = s->z - zOffset;
887
        mylight.color[0] = lightColor & 255;
888
        mylight.color[1] = (lightColor >> 8) & 255;
889
        mylight.color[2] = (lightColor >> 16) & 255;
890
        mylight.radius = lightRadius;
891
        actor[spriteNum].lightmaxrange = mylight.range = lightRange;
1402 terminx 892
 
5835 terminx 893
        mylight.priority = lightPrio;
1524 plagman 894
        mylight.tilenum = 0;
1402 terminx 895
 
3092 Plagman 896
        mylight.publicflags.emitshadow = 1;
897
        mylight.publicflags.negative = 0;
898
 
5835 terminx 899
        actor[spriteNum].lightId = polymer_addlight(&mylight);
900
        if (actor[spriteNum].lightId >= 0)
901
            actor[spriteNum].lightptr = &prlights[actor[spriteNum].lightId];
1402 terminx 902
        return;
903
    }
904
 
5835 terminx 905
    s->z -= zOffset;
1425 terminx 906
 
5835 terminx 907
    if (lightRange<actor[spriteNum].lightmaxrange>> 1)
908
        actor[spriteNum].lightmaxrange = 0;
1430 terminx 909
 
5835 terminx 910
    if (lightRange > actor[spriteNum].lightmaxrange || lightPrio != actor[spriteNum].lightptr->priority ||
911
        Bmemcmp(&sprite[spriteNum], actor[spriteNum].lightptr, sizeof(int32_t) * 3))
1402 terminx 912
    {
5835 terminx 913
        if (lightRange > actor[spriteNum].lightmaxrange)
914
            actor[spriteNum].lightmaxrange = lightRange;
1410 terminx 915
 
5835 terminx 916
        Bmemcpy(actor[spriteNum].lightptr, &sprite[spriteNum], sizeof(int32_t) * 3);
917
        actor[spriteNum].lightptr->sector = s->sectnum;
918
        actor[spriteNum].lightptr->flags.invalidate = 1;
1402 terminx 919
    }
1409 terminx 920
 
5835 terminx 921
    actor[spriteNum].lightptr->priority = lightPrio;
922
    actor[spriteNum].lightptr->range = lightRange;
923
    actor[spriteNum].lightptr->color[0] = lightColor & 255;
924
    actor[spriteNum].lightptr->color[1] = (lightColor >> 8) & 255;
925
    actor[spriteNum].lightptr->color[2] = (lightColor >> 16) & 255;
1409 terminx 926
 
5835 terminx 927
    s->z += zOffset;
1402 terminx 928
 
929
#else
5835 terminx 930
    UNREFERENCED_PARAMETER(lightRadius);
931
    UNREFERENCED_PARAMETER(spriteNum);
932
    UNREFERENCED_PARAMETER(zOffset);
933
    UNREFERENCED_PARAMETER(lightRange);
934
    UNREFERENCED_PARAMETER(lightColor);
935
    UNREFERENCED_PARAMETER(lightPrio);
1402 terminx 936
#endif
937
}
938
 
6244 terminx 939
ACTOR_STATIC void A_MaybeAwakenBadGuys(int const spriteNum)
5826 terminx 940
{
941
    if (sprite[spriteNum].sectnum == MAXSECTORS)
942
        return;
943
 
944
    if (A_CheckSpriteFlags(spriteNum, SFLAG_WAKEUPBADGUYS))
945
    {
7603 terminx 946
        auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
5826 terminx 947
 
5829 terminx 948
        for (bssize_t nextSprite, SPRITES_OF_STAT_SAFE(STAT_ZOMBIEACTOR, spriteNum, nextSprite))
5826 terminx 949
        {
950
            if (A_CheckEnemySprite(&sprite[spriteNum]))
951
            {
952
                if (sprite[spriteNum].sectnum == pSprite->sectnum
953
                    || sprite[spriteNum].sectnum == nextsectorneighborz(pSprite->sectnum, sector[pSprite->sectnum].floorz, 1, 1)
954
                    || cansee(pSprite->x, pSprite->y, pSprite->z - PHEIGHT, pSprite->sectnum, sprite[spriteNum].x, sprite[spriteNum].y,
955
                              sprite[spriteNum].z - PHEIGHT, sprite[spriteNum].sectnum))
956
                {
6908 terminx 957
                    actor[spriteNum].timetosleep = SLEEPTIME;
5826 terminx 958
                    A_PlayAlertSound(spriteNum);
959
                    changespritestat(spriteNum, STAT_ACTOR);
960
 
961
                    if (A_CheckSpriteFlags(spriteNum, SFLAG_WAKEUPBADGUYS))
962
                        A_MaybeAwakenBadGuys(spriteNum);
963
                }
964
            }
965
        }
966
    }
967
}
968
 
969
 
1143 terminx 970
// sleeping monsters, etc
1595 helixhorne 971
ACTOR_STATIC void G_MoveZombieActors(void)
5 Plagman 972
{
6244 terminx 973
    int spriteNum = headspritestat[STAT_ZOMBIEACTOR], canSeePlayer;
5 Plagman 974
 
5825 terminx 975
    while (spriteNum >= 0)
5 Plagman 976
    {
7776 terminx 977
        int const  nextSprite = nextspritestat[spriteNum];
978
        int32_t    playerDist;
979
        auto const pSprite   = &sprite[spriteNum];
980
        int const  playerNum = A_FindPlayer(pSprite, &playerDist);
981
        auto const pPlayer   = g_player[playerNum].ps;
5 Plagman 982
 
5932 terminx 983
        if (sprite[pPlayer->i].extra > 0)
5 Plagman 984
        {
5825 terminx 985
            if (playerDist < 30000)
5 Plagman 986
            {
5825 terminx 987
                actor[spriteNum].timetosleep++;
988
                if (actor[spriteNum].timetosleep >= (playerDist>>8))
5 Plagman 989
                {
5932 terminx 990
                    if (pPlayer->newowner == -1 && A_CheckEnemySprite(pSprite))
5 Plagman 991
                    {
5932 terminx 992
                        vec3_t const p = { pPlayer->pos.x + 64 - (krand() & 127),
993
                                           pPlayer->pos.y + 64 - (krand() & 127),
994
                                           pPlayer->pos.z - (krand() % ZOFFSET5) };
5826 terminx 995
 
5932 terminx 996
                        int16_t pSectnum = pPlayer->cursectnum;
3679 helixhorne 997
 
5825 terminx 998
                        updatesector(p.x, p.y, &pSectnum);
999
 
1000
                        if (pSectnum == -1)
5 Plagman 1001
                        {
5825 terminx 1002
                            spriteNum = nextSprite;
5 Plagman 1003
                            continue;
1004
                        }
3679 helixhorne 1005
 
5826 terminx 1006
                        vec3_t const s = { pSprite->x + 64 - (krand() & 127),
1007
                                           pSprite->y + 64 - (krand() & 127),
1008
                                           pSprite->z - (krand() % (52 << 8)) };
1009
 
5825 terminx 1010
                        int16_t sectNum = pSprite->sectnum;
1011
 
5826 terminx 1012
                        updatesector(s.x, s.y, &sectNum);
5825 terminx 1013
 
1014
                        if (sectNum == -1)
5 Plagman 1015
                        {
5825 terminx 1016
                            spriteNum = nextSprite;
5 Plagman 1017
                            continue;
1018
                        }
3679 helixhorne 1019
 
6244 terminx 1020
                        canSeePlayer = cansee(s.x, s.y, s.z, sectNum, p.x, p.y, p.z, pSectnum);
5 Plagman 1021
                    }
1022
                    else
6244 terminx 1023
                        canSeePlayer = cansee(pSprite->x, pSprite->y, pSprite->z - ((krand() & 31) << 8), pSprite->sectnum, pPlayer->opos.x,
5932 terminx 1024
                            pPlayer->opos.y, pPlayer->opos.z - ((krand() & 31) << 8), pPlayer->cursectnum);
5 Plagman 1025
 
6244 terminx 1026
                    if (canSeePlayer)
2652 terminx 1027
                    {
5825 terminx 1028
                        switch (DYNAMICTILEMAP(pSprite->picnum))
5 Plagman 1029
                        {
6798 terminx 1030
#ifndef EDUKE32_STANDALONE
5833 terminx 1031
                            case RUBBERCAN__STATIC:
1032
                            case EXPLODINGBARREL__STATIC:
1033
                            case WOODENHORSE__STATIC:
1034
                            case HORSEONSIDE__STATIC:
1035
                            case CANWITHSOMETHING__STATIC:
1036
                            case CANWITHSOMETHING2__STATIC:
1037
                            case CANWITHSOMETHING3__STATIC:
1038
                            case CANWITHSOMETHING4__STATIC:
1039
                            case FIREBARREL__STATIC:
1040
                            case FIREVASE__STATIC:
1041
                            case NUKEBARREL__STATIC:
1042
                            case NUKEBARRELDENTED__STATIC:
1043
                            case NUKEBARRELLEAKED__STATIC:
1044
                            case TRIPBOMB__STATIC:
8559 terminx 1045
                                if (!FURY)
1046
                                {
1047
                                    pSprite->shade = ((sector[pSprite->sectnum].ceilingstat & 1) && A_CheckSpriteFlags(spriteNum, SFLAG_NOSHADE) == 0)
1048
                                                     ? sector[pSprite->sectnum].ceilingshade
1049
                                                     : sector[pSprite->sectnum].floorshade;
1050
                                    actor[spriteNum].timetosleep = 0;
1051
                                    changespritestat(spriteNum, STAT_STANDABLE);
1052
                                }
5833 terminx 1053
                                break;
5 Plagman 1054
 
5833 terminx 1055
                            case RECON__STATIC:
8559 terminx 1056
                                if (!FURY)
1057
                                    CS(spriteNum) |= 257;
6798 terminx 1058
                                fallthrough__;
1059
#endif
5833 terminx 1060
                            default:
1061
                                if (A_CheckSpriteFlags(spriteNum, SFLAG_USEACTIVATOR) && sector[sprite[spriteNum].sectnum].lotag & 16384)
1062
                                    break;
5826 terminx 1063
 
5833 terminx 1064
                                actor[spriteNum].timetosleep = 0;
1065
                                A_PlayAlertSound(spriteNum);
1066
                                changespritestat(spriteNum, STAT_ACTOR);
5826 terminx 1067
 
5833 terminx 1068
                                if (A_CheckSpriteFlags(spriteNum, SFLAG_WAKEUPBADGUYS))
1069
                                    A_MaybeAwakenBadGuys(spriteNum);
5826 terminx 1070
 
5833 terminx 1071
                                break;
5 Plagman 1072
                        }
2652 terminx 1073
                    }
5833 terminx 1074
                    else
1075
                        actor[spriteNum].timetosleep = 0;
5 Plagman 1076
                }
1077
            }
3679 helixhorne 1078
 
5825 terminx 1079
            if (A_CheckEnemySprite(pSprite) && A_CheckSpriteFlags(spriteNum,SFLAG_NOSHADE) == 0)
5 Plagman 1080
            {
5826 terminx 1081
                pSprite->shade = (sector[pSprite->sectnum].ceilingstat & 1)
1082
                                ? sector[pSprite->sectnum].ceilingshade
1083
                                : sector[pSprite->sectnum].floorshade;
5 Plagman 1084
            }
1085
        }
3679 helixhorne 1086
 
5825 terminx 1087
        spriteNum = nextSprite;
5 Plagman 1088
    }
1089
}
1090
 
2993 terminx 1091
// stupid name, but it's what the function does.
6244 terminx 1092
static FORCE_INLINE int G_FindExplosionInSector(int const sectNum)
5 Plagman 1093
{
5829 terminx 1094
    for (bssize_t SPRITES_OF(STAT_MISC, i))
6244 terminx 1095
        if (PN(i) == EXPLOSION2 && sectNum == SECT(i))
5 Plagman 1096
            return i;
3679 helixhorne 1097
 
5 Plagman 1098
    return -1;
1099
}
1100
 
6076 hendricks2 1101
static FORCE_INLINE void P_Nudge(int playerNum, int spriteNum, int shiftLeft)
2874 helixhorne 1102
{
5825 terminx 1103
    g_player[playerNum].ps->vel.x += actor[spriteNum].extra * (sintable[(actor[spriteNum].ang + 512) & 2047]) << shiftLeft;
1104
    g_player[playerNum].ps->vel.y += actor[spriteNum].extra * (sintable[actor[spriteNum].ang & 2047]) << shiftLeft;
2874 helixhorne 1105
}
1106
 
6244 terminx 1107
int A_IncurDamage(int const spriteNum)
5 Plagman 1108
{
7776 terminx 1109
    auto const pSprite = &sprite[spriteNum];
1110
    auto const pActor  = &actor[spriteNum];
5 Plagman 1111
 
3626 helixhorne 1112
    // dmg->picnum check: safety, since it might have been set to <0 from CON.
5825 terminx 1113
    if (pActor->extra < 0 || pSprite->extra < 0 || pActor->picnum < 0)
5 Plagman 1114
    {
5825 terminx 1115
        pActor->extra = -1;
3053 terminx 1116
        return -1;
1117
    }
5 Plagman 1118
 
5825 terminx 1119
    if (pSprite->picnum == APLAYER)
3053 terminx 1120
    {
5825 terminx 1121
        if (ud.god && pActor->picnum != SHRINKSPARK)
4745 terminx 1122
            return -1;
5 Plagman 1123
 
5833 terminx 1124
        int const playerNum = P_GetP(pSprite);
5825 terminx 1125
 
6578 hendricks2 1126
        if (pActor->owner >= 0 && (sprite[pActor->owner].picnum == APLAYER))
1127
        {
1128
            if (
1129
                (ud.ffire == 0) &&
1130
                (spriteNum != pActor->owner) &&       // Not damaging self.
1131
                ((g_gametypeFlags[ud.coop] & GAMETYPE_PLAYERSFRIENDLY) ||
1132
                ((g_gametypeFlags[ud.coop] & GAMETYPE_TDM) && g_player[playerNum].ps->team == g_player[P_Get(pActor->owner)].ps->team))
1133
                )
1134
                {
1135
                    // Nullify damage and cancel.
1136
                    pActor->owner = -1;
1137
                    pActor->extra = -1;
1138
                    return -1;
1139
                }
1140
        }
5 Plagman 1141
 
5825 terminx 1142
        pSprite->extra -= pActor->extra;
268 terminx 1143
 
5825 terminx 1144
        if (pActor->owner >= 0 && pSprite->extra <= 0 && pActor->picnum != FREEZEBLAST)
3053 terminx 1145
        {
5833 terminx 1146
            int const damageOwner = pActor->owner;
1147
            pSprite->extra        = 0;
4226 helixhorne 1148
 
5825 terminx 1149
            g_player[playerNum].ps->wackedbyactor = damageOwner;
5 Plagman 1150
 
5825 terminx 1151
            if (sprite[damageOwner].picnum == APLAYER && playerNum != P_Get(damageOwner))
1152
                g_player[playerNum].ps->frag_ps = P_Get(damageOwner);
5 Plagman 1153
 
5825 terminx 1154
            pActor->owner = g_player[playerNum].ps->i;
3053 terminx 1155
        }
5 Plagman 1156
 
5825 terminx 1157
        switch (DYNAMICTILEMAP(pActor->picnum))
3053 terminx 1158
        {
4745 terminx 1159
            case RADIUSEXPLOSION__STATIC:
6798 terminx 1160
            case SEENINE__STATIC:
1161
#ifndef EDUKE32_STANDALONE
4745 terminx 1162
            case RPG__STATIC:
1163
            case HYDRENT__STATIC:
1164
            case HEAVYHBOMB__STATIC:
1165
            case OOZFILTER__STATIC:
1166
            case EXPLODINGBARREL__STATIC:
6798 terminx 1167
#endif
5825 terminx 1168
                P_Nudge(playerNum, spriteNum, 2);
4745 terminx 1169
                break;
3679 helixhorne 1170
 
4745 terminx 1171
            default:
5825 terminx 1172
                P_Nudge(playerNum, spriteNum, (A_CheckSpriteFlags(pActor->owner, SFLAG_PROJECTILE) &&
1173
                                       (SpriteProjectile[pActor->owner].workslike & PROJECTILE_RPG))
1174
                                      ? 2
1175
                                      : 1);
4745 terminx 1176
                break;
3053 terminx 1177
        }
5 Plagman 1178
 
5825 terminx 1179
        pActor->extra = -1;
1180
        return pActor->picnum;
3053 terminx 1181
    }
5 Plagman 1182
 
5825 terminx 1183
    if (pActor->extra == 0 && pActor->picnum == SHRINKSPARK && pSprite->xrepeat < 24)
4745 terminx 1184
        return -1;
5 Plagman 1185
 
5825 terminx 1186
    pSprite->extra -= pActor->extra;
5 Plagman 1187
 
5825 terminx 1188
    if (pSprite->picnum != RECON && pSprite->owner >= 0 && sprite[pSprite->owner].statnum < MAXSTATUS)
1189
        pSprite->owner = pActor->owner;
5 Plagman 1190
 
5825 terminx 1191
    pActor->extra = -1;
4745 terminx 1192
 
5825 terminx 1193
    return pActor->picnum;
5 Plagman 1194
}
1195
 
1143 terminx 1196
void A_MoveCyclers(void)
5 Plagman 1197
{
5835 terminx 1198
    for (bssize_t i=g_cyclerCnt-1; i>=0; i--)
5 Plagman 1199
    {
5835 terminx 1200
        int16_t *const pCycler     = g_cyclers[i];
5833 terminx 1201
        int const      sectNum     = pCycler[0];
1202
        int            spriteShade = pCycler[2];
1203
        int const      floorShade  = pCycler[3];
1204
        int            sectorShade = clamp(floorShade + (sintable[pCycler[1] & 2047] >> 10), spriteShade, floorShade);
5 Plagman 1205
 
5825 terminx 1206
        pCycler[1] += sector[sectNum].extra;
3053 terminx 1207
 
5833 terminx 1208
        if (pCycler[5]) // angle 1536...
5 Plagman 1209
        {
5825 terminx 1210
            walltype *pWall = &wall[sector[sectNum].wallptr];
3053 terminx 1211
 
5829 terminx 1212
            for (bssize_t wallsLeft = sector[sectNum].wallnum; wallsLeft > 0; wallsLeft--, pWall++)
3053 terminx 1213
            {
5825 terminx 1214
                if (pWall->hitag != 1)
5 Plagman 1215
                {
5833 terminx 1216
                    pWall->shade = sectorShade;
5 Plagman 1217
 
5825 terminx 1218
                    if ((pWall->cstat&2) && pWall->nextwall >= 0)
5833 terminx 1219
                        wall[pWall->nextwall].shade = sectorShade;
3053 terminx 1220
                }
1221
            }
5 Plagman 1222
 
5833 terminx 1223
            sector[sectNum].floorshade = sector[sectNum].ceilingshade = sectorShade;
5 Plagman 1224
        }
1225
    }
1226
}
1227
 
1143 terminx 1228
void A_MoveDummyPlayers(void)
5 Plagman 1229
{
6244 terminx 1230
    int spriteNum = headspritestat[STAT_DUMMYPLAYER];
5 Plagman 1231
 
5825 terminx 1232
    while (spriteNum >= 0)
5 Plagman 1233
    {
7776 terminx 1234
        int const  playerNum     = P_Get(OW(spriteNum));
1235
        auto const pPlayer       = g_player[playerNum].ps;
1236
        int const  nextSprite    = nextspritestat[spriteNum];
1237
        int const  playerSectnum = pPlayer->cursectnum;
2342 helixhorne 1238
 
5825 terminx 1239
        if (pPlayer->on_crane >= 0 || (playerSectnum >= 0 && sector[playerSectnum].lotag != ST_1_ABOVE_WATER) || sprite[pPlayer->i].extra <= 0)
5 Plagman 1240
        {
5825 terminx 1241
            pPlayer->dummyplayersprite = -1;
5830 terminx 1242
            DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 1243
        }
1244
        else
1245
        {
5825 terminx 1246
            if (pPlayer->on_ground && pPlayer->on_warping_sector == 1 && playerSectnum >= 0 && sector[playerSectnum].lotag == ST_1_ABOVE_WATER)
5 Plagman 1247
            {
5825 terminx 1248
                CS(spriteNum) = 257;
1249
                SZ(spriteNum) = sector[SECT(spriteNum)].ceilingz+(27<<8);
6725 terminx 1250
                SA(spriteNum) = fix16_to_int(pPlayer->q16ang);
5825 terminx 1251
                if (T1(spriteNum) == 8)
1252
                    T1(spriteNum) = 0;
1253
                else T1(spriteNum)++;
5 Plagman 1254
            }
1255
            else
1256
            {
5825 terminx 1257
                if (sector[SECT(spriteNum)].lotag != ST_2_UNDERWATER) SZ(spriteNum) = sector[SECT(spriteNum)].floorz;
1258
                CS(spriteNum) = 32768;
5 Plagman 1259
            }
1260
        }
1261
 
5825 terminx 1262
        SX(spriteNum) += (pPlayer->pos.x-pPlayer->opos.x);
1263
        SY(spriteNum) += (pPlayer->pos.y-pPlayer->opos.y);
7973 terminx 1264
        setsprite(spriteNum, &sprite[spriteNum].pos);
5 Plagman 1265
 
5825 terminx 1266
next_sprite:
1267
        spriteNum = nextSprite;
5 Plagman 1268
    }
1269
}
1270
 
3072 helixhorne 1271
 
7243 terminx 1272
static int P_Submerge(int, DukePlayer_t *, int, int);
1273
static int P_Emerge(int, DukePlayer_t *, int, int);
5979 hendricks2 1274
static void P_FinishWaterChange(int, DukePlayer_t *, int, int, int);
3072 helixhorne 1275
 
8605 terminx 1276
static fix16_t P_GetQ16AngleDeltaForTic(DukePlayer_t const *pPlayer)
1277
{
1278
    auto oldAngle = pPlayer->oq16ang;
1279
    auto newAngle = pPlayer->q16ang;
1280
 
1281
    if (klabs(fix16_sub(oldAngle, newAngle)) < F16(1024))
1282
        return fix16_sub(newAngle, oldAngle);
1283
 
1284
    if (newAngle > F16(1024))
1285
        newAngle = fix16_sub(newAngle, F16(2048));
1286
 
1287
    if (oldAngle > F16(1024))
1288
        oldAngle = fix16_sub(oldAngle, F16(2048));
1289
 
1290
    return fix16_sub(newAngle, oldAngle);
1291
}
1292
 
1595 helixhorne 1293
ACTOR_STATIC void G_MovePlayers(void)
5 Plagman 1294
{
6244 terminx 1295
    int spriteNum = headspritestat[STAT_PLAYER];
5 Plagman 1296
 
5825 terminx 1297
    while (spriteNum >= 0)
5 Plagman 1298
    {
7776 terminx 1299
        int const  nextSprite = nextspritestat[spriteNum];
1300
        auto const pSprite    = &sprite[spriteNum];
1301
        auto const pPlayer    = g_player[P_GetP(pSprite)].ps;
5 Plagman 1302
 
5825 terminx 1303
        if (pSprite->owner >= 0)
5 Plagman 1304
        {
5825 terminx 1305
            if (pPlayer->newowner >= 0)  //Looking thru the camera
5 Plagman 1306
            {
5825 terminx 1307
                pSprite->x              = pPlayer->opos.x;
1308
                pSprite->y              = pPlayer->opos.y;
1309
                pSprite->z              = pPlayer->opos.z + PHEIGHT;
1310
                actor[spriteNum].bpos.z = pSprite->z;
6927 terminx 1311
                pSprite->ang            = fix16_to_int(pPlayer->oq16ang);
5825 terminx 1312
 
7697 terminx 1313
                setsprite(spriteNum, &pSprite->pos);
5 Plagman 1314
            }
1315
            else
1316
            {
6244 terminx 1317
                int32_t otherPlayerDist;
3072 helixhorne 1318
#ifdef YAX_ENABLE
1319
                // TROR water submerge/emerge
5825 terminx 1320
                int const playerSectnum = pSprite->sectnum;
1321
                int const sectorLotag   = sector[playerSectnum].lotag;
1322
                int32_t   otherSector;
3072 helixhorne 1323
 
7603 terminx 1324
                if (A_CheckNoSE7Water((uspriteptr_t)pSprite, playerSectnum, sectorLotag, &otherSector))
3072 helixhorne 1325
                {
3678 helixhorne 1326
                    // NOTE: Compare with G_MoveTransports().
5825 terminx 1327
                    pPlayer->on_warping_sector = 1;
3677 helixhorne 1328
 
6604 hendricks2 1329
                    if ((sectorLotag == ST_1_ABOVE_WATER ?
7243 terminx 1330
                        P_Submerge(P_GetP(pSprite), pPlayer, playerSectnum, otherSector) :
1331
                        P_Emerge(P_GetP(pSprite), pPlayer, playerSectnum, otherSector)) == 1)
5825 terminx 1332
                        P_FinishWaterChange(spriteNum, pPlayer, sectorLotag, -1, otherSector);
3072 helixhorne 1333
                }
1334
#endif
2925 helixhorne 1335
                if (g_netServer || ud.multimode > 1)
6244 terminx 1336
                    otherp = P_FindOtherPlayer(P_GetP(pSprite), &otherPlayerDist);
5 Plagman 1337
                else
1338
                {
5825 terminx 1339
                    otherp = P_GetP(pSprite);
6244 terminx 1340
                    otherPlayerDist = 0;
5 Plagman 1341
                }
1342
 
5825 terminx 1343
                if (G_HaveActor(sprite[spriteNum].picnum))
6244 terminx 1344
                    A_Execute(spriteNum, P_GetP(pSprite), otherPlayerDist);
5 Plagman 1345
 
8605 terminx 1346
                pPlayer->q16angvel    = P_GetQ16AngleDeltaForTic(pPlayer);
1347
                pPlayer->oq16ang      = pPlayer->q16ang;
1348
                pPlayer->oq16horiz    = pPlayer->q16horiz;
1349
                pPlayer->oq16horizoff = pPlayer->q16horizoff;
1350
 
2925 helixhorne 1351
                if (g_netServer || ud.multimode > 1)
5825 terminx 1352
                {
564 terminx 1353
                    if (sprite[g_player[otherp].ps->i].extra > 0)
5 Plagman 1354
                    {
5825 terminx 1355
                        if (pSprite->yrepeat > 32 && sprite[g_player[otherp].ps->i].yrepeat < 32)
5 Plagman 1356
                        {
6244 terminx 1357
                            if (otherPlayerDist < 1400 && pPlayer->knee_incs == 0)
5 Plagman 1358
                            {
7242 seventyfiv 1359
                                // Don't stomp teammates.
1360
                                if (
1361
                                    ((g_gametypeFlags[ud.coop] & GAMETYPE_TDM) && pPlayer->team != g_player[otherp].ps->team) ||
1362
                                    (!(g_gametypeFlags[ud.coop] & GAMETYPE_PLAYERSFRIENDLY) && !(g_gametypeFlags[ud.coop] & GAMETYPE_TDM))
1363
                                    )
6579 hendricks2 1364
                                {
1365
                                    pPlayer->knee_incs = 1;
1366
                                    pPlayer->weapon_pos = -1;
1367
                                    pPlayer->actorsqu = g_player[otherp].ps->i;
1368
                                }
5 Plagman 1369
                            }
1370
                        }
1371
                    }
5825 terminx 1372
                }
3053 terminx 1373
 
331 terminx 1374
                if (ud.god)
5 Plagman 1375
                {
5825 terminx 1376
                    pSprite->extra = pPlayer->max_player_health;
1377
                    pSprite->cstat = 257;
5452 hendricks2 1378
                    if (!WW2GI)
5825 terminx 1379
                        pPlayer->inv_amount[GET_JETPACK] = 1599;
5 Plagman 1380
                }
1381
 
5825 terminx 1382
                if (pSprite->extra > 0)
5 Plagman 1383
                {
8030 terminx 1384
#ifndef EDUKE32_STANDALONE
1385
                    if (!FURY)
1386
                    {
1387
                        actor[spriteNum].owner = spriteNum;
5 Plagman 1388
 
8030 terminx 1389
                        if (ud.god == 0)
1390
                            if (G_CheckForSpaceCeiling(pSprite->sectnum) || G_CheckForSpaceFloor(pSprite->sectnum))
1391
                            {
1392
                                OSD_Printf(OSD_ERROR "%s: player killed by space sector!\n", EDUKE32_FUNCTION);
1393
                                P_QuickKill(pPlayer);
1394
                            }
1395
                    }
1396
#endif
5 Plagman 1397
                }
1398
                else
1399
                {
5825 terminx 1400
                    pPlayer->pos.x = pSprite->x;
1401
                    pPlayer->pos.y = pSprite->y;
1402
                    pPlayer->pos.z = pSprite->z-(20<<8);
5 Plagman 1403
 
5825 terminx 1404
                    pPlayer->newowner = -1;
5 Plagman 1405
 
5825 terminx 1406
                    if (pPlayer->wackedbyactor >= 0 && sprite[pPlayer->wackedbyactor].statnum < MAXSTATUS)
5 Plagman 1407
                    {
6725 terminx 1408
                        pPlayer->q16ang += fix16_to_int(G_GetAngleDelta(pPlayer->q16ang,
1409
                                                                      getangle(sprite[pPlayer->wackedbyactor].x - pPlayer->pos.x,
1410
                                                                               sprite[pPlayer->wackedbyactor].y - pPlayer->pos.y))
1411
                                                      >> 1);
1412
                        pPlayer->q16ang &= 0x7FFFFFF;
5 Plagman 1413
                    }
3053 terminx 1414
                }
5 Plagman 1415
 
6725 terminx 1416
                pSprite->ang = fix16_to_int(pPlayer->q16ang);
5 Plagman 1417
            }
1418
        }
1419
        else
1420
        {
5825 terminx 1421
            if (pPlayer->holoduke_on == -1)
5830 terminx 1422
                DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 1423
 
7905 terminx 1424
            actor[spriteNum].bpos = pSprite->pos;
5825 terminx 1425
            pSprite->cstat = 0;
5 Plagman 1426
 
5825 terminx 1427
            if (pSprite->xrepeat < 42)
5 Plagman 1428
            {
5825 terminx 1429
                pSprite->xrepeat += 4;
1430
                pSprite->cstat |= 2;
5 Plagman 1431
            }
5825 terminx 1432
            else pSprite->xrepeat = 42;
3053 terminx 1433
 
5825 terminx 1434
            if (pSprite->yrepeat < 36)
1435
                pSprite->yrepeat += 4;
5 Plagman 1436
            else
1437
            {
5825 terminx 1438
                pSprite->yrepeat = 36;
1439
                if (sector[pSprite->sectnum].lotag != ST_2_UNDERWATER)
1440
                    A_Fall(spriteNum);
1441
                if (pSprite->zvel == 0 && sector[pSprite->sectnum].lotag == ST_1_ABOVE_WATER)
5827 terminx 1442
                    pSprite->z += ZOFFSET5;
5 Plagman 1443
            }
1444
 
5825 terminx 1445
            if (pSprite->extra < 8)
5 Plagman 1446
            {
5825 terminx 1447
                pSprite->xvel = 128;
6725 terminx 1448
                pSprite->ang = fix16_to_int(pPlayer->q16ang);
5825 terminx 1449
                pSprite->extra++;
1450
                A_SetSprite(spriteNum,CLIPMASK0);
5 Plagman 1451
            }
1452
            else
1453
            {
6725 terminx 1454
                pSprite->ang = 2047-fix16_to_int(pPlayer->q16ang);
7697 terminx 1455
                setsprite(spriteNum,&pSprite->pos);
5 Plagman 1456
            }
1457
        }
1458
 
5825 terminx 1459
        pSprite->shade =
1460
        logapproach(pSprite->shade, (sector[pSprite->sectnum].ceilingstat & 1) ? sector[pSprite->sectnum].ceilingshade
1461
                                                                               : sector[pSprite->sectnum].floorshade);
5 Plagman 1462
 
5825 terminx 1463
next_sprite:
1464
        spriteNum = nextSprite;
5 Plagman 1465
    }
1466
}
1467
 
1595 helixhorne 1468
ACTOR_STATIC void G_MoveFX(void)
5 Plagman 1469
{
5825 terminx 1470
    int spriteNum = headspritestat[STAT_FX];
5 Plagman 1471
 
5825 terminx 1472
    while (spriteNum >= 0)
5 Plagman 1473
    {
7776 terminx 1474
        auto const pSprite    = &sprite[spriteNum];
1475
        int const  nextSprite = nextspritestat[spriteNum];
5 Plagman 1476
 
5825 terminx 1477
        switch (DYNAMICTILEMAP(pSprite->picnum))
5 Plagman 1478
        {
337 terminx 1479
        case RESPAWN__STATIC:
5825 terminx 1480
            if (pSprite->extra == 66)
337 terminx 1481
            {
5825 terminx 1482
                /*int32_t j =*/ A_Spawn(spriteNum,SHT(spriteNum));
337 terminx 1483
                //                    sprite[j].pal = sprite[i].pal;
5830 terminx 1484
                DELETE_SPRITE_AND_CONTINUE(spriteNum);
337 terminx 1485
            }
5825 terminx 1486
            else if (pSprite->extra > (66-13))
1487
                sprite[spriteNum].extra++;
337 terminx 1488
            break;
5 Plagman 1489
 
337 terminx 1490
        case MUSICANDSFX__STATIC:
2885 helixhorne 1491
        {
7776 terminx 1492
            int32_t const spriteHitag = (uint16_t)pSprite->hitag;
1493
            auto const    pPlayer     = g_player[screenpeek].ps;
5 Plagman 1494
 
5825 terminx 1495
            if (T2(spriteNum) != ud.config.SoundToggle)
337 terminx 1496
            {
3822 helixhorne 1497
                // If sound playback was toggled, restart.
5825 terminx 1498
                T2(spriteNum) = ud.config.SoundToggle;
1499
                T1(spriteNum) = 0;
337 terminx 1500
            }
1501
 
5825 terminx 1502
            if (pSprite->lotag >= 1000 && pSprite->lotag < 2000)
337 terminx 1503
            {
6647 hendricks2 1504
                int32_t playerDist = ldist(&sprite[pPlayer->i], pSprite);
2885 helixhorne 1505
 
4249 hendricks2 1506
#ifdef SPLITSCREEN_MOD_HACKS
2957 helixhorne 1507
                if (g_fakeMultiMode==2)
2885 helixhorne 1508
                {
1509
                    // HACK for splitscreen mod
5825 terminx 1510
                    int32_t otherdist = ldist(&sprite[g_player[1].ps->i],pSprite);
6244 terminx 1511
                    playerDist = min(playerDist, otherdist);
2885 helixhorne 1512
                }
4249 hendricks2 1513
#endif
2885 helixhorne 1514
 
6244 terminx 1515
                if (playerDist < spriteHitag && T1(spriteNum) == 0)
5 Plagman 1516
                {
5825 terminx 1517
                    FX_SetReverb(pSprite->lotag - 1000);
1518
                    T1(spriteNum) = 1;
5 Plagman 1519
                }
6244 terminx 1520
                else if (playerDist >= spriteHitag && T1(spriteNum) == 1)
5 Plagman 1521
                {
337 terminx 1522
                    FX_SetReverb(0);
1523
                    FX_SetReverbDelay(0);
5825 terminx 1524
                    T1(spriteNum) = 0;
5 Plagman 1525
                }
337 terminx 1526
            }
5825 terminx 1527
            else if (pSprite->lotag < 999 && (unsigned)sector[pSprite->sectnum].lotag < 9 &&  // ST_9_SLIDING_ST_DOOR
1528
                         ud.config.AmbienceToggle && sector[SECT(spriteNum)].floorz != sector[SECT(spriteNum)].ceilingz)
337 terminx 1529
            {
5825 terminx 1530
                if (g_sounds[pSprite->lotag].m & SF_MSFX)
5 Plagman 1531
                {
6244 terminx 1532
                    int playerDist = dist(&sprite[pPlayer->i], pSprite);
2885 helixhorne 1533
 
4249 hendricks2 1534
#ifdef SPLITSCREEN_MOD_HACKS
2957 helixhorne 1535
                    if (g_fakeMultiMode==2)
2885 helixhorne 1536
                    {
1537
                        // HACK for splitscreen mod
5825 terminx 1538
                        int32_t otherdist = dist(&sprite[g_player[1].ps->i],pSprite);
1539
                        playerDist = min(playerDist, otherdist);
2885 helixhorne 1540
                    }
4249 hendricks2 1541
#endif
2885 helixhorne 1542
 
5825 terminx 1543
                    if (playerDist < spriteHitag && T1(spriteNum) == 0 && FX_VoiceAvailable(g_sounds[pSprite->lotag].pr-1))
5 Plagman 1544
                    {
3822 helixhorne 1545
                        // Start playing an ambience sound.
1546
 
5825 terminx 1547
                        char om = g_sounds[pSprite->lotag].m;
1143 terminx 1548
                        if (g_numEnvSoundsPlaying == ud.config.NumVoices)
5 Plagman 1549
                        {
2887 helixhorne 1550
                            int32_t j;
1551
 
1552
                            for (SPRITES_OF(STAT_FX, j))
5825 terminx 1553
                                if (j != spriteNum && S_IsAmbientSFX(j) && actor[j].t_data[0] == 1 &&
1554
                                        dist(&sprite[j], &sprite[pPlayer->i]) > playerDist)
5 Plagman 1555
                                {
1143 terminx 1556
                                    S_StopEnvSound(sprite[j].lotag,j);
337 terminx 1557
                                    break;
5 Plagman 1558
                                }
2887 helixhorne 1559
 
1560
                            if (j == -1)
5825 terminx 1561
                                goto next_sprite;
5 Plagman 1562
                        }
2887 helixhorne 1563
 
5825 terminx 1564
                        g_sounds[pSprite->lotag].m |= SF_LOOP;
1565
                        A_PlaySound(pSprite->lotag,spriteNum);
1566
                        g_sounds[pSprite->lotag].m = om;
1567
                        T1(spriteNum) = 1;  // AMBIENT_SFX_PLAYING
5 Plagman 1568
                    }
5825 terminx 1569
                    else if (playerDist >= spriteHitag && T1(spriteNum) == 1)
5 Plagman 1570
                    {
3822 helixhorne 1571
                        // Stop playing ambience sound because we're out of its range.
1572
 
4352 helixhorne 1573
                        // T1 will be reset in sounds.c: CLEAR_SOUND_T0
1599 terminx 1574
                        // T1 = 0;
5825 terminx 1575
                        S_StopEnvSound(pSprite->lotag,spriteNum);
5 Plagman 1576
                    }
1577
                }
2887 helixhorne 1578
 
7914 terminx 1579
                if ((g_sounds[pSprite->lotag].m & (SF_GLOBAL|SF_DTAG)) == SF_GLOBAL)
337 terminx 1580
                {
2887 helixhorne 1581
                    // Randomly playing global sounds (flyby of planes, screams, ...)
1582
 
5825 terminx 1583
                    if (T5(spriteNum) > 0)
1584
                        T5(spriteNum)--;
1143 terminx 1585
                    else
2876 helixhorne 1586
                    {
6244 terminx 1587
                        for (int TRAVERSE_CONNECT(playerNum))
1588
                            if (playerNum == myconnectindex && g_player[playerNum].ps->cursectnum == pSprite->sectnum)
2379 helixhorne 1589
                            {
5825 terminx 1590
                                S_PlaySound(pSprite->lotag + (unsigned)g_globalRandom % (pSprite->hitag+1));
1591
                                T5(spriteNum) = GAMETICSPERSEC*40 + g_globalRandom%(GAMETICSPERSEC*40);
2379 helixhorne 1592
                            }
2876 helixhorne 1593
                    }
337 terminx 1594
                }
1595
            }
1596
            break;
5 Plagman 1597
        }
2885 helixhorne 1598
        }
5825 terminx 1599
next_sprite:
1600
        spriteNum = nextSprite;
5 Plagman 1601
    }
1602
}
1603
 
1595 helixhorne 1604
ACTOR_STATIC void G_MoveFallers(void)
5 Plagman 1605
{
6244 terminx 1606
    int spriteNum = headspritestat[STAT_FALLER];
5 Plagman 1607
 
5825 terminx 1608
    while (spriteNum >= 0)
5 Plagman 1609
    {
7776 terminx 1610
        int const  nextSprite = nextspritestat[spriteNum];
1611
        auto const pSprite    = &sprite[spriteNum];
1612
        int const  sectNum    = pSprite->sectnum;
5 Plagman 1613
 
5825 terminx 1614
        if (T1(spriteNum) == 0)
5 Plagman 1615
        {
6244 terminx 1616
            const int16_t oextra = pSprite->extra;
5825 terminx 1617
            int j;
3679 helixhorne 1618
 
5825 terminx 1619
            pSprite->z -= ZOFFSET2;
1620
            T2(spriteNum) = pSprite->ang;
6244 terminx 1621
 
5825 terminx 1622
            if ((j = A_IncurDamage(spriteNum)) >= 0)
5 Plagman 1623
            {
333 terminx 1624
                if (j == FIREEXT || j == RPG || j == RADIUSEXPLOSION || j == SEENINE || j == OOZFILTER)
559 terminx 1625
                {
5825 terminx 1626
                    if (pSprite->extra <= 0)
5 Plagman 1627
                    {
5825 terminx 1628
                        T1(spriteNum) = 1;
3679 helixhorne 1629
 
5829 terminx 1630
                        for (bssize_t SPRITES_OF(STAT_FALLER, j))
5 Plagman 1631
                        {
5825 terminx 1632
                            if (sprite[j].hitag == SHT(spriteNum))
5 Plagman 1633
                            {
1625 terminx 1634
                                actor[j].t_data[0] = 1;
5 Plagman 1635
                                sprite[j].cstat &= (65535-64);
331 terminx 1636
                                if (sprite[j].picnum == CEILINGSTEAM || sprite[j].picnum == STEAM)
5 Plagman 1637
                                    sprite[j].cstat |= 32768;
1638
                            }
1639
                        }
1640
                    }
1641
                }
1642
                else
1643
                {
5825 terminx 1644
                    actor[spriteNum].extra = 0;
1645
                    pSprite->extra = oextra;
5 Plagman 1646
                }
1647
            }
5825 terminx 1648
            pSprite->ang = T2(spriteNum);
1649
            pSprite->z += ZOFFSET2;
5 Plagman 1650
        }
5825 terminx 1651
        else if (T1(spriteNum) == 1)
5 Plagman 1652
        {
5825 terminx 1653
            if ((int16_t)pSprite->lotag > 0)
5 Plagman 1654
            {
5825 terminx 1655
                pSprite->lotag-=3;
1656
                if ((int16_t)pSprite->lotag <= 0)
5 Plagman 1657
                {
5825 terminx 1658
                    pSprite->xvel = (32+(krand()&63));
1659
                    pSprite->zvel = -(1024+(krand()&1023));
5 Plagman 1660
                }
1661
            }
1662
            else
1663
            {
6244 terminx 1664
                int32_t spriteGravity = g_spriteGravity;
3679 helixhorne 1665
 
5825 terminx 1666
                if (pSprite->xvel > 0)
5 Plagman 1667
                {
5825 terminx 1668
                    pSprite->xvel -= 8;
1669
                    A_SetSprite(spriteNum,CLIPMASK0);
5 Plagman 1670
                }
1671
 
5825 terminx 1672
                if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(pSprite->sectnum)))
6244 terminx 1673
                    spriteGravity = 0;
1674
                else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(pSprite->sectnum)))
1675
                    spriteGravity = g_spriteGravity / 6;
5 Plagman 1676
 
8637 terminx 1677
                if (pSprite->z < (sector[sectNum].floorz-ACTOR_FLOOR_OFFSET))
5 Plagman 1678
                {
6244 terminx 1679
                    pSprite->zvel += spriteGravity;
8637 terminx 1680
                    if (pSprite->zvel > ACTOR_MAXFALLINGZVEL)
1681
                        pSprite->zvel = ACTOR_MAXFALLINGZVEL;
5825 terminx 1682
                    pSprite->z += pSprite->zvel;
5 Plagman 1683
                }
6244 terminx 1684
 
5825 terminx 1685
                if ((sector[sectNum].floorz-pSprite->z) < ZOFFSET2)
5 Plagman 1686
                {
6911 terminx 1687
#ifndef EDUKE32_STANDALONE
7673 terminx 1688
                    for (int x = 0, x_end = 1+(krand()&7); x < x_end; ++x)
6244 terminx 1689
                        RANDOMSCRAP(pSprite, spriteNum);
6911 terminx 1690
#endif
5830 terminx 1691
                    DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 1692
                }
1693
            }
1694
        }
1695
 
5825 terminx 1696
next_sprite:
1697
        spriteNum = nextSprite;
5 Plagman 1698
    }
1699
}
1700
 
1595 helixhorne 1701
ACTOR_STATIC void G_MoveStandables(void)
5 Plagman 1702
{
6244 terminx 1703
    int spriteNum = headspritestat[STAT_STANDABLE], j, switchPic;
2451 helixhorne 1704
 
5825 terminx 1705
    while (spriteNum >= 0)
5 Plagman 1706
    {
7776 terminx 1707
        int const  nextSprite = nextspritestat[spriteNum];
1708
        auto const pData      = &actor[spriteNum].t_data[0];
1709
        auto const pSprite    = &sprite[spriteNum];
1710
        int const  sectNum    = pSprite->sectnum;
5 Plagman 1711
 
5825 terminx 1712
        if (sectNum < 0)
5830 terminx 1713
            DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 1714
 
3682 helixhorne 1715
        // Rotation-fixed sprites in rotating sectors already have bpos* updated.
5825 terminx 1716
        if ((pData[7]&(0xffff0000))!=ROTFIXSPR_MAGIC)
7905 terminx 1717
            actor[spriteNum].bpos = pSprite->pos;
5 Plagman 1718
 
6798 terminx 1719
#ifndef EDUKE32_STANDALONE
8559 terminx 1720
        if (!FURY && PN(spriteNum) >= CRANE && PN(spriteNum) <= CRANE+3)
5 Plagman 1721
        {
3679 helixhorne 1722
            int32_t nextj;
1723
 
5 Plagman 1724
            //t[0] = state
1725
            //t[1] = checking sector number
1726
 
5825 terminx 1727
            if (pSprite->xvel) A_GetZLimits(spriteNum);
5 Plagman 1728
 
5825 terminx 1729
            if (pData[0] == 0)   //Waiting to check the sector
5 Plagman 1730
            {
5825 terminx 1731
                for (SPRITES_OF_SECT_SAFE(pData[1], j, nextj))
5 Plagman 1732
                {
333 terminx 1733
                    switch (sprite[j].statnum)
5 Plagman 1734
                    {
5825 terminx 1735
                        case STAT_ACTOR:
1736
                        case STAT_ZOMBIEACTOR:
1737
                        case STAT_STANDABLE:
1738
                        case STAT_PLAYER:
1739
                        {
1740
                            vec3_t vect = { g_origins[pData[4]+1].x, g_origins[pData[4]+1].y, sprite[j].z };
1208 terminx 1741
 
5825 terminx 1742
                            pSprite->ang = getangle(vect.x-pSprite->x, vect.y-pSprite->y);
1743
                            setsprite(j, &vect);
1744
                            pData[0]++;
1745
                            goto next_sprite;
1746
                        }
5 Plagman 1747
                    }
1748
                }
1749
            }
1750
 
5825 terminx 1751
            else if (pData[0]==1)
5 Plagman 1752
            {
5825 terminx 1753
                if (pSprite->xvel < 184)
5 Plagman 1754
                {
5825 terminx 1755
                    pSprite->picnum = CRANE+1;
1756
                    pSprite->xvel += 8;
5 Plagman 1757
                }
5825 terminx 1758
                A_SetSprite(spriteNum,CLIPMASK0);
1759
                if (sectNum == pData[1])
1760
                    pData[0]++;
5 Plagman 1761
            }
5825 terminx 1762
            else if (pData[0]==2 || pData[0]==7)
5 Plagman 1763
            {
5825 terminx 1764
                pSprite->z += (1024+512);
5 Plagman 1765
 
5825 terminx 1766
                if (pData[0]==2)
5 Plagman 1767
                {
5825 terminx 1768
                    if (sector[sectNum].floorz - pSprite->z < (64<<8))
1769
                        if (pSprite->picnum > CRANE) pSprite->picnum--;
5 Plagman 1770
 
5825 terminx 1771
                    if (sector[sectNum].floorz - pSprite->z < 4096+1024)
1772
                        pData[0]++;
5 Plagman 1773
                }
3679 helixhorne 1774
 
5825 terminx 1775
                if (pData[0]==7)
5 Plagman 1776
                {
5825 terminx 1777
                    if (sector[sectNum].floorz - pSprite->z < (64<<8))
5 Plagman 1778
                    {
5825 terminx 1779
                        if (pSprite->picnum > CRANE) pSprite->picnum--;
5 Plagman 1780
                        else
1781
                        {
5825 terminx 1782
                            if (pSprite->owner==-2)
5 Plagman 1783
                            {
5825 terminx 1784
                                int32_t p = A_FindPlayer(pSprite, NULL);
1143 terminx 1785
                                A_PlaySound(DUKE_GRUNT,g_player[p].ps->i);
5825 terminx 1786
                                if (g_player[p].ps->on_crane == spriteNum)
564 terminx 1787
                                    g_player[p].ps->on_crane = -1;
5 Plagman 1788
                            }
3679 helixhorne 1789
 
5825 terminx 1790
                            pData[0]++;
1791
                            pSprite->owner = -1;
5 Plagman 1792
                        }
1793
                    }
1794
                }
1795
            }
5825 terminx 1796
            else if (pData[0]==3)
5 Plagman 1797
            {
5825 terminx 1798
                pSprite->picnum++;
1799
                if (pSprite->picnum == CRANE+2)
5 Plagman 1800
                {
8560 terminx 1801
                    int32_t p = G_GetPlayerInSector(pData[1]);
3679 helixhorne 1802
 
564 terminx 1803
                    if (p >= 0 && g_player[p].ps->on_ground)
5 Plagman 1804
                    {
5825 terminx 1805
                        pSprite->owner = -2;
1806
                        g_player[p].ps->on_crane = spriteNum;
1143 terminx 1807
                        A_PlaySound(DUKE_GRUNT,g_player[p].ps->i);
6725 terminx 1808
                        g_player[p].ps->q16ang = fix16_from_int(pSprite->ang+1024);
5 Plagman 1809
                    }
1810
                    else
1811
                    {
5825 terminx 1812
                        for (SPRITES_OF_SECT(pData[1], j))
5 Plagman 1813
                        {
333 terminx 1814
                            switch (sprite[j].statnum)
5 Plagman 1815
                            {
1487 terminx 1816
                            case STAT_ACTOR:
1817
                            case STAT_STANDABLE:
5825 terminx 1818
                                pSprite->owner = j;
337 terminx 1819
                                break;
5 Plagman 1820
                            }
1821
                        }
1822
                    }
1823
 
5825 terminx 1824
                    pData[0]++;//Grabbed the sprite
1825
                    pData[2]=0;
1826
                    goto next_sprite;
5 Plagman 1827
                }
1828
            }
5825 terminx 1829
            else if (pData[0]==4) //Delay before going up
5 Plagman 1830
            {
5825 terminx 1831
                pData[2]++;
1832
                if (pData[2] > 10)
1833
                    pData[0]++;
5 Plagman 1834
            }
5825 terminx 1835
            else if (pData[0]==5 || pData[0] == 8)
5 Plagman 1836
            {
5825 terminx 1837
                if (pData[0]==8 && pSprite->picnum < (CRANE+2))
1838
                    if ((sector[sectNum].floorz-pSprite->z) > 8192)
1839
                        pSprite->picnum++;
5 Plagman 1840
 
5825 terminx 1841
                if (pSprite->z < g_origins[pData[4]+2].x)
5 Plagman 1842
                {
5825 terminx 1843
                    pData[0]++;
1844
                    pSprite->xvel = 0;
5 Plagman 1845
                }
1846
                else
5825 terminx 1847
                    pSprite->z -= (1024+512);
5 Plagman 1848
            }
5825 terminx 1849
            else if (pData[0]==6)
5 Plagman 1850
            {
5825 terminx 1851
                if (pSprite->xvel < 192)
1852
                    pSprite->xvel += 8;
1853
                pSprite->ang = getangle(g_origins[pData[4]].x - pSprite->x, g_origins[pData[4]].y - pSprite->y);
1854
                A_SetSprite(spriteNum,CLIPMASK0);
1855
                if (((pSprite->x-g_origins[pData[4]].x)*(pSprite->x-g_origins[pData[4]].x)+(pSprite->y-g_origins[pData[4]].y)*(pSprite->y-g_origins[pData[4]].y)) < (128*128))
1856
                    pData[0]++;
5 Plagman 1857
            }
1858
 
5825 terminx 1859
            else if (pData[0]==9)
1860
                pData[0] = 0;
5 Plagman 1861
 
1208 terminx 1862
            {
1863
                vec3_t vect;
5825 terminx 1864
                Bmemcpy(&vect,pSprite,sizeof(vec3_t));
1208 terminx 1865
                vect.z -= (34<<8);
5825 terminx 1866
                setsprite(g_origins[pData[4]+2].y, &vect);
1208 terminx 1867
            }
5 Plagman 1868
 
1208 terminx 1869
 
5825 terminx 1870
            if (pSprite->owner != -1)
5 Plagman 1871
            {
5825 terminx 1872
                int32_t p = A_FindPlayer(pSprite, NULL);
5 Plagman 1873
 
5825 terminx 1874
                if (A_IncurDamage(spriteNum) >= 0)
5 Plagman 1875
                {
5825 terminx 1876
                    if (pSprite->owner == -2)
1877
                        if (g_player[p].ps->on_crane == spriteNum)
564 terminx 1878
                            g_player[p].ps->on_crane = -1;
5825 terminx 1879
                    pSprite->owner = -1;
1880
                    pSprite->picnum = CRANE;
1881
                    goto next_sprite;
559 terminx 1882
                }
5 Plagman 1883
 
5825 terminx 1884
                if (pSprite->owner >= 0)
559 terminx 1885
                {
7697 terminx 1886
                    setsprite(pSprite->owner,&pSprite->pos);
5 Plagman 1887
 
7905 terminx 1888
                    actor[pSprite->owner].bpos = pSprite->pos;
5 Plagman 1889
 
5825 terminx 1890
                    pSprite->zvel = 0;
559 terminx 1891
                }
5825 terminx 1892
                else if (pSprite->owner == -2)
559 terminx 1893
                {
7776 terminx 1894
                    auto const ps = g_player[p].ps;
1208 terminx 1895
 
6725 terminx 1896
                    ps->opos.x = ps->pos.x = pSprite->x-(sintable[(fix16_to_int(ps->q16ang)+512)&2047]>>6);
1897
                    ps->opos.y = ps->pos.y = pSprite->y-(sintable[fix16_to_int(ps->q16ang)&2047]>>6);
5825 terminx 1898
                    ps->opos.z = ps->pos.z = pSprite->z+(2<<8);
2875 helixhorne 1899
 
7973 terminx 1900
                    setsprite(ps->i, &ps->pos);
2875 helixhorne 1901
                    ps->cursectnum = sprite[ps->i].sectnum;
559 terminx 1902
                }
5 Plagman 1903
            }
1904
 
5825 terminx 1905
            goto next_sprite;
5 Plagman 1906
        }
8559 terminx 1907
        else if (!FURY && PN(spriteNum) >= WATERFOUNTAIN && PN(spriteNum) <= WATERFOUNTAIN+3)
5 Plagman 1908
        {
5825 terminx 1909
            if (pData[0] > 0)
5 Plagman 1910
            {
5825 terminx 1911
                if (pData[0] < 20)
5 Plagman 1912
                {
5825 terminx 1913
                    pData[0]++;
5 Plagman 1914
 
5825 terminx 1915
                    pSprite->picnum++;
5 Plagman 1916
 
5825 terminx 1917
                    if (pSprite->picnum == (WATERFOUNTAIN+3))
1918
                        pSprite->picnum = WATERFOUNTAIN+1;
5 Plagman 1919
                }
1920
                else
1921
                {
6798 terminx 1922
                    int32_t playerDist;
1923
 
6244 terminx 1924
                    A_FindPlayer(pSprite,&playerDist);
5 Plagman 1925
 
6244 terminx 1926
                    if (playerDist > 512)
5 Plagman 1927
                    {
5825 terminx 1928
                        pData[0] = 0;
1929
                        pSprite->picnum = WATERFOUNTAIN;
5 Plagman 1930
                    }
5825 terminx 1931
                    else pData[0] = 1;
5 Plagman 1932
                }
1933
            }
5825 terminx 1934
            goto next_sprite;
5 Plagman 1935
        }
8559 terminx 1936
        else if (!FURY && AFLAMABLE(pSprite->picnum))
5 Plagman 1937
        {
5825 terminx 1938
            if (T1(spriteNum) == 1)
5 Plagman 1939
            {
5825 terminx 1940
                if ((++T2(spriteNum)&3) > 0) goto next_sprite;
5 Plagman 1941
 
5825 terminx 1942
                if (pSprite->picnum == TIRE && T2(spriteNum) == 32)
5 Plagman 1943
                {
5825 terminx 1944
                    pSprite->cstat = 0;
1945
                    j = A_Spawn(spriteNum,BLOODPOOL);
5 Plagman 1946
                    sprite[j].shade = 127;
1947
                }
1948
                else
1949
                {
5825 terminx 1950
                    if (pSprite->shade < 64) pSprite->shade++;
5830 terminx 1951
                    else DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 1952
                }
1953
 
5825 terminx 1954
                j = pSprite->xrepeat-(krand()&7);
331 terminx 1955
                if (j < 10)
5830 terminx 1956
                    DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 1957
 
5825 terminx 1958
                pSprite->xrepeat = j;
5 Plagman 1959
 
5825 terminx 1960
                j = pSprite->yrepeat-(krand()&7);
335 terminx 1961
                if (j < 4)
5830 terminx 1962
                    DELETE_SPRITE_AND_CONTINUE(spriteNum);
2609 helixhorne 1963
 
5825 terminx 1964
                pSprite->yrepeat = j;
5 Plagman 1965
            }
5825 terminx 1966
            if (pSprite->picnum == BOX)
5 Plagman 1967
            {
5825 terminx 1968
                A_Fall(spriteNum);
1969
                actor[spriteNum].ceilingz = sector[pSprite->sectnum].ceilingz;
5 Plagman 1970
            }
5825 terminx 1971
            goto next_sprite;
5 Plagman 1972
        }
8559 terminx 1973
        else if (!FURY && pSprite->picnum == TRIPBOMB)
5 Plagman 1974
        {
4256 helixhorne 1975
            // TIMER_CONTROL
5825 terminx 1976
            if (actor[spriteNum].t_data[6] == 1)
5 Plagman 1977
            {
1978
 
5825 terminx 1979
                if (actor[spriteNum].t_data[7] >= 1)
5 Plagman 1980
                {
5825 terminx 1981
                    actor[spriteNum].t_data[7]--;
5 Plagman 1982
                }
1983
 
5825 terminx 1984
                if (actor[spriteNum].t_data[7] <= 0)
5 Plagman 1985
                {
5825 terminx 1986
                    T3(spriteNum)=16;
1987
                    actor[spriteNum].t_data[6]=3;
1988
                    A_PlaySound(LASERTRIP_ARMING,spriteNum);
5 Plagman 1989
                }
1990
                // we're on a timer....
1991
            }
5825 terminx 1992
            if (T3(spriteNum) > 0 && actor[spriteNum].t_data[6] == 3)
5 Plagman 1993
            {
5825 terminx 1994
                T3(spriteNum)--;
1625 terminx 1995
 
5825 terminx 1996
                if (T3(spriteNum) == 8)
5 Plagman 1997
                {
6244 terminx 1998
                    for (j=0; j<5; j++)
1999
                        RANDOMSCRAP(pSprite, spriteNum);
5 Plagman 2000
 
6244 terminx 2001
                    int const dmg = pSprite->extra;
2002
                    A_RadiusDamage(spriteNum, g_tripbombRadius, dmg>>2, dmg>>1, dmg-(dmg>>2), dmg);
2003
 
5825 terminx 2004
                    j = A_Spawn(spriteNum,EXPLOSION2);
1665 terminx 2005
                    A_PlaySound(LASERTRIP_EXPLODE,j);
5825 terminx 2006
                    sprite[j].ang = pSprite->ang;
5 Plagman 2007
                    sprite[j].xvel = 348;
1143 terminx 2008
                    A_SetSprite(j,CLIPMASK0);
5 Plagman 2009
 
3679 helixhorne 2010
                    for (SPRITES_OF(STAT_MISC, j))
5 Plagman 2011
                    {
5825 terminx 2012
                        if (sprite[j].picnum == LASERLINE && pSprite->hitag == sprite[j].hitag)
5 Plagman 2013
                            sprite[j].xrepeat = sprite[j].yrepeat = 0;
2014
                    }
2609 helixhorne 2015
 
5830 terminx 2016
                    DELETE_SPRITE_AND_CONTINUE(spriteNum);
5 Plagman 2017
                }
5825 terminx 2018
                goto next_sprite;
5 Plagman 2019
            }
2020
            else
2021
            {
6244 terminx 2022
                int const oldExtra = pSprite->extra;
2023
                int const oldAng = pSprite->ang;
2024
 
5825 terminx 2025
                pSprite->extra = 1;
2026
                if (A_IncurDamage(spriteNum) >= 0)
3679 helixhorne 2027
                {
5825 terminx 2028
                    actor[spriteNum].t_data[6] = 3;
2029
                    T3(spriteNum) = 16;
3679 helixhorne 2030
                }
6244 terminx 2031
                pSprite->extra = oldExtra;
2032
                pSprite->ang = oldAng;
5 Plagman 2033
            }
2034
 
5825 terminx 2035
            switch (T1(spriteNum))
5 Plagman 2036
            {
1625 terminx 2037
            default:
6244 terminx 2038
            {
2039
                int32_t playerDist;
2040
                A_FindPlayer(pSprite, &playerDist);
2041
                if (playerDist > 768 || T1(spriteNum) > 16) T1(spriteNum)++;
1625 terminx 2042
                break;
6244 terminx 2043
            }
1625 terminx 2044
 
2045
            case 32:
3680 helixhorne 2046
            {
6244 terminx 2047
                int16_t hitSprite;
2048
                int const oldAng = pSprite->ang;
3680 helixhorne 2049
 
5825 terminx 2050
                pSprite->ang = T6(spriteNum);
5 Plagman 2051
 
5825 terminx 2052
                T4(spriteNum) = pSprite->x;
2053
                T5(spriteNum) = pSprite->y;
1625 terminx 2054
 
5825 terminx 2055
                pSprite->x += sintable[(T6(spriteNum)+512)&2047]>>9;
2056
                pSprite->y += sintable[(T6(spriteNum))&2047]>>9;
2057
                pSprite->z -= (3<<8);
1625 terminx 2058
 
8718 terminx 2059
                int16_t const oldSectNum = pSprite->sectnum;
2060
                int16_t       curSectNum = pSprite->sectnum;
5 Plagman 2061
 
8718 terminx 2062
                updatesectorneighbor(pSprite->x, pSprite->y, &curSectNum, 1024, 2048);
2063
                changespritesect(spriteNum, curSectNum);
2064
 
8730 terminx 2065
                int32_t hitDist = A_CheckHitSprite(spriteNum, &hitSprite);
5 Plagman 2066
 
6244 terminx 2067
                actor[spriteNum].lastv.x = hitDist;
2068
                pSprite->ang = oldAng;
5 Plagman 2069
 
8718 terminx 2070
                // we're on a trip wire
5825 terminx 2071
                if (actor[spriteNum].t_data[6] != 1)
5 Plagman 2072
                {
6244 terminx 2073
                    while (hitDist > 0)
5 Plagman 2074
                    {
8718 terminx 2075
                        j = A_Spawn(spriteNum, LASERLINE);
2076
 
5825 terminx 2077
                        sprite[j].hitag = pSprite->hitag;
1625 terminx 2078
                        actor[j].t_data[1] = sprite[j].z;
5 Plagman 2079
 
6244 terminx 2080
                        if (hitDist < 1024)
5 Plagman 2081
                        {
6244 terminx 2082
                            sprite[j].xrepeat = hitDist>>5;
5 Plagman 2083
                            break;
2084
                        }
6244 terminx 2085
                        hitDist -= 1024;
2072 hendricks2 2086
 
8718 terminx 2087
                        pSprite->x += sintable[(T6(spriteNum)+512)&2047]>>4;
2088
                        pSprite->y += sintable[(T6(spriteNum))&2047]>>4;
2089
 
2090
                        updatesectorneighbor(pSprite->x, pSprite->y, &curSectNum, 1024, 2048);
2091
 
2092
                        if (curSectNum == -1)
2072 hendricks2 2093
                            break;
8718 terminx 2094
 
2095
                        changespritesect(spriteNum, curSectNum);
2096
 
2097
                        // this is a hack to work around the LASERLINE sprite's art tile offset
2098
                        changespritesect(j, curSectNum);
5 Plagman 2099
                    }
2100
                }
1625 terminx 2101
 
5825 terminx 2102
                T1(spriteNum)++;
1625 terminx 2103
 
8718 terminx 2104
                pSprite->pos.vec2 = { T4(spriteNum), T5(spriteNum) };
5825 terminx 2105
                pSprite->z += (3<<8);
1625 terminx 2106
 
8718 terminx 2107
                changespritesect(spriteNum, oldSectNum);
5825 terminx 2108
                T4(spriteNum) = T3(spriteNum) = 0;