Subversion Repositories eduke32

Rev

Rev 5021 | Details | Compare with Previous | Last modification | View Log | RSS feed

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