Subversion Repositories eduke32

Rev

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