Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
5604 terminx 3
Copyright (C) 2016 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
4541 hendricks2 19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
5 Plagman 20
*/
21
//-------------------------------------------------------------------------
5604 terminx 22
 
7186 terminx 23
#include "anim.h"
7239 terminx 24
#include "cmdline.h"
6895 terminx 25
#include "colmatch.h"
6074 hendricks2 26
#include "compat.h"
5611 terminx 27
#include "duke3d.h"
6895 terminx 28
#include "input.h"
29
#include "menus.h"
30
#include "osdcmds.h"
31
#include "savegame.h"
5 Plagman 32
#include "scriplib.h"
8096 hendricks2 33
#include "communityapi.h"
5 Plagman 34
 
2721 helixhorne 35
#ifdef LUNATIC
3148 helixhorne 36
# include "lunatic_game.h"
2329 helixhorne 37
#endif
38
 
7359 hendricks2 39
#include "vfs.h"
40
 
1595 helixhorne 41
#if KRANDDEBUG
42
# define GAMEEXEC_INLINE
43
# define GAMEEXEC_STATIC
44
#else
45
# define GAMEEXEC_INLINE inline
46
# define GAMEEXEC_STATIC static
47
#endif
48
 
3946 helixhorne 49
vmstate_t vm;
50
 
51
#if !defined LUNATIC
3460 helixhorne 52
int32_t g_tw;
7205 terminx 53
int32_t g_currentEvent = -1;
1956 helixhorne 54
 
4988 terminx 55
intptr_t const *insptr;
4902 terminx 56
 
5825 terminx 57
int32_t g_returnVarID    = -1;  // var ID of "RETURN"
58
int32_t g_weaponVarID    = -1;  // var ID of "WEAPON"
59
int32_t g_worksLikeVarID = -1;  // var ID of "WORKSLIKE"
60
int32_t g_zRangeVarID    = -1;  // var ID of "ZRANGE"
61
int32_t g_angRangeVarID  = -1;  // var ID of "ANGRANGE"
62
int32_t g_aimAngleVarID  = -1;  // var ID of "AUTOAIMANGLE"
63
int32_t g_lotagVarID     = -1;  // var ID of "LOTAG"
64
int32_t g_hitagVarID     = -1;  // var ID of "HITAG"
65
int32_t g_textureVarID   = -1;  // var ID of "TEXTURE"
66
int32_t g_thisActorVarID = -1;  // var ID of "THISACTOR"
67
int32_t g_structVarIDs   = -1;
4902 terminx 68
 
6736 terminx 69
// for timing events and actors
70
uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES];
71
double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES], g_actorMinMs[MAXTILES], g_actorMaxMs[MAXTILES];
72
 
8366 terminx 73
GAMEEXEC_STATIC void VM_Execute(int const loop = false);
617 terminx 74
 
6056 hendricks2 75
# include "gamestructures.cpp"
3354 helixhorne 76
#endif
1180 terminx 77
 
5755 hendricks2 78
#if !defined LUNATIC
7648 terminx 79
void VM_ScriptInfo(intptr_t const * const ptr, int const range)
1031 hnt_ts 80
{
7261 terminx 81
    if (!apScript || !ptr || g_currentEvent == -1)
1631 terminx 82
        return;
83
 
7261 terminx 84
    initprintf("\n");
85
 
86
    for (auto pScript = max<intptr_t const *>(ptr - (range >> 1), apScript),
87
                p_end   = min<intptr_t const *>(ptr + (range >> 1), apScript + g_scriptSize);
88
            pScript < p_end;
89
            ++pScript)
1031 hnt_ts 90
    {
7261 terminx 91
        initprintf("%5d: %3d: ", (int32_t)(pScript - apScript), (int32_t)(pScript - ptr));
2229 hendricks2 92
 
7266 terminx 93
        auto &v = *pScript;
7658 terminx 94
        int const lineNum = VM_DECODE_LINE_NUMBER(v);
95
        int const vmInst  = VM_DECODE_INST(v);
7266 terminx 96
 
7658 terminx 97
        if (lineNum && lineNum != VM_IFELSE_MAGIC && vmInst < CON_OPCODE_END)
98
            initprintf("%5d %s (%d)\n", lineNum, VM_GetKeywordForID(vmInst), vmInst);
7261 terminx 99
        else
100
            initprintf("%d\n", (int32_t)*pScript);
101
    }
4902 terminx 102
 
7261 terminx 103
    initprintf("\n");
1631 terminx 104
 
5513 terminx 105
    if (ptr == insptr)
106
    {
7005 terminx 107
        if (vm.pUSprite)
6234 terminx 108
            initprintf("current actor: %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum);
1631 terminx 109
 
7658 terminx 110
        initprintf("g_errorLineNum: %d, g_tw: %d\n", VM_DECODE_LINE_NUMBER(g_tw), VM_DECODE_INST(g_tw));
5513 terminx 111
    }
5755 hendricks2 112
}
3354 helixhorne 113
#endif
1031 hnt_ts 114
 
6232 terminx 115
static void VM_DeleteSprite(int const spriteNum, int const playerNum)
3514 helixhorne 116
{
5825 terminx 117
    if (EDUKE32_PREDICT_FALSE((unsigned) spriteNum >= MAXSPRITES))
3983 terminx 118
        return;
3514 helixhorne 119
 
3983 terminx 120
    // if player was set to squish, first stop that...
5825 terminx 121
    if (EDUKE32_PREDICT_FALSE(playerNum >= 0 && g_player[playerNum].ps->actorsqu == spriteNum))
122
        g_player[playerNum].ps->actorsqu = -1;
3983 terminx 123
 
5825 terminx 124
    A_DeleteSprite(spriteNum);
3514 helixhorne 125
}
126
 
6503 hendricks2 127
intptr_t apScriptEvents[MAXEVENTS];
4902 terminx 128
 
2709 helixhorne 129
// May recurse, e.g. through EVENT_XXX -> ... -> EVENT_KILLIT
4745 terminx 130
#ifdef LUNATIC
7636 terminx 131
static FORCE_INLINE int32_t VM_EventInlineInternal__(int const &eventNum, int const &spriteNum, int const &playerNum, int const &playerDist, int32_t returnValue)
5 Plagman 132
{
6828 terminx 133
    const double t = timerGetHiTicks();
5825 terminx 134
    int32_t ret = El_CallEvent(&g_ElState, eventNum, spriteNum, playerNum, playerDist, &returnValue);
2842 helixhorne 135
 
4673 terminx 136
    // NOTE: the run times are those of the called event plus any events
137
    // called by it, *not* "self" time.
6828 terminx 138
    g_eventTotalMs[eventNum] += timerGetHiTicks()-t;
5825 terminx 139
    g_eventCalls[eventNum]++;
3946 helixhorne 140
 
4673 terminx 141
    if (ret == 1)
5825 terminx 142
        VM_DeleteSprite(spriteNum, playerNum);
4745 terminx 143
 
5825 terminx 144
    return returnValue;
4745 terminx 145
}
3514 helixhorne 146
#else
7634 terminx 147
static uspritetype dummy_sprite;
148
static actor_t     dummy_actor;
149
 
150
static inline void VM_DummySprite(void)
6236 terminx 151
{
152
    vm.pUSprite = &dummy_sprite;
7261 terminx 153
    vm.pActor   = &dummy_actor;
154
    vm.pData    = &dummy_actor.t_data[0];
6236 terminx 155
}
156
 
7636 terminx 157
// verification that the event actually exists happens elsewhere
8408 terminx 158
static FORCE_INLINE int32_t VM_EventInlineInternal__(int const eventNum, int const spriteNum, int const playerNum,
7636 terminx 159
                                                       int const playerDist = -1, int32_t returnValue = 0)
4745 terminx 160
{
7950 terminx 161
    vmstate_t const newVMstate = { spriteNum, playerNum, playerDist, 0,
162
                                   &sprite[spriteNum&(MAXSPRITES-1)],
163
                                   &actor[spriteNum&(MAXSPRITES-1)].t_data[0],
164
                                   g_player[playerNum&(MAXPLAYERS-1)].ps,
165
                                   &actor[spriteNum&(MAXSPRITES-1)] };
166
 
7637 terminx 167
    auto &globalReturn = aGameVars[g_returnVarID].global;
6736 terminx 168
 
7637 terminx 169
    struct
7261 terminx 170
    {
171
        vmstate_t vm;
7637 terminx 172
        intptr_t globalReturn;
173
        int eventNum;
7261 terminx 174
        intptr_t const *insptr;
7637 terminx 175
    } const saved = { vm, globalReturn, g_currentEvent, insptr };
4745 terminx 176
 
7637 terminx 177
    vm = newVMstate;
7261 terminx 178
    g_currentEvent = eventNum;
7637 terminx 179
    insptr = apScript + apScriptEvents[eventNum];
180
    globalReturn = returnValue;
4745 terminx 181
 
7261 terminx 182
    double const t = timerGetHiTicks();
4745 terminx 183
 
7637 terminx 184
    if ((unsigned)spriteNum >= MAXSPRITES)
6236 terminx 185
        VM_DummySprite();
6303 hendricks2 186
 
7637 terminx 187
    if ((unsigned)playerNum >= (unsigned)g_mostConcurrentPlayers)
5825 terminx 188
        vm.pPlayer = g_player[0].ps;
4902 terminx 189
 
7631 terminx 190
    VM_Execute(true);
5 Plagman 191
 
5825 terminx 192
    if (vm.flags & VM_KILL)
193
        VM_DeleteSprite(vm.spriteNum, vm.playerNum);
1802 terminx 194
 
7637 terminx 195
    g_eventTotalMs[eventNum] += timerGetHiTicks()-t;
196
    g_eventCalls[eventNum]++;
2656 terminx 197
 
7637 terminx 198
    // restoring these needs to happen after VM_DeleteSprite() due to event recursion
199
    returnValue = globalReturn;
6542 terminx 200
 
7637 terminx 201
    vm             = saved.vm;
202
    globalReturn   = saved.globalReturn;
203
    g_currentEvent = saved.eventNum;
204
    insptr         = saved.insptr;
7261 terminx 205
 
5825 terminx 206
    return returnValue;
5 Plagman 207
}
4745 terminx 208
#endif
5 Plagman 209
 
7648 terminx 210
// the idea here is that the compiler inlines the call to VM_EventInlineInternal__() and gives us a set of
7636 terminx 211
// functions which are optimized further based on distance/return having values known at compile time
4745 terminx 212
 
7636 terminx 213
int32_t VM_ExecuteEvent(int const nEventID, int const spriteNum, int const playerNum, int const nDist, int32_t const nReturn)
4745 terminx 214
{
7636 terminx 215
    return VM_EventInlineInternal__(nEventID, spriteNum, playerNum, nDist, nReturn);
4745 terminx 216
}
217
 
7636 terminx 218
int32_t VM_ExecuteEvent(int const nEventID, int const spriteNum, int const playerNum, int const nDist)
4745 terminx 219
{
7636 terminx 220
    return VM_EventInlineInternal__(nEventID, spriteNum, playerNum, nDist);
4745 terminx 221
}
222
 
7636 terminx 223
int32_t VM_ExecuteEvent(int const nEventID, int const spriteNum, int const playerNum)
4745 terminx 224
{
7636 terminx 225
    return VM_EventInlineInternal__(nEventID, spriteNum, playerNum);
4745 terminx 226
}
227
 
7636 terminx 228
int32_t VM_ExecuteEventWithValue(int const nEventID, int const spriteNum, int const playerNum, int32_t const nReturn)
4745 terminx 229
{
7636 terminx 230
    return VM_EventInlineInternal__(nEventID, spriteNum, playerNum, -1, nReturn);
4745 terminx 231
}
232
 
7637 terminx 233
 
8366 terminx 234
static int VM_CheckSquished(void)
5 Plagman 235
{
7603 terminx 236
    auto const pSector = (usectorptr_t)&sector[vm.pSprite->sectnum];
395 terminx 237
 
7205 terminx 238
    if (pSector->lotag == ST_23_SWINGING_DOOR || (vm.pSprite->picnum == APLAYER && ud.noclip) ||
7259 terminx 239
        (pSector->lotag == ST_1_ABOVE_WATER && !A_CheckNoSE7Water(vm.pUSprite, vm.pSprite->sectnum, pSector->lotag, NULL)))
395 terminx 240
        return 0;
241
 
5825 terminx 242
    int32_t floorZ = pSector->floorz;
243
    int32_t ceilZ  = pSector->ceilingz;
2071 helixhorne 244
#ifdef YAX_ENABLE
5657 terminx 245
    int16_t cb, fb;
2071 helixhorne 246
 
5825 terminx 247
    yax_getbunches(vm.pSprite->sectnum, &cb, &fb);
5657 terminx 248
 
5825 terminx 249
    if (cb >= 0 && (pSector->ceilingstat&512)==0)  // if ceiling non-blocking...
5827 terminx 250
        ceilZ -= ZOFFSET5;  // unconditionally don't squish... yax_getneighborsect is slowish :/
5825 terminx 251
    if (fb >= 0 && (pSector->floorstat&512)==0)
5827 terminx 252
        floorZ += ZOFFSET5;
2071 helixhorne 253
#endif
254
 
6895 terminx 255
    if (vm.pSprite->pal == 1 ? (floorZ - ceilZ >= ZOFFSET5 || (pSector->lotag & 32768u)) : (floorZ - ceilZ >= ZOFFSET4))
7202 terminx 256
        return 0;
5768 hendricks2 257
 
5825 terminx 258
    P_DoQuote(QUOTE_SQUISHED, vm.pPlayer);
2071 helixhorne 259
 
5825 terminx 260
    if (A_CheckEnemySprite(vm.pSprite))
261
        vm.pSprite->xvel = 0;
1625 terminx 262
 
7202 terminx 263
#ifndef EDUKE32_STANDALONE
5825 terminx 264
    if (EDUKE32_PREDICT_FALSE(vm.pSprite->pal == 1)) // frozen
1625 terminx 265
    {
6236 terminx 266
        vm.pActor->picnum = SHOTSPARK1;
267
        vm.pActor->extra  = 1;
1625 terminx 268
        return 0;
395 terminx 269
    }
7202 terminx 270
#endif
1625 terminx 271
 
272
    return 1;
395 terminx 273
}
274
 
4451 helixhorne 275
#if !defined LUNATIC
5825 terminx 276
GAMEEXEC_STATIC GAMEEXEC_INLINE void P_ForceAngle(DukePlayer_t *pPlayer)
398 terminx 277
{
5821 terminx 278
    int const nAngle = 128-(krand()&255);
398 terminx 279
 
6725 terminx 280
    pPlayer->q16horiz           += F16(64);
5825 terminx 281
    pPlayer->return_to_center = 9;
282
    pPlayer->rotscrnang       = nAngle >> 1;
283
    pPlayer->look_ang         = pPlayer->rotscrnang;
398 terminx 284
}
4451 helixhorne 285
#endif
398 terminx 286
 
6236 terminx 287
// wow, this function sucks
6274 hendricks2 288
#ifdef __cplusplus
289
extern "C"
290
#endif
8366 terminx 291
int A_Dodge(spritetype * const);
292
int A_Dodge(spritetype * const pSprite)
395 terminx 293
{
5821 terminx 294
    if (A_CheckEnemySprite(pSprite) && pSprite->extra <= 0)  // hack
1171 terminx 295
        return 0;
296
 
6236 terminx 297
    vec2_t const msin = { sintable[(pSprite->ang + 512) & 2047], sintable[pSprite->ang & 2047] };
298
 
6575 terminx 299
    for (native_t nexti, SPRITES_OF_STAT_SAFE(STAT_PROJECTILE, i, nexti)) //weapons list
5 Plagman 300
    {
5825 terminx 301
        if (OW(i) == i)
5 Plagman 302
            continue;
303
 
6236 terminx 304
        vec2_t const b = { SX(i) - pSprite->x, SY(i) - pSprite->y };
5825 terminx 305
        vec2_t const v = { sintable[(SA(i) + 512) & 2047], sintable[SA(i) & 2047] };
5 Plagman 306
 
5821 terminx 307
        if (((msin.x * b.x) + (msin.y * b.y) >= 0) && ((v.x * b.x) + (v.y * b.y) < 0))
1802 terminx 308
        {
5821 terminx 309
            if (klabs((v.x * b.y) - (v.y * b.x)) < 65536 << 6)
5 Plagman 310
            {
5821 terminx 311
                pSprite->ang -= 512+(krand()&1024);
1802 terminx 312
                return 1;
5 Plagman 313
            }
1802 terminx 314
        }
5 Plagman 315
    }
5015 helixhorne 316
 
5 Plagman 317
    return 0;
318
}
319
 
7648 terminx 320
int A_GetFurthestAngle(int const spriteNum, int const angDiv)
5 Plagman 321
{
7603 terminx 322
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
5 Plagman 323
 
5825 terminx 324
    if (pSprite->picnum != APLAYER && (AC_COUNT(actor[spriteNum].t_data)&63) > 2)
7669 terminx 325
        return (pSprite->ang + 1024) & 2047;
5 Plagman 326
 
7202 terminx 327
    int       furthestAngle = 0;
328
    int const angIncs       = tabledivide32_noinline(2048, angDiv);
6236 terminx 329
    int32_t   greatestDist  = INT32_MIN;
5015 helixhorne 330
    hitdata_t hit;
331
 
6575 terminx 332
    for (native_t j = pSprite->ang; j < (2048 + pSprite->ang); j += angIncs)
5 Plagman 333
    {
7603 terminx 334
        vec3_t origin = *(const vec3_t *)pSprite;
335
        origin.z -= ZOFFSET3;
336
        hitscan(&origin, pSprite->sectnum, sintable[(j + 512) & 2047], sintable[j & 2047], 0, &hit, CLIPMASK1);
5 Plagman 337
 
6236 terminx 338
        int const hitDist = klabs(hit.pos.x-pSprite->x) + klabs(hit.pos.y-pSprite->y);
5015 helixhorne 339
 
6236 terminx 340
        if (hitDist > greatestDist)
1048 terminx 341
        {
6236 terminx 342
            greatestDist = hitDist;
343
            furthestAngle = j;
5 Plagman 344
        }
5015 helixhorne 345
    }
3920 helixhorne 346
 
7202 terminx 347
    return furthestAngle & 2047;
5 Plagman 348
}
349
 
7603 terminx 350
int A_FurthestVisiblePoint(int const spriteNum, uspriteptr_t const ts, vec2_t * const vect)
5 Plagman 351
{
5825 terminx 352
    if (AC_COUNT(actor[spriteNum].t_data)&63)
2652 terminx 353
        return -1;
354
 
7603 terminx 355
    auto const pnSprite = (uspriteptr_t)&sprite[spriteNum];
5 Plagman 356
 
5015 helixhorne 357
    hitdata_t hit;
5821 terminx 358
    int const angincs = 128;
359
//    ((!g_netServer && ud.multimode < 2) && ud.player_skill < 3) ? 2048 / 2 : tabledivide32_noinline(2048, 1 + (krand() & 1));
1048 terminx 360
 
6575 terminx 361
    for (native_t j = ts->ang; j < (2048 + ts->ang); j += (angincs /*-(krand()&511)*/))
5015 helixhorne 362
    {
7603 terminx 363
        vec3_t origin = *(const vec3_t *)ts;
364
        origin.z -= ZOFFSET2;
365
        hitscan(&origin, ts->sectnum, sintable[(j + 512) & 2047], sintable[j & 2047], 16384 - (krand() & 32767), &hit, CLIPMASK1);
1048 terminx 366
 
5821 terminx 367
        if (hit.sect < 0)
368
            continue;
1208 terminx 369
 
5853 terminx 370
        int const d  = FindDistance2D(hit.pos.x - ts->x, hit.pos.y - ts->y);
5821 terminx 371
        int const da = FindDistance2D(hit.pos.x - pnSprite->x, hit.pos.y - pnSprite->y);
5015 helixhorne 372
 
5821 terminx 373
        if (d < da)
374
        {
6895 terminx 375
            if (cansee(hit.pos.x, hit.pos.y, hit.pos.z, hit.sect, pnSprite->x, pnSprite->y, pnSprite->z - ZOFFSET2, pnSprite->sectnum))
5015 helixhorne 376
            {
6236 terminx 377
                vect->x = hit.pos.x;
378
                vect->y = hit.pos.y;
5015 helixhorne 379
                return hit.sect;
380
            }
5821 terminx 381
        }
5 Plagman 382
    }
5015 helixhorne 383
 
384
    return -1;
5 Plagman 385
}
386
 
7667 terminx 387
void VM_GetZRange(int const spriteNum, int32_t * const ceilhit, int32_t * const florhit, int const wallDist)
5 Plagman 388
{
7603 terminx 389
    auto const pSprite = &sprite[spriteNum];
5853 terminx 390
    int const          ocstat  = pSprite->cstat;
5 Plagman 391
 
5825 terminx 392
    pSprite->cstat = 0;
393
    pSprite->z -= ZOFFSET;
1217 terminx 394
 
7697 terminx 395
    getzrange(&pSprite->pos, pSprite->sectnum, &actor[spriteNum].ceilingz, ceilhit, &actor[spriteNum].floorz, florhit, wallDist, CLIPMASK0);
5 Plagman 396
 
5825 terminx 397
    pSprite->z += ZOFFSET;
398
    pSprite->cstat = ocstat;
5015 helixhorne 399
}
5 Plagman 400
 
6236 terminx 401
void A_GetZLimits(int const spriteNum)
5015 helixhorne 402
{
7259 terminx 403
    auto const pSprite = &sprite[spriteNum];
404
    int32_t    ceilhit, florhit;
7436 terminx 405
    int const clipDist = A_GetClipdist(spriteNum, -1);
1217 terminx 406
 
7436 terminx 407
    VM_GetZRange(spriteNum, &ceilhit, &florhit, pSprite->statnum == STAT_PROJECTILE ? clipDist << 3 : clipDist);
5825 terminx 408
    actor[spriteNum].flags &= ~SFLAG_NOFLOORSHADOW;
5015 helixhorne 409
 
410
    if ((florhit&49152) == 49152 && (sprite[florhit&(MAXSPRITES-1)].cstat&48) == 0)
4680 terminx 411
    {
7603 terminx 412
        auto const hitspr = (uspriteptr_t)&sprite[florhit&(MAXSPRITES-1)];
2192 helixhorne 413
 
5015 helixhorne 414
        florhit &= (MAXSPRITES-1);
2192 helixhorne 415
 
5015 helixhorne 416
        // If a non-projectile would fall onto non-frozen enemy OR an enemy onto a player...
5821 terminx 417
        if ((A_CheckEnemySprite(hitspr) && hitspr->pal != 1 && pSprite->statnum != STAT_PROJECTILE)
418
                || (hitspr->picnum == APLAYER && A_CheckEnemySprite(pSprite)))
4680 terminx 419
        {
5825 terminx 420
            actor[spriteNum].flags |= SFLAG_NOFLOORSHADOW;  // No shadows on actors
5821 terminx 421
            pSprite->xvel = -256;  // SLIDE_ABOVE_ENEMY
7667 terminx 422
            A_SetSprite(spriteNum, CLIPMASK0);
5 Plagman 423
        }
5821 terminx 424
        else if (pSprite->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && pSprite->owner==florhit)
1677 terminx 425
        {
5825 terminx 426
            actor[spriteNum].ceilingz = sector[pSprite->sectnum].ceilingz;
427
            actor[spriteNum].floorz   = sector[pSprite->sectnum].floorz;
1677 terminx 428
        }
4680 terminx 429
    }
5 Plagman 430
}
431
 
6232 terminx 432
void A_Fall(int const spriteNum)
5 Plagman 433
{
7259 terminx 434
    auto const pSprite = &sprite[spriteNum];
5825 terminx 435
    int spriteGravity = g_spriteGravity;
5015 helixhorne 436
 
5821 terminx 437
    if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(pSprite->sectnum)))
5825 terminx 438
        spriteGravity = 0;
5821 terminx 439
    else if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(pSprite->sectnum)))
5825 terminx 440
        spriteGravity = g_spriteGravity/6;
5 Plagman 441
 
7952 terminx 442
    int32_t ceilhit, florhit;
443
    VM_GetZRange(spriteNum, &ceilhit, &florhit, A_GetClipdist(spriteNum, -1));
5 Plagman 444
 
1877 helixhorne 445
#ifdef YAX_ENABLE
5821 terminx 446
    int fbunch = (sector[pSprite->sectnum].floorstat&512) ? -1 : yax_getbunch(pSprite->sectnum, YAX_FLOOR);
1877 helixhorne 447
#endif
3682 helixhorne 448
 
5825 terminx 449
    if (pSprite->z < actor[spriteNum].floorz-ZOFFSET
1877 helixhorne 450
#ifdef YAX_ENABLE
3682 helixhorne 451
            || fbunch >= 0
1877 helixhorne 452
#endif
2652 terminx 453
       )
5 Plagman 454
    {
5821 terminx 455
        if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER && pSprite->zvel > 3122)
456
            pSprite->zvel = 3144;
5825 terminx 457
        pSprite->z += pSprite->zvel = min(6144, pSprite->zvel+spriteGravity);
5 Plagman 458
    }
3682 helixhorne 459
 
1877 helixhorne 460
#ifdef YAX_ENABLE
461
    if (fbunch >= 0)
7697 terminx 462
        setspritez(spriteNum, &pSprite->pos);
3682 helixhorne 463
    else
1877 helixhorne 464
#endif
5825 terminx 465
        if (pSprite->z >= actor[spriteNum].floorz-ZOFFSET)
2652 terminx 466
        {
5825 terminx 467
            pSprite->z = actor[spriteNum].floorz-ZOFFSET;
5821 terminx 468
            pSprite->zvel = 0;
2652 terminx 469
        }
5 Plagman 470
}
471
 
7202 terminx 472
int __fastcall G_GetAngleDelta(int currAngle, int newAngle)
5 Plagman 473
{
5825 terminx 474
    currAngle &= 2047;
475
    newAngle &= 2047;
5 Plagman 476
 
5825 terminx 477
    if (klabs(currAngle-newAngle) < 1024)
521 terminx 478
    {
1143 terminx 479
//        OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
5825 terminx 480
        return newAngle-currAngle;
522 terminx 481
    }
5 Plagman 482
 
6895 terminx 483
    if (newAngle > 1024)
484
        newAngle -= 2048;
485
    if (currAngle > 1024)
486
        currAngle -= 2048;
428 terminx 487
 
1143 terminx 488
//    OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
5825 terminx 489
    return newAngle-currAngle;
5 Plagman 490
}
491
 
6232 terminx 492
GAMEEXEC_STATIC void VM_AlterAng(int32_t const moveFlags)
5 Plagman 493
{
5825 terminx 494
    int const elapsedTics = (AC_COUNT(vm.pData))&31;
5 Plagman 495
 
3459 helixhorne 496
#if !defined LUNATIC
5825 terminx 497
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.pData) >= (unsigned)g_scriptSize-1))
2451 helixhorne 498
 
1685 terminx 499
    {
5825 terminx 500
        AC_MOVE_ID(vm.pData) = 0;
6234 terminx 501
        OSD_Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.spriteNum, vm.pUSprite->picnum);
1686 terminx 502
        return;
1685 terminx 503
    }
504
 
7633 terminx 505
    auto const moveptr = apScript + AC_MOVE_ID(vm.pData);
506
    auto &hvel    = moveptr[0];
507
    auto &vvel    = moveptr[1];
2724 helixhorne 508
#else
7633 terminx 509
    auto &hvel = vm.pActor->mv.hvel;
510
    auto &vvel = vm.pActor->mv.vvel;
2724 helixhorne 511
#endif
5 Plagman 512
 
7633 terminx 513
    vm.pSprite->xvel += (hvel - vm.pSprite->xvel)/5;
514
    if (vm.pSprite->zvel < 648)
515
        vm.pSprite->zvel += ((vvel<<4) - vm.pSprite->zvel)/5;
516
 
5825 terminx 517
    if (A_CheckEnemySprite(vm.pSprite) && vm.pSprite->extra <= 0) // hack
1171 terminx 518
        return;
519
 
5825 terminx 520
    if (moveFlags&seekplayer)
5 Plagman 521
    {
5825 terminx 522
        int const spriteAngle    = vm.pSprite->ang;
6232 terminx 523
        int const holoDukeSprite = vm.pPlayer->holoduke_on;
1048 terminx 524
 
5 Plagman 525
        // NOTE: looks like 'owner' is set to target sprite ID...
526
 
6895 terminx 527
        vm.pSprite->owner = (holoDukeSprite >= 0
528
                             && cansee(sprite[holoDukeSprite].x, sprite[holoDukeSprite].y, sprite[holoDukeSprite].z, sprite[holoDukeSprite].sectnum,
529
                                       vm.pSprite->x, vm.pSprite->y, vm.pSprite->z, vm.pSprite->sectnum))
5853 terminx 530
          ? holoDukeSprite
531
          : vm.pPlayer->i;
5 Plagman 532
 
6232 terminx 533
        int const goalAng = (sprite[vm.pSprite->owner].picnum == APLAYER)
6236 terminx 534
                  ? getangle(vm.pActor->lastv.x - vm.pSprite->x, vm.pActor->lastv.y - vm.pSprite->y)
5853 terminx 535
                  : getangle(sprite[vm.pSprite->owner].x - vm.pSprite->x, sprite[vm.pSprite->owner].y - vm.pSprite->y);
5 Plagman 536
 
5825 terminx 537
        if (vm.pSprite->xvel && vm.pSprite->picnum != DRONE)
5 Plagman 538
        {
6232 terminx 539
            int const angDiff = G_GetAngleDelta(spriteAngle, goalAng);
5 Plagman 540
 
5825 terminx 541
            if (elapsedTics < 2)
5 Plagman 542
            {
5825 terminx 543
                if (klabs(angDiff) < 256)
5 Plagman 544
                {
6236 terminx 545
                    int const angInc = 128-(krand()&256);
546
                    vm.pSprite->ang += angInc;
5825 terminx 547
                    if (A_GetHitscanRange(vm.spriteNum) < 844)
6236 terminx 548
                        vm.pSprite->ang -= angInc;
5 Plagman 549
                }
550
            }
5825 terminx 551
            else if (elapsedTics > 18 && elapsedTics < GAMETICSPERSEC) // choose
5 Plagman 552
            {
6895 terminx 553
                if (klabs(angDiff >> 2) < 128)
554
                    vm.pSprite->ang = goalAng;
555
                else
556
                    vm.pSprite->ang += angDiff >> 2;
5 Plagman 557
            }
558
        }
6895 terminx 559
        else
560
            vm.pSprite->ang = goalAng;
5 Plagman 561
    }
562
 
5825 terminx 563
    if (elapsedTics < 1)
5 Plagman 564
    {
5825 terminx 565
        if (moveFlags&furthestdir)
5 Plagman 566
        {
5825 terminx 567
            vm.pSprite->ang = A_GetFurthestAngle(vm.spriteNum, 2);
568
            vm.pSprite->owner = vm.pPlayer->i;
5 Plagman 569
        }
570
 
5825 terminx 571
        if (moveFlags&fleeenemy)
572
            vm.pSprite->ang = A_GetFurthestAngle(vm.spriteNum, 2);
5 Plagman 573
    }
574
}
575
 
6232 terminx 576
static inline void VM_AddAngle(int const shift, int const goalAng)
2745 helixhorne 577
{
5825 terminx 578
    int angDiff = G_GetAngleDelta(vm.pSprite->ang, goalAng) >> shift;
2745 helixhorne 579
 
5825 terminx 580
    if ((angDiff > -8 && angDiff < 0) || (angDiff < 8 && angDiff > 0))
581
        angDiff <<= 1;
2745 helixhorne 582
 
5825 terminx 583
    vm.pSprite->ang += angDiff;
2745 helixhorne 584
}
585
 
6232 terminx 586
static inline void VM_FacePlayer(int const shift)
2745 helixhorne 587
{
5825 terminx 588
    VM_AddAngle(shift, (vm.pPlayer->newowner >= 0) ? getangle(vm.pPlayer->opos.x - vm.pSprite->x, vm.pPlayer->opos.y - vm.pSprite->y)
589
                                                 : getangle(vm.pPlayer->pos.x - vm.pSprite->x, vm.pPlayer->pos.y - vm.pSprite->y));
2745 helixhorne 590
}
591
 
3666 helixhorne 592
////////// TROR get*zofslope //////////
593
// These rather belong into the engine.
594
 
4745 terminx 595
static int32_t VM_GetCeilZOfSlope(void)
3666 helixhorne 596
{
7905 terminx 597
    vec2_t const vect     = vm.pSprite->pos.vec2;
5825 terminx 598
    int const    sectnum  = vm.pSprite->sectnum;
4745 terminx 599
 
3666 helixhorne 600
#ifdef YAX_ENABLE
601
    if ((sector[sectnum].ceilingstat&512)==0)
602
    {
5821 terminx 603
        int const nsect = yax_getneighborsect(vect.x, vect.y, sectnum, YAX_CEILING);
3666 helixhorne 604
        if (nsect >= 0)
5821 terminx 605
            return getceilzofslope(nsect, vect.x, vect.y);
3666 helixhorne 606
    }
607
#endif
5821 terminx 608
    return getceilzofslope(sectnum, vect.x, vect.y);
3666 helixhorne 609
}
610
 
7227 terminx 611
#ifndef EDUKE32_STANDALONE
4745 terminx 612
static int32_t VM_GetFlorZOfSlope(void)
3666 helixhorne 613
{
7905 terminx 614
    vec2_t const vect    = vm.pSprite->pos.vec2;
5825 terminx 615
    int const    sectnum = vm.pSprite->sectnum;
4745 terminx 616
 
3666 helixhorne 617
#ifdef YAX_ENABLE
618
    if ((sector[sectnum].floorstat&512)==0)
619
    {
5821 terminx 620
        int const nsect = yax_getneighborsect(vect.x, vect.y, sectnum, YAX_FLOOR);
3666 helixhorne 621
        if (nsect >= 0)
5821 terminx 622
            return getflorzofslope(nsect, vect.x, vect.y);
3666 helixhorne 623
    }
624
#endif
5821 terminx 625
    return getflorzofslope(sectnum, vect.x, vect.y);
3666 helixhorne 626
}
7227 terminx 627
#endif
3666 helixhorne 628
 
629
////////////////////
630
 
4955 helixhorne 631
static int32_t A_GetWaterZOffset(int spritenum);
632
 
1625 terminx 633
GAMEEXEC_STATIC void VM_Move(void)
5 Plagman 634
{
6581 hendricks2 635
    auto const movflagsptr = &AC_MOVFLAGS(vm.pSprite, &actor[vm.spriteNum]);
636
    // NOTE: test against -1 commented out and later revived in source history
637
    // XXX: Does its presence/absence break anything? Where are movflags with all bits set created?
7719 terminx 638
    int const movflags = (*movflagsptr == (remove_pointer_t<decltype(movflagsptr)>)-1) ? 0 : *movflagsptr;
5825 terminx 639
    int const deadflag = (A_CheckEnemySprite(vm.pSprite) && vm.pSprite->extra <= 0);
5 Plagman 640
 
5825 terminx 641
    AC_COUNT(vm.pData)++;
5 Plagman 642
 
5825 terminx 643
    if (AC_MOVE_ID(vm.pData) == 0 || movflags == 0)
1171 terminx 644
    {
6236 terminx 645
        if (deadflag || (vm.pActor->bpos.x != vm.pSprite->x) || (vm.pActor->bpos.y != vm.pSprite->y))
1171 terminx 646
        {
7905 terminx 647
            vm.pActor->bpos.vec2 = vm.pSprite->pos.vec2;
7973 terminx 648
            setsprite(vm.spriteNum, &vm.pSprite->pos);
1171 terminx 649
        }
650
        return;
651
    }
652
 
3919 helixhorne 653
    if (deadflag)
654
        goto dead;
1909 terminx 655
 
3919 helixhorne 656
    if (movflags&face_player)
3459 helixhorne 657
        VM_FacePlayer(2);
5 Plagman 658
 
3919 helixhorne 659
    if (movflags&spin)
5825 terminx 660
        vm.pSprite->ang += sintable[((AC_COUNT(vm.pData)<<3)&2047)]>>6;
5 Plagman 661
 
3919 helixhorne 662
    if (movflags&face_player_slow)
3459 helixhorne 663
        VM_FacePlayer(4);
5 Plagman 664
 
4378 helixhorne 665
    if ((movflags&jumptoplayer_bits) == jumptoplayer_bits)
5 Plagman 666
    {
5825 terminx 667
        if (AC_COUNT(vm.pData) < 16)
668
            vm.pSprite->zvel -= (sintable[(512+(AC_COUNT(vm.pData)<<4))&2047]>>5);
5 Plagman 669
    }
670
 
3919 helixhorne 671
    if (movflags&face_player_smart)
5 Plagman 672
    {
6895 terminx 673
        vec2_t const vect = { vm.pPlayer->pos.x + (vm.pPlayer->vel.x / 768), vm.pPlayer->pos.y + (vm.pPlayer->vel.y / 768) };
5825 terminx 674
        VM_AddAngle(2, getangle(vect.x - vm.pSprite->x, vect.y - vm.pSprite->y));
5 Plagman 675
    }
676
 
1909 terminx 677
dead:
3459 helixhorne 678
#if !defined LUNATIC
5825 terminx 679
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.pData) >= (unsigned)g_scriptSize-1))
1684 terminx 680
    {
5825 terminx 681
        AC_MOVE_ID(vm.pData) = 0;
6234 terminx 682
        OSD_Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum);
1686 terminx 683
        return;
1685 terminx 684
    }
5 Plagman 685
 
7259 terminx 686
    auto const moveptr = apScript + AC_MOVE_ID(vm.pData);
7633 terminx 687
    auto &hvel = moveptr[0];
688
    auto &vvel = moveptr[1];
689
#else
690
    auto &hvel = vm.pActor->mv.hvel;
691
    auto &vvel = vm.pActor->mv.vvel;
692
#endif
2185 helixhorne 693
 
6895 terminx 694
    if (movflags & geth)
7633 terminx 695
        vm.pSprite->xvel += (hvel - vm.pSprite->xvel) >> 1;
696
 
6895 terminx 697
    if (movflags & getv)
7633 terminx 698
        vm.pSprite->zvel += (16 * vvel - vm.pSprite->zvel) >> 1;
1820 terminx 699
 
3919 helixhorne 700
    if (movflags&dodgebullet && !deadflag)
5825 terminx 701
        A_Dodge(vm.pSprite);
5 Plagman 702
 
5825 terminx 703
    if (vm.pSprite->picnum != APLAYER)
3919 helixhorne 704
        VM_AlterAng(movflags);
5 Plagman 705
 
5825 terminx 706
    if (vm.pSprite->xvel > -6 && vm.pSprite->xvel < 6)
707
        vm.pSprite->xvel = 0;
5 Plagman 708
 
5825 terminx 709
    int badguyp = A_CheckEnemySprite(vm.pSprite);
5 Plagman 710
 
5825 terminx 711
    if (vm.pSprite->xvel || vm.pSprite->zvel)
5 Plagman 712
    {
5834 terminx 713
        int spriteXvel = vm.pSprite->xvel;
714
        int angDiff    = vm.pSprite->ang;
2745 helixhorne 715
 
7227 terminx 716
#ifndef EDUKE32_STANDALONE
7911 terminx 717
        if (badguyp && (FURY || vm.pSprite->picnum != ROTATEGUN))
5 Plagman 718
        {
7911 terminx 719
            if (!FURY && (vm.pSprite->picnum == DRONE || vm.pSprite->picnum == COMMANDER) && vm.pSprite->extra > 0)
5 Plagman 720
            {
5825 terminx 721
                if (vm.pSprite->picnum == COMMANDER)
5 Plagman 722
                {
5821 terminx 723
                    int32_t nSectorZ;
3663 helixhorne 724
                    // NOTE: COMMANDER updates both actor[].floorz and
725
                    // .ceilingz regardless of its zvel.
6236 terminx 726
                    vm.pActor->floorz = nSectorZ = VM_GetFlorZOfSlope();
5825 terminx 727
                    if (vm.pSprite->z > nSectorZ-ZOFFSET3)
5 Plagman 728
                    {
5825 terminx 729
                        vm.pSprite->z = nSectorZ-ZOFFSET3;
730
                        vm.pSprite->zvel = 0;
5 Plagman 731
                    }
732
 
6236 terminx 733
                    vm.pActor->ceilingz = nSectorZ = VM_GetCeilZOfSlope();
5825 terminx 734
                    if (vm.pSprite->z < nSectorZ+(80<<8))
5 Plagman 735
                    {
5825 terminx 736
                        vm.pSprite->z = nSectorZ+(80<<8);
737
                        vm.pSprite->zvel = 0;
5 Plagman 738
                    }
739
                }
740
                else
741
                {
5821 terminx 742
                    int32_t nSectorZ;
3663 helixhorne 743
                    // The DRONE updates either .floorz or .ceilingz, not both.
5825 terminx 744
                    if (vm.pSprite->zvel > 0)
5 Plagman 745
                    {
6236 terminx 746
                        vm.pActor->floorz = nSectorZ = VM_GetFlorZOfSlope();
5825 terminx 747
                        if (vm.pSprite->z > nSectorZ-(30<<8))
748
                            vm.pSprite->z = nSectorZ-(30<<8);
5 Plagman 749
                    }
750
                    else
751
                    {
6236 terminx 752
                        vm.pActor->ceilingz = nSectorZ = VM_GetCeilZOfSlope();
5825 terminx 753
                        if (vm.pSprite->z < nSectorZ+(50<<8))
5 Plagman 754
                        {
5825 terminx 755
                            vm.pSprite->z = nSectorZ+(50<<8);
756
                            vm.pSprite->zvel = 0;
5 Plagman 757
                        }
758
                    }
759
                }
760
            }
7911 terminx 761
            else if ((FURY && badguyp) || vm.pSprite->picnum != ORGANTIC)
7227 terminx 762
#else
763
        if (badguyp)
764
        {
765
#endif
5 Plagman 766
            {
5014 helixhorne 767
                // All other actors besides ORGANTIC don't update .floorz or
768
                // .ceilingz here.
5825 terminx 769
                if (vm.pSprite->zvel > 0)
5 Plagman 770
                {
6236 terminx 771
                    if (vm.pSprite->z > vm.pActor->floorz)
772
                        vm.pSprite->z = vm.pActor->floorz;
5825 terminx 773
                    vm.pSprite->z += A_GetWaterZOffset(vm.spriteNum);
4953 helixhorne 774
                }
5825 terminx 775
                else if (vm.pSprite->zvel < 0)
4953 helixhorne 776
                {
5821 terminx 777
                    int const l = VM_GetCeilZOfSlope();
5014 helixhorne 778
 
5825 terminx 779
                    if (vm.pSprite->z < l+(66<<8))
5 Plagman 780
                    {
5825 terminx 781
                        vm.pSprite->z = l+(66<<8);
782
                        vm.pSprite->zvel >>= 1;
5 Plagman 783
                    }
784
                }
785
            }
786
 
5825 terminx 787
            if (vm.playerDist < 960 && vm.pSprite->xrepeat > 16)
5 Plagman 788
            {
5834 terminx 789
                spriteXvel = -(1024 - vm.playerDist);
5825 terminx 790
                angDiff = getangle(vm.pPlayer->pos.x - vm.pSprite->x, vm.pPlayer->pos.y - vm.pSprite->y);
5 Plagman 791
 
5825 terminx 792
                if (vm.playerDist < 512)
5 Plagman 793
                {
5825 terminx 794
                    vm.pPlayer->vel.x = 0;
795
                    vm.pPlayer->vel.y = 0;
5 Plagman 796
                }
797
                else
798
                {
5825 terminx 799
                    vm.pPlayer->vel.x = mulscale16(vm.pPlayer->vel.x, vm.pPlayer->runspeed - 0x2000);
800
                    vm.pPlayer->vel.y = mulscale16(vm.pPlayer->vel.y, vm.pPlayer->runspeed - 0x2000);
5 Plagman 801
                }
802
            }
7227 terminx 803
            else
804
#ifndef EDUKE32_STANDALONE
7911 terminx 805
                if (FURY || (vm.pSprite->picnum != DRONE && vm.pSprite->picnum != SHARK && vm.pSprite->picnum != COMMANDER))
7227 terminx 806
#endif
5 Plagman 807
            {
5825 terminx 808
                if (vm.pPlayer->actorsqu == vm.spriteNum)
3920 helixhorne 809
                    return;
3102 terminx 810
 
5825 terminx 811
                if (!A_CheckSpriteFlags(vm.spriteNum, SFLAG_SMOOTHMOVE))
5 Plagman 812
                {
5825 terminx 813
                    if (AC_COUNT(vm.pData) & 1)
3920 helixhorne 814
                        return;
5834 terminx 815
                    spriteXvel <<= 1;
5 Plagman 816
                }
817
            }
818
        }
5825 terminx 819
        else if (vm.pSprite->picnum == APLAYER)
6236 terminx 820
            if (vm.pSprite->z < vm.pActor->ceilingz+ZOFFSET5)
821
                vm.pSprite->z = vm.pActor->ceilingz+ZOFFSET5;
5 Plagman 822
 
6895 terminx 823
        vec3_t const vect
824
        = { (spriteXvel * (sintable[(angDiff + 512) & 2047])) >> 14, (spriteXvel * (sintable[angDiff & 2047])) >> 14, vm.pSprite->zvel };
1207 terminx 825
 
6236 terminx 826
        vm.pActor->movflag = A_MoveSprite(vm.spriteNum, &vect, (A_CheckSpriteFlags(vm.spriteNum, SFLAG_NOCLIP) ? 0 : CLIPMASK0));
5 Plagman 827
    }
828
 
3919 helixhorne 829
    if (!badguyp)
2745 helixhorne 830
        return;
5 Plagman 831
 
5825 terminx 832
    vm.pSprite->shade += (sector[vm.pSprite->sectnum].ceilingstat & 1) ? (sector[vm.pSprite->sectnum].ceilingshade - vm.pSprite->shade) >> 1
833
                                                                 : (sector[vm.pSprite->sectnum].floorshade - vm.pSprite->shade) >> 1;
5 Plagman 834
}
835
 
6232 terminx 836
static void P_AddWeaponMaybeSwitch(DukePlayer_t * const ps, int const weaponNum)
2873 helixhorne 837
{
4699 terminx 838
    if ((ps->weaponswitch & (1|4)) == (1|4))
2975 hendricks2 839
    {
5825 terminx 840
        int const playerNum    = P_Get(ps->i);
5821 terminx 841
        int       new_wchoice  = -1;
842
        int       curr_wchoice = -1;
2975 hendricks2 843
 
6575 terminx 844
        for (native_t i=0; i<=FREEZE_WEAPON && (new_wchoice < 0 || curr_wchoice < 0); i++)
2975 hendricks2 845
        {
5825 terminx 846
            int w = g_player[playerNum].wchoice[i];
2975 hendricks2 847
 
4215 helixhorne 848
            if (w == KNEE_WEAPON)
849
                w = FREEZE_WEAPON;
6895 terminx 850
            else
851
                w--;
2975 hendricks2 852
 
853
            if (w == ps->curr_weapon)
854
                curr_wchoice = i;
5825 terminx 855
            if (w == weaponNum)
2975 hendricks2 856
                new_wchoice = i;
857
        }
858
 
5825 terminx 859
        P_AddWeapon(ps, weaponNum, (new_wchoice < curr_wchoice));
2975 hendricks2 860
    }
861
    else
4216 helixhorne 862
    {
5825 terminx 863
        P_AddWeapon(ps, weaponNum, (ps->weaponswitch & 1));
4216 helixhorne 864
    }
2873 helixhorne 865
}
866
 
3520 helixhorne 867
#if defined LUNATIC
6895 terminx 868
void        P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap) { P_AddWeaponMaybeSwitch(g_player[snum].ps, weap); }
3520 helixhorne 869
#else
6232 terminx 870
static void P_AddWeaponAmmoCommon(DukePlayer_t * const pPlayer, int const weaponNum, int const nAmount)
2873 helixhorne 871
{
5826 terminx 872
    P_AddAmmo(pPlayer, weaponNum, nAmount);
2873 helixhorne 873
 
5825 terminx 874
    if (PWEAPON(vm.playerNum, pPlayer->curr_weapon, WorksLike) == KNEE_WEAPON && (pPlayer->gotweapon & (1 << weaponNum)))
875
        P_AddWeaponMaybeSwitch(pPlayer, weaponNum);
2873 helixhorne 876
}
877
 
6321 hendricks2 878
static void VM_AddWeapon(DukePlayer_t * const pPlayer, int const weaponNum, int const nAmount)
2873 helixhorne 879
{
5825 terminx 880
    if (EDUKE32_PREDICT_FALSE((unsigned)weaponNum >= MAX_WEAPONS))
2873 helixhorne 881
    {
6345 terminx 882
        CON_ERRPRINTF("invalid weapon %d\n", weaponNum);
6321 hendricks2 883
        return;
2873 helixhorne 884
    }
885
 
5825 terminx 886
    if ((pPlayer->gotweapon & (1 << weaponNum)) == 0)
2873 helixhorne 887
    {
5825 terminx 888
        P_AddWeaponMaybeSwitch(pPlayer, weaponNum);
2873 helixhorne 889
    }
5825 terminx 890
    else if (pPlayer->ammo_amount[weaponNum] >= pPlayer->max_ammo_amount[weaponNum])
2873 helixhorne 891
    {
5825 terminx 892
        vm.flags |= VM_NOEXECUTE;
6321 hendricks2 893
        return;
2873 helixhorne 894
    }
895
 
5825 terminx 896
    P_AddWeaponAmmoCommon(pPlayer, weaponNum, nAmount);
6321 hendricks2 897
}
2873 helixhorne 898
 
6321 hendricks2 899
static void VM_AddAmmo(DukePlayer_t * const pPlayer, int const weaponNum, int const nAmount)
900
{
901
    if (EDUKE32_PREDICT_FALSE((unsigned)weaponNum >= MAX_WEAPONS))
902
    {
6345 terminx 903
        CON_ERRPRINTF("invalid weapon %d\n", weaponNum);
6321 hendricks2 904
        return;
905
    }
906
 
907
    if (pPlayer->ammo_amount[weaponNum] >= pPlayer->max_ammo_amount[weaponNum])
908
    {
909
        vm.flags |= VM_NOEXECUTE;
910
        return;
911
    }
912
 
913
    P_AddWeaponAmmoCommon(pPlayer, weaponNum, nAmount);
2873 helixhorne 914
}
6320 hendricks2 915
 
916
static void VM_AddInventory(DukePlayer_t * const pPlayer, int const itemNum, int const nAmount)
917
{
918
    switch (itemNum)
919
    {
920
    case GET_STEROIDS:
921
    case GET_SCUBA:
922
    case GET_HOLODUKE:
923
    case GET_JETPACK:
924
    case GET_HEATS:
925
    case GET_FIRSTAID:
926
    case GET_BOOTS:
927
        pPlayer->inven_icon = inv_to_icon[itemNum];
928
        pPlayer->inv_amount[itemNum] = nAmount;
929
        break;
930
 
931
    case GET_SHIELD:
932
    {
933
        int16_t & shield_amount = pPlayer->inv_amount[GET_SHIELD];
934
        shield_amount = min(shield_amount + nAmount, pPlayer->max_shield_amount);
935
        break;
936
    }
937
 
938
    case GET_ACCESS:
939
        switch (vm.pSprite->pal)
940
        {
6895 terminx 941
                case 0: pPlayer->got_access |= 1; break;
942
                case 21: pPlayer->got_access |= 2; break;
943
                case 23: pPlayer->got_access |= 4; break;
6320 hendricks2 944
        }
945
        break;
946
 
6895 terminx 947
        default: CON_ERRPRINTF("invalid inventory item %d\n", itemNum); break;
6320 hendricks2 948
    }
949
}
3354 helixhorne 950
#endif
2873 helixhorne 951
 
7202 terminx 952
static int A_GetVerticalVel(actor_t const * const pActor)
4954 helixhorne 953
{
954
#ifdef LUNATIC
5821 terminx 955
    return pActor->mv.vvel;
4954 helixhorne 956
#else
5821 terminx 957
    int32_t moveScriptOfs = AC_MOVE_ID(pActor->t_data);
4954 helixhorne 958
 
5825 terminx 959
    return ((unsigned) moveScriptOfs < (unsigned) g_scriptSize - 1) ? apScript[moveScriptOfs + 1] : 0;
4954 helixhorne 960
#endif
961
}
962
 
6232 terminx 963
static int32_t A_GetWaterZOffset(int const spriteNum)
4954 helixhorne 964
{
7603 terminx 965
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
7259 terminx 966
    auto const pActor  = &actor[spriteNum];
4954 helixhorne 967
 
5821 terminx 968
    if (sector[pSprite->sectnum].lotag == ST_1_ABOVE_WATER)
4954 helixhorne 969
    {
5825 terminx 970
        if (A_CheckSpriteFlags(spriteNum, SFLAG_NOWATERDIP))
4954 helixhorne 971
            return 0;
972
 
973
        // fix for flying/jumping monsters getting stuck in water
5821 terminx 974
        if ((AC_MOVFLAGS(pSprite, pActor) & jumptoplayer_only) || (G_HaveActor(pSprite->picnum) && A_GetVerticalVel(pActor) != 0))
4954 helixhorne 975
            return 0;
976
 
977
        return ACTOR_ONWATER_ADDZ;
978
    }
979
 
980
    return 0;
981
}
982
 
6232 terminx 983
static void VM_Fall(int const spriteNum, spritetype * const pSprite)
3252 helixhorne 984
{
5834 terminx 985
    int spriteGravity = g_spriteGravity;
3684 helixhorne 986
 
5821 terminx 987
    pSprite->xoffset = pSprite->yoffset = 0;
3252 helixhorne 988
 
5821 terminx 989
    if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(pSprite->sectnum)))
5834 terminx 990
        spriteGravity = g_spriteGravity/6;
5821 terminx 991
    else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(pSprite->sectnum)))
5834 terminx 992
        spriteGravity = 0;
3684 helixhorne 993
 
5825 terminx 994
    if (!actor[spriteNum].cgg-- || (sector[pSprite->sectnum].floorstat&2))
995
        actor[spriteNum].cgg = 3;
3252 helixhorne 996
 
7952 terminx 997
    A_GetZLimits(spriteNum);
998
 
5825 terminx 999
    if (pSprite->z < actor[spriteNum].floorz-ZOFFSET)
3684 helixhorne 1000
    {
1001
        // Free fall.
5834 terminx 1002
        pSprite->zvel = min(pSprite->zvel+spriteGravity, ACTOR_MAXFALLINGZVEL);
1003
        int newZ = pSprite->z + pSprite->zvel;
4953 helixhorne 1004
 
3252 helixhorne 1005
#ifdef YAX_ENABLE
6895 terminx 1006
        if (yax_getbunch(pSprite->sectnum, YAX_FLOOR) >= 0 && (sector[pSprite->sectnum].floorstat & 512) == 0)
7697 terminx 1007
            setspritez(spriteNum, &pSprite->pos);
3684 helixhorne 1008
        else
3252 helixhorne 1009
#endif
5825 terminx 1010
            if (newZ > actor[spriteNum].floorz - ZOFFSET)
1011
                newZ = actor[spriteNum].floorz - ZOFFSET;
4953 helixhorne 1012
 
5825 terminx 1013
        pSprite->z = newZ;
3684 helixhorne 1014
        return;
1015
    }
3679 helixhorne 1016
 
4953 helixhorne 1017
    // Preliminary new z position of the actor.
5834 terminx 1018
    int newZ = actor[spriteNum].floorz - ZOFFSET;
3252 helixhorne 1019
 
5821 terminx 1020
    if (A_CheckEnemySprite(pSprite) || (pSprite->picnum == APLAYER && pSprite->owner >= 0))
3684 helixhorne 1021
    {
5821 terminx 1022
        if (pSprite->zvel > 3084 && pSprite->extra <= 1)
3252 helixhorne 1023
        {
3684 helixhorne 1024
            // I'm guessing this DRONE check is from a beta version of the game
1025
            // where they crashed into the ground when killed
6911 terminx 1026
#ifndef EDUKE32_STANDALONE
7911 terminx 1027
            if (!FURY && !(pSprite->picnum == APLAYER && pSprite->extra > 0) && pSprite->pal != 1 && pSprite->picnum != DRONE)
3252 helixhorne 1028
            {
5825 terminx 1029
                A_DoGuts(spriteNum,JIBS6,15);
1030
                A_PlaySound(SQUISHED,spriteNum);
1031
                A_Spawn(spriteNum,BLOODPOOL);
3252 helixhorne 1032
            }
6911 terminx 1033
#endif
5825 terminx 1034
            actor[spriteNum].picnum = SHOTSPARK1;
1035
            actor[spriteNum].extra = 1;
5821 terminx 1036
            pSprite->zvel = 0;
3684 helixhorne 1037
        }
5821 terminx 1038
        else if (pSprite->zvel > 2048 && sector[pSprite->sectnum].lotag != ST_1_ABOVE_WATER)
3684 helixhorne 1039
        {
5821 terminx 1040
            int16_t newsect = pSprite->sectnum;
3679 helixhorne 1041
 
7697 terminx 1042
            pushmove(&pSprite->pos, &newsect, 128, 4<<8, 4<<8, CLIPMASK0);
3684 helixhorne 1043
            if ((unsigned)newsect < MAXSECTORS)
5825 terminx 1044
                changespritesect(spriteNum, newsect);
3684 helixhorne 1045
 
5825 terminx 1046
            A_PlaySound(THUD, spriteNum);
3252 helixhorne 1047
        }
1048
    }
1049
 
7952 terminx 1050
    if (sector[pSprite->sectnum].lotag == ST_1_ABOVE_WATER && actor[spriteNum].floorz == getcorrectflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y))
3252 helixhorne 1051
    {
5825 terminx 1052
        pSprite->z = newZ + A_GetWaterZOffset(spriteNum);
3252 helixhorne 1053
        return;
1054
    }
3459 helixhorne 1055
 
5825 terminx 1056
    pSprite->z = newZ;
5821 terminx 1057
    pSprite->zvel = 0;
3252 helixhorne 1058
}
1059
 
6232 terminx 1060
static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags, int32_t const resetFlags)
3252 helixhorne 1061
{
1062
    //AddLog("resetplayer");
5825 terminx 1063
    if (!g_netServer && ud.multimode < 2 && !(resetFlags & 2))
3252 helixhorne 1064
    {
6823 hendricks2 1065
        if (g_quickload && g_quickload->isValid() && ud.recstat != 2 && !(resetFlags & 8))
3252 helixhorne 1066
        {
6677 hendricks2 1067
            if (resetFlags & 4)
1068
            {
1069
                KB_FlushKeyboardQueue();
1070
                KB_ClearKeysDown();
1071
                FX_StopAllSounds();
1072
                S_ClearSoundLocks();
6761 hendricks2 1073
                if (G_LoadPlayerMaybeMulti(*g_quickload) != 0)
1074
                {
1075
                    g_quickload->reset();
1076
                    goto QuickLoadFailure;
1077
                }
6677 hendricks2 1078
            }
1079
            else if (!(resetFlags & 1))
1080
            {
1081
                Menu_Open(playerNum);
1082
                KB_ClearKeyDown(sc_Space);
1083
                I_AdvanceTriggerClear();
1084
                Menu_Change(MENU_RESETPLAYER);
1085
            }
3252 helixhorne 1086
        }
6761 hendricks2 1087
        else
1088
        {
1089
            QuickLoadFailure:
1090
            g_player[playerNum].ps->gm = MODE_RESTART;
1091
        }
3946 helixhorne 1092
#if !defined LUNATIC
5825 terminx 1093
        vmFlags |= VM_NOEXECUTE;
3946 helixhorne 1094
#endif
3252 helixhorne 1095
    }
1096
    else
1097
    {
5825 terminx 1098
        if (playerNum == myconnectindex)
3252 helixhorne 1099
        {
3405 helixhorne 1100
            CAMERADIST = 0;
8050 pogokeen 1101
            CAMERACLOCK = (int32_t) totalclock;
3252 helixhorne 1102
        }
1103
 
1104
        if (g_fakeMultiMode)
7172 terminx 1105
            P_ResetMultiPlayer(playerNum);
3260 helixhorne 1106
#ifndef NETCODE_DISABLE
3252 helixhorne 1107
        if (g_netServer)
1108
        {
7172 terminx 1109
            P_ResetMultiPlayer(playerNum);
5825 terminx 1110
            Net_SpawnPlayer(playerNum);
3252 helixhorne 1111
        }
3260 helixhorne 1112
#endif
3252 helixhorne 1113
    }
3460 helixhorne 1114
 
5825 terminx 1115
    P_UpdateScreenPal(g_player[playerNum].ps);
3252 helixhorne 1116
    //AddLog("EOF: resetplayer");
3460 helixhorne 1117
 
5825 terminx 1118
    return vmFlags;
3252 helixhorne 1119
}
1120
 
6232 terminx 1121
void G_GetTimeDate(int32_t * const pValues)
3486 helixhorne 1122
{
5825 terminx 1123
    time_t timeStruct;
1124
    time(&timeStruct);
1125
    struct tm *pTime = localtime(&timeStruct);
3486 helixhorne 1126
 
1127
    // initprintf("Time&date: %s\n",asctime (ti));
1128
 
5825 terminx 1129
    pValues[0] = pTime->tm_sec;
1130
    pValues[1] = pTime->tm_min;
1131
    pValues[2] = pTime->tm_hour;
1132
    pValues[3] = pTime->tm_mday;
1133
    pValues[4] = pTime->tm_mon;
1134
    pValues[5] = pTime->tm_year+1900;
1135
    pValues[6] = pTime->tm_wday;
1136
    pValues[7] = pTime->tm_yday;
3486 helixhorne 1137
}
1138
 
6414 hendricks2 1139
static int G_StartTrackSlot(int const volumeNum, int const levelNum)
3490 helixhorne 1140
{
6414 hendricks2 1141
    if ((unsigned)volumeNum <= MAXVOLUMES && (unsigned)levelNum < MAXLEVELS)
3490 helixhorne 1142
    {
6414 hendricks2 1143
        int trackNum = MAXLEVELS*volumeNum + levelNum;
3490 helixhorne 1144
 
6619 hendricks2 1145
        return S_TryPlaySpecialMusic(trackNum);
3490 helixhorne 1146
    }
1147
 
1148
    return 1;
1149
}
1150
 
6426 hendricks2 1151
#ifndef LUNATIC
6623 hendricks2 1152
static int G_StartTrackSlotWrap(int const volumeNum, int const levelNum)
6414 hendricks2 1153
{
1154
    if (EDUKE32_PREDICT_FALSE(G_StartTrackSlot(volumeNum, levelNum)))
6623 hendricks2 1155
    {
6895 terminx 1156
        CON_ERRPRINTF("invalid level %d or null music for volume %d level %d\n", levelNum, volumeNum, levelNum);
6623 hendricks2 1157
        return 1;
1158
    }
1159
 
1160
    return 0;
6414 hendricks2 1161
}
6426 hendricks2 1162
#else
6895 terminx 1163
int G_StartTrack(int const levelNum) { return G_StartTrackSlot(ud.volume_number, levelNum); }
6414 hendricks2 1164
#endif
1165
 
8366 terminx 1166
LUNATIC_EXTERN void G_ShowView(vec3_t vec, fix16_t a, fix16_t horiz, int sect, int ix1, int iy1, int ix2, int iy2, int unbiasedp)
3861 helixhorne 1167
{
7491 hendricks2 1168
    int x1 = min(ix1, ix2);
1169
    int x2 = max(ix1, ix2);
1170
    int y1 = min(iy1, iy2);
1171
    int y2 = max(iy1, iy2);
3861 helixhorne 1172
 
1173
    if (!unbiasedp)
1174
    {
1175
        // The showview command has a rounding bias towards zero,
1176
        // e.g. floor((319*1680)/320) == 1674
1177
        x1 = scale(x1,xdim,320);
1178
        y1 = scale(y1,ydim,200);
1179
        x2 = scale(x2,xdim,320);
1180
        y2 = scale(y2,ydim,200);
1181
    }
1182
    else
1183
    {
1184
        // This will map the maximum 320-based coordinate to the
1185
        // maximum real screen coordinate:
1186
        // floor((319*1679)/319) == 1679
1187
        x1 = scale(x1,xdim-1,319);
1188
        y1 = scale(y1,ydim-1,199);
1189
        x2 = scale(x2,xdim-1,319);
1190
        y2 = scale(y2,ydim-1,199);
1191
    }
1192
 
6727 terminx 1193
    horiz = fix16_clamp(horiz, F16(HORIZ_MIN), F16(HORIZ_MAX));
1194
 
7350 terminx 1195
    int const viewingRange = viewingrange;
1196
    int const yxAspect = yxaspect;
1197
 
6828 terminx 1198
    videoSetViewableArea(x1,y1,x2,y2);
7350 terminx 1199
    renderSetAspect(viewingRange, yxAspect);
5821 terminx 1200
    int const smoothratio = calc_smoothratio(totalclock, ototalclock);
3861 helixhorne 1201
    G_DoInterpolations(smoothratio);
7733 pogokeen 1202
    if (!display_mirror)
1203
        G_HandleMirror(vec.x, vec.y, vec.z, a, horiz, smoothratio);
3861 helixhorne 1204
#ifdef POLYMER
6829 terminx 1205
    if (videoGetRenderMode() == REND_POLYMER)
8428 hendricks2 1206
        polymer_setanimatesprites(G_DoSpriteAnimations, vec.x, vec.y, vec.z, fix16_to_int(a), smoothratio);
3861 helixhorne 1207
#endif
1208
    yax_preparedrawrooms();
6831 terminx 1209
    renderDrawRoomsQ16(vec.x, vec.y, vec.z, a, horiz, sect);
3861 helixhorne 1210
    yax_drawrooms(G_DoSpriteAnimations, sect, 0, smoothratio);
1211
 
1212
    display_mirror = 2;
8428 hendricks2 1213
    G_DoSpriteAnimations(vec.x, vec.y, vec.z, fix16_to_int(a), smoothratio);
3861 helixhorne 1214
    display_mirror = 0;
6831 terminx 1215
    renderDrawMasks();
3861 helixhorne 1216
    G_RestoreInterpolations();
1217
    G_UpdateScreenArea();
7350 terminx 1218
    renderSetAspect(viewingRange, yxAspect);
3861 helixhorne 1219
}
1220
 
6508 hendricks2 1221
void Screen_Play(void)
1222
{
7202 terminx 1223
    bool running = true;
6508 hendricks2 1224
 
1225
    I_ClearAllInput();
1226
 
1227
    do
1228
    {
8139 terminx 1229
        gameHandleEvents();
6508 hendricks2 1230
 
6648 hendricks2 1231
        ototalclock = totalclock + 1; // pause game like ANMs
1232
 
6641 hendricks2 1233
        if (!G_FPSLimit())
1234
            continue;
1235
 
6828 terminx 1236
        videoClearScreen(0);
7202 terminx 1237
 
7951 terminx 1238
        if (VM_OnEventWithReturn(EVENT_SCREEN, -1, myconnectindex, I_CheckAllInput()))
7202 terminx 1239
            running = false;
6508 hendricks2 1240
 
7730 pogokeen 1241
        videoNextPage();
6508 hendricks2 1242
        I_ClearAllInput();
1243
    } while (running);
1244
}
1245
 
3410 helixhorne 1246
#if !defined LUNATIC
7358 hendricks2 1247
#if defined __GNUC__ || defined __clang__
7647 terminx 1248
# define CON_USE_COMPUTED_GOTO
7358 hendricks2 1249
#endif
7382 terminx 1250
 
7647 terminx 1251
#ifdef CON_USE_COMPUTED_GOTO
7358 hendricks2 1252
# define vInstruction(KEYWORDID) VINST_ ## KEYWORDID
7631 terminx 1253
# define vmErrorCase VINST_CON_OPCODE_END
7658 terminx 1254
# define eval(INSTRUCTION) { goto *jumpTable[min<uint16_t>(INSTRUCTION, CON_OPCODE_END)]; }
1255
# define dispatch_unconditionally(...) { g_tw = tw = *insptr; eval((VM_DECODE_INST(tw))) }
7647 terminx 1256
# define dispatch(...) { if (vm_execution_depth && (vm.flags & (VM_RETURN|VM_KILL|VM_NOEXECUTE)) == 0) dispatch_unconditionally(__VA_ARGS__); return; }
7378 terminx 1257
# define abort_after_error(...) return
7358 hendricks2 1258
# define vInstructionPointer(KEYWORDID) &&VINST_ ## KEYWORDID
1259
# define COMMA ,
1260
# define JUMP_TABLE_ARRAY_LITERAL { TRANSFORM_SCRIPT_KEYWORDS_LIST(vInstructionPointer, COMMA) }
1261
#else
7357 hendricks2 1262
# define vInstruction(KEYWORDID) case KEYWORDID
7631 terminx 1263
# define vmErrorCase default
7646 terminx 1264
# define dispatch_unconditionally(...) continue
7378 terminx 1265
# define dispatch(...) continue
7357 hendricks2 1266
# define eval(INSTRUCTION) switch(INSTRUCTION)
7378 terminx 1267
# define abort_after_error(...) continue // non-threaded dispatch handles this in the loop condition in VM_Execute()
7358 hendricks2 1268
#endif
7357 hendricks2 1269
 
7638 terminx 1270
#define VM_ASSERT(condition, ...)                \
1271
    do                                           \
1272
    {                                            \
1273
        if (EDUKE32_PREDICT_FALSE(!(condition))) \
1274
        {                                        \
1275
            CON_ERRPRINTF(__VA_ARGS__);          \
1276
            abort_after_error();                 \
1277
        }                                        \
1278
    } while (0)
1279
 
7655 terminx 1280
// be careful when changing this--the assignment used as a condition doubles as a null pointer check
1281
#define VM_CONDITIONAL(xxx)                                                                       \
1282
    do                                                                                            \
1283
    {                                                                                             \
7658 terminx 1284
        if ((xxx) || ((insptr = (intptr_t *)insptr[1]) && (VM_DECODE_INST(*insptr) == CON_ELSE))) \
7655 terminx 1285
        {                                                                                         \
1286
            insptr += 2;                                                                          \
1287
            VM_Execute();                                                                         \
1288
        }                                                                                         \
1289
    } while (0)
1290
 
8366 terminx 1291
GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
5 Plagman 1292
{
7658 terminx 1293
    int vm_execution_depth = loop;
1294
#ifdef CON_USE_COMPUTED_GOTO
1295
    static void *const jumpTable[] = JUMP_TABLE_ARRAY_LITERAL;
1296
#else
7261 terminx 1297
    do
1436 terminx 1298
    {
7358 hendricks2 1299
#endif
7658 terminx 1300
        int32_t tw = *insptr;
1301
        g_tw = tw;
1436 terminx 1302
 
7658 terminx 1303
        eval(VM_DECODE_INST(tw))
430 terminx 1304
        {
7358 hendricks2 1305
            vInstruction(CON_LEFTBRACE):
1306
            {
7647 terminx 1307
                insptr++, vm_execution_depth++;
7378 terminx 1308
                dispatch_unconditionally();
7358 hendricks2 1309
            }
1310
 
1311
            vInstruction(CON_RIGHTBRACE):
1312
            {
7647 terminx 1313
                insptr++, vm_execution_depth--;
7377 terminx 1314
                dispatch();
7358 hendricks2 1315
            }
1316
 
1317
            vInstruction(CON_ELSE):
1318
            {
1319
                insptr = (intptr_t *)insptr[1];
7378 terminx 1320
                dispatch_unconditionally();
7358 hendricks2 1321
            }
7646 terminx 1322
 
7382 terminx 1323
            vInstruction(CON_STATE):
7646 terminx 1324
            {
1325
                auto tempscrptr = &insptr[2];
1326
                insptr = (intptr_t *)insptr[1];
1327
                VM_Execute(true);
1328
                insptr = tempscrptr;
1329
            }
1330
            dispatch();
7358 hendricks2 1331
 
7382 terminx 1332
#ifdef CON_DISCRETE_VAR_ACCESS
7357 hendricks2 1333
            vInstruction(CON_IFVARE_GLOBAL):
6895 terminx 1334
                insptr++;
7266 terminx 1335
                tw = aGameVars[*insptr++].global;
1336
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1337
                dispatch();
7357 hendricks2 1338
            vInstruction(CON_IFVARN_GLOBAL):
7266 terminx 1339
                insptr++;
1340
                tw = aGameVars[*insptr++].global;
1341
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1342
                dispatch();
7357 hendricks2 1343
            vInstruction(CON_IFVARAND_GLOBAL):
7266 terminx 1344
                insptr++;
1345
                tw = aGameVars[*insptr++].global;
1346
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1347
                dispatch();
7357 hendricks2 1348
            vInstruction(CON_IFVAROR_GLOBAL):
7266 terminx 1349
                insptr++;
1350
                tw = aGameVars[*insptr++].global;
1351
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1352
                dispatch();
7357 hendricks2 1353
            vInstruction(CON_IFVARXOR_GLOBAL):
7266 terminx 1354
                insptr++;
1355
                tw = aGameVars[*insptr++].global;
1356
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1357
                dispatch();
7357 hendricks2 1358
            vInstruction(CON_IFVAREITHER_GLOBAL):
7266 terminx 1359
                insptr++;
1360
                tw = aGameVars[*insptr++].global;
1361
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1362
                dispatch();
7357 hendricks2 1363
            vInstruction(CON_IFVARBOTH_GLOBAL):
7266 terminx 1364
                insptr++;
1365
                tw = aGameVars[*insptr++].global;
1366
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1367
                dispatch();
7357 hendricks2 1368
            vInstruction(CON_IFVARG_GLOBAL):
7266 terminx 1369
                insptr++;
1370
                tw = aGameVars[*insptr++].global;
1371
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1372
                dispatch();
7357 hendricks2 1373
            vInstruction(CON_IFVARGE_GLOBAL):
7266 terminx 1374
                insptr++;
1375
                tw = aGameVars[*insptr++].global;
1376
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1377
                dispatch();
7357 hendricks2 1378
            vInstruction(CON_IFVARL_GLOBAL):
7266 terminx 1379
                insptr++;
1380
                tw = aGameVars[*insptr++].global;
1381
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1382
                dispatch();
7357 hendricks2 1383
            vInstruction(CON_IFVARLE_GLOBAL):
7266 terminx 1384
                insptr++;
1385
                tw = aGameVars[*insptr++].global;
1386
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1387
                dispatch();
7357 hendricks2 1388
            vInstruction(CON_IFVARA_GLOBAL):
7266 terminx 1389
                insptr++;
1390
                tw = aGameVars[*insptr++].global;
1391
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1392
                dispatch();
7357 hendricks2 1393
            vInstruction(CON_IFVARAE_GLOBAL):
7266 terminx 1394
                insptr++;
1395
                tw = aGameVars[*insptr++].global;
1396
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1397
                dispatch();
7357 hendricks2 1398
            vInstruction(CON_IFVARB_GLOBAL):
7266 terminx 1399
                insptr++;
1400
                tw = aGameVars[*insptr++].global;
1401
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1402
                dispatch();
7357 hendricks2 1403
            vInstruction(CON_IFVARBE_GLOBAL):
7266 terminx 1404
                insptr++;
1405
                tw = aGameVars[*insptr++].global;
1406
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1407
                dispatch();
5825 terminx 1408
 
7357 hendricks2 1409
            vInstruction(CON_SETVAR_GLOBAL):
7263 terminx 1410
                insptr++;
1411
                aGameVars[*insptr].global = insptr[1];
1412
                insptr += 2;
7377 terminx 1413
                dispatch();
7357 hendricks2 1414
            vInstruction(CON_ADDVAR_GLOBAL):
6895 terminx 1415
                insptr++;
7266 terminx 1416
                aGameVars[*insptr].global += insptr[1];
1417
                insptr += 2;
7377 terminx 1418
                dispatch();
7357 hendricks2 1419
            vInstruction(CON_SUBVAR_GLOBAL):
7263 terminx 1420
                insptr++;
7266 terminx 1421
                aGameVars[*insptr].global -= insptr[1];
7263 terminx 1422
                insptr += 2;
7377 terminx 1423
                dispatch();
7357 hendricks2 1424
            vInstruction(CON_MULVAR_GLOBAL):
7263 terminx 1425
                insptr++;
7266 terminx 1426
                aGameVars[*insptr].global *= insptr[1];
7263 terminx 1427
                insptr += 2;
7377 terminx 1428
                dispatch();
7357 hendricks2 1429
            vInstruction(CON_ANDVAR_GLOBAL):
6895 terminx 1430
                insptr++;
7266 terminx 1431
                aGameVars[*insptr].global &= insptr[1];
1432
                insptr += 2;
7377 terminx 1433
                dispatch();
7357 hendricks2 1434
            vInstruction(CON_XORVAR_GLOBAL):
7263 terminx 1435
                insptr++;
7266 terminx 1436
                aGameVars[*insptr].global ^= insptr[1];
7263 terminx 1437
                insptr += 2;
7377 terminx 1438
                dispatch();
7357 hendricks2 1439
            vInstruction(CON_ORVAR_GLOBAL):
7263 terminx 1440
                insptr++;
7266 terminx 1441
                aGameVars[*insptr].global |= insptr[1];
7263 terminx 1442
                insptr += 2;
7377 terminx 1443
                dispatch();
7357 hendricks2 1444
            vInstruction(CON_SHIFTVARL_GLOBAL):
7266 terminx 1445
                insptr++;
1446
                aGameVars[*insptr].global <<= insptr[1];
1447
                insptr += 2;
7377 terminx 1448
                dispatch();
7357 hendricks2 1449
            vInstruction(CON_SHIFTVARR_GLOBAL):
7266 terminx 1450
                insptr++;
1451
                aGameVars[*insptr].global >>= insptr[1];
1452
                insptr += 2;
7377 terminx 1453
                dispatch();
7263 terminx 1454
 
7357 hendricks2 1455
            vInstruction(CON_IFVARE_ACTOR):
6895 terminx 1456
                insptr++;
7266 terminx 1457
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1458
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1459
                dispatch();
7357 hendricks2 1460
            vInstruction(CON_IFVARN_ACTOR):
7266 terminx 1461
                insptr++;
1462
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1463
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1464
                dispatch();
7357 hendricks2 1465
            vInstruction(CON_IFVARAND_ACTOR):
7266 terminx 1466
                insptr++;
1467
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1468
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1469
                dispatch();
7357 hendricks2 1470
            vInstruction(CON_IFVAROR_ACTOR):
7266 terminx 1471
                insptr++;
1472
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1473
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1474
                dispatch();
7357 hendricks2 1475
            vInstruction(CON_IFVARXOR_ACTOR):
7266 terminx 1476
                insptr++;
1477
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1478
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1479
                dispatch();
7357 hendricks2 1480
            vInstruction(CON_IFVAREITHER_ACTOR):
7266 terminx 1481
                insptr++;
1482
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1483
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1484
                dispatch();
7357 hendricks2 1485
            vInstruction(CON_IFVARBOTH_ACTOR):
7266 terminx 1486
                insptr++;
1487
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1488
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1489
                dispatch();
7357 hendricks2 1490
            vInstruction(CON_IFVARG_ACTOR):
7266 terminx 1491
                insptr++;
1492
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1493
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1494
                dispatch();
7357 hendricks2 1495
            vInstruction(CON_IFVARGE_ACTOR):
7266 terminx 1496
                insptr++;
1497
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1498
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1499
                dispatch();
7357 hendricks2 1500
            vInstruction(CON_IFVARL_ACTOR):
7266 terminx 1501
                insptr++;
1502
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1503
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1504
                dispatch();
7357 hendricks2 1505
            vInstruction(CON_IFVARLE_ACTOR):
7266 terminx 1506
                insptr++;
1507
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1508
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1509
                dispatch();
7357 hendricks2 1510
            vInstruction(CON_IFVARA_ACTOR):
7266 terminx 1511
                insptr++;
1512
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1513
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1514
                dispatch();
7357 hendricks2 1515
            vInstruction(CON_IFVARAE_ACTOR):
7266 terminx 1516
                insptr++;
1517
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1518
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1519
                dispatch();
7357 hendricks2 1520
            vInstruction(CON_IFVARB_ACTOR):
7266 terminx 1521
                insptr++;
1522
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1523
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1524
                dispatch();
7357 hendricks2 1525
            vInstruction(CON_IFVARBE_ACTOR):
7266 terminx 1526
                insptr++;
1527
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1528
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1529
                dispatch();
5 Plagman 1530
 
7357 hendricks2 1531
            vInstruction(CON_SETVAR_ACTOR):
6895 terminx 1532
                insptr++;
7266 terminx 1533
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] = insptr[1];
1534
                insptr += 2;
7377 terminx 1535
                dispatch();
7357 hendricks2 1536
            vInstruction(CON_ADDVAR_ACTOR):
7266 terminx 1537
                insptr++;
1538
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] += insptr[1];
1539
                insptr += 2;
7377 terminx 1540
                dispatch();
7357 hendricks2 1541
            vInstruction(CON_SUBVAR_ACTOR):
7266 terminx 1542
                insptr++;
1543
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] -= insptr[1];
1544
                insptr += 2;
7377 terminx 1545
                dispatch();
7357 hendricks2 1546
            vInstruction(CON_MULVAR_ACTOR):
7266 terminx 1547
                insptr++;
1548
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] *= insptr[1];
1549
                insptr += 2;
7377 terminx 1550
                dispatch();
7357 hendricks2 1551
            vInstruction(CON_ANDVAR_ACTOR):
7266 terminx 1552
                insptr++;
1553
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] &= insptr[1];
1554
                insptr += 2;
7377 terminx 1555
                dispatch();
7357 hendricks2 1556
            vInstruction(CON_XORVAR_ACTOR):
7266 terminx 1557
                insptr++;
1558
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] ^= insptr[1];
1559
                insptr += 2;
7377 terminx 1560
                dispatch();
7357 hendricks2 1561
            vInstruction(CON_ORVAR_ACTOR):
7266 terminx 1562
                insptr++;
1563
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] |= insptr[1];
1564
                insptr += 2;
7377 terminx 1565
                dispatch();
7357 hendricks2 1566
            vInstruction(CON_SHIFTVARL_ACTOR):
7266 terminx 1567
                insptr++;
1568
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] <<= insptr[1];
1569
                insptr += 2;
7377 terminx 1570
                dispatch();
7357 hendricks2 1571
            vInstruction(CON_SHIFTVARR_ACTOR):
7266 terminx 1572
                insptr++;
1573
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] >>= insptr[1];
1574
                insptr += 2;
7377 terminx 1575
                dispatch();
1436 terminx 1576
 
7357 hendricks2 1577
            vInstruction(CON_IFVARE_PLAYER):
6895 terminx 1578
                insptr++;
7266 terminx 1579
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1580
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1581
                dispatch();
7357 hendricks2 1582
            vInstruction(CON_IFVARN_PLAYER):
7266 terminx 1583
                insptr++;
1584
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1585
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1586
                dispatch();
7357 hendricks2 1587
            vInstruction(CON_IFVARAND_PLAYER):
7266 terminx 1588
                insptr++;
1589
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1590
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1591
                dispatch();
7357 hendricks2 1592
            vInstruction(CON_IFVAROR_PLAYER):
7266 terminx 1593
                insptr++;
1594
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1595
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1596
                dispatch();
7357 hendricks2 1597
            vInstruction(CON_IFVARXOR_PLAYER):
7266 terminx 1598
                insptr++;
1599
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1600
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1601
                dispatch();
7357 hendricks2 1602
            vInstruction(CON_IFVAREITHER_PLAYER):
7266 terminx 1603
                insptr++;
1604
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1605
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1606
                dispatch();
7357 hendricks2 1607
            vInstruction(CON_IFVARBOTH_PLAYER):
7266 terminx 1608
                insptr++;
1609
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1610
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1611
                dispatch();
7357 hendricks2 1612
            vInstruction(CON_IFVARG_PLAYER):
7266 terminx 1613
                insptr++;
1614
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1615
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1616
                dispatch();
7357 hendricks2 1617
            vInstruction(CON_IFVARGE_PLAYER):
7266 terminx 1618
                insptr++;
1619
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1620
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1621
                dispatch();
7357 hendricks2 1622
            vInstruction(CON_IFVARL_PLAYER):
7266 terminx 1623
                insptr++;
1624
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1625
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1626
                dispatch();
7357 hendricks2 1627
            vInstruction(CON_IFVARLE_PLAYER):
7266 terminx 1628
                insptr++;
1629
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1630
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1631
                dispatch();
7357 hendricks2 1632
            vInstruction(CON_IFVARA_PLAYER):
7266 terminx 1633
                insptr++;
1634
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1635
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1636
                dispatch();
7357 hendricks2 1637
            vInstruction(CON_IFVARAE_PLAYER):
7266 terminx 1638
                insptr++;
1639
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1640
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1641
                dispatch();
7357 hendricks2 1642
            vInstruction(CON_IFVARB_PLAYER):
7266 terminx 1643
                insptr++;
1644
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1645
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1646
                dispatch();
7357 hendricks2 1647
            vInstruction(CON_IFVARBE_PLAYER):
7266 terminx 1648
                insptr++;
1649
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1650
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1651
                dispatch();
1436 terminx 1652
 
7357 hendricks2 1653
            vInstruction(CON_SETVAR_PLAYER):
7263 terminx 1654
                insptr++;
7266 terminx 1655
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] = insptr[1];
7263 terminx 1656
                insptr += 2;
7377 terminx 1657
                dispatch();
7357 hendricks2 1658
            vInstruction(CON_ADDVAR_PLAYER):
7263 terminx 1659
                insptr++;
7266 terminx 1660
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] += insptr[1];
7263 terminx 1661
                insptr += 2;
7377 terminx 1662
                dispatch();
7357 hendricks2 1663
            vInstruction(CON_SUBVAR_PLAYER):
6895 terminx 1664
                insptr++;
7266 terminx 1665
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] -= insptr[1];
1666
                insptr += 2;
7377 terminx 1667
                dispatch();
7357 hendricks2 1668
            vInstruction(CON_MULVAR_PLAYER):
7266 terminx 1669
                insptr++;
1670
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] *= insptr[1];
1671
                insptr += 2;
7377 terminx 1672
                dispatch();
7357 hendricks2 1673
            vInstruction(CON_ANDVAR_PLAYER):
7266 terminx 1674
                insptr++;
1675
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] &= insptr[1];
1676
                insptr += 2;
7377 terminx 1677
                dispatch();
7357 hendricks2 1678
            vInstruction(CON_XORVAR_PLAYER):
7266 terminx 1679
                insptr++;
1680
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] ^= insptr[1];
1681
                insptr += 2;
7377 terminx 1682
                dispatch();
7357 hendricks2 1683
            vInstruction(CON_ORVAR_PLAYER):
7266 terminx 1684
                insptr++;
1685
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] |= insptr[1];
1686
                insptr += 2;
7377 terminx 1687
                dispatch();
7357 hendricks2 1688
            vInstruction(CON_SHIFTVARL_PLAYER):
7266 terminx 1689
                insptr++;
1690
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] <<= insptr[1];
1691
                insptr += 2;
7377 terminx 1692
                dispatch();
7357 hendricks2 1693
            vInstruction(CON_SHIFTVARR_PLAYER):
7266 terminx 1694
                insptr++;
1695
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] >>= insptr[1];
1696
                insptr += 2;
7377 terminx 1697
                dispatch();
1436 terminx 1698
 
7357 hendricks2 1699
            vInstruction(CON_WHILEVARN_GLOBAL):
7266 terminx 1700
            {
1701
                auto const savedinsptr = &insptr[2];
1702
                do
1703
                {
1704
                    insptr = savedinsptr;
1705
                    tw = (aGameVars[insptr[-1]].global != *insptr);
1706
                    VM_CONDITIONAL(tw);
1707
                } while (tw);
7377 terminx 1708
                dispatch();
7266 terminx 1709
            }
1710
 
7357 hendricks2 1711
            vInstruction(CON_WHILEVARL_GLOBAL):
7266 terminx 1712
            {
1713
                auto const savedinsptr = &insptr[2];
1714
                do
1715
                {
1716
                    insptr = savedinsptr;
1717
                    tw = (aGameVars[insptr[-1]].global < *insptr);
1718
                    VM_CONDITIONAL(tw);
1719
                } while (tw);
7377 terminx 1720
                dispatch();
7266 terminx 1721
            }
1722
 
7357 hendricks2 1723
            vInstruction(CON_WHILEVARN_ACTOR):
7266 terminx 1724
            {
1725
                auto const savedinsptr = &insptr[2];
1726
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.spriteNum & (MAXSPRITES-1)];
1727
                do
1728
                {
1729
                    insptr = savedinsptr;
1730
                    tw = (v != *insptr);
1731
                    VM_CONDITIONAL(tw);
1732
                } while (tw);
1733
 
7377 terminx 1734
                dispatch();
7266 terminx 1735
            }
1736
 
7357 hendricks2 1737
            vInstruction(CON_WHILEVARL_ACTOR):
7266 terminx 1738
            {
1739
                auto const savedinsptr = &insptr[2];
1740
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.spriteNum & (MAXSPRITES-1)];
1741
                do
1742
                {
1743
                    insptr = savedinsptr;
1744
                    tw = (v < *insptr);
1745
                    VM_CONDITIONAL(tw);
1746
                } while (tw);
1747
 
7377 terminx 1748
                dispatch();
7266 terminx 1749
            }
1750
 
7357 hendricks2 1751
            vInstruction(CON_WHILEVARN_PLAYER):
7266 terminx 1752
            {
1753
                auto const savedinsptr = &insptr[2];
1754
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.playerNum & (MAXPLAYERS-1)];
1755
                do
1756
                {
1757
                    insptr = savedinsptr;
1758
                    tw = (v != *insptr);
1759
                    VM_CONDITIONAL(tw);
1760
                } while (tw);
1761
 
7377 terminx 1762
                dispatch();
7266 terminx 1763
            }
1764
 
7357 hendricks2 1765
            vInstruction(CON_WHILEVARL_PLAYER):
7266 terminx 1766
            {
1767
                auto const savedinsptr = &insptr[2];
1768
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.playerNum & (MAXPLAYERS-1)];
1769
                do
1770
                {
1771
                    insptr = savedinsptr;
1772
                    tw = (v < *insptr);
1773
                    VM_CONDITIONAL(tw);
1774
                } while (tw);
1775
 
7377 terminx 1776
                dispatch();
7266 terminx 1777
            }
1778
 
7357 hendricks2 1779
            vInstruction(CON_MODVAR_GLOBAL):
7263 terminx 1780
                insptr++;
7266 terminx 1781
                aGameVars[*insptr].global %= insptr[1];
7263 terminx 1782
                insptr += 2;
7377 terminx 1783
                dispatch();
7357 hendricks2 1784
            vInstruction(CON_MODVAR_ACTOR):
7263 terminx 1785
                insptr++;
7266 terminx 1786
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] %= insptr[1];
7263 terminx 1787
                insptr += 2;
7377 terminx 1788
                dispatch();
7357 hendricks2 1789
            vInstruction(CON_MODVAR_PLAYER):
6895 terminx 1790
                insptr++;
7266 terminx 1791
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] %= insptr[1];
1792
                insptr += 2;
7377 terminx 1793
                dispatch();
7355 hendricks2 1794
#endif
1436 terminx 1795
 
7357 hendricks2 1796
            vInstruction(CON_IFVARAND):
6895 terminx 1797
                insptr++;
7652 terminx 1798
                tw = Gv_GetVar(*insptr++);
7266 terminx 1799
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1800
                dispatch();
4902 terminx 1801
 
7357 hendricks2 1802
            vInstruction(CON_IFVAROR):
7265 terminx 1803
                insptr++;
7652 terminx 1804
                tw = Gv_GetVar(*insptr++);
7266 terminx 1805
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1806
                dispatch();
7265 terminx 1807
 
7357 hendricks2 1808
            vInstruction(CON_IFVARXOR):
6895 terminx 1809
                insptr++;
7652 terminx 1810
                tw = Gv_GetVar(*insptr++);
7266 terminx 1811
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1812
                dispatch();
1909 terminx 1813
 
7357 hendricks2 1814
            vInstruction(CON_IFVAREITHER):
7265 terminx 1815
                insptr++;
7652 terminx 1816
                tw = Gv_GetVar(*insptr++);
7266 terminx 1817
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1818
                dispatch();
7265 terminx 1819
 
7357 hendricks2 1820
            vInstruction(CON_IFVARBOTH):
6895 terminx 1821
                insptr++;
7652 terminx 1822
                tw = Gv_GetVar(*insptr++);
7266 terminx 1823
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1824
                dispatch();
51 terminx 1825
 
7357 hendricks2 1826
            vInstruction(CON_IFRND):
7266 terminx 1827
                VM_CONDITIONAL(rnd(*(++insptr)));
7377 terminx 1828
                dispatch();
5 Plagman 1829
 
7357 hendricks2 1830
            vInstruction(CON_IFVARG):
6895 terminx 1831
                insptr++;
7652 terminx 1832
                tw = Gv_GetVar(*insptr++);
7266 terminx 1833
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1834
                dispatch();
1440 terminx 1835
 
7357 hendricks2 1836
            vInstruction(CON_IFVARGE):
6895 terminx 1837
                insptr++;
7652 terminx 1838
                tw = Gv_GetVar(*insptr++);
7266 terminx 1839
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1840
                dispatch();
51 terminx 1841
 
7357 hendricks2 1842
            vInstruction(CON_IFVARL):
6895 terminx 1843
                insptr++;
7652 terminx 1844
                tw = Gv_GetVar(*insptr++);
7266 terminx 1845
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1846
                dispatch();
5 Plagman 1847
 
7357 hendricks2 1848
            vInstruction(CON_IFVARLE):
6895 terminx 1849
                insptr++;
7652 terminx 1850
                tw = Gv_GetVar(*insptr++);
7266 terminx 1851
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1852
                dispatch();
5 Plagman 1853
 
7357 hendricks2 1854
            vInstruction(CON_IFVARA):
6895 terminx 1855
                insptr++;
7652 terminx 1856
                tw = Gv_GetVar(*insptr++);
7266 terminx 1857
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1858
                dispatch();
337 terminx 1859
 
7357 hendricks2 1860
            vInstruction(CON_IFVARAE):
6895 terminx 1861
                insptr++;
7652 terminx 1862
                tw = Gv_GetVar(*insptr++);
7266 terminx 1863
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1864
                dispatch();
5 Plagman 1865
 
7357 hendricks2 1866
            vInstruction(CON_IFVARB):
6895 terminx 1867
                insptr++;
7652 terminx 1868
                tw = Gv_GetVar(*insptr++);
7266 terminx 1869
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1870
                dispatch();
1436 terminx 1871
 
7357 hendricks2 1872
            vInstruction(CON_IFVARBE):
6895 terminx 1873
                insptr++;
7652 terminx 1874
                tw = Gv_GetVar(*insptr++);
7266 terminx 1875
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1876
                dispatch();
335 terminx 1877
 
7357 hendricks2 1878
            vInstruction(CON_SETVARVAR):
6895 terminx 1879
                insptr++;
7266 terminx 1880
                {
1881
                    tw = *insptr++;
7652 terminx 1882
                    int const nValue = Gv_GetVar(*insptr++);
7266 terminx 1883
 
1884
                    if ((aGameVars[tw].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0)
1885
                        aGameVars[tw].global = nValue;
1886
                    else
7653 terminx 1887
                        Gv_SetVar(tw, nValue);
7266 terminx 1888
                }
7377 terminx 1889
                dispatch();
335 terminx 1890
 
7357 hendricks2 1891
            vInstruction(CON_ADDVARVAR):
7265 terminx 1892
                insptr++;
7266 terminx 1893
                tw = *insptr++;
7652 terminx 1894
                Gv_AddVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1895
                dispatch();
7265 terminx 1896
 
7357 hendricks2 1897
            vInstruction(CON_SUBVARVAR):
6895 terminx 1898
                insptr++;
7266 terminx 1899
                tw = *insptr++;
7652 terminx 1900
                Gv_SubVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1901
                dispatch();
335 terminx 1902
 
7357 hendricks2 1903
            vInstruction(CON_ANDVARVAR):
7265 terminx 1904
                insptr++;
7266 terminx 1905
                tw = *insptr++;
7652 terminx 1906
                Gv_AndVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1907
                dispatch();
7265 terminx 1908
 
7357 hendricks2 1909
            vInstruction(CON_XORVARVAR):
6895 terminx 1910
                insptr++;
7266 terminx 1911
                tw = *insptr++;
7652 terminx 1912
                Gv_XorVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1913
                dispatch();
335 terminx 1914
 
7357 hendricks2 1915
            vInstruction(CON_ORVARVAR):
7265 terminx 1916
                insptr++;
7266 terminx 1917
                tw = *insptr++;
7652 terminx 1918
                Gv_OrVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1919
                dispatch();
7265 terminx 1920
 
7357 hendricks2 1921
            vInstruction(CON_SHIFTVARVARL):
6895 terminx 1922
                insptr++;
7266 terminx 1923
                tw = *insptr++;
7652 terminx 1924
                Gv_ShiftVarL(tw, Gv_GetVar(*insptr++));
7377 terminx 1925
                dispatch();
2451 helixhorne 1926
 
7357 hendricks2 1927
            vInstruction(CON_SHIFTVARVARR):
7265 terminx 1928
                insptr++;
7266 terminx 1929
                tw = *insptr++;
7652 terminx 1930
                Gv_ShiftVarR(tw, Gv_GetVar(*insptr++));
7377 terminx 1931
                dispatch();
7265 terminx 1932
 
7357 hendricks2 1933
            vInstruction(CON_MULVARVAR):
6895 terminx 1934
                insptr++;
7266 terminx 1935
                tw = *insptr++;
7652 terminx 1936
                Gv_MulVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1937
                dispatch();
2451 helixhorne 1938
 
7382 terminx 1939
#ifdef CON_DISCRETE_VAR_ACCESS
7357 hendricks2 1940
            vInstruction(CON_DIVVAR_GLOBAL):
7265 terminx 1941
                insptr++;
7266 terminx 1942
                aGameVars[*insptr].global = tabledivide32(aGameVars[*insptr].global, insptr[1]);
1943
                insptr += 2;
7377 terminx 1944
                dispatch();
7265 terminx 1945
 
7357 hendricks2 1946
            vInstruction(CON_DIVVAR_PLAYER):
7266 terminx 1947
            {
6895 terminx 1948
                insptr++;
7266 terminx 1949
                auto &v = aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS - 1)];
3920 helixhorne 1950
 
7266 terminx 1951
                v = tabledivide32(v, insptr[1]);
1952
                insptr += 2;
7377 terminx 1953
                dispatch();
7266 terminx 1954
            }
3920 helixhorne 1955
 
7357 hendricks2 1956
            vInstruction(CON_DIVVAR_ACTOR):
7266 terminx 1957
            {
7265 terminx 1958
                insptr++;
7266 terminx 1959
                auto &v = aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES - 1)];
1960
 
1961
                v = tabledivide32(v, insptr[1]);
1962
                insptr += 2;
7377 terminx 1963
                dispatch();
7266 terminx 1964
            }
7355 hendricks2 1965
#endif
7265 terminx 1966
 
7357 hendricks2 1967
            vInstruction(CON_DIVVARVAR):
6895 terminx 1968
                insptr++;
7266 terminx 1969
                {
1970
                    tw = *insptr++;
1971
 
7652 terminx 1972
                    int const nValue = Gv_GetVar(*insptr++);
7266 terminx 1973
 
7638 terminx 1974
                    VM_ASSERT(nValue, "divide by zero!\n");
7266 terminx 1975
 
1976
                    Gv_DivVar(tw, nValue);
7377 terminx 1977
                    dispatch();
7266 terminx 1978
                }
1979
 
7357 hendricks2 1980
            vInstruction(CON_IFVARE):
7266 terminx 1981
                insptr++;
7652 terminx 1982
                tw = Gv_GetVar(*insptr++);
7266 terminx 1983
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1984
                dispatch();
5 Plagman 1985
 
7357 hendricks2 1986
            vInstruction(CON_IFVARN):
7265 terminx 1987
                insptr++;
7652 terminx 1988
                tw = Gv_GetVar(*insptr++);
7266 terminx 1989
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1990
                dispatch();
7265 terminx 1991
 
7357 hendricks2 1992
            vInstruction(CON_IFVARVARE):
6895 terminx 1993
                insptr++;
7652 terminx 1994
                tw = Gv_GetVar(*insptr++);
1995
                tw = (tw == Gv_GetVar(*insptr++));
7266 terminx 1996
                insptr--;
1997
                VM_CONDITIONAL(tw);
7377 terminx 1998
                dispatch();
5 Plagman 1999
 
7357 hendricks2 2000
            vInstruction(CON_IFVARVARN):
7265 terminx 2001
                insptr++;
7652 terminx 2002
                tw = Gv_GetVar(*insptr++);
2003
                tw = (tw != Gv_GetVar(*insptr++));
7266 terminx 2004
                insptr--;
2005
                VM_CONDITIONAL(tw);
7377 terminx 2006
                dispatch();
7265 terminx 2007
 
7357 hendricks2 2008
            vInstruction(CON_IFVARVARG):
6895 terminx 2009
                insptr++;
7652 terminx 2010
                tw = Gv_GetVar(*insptr++);
2011
                tw = (tw > Gv_GetVar(*insptr++));
7266 terminx 2012
                insptr--;
2013
                VM_CONDITIONAL(tw);
7377 terminx 2014
                dispatch();
3803 terminx 2015
 
7357 hendricks2 2016
            vInstruction(CON_IFVARVARGE):
7265 terminx 2017
                insptr++;
7652 terminx 2018
                tw = Gv_GetVar(*insptr++);
2019
                tw = (tw >= Gv_GetVar(*insptr++));
7266 terminx 2020
                insptr--;
2021
                VM_CONDITIONAL(tw);
7377 terminx 2022
                dispatch();
7265 terminx 2023
 
7357 hendricks2 2024
            vInstruction(CON_IFVARVARL):
6895 terminx 2025
                insptr++;
7652 terminx 2026
                tw = Gv_GetVar(*insptr++);
2027
                tw = (tw < Gv_GetVar(*insptr++));
7266 terminx 2028
                insptr--;
2029
                VM_CONDITIONAL(tw);
7377 terminx 2030
                dispatch();
5 Plagman 2031
 
7357 hendricks2 2032
            vInstruction(CON_IFVARVARLE):
7265 terminx 2033
                insptr++;
7652 terminx 2034
                tw = Gv_GetVar(*insptr++);
2035
                tw = (tw <= Gv_GetVar(*insptr++));
7266 terminx 2036
                insptr--;
2037
                VM_CONDITIONAL(tw);
7377 terminx 2038
                dispatch();
7265 terminx 2039
 
7357 hendricks2 2040
            vInstruction(CON_IFVARVARA):
6895 terminx 2041
                insptr++;
7652 terminx 2042
                tw = Gv_GetVar(*insptr++);
2043
                tw = ((uint32_t)tw > (uint32_t)Gv_GetVar(*insptr++));
7266 terminx 2044
                insptr--;
2045
                VM_CONDITIONAL(tw);
7377 terminx 2046
                dispatch();
51 terminx 2047
 
7357 hendricks2 2048
            vInstruction(CON_IFVARVARAE):
7265 terminx 2049
                insptr++;
7652 terminx 2050
                tw = Gv_GetVar(*insptr++);
2051
                tw = ((uint32_t)tw >= (uint32_t)Gv_GetVar(*insptr++));
7266 terminx 2052
                insptr--;
2053
                VM_CONDITIONAL(tw);
7377 terminx 2054
                dispatch();
7265 terminx 2055
 
7357 hendricks2 2056
            vInstruction(CON_IFVARVARB):
6895 terminx 2057
                insptr++;
7652 terminx 2058
                tw = Gv_GetVar(*insptr++);
2059
                tw = ((uint32_t)tw < (uint32_t)Gv_GetVar(*insptr++));
7266 terminx 2060
                insptr--;
2061
                VM_CONDITIONAL(tw);
7377 terminx 2062
                dispatch();
51 terminx 2063
 
7357 hendricks2 2064
            vInstruction(CON_IFVARVARBE):
7265 terminx 2065
                insptr++;
7652 terminx 2066
                tw = Gv_GetVar(*insptr++);
2067
                tw = ((uint32_t)tw <= (uint32_t)Gv_GetVar(*insptr++));
7266 terminx 2068
                insptr--;
2069
                VM_CONDITIONAL(tw);
7377 terminx 2070
                dispatch();
7265 terminx 2071
 
7357 hendricks2 2072
            vInstruction(CON_IFVARVARAND):