Subversion Repositories eduke32

Rev

Rev 4975 | 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
//-------------------------------------------------------------------------
22
 
23
#include <time.h>
1458 terminx 24
#include <stdlib.h>
2985 helixhorne 25
#include <math.h>  // sqrt
5 Plagman 26
 
3170 helixhorne 27
#include "compat.h"
28
 
4902 terminx 29
#include "build.h"
30
 
5 Plagman 31
#include "duke3d.h"
32
#include "gamedef.h"
1677 terminx 33
#include "gameexec.h"
5 Plagman 34
#include "scriplib.h"
1677 terminx 35
#include "savegame.h"
36
#include "premap.h"
968 terminx 37
#include "osdcmds.h"
5 Plagman 38
#include "osd.h"
1677 terminx 39
#include "menus.h"
4507 hendricks2 40
#include "input.h"
4987 terminx 41
#include "anim.h"
5 Plagman 42
 
2721 helixhorne 43
#ifdef LUNATIC
3148 helixhorne 44
# include "lunatic_game.h"
2329 helixhorne 45
#endif
46
 
1595 helixhorne 47
#if KRANDDEBUG
48
# define GAMEEXEC_INLINE
49
# define GAMEEXEC_STATIC
50
#else
51
# define GAMEEXEC_INLINE inline
52
# define GAMEEXEC_STATIC static
53
#endif
54
 
3946 helixhorne 55
vmstate_t vm;
56
 
57
#if !defined LUNATIC
3242 helixhorne 58
enum vmflags_t {
59
    VM_RETURN       = 0x00000001,
60
    VM_KILL         = 0x00000002,
61
    VM_NOEXECUTE    = 0x00000004,
62
};
63
 
3460 helixhorne 64
int32_t g_tw;
1205 terminx 65
int32_t g_errorLineNum;
1956 helixhorne 66
int32_t g_currentEventExec = -1;
67
 
4902 terminx 68
intptr_t *insptr;
69
 
70
int32_t g_iReturnVarID = -1;     // var ID of "RETURN"
71
int32_t g_iWeaponVarID = -1;     // var ID of "WEAPON"
72
int32_t g_iWorksLikeVarID = -1;  // var ID of "WORKSLIKE"
73
int32_t g_iZRangeVarID = -1;     // var ID of "ZRANGE"
74
int32_t g_iAngRangeVarID = -1;   // var ID of "ANGRANGE"
75
int32_t g_iAimAngleVarID = -1;   // var ID of "AUTOAIMANGLE"
76
int32_t g_iLoTagID = -1;         // var ID of "LOTAG"
77
int32_t g_iHiTagID = -1;         // var ID of "HITAG"
78
int32_t g_iTextureID = -1;       // var ID of "TEXTURE"
79
int32_t g_iThisActorID = -1;     // var ID of "THISACTOR"
80
int32_t g_iSpriteVarID = -1;
81
int32_t g_iSectorVarID = -1;
82
int32_t g_iWallVarID = -1;
83
int32_t g_iPlayerVarID = -1;
84
int32_t g_iActorVarID = -1;
85
 
1909 terminx 86
GAMEEXEC_STATIC void VM_Execute(int32_t loop);
617 terminx 87
 
3354 helixhorne 88
# include "gamestructures.c"
89
#endif
1180 terminx 90
 
4902 terminx 91
#define VM_INSTMASK 0xfff
92
 
4699 terminx 93
#define VM_CONDITIONAL(xxx)                                                                                            \
4745 terminx 94
    {                                                                                                                  \
4902 terminx 95
        if ((xxx) || ((insptr = (intptr_t *)*(insptr + 1)) && (((*insptr) & VM_INSTMASK) == CON_ELSE)))                \
4745 terminx 96
        {                                                                                                              \
97
            insptr += 2;                                                                                               \
98
            VM_Execute(0);                                                                                             \
99
        }                                                                                                              \
4699 terminx 100
    }
1909 terminx 101
 
1625 terminx 102
void VM_ScriptInfo(void)
1031 hnt_ts 103
{
3410 helixhorne 104
#if !defined LUNATIC
1631 terminx 105
    if (!script)
106
        return;
107
 
108
    if (insptr)
1031 hnt_ts 109
    {
2229 hendricks2 110
        initprintf("\n");
111
 
4902 terminx 112
        for (intptr_t *p = insptr - 32; p < insptr + 32; p++)
1631 terminx 113
        {
4902 terminx 114
            if ((int32_t)(p - script) >= g_scriptSize)
115
                break;
2229 hendricks2 116
 
4902 terminx 117
            initprintf("%5d: %3d: ", (int32_t) (p - script), (int32_t) (p - insptr));
118
 
119
            if (*p >> 12 && (*p & VM_INSTMASK) < CON_END)
120
                initprintf("%5d %s\n", (int32_t) (*p >> 12), keyw[*p & VM_INSTMASK]);
1631 terminx 121
            else
4902 terminx 122
                initprintf("%d\n", (int32_t) *p);
1631 terminx 123
        }
124
 
125
        initprintf("\n");
1031 hnt_ts 126
    }
1631 terminx 127
 
128
    if (vm.g_i)
4902 terminx 129
        initprintf("current actor: %d (%d)\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
1631 terminx 130
 
4902 terminx 131
    initprintf("g_errorLineNum: %d, g_tw: %d\n", g_errorLineNum, g_tw);
3354 helixhorne 132
#endif
1031 hnt_ts 133
}
134
 
4745 terminx 135
static void VM_DeleteSprite(int32_t iActor, int32_t iPlayer)
3514 helixhorne 136
{
4680 terminx 137
    if (EDUKE32_PREDICT_FALSE((unsigned) iActor >= MAXSPRITES))
3983 terminx 138
        return;
3514 helixhorne 139
 
3983 terminx 140
    // if player was set to squish, first stop that...
4680 terminx 141
    if (EDUKE32_PREDICT_FALSE(iPlayer >= 0 && g_player[iPlayer].ps->actorsqu == iActor))
3983 terminx 142
        g_player[iPlayer].ps->actorsqu = -1;
143
 
144
    A_DeleteSprite(iActor);
3514 helixhorne 145
}
146
 
4902 terminx 147
intptr_t *apScriptGameEvent[MAXGAMEEVENTS];
148
 
2709 helixhorne 149
// May recurse, e.g. through EVENT_XXX -> ... -> EVENT_KILLIT
4745 terminx 150
#ifdef LUNATIC
151
FORCE_INLINE int32_t VM_EventCommon_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist, int32_t iReturn)
5 Plagman 152
{
4673 terminx 153
    const double t = gethiticks();
154
    int32_t ret = El_CallEvent(&g_ElState, iEventID, iActor, iPlayer, lDist, &iReturn);
2842 helixhorne 155
 
4673 terminx 156
    // NOTE: the run times are those of the called event plus any events
157
    // called by it, *not* "self" time.
158
    g_eventTotalMs[iEventID] += gethiticks()-t;
159
    g_eventCalls[iEventID]++;
3946 helixhorne 160
 
4673 terminx 161
    if (ret == 1)
4745 terminx 162
        VM_DeleteSprite(iActor, iPlayer);
163
 
164
    return iReturn;
165
}
3514 helixhorne 166
#else
4745 terminx 167
FORCE_INLINE int32_t VM_EventCommon_(const int32_t iEventID, const int32_t iActor, const int32_t iPlayer,
168
                                     const int32_t lDist, int32_t iReturn)
169
{
170
    // this is initialized first thing because iActor, iPlayer, lDist, etc are already right there on the stack
171
    // from the function call
172
    const vmstate_t tempvm = { iActor, iPlayer, lDist, &actor[(unsigned)iActor].t_data[0],
4902 terminx 173
                               &sprite[(unsigned)iActor], g_player[iPlayer].ps, 0 };
4745 terminx 174
 
175
    // since we're targeting C99 and C++ now, we can interweave these to avoid
176
    // having to load addresses for things twice
177
    // for example, because we are loading backupReturnVar with the value of
178
    // aGameVars[g_iReturnVarID].val.lValue, the compiler can avoid having to
179
    // reload the address of aGameVars[g_iReturnVarID].val.lValue in order to
180
    // set it to the value of iReturn (...which should still be on the stack!)
181
 
182
    const int32_t backupReturnVar = aGameVars[g_iReturnVarID].val.lValue;
183
    aGameVars[g_iReturnVarID].val.lValue = iReturn;
184
 
185
    const int32_t backupEventExec = g_currentEventExec;
186
    g_currentEventExec = iEventID;
187
 
188
    intptr_t *oinsptr = insptr;
189
    insptr = apScriptGameEvent[iEventID];
190
 
4727 helixhorne 191
    const vmstate_t vm_backup = vm;
4745 terminx 192
    vm = tempvm;
4727 helixhorne 193
 
4745 terminx 194
    // check tempvm instead of vm... this way, we are not actually loading
195
    // FROM vm anywhere until VM_Execute() is called
196
    if ((unsigned)tempvm.g_i >= MAXSPRITES)
4721 terminx 197
    {
198
        static spritetype dummy_sprite;
199
        static int32_t dummy_t[ARRAY_SIZE(actor[0].t_data)];
4709 helixhorne 200
 
4745 terminx 201
        vm.g_sp = &dummy_sprite;
202
        vm.g_t = dummy_t;
4721 terminx 203
    }
2652 terminx 204
 
4902 terminx 205
    if ((unsigned)iPlayer >= (unsigned)playerswhenstarted)
206
        vm.g_pp = g_player[0].ps;
207
 
4673 terminx 208
    VM_Execute(1);
5 Plagman 209
 
4673 terminx 210
    if (vm.g_flags & VM_KILL)
4745 terminx 211
        VM_DeleteSprite(vm.g_i, vm.g_p);
1802 terminx 212
 
4745 terminx 213
    // this needs to happen after VM_DeleteSprite() because VM_DeleteSprite()
214
    // can trigger additional events
4721 terminx 215
    vm = vm_backup;
4673 terminx 216
    insptr = oinsptr;
217
    g_currentEventExec = backupEventExec;
218
    iReturn = aGameVars[g_iReturnVarID].val.lValue;
219
    aGameVars[g_iReturnVarID].val.lValue = backupReturnVar;
2656 terminx 220
 
2923 helixhorne 221
    return iReturn;
5 Plagman 222
}
4745 terminx 223
#endif
5 Plagman 224
 
4745 terminx 225
// the idea here is that the compiler inlines the call to VM_EventCommon_() and gives us a set of full functions
226
// which are not only optimized further based on lDist or iReturn (or both) having values known at compile time,
227
// but are called faster due to having less parameters
228
 
229
int32_t VM_OnEventWithBoth_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist, int32_t iReturn)
230
{
231
    return VM_EventCommon_(iEventID, iActor, iPlayer, lDist, iReturn);
232
}
233
 
234
int32_t VM_OnEventWithReturn_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t iReturn)
235
{
236
    return VM_EventCommon_(iEventID, iActor, iPlayer, -1, iReturn);
237
}
238
 
239
int32_t VM_OnEventWithDist_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist)
240
{
241
    return VM_EventCommon_(iEventID, iActor, iPlayer, lDist, 0);
242
}
243
 
244
int32_t VM_OnEvent_(int32_t iEventID, int32_t iActor, int32_t iPlayer)
245
{
246
    return VM_EventCommon_(iEventID, iActor, iPlayer, -1, 0);
247
}
248
 
4680 terminx 249
static int32_t VM_CheckSquished(void)
5 Plagman 250
{
4902 terminx 251
    sectortype const * const sc = &sector[vm.g_sp->sectnum];
395 terminx 252
 
4680 terminx 253
    if (sc->lotag == ST_23_SWINGING_DOOR || EDUKE32_PREDICT_FALSE(vm.g_sp->picnum == APLAYER && ud.noclip))
395 terminx 254
        return 0;
255
 
2071 helixhorne 256
    {
257
        int32_t fz=sc->floorz, cz=sc->ceilingz;
258
#ifdef YAX_ENABLE
259
        int16_t cb, fb;
260
 
261
        yax_getbunches(vm.g_sp->sectnum, &cb, &fb);
262
        if (cb >= 0 && (sc->ceilingstat&512)==0)  // if ceiling non-blocking...
3640 helixhorne 263
            cz -= (32<<8);  // unconditionally don't squish... yax_getneighborsect is slowish :/
2071 helixhorne 264
        if (fb >= 0 && (sc->floorstat&512)==0)
265
            fz += (32<<8);
266
#endif
267
 
268
        if (vm.g_sp->pal == 1 ?
269
            (fz - cz >= (32<<8) || (sc->lotag&32768)) :
270
            (fz - cz >= (12<<8)))
271
        return 0;
272
    }
4902 terminx 273
 
274
    P_DoQuote(QUOTE_SQUISHED, vm.g_pp);
2071 helixhorne 275
 
3640 helixhorne 276
    if (A_CheckEnemySprite(vm.g_sp))
277
        vm.g_sp->xvel = 0;
1625 terminx 278
 
4680 terminx 279
    if (EDUKE32_PREDICT_FALSE(vm.g_sp->pal == 1)) // frozen
1625 terminx 280
    {
281
        actor[vm.g_i].picnum = SHOTSPARK1;
282
        actor[vm.g_i].extra = 1;
283
        return 0;
395 terminx 284
    }
1625 terminx 285
 
286
    return 1;
395 terminx 287
}
288
 
4451 helixhorne 289
#if !defined LUNATIC
1595 helixhorne 290
GAMEEXEC_STATIC GAMEEXEC_INLINE void P_ForceAngle(DukePlayer_t *p)
398 terminx 291
{
1205 terminx 292
    int32_t n = 128-(krand()&255);
398 terminx 293
 
294
    p->horiz += 64;
295
    p->return_to_center = 9;
1802 terminx 296
    p->look_ang = p->rotscrnang = n>>1;
398 terminx 297
}
4451 helixhorne 298
#endif
398 terminx 299
 
3254 helixhorne 300
int32_t A_Dodge(spritetype *s)
395 terminx 301
{
1802 terminx 302
    int32_t bx,by,bxvect,byvect,i;
1205 terminx 303
    int32_t mx = s->x, my = s->y;
304
    int32_t mxvect = sintable[(s->ang+512)&2047];
305
    int32_t myvect = sintable[s->ang&2047];
5 Plagman 306
 
1171 terminx 307
    if (A_CheckEnemySprite(s) && s->extra <= 0) // hack
308
        return 0;
309
 
1229 terminx 310
    for (i=headspritestat[STAT_PROJECTILE]; i>=0; i=nextspritestat[i]) //weapons list
5 Plagman 311
    {
1802 terminx 312
        if (OW == i)
5 Plagman 313
            continue;
314
 
315
        bx = SX-mx;
316
        by = SY-my;
335 terminx 317
        bxvect = sintable[(SA+512)&2047];
318
        byvect = sintable[SA&2047];
5 Plagman 319
 
1802 terminx 320
        if ((mxvect * bx) + (myvect * by) >= 0 && (bxvect * bx) + (byvect * by) < 0)
321
        {
322
            if (klabs((bxvect * by) - (byvect * bx)) < 65536<<6)
5 Plagman 323
            {
1802 terminx 324
                s->ang -= 512+(krand()&1024);
325
                return 1;
5 Plagman 326
            }
1802 terminx 327
        }
5 Plagman 328
    }
329
    return 0;
330
}
331
 
3920 helixhorne 332
int32_t A_GetFurthestAngle(int32_t iActor, int32_t angs)
5 Plagman 333
{
432 terminx 334
    spritetype *s = &sprite[iActor];
5 Plagman 335
 
3920 helixhorne 336
    if (s->picnum != APLAYER && (AC_COUNT(actor[iActor].t_data)&63) > 2)
337
        return s->ang + 1024;
5 Plagman 338
 
339
    {
1205 terminx 340
        int32_t furthest_angle=0;
3920 helixhorne 341
        int32_t d, j;
342
        int32_t greatestd = INT32_MIN;
4658 terminx 343
        int32_t angincs=tabledivide32_noinline(2048, angs);
2877 helixhorne 344
        hitdata_t hit;
5 Plagman 345
 
1229 terminx 346
        for (j=s->ang; j<(2048+s->ang); j+=angincs)
1048 terminx 347
        {
1208 terminx 348
            s->z -= (8<<8);
349
            hitscan((const vec3_t *)s, s->sectnum,
1048 terminx 350
                    sintable[(j+512)&2047],
351
                    sintable[j&2047],0,
2877 helixhorne 352
                    &hit,CLIPMASK1);
1208 terminx 353
            s->z += (8<<8);
2877 helixhorne 354
            d = klabs(hit.pos.x-s->x) + klabs(hit.pos.y-s->y);
5 Plagman 355
 
1048 terminx 356
            if (d > greatestd)
357
            {
358
                greatestd = d;
359
                furthest_angle = j;
360
            }
5 Plagman 361
        }
3920 helixhorne 362
 
363
        return furthest_angle&2047;
5 Plagman 364
    }
365
}
366
 
3920 helixhorne 367
int32_t A_FurthestVisiblePoint(int32_t iActor, spritetype *ts, int32_t *dax, int32_t *day)
5 Plagman 368
{
3920 helixhorne 369
    if (AC_COUNT(actor[iActor].t_data)&63)
2652 terminx 370
        return -1;
371
 
5 Plagman 372
    {
1208 terminx 373
        int32_t d, da;//, d, cd, ca,tempx,tempy,cx,cy;
374
        int32_t j, angincs;
1048 terminx 375
        spritetype *s = &sprite[iActor];
2877 helixhorne 376
        hitdata_t hit;
5 Plagman 377
 
1587 terminx 378
        if ((!g_netServer && ud.multimode < 2) && ud.player_skill < 3)
1048 terminx 379
            angincs = 2048/2;
4658 terminx 380
        else angincs = tabledivide32_noinline(2048, 1+(krand()&1));
5 Plagman 381
 
1229 terminx 382
        for (j=ts->ang; j<(2048+ts->ang); j+=(angincs-(krand()&511)))
1048 terminx 383
        {
1208 terminx 384
            ts->z -= (16<<8);
385
            hitscan((const vec3_t *)ts, ts->sectnum,
1048 terminx 386
                    sintable[(j+512)&2047],
1143 terminx 387
                    sintable[j&2047],16384-(krand()&32767),
2877 helixhorne 388
                    &hit,CLIPMASK1);
1048 terminx 389
 
1208 terminx 390
            ts->z += (16<<8);
1048 terminx 391
 
2877 helixhorne 392
            d = klabs(hit.pos.x-ts->x)+klabs(hit.pos.y-ts->y);
393
            da = klabs(hit.pos.x-s->x)+klabs(hit.pos.y-s->y);
1208 terminx 394
 
2877 helixhorne 395
            if (d < da && hit.sect > -1)
396
                if (cansee(hit.pos.x,hit.pos.y,hit.pos.z,
397
                           hit.sect,s->x,s->y,s->z-(16<<8),s->sectnum))
1048 terminx 398
                {
2877 helixhorne 399
                    *dax = hit.pos.x;
400
                    *day = hit.pos.y;
401
                    return hit.sect;
1048 terminx 402
                }
403
        }
404
        return -1;
5 Plagman 405
    }
406
}
407
 
1205 terminx 408
void A_GetZLimits(int32_t iActor)
5 Plagman 409
{
432 terminx 410
    spritetype *s = &sprite[iActor];
5 Plagman 411
 
4680 terminx 412
    int32_t hz,lz,zr = 127;
413
    int32_t cstat = s->cstat;
428 terminx 414
 
4680 terminx 415
    s->cstat = 0;
1217 terminx 416
 
4680 terminx 417
    if (s->statnum == STAT_PROJECTILE)
418
        zr = 4;
5 Plagman 419
 
4680 terminx 420
    s->z -= ZOFFSET;
421
    getzrange((vec3_t *)s,s->sectnum,&actor[iActor].ceilingz,&hz,&actor[iActor].floorz,&lz,zr,CLIPMASK0);
422
    s->z += ZOFFSET;
5 Plagman 423
 
4680 terminx 424
    s->cstat = cstat;
1217 terminx 425
 
4680 terminx 426
    actor[iActor].flags &= ~SFLAG_NOFLOORSHADOW;
2249 helixhorne 427
 
4680 terminx 428
    if ((lz&49152) == 49152 && (sprite[lz&(MAXSPRITES-1)].cstat&48) == 0)
429
    {
430
        const spritetype *hitspr = &sprite[lz&(MAXSPRITES-1)];
2192 helixhorne 431
 
4680 terminx 432
        lz &= (MAXSPRITES-1);
2192 helixhorne 433
 
4680 terminx 434
        if ((A_CheckEnemySprite(hitspr) && hitspr->pal != 1 && s->statnum != STAT_PROJECTILE)
435
                || (hitspr->picnum == APLAYER && A_CheckEnemySprite(s)))
436
        {
437
            actor[iActor].flags |= SFLAG_NOFLOORSHADOW;  // No shadows on actors
438
            s->xvel = -256;
439
            A_SetSprite(iActor,CLIPMASK0);
5 Plagman 440
        }
4680 terminx 441
        else if (s->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && s->owner==lz)
1677 terminx 442
        {
443
            actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
444
            actor[iActor].floorz   = sector[s->sectnum].floorz;
445
        }
4680 terminx 446
    }
5 Plagman 447
}
448
 
1205 terminx 449
void A_Fall(int32_t iActor)
5 Plagman 450
{
432 terminx 451
    spritetype *s = &sprite[iActor];
1205 terminx 452
    int32_t hz,lz,c = g_spriteGravity;
1877 helixhorne 453
#ifdef YAX_ENABLE
454
    int16_t fbunch;
455
#endif
4680 terminx 456
    if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(s->sectnum)))
5 Plagman 457
        c = 0;
4680 terminx 458
    else if (sector[s->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(s->sectnum)))
459
        c = g_spriteGravity/6;
5 Plagman 460
 
1490 terminx 461
    if (s->statnum == STAT_ACTOR || s->statnum == STAT_PLAYER || s->statnum == STAT_ZOMBIEACTOR || s->statnum == STAT_STANDABLE)
1208 terminx 462
    {
1217 terminx 463
        int32_t cstat = s->cstat;
464
        s->cstat = 0;
1677 terminx 465
        s->z -= ZOFFSET;
1625 terminx 466
        getzrange((vec3_t *)s,s->sectnum,&actor[iActor].ceilingz,&hz,&actor[iActor].floorz,&lz,127L,CLIPMASK0);
1677 terminx 467
        s->z += ZOFFSET;
1217 terminx 468
        s->cstat = cstat;
1208 terminx 469
    }
5 Plagman 470
    else
471
    {
1625 terminx 472
        actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
473
        actor[iActor].floorz   = sector[s->sectnum].floorz;
5 Plagman 474
    }
475
 
1877 helixhorne 476
#ifdef YAX_ENABLE
4680 terminx 477
    fbunch = (sector[s->sectnum].floorstat&512) ? -1 : yax_getbunch(s->sectnum, YAX_FLOOR);
1877 helixhorne 478
#endif
3682 helixhorne 479
 
480
    if (s->z < actor[iActor].floorz-ZOFFSET
1877 helixhorne 481
#ifdef YAX_ENABLE
3682 helixhorne 482
            || fbunch >= 0
1877 helixhorne 483
#endif
2652 terminx 484
       )
5 Plagman 485
    {
3073 helixhorne 486
        if (sector[s->sectnum].lotag == ST_2_UNDERWATER && s->zvel > 3122)
5 Plagman 487
            s->zvel = 3144;
1181 terminx 488
        s->z += s->zvel = min(6144, s->zvel+c);
5 Plagman 489
    }
3682 helixhorne 490
 
1877 helixhorne 491
#ifdef YAX_ENABLE
492
    if (fbunch >= 0)
493
        setspritez(iActor, (vec3_t *)s);
3682 helixhorne 494
    else
1877 helixhorne 495
#endif
3682 helixhorne 496
        if (s->z >= actor[iActor].floorz-ZOFFSET)
2652 terminx 497
        {
3682 helixhorne 498
            s->z = actor[iActor].floorz-ZOFFSET;
2652 terminx 499
            s->zvel = 0;
500
        }
5 Plagman 501
}
502
 
1205 terminx 503
int32_t G_GetAngleDelta(int32_t a,int32_t na)
5 Plagman 504
{
505
    a &= 2047;
506
    na &= 2047;
507
 
331 terminx 508
    if (klabs(a-na) < 1024)
521 terminx 509
    {
1143 terminx 510
//        OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
5 Plagman 511
        return (na-a);
522 terminx 512
    }
5 Plagman 513
 
428 terminx 514
    if (na > 1024) na -= 2048;
515
    if (a > 1024) a -= 2048;
516
 
1143 terminx 517
//    OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
428 terminx 518
    return (na-a);
5 Plagman 519
}
520
 
3919 helixhorne 521
GAMEEXEC_STATIC void VM_AlterAng(int32_t movflags)
5 Plagman 522
{
3920 helixhorne 523
    const int32_t ticselapsed = (AC_COUNT(vm.g_t))&31;
5 Plagman 524
 
3459 helixhorne 525
#if !defined LUNATIC
2185 helixhorne 526
    const intptr_t *moveptr;
4680 terminx 527
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.g_t) >= (unsigned)g_scriptSize-1))
2451 helixhorne 528
 
1685 terminx 529
    {
3920 helixhorne 530
        AC_MOVE_ID(vm.g_t) = 0;
4763 hendricks2 531
        OSD_Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
1686 terminx 532
        return;
1685 terminx 533
    }
534
 
3920 helixhorne 535
    moveptr = script + AC_MOVE_ID(vm.g_t);
2185 helixhorne 536
 
4377 helixhorne 537
    vm.g_sp->xvel += (moveptr[0] - vm.g_sp->xvel)/5;
2864 helixhorne 538
    if (vm.g_sp->zvel < 648)
4377 helixhorne 539
        vm.g_sp->zvel += ((moveptr[1]<<4) - vm.g_sp->zvel)/5;
2724 helixhorne 540
#else
2864 helixhorne 541
    vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)/5;
542
    if (vm.g_sp->zvel < 648)
543
        vm.g_sp->zvel += ((actor[vm.g_i].mv.vvel<<4) - vm.g_sp->zvel)/5;
2724 helixhorne 544
#endif
5 Plagman 545
 
1204 terminx 546
    if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0) // hack
1171 terminx 547
        return;
548
 
3919 helixhorne 549
    if (movflags&seekplayer)
5 Plagman 550
    {
1205 terminx 551
        int32_t aang = vm.g_sp->ang, angdif, goalang;
4902 terminx 552
        int32_t j = vm.g_pp->holoduke_on;
1048 terminx 553
 
5 Plagman 554
        // NOTE: looks like 'owner' is set to target sprite ID...
555
 
1204 terminx 556
        if (j >= 0 && cansee(sprite[j].x,sprite[j].y,sprite[j].z,sprite[j].sectnum,vm.g_sp->x,vm.g_sp->y,vm.g_sp->z,vm.g_sp->sectnum))
557
            vm.g_sp->owner = j;
4902 terminx 558
        else vm.g_sp->owner = vm.g_pp->i;
5 Plagman 559
 
1204 terminx 560
        if (sprite[vm.g_sp->owner].picnum == APLAYER)
1625 terminx 561
            goalang = getangle(actor[vm.g_i].lastvx-vm.g_sp->x,actor[vm.g_i].lastvy-vm.g_sp->y);
5 Plagman 562
        else
1204 terminx 563
            goalang = getangle(sprite[vm.g_sp->owner].x-vm.g_sp->x,sprite[vm.g_sp->owner].y-vm.g_sp->y);
5 Plagman 564
 
1204 terminx 565
        if (vm.g_sp->xvel && vm.g_sp->picnum != DRONE)
5 Plagman 566
        {
1143 terminx 567
            angdif = G_GetAngleDelta(aang,goalang);
5 Plagman 568
 
331 terminx 569
            if (ticselapsed < 2)
5 Plagman 570
            {
333 terminx 571
                if (klabs(angdif) < 256)
5 Plagman 572
                {
1143 terminx 573
                    j = 128-(krand()&256);
1204 terminx 574
                    vm.g_sp->ang += j;
575
                    if (A_GetHitscanRange(vm.g_i) < 844)
576
                        vm.g_sp->ang -= j;
5 Plagman 577
                }
578
            }
1346 terminx 579
            else if (ticselapsed > 18 && ticselapsed < GAMETICSPERSEC) // choose
5 Plagman 580
            {
1204 terminx 581
                if (klabs(angdif>>2) < 128) vm.g_sp->ang = goalang;
582
                else vm.g_sp->ang += angdif>>2;
5 Plagman 583
            }
584
        }
1204 terminx 585
        else vm.g_sp->ang = goalang;
5 Plagman 586
    }
587
 
331 terminx 588
    if (ticselapsed < 1)
5 Plagman 589
    {
3919 helixhorne 590
        if (movflags&furthestdir)
5 Plagman 591
        {
1909 terminx 592
            vm.g_sp->ang = A_GetFurthestAngle(vm.g_i, 2);
4902 terminx 593
            vm.g_sp->owner = vm.g_pp->i;
5 Plagman 594
        }
595
 
3919 helixhorne 596
        if (movflags&fleeenemy)
1909 terminx 597
            vm.g_sp->ang = A_GetFurthestAngle(vm.g_i, 2);
5 Plagman 598
    }
599
}
600
 
4680 terminx 601
static inline void VM_AddAngle(int32_t shr, int32_t goalang)
2745 helixhorne 602
{
603
    int32_t angdif = G_GetAngleDelta(vm.g_sp->ang,goalang)>>shr;
604
 
605
    if ((angdif > -8 && angdif < 0) || (angdif < 8 && angdif > 0))
606
        angdif *= 2;
607
 
608
    vm.g_sp->ang += angdif;
609
}
610
 
3459 helixhorne 611
static void VM_FacePlayer(int32_t shr)
2745 helixhorne 612
{
613
    int32_t goalang;
614
 
4902 terminx 615
    if (vm.g_pp->newowner >= 0)
616
        goalang = getangle(vm.g_pp->opos.x-vm.g_sp->x, vm.g_pp->opos.y-vm.g_sp->y);
2745 helixhorne 617
    else
4902 terminx 618
        goalang = getangle(vm.g_pp->pos.x-vm.g_sp->x, vm.g_pp->pos.y-vm.g_sp->y);
2745 helixhorne 619
 
3459 helixhorne 620
    VM_AddAngle(shr, goalang);
2745 helixhorne 621
}
622
 
3666 helixhorne 623
////////// TROR get*zofslope //////////
624
// These rather belong into the engine.
625
 
4745 terminx 626
static int32_t VM_GetCeilZOfSlope(void)
3666 helixhorne 627
{
4745 terminx 628
    const int dax = vm.g_sp->x, day = vm.g_sp->y;
629
    const int sectnum = vm.g_sp->sectnum;
630
 
3666 helixhorne 631
#ifdef YAX_ENABLE
632
    if ((sector[sectnum].ceilingstat&512)==0)
633
    {
634
        int32_t nsect = yax_getneighborsect(dax, day, sectnum, YAX_CEILING);
635
        if (nsect >= 0)
636
            return getceilzofslope(nsect, dax, day);
637
    }
638
#endif
639
    return getceilzofslope(sectnum, dax, day);
640
}
641
 
4745 terminx 642
static int32_t VM_GetFlorZOfSlope(void)
3666 helixhorne 643
{
4745 terminx 644
    const int dax = vm.g_sp->x, day = vm.g_sp->y;
645
    const int sectnum = vm.g_sp->sectnum;
646
 
3666 helixhorne 647
#ifdef YAX_ENABLE
648
    if ((sector[sectnum].floorstat&512)==0)
649
    {
650
        int32_t nsect = yax_getneighborsect(dax, day, sectnum, YAX_FLOOR);
651
        if (nsect >= 0)
652
            return getflorzofslope(nsect, dax, day);
653
    }
654
#endif
655
    return getflorzofslope(sectnum, dax, day);
656
}
657
 
658
////////////////////
659
 
4955 helixhorne 660
static int32_t A_GetWaterZOffset(int spritenum);
661
 
1625 terminx 662
GAMEEXEC_STATIC void VM_Move(void)
5 Plagman 663
{
3459 helixhorne 664
#if !defined LUNATIC
2185 helixhorne 665
    const intptr_t *moveptr;
2724 helixhorne 666
#endif
3920 helixhorne 667
    // NOTE: commented out condition is dead since r3159 (making hi/lotag unsigned).
668
    // XXX: Does it break anything? Where are movflags with all bits set created?
3922 helixhorne 669
    const uint16_t *movflagsptr = &AC_MOVFLAGS(vm.g_sp, &actor[vm.g_i]);
670
    const int32_t movflags = /*(*movflagsptr==-1) ? 0 :*/ *movflagsptr;
3459 helixhorne 671
    const int32_t deadflag = (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0);
5 Plagman 672
 
3920 helixhorne 673
    AC_COUNT(vm.g_t)++;
5 Plagman 674
 
3920 helixhorne 675
    if (AC_MOVE_ID(vm.g_t) == 0 || movflags == 0)
1171 terminx 676
    {
3314 helixhorne 677
        if (deadflag || (actor[vm.g_i].bpos.x != vm.g_sp->x) || (actor[vm.g_i].bpos.y != vm.g_sp->y))
1171 terminx 678
        {
3314 helixhorne 679
            actor[vm.g_i].bpos.x = vm.g_sp->x;
680
            actor[vm.g_i].bpos.y = vm.g_sp->y;
2745 helixhorne 681
            setsprite(vm.g_i, (vec3_t *)vm.g_sp);
1171 terminx 682
        }
683
        return;
684
    }
685
 
3919 helixhorne 686
    if (deadflag)
687
        goto dead;
1909 terminx 688
 
3919 helixhorne 689
    if (movflags&face_player)
3459 helixhorne 690
        VM_FacePlayer(2);
5 Plagman 691
 
3919 helixhorne 692
    if (movflags&spin)
3920 helixhorne 693
        vm.g_sp->ang += sintable[((AC_COUNT(vm.g_t)<<3)&2047)]>>6;
5 Plagman 694
 
3919 helixhorne 695
    if (movflags&face_player_slow)
3459 helixhorne 696
        VM_FacePlayer(4);
5 Plagman 697
 
4378 helixhorne 698
    if ((movflags&jumptoplayer_bits) == jumptoplayer_bits)
5 Plagman 699
    {
3920 helixhorne 700
        if (AC_COUNT(vm.g_t) < 16)
701
            vm.g_sp->zvel -= (sintable[(512+(AC_COUNT(vm.g_t)<<4))&2047]>>5);
5 Plagman 702
    }
703
 
3919 helixhorne 704
    if (movflags&face_player_smart)
5 Plagman 705
    {
4902 terminx 706
        int32_t newx = vm.g_pp->pos.x + (vm.g_pp->vel.x/768);
707
        int32_t newy = vm.g_pp->pos.y + (vm.g_pp->vel.y/768);
3459 helixhorne 708
        int32_t goalang = getangle(newx-vm.g_sp->x,newy-vm.g_sp->y);
709
        VM_AddAngle(2, goalang);
5 Plagman 710
    }
711
 
1909 terminx 712
dead:
3459 helixhorne 713
#if !defined LUNATIC
4680 terminx 714
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.g_t) >= (unsigned)g_scriptSize-1))
1684 terminx 715
    {
3920 helixhorne 716
        AC_MOVE_ID(vm.g_t) = 0;
4763 hendricks2 717
        OSD_Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
1686 terminx 718
        return;
1685 terminx 719
    }
5 Plagman 720
 
3920 helixhorne 721
    moveptr = script + AC_MOVE_ID(vm.g_t);
2185 helixhorne 722
 
4377 helixhorne 723
    if (movflags&geth) vm.g_sp->xvel += ((moveptr[0])-vm.g_sp->xvel)>>1;
724
    if (movflags&getv) vm.g_sp->zvel += ((moveptr[1]<<4)-vm.g_sp->zvel)>>1;
2724 helixhorne 725
#else
3919 helixhorne 726
    if (movflags&geth) vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)>>1;
3924 helixhorne 727
    if (movflags&getv) vm.g_sp->zvel += (16*actor[vm.g_i].mv.vvel - vm.g_sp->zvel)>>1;
2724 helixhorne 728
#endif
1820 terminx 729
 
3919 helixhorne 730
    if (movflags&dodgebullet && !deadflag)
1204 terminx 731
        A_Dodge(vm.g_sp);
5 Plagman 732
 
1204 terminx 733
    if (vm.g_sp->picnum != APLAYER)
3919 helixhorne 734
        VM_AlterAng(movflags);
5 Plagman 735
 
3919 helixhorne 736
    if (vm.g_sp->xvel > -6 && vm.g_sp->xvel < 6)
737
        vm.g_sp->xvel = 0;
5 Plagman 738
 
4953 helixhorne 739
    int badguyp = A_CheckEnemySprite(vm.g_sp);
5 Plagman 740
 
1204 terminx 741
    if (vm.g_sp->xvel || vm.g_sp->zvel)
5 Plagman 742
    {
4745 terminx 743
        int32_t daxvel = vm.g_sp->xvel;
744
        int32_t angdif = vm.g_sp->ang;
2745 helixhorne 745
 
3919 helixhorne 746
        if (badguyp && vm.g_sp->picnum != ROTATEGUN)
5 Plagman 747
        {
1204 terminx 748
            if ((vm.g_sp->picnum == DRONE || vm.g_sp->picnum == COMMANDER) && vm.g_sp->extra > 0)
5 Plagman 749
            {
1204 terminx 750
                if (vm.g_sp->picnum == COMMANDER)
5 Plagman 751
                {
2745 helixhorne 752
                    int32_t l;
3663 helixhorne 753
                    // NOTE: COMMANDER updates both actor[].floorz and
754
                    // .ceilingz regardless of its zvel.
4745 terminx 755
                    actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
2745 helixhorne 756
                    if (vm.g_sp->z > l-(8<<8))
5 Plagman 757
                    {
2745 helixhorne 758
                        vm.g_sp->z = l-(8<<8);
1204 terminx 759
                        vm.g_sp->zvel = 0;
5 Plagman 760
                    }
761
 
4745 terminx 762
                    actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
3663 helixhorne 763
                    if (vm.g_sp->z < l+(80<<8))
5 Plagman 764
                    {
1204 terminx 765
                        vm.g_sp->z = l+(80<<8);
766
                        vm.g_sp->zvel = 0;
5 Plagman 767
                    }
768
                }
769
                else
770
                {
2745 helixhorne 771
                    int32_t l;
3663 helixhorne 772
                    // The DRONE updates either .floorz or .ceilingz, not both.
1204 terminx 773
                    if (vm.g_sp->zvel > 0)
5 Plagman 774
                    {
4745 terminx 775
                        actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
2745 helixhorne 776
                        if (vm.g_sp->z > l-(30<<8))
1204 terminx 777
                            vm.g_sp->z = l-(30<<8);
5 Plagman 778
                    }
779
                    else
780
                    {
4745 terminx 781
                        actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
3663 helixhorne 782
                        if (vm.g_sp->z < l+(50<<8))
5 Plagman 783
                        {
1204 terminx 784
                            vm.g_sp->z = l+(50<<8);
785
                            vm.g_sp->zvel = 0;
5 Plagman 786
                        }
787
                    }
788
                }
789
            }
1204 terminx 790
            else if (vm.g_sp->picnum != ORGANTIC)
5 Plagman 791
            {
4975 helixhorne 792
                int32_t l;
793
 
794
                // In Duke3D, all other actors don't update .floorz or
795
                // .ceilingz here. In EDuke32, they do.
796
 
4953 helixhorne 797
                if (vm.g_sp->zvel > 0)
5 Plagman 798
                {
4975 helixhorne 799
                    actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
800
                    if (vm.g_sp->z > l)
801
                        vm.g_sp->z = l;
4955 helixhorne 802
                    vm.g_sp->z += A_GetWaterZOffset(vm.g_i);
4953 helixhorne 803
                }
804
                else if (vm.g_sp->zvel < 0)
805
                {
4975 helixhorne 806
                    actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
3663 helixhorne 807
                    if (vm.g_sp->z < l+(66<<8))
5 Plagman 808
                    {
1204 terminx 809
                        vm.g_sp->z = l+(66<<8);
810
                        vm.g_sp->zvel >>= 1;
5 Plagman 811
                    }
812
                }
813
            }
814
 
1204 terminx 815
            if (vm.g_x < 960 && vm.g_sp->xrepeat > 16)
5 Plagman 816
            {
4745 terminx 817
                daxvel = -(1024 - vm.g_x);
4902 terminx 818
                angdif = getangle(vm.g_pp->pos.x - vm.g_sp->x, vm.g_pp->pos.y - vm.g_sp->y);
5 Plagman 819
 
1204 terminx 820
                if (vm.g_x < 512)
5 Plagman 821
                {
4902 terminx 822
                    vm.g_pp->vel.x = 0;
823
                    vm.g_pp->vel.y = 0;
5 Plagman 824
                }
825
                else
826
                {
4902 terminx 827
                    vm.g_pp->vel.x = mulscale16(vm.g_pp->vel.x, vm.g_pp->runspeed - 0x2000);
828
                    vm.g_pp->vel.y = mulscale16(vm.g_pp->vel.y, vm.g_pp->runspeed - 0x2000);
5 Plagman 829
                }
830
            }
1204 terminx 831
            else if (vm.g_sp->picnum != DRONE && vm.g_sp->picnum != SHARK && vm.g_sp->picnum != COMMANDER)
5 Plagman 832
            {
4902 terminx 833
                if (vm.g_pp->actorsqu == vm.g_i)
3920 helixhorne 834
                    return;
3102 terminx 835
 
4351 helixhorne 836
                if (!A_CheckSpriteFlags(vm.g_i, SFLAG_SMOOTHMOVE))
5 Plagman 837
                {
4745 terminx 838
                    if (AC_COUNT(vm.g_t) & 1)
3920 helixhorne 839
                        return;
3102 terminx 840
                    daxvel <<= 1;
5 Plagman 841
                }
842
            }
843
        }
4745 terminx 844
        else if (vm.g_sp->picnum == APLAYER)
845
            if (vm.g_sp->z < actor[vm.g_i].ceilingz+(32<<8))
846
                vm.g_sp->z = actor[vm.g_i].ceilingz+(32<<8);
5 Plagman 847
 
4745 terminx 848
        vec3_t tmpvect = { (daxvel * (sintable[(angdif + 512) & 2047])) >> 14,
849
                           (daxvel * (sintable[angdif & 2047])) >> 14, vm.g_sp->zvel };
1207 terminx 850
 
4745 terminx 851
        actor[vm.g_i].movflag =
4953 helixhorne 852
            A_MoveSprite(vm.g_i, &tmpvect, (A_CheckSpriteFlags(vm.g_i, SFLAG_NOCLIP) ? 0 : CLIPMASK0));
5 Plagman 853
    }
854
 
3919 helixhorne 855
    if (!badguyp)
2745 helixhorne 856
        return;
5 Plagman 857
 
4745 terminx 858
    vm.g_sp->shade += (sector[vm.g_sp->sectnum].ceilingstat & 1) ?
859
                      (sector[vm.g_sp->sectnum].ceilingshade - vm.g_sp->shade) >> 1 :
860
                      (sector[vm.g_sp->sectnum].floorshade - vm.g_sp->shade) >> 1;
5 Plagman 861
}
862
 
3520 helixhorne 863
static void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap)
2873 helixhorne 864
{
4699 terminx 865
    if ((ps->weaponswitch & (1|4)) == (1|4))
2975 hendricks2 866
    {
4226 helixhorne 867
        const int32_t snum = P_Get(ps->i);
4215 helixhorne 868
        int32_t i, new_wchoice = -1, curr_wchoice = -1;
2975 hendricks2 869
 
4215 helixhorne 870
        for (i=0; i<=FREEZE_WEAPON && (new_wchoice < 0 || curr_wchoice < 0); i++)
2975 hendricks2 871
        {
4215 helixhorne 872
            int32_t w = g_player[snum].wchoice[i];
2975 hendricks2 873
 
4215 helixhorne 874
            if (w == KNEE_WEAPON)
875
                w = FREEZE_WEAPON;
2975 hendricks2 876
            else w--;
877
 
878
            if (w == ps->curr_weapon)
879
                curr_wchoice = i;
880
            if (w == weap)
881
                new_wchoice = i;
882
        }
883
 
4216 helixhorne 884
        P_AddWeapon(ps, weap, (new_wchoice < curr_wchoice));
2975 hendricks2 885
    }
886
    else
4216 helixhorne 887
    {
888
        P_AddWeapon(ps, weap, (ps->weaponswitch & 1));
889
    }
2873 helixhorne 890
}
891
 
3520 helixhorne 892
#if defined LUNATIC
893
void P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap)
894
{
895
    P_AddWeaponMaybeSwitch(g_player[snum].ps, weap);
896
}
897
#else
3249 helixhorne 898
static void P_AddWeaponAmmoCommon(DukePlayer_t *ps, int32_t weap, int32_t amount)
2873 helixhorne 899
{
900
    P_AddAmmo(weap, ps, amount);
901
 
4650 terminx 902
    if (PWEAPON(vm.g_p, ps->curr_weapon, WorksLike) == KNEE_WEAPON && (ps->gotweapon & (1 << weap)))
3249 helixhorne 903
        P_AddWeaponMaybeSwitch(ps, weap);
2873 helixhorne 904
}
905
 
906
static int32_t VM_AddWeapon(int32_t weap, int32_t amount, DukePlayer_t *ps)
907
{
4699 terminx 908
    if (EDUKE32_PREDICT_FALSE((unsigned)weap >= MAX_WEAPONS))
2873 helixhorne 909
    {
3000 helixhorne 910
        CON_ERRPRINTF("Invalid weapon ID %d\n", weap);
2873 helixhorne 911
        return 1;
912
    }
913
 
914
    if ((ps->gotweapon & (1 << weap)) == 0)
915
    {
3249 helixhorne 916
        P_AddWeaponMaybeSwitch(ps, weap);
2873 helixhorne 917
    }
918
    else if (ps->ammo_amount[weap] >= ps->max_ammo_amount[weap])
919
    {
920
        vm.g_flags |= VM_NOEXECUTE;
921
        return 2;
922
    }
923
 
3249 helixhorne 924
    P_AddWeaponAmmoCommon(ps, weap, amount);
2873 helixhorne 925
 
926
    return 0;
927
}
3354 helixhorne 928
#endif
2873 helixhorne 929
 
4954 helixhorne 930
static int32_t A_GetVerticalVel(const actor_t *ac)
931
{
932
#ifdef LUNATIC
933
    return ac->mv.vvel;
934
#else
935
    int32_t moveScriptOfs = AC_MOVE_ID(ac->t_data);
936
 
937
    if ((unsigned)moveScriptOfs < (unsigned)g_scriptSize-1)
938
        return script[moveScriptOfs + 1];
939
    else
940
        return 0;
941
#endif
942
}
943
 
944
static int32_t A_GetWaterZOffset(int spritenum)
945
{
946
    const spritetype *const sp = &sprite[spritenum];
947
    const actor_t *const ac = &actor[spritenum];
948
 
949
    if (sector[sp->sectnum].lotag == ST_1_ABOVE_WATER)
950
    {
4956 helixhorne 951
        if (A_CheckSpriteFlags(spritenum, SFLAG_NOWATERDIP))
4954 helixhorne 952
            return 0;
953
 
954
        // fix for flying/jumping monsters getting stuck in water
955
        if ((AC_MOVFLAGS(sp, ac) & jumptoplayer_only) ||
956
            (G_HaveActor(sp->picnum) && A_GetVerticalVel(ac) != 0))
957
            return 0;
958
 
959
        return ACTOR_ONWATER_ADDZ;
960
    }
961
 
962
    return 0;
963
}
964
 
3460 helixhorne 965
static void VM_Fall(int32_t g_i, spritetype *g_sp)
3252 helixhorne 966
{
3684 helixhorne 967
    int32_t grav = g_spriteGravity;
968
 
3460 helixhorne 969
    g_sp->xoffset = g_sp->yoffset = 0;
3252 helixhorne 970
 
4680 terminx 971
    if (sector[g_sp->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(g_sp->sectnum)))
3684 helixhorne 972
        grav = g_spriteGravity/6;
4680 terminx 973
    else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(g_sp->sectnum)))
3684 helixhorne 974
        grav = 0;
975
 
976
    if (!actor[g_i].cgg-- || (sector[g_sp->sectnum].floorstat&2))
3252 helixhorne 977
    {
3684 helixhorne 978
        A_GetZLimits(g_i);
979
        actor[g_i].cgg = 3;
980
    }
3252 helixhorne 981
 
3684 helixhorne 982
    if (g_sp->z < actor[g_i].floorz-ZOFFSET)
983
    {
984
        // Free fall.
985
        g_sp->zvel = min(g_sp->zvel+grav, ACTOR_MAXFALLINGZVEL);
4953 helixhorne 986
        int32_t z = g_sp->z + g_sp->zvel;
987
 
3252 helixhorne 988
#ifdef YAX_ENABLE
3684 helixhorne 989
        if (yax_getbunch(g_sp->sectnum, YAX_FLOOR) >= 0 &&
990
                (sector[g_sp->sectnum].floorstat&512)==0)
991
            setspritez(g_i, (vec3_t *)g_sp);
992
        else
3252 helixhorne 993
#endif
4953 helixhorne 994
            if (z > actor[g_i].floorz - ZOFFSET)
995
                z = actor[g_i].floorz - ZOFFSET;
996
 
997
        g_sp->z = z;
3684 helixhorne 998
        return;
999
    }
3679 helixhorne 1000
 
4953 helixhorne 1001
    // Preliminary new z position of the actor.
1002
    int32_t z = actor[g_i].floorz - ZOFFSET;
3252 helixhorne 1003
 
3684 helixhorne 1004
    if (A_CheckEnemySprite(g_sp) || (g_sp->picnum == APLAYER && g_sp->owner >= 0))
1005
    {
1006
        if (g_sp->zvel > 3084 && g_sp->extra <= 1)
3252 helixhorne 1007
        {
3684 helixhorne 1008
            // I'm guessing this DRONE check is from a beta version of the game
1009
            // where they crashed into the ground when killed
1010
            if (!(g_sp->picnum == APLAYER && g_sp->extra > 0) && g_sp->pal != 1 && g_sp->picnum != DRONE)
3252 helixhorne 1011
            {
3684 helixhorne 1012
                A_DoGuts(g_i,JIBS6,15);
1013
                A_PlaySound(SQUISHED,g_i);
1014
                A_Spawn(g_i,BLOODPOOL);
3252 helixhorne 1015
            }
3679 helixhorne 1016
 
3684 helixhorne 1017
            actor[g_i].picnum = SHOTSPARK1;
1018
            actor[g_i].extra = 1;
1019
            g_sp->zvel = 0;
1020
        }
1021
        else if (g_sp->zvel > 2048 && sector[g_sp->sectnum].lotag != ST_1_ABOVE_WATER)
1022
        {
1023
            int16_t newsect = g_sp->sectnum;
3679 helixhorne 1024
 
3684 helixhorne 1025
            pushmove((vec3_t *)g_sp, &newsect, 128, 4<<8, 4<<8, CLIPMASK0);
1026
            if ((unsigned)newsect < MAXSECTORS)
1027
                changespritesect(g_i, newsect);
1028
 
1029
            A_PlaySound(THUD, g_i);
3252 helixhorne 1030
        }
1031
    }
1032
 
3684 helixhorne 1033
    if (sector[g_sp->sectnum].lotag == ST_1_ABOVE_WATER)
3252 helixhorne 1034
    {
4954 helixhorne 1035
        g_sp->z = z + A_GetWaterZOffset(g_i);
3252 helixhorne 1036
        return;
1037
    }
3459 helixhorne 1038
 
4953 helixhorne 1039
    g_sp->z = z;
3460 helixhorne 1040
    g_sp->zvel = 0;
3252 helixhorne 1041
}
1042
 
3460 helixhorne 1043
static int32_t VM_ResetPlayer(int32_t g_p, int32_t g_flags)
3252 helixhorne 1044
{
1045
    //AddLog("resetplayer");
3460 helixhorne 1046
    if (!g_netServer && ud.multimode < 2)
3252 helixhorne 1047
    {
1048
        if (g_lastSaveSlot >= 0 && ud.recstat != 2)
1049
        {
4738 hendricks2 1050
            M_OpenMenu(g_p);
3252 helixhorne 1051
            KB_ClearKeyDown(sc_Space);
4507 hendricks2 1052
            I_AdvanceTriggerClear();
4399 hendricks2 1053
            M_ChangeMenu(MENU_RESETPLAYER);
3252 helixhorne 1054
        }
3460 helixhorne 1055
        else g_player[g_p].ps->gm = MODE_RESTART;
3946 helixhorne 1056
#if !defined LUNATIC
3460 helixhorne 1057
        g_flags |= VM_NOEXECUTE;
3946 helixhorne 1058
#endif
3252 helixhorne 1059
    }
1060
    else
1061
    {
3460 helixhorne 1062
        if (g_p == myconnectindex)
3252 helixhorne 1063
        {
3405 helixhorne 1064
            CAMERADIST = 0;
1065
            CAMERACLOCK = totalclock;
3252 helixhorne 1066
        }
1067
 
1068
        if (g_fakeMultiMode)
3460 helixhorne 1069
            P_ResetPlayer(g_p);
3260 helixhorne 1070
#ifndef NETCODE_DISABLE
3252 helixhorne 1071
        if (g_netServer)
1072
        {
3460 helixhorne 1073
            P_ResetPlayer(g_p);
3994 terminx 1074
            Net_SpawnPlayer(g_p);
3252 helixhorne 1075
        }
3260 helixhorne 1076
#endif
3252 helixhorne 1077
    }
3460 helixhorne 1078
 
1079
    P_UpdateScreenPal(g_player[g_p].ps);
3252 helixhorne 1080
    //AddLog("EOF: resetplayer");
3460 helixhorne 1081
 
1082
    return g_flags;
3252 helixhorne 1083
}
1084
 
3486 helixhorne 1085
void G_GetTimeDate(int32_t *vals)
1086
{
1087
    time_t rawtime;
1088
    struct tm *ti;
1089
 
1090
    time(&rawtime);
1091
    ti=localtime(&rawtime);
1092
    // initprintf("Time&date: %s\n",asctime (ti));
1093
 
1094
    vals[0] = ti->tm_sec;
1095
    vals[1] = ti->tm_min;
1096
    vals[2] = ti->tm_hour;
1097
    vals[3] = ti->tm_mday;
1098
    vals[4] = ti->tm_mon;
1099
    vals[5] = ti->tm_year+1900;
1100
    vals[6] = ti->tm_wday;
1101
    vals[7] = ti->tm_yday;
1102
}
1103
 
3490 helixhorne 1104
int32_t G_StartTrack(int32_t level)
1105
{
1106
    if ((unsigned)level < MAXLEVELS)
1107
    {
1108
        int32_t musicIndex = MAXLEVELS*ud.volume_number + level;
1109
 
3542 helixhorne 1110
        if (MapInfo[musicIndex].musicfn != NULL)
3490 helixhorne 1111
        {
3542 helixhorne 1112
            // Only set g_musicIndex on success.
3490 helixhorne 1113
            g_musicIndex = musicIndex;
4948 hendricks2 1114
            S_PlayMusic(MapInfo[musicIndex].musicfn);
3490 helixhorne 1115
 
1116
            return 0;
1117
        }
1118
    }
1119
 
1120
    return 1;
1121
}
1122
 
3861 helixhorne 1123
LUNATIC_EXTERN void G_ShowView(int32_t x, int32_t y, int32_t z, int32_t a, int32_t horiz, int32_t sect,
1124
                               int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp)
1125
{
1126
    int32_t smoothratio = calc_smoothratio(totalclock, ototalclock);
1127
#ifdef USE_OPENGL
1128
    int32_t oprojhacks;
1129
#endif
1130
 
1131
    if (g_screenCapture)
1132
        return;
1133
 
1134
    if (offscreenrendering)
1135
    {
1136
        clearview(0);
1137
        return;
1138
    }
1139
 
1140
    if (x1 > x2) swaplong(&x1,&x2);
1141
    if (y1 > y2) swaplong(&y1,&y2);
1142
 
1143
    if (!unbiasedp)
1144
    {
1145
        // The showview command has a rounding bias towards zero,
1146
        // e.g. floor((319*1680)/320) == 1674
1147
        x1 = scale(x1,xdim,320);
1148
        y1 = scale(y1,ydim,200);
1149
        x2 = scale(x2,xdim,320);
1150
        y2 = scale(y2,ydim,200);
1151
    }
1152
    else
1153
    {
1154
        // This will map the maximum 320-based coordinate to the
1155
        // maximum real screen coordinate:
1156
        // floor((319*1679)/319) == 1679
1157
        x1 = scale(x1,xdim-1,319);
1158
        y1 = scale(y1,ydim-1,199);
1159
        x2 = scale(x2,xdim-1,319);
1160
        y2 = scale(y2,ydim-1,199);
1161
    }
1162
 
1163
    horiz = clamp(horiz, HORIZ_MIN, HORIZ_MAX);
1164
 
1165
#ifdef USE_OPENGL
1166
    oprojhacks = glprojectionhacks;
1167
    glprojectionhacks = 0;
1168
#endif
1169
    {
1170
        int32_t o = newaspect_enable;
1171
        newaspect_enable = r_usenewaspect;
1172
        setaspect_new_use_dimen = 1;
1173
 
1174
        setview(x1,y1,x2,y2);
1175
 
1176
        setaspect_new_use_dimen = 0;
1177
        newaspect_enable = o;
1178
    }
1179
 
1180
    G_DoInterpolations(smoothratio);
1181
 
1182
    G_HandleMirror(x, y, z, a, horiz, smoothratio);
1183
#ifdef POLYMER
1184
    if (getrendermode() == REND_POLYMER)
1185
        polymer_setanimatesprites(G_DoSpriteAnimations, x,y,a,smoothratio);
1186
#endif
1187
    yax_preparedrawrooms();
1188
    drawrooms(x,y,z,a,horiz,sect);
1189
    yax_drawrooms(G_DoSpriteAnimations, sect, 0, smoothratio);
1190
 
1191
    display_mirror = 2;
1192
    G_DoSpriteAnimations(x,y,a,smoothratio);
1193
    display_mirror = 0;
1194
    drawmasks();
1195
    G_RestoreInterpolations();
1196
    G_UpdateScreenArea();
1197
#ifdef USE_OPENGL
1198
    glprojectionhacks = oprojhacks;
1199
#endif
1200
}
1201
 
3410 helixhorne 1202
#if !defined LUNATIC
4745 terminx 1203
GAMEEXEC_STATIC void VM_Execute(int loop)
5 Plagman 1204
{
4745 terminx 1205
    int tw = *insptr;
4902 terminx 1206
    DukePlayer_t * const ps = vm.g_pp;
5 Plagman 1207
 
1458 terminx 1208
    // jump directly into the loop, saving us from the checks during the first iteration
1209
    goto skip_check;
1210
 
1909 terminx 1211
    while (loop)
1436 terminx 1212
    {
4745 terminx 1213
        if (vm.g_flags & (VM_RETURN | VM_KILL | VM_NOEXECUTE))
4902 terminx 1214
            break;
1458 terminx 1215
 
1436 terminx 1216
        tw = *insptr;
5 Plagman 1217
 
1458 terminx 1218
skip_check:
1436 terminx 1219
        //      Bsprintf(g_szBuf,"Parsing: %d",*insptr);
1220
        //      AddLog(g_szBuf);
871 hnt_ts 1221
 
1436 terminx 1222
        g_errorLineNum = tw>>12;
4902 terminx 1223
        g_tw = tw &= VM_INSTMASK;
1436 terminx 1224
 
4902 terminx 1225
        if (tw == CON_LEFTBRACE)
1226
        {
1227
            insptr++;
1228
            loop++;
1229
            continue;
1230
        }
1231
        else if (tw == CON_RIGHTBRACE)
1232
        {
1233
            loop--;
1234
            insptr++;
1235
            continue;
1236
        }
1237
        else if (tw == CON_ELSE)
1238
        {
1239
            insptr = (intptr_t *) *(insptr+1);
1240
            continue;
1241
        }
1242
        else if (tw == CON_STATE)
1243
        {
1244
            intptr_t * const tempscrptr = insptr + 2;
1245
            insptr = (intptr_t *)*(insptr + 1);
1246
            VM_Execute(1);
1247
            insptr = tempscrptr;
1248
            continue;
1249
        }
1250
 
1436 terminx 1251
        switch (tw)
430 terminx 1252
        {
4902 terminx 1253
        case CON_IFVARE:
1254
            insptr++;
1255
            tw = Gv_GetVarX(*insptr++);
1256
            VM_CONDITIONAL(tw == *insptr);
1257
            continue;
1258
 
1436 terminx 1259
        case CON_REDEFINEQUOTE:
1260
            insptr++;
484 terminx 1261
            {
1436 terminx 1262
                int32_t q = *insptr++, i = *insptr++;
4680 terminx 1263
                if (EDUKE32_PREDICT_FALSE((ScriptQuotes[q] == NULL || ScriptQuoteRedefinitions[i] == NULL)))
1436 terminx 1264
                {
3000 helixhorne 1265
                    CON_ERRPRINTF("%d %d null quote\n", q,i);
1436 terminx 1266
                    break;
1267
                }
1268
                Bstrcpy(ScriptQuotes[q],ScriptQuoteRedefinitions[i]);
1458 terminx 1269
                continue;
484 terminx 1270
            }
49 terminx 1271
 
1436 terminx 1272
        case CON_GETTHISPROJECTILE:
1273
        case CON_SETTHISPROJECTILE:
1274
            insptr++;
5 Plagman 1275
            {
1436 terminx 1276
                // syntax [gs]etplayer[<var>].x <VAR>
1277
                // <varid> <xxxid> <varid>
1278
                int32_t lVar1=*insptr++, lLabelID=*insptr++, lVar2=*insptr++;
5 Plagman 1279
 
1625 terminx 1280
                VM_AccessActiveProjectile(tw==CON_SETTHISPROJECTILE,lVar1,lLabelID,lVar2);
1458 terminx 1281
                continue;
337 terminx 1282
            }
1436 terminx 1283
 
1284
        case CON_IFRND:
1909 terminx 1285
            VM_CONDITIONAL(rnd(*(++insptr)));
1458 terminx 1286
            continue;
1436 terminx 1287
 
1288
        case CON_IFCANSHOOTTARGET:
1440 terminx 1289
        {
1290
            if (vm.g_x > 1024)
337 terminx 1291
            {
1909 terminx 1292
                int16_t temphit;
4902 terminx 1293
                int32_t j;
1436 terminx 1294
 
4902 terminx 1295
                if ((j = A_CheckHitSprite(vm.g_i, &temphit)) == (1 << 30))
1440 terminx 1296
                {
1909 terminx 1297
                    VM_CONDITIONAL(1);
1298
                    continue;
1440 terminx 1299
                }
1436 terminx 1300
 
4902 terminx 1301
                int32_t sclip = 768, angdif = 16;
1302
 
1303
                if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->xrepeat > 56)
1440 terminx 1304
                {
4902 terminx 1305
                    sclip = 3084;
1306
                    angdif = 48;
1307
                }
1909 terminx 1308
 
4902 terminx 1309
                if (j > sclip)
1310
                {
1311
                    if (temphit >= 0 && sprite[temphit].picnum == vm.g_sp->picnum)
1436 terminx 1312
                    {
4902 terminx 1313
                        VM_CONDITIONAL(0);
1314
                        continue;
1909 terminx 1315
                    }
1316
 
4902 terminx 1317
                    vm.g_sp->ang += angdif;
1318
                    j = A_CheckHitSprite(vm.g_i, &temphit);
1319
                    vm.g_sp->ang -= angdif;
1320
 
1909 terminx 1321
                    if (j > sclip)
1322
                    {
1323
                        if (temphit >= 0 && sprite[temphit].picnum == vm.g_sp->picnum)
1324
                        {
1325
                            VM_CONDITIONAL(0);
1326
                            continue;
1327
                        }
1328
 
4902 terminx 1329
                        vm.g_sp->ang -= angdif;
1330
                        j = A_CheckHitSprite(vm.g_i, &temphit);
1440 terminx 1331
                        vm.g_sp->ang += angdif;
1909 terminx 1332
 
4902 terminx 1333
                        if (j > 768)
5 Plagman 1334
                        {
1440 terminx 1335
                            if (temphit >= 0 && sprite[temphit].picnum == vm.g_sp->picnum)
5 Plagman 1336
                            {
1909 terminx 1337
                                VM_CONDITIONAL(0);
1338
                                continue;
1339
                            }
1340
 
4902 terminx 1341
                            VM_CONDITIONAL(1);
1342
                            continue;
5 Plagman 1343
                        }
1344
                    }
1345
                }
1346
            }
1909 terminx 1347
            VM_CONDITIONAL(1);
1440 terminx 1348
        }
1458 terminx 1349
        continue;
1440 terminx 1350
 
1436 terminx 1351
        case CON_IFCANSEETARGET:
4902 terminx 1352
            tw = cansee(vm.g_sp->x, vm.g_sp->y, vm.g_sp->z-((krand()&41)<<8),
2875 helixhorne 1353
                               vm.g_sp->sectnum, ps->pos.x, ps->pos.y,
1354
                               ps->pos.z/*-((krand()&41)<<8)*/, sprite[ps->i].sectnum);
4902 terminx 1355
            VM_CONDITIONAL(tw);
1356
            if (tw) actor[vm.g_i].timetosleep = SLEEPTIME;
1458 terminx 1357
        continue;
51 terminx 1358
 
1436 terminx 1359
        case CON_IFACTORNOTSTAYPUT:
1909 terminx 1360
            VM_CONDITIONAL(actor[vm.g_i].actorstayput == -1);
1458 terminx 1361
            continue;
5 Plagman 1362
 
1436 terminx 1363
        case CON_IFCANSEE:
1440 terminx 1364
        {
2875 helixhorne 1365
            spritetype *s = &sprite[ps->i];
1440 terminx 1366
            int32_t j;
1367
 
1368
            // select sprite for monster to target
1369
            // if holoduke is on, let them target holoduke first.
1370
            //
2875 helixhorne 1371
            if (ps->holoduke_on >= 0)
1436 terminx 1372
            {
2875 helixhorne 1373
                s = &sprite[ps->holoduke_on];
1440 terminx 1374
                j = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z-(krand()&((32<<8)-1)),vm.g_sp->sectnum,
1375
                           s->x,s->y,s->z,s->sectnum);
51 terminx 1376
 
1440 terminx 1377
                if (j == 0)
1436 terminx 1378
                {
1440 terminx 1379
                    // they can't see player's holoduke
1380
                    // check for player...
2875 helixhorne 1381
                    s = &sprite[ps->i];
1436 terminx 1382
                }
1440 terminx 1383
            }
5 Plagman 1384
 
1440 terminx 1385
            // can they see player, (or player's holoduke)
1386
            j = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z-(krand()&((47<<8))),vm.g_sp->sectnum,
1387
                       s->x,s->y,s->z-(24<<8),s->sectnum);
5 Plagman 1388
 
1440 terminx 1389
            if (j == 0)
1390
            {
1625 terminx 1391
                // search around for target player
5 Plagman 1392
 
1625 terminx 1393
                // also modifies 'target' x&y if found..
337 terminx 1394
 
1625 terminx 1395
                j = 1;
1396
                if (A_FurthestVisiblePoint(vm.g_i,s,&actor[vm.g_i].lastvx,&actor[vm.g_i].lastvy) == -1)
1397
                    j = 0;
1440 terminx 1398
            }
1399
            else
1400
            {
1401
                // else, they did see it.
1402
                // save where we were looking...
1625 terminx 1403
                actor[vm.g_i].lastvx = s->x;
1404
                actor[vm.g_i].lastvy = s->y;
1440 terminx 1405
            }
5 Plagman 1406
 
1487 terminx 1407
            if (j && (vm.g_sp->statnum == STAT_ACTOR || vm.g_sp->statnum == STAT_STANDABLE))
1625 terminx 1408
                actor[vm.g_i].timetosleep = SLEEPTIME;
1436 terminx 1409
 
1909 terminx 1410
            VM_CONDITIONAL(j);
1458 terminx 1411
            continue;
1440 terminx 1412
        }
335 terminx 1413
 
1436 terminx 1414
        case CON_IFHITWEAPON:
1909 terminx 1415
            VM_CONDITIONAL(A_IncurDamage(vm.g_i) >= 0);
1458 terminx 1416
            continue;
335 terminx 1417
 
1436 terminx 1418
        case CON_IFSQUISHED:
1909 terminx 1419
            VM_CONDITIONAL(VM_CheckSquished());
1458 terminx 1420
            continue;
335 terminx 1421
 
1436 terminx 1422
        case CON_IFDEAD:
1909 terminx 1423
            VM_CONDITIONAL(vm.g_sp->extra <= 0);
1458 terminx 1424
            continue;
335 terminx 1425
 
1436 terminx 1426
        case CON_AI:
1427
            insptr++;
1428
            //Following changed to use pointersizes
3920 helixhorne 1429
            AC_AI_ID(vm.g_t) = *insptr++; // Ai
2451 helixhorne 1430
 
3920 helixhorne 1431
            AC_ACTION_ID(vm.g_t) = *(script + AC_AI_ID(vm.g_t));  // Action
3456 helixhorne 1432
 
3920 helixhorne 1433
            // NOTE: "if" check added in r1155. It used to be a pointer though.
1434
            if (AC_AI_ID(vm.g_t))
1435
                AC_MOVE_ID(vm.g_t) = *(script + AC_AI_ID(vm.g_t) + 1);  // move
2451 helixhorne 1436
 
3920 helixhorne 1437
            vm.g_sp->hitag = *(script + AC_AI_ID(vm.g_t) + 2);  // move flags
1438
 
1439
            AC_COUNT(vm.g_t) = AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
1440
 
2709 helixhorne 1441
            if (!A_CheckEnemySprite(vm.g_sp) || vm.g_sp->extra > 0) // hack
1442
                if (vm.g_sp->hitag&random_angle)
1443
                    vm.g_sp->ang = krand()&2047;
1458 terminx 1444
            continue;
5 Plagman 1445
 
1436 terminx 1446
        case CON_ACTION:
1447
            insptr++;
3920 helixhorne 1448
            AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
1449
            AC_ACTION_ID(vm.g_t) = *insptr++;
1458 terminx 1450
            continue;
5 Plagman 1451
 
3803 terminx 1452
        case CON_IFPLAYERSL:
1453
            VM_CONDITIONAL(numplayers < *(++insptr));
1454
            continue;
1455
 
1436 terminx 1456
        case CON_IFPDISTL:
1909 terminx 1457
            VM_CONDITIONAL(vm.g_x < *(++insptr));
1625 terminx 1458
            if (vm.g_x > MAXSLEEPDIST && actor[vm.g_i].timetosleep == 0)
1459
                actor[vm.g_i].timetosleep = SLEEPTIME;
1458 terminx 1460
            continue;
5 Plagman 1461
 
1436 terminx 1462
        case CON_IFPDISTG:
1909 terminx 1463
            VM_CONDITIONAL(vm.g_x > *(++insptr));
1625 terminx 1464
            if (vm.g_x > MAXSLEEPDIST && actor[vm.g_i].timetosleep == 0)
1465
                actor[vm.g_i].timetosleep = SLEEPTIME;
1458 terminx 1466
            continue;
51 terminx 1467
 
1436 terminx 1468
        case CON_ADDSTRENGTH:
1469
            insptr++;
1470
            vm.g_sp->extra += *insptr++;
1458 terminx 1471
            continue;
51 terminx 1472
 
1436 terminx 1473
        case CON_STRENGTH:
1474
            insptr++;
1475
            vm.g_sp->extra = *insptr++;
1458 terminx 1476
            continue;
51 terminx 1477
 
1436 terminx 1478
        case CON_IFGOTWEAPONCE:
1479
            insptr++;
5 Plagman 1480
 
1587 terminx 1481
            if ((GametypeFlags[ud.coop]&GAMETYPE_WEAPSTAY) && (g_netServer || ud.multimode > 1))
5 Plagman 1482
            {
1436 terminx 1483
                if (*insptr == 0)
1484
                {
1485
                    int32_t j = 0;
2875 helixhorne 1486
                    for (; j < ps->weapreccnt; j++)
1487
                        if (ps->weaprecs[j] == vm.g_sp->picnum)
1436 terminx 1488
                            break;
5 Plagman 1489
 
2875 helixhorne 1490
                    VM_CONDITIONAL(j < ps->weapreccnt && vm.g_sp->owner == vm.g_i);
1625 terminx 1491
                    continue;
1436 terminx 1492
                }
2875 helixhorne 1493
                else if (ps->weapreccnt < MAX_WEAPONS)
1436 terminx 1494
                {
2875 helixhorne 1495
                    ps->weaprecs[ps->weapreccnt++] = vm.g_sp->picnum;
1909 terminx 1496
                    VM_CONDITIONAL(vm.g_sp->owner == vm.g_i);
1625 terminx 1497
                    continue;
1436 terminx 1498
                }
5 Plagman 1499
            }
1909 terminx 1500
            VM_CONDITIONAL(0);
1458 terminx 1501
            continue;
1436 terminx 1502
 
1503
        case CON_GETLASTPAL:
1504
            insptr++;
1505
            if (vm.g_sp->picnum == APLAYER)
4226 helixhorne 1506
                vm.g_sp->pal = g_player[P_GetP(vm.g_sp)].ps->palookup;
1436 terminx 1507
            else
337 terminx 1508
            {
1436 terminx 1509
                if (vm.g_sp->pal == 1 && vm.g_sp->extra == 0) // hack for frozen
1510
                    vm.g_sp->extra++;
1625 terminx 1511
                vm.g_sp->pal = actor[vm.g_i].tempang;
337 terminx 1512
            }
1625 terminx 1513
            actor[vm.g_i].tempang = 0;
1458 terminx 1514
            continue;
51 terminx 1515
 
1436 terminx 1516
        case CON_TOSSWEAPON:
1517
            insptr++;
4227 helixhorne 1518
            // NOTE: assumes that current actor is APLAYER
1519
            P_DropWeapon(P_GetP(vm.g_sp));
1458 terminx 1520
            continue;
51 terminx 1521
 
1436 terminx 1522
        case CON_MIKESND:
1837 terminx 1523
            insptr++;
4680 terminx 1524
            if (EDUKE32_PREDICT_FALSE(((unsigned)vm.g_sp->yvel >= MAXSOUNDS)))
1436 terminx 1525
            {
3238 hendricks2 1526
                CON_ERRPRINTF("Invalid sound %d\n", TrackerCast(vm.g_sp->yvel));
1458 terminx 1527
                continue;
1436 terminx 1528
            }
1461 terminx 1529
            if (!S_CheckSoundPlaying(vm.g_i,vm.g_sp->yvel))
1436 terminx 1530
                A_PlaySound(vm.g_sp->yvel,vm.g_i);
1458 terminx 1531
            continue;
51 terminx 1532
 
1436 terminx 1533
        case CON_PKICK:
951 hnt_ts 1534
            insptr++;
1436 terminx 1535
 
1587 terminx 1536
            if ((g_netServer || ud.multimode > 1) && vm.g_sp->picnum == APLAYER)
1436 terminx 1537
            {
1538
                if (g_player[otherp].ps->quick_kick == 0)
1539
                    g_player[otherp].ps->quick_kick = 14;
1540
            }
4902 terminx 1541
            else if (vm.g_sp->picnum != APLAYER && ps->quick_kick == 0)
1542
                ps->quick_kick = 14;
1458 terminx 1543
            continue;
51 terminx 1544
 
1436 terminx 1545
        case CON_SIZETO:
1546
            insptr++;
5 Plagman 1547
 
4902 terminx 1548
            tw = (*insptr++ - vm.g_sp->xrepeat)<<1;
1549
            vm.g_sp->xrepeat += ksgn(tw);
1550
 
1551
            if ((vm.g_sp->picnum == APLAYER && vm.g_sp->yrepeat < 36) || *insptr < vm.g_sp->yrepeat ||
1552
                    ((vm.g_sp->yrepeat*(tilesiz[vm.g_sp->picnum].y+8))<<2) < (actor[vm.g_i].floorz - actor[vm.g_i].ceilingz))
1436 terminx 1553
            {
4902 terminx 1554
                tw = ((*insptr)-vm.g_sp->yrepeat)<<1;
1555
                if (klabs(tw)) vm.g_sp->yrepeat += ksgn(tw);
1556
            }
51 terminx 1557
 
1436 terminx 1558
            insptr++;
5 Plagman 1559
 
1458 terminx 1560
            continue;
5 Plagman 1561
 
1436 terminx 1562
        case CON_SIZEAT:
1563
            insptr++;
1564
            vm.g_sp->xrepeat = (uint8_t) *insptr++;
1565
            vm.g_sp->yrepeat = (uint8_t) *insptr++;
1458 terminx 1566
            continue;
1436 terminx 1567
 
1568
        case CON_SHOOT:
1569
            insptr++;
1570
            A_Shoot(vm.g_i,*insptr++);
1458 terminx 1571
            continue;
1436 terminx 1572
 
1573
        case CON_SOUNDONCE:
4680 terminx 1574
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1215 terminx 1575
            {
3000 helixhorne 1576
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr++);
1458 terminx 1577
                continue;
1215 terminx 1578
            }
1461 terminx 1579
            if (!S_CheckSoundPlaying(vm.g_i,*insptr++))
1436 terminx 1580
                A_PlaySound(*(insptr-1),vm.g_i);
1458 terminx 1581
            continue;
62 terminx 1582
 
1461 terminx 1583
        case CON_IFACTORSOUND:
1584
            insptr++;
1585
            {
1586
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
1587
 
4680 terminx 1588
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSOUNDS))
1461 terminx 1589
                {
3000 helixhorne 1590
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1461 terminx 1591
                    insptr++;
1592
                    continue;
1593
                }
1594
                insptr--;
1909 terminx 1595
                VM_CONDITIONAL(A_CheckSoundPlaying(i,j));
1461 terminx 1596
            }
1597
            continue;
1598
 
1436 terminx 1599
        case CON_IFSOUND:
4680 terminx 1600
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1436 terminx 1601
            {
3000 helixhorne 1602
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1436 terminx 1603
                insptr++;
1458 terminx 1604
                continue;
1436 terminx 1605
            }
1909 terminx 1606
            VM_CONDITIONAL(S_CheckSoundPlaying(vm.g_i,*insptr));
2442 helixhorne 1607
            //    VM_DoConditional(SoundOwner[*insptr][0].ow == vm.g_i);
1458 terminx 1608
            continue;
51 terminx 1609
 
1436 terminx 1610
        case CON_STOPSOUND:
4680 terminx 1611
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1436 terminx 1612
            {
3000 helixhorne 1613
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1458 terminx 1614
                insptr++;
1615
                continue;
1436 terminx 1616
            }
1461 terminx 1617
            if (S_CheckSoundPlaying(vm.g_i,*insptr))
1465 terminx 1618
                S_StopSound((int16_t)*insptr);
1436 terminx 1619
            insptr++;
1458 terminx 1620
            continue;
51 terminx 1621
 
1461 terminx 1622
        case CON_STOPACTORSOUND:
1623
            insptr++;
1624
            {
1625
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
1626
 
4680 terminx 1627
                if (EDUKE32_PREDICT_FALSE((unsigned)j>=MAXSOUNDS))
1461 terminx 1628
                {
3000 helixhorne 1629
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1461 terminx 1630
                    continue;
1631
                }
1632
 
1633
                if (A_CheckSoundPlaying(i,j))
1634
                    S_StopEnvSound(j,i);
1635
 
1636
                continue;
1637
            }
1638
 
2104 helixhorne 1639
        case CON_SETACTORSOUNDPITCH:
1640
            insptr++;
1641
            {
1642
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++), pitchoffset = Gv_GetVarX(*insptr++);
1643
 
4680 terminx 1644
                if (EDUKE32_PREDICT_FALSE((unsigned)j>=MAXSOUNDS))
2104 helixhorne 1645
                {
3000 helixhorne 1646
                    CON_ERRPRINTF("Invalid sound %d\n", j);
2104 helixhorne 1647
                    continue;
1648
                }
1649
 
1650
                S_ChangeSoundPitch(j,i,pitchoffset);
1651
 
1652
                continue;
1653
            }
1654
 
1436 terminx 1655
        case CON_GLOBALSOUND:
4680 terminx 1656
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1436 terminx 1657
            {
3000 helixhorne 1658
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1458 terminx 1659
                insptr++;
1660
                continue;
1436 terminx 1661
            }
2890 helixhorne 1662
            if (vm.g_p == screenpeek || (GametypeFlags[ud.coop]&GAMETYPE_COOPSOUND)
4249 hendricks2 1663
#ifdef SPLITSCREEN_MOD_HACKS
2957 helixhorne 1664
                || (g_fakeMultiMode==2)
4249 hendricks2 1665
#endif
2890 helixhorne 1666
                )
1461 terminx 1667
                A_PlaySound(*insptr,g_player[screenpeek].ps->i);
1436 terminx 1668
            insptr++;
1458 terminx 1669
            continue;
51 terminx 1670
 
1436 terminx 1671
        case CON_SOUND:
4680 terminx 1672
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1436 terminx 1673
            {
3000 helixhorne 1674
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1458 terminx 1675
                insptr++;
1676
                continue;
1436 terminx 1677
            }
1461 terminx 1678
            A_PlaySound(*insptr++,vm.g_i);
1458 terminx 1679
            continue;
51 terminx 1680
 
1436 terminx 1681
        case CON_TIP:
1215 terminx 1682
            insptr++;
4902 terminx 1683
            ps->tipincs = GAMETICSPERSEC;
1458 terminx 1684
            continue;
51 terminx 1685
 
1436 terminx 1686
        case CON_FALL:
1687
            insptr++;
3460 helixhorne 1688
            VM_Fall(vm.g_i, vm.g_sp);
1458 terminx 1689
            continue;
1021 terminx 1690
 
1436 terminx 1691
        case CON_RETURN:
1625 terminx 1692
            vm.g_flags |= VM_RETURN;
1436 terminx 1693
        case CON_ENDA:
1694
        case CON_BREAK:
1695
        case CON_ENDS:
1909 terminx 1696
            return;
4699 terminx 1697
        case CON_NULLOP:
1436 terminx 1698
            insptr++;
4699 terminx 1699
            continue;
2873 helixhorne 1700
 
1436 terminx 1701
        case CON_ADDAMMO:
2873 helixhorne 1702
            insptr++;
532 terminx 1703
            {
2873 helixhorne 1704
                int32_t weap=*insptr++, amount=*insptr++;
1705
 
4680 terminx 1706
                if (EDUKE32_PREDICT_FALSE((unsigned)weap >= MAX_WEAPONS))
2873 helixhorne 1707
                {
3000 helixhorne 1708
                    CON_ERRPRINTF("Invalid weapon ID %d\n", weap);
2873 helixhorne 1709
                    break;
1710
                }
1711
 
1712
                if (ps->ammo_amount[weap] >= ps->max_ammo_amount[weap])
1713
                {
1714
                    vm.g_flags |= VM_NOEXECUTE;
4745 terminx 1715
                    return;
2873 helixhorne 1716
                }
1717
 
3249 helixhorne 1718
                P_AddWeaponAmmoCommon(ps, weap, amount);
2873 helixhorne 1719
 
1720
                continue;
1436 terminx 1721
            }
337 terminx 1722
 
1436 terminx 1723
        case CON_MONEY:
1724
            insptr++;
1725
            A_SpawnMultiple(vm.g_i, MONEY, *insptr++);
1458 terminx 1726
            continue;
51 terminx 1727
 
1436 terminx 1728
        case CON_MAIL:
1729
            insptr++;
1730
            A_SpawnMultiple(vm.g_i, MAIL, *insptr++);
1458 terminx 1731
            continue;
51 terminx 1732
 
1436 terminx 1733
        case CON_SLEEPTIME:
1734
            insptr++;
1625 terminx 1735
            actor[vm.g_i].timetosleep = (int16_t)*insptr++;
1458 terminx 1736
            continue;
51 terminx 1737
 
1436 terminx 1738
        case CON_PAPER:
1739
            insptr++;
1740
            A_SpawnMultiple(vm.g_i, PAPER, *insptr++);
1458 terminx 1741
            continue;
51 terminx 1742
 
1436 terminx 1743
        case CON_ADDKILLS:
1744
            insptr++;
4902 terminx 1745
            ps->actors_killed += *insptr++;
1625 terminx 1746
            actor[vm.g_i].actorstayput = -1;
1458 terminx 1747
            continue;
51 terminx 1748
 
1436 terminx 1749
        case CON_LOTSOFGLASS:
1750
            insptr++;
1751
            A_SpawnGlass(vm.g_i,*insptr++);
1458 terminx 1752
            continue;
51 terminx 1753
 
1436 terminx 1754
        case CON_KILLIT:
1755
            insptr++;
1625 terminx 1756
            vm.g_flags |= VM_KILL;
4745 terminx 1757
            return;
51 terminx 1758
 
1436 terminx 1759
        case CON_ADDWEAPON:
2873 helixhorne 1760
            insptr++;
1436 terminx 1761
            {
2873 helixhorne 1762
                int32_t weap=*insptr++, amount=*insptr++;
4902 terminx 1763
                VM_AddWeapon(weap, amount, ps);
2873 helixhorne 1764
 
1458 terminx 1765
                continue;
1436 terminx 1766
            }
337 terminx 1767
 
1436 terminx 1768
        case CON_DEBUG:
1769
            insptr++;
2419 hendricks2 1770
            initprintf("%" PRIdPTR "\n",*insptr++);
1458 terminx 1771
            continue;
51 terminx 1772
 
1436 terminx 1773
        case CON_ENDOFGAME:
3803 terminx 1774
        case CON_ENDOFLEVEL:
1436 terminx 1775
            insptr++;
4902 terminx 1776
            ps->timebeforeexit = *insptr++;
1777
            ps->customexitsound = -1;
1436 terminx 1778
            ud.eog = 1;
1458 terminx 1779
            continue;
51 terminx 1780
 
1436 terminx 1781
        case CON_ADDPHEALTH:
1782
            insptr++;
51 terminx 1783
 
335 terminx 1784
            {
1436 terminx 1785
                int32_t j;
1215 terminx 1786
 
2875 helixhorne 1787
                if (ps->newowner >= 0)
1788
                    G_ClearCameraView(ps);
1436 terminx 1789
 
2875 helixhorne 1790
                j = sprite[ps->i].extra;
5 Plagman 1791
 
1436 terminx 1792
                if (vm.g_sp->picnum != ATOMICHEALTH)
1215 terminx 1793
                {
2875 helixhorne 1794
                    if (j > ps->max_player_health && *insptr > 0)
1436 terminx 1795
                    {
1796
                        insptr++;
1458 terminx 1797
                        continue;
1436 terminx 1798
                    }
1799
                    else
1800
                    {
1801
                        if (j > 0)
1802
                            j += *insptr;
2875 helixhorne 1803
                        if (j > ps->max_player_health && *insptr > 0)
1804
                            j = ps->max_player_health;
1436 terminx 1805
                    }
1215 terminx 1806
                }
1807
                else
1808
                {
1809
                    if (j > 0)
1810
                        j += *insptr;
2875 helixhorne 1811
                    if (j > (ps->max_player_health<<1))
1812
                        j = (ps->max_player_health<<1);
1215 terminx 1813
                }
5 Plagman 1814
 
1436 terminx 1815
                if (j < 0) j = 0;
5 Plagman 1816
 
1436 terminx 1817
                if (ud.god == 0)
1215 terminx 1818
                {
1436 terminx 1819
                    if (*insptr > 0)
1820
                    {
2875 helixhorne 1821
                        if ((j - *insptr) < (ps->max_player_health>>2) &&
1822
                                j >= (ps->max_player_health>>2))
1823
                            A_PlaySound(DUKE_GOTHEALTHATLOW,ps->i);
5 Plagman 1824
 
2875 helixhorne 1825
                        ps->last_extra = j;
1436 terminx 1826
                    }
1827
 
2875 helixhorne 1828
                    sprite[ps->i].extra = j;
1215 terminx 1829
                }
5 Plagman 1830
            }
1831
 
1436 terminx 1832
            insptr++;
1458 terminx 1833
            continue;
51 terminx 1834
 
1436 terminx 1835
        case CON_MOVE:
1836
            insptr++;
3920 helixhorne 1837
            AC_COUNT(vm.g_t) = 0;
1838
            AC_MOVE_ID(vm.g_t) = *insptr++;
1436 terminx 1839
            vm.g_sp->hitag = *insptr++;
1840
            if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0) // hack
1458 terminx 1841
                continue;
1436 terminx 1842
            if (vm.g_sp->hitag&random_angle)
1843
                vm.g_sp->ang = krand()&2047;
1458 terminx 1844
            continue;
5 Plagman 1845
 
1436 terminx 1846
        case CON_ADDWEAPONVAR:
1847
            insptr++;
484 terminx 1848
            {
2873 helixhorne 1849
                int32_t weap=Gv_GetVarX(*insptr++), amount=Gv_GetVarX(*insptr++);
4902 terminx 1850
                VM_AddWeapon(weap, amount, ps);
1458 terminx 1851
                continue;
484 terminx 1852
            }
335 terminx 1853
 
1436 terminx 1854
        case CON_ACTIVATEBYSECTOR:
1855
        case CON_OPERATESECTORS:
1856
        case CON_OPERATEACTIVATORS:
1857
        case CON_SETASPECT:
1858
        case CON_SSP:
1859
            insptr++;
1860
            {
1861
                int32_t var1 = Gv_GetVarX(*insptr++), var2;
1862
                if (tw == CON_OPERATEACTIVATORS && *insptr == g_iThisActorID)
1863
                {
1864
                    var2 = vm.g_p;
1865
                    insptr++;
1866
                }
1867
                else var2 = Gv_GetVarX(*insptr++);
335 terminx 1868
 
1436 terminx 1869
                switch (tw)
1870
                {
1871
                case CON_ACTIVATEBYSECTOR:
4680 terminx 1872
                    if (EDUKE32_PREDICT_FALSE((unsigned)var1 >= (unsigned)numsectors))
1873
                    {
1874
                        CON_ERRPRINTF("Invalid sector %d\n", var1);
1875
                        break;
1876
                    }
1802 terminx 1877
                    G_ActivateBySector(var1, var2);
1436 terminx 1878
                    break;
1879
                case CON_OPERATESECTORS:
4680 terminx 1880
                    if (EDUKE32_PREDICT_FALSE((unsigned)var1 >= (unsigned)numsectors))
1881
                    {
1882
                        CON_ERRPRINTF("Invalid sector %d\n", var1);
1883
                        break;
1884
                    }
1436 terminx 1885
                    G_OperateSectors(var1, var2);
1886
                    break;
1887
                case CON_OPERATEACTIVATORS:
4680 terminx 1888
                    if (EDUKE32_PREDICT_FALSE((unsigned)var2>=(unsigned)playerswhenstarted))
1889
                    {
1890
                        CON_ERRPRINTF("Invalid player %d\n", var2);
1891
                        break;
1892
                    }
1436 terminx 1893
                    G_OperateActivators(var1, var2);
1894
                    break;
1895
                case CON_SETASPECT:
1896
                    setaspect(var1, var2);
1897
                    break;
1898
                case CON_SSP:
4680 terminx 1899
                    if (EDUKE32_PREDICT_FALSE((unsigned)var1 >= MAXSPRITES))
1900
                    {
1901
                        CON_ERRPRINTF("Invalid sprite %d\n", var1);
1902
                        break;
1903
                    }
1436 terminx 1904
                    A_SetSprite(var1, var2);
1905
                    break;
1906
                }
1458 terminx 1907
                continue;
967 terminx 1908
            }
892 hnt_ts 1909
 
1436 terminx 1910
        case CON_CANSEESPR:
1911
            insptr++;
1912
            {
1913
                int32_t lVar1 = Gv_GetVarX(*insptr++), lVar2 = Gv_GetVarX(*insptr++), res;
106 terminx 1914
 
4680 terminx 1915
                if (EDUKE32_PREDICT_FALSE((unsigned)lVar1 >= MAXSPRITES || (unsigned)lVar2 >= MAXSPRITES))
1436 terminx 1916
                {
3000 helixhorne 1917
                    CON_ERRPRINTF("Invalid sprite %d\n", (unsigned)lVar1 >= MAXSPRITES ? lVar1 : lVar2);
1436 terminx 1918
                    res=0;
1919
                }
1920
                else res=cansee(sprite[lVar1].x,sprite[lVar1].y,sprite[lVar1].z,sprite[lVar1].sectnum,
1440 terminx 1921
                                    sprite[lVar2].x,sprite[lVar2].y,sprite[lVar2].z,sprite[lVar2].sectnum);
106 terminx 1922
 
1436 terminx 1923
                Gv_SetVarX(*insptr++, res);
1458 terminx 1924
                continue;
1436 terminx 1925
            }
1926
 
1927
        case CON_OPERATERESPAWNS:
1909 terminx 1928
            insptr++;
1929
            G_OperateRespawns(Gv_GetVarX(*insptr++));
1930
            continue;
1931
 
1436 terminx 1932
        case CON_OPERATEMASTERSWITCHES:
1909 terminx 1933
            insptr++;
1934
            G_OperateMasterSwitches(Gv_GetVarX(*insptr++));
1935
            continue;
1936
 
1436 terminx 1937
        case CON_CHECKACTIVATORMOTION:
1938
            insptr++;
1909 terminx 1939
            aGameVars[g_iReturnVarID].val.lValue = G_CheckActivatorMotion(Gv_GetVarX(*insptr++));
1940
            continue;
1436 terminx 1941
 
1942
        case CON_INSERTSPRITEQ:
1943
            insptr++;
1944
            A_AddToDeleteQueue(vm.g_i);
1458 terminx 1945
            continue;
5 Plagman 1946
 
1436 terminx 1947
        case CON_QSTRLEN:
1948
            insptr++;
484 terminx 1949
            {
1436 terminx 1950
                int32_t i=*insptr++;
1951
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 1952
                if (EDUKE32_PREDICT_FALSE(ScriptQuotes[j] == NULL))
1436 terminx 1953
                {
3000 helixhorne 1954
                    CON_ERRPRINTF("null quote %d\n", j);
1436 terminx 1955
                    Gv_SetVarX(i,-1);
1458 terminx 1956
                    continue;
1436 terminx 1957
                }
1958
                Gv_SetVarX(i,Bstrlen(ScriptQuotes[j]));
1458 terminx 1959
                continue;
484 terminx 1960
            }
337 terminx 1961
 
3833 hendricks2 1962
        case CON_QSTRDIM:
1963
            insptr++;
1964
            {
1965
                vec2_t dim = { 0, 0, };
1966
 
1967
                int32_t w=*insptr++;
1968
                int32_t h=*insptr++;
1969
 
1970
                int32_t tilenum = Gv_GetVarX(*insptr++);
1971
                int32_t x=Gv_GetVarX(*insptr++), y=Gv_GetVarX(*insptr++), z = Gv_GetVarX(*insptr++);
1972
                int32_t blockangle=Gv_GetVarX(*insptr++);
1973
                int32_t q=Gv_GetVarX(*insptr++);
1974
                int32_t orientation=Gv_GetVarX(*insptr++);
1975
                int32_t xspace=Gv_GetVarX(*insptr++), yline=Gv_GetVarX(*insptr++);
1976
                int32_t xbetween=Gv_GetVarX(*insptr++), ybetween=Gv_GetVarX(*insptr++);
1977
                int32_t f=Gv_GetVarX(*insptr++);
1978
                int32_t x1=Gv_GetVarX(*insptr++), y1=Gv_GetVarX(*insptr++);
1979
                int32_t x2=Gv_GetVarX(*insptr++), y2=Gv_GetVarX(*insptr++);
1980
 
1981
                orientation &= (ROTATESPRITE_MAX-1);
1982
 
4680 terminx 1983
                if (EDUKE32_PREDICT_FALSE(tilenum < 0 || tilenum+255 >= MAXTILES))
3833 hendricks2 1984
                    CON_ERRPRINTF("invalid base tilenum %d\n", tilenum);
4902 terminx 1985
                else if (EDUKE32_PREDICT_FALSE((unsigned)q >= MAXQUOTES || ScriptQuotes[q] == NULL))
3833 hendricks2 1986
                    CON_ERRPRINTF("invalid quote ID %d\n", q);
1987
                else
3849 hendricks2 1988
                    dim = G_ScreenTextSize(tilenum,x,y,z,blockangle,ScriptQuotes[q],2|orientation,xspace,yline,xbetween,ybetween,f,x1,y1,x2,y2);
3833 hendricks2 1989
 
1990
                Gv_SetVarX(w,dim.x);
1991
                Gv_SetVarX(h,dim.y);
1992
                continue;
1993
            }
1994
 
1436 terminx 1995
        case CON_HEADSPRITESTAT:
1996
            insptr++;
1181 terminx 1997
            {
1436 terminx 1998
                int32_t i=*insptr++;
1999
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 2000
                if (EDUKE32_PREDICT_FALSE((unsigned)j > MAXSTATUS))
1436 terminx 2001
                {
3000 helixhorne 2002
                    CON_ERRPRINTF("invalid status list %d\n", j);
1458 terminx 2003
                    continue;
1436 terminx 2004
                }
2005
                Gv_SetVarX(i,headspritestat[j]);
1458 terminx 2006
                continue;
1181 terminx 2007
            }
2008
 
1436 terminx 2009
        case CON_PREVSPRITESTAT:
2010
            insptr++;
1181 terminx 2011
            {
1436 terminx 2012
                int32_t i=*insptr++;
2013
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 2014
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSPRITES))
1436 terminx 2015
                {
3000 helixhorne 2016
                    CON_ERRPRINTF("invalid sprite ID %d\n", j);
1458 terminx 2017
                    continue;
1436 terminx 2018
                }
2019
                Gv_SetVarX(i,prevspritestat[j]);
1458 terminx 2020
                continue;
1181 terminx 2021
            }
2022
 
1436 terminx 2023
        case CON_NEXTSPRITESTAT:
2024
            insptr++;
1181 terminx 2025
            {
1436 terminx 2026
                int32_t i=*insptr++;
2027
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 2028
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSPRITES))
1436 terminx 2029
                {
3000 helixhorne 2030
                    CON_ERRPRINTF("invalid sprite ID %d\n", j);
1458 terminx 2031
                    continue;
1436 terminx 2032
                }
2033
                Gv_SetVarX(i,nextspritestat[j]);
1458 terminx 2034
                continue;
1181 terminx 2035
            }
2036
 
1436 terminx 2037
        case CON_HEADSPRITESECT:
2038
            insptr++;
1181 terminx 2039
            {
1436 terminx 2040
                int32_t i=*insptr++;
2041
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 2042
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= (unsigned)numsectors))
1436 terminx 2043
                {
3000 helixhorne 2044
                    CON_ERRPRINTF("invalid sector %d\n", j);
1458 terminx 2045
                    continue;
1436 terminx 2046
                }
2047
                Gv_SetVarX(i,headspritesect[j]);
1458 terminx 2048
                continue;
1181 terminx 2049
            }
2050
 
1436 terminx 2051
        case CON_PREVSPRITESECT:
2052
            insptr++;
1181 terminx 2053
            {
1436 terminx 2054
                int32_t i=*insptr++;
2055
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 2056
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSPRITES))
1436 terminx 2057
                {
3000 helixhorne 2058
                    CON_ERRPRINTF("invalid sprite ID %d\n", j);
1458 terminx 2059
                    continue;
1436 terminx 2060
                }
2061
                Gv_SetVarX(i,prevspritesect[j]);
1458 terminx 2062
                continue;
1181 terminx 2063
            }
2064
 
1436 terminx 2065
        case CON_NEXTSPRITESECT:
2066
            insptr++;
1181 terminx 2067
            {
1436 terminx 2068
                int32_t i=*insptr++;
2069
                int32_t j=Gv_GetVarX(*insptr++);
4680 terminx 2070
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSPRITES))
1436 terminx 2071
                {
3000 helixhorne 2072
                    CON_ERRPRINTF("invalid sprite ID %d\n", j);
1458 terminx 2073
                    continue;
1436 terminx 2074
                }
2075
                Gv_SetVarX(i,nextspritesect[j]);
1458 terminx 2076
                continue;
1181 terminx 2077
            }
2078
 
1436 terminx 2079
        case CON_GETKEYNAME:
2080
            insptr++;
587 terminx 2081
            {
1436 terminx 2082
                int32_t i = Gv_GetVarX(*insptr++),
1909 terminx 2083
                        f = Gv_GetVarX(*insptr++);
2084
                int32_t j = Gv_GetVarX(*insptr++);
2085
 
4902 terminx 2086
                if (EDUKE32_PREDICT_FALSE((unsigned)i >= MAXQUOTES || ScriptQuotes[i] == NULL))
3200 terminx 2087
                {
3000 helixhorne 2088
                    CON_ERRPRINTF("invalid quote ID %d\n", i);
3200 terminx 2089
                    continue;
2090
                }
4680 terminx 2091
                else if (EDUKE32_PREDICT_FALSE((unsigned)f >= NUMGAMEFUNCTIONS))
3200 terminx 2092
                {
3000 helixhorne 2093
                    CON_ERRPRINTF("invalid function %d\n", f);
3200 terminx 2094
                    continue;
2095
                }
622 terminx 2096
                else
967 terminx 2097
                {
1909 terminx 2098
                    if (j < 2)
1436 terminx 2099
                        Bstrcpy(tempbuf,KB_ScanCodeToString(ud.config.KeyboardKeys[f][j]));
2100
                    else
2101
                    {
2102
                        Bstrcpy(tempbuf,KB_ScanCodeToString(ud.config.KeyboardKeys[f][0]));
1909 terminx 2103
 
1436 terminx 2104
                        if (!*tempbuf)
2105
                            Bstrcpy(tempbuf,KB_ScanCodeToString(ud.config.KeyboardKeys[f][1]));
2106
                    }
587 terminx 2107
                }
622 terminx 2108
 
1436 terminx 2109
                if (*tempbuf)
2110
                    Bstrcpy(ScriptQuotes[i],tempbuf);
1909 terminx 2111
 
1458 terminx 2112
                continue;
962 terminx 2113
            }
1909 terminx 2114
 
1436 terminx 2115
        case CON_QSUBSTR:
2116
            insptr++;
484 terminx 2117
            {
1440 terminx 2118
                int32_t q1 = Gv_GetVarX(*insptr++);
2119
                int32_t q2 = Gv_GetVarX(*insptr++);
2120
                int32_t st = Gv_GetVarX(*insptr++);
2121
                int32_t ln = Gv_GetVarX(*insptr++);
165 terminx 2122
 
4902 terminx 2123
                if (EDUKE32_PREDICT_FALSE((unsigned)q1>=MAXQUOTES || ScriptQuotes[q1] == NULL))
1440 terminx 2124
                {
3000 helixhorne 2125
                    CON_ERRPRINTF("invalid quote ID %d\n", q1);
1458 terminx 2126
                    continue;
1440 terminx 2127
                }
4902 terminx 2128
                if (EDUKE32_PREDICT_FALSE((unsigned)q2>=MAXQUOTES || ScriptQuotes[q2] == NULL))
1440 terminx 2129
                {
3000 helixhorne 2130
                    CON_ERRPRINTF("invalid quote ID %d\n", q2);
1458 terminx 2131
                    continue;
1440 terminx 2132
                }
1436 terminx 2133
 
4680 terminx 2134
                if (EDUKE32_PREDICT_FALSE((unsigned)st >= MAXQUOTELEN))
484 terminx 2135
                {
4583 helixhorne 2136
                    CON_ERRPRINTF("invalid start position %d\n", st);
2137
                    continue;
2138
                }
2139
 
4680 terminx 2140
                if (EDUKE32_PREDICT_FALSE(ln < 0))
4583 helixhorne 2141
                {
2142
                    CON_ERRPRINTF("invalid length %d\n", ln);
2143
                    continue;
2144
                }
2145
 
4902 terminx 2146
                char *s1 = ScriptQuotes[q1];
2147
                char *s2 = ScriptQuotes[q2];
2148
 
2149
                while (*s2 && st--) s2++;
2150
                while ((*s1 = *s2) && ln--)
4583 helixhorne 2151
                {
4902 terminx 2152
                    s1++;
2153
                    s2++;
2154
                }
2155
                *s1 = 0;
1440 terminx 2156
 
1458 terminx 2157
                continue;
1436 terminx 2158
            }
2159
 
2160
        case CON_GETPNAME:
1457 terminx 2161
        case CON_QSTRNCAT:
1436 terminx 2162
        case CON_QSTRCAT:
2163
        case CON_QSTRCPY:
2164
        case CON_QGETSYSSTR:
2165
        case CON_CHANGESPRITESECT:
2166
            insptr++;
2167
            {
2168
                int32_t i = Gv_GetVarX(*insptr++), j;
2169
                if (tw == CON_GETPNAME && *insptr == g_iThisActorID)
960 terminx 2170
                {
1436 terminx 2171
                    j = vm.g_p;
2172
                    insptr++;
960 terminx 2173
                }
1436 terminx 2174
                else j = Gv_GetVarX(*insptr++);
2175
 
2176
                switch (tw)
960 terminx 2177
                {
1436 terminx 2178
                case CON_GETPNAME:
4902 terminx 2179
                    if (EDUKE32_PREDICT_FALSE((unsigned)i>=MAXQUOTES || ScriptQuotes[i] == NULL))
1436 terminx 2180
                    {
4902 terminx 2181
                        CON_ERRPRINTF("invalid quote ID %d\n", i);
1436 terminx 2182
                        break;
2183
                    }
2184
                    if (g_player[j].user_name[0])
2185
                        Bstrcpy(ScriptQuotes[i],g_player[j].user_name);
2186
                    else Bsprintf(ScriptQuotes[i],"%d",j);
960 terminx 2187
                    break;
1436 terminx 2188
                case CON_QGETSYSSTR:
4902 terminx 2189
                    if (EDUKE32_PREDICT_FALSE((unsigned)i>=MAXQUOTES || ScriptQuotes[i] == NULL))
1436 terminx 2190
                    {
4902 terminx 2191
                        CON_ERRPRINTF("invalid quote ID %d\n", i);
1436 terminx 2192
                        break;
2193
                    }
2194
                    switch (j)
2195
                    {
2196
                    case STR_MAPNAME:
2197
                    case STR_MAPFILENAME:
4380 helixhorne 2198
                    {
2199
                        int32_t idx = ud.volume_number*MAXLEVELS + ud.level_number;
2200
                        const char *src;
2201
 
4680 terminx 2202
                        if (EDUKE32_PREDICT_FALSE((unsigned)idx >= ARRAY_SIZE(MapInfo)))
4380 helixhorne 2203
                        {
2204
                            CON_ERRPRINTF("out of bounds map number (vol=%d, lev=%d)\n",
2205
                                          ud.volume_number, ud.level_number);
2206
                            break;
2207
                        }
2208
 
2209
                        src = j==STR_MAPNAME ? MapInfo[idx].name : MapInfo[idx].filename;
4680 terminx 2210
                        if (EDUKE32_PREDICT_FALSE(src == NULL))
4380 helixhorne 2211
                        {
2212
                            CON_ERRPRINTF("attempted access to %s of non-existent map (vol=%d, lev=%d)",
2213
                                          j==STR_MAPNAME ? "name" : "file name",
2214
                                          ud.volume_number, ud.level_number);
2215
                            break;
2216
                        }
2217
 
2218
                        Bstrcpy(ScriptQuotes[i], j==STR_MAPNAME ? MapInfo[idx].name : MapInfo[idx].filename);
1436 terminx 2219
                        break;
4380 helixhorne 2220
                    }
1436 terminx 2221
                    case STR_PLAYERNAME:
4680 terminx 2222
                        if (EDUKE32_PREDICT_FALSE((unsigned)vm.g_p >= (unsigned)playerswhenstarted))
4380 helixhorne 2223
                        {
2224
                            CON_ERRPRINTF("Invalid player ID %d\n", vm.g_p);
2225
                            break;