Subversion Repositories eduke32

Rev

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

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