Subversion Repositories eduke32

Rev

Rev 8734 | 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"
8734 terminx 26
#include "communityapi.h"
6074 hendricks2 27
#include "compat.h"
5611 terminx 28
#include "duke3d.h"
8734 terminx 29
#include "gamestructures.h"
6895 terminx 30
#include "input.h"
31
#include "menus.h"
32
#include "osdcmds.h"
33
#include "savegame.h"
5 Plagman 34
#include "scriplib.h"
35
 
2721 helixhorne 36
#ifdef LUNATIC
3148 helixhorne 37
# include "lunatic_game.h"
2329 helixhorne 38
#endif
39
 
7359 hendricks2 40
#include "vfs.h"
41
 
1595 helixhorne 42
#if KRANDDEBUG
43
# define GAMEEXEC_INLINE
44
# define GAMEEXEC_STATIC
45
#else
46
# define GAMEEXEC_INLINE inline
47
# define GAMEEXEC_STATIC static
48
#endif
49
 
3946 helixhorne 50
vmstate_t vm;
51
 
52
#if !defined LUNATIC
3460 helixhorne 53
int32_t g_tw;
7205 terminx 54
int32_t g_currentEvent = -1;
1956 helixhorne 55
 
4988 terminx 56
intptr_t const *insptr;
4902 terminx 57
 
5825 terminx 58
int32_t g_returnVarID    = -1;  // var ID of "RETURN"
59
int32_t g_weaponVarID    = -1;  // var ID of "WEAPON"
60
int32_t g_worksLikeVarID = -1;  // var ID of "WORKSLIKE"
61
int32_t g_zRangeVarID    = -1;  // var ID of "ZRANGE"
62
int32_t g_angRangeVarID  = -1;  // var ID of "ANGRANGE"
63
int32_t g_aimAngleVarID  = -1;  // var ID of "AUTOAIMANGLE"
64
int32_t g_lotagVarID     = -1;  // var ID of "LOTAG"
65
int32_t g_hitagVarID     = -1;  // var ID of "HITAG"
66
int32_t g_textureVarID   = -1;  // var ID of "TEXTURE"
67
int32_t g_thisActorVarID = -1;  // var ID of "THISACTOR"
68
int32_t g_structVarIDs   = -1;
4902 terminx 69
 
6736 terminx 70
// for timing events and actors
71
uint32_t g_eventCalls[MAXEVENTS], g_actorCalls[MAXTILES];
72
double g_eventTotalMs[MAXEVENTS], g_actorTotalMs[MAXTILES], g_actorMinMs[MAXTILES], g_actorMaxMs[MAXTILES];
73
 
8366 terminx 74
GAMEEXEC_STATIC void VM_Execute(int const loop = false);
617 terminx 75
 
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];
8636 terminx 390
    int const  ocstat  = pSprite->cstat;
5 Plagman 391
 
5825 terminx 392
    pSprite->cstat = 0;
8637 terminx 393
    pSprite->z -= ACTOR_FLOOR_OFFSET;
1217 terminx 394
 
7697 terminx 395
    getzrange(&pSprite->pos, pSprite->sectnum, &actor[spriteNum].ceilingz, ceilhit, &actor[spriteNum].floorz, florhit, wallDist, CLIPMASK0);
5 Plagman 396
 
8637 terminx 397
    pSprite->z += ACTOR_FLOOR_OFFSET;
5825 terminx 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;
8636 terminx 405
    int const  clipDist = A_GetClipdist(spriteNum, -1);
406
    auto const oceilz   = actor[spriteNum].ceilingz;
1217 terminx 407
 
7436 terminx 408
    VM_GetZRange(spriteNum, &ceilhit, &florhit, pSprite->statnum == STAT_PROJECTILE ? clipDist << 3 : clipDist);
5825 terminx 409
    actor[spriteNum].flags &= ~SFLAG_NOFLOORSHADOW;
5015 helixhorne 410
 
411
    if ((florhit&49152) == 49152 && (sprite[florhit&(MAXSPRITES-1)].cstat&48) == 0)
4680 terminx 412
    {
7603 terminx 413
        auto const hitspr = (uspriteptr_t)&sprite[florhit&(MAXSPRITES-1)];
2192 helixhorne 414
 
5015 helixhorne 415
        florhit &= (MAXSPRITES-1);
2192 helixhorne 416
 
5015 helixhorne 417
        // If a non-projectile would fall onto non-frozen enemy OR an enemy onto a player...
5821 terminx 418
        if ((A_CheckEnemySprite(hitspr) && hitspr->pal != 1 && pSprite->statnum != STAT_PROJECTILE)
419
                || (hitspr->picnum == APLAYER && A_CheckEnemySprite(pSprite)))
4680 terminx 420
        {
5825 terminx 421
            actor[spriteNum].flags |= SFLAG_NOFLOORSHADOW;  // No shadows on actors
5821 terminx 422
            pSprite->xvel = -256;  // SLIDE_ABOVE_ENEMY
7667 terminx 423
            A_SetSprite(spriteNum, CLIPMASK0);
5 Plagman 424
        }
5821 terminx 425
        else if (pSprite->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && pSprite->owner==florhit)
1677 terminx 426
        {
5825 terminx 427
            actor[spriteNum].ceilingz = sector[pSprite->sectnum].ceilingz;
428
            actor[spriteNum].floorz   = sector[pSprite->sectnum].floorz;
1677 terminx 429
        }
4680 terminx 430
    }
8636 terminx 431
 
432
    // in E1L1, the dumpster fire sprites break after calling this function because the cardboard boxes
433
    // are a few units higher than the fire and are detected as the "ceiling"
434
    // unfortunately, this trips the "ifgapzl 16 break" in "state firestate"
435
    if ((ceilhit&49152) == 49152 && (sprite[ceilhit&(MAXSPRITES-1)].cstat&48) == 0)
436
    {
437
        if (pSprite->z >= actor[spriteNum].floorz)
438
            actor[spriteNum].ceilingz = oceilz;
439
    }
5 Plagman 440
}
441
 
6232 terminx 442
void A_Fall(int const spriteNum)
5 Plagman 443
{
7259 terminx 444
    auto const pSprite = &sprite[spriteNum];
5825 terminx 445
    int spriteGravity = g_spriteGravity;
5015 helixhorne 446
 
5821 terminx 447
    if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(pSprite->sectnum)))
5825 terminx 448
        spriteGravity = 0;
5821 terminx 449
    else if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(pSprite->sectnum)))
5825 terminx 450
        spriteGravity = g_spriteGravity/6;
5 Plagman 451
 
7952 terminx 452
    int32_t ceilhit, florhit;
453
    VM_GetZRange(spriteNum, &ceilhit, &florhit, A_GetClipdist(spriteNum, -1));
5 Plagman 454
 
1877 helixhorne 455
#ifdef YAX_ENABLE
5821 terminx 456
    int fbunch = (sector[pSprite->sectnum].floorstat&512) ? -1 : yax_getbunch(pSprite->sectnum, YAX_FLOOR);
1877 helixhorne 457
#endif
3682 helixhorne 458
 
8637 terminx 459
    if (pSprite->z < actor[spriteNum].floorz-ACTOR_FLOOR_OFFSET
1877 helixhorne 460
#ifdef YAX_ENABLE
3682 helixhorne 461
            || fbunch >= 0
1877 helixhorne 462
#endif
2652 terminx 463
       )
5 Plagman 464
    {
5821 terminx 465
        if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER && pSprite->zvel > 3122)
466
            pSprite->zvel = 3144;
8637 terminx 467
        pSprite->z += pSprite->zvel = min(ACTOR_MAXFALLINGZVEL, pSprite->zvel+spriteGravity);
5 Plagman 468
    }
3682 helixhorne 469
 
1877 helixhorne 470
#ifdef YAX_ENABLE
471
    if (fbunch >= 0)
7697 terminx 472
        setspritez(spriteNum, &pSprite->pos);
3682 helixhorne 473
    else
1877 helixhorne 474
#endif
8637 terminx 475
        if (pSprite->z >= actor[spriteNum].floorz-ACTOR_FLOOR_OFFSET)
2652 terminx 476
        {
8637 terminx 477
            pSprite->z = actor[spriteNum].floorz-ACTOR_FLOOR_OFFSET;
5821 terminx 478
            pSprite->zvel = 0;
2652 terminx 479
        }
5 Plagman 480
}
481
 
7202 terminx 482
int __fastcall G_GetAngleDelta(int currAngle, int newAngle)
5 Plagman 483
{
5825 terminx 484
    currAngle &= 2047;
485
    newAngle &= 2047;
5 Plagman 486
 
5825 terminx 487
    if (klabs(currAngle-newAngle) < 1024)
521 terminx 488
    {
1143 terminx 489
//        OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
5825 terminx 490
        return newAngle-currAngle;
522 terminx 491
    }
5 Plagman 492
 
6895 terminx 493
    if (newAngle > 1024)
494
        newAngle -= 2048;
495
    if (currAngle > 1024)
496
        currAngle -= 2048;
428 terminx 497
 
1143 terminx 498
//    OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
5825 terminx 499
    return newAngle-currAngle;
5 Plagman 500
}
501
 
6232 terminx 502
GAMEEXEC_STATIC void VM_AlterAng(int32_t const moveFlags)
5 Plagman 503
{
5825 terminx 504
    int const elapsedTics = (AC_COUNT(vm.pData))&31;
5 Plagman 505
 
3459 helixhorne 506
#if !defined LUNATIC
5825 terminx 507
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.pData) >= (unsigned)g_scriptSize-1))
2451 helixhorne 508
 
1685 terminx 509
    {
5825 terminx 510
        AC_MOVE_ID(vm.pData) = 0;
6234 terminx 511
        OSD_Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.spriteNum, vm.pUSprite->picnum);
1686 terminx 512
        return;
1685 terminx 513
    }
514
 
7633 terminx 515
    auto const moveptr = apScript + AC_MOVE_ID(vm.pData);
516
    auto &hvel    = moveptr[0];
517
    auto &vvel    = moveptr[1];
2724 helixhorne 518
#else
7633 terminx 519
    auto &hvel = vm.pActor->mv.hvel;
520
    auto &vvel = vm.pActor->mv.vvel;
2724 helixhorne 521
#endif
5 Plagman 522
 
7633 terminx 523
    vm.pSprite->xvel += (hvel - vm.pSprite->xvel)/5;
524
    if (vm.pSprite->zvel < 648)
525
        vm.pSprite->zvel += ((vvel<<4) - vm.pSprite->zvel)/5;
526
 
5825 terminx 527
    if (A_CheckEnemySprite(vm.pSprite) && vm.pSprite->extra <= 0) // hack
1171 terminx 528
        return;
529
 
5825 terminx 530
    if (moveFlags&seekplayer)
5 Plagman 531
    {
5825 terminx 532
        int const spriteAngle    = vm.pSprite->ang;
6232 terminx 533
        int const holoDukeSprite = vm.pPlayer->holoduke_on;
1048 terminx 534
 
5 Plagman 535
        // NOTE: looks like 'owner' is set to target sprite ID...
536
 
6895 terminx 537
        vm.pSprite->owner = (holoDukeSprite >= 0
538
                             && cansee(sprite[holoDukeSprite].x, sprite[holoDukeSprite].y, sprite[holoDukeSprite].z, sprite[holoDukeSprite].sectnum,
539
                                       vm.pSprite->x, vm.pSprite->y, vm.pSprite->z, vm.pSprite->sectnum))
5853 terminx 540
          ? holoDukeSprite
541
          : vm.pPlayer->i;
5 Plagman 542
 
6232 terminx 543
        int const goalAng = (sprite[vm.pSprite->owner].picnum == APLAYER)
6236 terminx 544
                  ? getangle(vm.pActor->lastv.x - vm.pSprite->x, vm.pActor->lastv.y - vm.pSprite->y)
5853 terminx 545
                  : getangle(sprite[vm.pSprite->owner].x - vm.pSprite->x, sprite[vm.pSprite->owner].y - vm.pSprite->y);
5 Plagman 546
 
5825 terminx 547
        if (vm.pSprite->xvel && vm.pSprite->picnum != DRONE)
5 Plagman 548
        {
6232 terminx 549
            int const angDiff = G_GetAngleDelta(spriteAngle, goalAng);
5 Plagman 550
 
5825 terminx 551
            if (elapsedTics < 2)
5 Plagman 552
            {
5825 terminx 553
                if (klabs(angDiff) < 256)
5 Plagman 554
                {
6236 terminx 555
                    int const angInc = 128-(krand()&256);
556
                    vm.pSprite->ang += angInc;
5825 terminx 557
                    if (A_GetHitscanRange(vm.spriteNum) < 844)
6236 terminx 558
                        vm.pSprite->ang -= angInc;
5 Plagman 559
                }
560
            }
5825 terminx 561
            else if (elapsedTics > 18 && elapsedTics < GAMETICSPERSEC) // choose
5 Plagman 562
            {
6895 terminx 563
                if (klabs(angDiff >> 2) < 128)
564
                    vm.pSprite->ang = goalAng;
565
                else
566
                    vm.pSprite->ang += angDiff >> 2;
5 Plagman 567
            }
568
        }
6895 terminx 569
        else
570
            vm.pSprite->ang = goalAng;
5 Plagman 571
    }
572
 
5825 terminx 573
    if (elapsedTics < 1)
5 Plagman 574
    {
5825 terminx 575
        if (moveFlags&furthestdir)
5 Plagman 576
        {
5825 terminx 577
            vm.pSprite->ang = A_GetFurthestAngle(vm.spriteNum, 2);
578
            vm.pSprite->owner = vm.pPlayer->i;
5 Plagman 579
        }
580
 
5825 terminx 581
        if (moveFlags&fleeenemy)
582
            vm.pSprite->ang = A_GetFurthestAngle(vm.spriteNum, 2);
5 Plagman 583
    }
584
}
585
 
6232 terminx 586
static inline void VM_AddAngle(int const shift, int const goalAng)
2745 helixhorne 587
{
5825 terminx 588
    int angDiff = G_GetAngleDelta(vm.pSprite->ang, goalAng) >> shift;
2745 helixhorne 589
 
5825 terminx 590
    if ((angDiff > -8 && angDiff < 0) || (angDiff < 8 && angDiff > 0))
591
        angDiff <<= 1;
2745 helixhorne 592
 
5825 terminx 593
    vm.pSprite->ang += angDiff;
2745 helixhorne 594
}
595
 
6232 terminx 596
static inline void VM_FacePlayer(int const shift)
2745 helixhorne 597
{
5825 terminx 598
    VM_AddAngle(shift, (vm.pPlayer->newowner >= 0) ? getangle(vm.pPlayer->opos.x - vm.pSprite->x, vm.pPlayer->opos.y - vm.pSprite->y)
599
                                                 : getangle(vm.pPlayer->pos.x - vm.pSprite->x, vm.pPlayer->pos.y - vm.pSprite->y));
2745 helixhorne 600
}
601
 
3666 helixhorne 602
////////// TROR get*zofslope //////////
603
// These rather belong into the engine.
604
 
4745 terminx 605
static int32_t VM_GetCeilZOfSlope(void)
3666 helixhorne 606
{
7905 terminx 607
    vec2_t const vect     = vm.pSprite->pos.vec2;
5825 terminx 608
    int const    sectnum  = vm.pSprite->sectnum;
4745 terminx 609
 
3666 helixhorne 610
#ifdef YAX_ENABLE
611
    if ((sector[sectnum].ceilingstat&512)==0)
612
    {
5821 terminx 613
        int const nsect = yax_getneighborsect(vect.x, vect.y, sectnum, YAX_CEILING);
3666 helixhorne 614
        if (nsect >= 0)
5821 terminx 615
            return getceilzofslope(nsect, vect.x, vect.y);
3666 helixhorne 616
    }
617
#endif
5821 terminx 618
    return getceilzofslope(sectnum, vect.x, vect.y);
3666 helixhorne 619
}
620
 
7227 terminx 621
#ifndef EDUKE32_STANDALONE
4745 terminx 622
static int32_t VM_GetFlorZOfSlope(void)
3666 helixhorne 623
{
7905 terminx 624
    vec2_t const vect    = vm.pSprite->pos.vec2;
5825 terminx 625
    int const    sectnum = vm.pSprite->sectnum;
4745 terminx 626
 
3666 helixhorne 627
#ifdef YAX_ENABLE
628
    if ((sector[sectnum].floorstat&512)==0)
629
    {
5821 terminx 630
        int const nsect = yax_getneighborsect(vect.x, vect.y, sectnum, YAX_FLOOR);
3666 helixhorne 631
        if (nsect >= 0)
5821 terminx 632
            return getflorzofslope(nsect, vect.x, vect.y);
3666 helixhorne 633
    }
634
#endif
5821 terminx 635
    return getflorzofslope(sectnum, vect.x, vect.y);
3666 helixhorne 636
}
7227 terminx 637
#endif
3666 helixhorne 638
 
639
////////////////////
640
 
4955 helixhorne 641
static int32_t A_GetWaterZOffset(int spritenum);
642
 
1625 terminx 643
GAMEEXEC_STATIC void VM_Move(void)
5 Plagman 644
{
6581 hendricks2 645
    auto const movflagsptr = &AC_MOVFLAGS(vm.pSprite, &actor[vm.spriteNum]);
646
    // NOTE: test against -1 commented out and later revived in source history
647
    // XXX: Does its presence/absence break anything? Where are movflags with all bits set created?
7719 terminx 648
    int const movflags = (*movflagsptr == (remove_pointer_t<decltype(movflagsptr)>)-1) ? 0 : *movflagsptr;
5825 terminx 649
    int const deadflag = (A_CheckEnemySprite(vm.pSprite) && vm.pSprite->extra <= 0);
5 Plagman 650
 
5825 terminx 651
    AC_COUNT(vm.pData)++;
5 Plagman 652
 
5825 terminx 653
    if (AC_MOVE_ID(vm.pData) == 0 || movflags == 0)
1171 terminx 654
    {
8724 terminx 655
        if (deadflag)
7973 terminx 656
            setsprite(vm.spriteNum, &vm.pSprite->pos);
8724 terminx 657
 
1171 terminx 658
        return;
659
    }
660
 
8731 terminx 661
    if (!deadflag)
662
    {
663
        if (movflags & face_player)
664
            VM_FacePlayer(2);
1909 terminx 665
 
8731 terminx 666
        if (movflags & spin)
667
            vm.pSprite->ang += sintable[((AC_COUNT(vm.pData) << 3) & 2047)] >> 6;
5 Plagman 668
 
8731 terminx 669
        if (movflags & face_player_slow)
670
            VM_FacePlayer(4);
5 Plagman 671
 
8731 terminx 672
        if ((movflags & jumptoplayer_bits) == jumptoplayer_bits)
673
        {
674
            if (AC_COUNT(vm.pData) < 16)
675
                vm.pSprite->zvel -= (sintable[(512 + (AC_COUNT(vm.pData) << 4)) & 2047] >> 5);
676
        }
5 Plagman 677
 
8731 terminx 678
        if (movflags & face_player_smart)
679
        {
680
            vec2_t const vect = { vm.pPlayer->pos.x + (vm.pPlayer->vel.x / 768), vm.pPlayer->pos.y + (vm.pPlayer->vel.y / 768) };
681
            VM_AddAngle(2, getangle(vect.x - vm.pSprite->x, vect.y - vm.pSprite->y));
682
        }
5 Plagman 683
    }
684
 
3459 helixhorne 685
#if !defined LUNATIC
5825 terminx 686
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.pData) >= (unsigned)g_scriptSize-1))
1684 terminx 687
    {
5825 terminx 688
        AC_MOVE_ID(vm.pData) = 0;
6234 terminx 689
        OSD_Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.spriteNum, vm.pUSprite->picnum);
1686 terminx 690
        return;
1685 terminx 691
    }
5 Plagman 692
 
7259 terminx 693
    auto const moveptr = apScript + AC_MOVE_ID(vm.pData);
7633 terminx 694
    auto &hvel = moveptr[0];
695
    auto &vvel = moveptr[1];
696
#else
697
    auto &hvel = vm.pActor->mv.hvel;
698
    auto &vvel = vm.pActor->mv.vvel;
699
#endif
2185 helixhorne 700
 
6895 terminx 701
    if (movflags & geth)
7633 terminx 702
        vm.pSprite->xvel += (hvel - vm.pSprite->xvel) >> 1;
703
 
6895 terminx 704
    if (movflags & getv)
7633 terminx 705
        vm.pSprite->zvel += (16 * vvel - vm.pSprite->zvel) >> 1;
1820 terminx 706
 
3919 helixhorne 707
    if (movflags&dodgebullet && !deadflag)
5825 terminx 708
        A_Dodge(vm.pSprite);
5 Plagman 709
 
5825 terminx 710
    if (vm.pSprite->picnum != APLAYER)
3919 helixhorne 711
        VM_AlterAng(movflags);
5 Plagman 712
 
5825 terminx 713
    if (vm.pSprite->xvel > -6 && vm.pSprite->xvel < 6)
714
        vm.pSprite->xvel = 0;
5 Plagman 715
 
5825 terminx 716
    int badguyp = A_CheckEnemySprite(vm.pSprite);
5 Plagman 717
 
5825 terminx 718
    if (vm.pSprite->xvel || vm.pSprite->zvel)
5 Plagman 719
    {
5834 terminx 720
        int spriteXvel = vm.pSprite->xvel;
721
        int angDiff    = vm.pSprite->ang;
2745 helixhorne 722
 
7227 terminx 723
#ifndef EDUKE32_STANDALONE
7911 terminx 724
        if (badguyp && (FURY || vm.pSprite->picnum != ROTATEGUN))
5 Plagman 725
        {
7911 terminx 726
            if (!FURY && (vm.pSprite->picnum == DRONE || vm.pSprite->picnum == COMMANDER) && vm.pSprite->extra > 0)
5 Plagman 727
            {
5825 terminx 728
                if (vm.pSprite->picnum == COMMANDER)
5 Plagman 729
                {
5821 terminx 730
                    int32_t nSectorZ;
3663 helixhorne 731
                    // NOTE: COMMANDER updates both actor[].floorz and
732
                    // .ceilingz regardless of its zvel.
6236 terminx 733
                    vm.pActor->floorz = nSectorZ = VM_GetFlorZOfSlope();
5825 terminx 734
                    if (vm.pSprite->z > nSectorZ-ZOFFSET3)
5 Plagman 735
                    {
5825 terminx 736
                        vm.pSprite->z = nSectorZ-ZOFFSET3;
737
                        vm.pSprite->zvel = 0;
5 Plagman 738
                    }
739
 
6236 terminx 740
                    vm.pActor->ceilingz = nSectorZ = VM_GetCeilZOfSlope();
5825 terminx 741
                    if (vm.pSprite->z < nSectorZ+(80<<8))
5 Plagman 742
                    {
5825 terminx 743
                        vm.pSprite->z = nSectorZ+(80<<8);
744
                        vm.pSprite->zvel = 0;
5 Plagman 745
                    }
746
                }
747
                else
748
                {
5821 terminx 749
                    int32_t nSectorZ;
3663 helixhorne 750
                    // The DRONE updates either .floorz or .ceilingz, not both.
5825 terminx 751
                    if (vm.pSprite->zvel > 0)
5 Plagman 752
                    {
6236 terminx 753
                        vm.pActor->floorz = nSectorZ = VM_GetFlorZOfSlope();
5825 terminx 754
                        if (vm.pSprite->z > nSectorZ-(30<<8))
755
                            vm.pSprite->z = nSectorZ-(30<<8);
5 Plagman 756
                    }
757
                    else
758
                    {
6236 terminx 759
                        vm.pActor->ceilingz = nSectorZ = VM_GetCeilZOfSlope();
5825 terminx 760
                        if (vm.pSprite->z < nSectorZ+(50<<8))
5 Plagman 761
                        {
5825 terminx 762
                            vm.pSprite->z = nSectorZ+(50<<8);
763
                            vm.pSprite->zvel = 0;
5 Plagman 764
                        }
765
                    }
766
                }
767
            }
7911 terminx 768
            else if ((FURY && badguyp) || vm.pSprite->picnum != ORGANTIC)
7227 terminx 769
#else
770
        if (badguyp)
771
        {
772
#endif
5 Plagman 773
            {
5014 helixhorne 774
                // All other actors besides ORGANTIC don't update .floorz or
775
                // .ceilingz here.
5825 terminx 776
                if (vm.pSprite->zvel > 0)
5 Plagman 777
                {
6236 terminx 778
                    if (vm.pSprite->z > vm.pActor->floorz)
779
                        vm.pSprite->z = vm.pActor->floorz;
5825 terminx 780
                    vm.pSprite->z += A_GetWaterZOffset(vm.spriteNum);
4953 helixhorne 781
                }
5825 terminx 782
                else if (vm.pSprite->zvel < 0)
4953 helixhorne 783
                {
5821 terminx 784
                    int const l = VM_GetCeilZOfSlope();
5014 helixhorne 785
 
5825 terminx 786
                    if (vm.pSprite->z < l+(66<<8))
5 Plagman 787
                    {
5825 terminx 788
                        vm.pSprite->z = l+(66<<8);
789
                        vm.pSprite->zvel >>= 1;
5 Plagman 790
                    }
791
                }
792
            }
793
 
5825 terminx 794
            if (vm.playerDist < 960 && vm.pSprite->xrepeat > 16)
5 Plagman 795
            {
5834 terminx 796
                spriteXvel = -(1024 - vm.playerDist);
5825 terminx 797
                angDiff = getangle(vm.pPlayer->pos.x - vm.pSprite->x, vm.pPlayer->pos.y - vm.pSprite->y);
5 Plagman 798
 
5825 terminx 799
                if (vm.playerDist < 512)
5 Plagman 800
                {
5825 terminx 801
                    vm.pPlayer->vel.x = 0;
802
                    vm.pPlayer->vel.y = 0;
5 Plagman 803
                }
804
                else
805
                {
5825 terminx 806
                    vm.pPlayer->vel.x = mulscale16(vm.pPlayer->vel.x, vm.pPlayer->runspeed - 0x2000);
807
                    vm.pPlayer->vel.y = mulscale16(vm.pPlayer->vel.y, vm.pPlayer->runspeed - 0x2000);
5 Plagman 808
                }
809
            }
7227 terminx 810
            else
811
#ifndef EDUKE32_STANDALONE
7911 terminx 812
                if (FURY || (vm.pSprite->picnum != DRONE && vm.pSprite->picnum != SHARK && vm.pSprite->picnum != COMMANDER))
7227 terminx 813
#endif
5 Plagman 814
            {
5825 terminx 815
                if (vm.pPlayer->actorsqu == vm.spriteNum)
3920 helixhorne 816
                    return;
3102 terminx 817
 
5825 terminx 818
                if (!A_CheckSpriteFlags(vm.spriteNum, SFLAG_SMOOTHMOVE))
5 Plagman 819
                {
5825 terminx 820
                    if (AC_COUNT(vm.pData) & 1)
3920 helixhorne 821
                        return;
5834 terminx 822
                    spriteXvel <<= 1;
5 Plagman 823
                }
824
            }
825
        }
5825 terminx 826
        else if (vm.pSprite->picnum == APLAYER)
6236 terminx 827
            if (vm.pSprite->z < vm.pActor->ceilingz+ZOFFSET5)
828
                vm.pSprite->z = vm.pActor->ceilingz+ZOFFSET5;
5 Plagman 829
 
6895 terminx 830
        vec3_t const vect
831
        = { (spriteXvel * (sintable[(angDiff + 512) & 2047])) >> 14, (spriteXvel * (sintable[angDiff & 2047])) >> 14, vm.pSprite->zvel };
1207 terminx 832
 
6236 terminx 833
        vm.pActor->movflag = A_MoveSprite(vm.spriteNum, &vect, (A_CheckSpriteFlags(vm.spriteNum, SFLAG_NOCLIP) ? 0 : CLIPMASK0));
5 Plagman 834
    }
835
 
3919 helixhorne 836
    if (!badguyp)
2745 helixhorne 837
        return;
5 Plagman 838
 
5825 terminx 839
    vm.pSprite->shade += (sector[vm.pSprite->sectnum].ceilingstat & 1) ? (sector[vm.pSprite->sectnum].ceilingshade - vm.pSprite->shade) >> 1
840
                                                                 : (sector[vm.pSprite->sectnum].floorshade - vm.pSprite->shade) >> 1;
5 Plagman 841
}
842
 
6232 terminx 843
static void P_AddWeaponMaybeSwitch(DukePlayer_t * const ps, int const weaponNum)
2873 helixhorne 844
{
4699 terminx 845
    if ((ps->weaponswitch & (1|4)) == (1|4))
2975 hendricks2 846
    {
5825 terminx 847
        int const playerNum    = P_Get(ps->i);
5821 terminx 848
        int       new_wchoice  = -1;
849
        int       curr_wchoice = -1;
2975 hendricks2 850
 
6575 terminx 851
        for (native_t i=0; i<=FREEZE_WEAPON && (new_wchoice < 0 || curr_wchoice < 0); i++)
2975 hendricks2 852
        {
5825 terminx 853
            int w = g_player[playerNum].wchoice[i];
2975 hendricks2 854
 
4215 helixhorne 855
            if (w == KNEE_WEAPON)
856
                w = FREEZE_WEAPON;
6895 terminx 857
            else
858
                w--;
2975 hendricks2 859
 
860
            if (w == ps->curr_weapon)
861
                curr_wchoice = i;
5825 terminx 862
            if (w == weaponNum)
2975 hendricks2 863
                new_wchoice = i;
864
        }
865
 
5825 terminx 866
        P_AddWeapon(ps, weaponNum, (new_wchoice < curr_wchoice));
2975 hendricks2 867
    }
868
    else
4216 helixhorne 869
    {
5825 terminx 870
        P_AddWeapon(ps, weaponNum, (ps->weaponswitch & 1));
4216 helixhorne 871
    }
2873 helixhorne 872
}
873
 
3520 helixhorne 874
#if defined LUNATIC
6895 terminx 875
void        P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap) { P_AddWeaponMaybeSwitch(g_player[snum].ps, weap); }
3520 helixhorne 876
#else
6232 terminx 877
static void P_AddWeaponAmmoCommon(DukePlayer_t * const pPlayer, int const weaponNum, int const nAmount)
2873 helixhorne 878
{
5826 terminx 879
    P_AddAmmo(pPlayer, weaponNum, nAmount);
2873 helixhorne 880
 
5825 terminx 881
    if (PWEAPON(vm.playerNum, pPlayer->curr_weapon, WorksLike) == KNEE_WEAPON && (pPlayer->gotweapon & (1 << weaponNum)))
882
        P_AddWeaponMaybeSwitch(pPlayer, weaponNum);
2873 helixhorne 883
}
884
 
6321 hendricks2 885
static void VM_AddWeapon(DukePlayer_t * const pPlayer, int const weaponNum, int const nAmount)
2873 helixhorne 886
{
5825 terminx 887
    if (EDUKE32_PREDICT_FALSE((unsigned)weaponNum >= MAX_WEAPONS))
2873 helixhorne 888
    {
6345 terminx 889
        CON_ERRPRINTF("invalid weapon %d\n", weaponNum);
6321 hendricks2 890
        return;
2873 helixhorne 891
    }
892
 
5825 terminx 893
    if ((pPlayer->gotweapon & (1 << weaponNum)) == 0)
2873 helixhorne 894
    {
5825 terminx 895
        P_AddWeaponMaybeSwitch(pPlayer, weaponNum);
2873 helixhorne 896
    }
5825 terminx 897
    else if (pPlayer->ammo_amount[weaponNum] >= pPlayer->max_ammo_amount[weaponNum])
2873 helixhorne 898
    {
5825 terminx 899
        vm.flags |= VM_NOEXECUTE;
6321 hendricks2 900
        return;
2873 helixhorne 901
    }
902
 
5825 terminx 903
    P_AddWeaponAmmoCommon(pPlayer, weaponNum, nAmount);
6321 hendricks2 904
}
2873 helixhorne 905
 
6321 hendricks2 906
static void VM_AddAmmo(DukePlayer_t * const pPlayer, int const weaponNum, int const nAmount)
907
{
908
    if (EDUKE32_PREDICT_FALSE((unsigned)weaponNum >= MAX_WEAPONS))
909
    {
6345 terminx 910
        CON_ERRPRINTF("invalid weapon %d\n", weaponNum);
6321 hendricks2 911
        return;
912
    }
913
 
914
    if (pPlayer->ammo_amount[weaponNum] >= pPlayer->max_ammo_amount[weaponNum])
915
    {
916
        vm.flags |= VM_NOEXECUTE;
917
        return;
918
    }
919
 
920
    P_AddWeaponAmmoCommon(pPlayer, weaponNum, nAmount);
2873 helixhorne 921
}
6320 hendricks2 922
 
923
static void VM_AddInventory(DukePlayer_t * const pPlayer, int const itemNum, int const nAmount)
924
{
925
    switch (itemNum)
926
    {
927
    case GET_STEROIDS:
928
    case GET_SCUBA:
929
    case GET_HOLODUKE:
930
    case GET_JETPACK:
931
    case GET_HEATS:
932
    case GET_FIRSTAID:
933
    case GET_BOOTS:
934
        pPlayer->inven_icon = inv_to_icon[itemNum];
935
        pPlayer->inv_amount[itemNum] = nAmount;
936
        break;
937
 
938
    case GET_SHIELD:
939
    {
940
        int16_t & shield_amount = pPlayer->inv_amount[GET_SHIELD];
941
        shield_amount = min(shield_amount + nAmount, pPlayer->max_shield_amount);
942
        break;
943
    }
944
 
945
    case GET_ACCESS:
946
        switch (vm.pSprite->pal)
947
        {
6895 terminx 948
                case 0: pPlayer->got_access |= 1; break;
949
                case 21: pPlayer->got_access |= 2; break;
950
                case 23: pPlayer->got_access |= 4; break;
6320 hendricks2 951
        }
952
        break;
953
 
6895 terminx 954
        default: CON_ERRPRINTF("invalid inventory item %d\n", itemNum); break;
6320 hendricks2 955
    }
956
}
3354 helixhorne 957
#endif
2873 helixhorne 958
 
7202 terminx 959
static int A_GetVerticalVel(actor_t const * const pActor)
4954 helixhorne 960
{
961
#ifdef LUNATIC
5821 terminx 962
    return pActor->mv.vvel;
4954 helixhorne 963
#else
5821 terminx 964
    int32_t moveScriptOfs = AC_MOVE_ID(pActor->t_data);
4954 helixhorne 965
 
5825 terminx 966
    return ((unsigned) moveScriptOfs < (unsigned) g_scriptSize - 1) ? apScript[moveScriptOfs + 1] : 0;
4954 helixhorne 967
#endif
968
}
969
 
6232 terminx 970
static int32_t A_GetWaterZOffset(int const spriteNum)
4954 helixhorne 971
{
7603 terminx 972
    auto const pSprite = (uspriteptr_t)&sprite[spriteNum];
7259 terminx 973
    auto const pActor  = &actor[spriteNum];
4954 helixhorne 974
 
5821 terminx 975
    if (sector[pSprite->sectnum].lotag == ST_1_ABOVE_WATER)
4954 helixhorne 976
    {
5825 terminx 977
        if (A_CheckSpriteFlags(spriteNum, SFLAG_NOWATERDIP))
4954 helixhorne 978
            return 0;
979
 
980
        // fix for flying/jumping monsters getting stuck in water
5821 terminx 981
        if ((AC_MOVFLAGS(pSprite, pActor) & jumptoplayer_only) || (G_HaveActor(pSprite->picnum) && A_GetVerticalVel(pActor) != 0))
4954 helixhorne 982
            return 0;
983
 
984
        return ACTOR_ONWATER_ADDZ;
985
    }
986
 
987
    return 0;
988
}
989
 
6232 terminx 990
static void VM_Fall(int const spriteNum, spritetype * const pSprite)
3252 helixhorne 991
{
5834 terminx 992
    int spriteGravity = g_spriteGravity;
3684 helixhorne 993
 
5821 terminx 994
    pSprite->xoffset = pSprite->yoffset = 0;
3252 helixhorne 995
 
5821 terminx 996
    if (sector[pSprite->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(pSprite->sectnum)))
5834 terminx 997
        spriteGravity = g_spriteGravity/6;
5821 terminx 998
    else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(pSprite->sectnum)))
5834 terminx 999
        spriteGravity = 0;
3684 helixhorne 1000
 
5825 terminx 1001
    if (!actor[spriteNum].cgg-- || (sector[pSprite->sectnum].floorstat&2))
1002
        actor[spriteNum].cgg = 3;
3252 helixhorne 1003
 
7952 terminx 1004
    A_GetZLimits(spriteNum);
1005
 
8637 terminx 1006
    if (pSprite->z < actor[spriteNum].floorz-ACTOR_FLOOR_OFFSET)
3684 helixhorne 1007
    {
1008
        // Free fall.
5834 terminx 1009
        pSprite->zvel = min(pSprite->zvel+spriteGravity, ACTOR_MAXFALLINGZVEL);
1010
        int newZ = pSprite->z + pSprite->zvel;
4953 helixhorne 1011
 
3252 helixhorne 1012
#ifdef YAX_ENABLE
6895 terminx 1013
        if (yax_getbunch(pSprite->sectnum, YAX_FLOOR) >= 0 && (sector[pSprite->sectnum].floorstat & 512) == 0)
7697 terminx 1014
            setspritez(spriteNum, &pSprite->pos);
3684 helixhorne 1015
        else
3252 helixhorne 1016
#endif
8637 terminx 1017
            if (newZ > actor[spriteNum].floorz - ACTOR_FLOOR_OFFSET)
1018
                newZ = actor[spriteNum].floorz - ACTOR_FLOOR_OFFSET;
4953 helixhorne 1019
 
5825 terminx 1020
        pSprite->z = newZ;
3684 helixhorne 1021
        return;
1022
    }
3679 helixhorne 1023
 
4953 helixhorne 1024
    // Preliminary new z position of the actor.
8637 terminx 1025
    int newZ = actor[spriteNum].floorz - ACTOR_FLOOR_OFFSET;
3252 helixhorne 1026
 
5821 terminx 1027
    if (A_CheckEnemySprite(pSprite) || (pSprite->picnum == APLAYER && pSprite->owner >= 0))
3684 helixhorne 1028
    {
5821 terminx 1029
        if (pSprite->zvel > 3084 && pSprite->extra <= 1)
3252 helixhorne 1030
        {
3684 helixhorne 1031
            // I'm guessing this DRONE check is from a beta version of the game
1032
            // where they crashed into the ground when killed
6911 terminx 1033
#ifndef EDUKE32_STANDALONE
7911 terminx 1034
            if (!FURY && !(pSprite->picnum == APLAYER && pSprite->extra > 0) && pSprite->pal != 1 && pSprite->picnum != DRONE)
3252 helixhorne 1035
            {
5825 terminx 1036
                A_DoGuts(spriteNum,JIBS6,15);
1037
                A_PlaySound(SQUISHED,spriteNum);
1038
                A_Spawn(spriteNum,BLOODPOOL);
3252 helixhorne 1039
            }
6911 terminx 1040
#endif
5825 terminx 1041
            actor[spriteNum].picnum = SHOTSPARK1;
1042
            actor[spriteNum].extra = 1;
5821 terminx 1043
            pSprite->zvel = 0;
3684 helixhorne 1044
        }
5821 terminx 1045
        else if (pSprite->zvel > 2048 && sector[pSprite->sectnum].lotag != ST_1_ABOVE_WATER)
3684 helixhorne 1046
        {
5821 terminx 1047
            int16_t newsect = pSprite->sectnum;
3679 helixhorne 1048
 
7697 terminx 1049
            pushmove(&pSprite->pos, &newsect, 128, 4<<8, 4<<8, CLIPMASK0);
3684 helixhorne 1050
            if ((unsigned)newsect < MAXSECTORS)
5825 terminx 1051
                changespritesect(spriteNum, newsect);
3684 helixhorne 1052
 
8736 terminx 1053
#ifndef EDUKE32_STANDALONE
1054
            if (!FURY)
1055
                A_PlaySound(THUD, spriteNum);
1056
#endif
3252 helixhorne 1057
        }
1058
    }
1059
 
7952 terminx 1060
    if (sector[pSprite->sectnum].lotag == ST_1_ABOVE_WATER && actor[spriteNum].floorz == getcorrectflorzofslope(pSprite->sectnum, pSprite->x, pSprite->y))
3252 helixhorne 1061
    {
5825 terminx 1062
        pSprite->z = newZ + A_GetWaterZOffset(spriteNum);
3252 helixhorne 1063
        return;
1064
    }
3459 helixhorne 1065
 
5825 terminx 1066
    pSprite->z = newZ;
5821 terminx 1067
    pSprite->zvel = 0;
3252 helixhorne 1068
}
1069
 
6232 terminx 1070
static int32_t VM_ResetPlayer(int const playerNum, int32_t vmFlags, int32_t const resetFlags)
3252 helixhorne 1071
{
1072
    //AddLog("resetplayer");
5825 terminx 1073
    if (!g_netServer && ud.multimode < 2 && !(resetFlags & 2))
3252 helixhorne 1074
    {
6823 hendricks2 1075
        if (g_quickload && g_quickload->isValid() && ud.recstat != 2 && !(resetFlags & 8))
3252 helixhorne 1076
        {
6677 hendricks2 1077
            if (resetFlags & 4)
1078
            {
1079
                KB_FlushKeyboardQueue();
1080
                KB_ClearKeysDown();
1081
                FX_StopAllSounds();
1082
                S_ClearSoundLocks();
6761 hendricks2 1083
                if (G_LoadPlayerMaybeMulti(*g_quickload) != 0)
1084
                {
1085
                    g_quickload->reset();
1086
                    goto QuickLoadFailure;
1087
                }
6677 hendricks2 1088
            }
1089
            else if (!(resetFlags & 1))
1090
            {
1091
                Menu_Open(playerNum);
1092
                KB_ClearKeyDown(sc_Space);
1093
                I_AdvanceTriggerClear();
1094
                Menu_Change(MENU_RESETPLAYER);
1095
            }
3252 helixhorne 1096
        }
6761 hendricks2 1097
        else
1098
        {
1099
            QuickLoadFailure:
1100
            g_player[playerNum].ps->gm = MODE_RESTART;
1101
        }
3946 helixhorne 1102
#if !defined LUNATIC
5825 terminx 1103
        vmFlags |= VM_NOEXECUTE;
3946 helixhorne 1104
#endif
3252 helixhorne 1105
    }
1106
    else
1107
    {
5825 terminx 1108
        if (playerNum == myconnectindex)
3252 helixhorne 1109
        {
3405 helixhorne 1110
            CAMERADIST = 0;
8050 pogokeen 1111
            CAMERACLOCK = (int32_t) totalclock;
3252 helixhorne 1112
        }
1113
 
1114
        if (g_fakeMultiMode)
7172 terminx 1115
            P_ResetMultiPlayer(playerNum);
3260 helixhorne 1116
#ifndef NETCODE_DISABLE
3252 helixhorne 1117
        if (g_netServer)
1118
        {
7172 terminx 1119
            P_ResetMultiPlayer(playerNum);
5825 terminx 1120
            Net_SpawnPlayer(playerNum);
3252 helixhorne 1121
        }
3260 helixhorne 1122
#endif
3252 helixhorne 1123
    }
3460 helixhorne 1124
 
5825 terminx 1125
    P_UpdateScreenPal(g_player[playerNum].ps);
3252 helixhorne 1126
    //AddLog("EOF: resetplayer");
3460 helixhorne 1127
 
5825 terminx 1128
    return vmFlags;
3252 helixhorne 1129
}
1130
 
6232 terminx 1131
void G_GetTimeDate(int32_t * const pValues)
3486 helixhorne 1132
{
5825 terminx 1133
    time_t timeStruct;
1134
    time(&timeStruct);
1135
    struct tm *pTime = localtime(&timeStruct);
3486 helixhorne 1136
 
1137
    // initprintf("Time&date: %s\n",asctime (ti));
1138
 
5825 terminx 1139
    pValues[0] = pTime->tm_sec;
1140
    pValues[1] = pTime->tm_min;
1141
    pValues[2] = pTime->tm_hour;
1142
    pValues[3] = pTime->tm_mday;
1143
    pValues[4] = pTime->tm_mon;
1144
    pValues[5] = pTime->tm_year+1900;
1145
    pValues[6] = pTime->tm_wday;
1146
    pValues[7] = pTime->tm_yday;
3486 helixhorne 1147
}
1148
 
6414 hendricks2 1149
static int G_StartTrackSlot(int const volumeNum, int const levelNum)
3490 helixhorne 1150
{
6414 hendricks2 1151
    if ((unsigned)volumeNum <= MAXVOLUMES && (unsigned)levelNum < MAXLEVELS)
3490 helixhorne 1152
    {
6414 hendricks2 1153
        int trackNum = MAXLEVELS*volumeNum + levelNum;
3490 helixhorne 1154
 
6619 hendricks2 1155
        return S_TryPlaySpecialMusic(trackNum);
3490 helixhorne 1156
    }
1157
 
1158
    return 1;
1159
}
1160
 
6426 hendricks2 1161
#ifndef LUNATIC
6623 hendricks2 1162
static int G_StartTrackSlotWrap(int const volumeNum, int const levelNum)
6414 hendricks2 1163
{
1164
    if (EDUKE32_PREDICT_FALSE(G_StartTrackSlot(volumeNum, levelNum)))
6623 hendricks2 1165
    {
6895 terminx 1166
        CON_ERRPRINTF("invalid level %d or null music for volume %d level %d\n", levelNum, volumeNum, levelNum);
6623 hendricks2 1167
        return 1;
1168
    }
1169
 
1170
    return 0;
6414 hendricks2 1171
}
6426 hendricks2 1172
#else
6895 terminx 1173
int G_StartTrack(int const levelNum) { return G_StartTrackSlot(ud.volume_number, levelNum); }
6414 hendricks2 1174
#endif
1175
 
8366 terminx 1176
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 1177
{
7491 hendricks2 1178
    int x1 = min(ix1, ix2);
1179
    int x2 = max(ix1, ix2);
1180
    int y1 = min(iy1, iy2);
1181
    int y2 = max(iy1, iy2);
3861 helixhorne 1182
 
1183
    if (!unbiasedp)
1184
    {
1185
        // The showview command has a rounding bias towards zero,
1186
        // e.g. floor((319*1680)/320) == 1674
1187
        x1 = scale(x1,xdim,320);
1188
        y1 = scale(y1,ydim,200);
1189
        x2 = scale(x2,xdim,320);
1190
        y2 = scale(y2,ydim,200);
1191
    }
1192
    else
1193
    {
1194
        // This will map the maximum 320-based coordinate to the
1195
        // maximum real screen coordinate:
1196
        // floor((319*1679)/319) == 1679
1197
        x1 = scale(x1,xdim-1,319);
1198
        y1 = scale(y1,ydim-1,199);
1199
        x2 = scale(x2,xdim-1,319);
1200
        y2 = scale(y2,ydim-1,199);
1201
    }
1202
 
6727 terminx 1203
    horiz = fix16_clamp(horiz, F16(HORIZ_MIN), F16(HORIZ_MAX));
1204
 
7350 terminx 1205
    int const viewingRange = viewingrange;
1206
    int const yxAspect = yxaspect;
1207
 
6828 terminx 1208
    videoSetViewableArea(x1,y1,x2,y2);
7350 terminx 1209
    renderSetAspect(viewingRange, yxAspect);
5821 terminx 1210
    int const smoothratio = calc_smoothratio(totalclock, ototalclock);
3861 helixhorne 1211
    G_DoInterpolations(smoothratio);
7733 pogokeen 1212
    if (!display_mirror)
1213
        G_HandleMirror(vec.x, vec.y, vec.z, a, horiz, smoothratio);
3861 helixhorne 1214
#ifdef POLYMER
6829 terminx 1215
    if (videoGetRenderMode() == REND_POLYMER)
8428 hendricks2 1216
        polymer_setanimatesprites(G_DoSpriteAnimations, vec.x, vec.y, vec.z, fix16_to_int(a), smoothratio);
3861 helixhorne 1217
#endif
1218
    yax_preparedrawrooms();
6831 terminx 1219
    renderDrawRoomsQ16(vec.x, vec.y, vec.z, a, horiz, sect);
3861 helixhorne 1220
    yax_drawrooms(G_DoSpriteAnimations, sect, 0, smoothratio);
1221
 
1222
    display_mirror = 2;
8428 hendricks2 1223
    G_DoSpriteAnimations(vec.x, vec.y, vec.z, fix16_to_int(a), smoothratio);
3861 helixhorne 1224
    display_mirror = 0;
6831 terminx 1225
    renderDrawMasks();
3861 helixhorne 1226
    G_RestoreInterpolations();
1227
    G_UpdateScreenArea();
7350 terminx 1228
    renderSetAspect(viewingRange, yxAspect);
3861 helixhorne 1229
}
1230
 
6508 hendricks2 1231
void Screen_Play(void)
1232
{
7202 terminx 1233
    bool running = true;
6508 hendricks2 1234
 
1235
    I_ClearAllInput();
1236
 
1237
    do
1238
    {
8139 terminx 1239
        gameHandleEvents();
6508 hendricks2 1240
 
6648 hendricks2 1241
        ototalclock = totalclock + 1; // pause game like ANMs
1242
 
8716 terminx 1243
        if (!engineFPSLimit())
6641 hendricks2 1244
            continue;
1245
 
6828 terminx 1246
        videoClearScreen(0);
7202 terminx 1247
 
7951 terminx 1248
        if (VM_OnEventWithReturn(EVENT_SCREEN, -1, myconnectindex, I_CheckAllInput()))
7202 terminx 1249
            running = false;
6508 hendricks2 1250
 
7730 pogokeen 1251
        videoNextPage();
6508 hendricks2 1252
        I_ClearAllInput();
1253
    } while (running);
1254
}
1255
 
8622 hendricks2 1256
static void SetArray(int const arrayNum, int const arrayIndex, int const newValue)
1257
{
1258
    if (EDUKE32_PREDICT_FALSE((unsigned)arrayNum >= (unsigned)g_gameArrayCount || (unsigned)arrayIndex >= (unsigned)aGameArrays[arrayNum].size))
1259
    {
1260
        OSD_Printf(OSD_ERROR "Gv_SetVar(): tried to set invalid array %d or index out of bounds from "
1261
                             "sprite %d (%d), player %d\n",
1262
                   (int)arrayNum, vm.spriteNum, vm.pUSprite->picnum, vm.playerNum);
1263
        vm.flags |= VM_RETURN;
1264
        return;
1265
    }
1266
 
1267
    auto &arr = aGameArrays[arrayNum];
1268
 
1269
    if (EDUKE32_PREDICT_FALSE(arr.flags & GAMEARRAY_READONLY))
1270
    {
1271
        OSD_Printf(OSD_ERROR "Tried to set value in read-only array `%s'", arr.szLabel);
1272
        vm.flags |= VM_RETURN;
1273
        return;
1274
    }
1275
 
1276
    switch (arr.flags & GAMEARRAY_TYPE_MASK)
1277
    {
1278
        case 0: arr.pValues[arrayIndex]                              = newValue; break;
1279
        case GAMEARRAY_INT16: ((int16_t *)arr.pValues)[arrayIndex]   = newValue; break;
1280
        case GAMEARRAY_INT8: ((int8_t *)arr.pValues)[arrayIndex]     = newValue; break;
1281
        case GAMEARRAY_UINT16: ((uint16_t *)arr.pValues)[arrayIndex] = newValue; break;
1282
        case GAMEARRAY_UINT8: ((int8_t *)arr.pValues)[arrayIndex]    = newValue; break;
1283
        case GAMEARRAY_BITMAP:
1284
        {
1285
            uint32_t const mask  = pow2char[arrayIndex&7];
1286
            uint8_t &value = ((uint8_t *)arr.pValues)[arrayIndex>>3];
1287
            value = (value & ~mask) | (-!!newValue & mask);
1288
            break;
1289
        }
1290
    }
1291
}
1292
 
1293
static void ResizeArray(int const arrayNum, int const newSize)
1294
{
1295
    auto &arr = aGameArrays[arrayNum];
1296
 
1297
    int const oldSize = arr.size;
1298
 
1299
    if (newSize == oldSize || newSize < 0)
1300
        return;
1301
#if 0
1302
    OSD_Printf(OSDTEXT_GREEN "CON_RESIZEARRAY: resizing array %s from %d to %d\n",
1303
               array.szLabel, array.size, newSize);
1304
#endif
1305
    if (newSize == 0)
1306
    {
1307
        Xaligned_free(arr.pValues);
1308
        arr.pValues = nullptr;
1309
        arr.size = 0;
1310
        return;
1311
    }
1312
 
1313
    size_t const oldBytes = Gv_GetArrayAllocSizeForCount(arrayNum, oldSize);
1314
    size_t const newBytes = Gv_GetArrayAllocSizeForCount(arrayNum, newSize);
1315
 
1316
    auto const oldArray = arr.pValues;
1317
    auto const newArray = (intptr_t *)Xaligned_alloc(ARRAY_ALIGNMENT, newBytes);
1318
 
1319
    if (oldSize != 0)
1320
        Bmemcpy(newArray, oldArray, min(oldBytes, newBytes));
1321
 
1322
    if (newSize > oldSize)
1323
        Bmemset((char *)newArray + oldBytes, 0, newBytes - oldBytes);
1324
 
1325
    arr.pValues = newArray;
1326
    arr.size = newSize;
1327
 
1328
    Xaligned_free(oldArray);
1329
}
1330
 
3410 helixhorne 1331
#if !defined LUNATIC
7358 hendricks2 1332
#if defined __GNUC__ || defined __clang__
7647 terminx 1333
# define CON_USE_COMPUTED_GOTO
7358 hendricks2 1334
#endif
7382 terminx 1335
 
7647 terminx 1336
#ifdef CON_USE_COMPUTED_GOTO
7358 hendricks2 1337
# define vInstruction(KEYWORDID) VINST_ ## KEYWORDID
7631 terminx 1338
# define vmErrorCase VINST_CON_OPCODE_END
7658 terminx 1339
# define eval(INSTRUCTION) { goto *jumpTable[min<uint16_t>(INSTRUCTION, CON_OPCODE_END)]; }
1340
# define dispatch_unconditionally(...) { g_tw = tw = *insptr; eval((VM_DECODE_INST(tw))) }
7647 terminx 1341
# define dispatch(...) { if (vm_execution_depth && (vm.flags & (VM_RETURN|VM_KILL|VM_NOEXECUTE)) == 0) dispatch_unconditionally(__VA_ARGS__); return; }
7378 terminx 1342
# define abort_after_error(...) return
7358 hendricks2 1343
# define vInstructionPointer(KEYWORDID) &&VINST_ ## KEYWORDID
1344
# define COMMA ,
1345
# define JUMP_TABLE_ARRAY_LITERAL { TRANSFORM_SCRIPT_KEYWORDS_LIST(vInstructionPointer, COMMA) }
1346
#else
7357 hendricks2 1347
# define vInstruction(KEYWORDID) case KEYWORDID
7631 terminx 1348
# define vmErrorCase default
7646 terminx 1349
# define dispatch_unconditionally(...) continue
7378 terminx 1350
# define dispatch(...) continue
7357 hendricks2 1351
# define eval(INSTRUCTION) switch(INSTRUCTION)
7378 terminx 1352
# define abort_after_error(...) continue // non-threaded dispatch handles this in the loop condition in VM_Execute()
7358 hendricks2 1353
#endif
7357 hendricks2 1354
 
7638 terminx 1355
#define VM_ASSERT(condition, ...)                \
1356
    do                                           \
1357
    {                                            \
1358
        if (EDUKE32_PREDICT_FALSE(!(condition))) \
1359
        {                                        \
1360
            CON_ERRPRINTF(__VA_ARGS__);          \
1361
            abort_after_error();                 \
1362
        }                                        \
1363
    } while (0)
1364
 
7655 terminx 1365
// be careful when changing this--the assignment used as a condition doubles as a null pointer check
1366
#define VM_CONDITIONAL(xxx)                                                                       \
1367
    do                                                                                            \
1368
    {                                                                                             \
7658 terminx 1369
        if ((xxx) || ((insptr = (intptr_t *)insptr[1]) && (VM_DECODE_INST(*insptr) == CON_ELSE))) \
7655 terminx 1370
        {                                                                                         \
1371
            insptr += 2;                                                                          \
1372
            VM_Execute();                                                                         \
1373
        }                                                                                         \
1374
    } while (0)
1375
 
8366 terminx 1376
GAMEEXEC_STATIC void VM_Execute(int const loop /*= false*/)
5 Plagman 1377
{
7658 terminx 1378
    int vm_execution_depth = loop;
1379
#ifdef CON_USE_COMPUTED_GOTO
1380
    static void *const jumpTable[] = JUMP_TABLE_ARRAY_LITERAL;
1381
#else
7261 terminx 1382
    do
1436 terminx 1383
    {
7358 hendricks2 1384
#endif
7658 terminx 1385
        int32_t tw = *insptr;
1386
        g_tw = tw;
1436 terminx 1387
 
7658 terminx 1388
        eval(VM_DECODE_INST(tw))
430 terminx 1389
        {
7358 hendricks2 1390
            vInstruction(CON_LEFTBRACE):
1391
            {
7647 terminx 1392
                insptr++, vm_execution_depth++;
7378 terminx 1393
                dispatch_unconditionally();
7358 hendricks2 1394
            }
1395
 
1396
            vInstruction(CON_RIGHTBRACE):
1397
            {
7647 terminx 1398
                insptr++, vm_execution_depth--;
7377 terminx 1399
                dispatch();
7358 hendricks2 1400
            }
1401
 
1402
            vInstruction(CON_ELSE):
1403
            {
1404
                insptr = (intptr_t *)insptr[1];
7378 terminx 1405
                dispatch_unconditionally();
7358 hendricks2 1406
            }
7646 terminx 1407
 
7382 terminx 1408
            vInstruction(CON_STATE):
7646 terminx 1409
            {
1410
                auto tempscrptr = &insptr[2];
1411
                insptr = (intptr_t *)insptr[1];
1412
                VM_Execute(true);
1413
                insptr = tempscrptr;
1414
            }
1415
            dispatch();
7358 hendricks2 1416
 
7382 terminx 1417
#ifdef CON_DISCRETE_VAR_ACCESS
7357 hendricks2 1418
            vInstruction(CON_IFVARE_GLOBAL):
6895 terminx 1419
                insptr++;
7266 terminx 1420
                tw = aGameVars[*insptr++].global;
1421
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1422
                dispatch();
7357 hendricks2 1423
            vInstruction(CON_IFVARN_GLOBAL):
7266 terminx 1424
                insptr++;
1425
                tw = aGameVars[*insptr++].global;
1426
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1427
                dispatch();
7357 hendricks2 1428
            vInstruction(CON_IFVARAND_GLOBAL):
7266 terminx 1429
                insptr++;
1430
                tw = aGameVars[*insptr++].global;
1431
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1432
                dispatch();
7357 hendricks2 1433
            vInstruction(CON_IFVAROR_GLOBAL):
7266 terminx 1434
                insptr++;
1435
                tw = aGameVars[*insptr++].global;
1436
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1437
                dispatch();
7357 hendricks2 1438
            vInstruction(CON_IFVARXOR_GLOBAL):
7266 terminx 1439
                insptr++;
1440
                tw = aGameVars[*insptr++].global;
1441
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1442
                dispatch();
7357 hendricks2 1443
            vInstruction(CON_IFVAREITHER_GLOBAL):
7266 terminx 1444
                insptr++;
1445
                tw = aGameVars[*insptr++].global;
1446
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1447
                dispatch();
7357 hendricks2 1448
            vInstruction(CON_IFVARBOTH_GLOBAL):
7266 terminx 1449
                insptr++;
1450
                tw = aGameVars[*insptr++].global;
1451
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1452
                dispatch();
7357 hendricks2 1453
            vInstruction(CON_IFVARG_GLOBAL):
7266 terminx 1454
                insptr++;
1455
                tw = aGameVars[*insptr++].global;
1456
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1457
                dispatch();
7357 hendricks2 1458
            vInstruction(CON_IFVARGE_GLOBAL):
7266 terminx 1459
                insptr++;
1460
                tw = aGameVars[*insptr++].global;
1461
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1462
                dispatch();
7357 hendricks2 1463
            vInstruction(CON_IFVARL_GLOBAL):
7266 terminx 1464
                insptr++;
1465
                tw = aGameVars[*insptr++].global;
1466
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1467
                dispatch();
7357 hendricks2 1468
            vInstruction(CON_IFVARLE_GLOBAL):
7266 terminx 1469
                insptr++;
1470
                tw = aGameVars[*insptr++].global;
1471
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1472
                dispatch();
7357 hendricks2 1473
            vInstruction(CON_IFVARA_GLOBAL):
7266 terminx 1474
                insptr++;
1475
                tw = aGameVars[*insptr++].global;
1476
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1477
                dispatch();
7357 hendricks2 1478
            vInstruction(CON_IFVARAE_GLOBAL):
7266 terminx 1479
                insptr++;
1480
                tw = aGameVars[*insptr++].global;
1481
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1482
                dispatch();
7357 hendricks2 1483
            vInstruction(CON_IFVARB_GLOBAL):
7266 terminx 1484
                insptr++;
1485
                tw = aGameVars[*insptr++].global;
1486
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1487
                dispatch();
7357 hendricks2 1488
            vInstruction(CON_IFVARBE_GLOBAL):
7266 terminx 1489
                insptr++;
1490
                tw = aGameVars[*insptr++].global;
1491
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1492
                dispatch();
5825 terminx 1493
 
7357 hendricks2 1494
            vInstruction(CON_SETVAR_GLOBAL):
7263 terminx 1495
                insptr++;
1496
                aGameVars[*insptr].global = insptr[1];
1497
                insptr += 2;
7377 terminx 1498
                dispatch();
7357 hendricks2 1499
            vInstruction(CON_ADDVAR_GLOBAL):
6895 terminx 1500
                insptr++;
7266 terminx 1501
                aGameVars[*insptr].global += insptr[1];
1502
                insptr += 2;
7377 terminx 1503
                dispatch();
7357 hendricks2 1504
            vInstruction(CON_SUBVAR_GLOBAL):
7263 terminx 1505
                insptr++;
7266 terminx 1506
                aGameVars[*insptr].global -= insptr[1];
7263 terminx 1507
                insptr += 2;
7377 terminx 1508
                dispatch();
7357 hendricks2 1509
            vInstruction(CON_MULVAR_GLOBAL):
7263 terminx 1510
                insptr++;
7266 terminx 1511
                aGameVars[*insptr].global *= insptr[1];
7263 terminx 1512
                insptr += 2;
7377 terminx 1513
                dispatch();
7357 hendricks2 1514
            vInstruction(CON_ANDVAR_GLOBAL):
6895 terminx 1515
                insptr++;
7266 terminx 1516
                aGameVars[*insptr].global &= insptr[1];
1517
                insptr += 2;
7377 terminx 1518
                dispatch();
7357 hendricks2 1519
            vInstruction(CON_XORVAR_GLOBAL):
7263 terminx 1520
                insptr++;
7266 terminx 1521
                aGameVars[*insptr].global ^= insptr[1];
7263 terminx 1522
                insptr += 2;
7377 terminx 1523
                dispatch();
7357 hendricks2 1524
            vInstruction(CON_ORVAR_GLOBAL):
7263 terminx 1525
                insptr++;
7266 terminx 1526
                aGameVars[*insptr].global |= insptr[1];
7263 terminx 1527
                insptr += 2;
7377 terminx 1528
                dispatch();
7357 hendricks2 1529
            vInstruction(CON_SHIFTVARL_GLOBAL):
7266 terminx 1530
                insptr++;
1531
                aGameVars[*insptr].global <<= insptr[1];
1532
                insptr += 2;
7377 terminx 1533
                dispatch();
7357 hendricks2 1534
            vInstruction(CON_SHIFTVARR_GLOBAL):
7266 terminx 1535
                insptr++;
1536
                aGameVars[*insptr].global >>= insptr[1];
1537
                insptr += 2;
7377 terminx 1538
                dispatch();
7263 terminx 1539
 
7357 hendricks2 1540
            vInstruction(CON_IFVARE_ACTOR):
6895 terminx 1541
                insptr++;
7266 terminx 1542
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1543
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1544
                dispatch();
7357 hendricks2 1545
            vInstruction(CON_IFVARN_ACTOR):
7266 terminx 1546
                insptr++;
1547
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1548
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1549
                dispatch();
7357 hendricks2 1550
            vInstruction(CON_IFVARAND_ACTOR):
7266 terminx 1551
                insptr++;
1552
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1553
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1554
                dispatch();
7357 hendricks2 1555
            vInstruction(CON_IFVAROR_ACTOR):
7266 terminx 1556
                insptr++;
1557
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1558
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1559
                dispatch();
7357 hendricks2 1560
            vInstruction(CON_IFVARXOR_ACTOR):
7266 terminx 1561
                insptr++;
1562
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1563
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1564
                dispatch();
7357 hendricks2 1565
            vInstruction(CON_IFVAREITHER_ACTOR):
7266 terminx 1566
                insptr++;
1567
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1568
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1569
                dispatch();
7357 hendricks2 1570
            vInstruction(CON_IFVARBOTH_ACTOR):
7266 terminx 1571
                insptr++;
1572
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1573
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1574
                dispatch();
7357 hendricks2 1575
            vInstruction(CON_IFVARG_ACTOR):
7266 terminx 1576
                insptr++;
1577
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1578
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1579
                dispatch();
7357 hendricks2 1580
            vInstruction(CON_IFVARGE_ACTOR):
7266 terminx 1581
                insptr++;
1582
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1583
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1584
                dispatch();
7357 hendricks2 1585
            vInstruction(CON_IFVARL_ACTOR):
7266 terminx 1586
                insptr++;
1587
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1588
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1589
                dispatch();
7357 hendricks2 1590
            vInstruction(CON_IFVARLE_ACTOR):
7266 terminx 1591
                insptr++;
1592
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1593
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1594
                dispatch();
7357 hendricks2 1595
            vInstruction(CON_IFVARA_ACTOR):
7266 terminx 1596
                insptr++;
1597
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1598
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1599
                dispatch();
7357 hendricks2 1600
            vInstruction(CON_IFVARAE_ACTOR):
7266 terminx 1601
                insptr++;
1602
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1603
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1604
                dispatch();
7357 hendricks2 1605
            vInstruction(CON_IFVARB_ACTOR):
7266 terminx 1606
                insptr++;
1607
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1608
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1609
                dispatch();
7357 hendricks2 1610
            vInstruction(CON_IFVARBE_ACTOR):
7266 terminx 1611
                insptr++;
1612
                tw = aGameVars[*insptr++].pValues[vm.spriteNum & (MAXSPRITES-1)];
1613
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1614
                dispatch();
5 Plagman 1615
 
7357 hendricks2 1616
            vInstruction(CON_SETVAR_ACTOR):
6895 terminx 1617
                insptr++;
7266 terminx 1618
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] = insptr[1];
1619
                insptr += 2;
7377 terminx 1620
                dispatch();
7357 hendricks2 1621
            vInstruction(CON_ADDVAR_ACTOR):
7266 terminx 1622
                insptr++;
1623
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] += insptr[1];
1624
                insptr += 2;
7377 terminx 1625
                dispatch();
7357 hendricks2 1626
            vInstruction(CON_SUBVAR_ACTOR):
7266 terminx 1627
                insptr++;
1628
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] -= insptr[1];
1629
                insptr += 2;
7377 terminx 1630
                dispatch();
7357 hendricks2 1631
            vInstruction(CON_MULVAR_ACTOR):
7266 terminx 1632
                insptr++;
1633
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] *= insptr[1];
1634
                insptr += 2;
7377 terminx 1635
                dispatch();
7357 hendricks2 1636
            vInstruction(CON_ANDVAR_ACTOR):
7266 terminx 1637
                insptr++;
1638
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] &= insptr[1];
1639
                insptr += 2;
7377 terminx 1640
                dispatch();
7357 hendricks2 1641
            vInstruction(CON_XORVAR_ACTOR):
7266 terminx 1642
                insptr++;
1643
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] ^= insptr[1];
1644
                insptr += 2;
7377 terminx 1645
                dispatch();
7357 hendricks2 1646
            vInstruction(CON_ORVAR_ACTOR):
7266 terminx 1647
                insptr++;
1648
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] |= insptr[1];
1649
                insptr += 2;
7377 terminx 1650
                dispatch();
7357 hendricks2 1651
            vInstruction(CON_SHIFTVARL_ACTOR):
7266 terminx 1652
                insptr++;
1653
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] <<= insptr[1];
1654
                insptr += 2;
7377 terminx 1655
                dispatch();
7357 hendricks2 1656
            vInstruction(CON_SHIFTVARR_ACTOR):
7266 terminx 1657
                insptr++;
1658
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] >>= insptr[1];
1659
                insptr += 2;
7377 terminx 1660
                dispatch();
1436 terminx 1661
 
7357 hendricks2 1662
            vInstruction(CON_IFVARE_PLAYER):
6895 terminx 1663
                insptr++;
7266 terminx 1664
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1665
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 1666
                dispatch();
7357 hendricks2 1667
            vInstruction(CON_IFVARN_PLAYER):
7266 terminx 1668
                insptr++;
1669
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1670
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 1671
                dispatch();
7357 hendricks2 1672
            vInstruction(CON_IFVARAND_PLAYER):
7266 terminx 1673
                insptr++;
1674
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1675
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1676
                dispatch();
7357 hendricks2 1677
            vInstruction(CON_IFVAROR_PLAYER):
7266 terminx 1678
                insptr++;
1679
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1680
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1681
                dispatch();
7357 hendricks2 1682
            vInstruction(CON_IFVARXOR_PLAYER):
7266 terminx 1683
                insptr++;
1684
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1685
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1686
                dispatch();
7357 hendricks2 1687
            vInstruction(CON_IFVAREITHER_PLAYER):
7266 terminx 1688
                insptr++;
1689
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1690
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1691
                dispatch();
7357 hendricks2 1692
            vInstruction(CON_IFVARBOTH_PLAYER):
7266 terminx 1693
                insptr++;
1694
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1695
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1696
                dispatch();
7357 hendricks2 1697
            vInstruction(CON_IFVARG_PLAYER):
7266 terminx 1698
                insptr++;
1699
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1700
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1701
                dispatch();
7357 hendricks2 1702
            vInstruction(CON_IFVARGE_PLAYER):
7266 terminx 1703
                insptr++;
1704
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1705
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1706
                dispatch();
7357 hendricks2 1707
            vInstruction(CON_IFVARL_PLAYER):
7266 terminx 1708
                insptr++;
1709
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1710
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1711
                dispatch();
7357 hendricks2 1712
            vInstruction(CON_IFVARLE_PLAYER):
7266 terminx 1713
                insptr++;
1714
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1715
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1716
                dispatch();
7357 hendricks2 1717
            vInstruction(CON_IFVARA_PLAYER):
7266 terminx 1718
                insptr++;
1719
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1720
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1721
                dispatch();
7357 hendricks2 1722
            vInstruction(CON_IFVARAE_PLAYER):
7266 terminx 1723
                insptr++;
1724
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1725
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1726
                dispatch();
7357 hendricks2 1727
            vInstruction(CON_IFVARB_PLAYER):
7266 terminx 1728
                insptr++;
1729
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1730
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1731
                dispatch();
7357 hendricks2 1732
            vInstruction(CON_IFVARBE_PLAYER):
7266 terminx 1733
                insptr++;
1734
                tw = aGameVars[*insptr++].pValues[vm.playerNum & (MAXPLAYERS-1)];
1735
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1736
                dispatch();
1436 terminx 1737
 
7357 hendricks2 1738
            vInstruction(CON_SETVAR_PLAYER):
7263 terminx 1739
                insptr++;
7266 terminx 1740
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] = insptr[1];
7263 terminx 1741
                insptr += 2;
7377 terminx 1742
                dispatch();
7357 hendricks2 1743
            vInstruction(CON_ADDVAR_PLAYER):
7263 terminx 1744
                insptr++;
7266 terminx 1745
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] += insptr[1];
7263 terminx 1746
                insptr += 2;
7377 terminx 1747
                dispatch();
7357 hendricks2 1748
            vInstruction(CON_SUBVAR_PLAYER):
6895 terminx 1749
                insptr++;
7266 terminx 1750
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] -= insptr[1];
1751
                insptr += 2;
7377 terminx 1752
                dispatch();
7357 hendricks2 1753
            vInstruction(CON_MULVAR_PLAYER):
7266 terminx 1754
                insptr++;
1755
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] *= insptr[1];
1756
                insptr += 2;
7377 terminx 1757
                dispatch();
7357 hendricks2 1758
            vInstruction(CON_ANDVAR_PLAYER):
7266 terminx 1759
                insptr++;
1760
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] &= insptr[1];
1761
                insptr += 2;
7377 terminx 1762
                dispatch();
7357 hendricks2 1763
            vInstruction(CON_XORVAR_PLAYER):
7266 terminx 1764
                insptr++;
1765
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] ^= insptr[1];
1766
                insptr += 2;
7377 terminx 1767
                dispatch();
7357 hendricks2 1768
            vInstruction(CON_ORVAR_PLAYER):
7266 terminx 1769
                insptr++;
1770
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] |= insptr[1];
1771
                insptr += 2;
7377 terminx 1772
                dispatch();
7357 hendricks2 1773
            vInstruction(CON_SHIFTVARL_PLAYER):
7266 terminx 1774
                insptr++;
1775
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] <<= insptr[1];
1776
                insptr += 2;
7377 terminx 1777
                dispatch();
7357 hendricks2 1778
            vInstruction(CON_SHIFTVARR_PLAYER):
7266 terminx 1779
                insptr++;
1780
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] >>= insptr[1];
1781
                insptr += 2;
7377 terminx 1782
                dispatch();
1436 terminx 1783
 
7357 hendricks2 1784
            vInstruction(CON_WHILEVARN_GLOBAL):
7266 terminx 1785
            {
1786
                auto const savedinsptr = &insptr[2];
1787
                do
1788
                {
1789
                    insptr = savedinsptr;
1790
                    tw = (aGameVars[insptr[-1]].global != *insptr);
1791
                    VM_CONDITIONAL(tw);
1792
                } while (tw);
7377 terminx 1793
                dispatch();
7266 terminx 1794
            }
1795
 
7357 hendricks2 1796
            vInstruction(CON_WHILEVARL_GLOBAL):
7266 terminx 1797
            {
1798
                auto const savedinsptr = &insptr[2];
1799
                do
1800
                {
1801
                    insptr = savedinsptr;
1802
                    tw = (aGameVars[insptr[-1]].global < *insptr);
1803
                    VM_CONDITIONAL(tw);
1804
                } while (tw);
7377 terminx 1805
                dispatch();
7266 terminx 1806
            }
1807
 
7357 hendricks2 1808
            vInstruction(CON_WHILEVARN_ACTOR):
7266 terminx 1809
            {
1810
                auto const savedinsptr = &insptr[2];
1811
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.spriteNum & (MAXSPRITES-1)];
1812
                do
1813
                {
1814
                    insptr = savedinsptr;
1815
                    tw = (v != *insptr);
1816
                    VM_CONDITIONAL(tw);
1817
                } while (tw);
1818
 
7377 terminx 1819
                dispatch();
7266 terminx 1820
            }
1821
 
7357 hendricks2 1822
            vInstruction(CON_WHILEVARL_ACTOR):
7266 terminx 1823
            {
1824
                auto const savedinsptr = &insptr[2];
1825
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.spriteNum & (MAXSPRITES-1)];
1826
                do
1827
                {
1828
                    insptr = savedinsptr;
1829
                    tw = (v < *insptr);
1830
                    VM_CONDITIONAL(tw);
1831
                } while (tw);
1832
 
7377 terminx 1833
                dispatch();
7266 terminx 1834
            }
1835
 
7357 hendricks2 1836
            vInstruction(CON_WHILEVARN_PLAYER):
7266 terminx 1837
            {
1838
                auto const savedinsptr = &insptr[2];
1839
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.playerNum & (MAXPLAYERS-1)];
1840
                do
1841
                {
1842
                    insptr = savedinsptr;
1843
                    tw = (v != *insptr);
1844
                    VM_CONDITIONAL(tw);
1845
                } while (tw);
1846
 
7377 terminx 1847
                dispatch();
7266 terminx 1848
            }
1849
 
7357 hendricks2 1850
            vInstruction(CON_WHILEVARL_PLAYER):
7266 terminx 1851
            {
1852
                auto const savedinsptr = &insptr[2];
1853
                auto &v = aGameVars[savedinsptr[-1]].pValues[vm.playerNum & (MAXPLAYERS-1)];
1854
                do
1855
                {
1856
                    insptr = savedinsptr;
1857
                    tw = (v < *insptr);
1858
                    VM_CONDITIONAL(tw);
1859
                } while (tw);
1860
 
7377 terminx 1861
                dispatch();
7266 terminx 1862
            }
1863
 
7357 hendricks2 1864
            vInstruction(CON_MODVAR_GLOBAL):
7263 terminx 1865
                insptr++;
7266 terminx 1866
                aGameVars[*insptr].global %= insptr[1];
7263 terminx 1867
                insptr += 2;
7377 terminx 1868
                dispatch();
7357 hendricks2 1869
            vInstruction(CON_MODVAR_ACTOR):
7263 terminx 1870
                insptr++;
7266 terminx 1871
                aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES-1)] %= insptr[1];
7263 terminx 1872
                insptr += 2;
7377 terminx 1873
                dispatch();
7357 hendricks2 1874
            vInstruction(CON_MODVAR_PLAYER):
6895 terminx 1875
                insptr++;
7266 terminx 1876
                aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS-1)] %= insptr[1];
1877
                insptr += 2;
7377 terminx 1878
                dispatch();
7355 hendricks2 1879
#endif
1436 terminx 1880
 
7357 hendricks2 1881
            vInstruction(CON_IFVARAND):
6895 terminx 1882
                insptr++;
7652 terminx 1883
                tw = Gv_GetVar(*insptr++);
7266 terminx 1884
                VM_CONDITIONAL(tw & *insptr);
7377 terminx 1885
                dispatch();
4902 terminx 1886
 
7357 hendricks2 1887
            vInstruction(CON_IFVAROR):
7265 terminx 1888
                insptr++;
7652 terminx 1889
                tw = Gv_GetVar(*insptr++);
7266 terminx 1890
                VM_CONDITIONAL(tw | *insptr);
7377 terminx 1891
                dispatch();
7265 terminx 1892
 
7357 hendricks2 1893
            vInstruction(CON_IFVARXOR):
6895 terminx 1894
                insptr++;
7652 terminx 1895
                tw = Gv_GetVar(*insptr++);
7266 terminx 1896
                VM_CONDITIONAL(tw ^ *insptr);
7377 terminx 1897
                dispatch();
1909 terminx 1898
 
7357 hendricks2 1899
            vInstruction(CON_IFVAREITHER):
7265 terminx 1900
                insptr++;
7652 terminx 1901
                tw = Gv_GetVar(*insptr++);
7266 terminx 1902
                VM_CONDITIONAL(tw || *insptr);
7377 terminx 1903
                dispatch();
7265 terminx 1904
 
7357 hendricks2 1905
            vInstruction(CON_IFVARBOTH):
6895 terminx 1906
                insptr++;
7652 terminx 1907
                tw = Gv_GetVar(*insptr++);
7266 terminx 1908
                VM_CONDITIONAL(tw && *insptr);
7377 terminx 1909
                dispatch();
51 terminx 1910
 
7357 hendricks2 1911
            vInstruction(CON_IFRND):
7266 terminx 1912
                VM_CONDITIONAL(rnd(*(++insptr)));
7377 terminx 1913
                dispatch();
5 Plagman 1914
 
7357 hendricks2 1915
            vInstruction(CON_IFVARG):
6895 terminx 1916
                insptr++;
7652 terminx 1917
                tw = Gv_GetVar(*insptr++);
7266 terminx 1918
                VM_CONDITIONAL(tw > *insptr);
7377 terminx 1919
                dispatch();
1440 terminx 1920
 
7357 hendricks2 1921
            vInstruction(CON_IFVARGE):
6895 terminx 1922
                insptr++;
7652 terminx 1923
                tw = Gv_GetVar(*insptr++);
7266 terminx 1924
                VM_CONDITIONAL(tw >= *insptr);
7377 terminx 1925
                dispatch();
51 terminx 1926
 
7357 hendricks2 1927
            vInstruction(CON_IFVARL):
6895 terminx 1928
                insptr++;
7652 terminx 1929
                tw = Gv_GetVar(*insptr++);
7266 terminx 1930
                VM_CONDITIONAL(tw < *insptr);
7377 terminx 1931
                dispatch();
5 Plagman 1932
 
7357 hendricks2 1933
            vInstruction(CON_IFVARLE):
6895 terminx 1934
                insptr++;
7652 terminx 1935
                tw = Gv_GetVar(*insptr++);
7266 terminx 1936
                VM_CONDITIONAL(tw <= *insptr);
7377 terminx 1937
                dispatch();
5 Plagman 1938
 
7357 hendricks2 1939
            vInstruction(CON_IFVARA):
6895 terminx 1940
                insptr++;
7652 terminx 1941
                tw = Gv_GetVar(*insptr++);
7266 terminx 1942
                VM_CONDITIONAL((uint32_t)tw > (uint32_t)*insptr);
7377 terminx 1943
                dispatch();
337 terminx 1944
 
7357 hendricks2 1945
            vInstruction(CON_IFVARAE):
6895 terminx 1946
                insptr++;
7652 terminx 1947
                tw = Gv_GetVar(*insptr++);
7266 terminx 1948
                VM_CONDITIONAL((uint32_t)tw >= (uint32_t)*insptr);
7377 terminx 1949
                dispatch();
5 Plagman 1950
 
7357 hendricks2 1951
            vInstruction(CON_IFVARB):
6895 terminx 1952
                insptr++;
7652 terminx 1953
                tw = Gv_GetVar(*insptr++);
7266 terminx 1954
                VM_CONDITIONAL((uint32_t)tw < (uint32_t)*insptr);
7377 terminx 1955
                dispatch();
1436 terminx 1956
 
7357 hendricks2 1957
            vInstruction(CON_IFVARBE):
6895 terminx 1958
                insptr++;
7652 terminx 1959
                tw = Gv_GetVar(*insptr++);
7266 terminx 1960
                VM_CONDITIONAL((uint32_t)tw <= (uint32_t)*insptr);
7377 terminx 1961
                dispatch();
335 terminx 1962
 
7357 hendricks2 1963
            vInstruction(CON_SETVARVAR):
6895 terminx 1964
                insptr++;
7266 terminx 1965
                {
1966
                    tw = *insptr++;
7652 terminx 1967
                    int const nValue = Gv_GetVar(*insptr++);
7266 terminx 1968
 
1969
                    if ((aGameVars[tw].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0)
1970
                        aGameVars[tw].global = nValue;
1971
                    else
7653 terminx 1972
                        Gv_SetVar(tw, nValue);
7266 terminx 1973
                }
7377 terminx 1974
                dispatch();
335 terminx 1975
 
7357 hendricks2 1976
            vInstruction(CON_ADDVARVAR):
7265 terminx 1977
                insptr++;
7266 terminx 1978
                tw = *insptr++;
7652 terminx 1979
                Gv_AddVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1980
                dispatch();
7265 terminx 1981
 
7357 hendricks2 1982
            vInstruction(CON_SUBVARVAR):
6895 terminx 1983
                insptr++;
7266 terminx 1984
                tw = *insptr++;
7652 terminx 1985
                Gv_SubVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1986
                dispatch();
335 terminx 1987
 
7357 hendricks2 1988
            vInstruction(CON_ANDVARVAR):
7265 terminx 1989
                insptr++;
7266 terminx 1990
                tw = *insptr++;
7652 terminx 1991
                Gv_AndVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1992
                dispatch();
7265 terminx 1993
 
7357 hendricks2 1994
            vInstruction(CON_XORVARVAR):
6895 terminx 1995
                insptr++;
7266 terminx 1996
                tw = *insptr++;
7652 terminx 1997
                Gv_XorVar(tw, Gv_GetVar(*insptr++));
7377 terminx 1998
                dispatch();
335 terminx 1999
 
7357 hendricks2 2000
            vInstruction(CON_ORVARVAR):
7265 terminx 2001
                insptr++;
7266 terminx 2002
                tw = *insptr++;
7652 terminx 2003
                Gv_OrVar(tw, Gv_GetVar(*insptr++));
7377 terminx 2004
                dispatch();
7265 terminx 2005
 
7357 hendricks2 2006
            vInstruction(CON_SHIFTVARVARL):
6895 terminx 2007
                insptr++;
7266 terminx 2008
                tw = *insptr++;
7652 terminx 2009
                Gv_ShiftVarL(tw, Gv_GetVar(*insptr++));
7377 terminx 2010
                dispatch();
2451 helixhorne 2011
 
7357 hendricks2 2012
            vInstruction(CON_SHIFTVARVARR):
7265 terminx 2013
                insptr++;
7266 terminx 2014
                tw = *insptr++;
7652 terminx 2015
                Gv_ShiftVarR(tw, Gv_GetVar(*insptr++));
7377 terminx 2016
                dispatch();
7265 terminx 2017
 
7357 hendricks2 2018
            vInstruction(CON_MULVARVAR):
6895 terminx 2019
                insptr++;
7266 terminx 2020
                tw = *insptr++;
7652 terminx 2021
                Gv_MulVar(tw, Gv_GetVar(*insptr++));
7377 terminx 2022
                dispatch();
2451 helixhorne 2023
 
7382 terminx 2024
#ifdef CON_DISCRETE_VAR_ACCESS
7357 hendricks2 2025
            vInstruction(CON_DIVVAR_GLOBAL):
7265 terminx 2026
                insptr++;
7266 terminx 2027
                aGameVars[*insptr].global = tabledivide32(aGameVars[*insptr].global, insptr[1]);
2028
                insptr += 2;
7377 terminx 2029
                dispatch();
7265 terminx 2030
 
7357 hendricks2 2031
            vInstruction(CON_DIVVAR_PLAYER):
7266 terminx 2032
            {
6895 terminx 2033
                insptr++;
7266 terminx 2034
                auto &v = aGameVars[*insptr].pValues[vm.playerNum & (MAXPLAYERS - 1)];
3920 helixhorne 2035
 
7266 terminx 2036
                v = tabledivide32(v, insptr[1]);
2037
                insptr += 2;
7377 terminx 2038
                dispatch();
7266 terminx 2039
            }
3920 helixhorne 2040
 
7357 hendricks2 2041
            vInstruction(CON_DIVVAR_ACTOR):
7266 terminx 2042
            {
7265 terminx 2043
                insptr++;
7266 terminx 2044
                auto &v = aGameVars[*insptr].pValues[vm.spriteNum & (MAXSPRITES - 1)];
2045
 
2046
                v = tabledivide32(v, insptr[1]);
2047
                insptr += 2;
7377 terminx 2048
                dispatch();
7266 terminx 2049
            }
7355 hendricks2 2050
#endif
7265 terminx 2051
 
7357 hendricks2 2052
            vInstruction(CON_DIVVARVAR):
6895 terminx 2053
                insptr++;
7266 terminx 2054
                {
2055
                    tw = *insptr++;
2056
 
7652 terminx 2057
                    int const nValue = Gv_GetVar(*insptr++);
7266 terminx 2058
 
7638 terminx 2059
                    VM_ASSERT(nValue, "divide by zero!\n");
7266 terminx 2060
 
2061
                    Gv_DivVar(tw, nValue);
7377 terminx 2062
                    dispatch();
7266 terminx 2063
                }
2064
 
7357 hendricks2 2065
            vInstruction(CON_IFVARE):
7266 terminx 2066
                insptr++;
7652 terminx 2067
                tw = Gv_GetVar(*insptr++);
7266 terminx 2068
                VM_CONDITIONAL(tw == *insptr);
7377 terminx 2069
                dispatch();
5 Plagman 2070
 
7357 hendricks2 2071
            vInstruction(CON_IFVARN):
7265 terminx 2072
                insptr++;
7652 terminx 2073
                tw = Gv_GetVar(*insptr++);
7266 terminx 2074
                VM_CONDITIONAL(tw != *insptr);
7377 terminx 2075
                dispatch();
7265 terminx 2076
 
7357 hendricks2 2077
            vInstruction(CON_IFVARVARE):
6895 terminx 2078
                insptr++;
7652 terminx 2079
                tw = Gv_GetVar(*insptr++);
2080
                tw = (tw == Gv_GetVar(*insptr++));
7266 terminx 2081
                insptr--;
2082
                VM_CONDITIONAL(tw);
7377 terminx 2083
                dispatch();
5 Plagman 2084
 
7357 hendricks2 2085
            vInstruction(CON_IFVARVARN):
7265 terminx 2086
                insptr++;
7652 terminx 2087
                tw = Gv_GetVar(*insptr++);
2088
                tw = (tw != Gv_GetVar(*insptr++));
7266 terminx 2089
                insptr--;
2090
                VM_CONDITIONAL(tw);
7377 terminx 2091
                dispatch();
7265 terminx 2092
 
7357 hendricks2 2093
            vInstruction(CON_IFVARVARG):
6895 terminx 2094
                insptr++;
7652 terminx 2095
                tw = Gv_GetVar(*insptr++);
2096
                tw = (tw > Gv_GetVar(*insptr++));
7266 terminx 2097
                insptr--;