Subversion Repositories eduke32

Rev

Rev 5016 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5016 Rev 5031
1
//-------------------------------------------------------------------------
1
//-------------------------------------------------------------------------
2
/*
2
/*
3
Copyright (C) 2010 EDuke32 developers and contributors
3
Copyright (C) 2010 EDuke32 developers and contributors
4

4

5
This file is part of EDuke32.
5
This file is part of EDuke32.
6

6

7
EDuke32 is free software; you can redistribute it and/or
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
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
9
as published by the Free Software Foundation.
10

10

11
This program is distributed in the hope that it will be useful,
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14

14

15
See the GNU General Public License for more details.
15
See the GNU General Public License for more details.
16

16

17
You should have received a copy of the GNU General Public License
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
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
*/
20
*/
21
//-------------------------------------------------------------------------
21
//-------------------------------------------------------------------------
22
#include "compat.h"
22
#include "compat.h"
23
23
24
#include <time.h>
24
#include <time.h>
25
#include <stdlib.h>
25
#include <stdlib.h>
26
#include <math.h>  // sqrt
26
#include <math.h>  // sqrt
27
27
28
#include "build.h"
28
#include "build.h"
29
29
30
#include "duke3d.h"
30
#include "duke3d.h"
31
#include "gamedef.h"
31
#include "gamedef.h"
32
#include "gameexec.h"
32
#include "gameexec.h"
33
#include "scriplib.h"
33
#include "scriplib.h"
34
#include "savegame.h"
34
#include "savegame.h"
35
#include "premap.h"
35
#include "premap.h"
36
#include "osdcmds.h"
36
#include "osdcmds.h"
37
#include "osd.h"
37
#include "osd.h"
38
#include "menus.h"
38
#include "menus.h"
39
#include "input.h"
39
#include "input.h"
40
#include "anim.h"
40
#include "anim.h"
41
41
42
#ifdef LUNATIC
42
#ifdef LUNATIC
43
# include "lunatic_game.h"
43
# include "lunatic_game.h"
44
#endif
44
#endif
45
45
46
#if KRANDDEBUG
46
#if KRANDDEBUG
47
# define GAMEEXEC_INLINE
47
# define GAMEEXEC_INLINE
48
# define GAMEEXEC_STATIC
48
# define GAMEEXEC_STATIC
49
#else
49
#else
50
# define GAMEEXEC_INLINE inline
50
# define GAMEEXEC_INLINE inline
51
# define GAMEEXEC_STATIC static
51
# define GAMEEXEC_STATIC static
52
#endif
52
#endif
53
53
54
vmstate_t vm;
54
vmstate_t vm;
55
55
56
#if !defined LUNATIC
56
#if !defined LUNATIC
57
enum vmflags_t {
57
enum vmflags_t {
58
    VM_RETURN       = 0x00000001,
58
    VM_RETURN       = 0x00000001,
59
    VM_KILL         = 0x00000002,
59
    VM_KILL         = 0x00000002,
60
    VM_NOEXECUTE    = 0x00000004,
60
    VM_NOEXECUTE    = 0x00000004,
61
};
61
};
62
62
63
int32_t g_tw;
63
int32_t g_tw;
64
int32_t g_errorLineNum;
64
int32_t g_errorLineNum;
65
int32_t g_currentEventExec = -1;
65
int32_t g_currentEventExec = -1;
66
66
67
intptr_t const *insptr;
67
intptr_t const *insptr;
68
68
69
int32_t g_iReturnVarID = -1;     // var ID of "RETURN"
69
int32_t g_iReturnVarID = -1;     // var ID of "RETURN"
70
int32_t g_iWeaponVarID = -1;     // var ID of "WEAPON"
70
int32_t g_iWeaponVarID = -1;     // var ID of "WEAPON"
71
int32_t g_iWorksLikeVarID = -1;  // var ID of "WORKSLIKE"
71
int32_t g_iWorksLikeVarID = -1;  // var ID of "WORKSLIKE"
72
int32_t g_iZRangeVarID = -1;     // var ID of "ZRANGE"
72
int32_t g_iZRangeVarID = -1;     // var ID of "ZRANGE"
73
int32_t g_iAngRangeVarID = -1;   // var ID of "ANGRANGE"
73
int32_t g_iAngRangeVarID = -1;   // var ID of "ANGRANGE"
74
int32_t g_iAimAngleVarID = -1;   // var ID of "AUTOAIMANGLE"
74
int32_t g_iAimAngleVarID = -1;   // var ID of "AUTOAIMANGLE"
75
int32_t g_iLoTagID = -1;         // var ID of "LOTAG"
75
int32_t g_iLoTagID = -1;         // var ID of "LOTAG"
76
int32_t g_iHiTagID = -1;         // var ID of "HITAG"
76
int32_t g_iHiTagID = -1;         // var ID of "HITAG"
77
int32_t g_iTextureID = -1;       // var ID of "TEXTURE"
77
int32_t g_iTextureID = -1;       // var ID of "TEXTURE"
78
int32_t g_iThisActorID = -1;     // var ID of "THISACTOR"
78
int32_t g_iThisActorID = -1;     // var ID of "THISACTOR"
79
int32_t g_iSpriteVarID = -1;
79
int32_t g_iSpriteVarID = -1;
80
int32_t g_iSectorVarID = -1;
80
int32_t g_iSectorVarID = -1;
81
int32_t g_iWallVarID = -1;
81
int32_t g_iWallVarID = -1;
82
int32_t g_iPlayerVarID = -1;
82
int32_t g_iPlayerVarID = -1;
83
int32_t g_iActorVarID = -1;
83
int32_t g_iActorVarID = -1;
84
84
85
GAMEEXEC_STATIC void VM_Execute(int32_t loop);
85
GAMEEXEC_STATIC void VM_Execute(int32_t loop);
86
86
87
# include "gamestructures.c"
87
# include "gamestructures.c"
88
#endif
88
#endif
89
89
90
#define VM_INSTMASK 0xfff
90
#define VM_INSTMASK 0xfff
91
91
92
#define VM_CONDITIONAL(xxx)                                                                                            \
92
#define VM_CONDITIONAL(xxx)                                                                                            \
93
    {                                                                                                                  \
93
    {                                                                                                                  \
94
        if ((xxx) || ((insptr = (intptr_t *)*(insptr + 1)) && (((*insptr) & VM_INSTMASK) == CON_ELSE)))                \
94
        if ((xxx) || ((insptr = (intptr_t *)*(insptr + 1)) && (((*insptr) & VM_INSTMASK) == CON_ELSE)))                \
95
        {                                                                                                              \
95
        {                                                                                                              \
96
            insptr += 2;                                                                                               \
96
            insptr += 2;                                                                                               \
97
            VM_Execute(0);                                                                                             \
97
            VM_Execute(0);                                                                                             \
98
        }                                                                                                              \
98
        }                                                                                                              \
99
    }
99
    }
100
100
101
void VM_ScriptInfo(void)
101
void VM_ScriptInfo(void)
102
{
102
{
103
#if !defined LUNATIC
103
#if !defined LUNATIC
104
    if (!script)
104
    if (!script)
105
        return;
105
        return;
106
106
107
    if (insptr)
107
    if (insptr)
108
    {
108
    {
109
        initprintf("\n");
109
        initprintf("\n");
110
110
111
        for (intptr_t const *p = insptr - 32; p < insptr + 32; p++)
111
        for (intptr_t const *p = insptr - 32; p < insptr + 32; p++)
112
        {
112
        {
113
            if ((int32_t)(p - script) >= g_scriptSize)
113
            if ((int32_t)(p - script) >= g_scriptSize)
114
                break;
114
                break;
115
115
116
            initprintf("%5d: %3d: ", (int32_t) (p - script), (int32_t) (p - insptr));
116
            initprintf("%5d: %3d: ", (int32_t) (p - script), (int32_t) (p - insptr));
117
117
118
            if (*p >> 12 && (*p & VM_INSTMASK) < CON_END)
118
            if (*p >> 12 && (*p & VM_INSTMASK) < CON_END)
119
                initprintf("%5d %s\n", (int32_t) (*p >> 12), keyw[*p & VM_INSTMASK]);
119
                initprintf("%5d %s\n", (int32_t) (*p >> 12), keyw[*p & VM_INSTMASK]);
120
            else
120
            else
121
                initprintf("%d\n", (int32_t) *p);
121
                initprintf("%d\n", (int32_t) *p);
122
        }
122
        }
123
123
124
        initprintf("\n");
124
        initprintf("\n");
125
    }
125
    }
126
126
127
    if (vm.g_i)
127
    if (vm.g_i)
128
        initprintf("current actor: %d (%d)\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
128
        initprintf("current actor: %d (%d)\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
129
129
130
    initprintf("g_errorLineNum: %d, g_tw: %d\n", g_errorLineNum, g_tw);
130
    initprintf("g_errorLineNum: %d, g_tw: %d\n", g_errorLineNum, g_tw);
131
#endif
131
#endif
132
}
132
}
133
133
134
static void VM_DeleteSprite(int32_t iActor, int32_t iPlayer)
134
static void VM_DeleteSprite(int32_t iActor, int32_t iPlayer)
135
{
135
{
136
    if (EDUKE32_PREDICT_FALSE((unsigned) iActor >= MAXSPRITES))
136
    if (EDUKE32_PREDICT_FALSE((unsigned) iActor >= MAXSPRITES))
137
        return;
137
        return;
138
138
139
    // if player was set to squish, first stop that...
139
    // if player was set to squish, first stop that...
140
    if (EDUKE32_PREDICT_FALSE(iPlayer >= 0 && g_player[iPlayer].ps->actorsqu == iActor))
140
    if (EDUKE32_PREDICT_FALSE(iPlayer >= 0 && g_player[iPlayer].ps->actorsqu == iActor))
141
        g_player[iPlayer].ps->actorsqu = -1;
141
        g_player[iPlayer].ps->actorsqu = -1;
142
142
143
    A_DeleteSprite(iActor);
143
    A_DeleteSprite(iActor);
144
}
144
}
145
145
146
intptr_t *apScriptGameEvent[MAXGAMEEVENTS];
146
intptr_t *apScriptGameEvent[MAXGAMEEVENTS];
147
147
148
// May recurse, e.g. through EVENT_XXX -> ... -> EVENT_KILLIT
148
// May recurse, e.g. through EVENT_XXX -> ... -> EVENT_KILLIT
149
#ifdef LUNATIC
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)
150
FORCE_INLINE int32_t VM_EventCommon_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist, int32_t iReturn)
151
{
151
{
152
    const double t = gethiticks();
152
    const double t = gethiticks();
153
    int32_t ret = El_CallEvent(&g_ElState, iEventID, iActor, iPlayer, lDist, &iReturn);
153
    int32_t ret = El_CallEvent(&g_ElState, iEventID, iActor, iPlayer, lDist, &iReturn);
154
154
155
    // NOTE: the run times are those of the called event plus any events
155
    // NOTE: the run times are those of the called event plus any events
156
    // called by it, *not* "self" time.
156
    // called by it, *not* "self" time.
157
    g_eventTotalMs[iEventID] += gethiticks()-t;
157
    g_eventTotalMs[iEventID] += gethiticks()-t;
158
    g_eventCalls[iEventID]++;
158
    g_eventCalls[iEventID]++;
159
159
160
    if (ret == 1)
160
    if (ret == 1)
161
        VM_DeleteSprite(iActor, iPlayer);
161
        VM_DeleteSprite(iActor, iPlayer);
162
162
163
    return iReturn;
163
    return iReturn;
164
}
164
}
165
#else
165
#else
166
FORCE_INLINE int32_t VM_EventCommon_(const int32_t iEventID, const int32_t iActor, const int32_t iPlayer,
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)
167
                                     const int32_t lDist, int32_t iReturn)
168
{
168
{
169
    // this is initialized first thing because iActor, iPlayer, lDist, etc are already right there on the stack
169
    // this is initialized first thing because iActor, iPlayer, lDist, etc are already right there on the stack
170
    // from the function call
170
    // from the function call
171
    const vmstate_t tempvm = { iActor, iPlayer, lDist, &actor[(unsigned)iActor].t_data[0],
171
    const vmstate_t tempvm = { iActor, iPlayer, lDist, &actor[(unsigned)iActor].t_data[0],
172
                               &sprite[(unsigned)iActor], g_player[iPlayer].ps, 0 };
172
                               &sprite[(unsigned)iActor], g_player[iPlayer].ps, 0 };
173
173
174
    // since we're targeting C99 and C++ now, we can interweave these to avoid
174
    // since we're targeting C99 and C++ now, we can interweave these to avoid
175
    // having to load addresses for things twice
175
    // having to load addresses for things twice
176
    // for example, because we are loading backupReturnVar with the value of
176
    // for example, because we are loading backupReturnVar with the value of
177
    // aGameVars[g_iReturnVarID].val.lValue, the compiler can avoid having to
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
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!)
179
    // set it to the value of iReturn (...which should still be on the stack!)
180
180
181
    const int32_t backupReturnVar = aGameVars[g_iReturnVarID].val.lValue;
181
    const int32_t backupReturnVar = aGameVars[g_iReturnVarID].val.lValue;
182
    aGameVars[g_iReturnVarID].val.lValue = iReturn;
182
    aGameVars[g_iReturnVarID].val.lValue = iReturn;
183
183
184
    const int32_t backupEventExec = g_currentEventExec;
184
    const int32_t backupEventExec = g_currentEventExec;
185
    g_currentEventExec = iEventID;
185
    g_currentEventExec = iEventID;
186
186
187
    intptr_t const *oinsptr = insptr;
187
    intptr_t const *oinsptr = insptr;
188
    insptr = apScriptGameEvent[iEventID];
188
    insptr = apScriptGameEvent[iEventID];
189
189
190
    const vmstate_t vm_backup = vm;
190
    const vmstate_t vm_backup = vm;
191
    vm = tempvm;
191
    vm = tempvm;
192
192
193
    // check tempvm instead of vm... this way, we are not actually loading
193
    // check tempvm instead of vm... this way, we are not actually loading
194
    // FROM vm anywhere until VM_Execute() is called
194
    // FROM vm anywhere until VM_Execute() is called
195
    if ((unsigned)tempvm.g_i >= MAXSPRITES)
195
    if ((unsigned)tempvm.g_i >= MAXSPRITES)
196
    {
196
    {
197
        static spritetype dummy_sprite;
197
        static spritetype dummy_sprite;
198
        static int32_t dummy_t[ARRAY_SIZE(actor[0].t_data)];
198
        static int32_t dummy_t[ARRAY_SIZE(actor[0].t_data)];
199
199
200
        vm.g_sp = &dummy_sprite;
200
        vm.g_sp = &dummy_sprite;
201
        vm.g_t = dummy_t;
201
        vm.g_t = dummy_t;
202
    }
202
    }
203
203
204
    if ((unsigned)iPlayer >= (unsigned)playerswhenstarted)
204
    if ((unsigned)iPlayer >= (unsigned)playerswhenstarted)
205
        vm.g_pp = g_player[0].ps;
205
        vm.g_pp = g_player[0].ps;
206
206
207
    VM_Execute(1);
207
    VM_Execute(1);
208
208
209
    if (vm.g_flags & VM_KILL)
209
    if (vm.g_flags & VM_KILL)
210
        VM_DeleteSprite(vm.g_i, vm.g_p);
210
        VM_DeleteSprite(vm.g_i, vm.g_p);
211
211
212
    // this needs to happen after VM_DeleteSprite() because VM_DeleteSprite()
212
    // this needs to happen after VM_DeleteSprite() because VM_DeleteSprite()
213
    // can trigger additional events
213
    // can trigger additional events
214
    vm = vm_backup;
214
    vm = vm_backup;
215
    insptr = oinsptr;
215
    insptr = oinsptr;
216
    g_currentEventExec = backupEventExec;
216
    g_currentEventExec = backupEventExec;
217
    iReturn = aGameVars[g_iReturnVarID].val.lValue;
217
    iReturn = aGameVars[g_iReturnVarID].val.lValue;
218
    aGameVars[g_iReturnVarID].val.lValue = backupReturnVar;
218
    aGameVars[g_iReturnVarID].val.lValue = backupReturnVar;
219
219
220
    return iReturn;
220
    return iReturn;
221
}
221
}
222
#endif
222
#endif
223
223
224
// the idea here is that the compiler inlines the call to VM_EventCommon_() and gives us a set of full functions
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,
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
226
// but are called faster due to having less parameters
227
227
228
int32_t VM_OnEventWithBoth_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist, int32_t iReturn)
228
int32_t VM_OnEventWithBoth_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist, int32_t iReturn)
229
{
229
{
230
    return VM_EventCommon_(iEventID, iActor, iPlayer, lDist, iReturn);
230
    return VM_EventCommon_(iEventID, iActor, iPlayer, lDist, iReturn);
231
}
231
}
232
232
233
int32_t VM_OnEventWithReturn_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t iReturn)
233
int32_t VM_OnEventWithReturn_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t iReturn)
234
{
234
{
235
    return VM_EventCommon_(iEventID, iActor, iPlayer, -1, iReturn);
235
    return VM_EventCommon_(iEventID, iActor, iPlayer, -1, iReturn);
236
}
236
}
237
237
238
int32_t VM_OnEventWithDist_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist)
238
int32_t VM_OnEventWithDist_(int32_t iEventID, int32_t iActor, int32_t iPlayer, int32_t lDist)
239
{
239
{
240
    return VM_EventCommon_(iEventID, iActor, iPlayer, lDist, 0);
240
    return VM_EventCommon_(iEventID, iActor, iPlayer, lDist, 0);
241
}
241
}
242
242
243
int32_t VM_OnEvent_(int32_t iEventID, int32_t iActor, int32_t iPlayer)
243
int32_t VM_OnEvent_(int32_t iEventID, int32_t iActor, int32_t iPlayer)
244
{
244
{
245
    return VM_EventCommon_(iEventID, iActor, iPlayer, -1, 0);
245
    return VM_EventCommon_(iEventID, iActor, iPlayer, -1, 0);
246
}
246
}
247
247
248
static int32_t VM_CheckSquished(void)
248
static int32_t VM_CheckSquished(void)
249
{
249
{
250
    sectortype const * const sc = &sector[vm.g_sp->sectnum];
250
    sectortype const * const sc = &sector[vm.g_sp->sectnum];
251
251
252
    if (sc->lotag == ST_23_SWINGING_DOOR || EDUKE32_PREDICT_FALSE(vm.g_sp->picnum == APLAYER && ud.noclip))
252
    if (sc->lotag == ST_23_SWINGING_DOOR || EDUKE32_PREDICT_FALSE(vm.g_sp->picnum == APLAYER && ud.noclip))
253
        return 0;
253
        return 0;
254
254
255
    {
255
    {
256
        int32_t fz=sc->floorz, cz=sc->ceilingz;
256
        int32_t fz=sc->floorz, cz=sc->ceilingz;
257
#ifdef YAX_ENABLE
257
#ifdef YAX_ENABLE
258
        int16_t cb, fb;
258
        int16_t cb, fb;
259
259
260
        yax_getbunches(vm.g_sp->sectnum, &cb, &fb);
260
        yax_getbunches(vm.g_sp->sectnum, &cb, &fb);
261
        if (cb >= 0 && (sc->ceilingstat&512)==0)  // if ceiling non-blocking...
261
        if (cb >= 0 && (sc->ceilingstat&512)==0)  // if ceiling non-blocking...
262
            cz -= (32<<8);  // unconditionally don't squish... yax_getneighborsect is slowish :/
262
            cz -= (32<<8);  // unconditionally don't squish... yax_getneighborsect is slowish :/
263
        if (fb >= 0 && (sc->floorstat&512)==0)
263
        if (fb >= 0 && (sc->floorstat&512)==0)
264
            fz += (32<<8);
264
            fz += (32<<8);
265
#endif
265
#endif
266
266
267
        if (vm.g_sp->pal == 1 ?
267
        if (vm.g_sp->pal == 1 ?
268
            (fz - cz >= (32<<8) || (sc->lotag&32768)) :
268
            (fz - cz >= (32<<8) || (sc->lotag&32768)) :
269
            (fz - cz >= (12<<8)))
269
            (fz - cz >= (12<<8)))
270
        return 0;
270
        return 0;
271
    }
271
    }
272
   
272
   
273
    P_DoQuote(QUOTE_SQUISHED, vm.g_pp);
273
    P_DoQuote(QUOTE_SQUISHED, vm.g_pp);
274
274
275
    if (A_CheckEnemySprite(vm.g_sp))
275
    if (A_CheckEnemySprite(vm.g_sp))
276
        vm.g_sp->xvel = 0;
276
        vm.g_sp->xvel = 0;
277
277
278
    if (EDUKE32_PREDICT_FALSE(vm.g_sp->pal == 1)) // frozen
278
    if (EDUKE32_PREDICT_FALSE(vm.g_sp->pal == 1)) // frozen
279
    {
279
    {
280
        actor[vm.g_i].picnum = SHOTSPARK1;
280
        actor[vm.g_i].picnum = SHOTSPARK1;
281
        actor[vm.g_i].extra = 1;
281
        actor[vm.g_i].extra = 1;
282
        return 0;
282
        return 0;
283
    }
283
    }
284
284
285
    return 1;
285
    return 1;
286
}
286
}
287
287
288
#if !defined LUNATIC
288
#if !defined LUNATIC
289
GAMEEXEC_STATIC GAMEEXEC_INLINE void P_ForceAngle(DukePlayer_t *p)
289
GAMEEXEC_STATIC GAMEEXEC_INLINE void P_ForceAngle(DukePlayer_t *p)
290
{
290
{
291
    int32_t n = 128-(krand()&255);
291
    int32_t n = 128-(krand()&255);
292
292
293
    p->horiz += 64;
293
    p->horiz += 64;
294
    p->return_to_center = 9;
294
    p->return_to_center = 9;
295
    p->look_ang = p->rotscrnang = n>>1;
295
    p->look_ang = p->rotscrnang = n>>1;
296
}
296
}
297
#endif
297
#endif
298
298
299
int32_t A_Dodge(spritetype *s)
299
int32_t A_Dodge(spritetype *s)
300
{
300
{
301
    const int32_t mx = s->x, my = s->y;
301
    const int32_t mx = s->x, my = s->y;
302
    const int32_t mxvect = sintable[(s->ang+512)&2047];
302
    const int32_t mxvect = sintable[(s->ang+512)&2047];
303
    const int32_t myvect = sintable[s->ang&2047];
303
    const int32_t myvect = sintable[s->ang&2047];
304
304
305
    if (A_CheckEnemySprite(s) && s->extra <= 0) // hack
305
    if (A_CheckEnemySprite(s) && s->extra <= 0) // hack
306
        return 0;
306
        return 0;
307
307
308
    for (int32_t i=headspritestat[STAT_PROJECTILE]; i>=0; i=nextspritestat[i]) //weapons list
308
    for (int32_t i=headspritestat[STAT_PROJECTILE]; i>=0; i=nextspritestat[i]) //weapons list
309
    {
309
    {
310
        if (OW == i)
310
        if (OW == i)
311
            continue;
311
            continue;
312
312
313
        int32_t bx = SX-mx;
313
        int32_t bx = SX-mx;
314
        int32_t by = SY-my;
314
        int32_t by = SY-my;
315
        int32_t bxvect = sintable[(SA+512)&2047];
315
        int32_t bxvect = sintable[(SA+512)&2047];
316
        int32_t byvect = sintable[SA&2047];
316
        int32_t byvect = sintable[SA&2047];
317
317
318
        if (mxvect*bx + myvect*by >= 0 && bxvect*bx + byvect*by < 0)
318
        if (mxvect*bx + myvect*by >= 0 && bxvect*bx + byvect*by < 0)
319
        {
319
        {
320
            if (klabs(bxvect*by - byvect*bx) < 65536<<6)
320
            if (klabs(bxvect*by - byvect*bx) < 65536<<6)
321
            {
321
            {
322
                s->ang -= 512+(krand()&1024);
322
                s->ang -= 512+(krand()&1024);
323
                return 1;
323
                return 1;
324
            }
324
            }
325
        }
325
        }
326
    }
326
    }
327
327
328
    return 0;
328
    return 0;
329
}
329
}
330
330
331
int32_t A_GetFurthestAngle(int32_t iActor, int32_t angs)
331
int32_t A_GetFurthestAngle(int32_t iActor, int32_t angs)
332
{
332
{
333
    spritetype *const s = &sprite[iActor];
333
    spritetype *const s = &sprite[iActor];
334
334
335
    if (s->picnum != APLAYER && (AC_COUNT(actor[iActor].t_data)&63) > 2)
335
    if (s->picnum != APLAYER && (AC_COUNT(actor[iActor].t_data)&63) > 2)
336
        return s->ang + 1024;
336
        return s->ang + 1024;
337
337
338
    int32_t furthest_angle = 0, greatestd = INT32_MIN;
338
    int32_t furthest_angle = 0, greatestd = INT32_MIN;
339
    const int32_t angincs = tabledivide32_noinline(2048, angs);
339
    const int32_t angincs = tabledivide32_noinline(2048, angs);
340
    hitdata_t hit;
340
    hitdata_t hit;
341
341
342
    for (int32_t j=s->ang; j<(2048+s->ang); j+=angincs)
342
    for (int32_t j=s->ang; j<(2048+s->ang); j+=angincs)
343
    {
343
    {
344
        s->z -= (8<<8);
344
        s->z -= (8<<8);
345
        hitscan((const vec3_t *)s, s->sectnum,
345
        hitscan((const vec3_t *)s, s->sectnum,
346
                sintable[(j+512)&2047],
346
                sintable[(j+512)&2047],
347
                sintable[j&2047], 0,
347
                sintable[j&2047], 0,
348
                &hit, CLIPMASK1);
348
                &hit, CLIPMASK1);
349
        s->z += (8<<8);
349
        s->z += (8<<8);
350
350
351
        const int32_t d = klabs(hit.pos.x-s->x) + klabs(hit.pos.y-s->y);
351
        const int32_t d = klabs(hit.pos.x-s->x) + klabs(hit.pos.y-s->y);
352
352
353
        if (d > greatestd)
353
        if (d > greatestd)
354
        {
354
        {
355
            greatestd = d;
355
            greatestd = d;
356
            furthest_angle = j;
356
            furthest_angle = j;
357
        }
357
        }
358
    }
358
    }
359
359
360
    return furthest_angle&2047;
360
    return furthest_angle&2047;
361
}
361
}
362
362
363
int32_t A_FurthestVisiblePoint(int32_t iActor, tspritetype * const ts, int32_t *dax, int32_t *day)
363
int32_t A_FurthestVisiblePoint(int32_t iActor, tspritetype * const ts, int32_t *dax, int32_t *day)
364
{
364
{
365
    if (AC_COUNT(actor[iActor].t_data)&63)
365
    if (AC_COUNT(actor[iActor].t_data)&63)
366
        return -1;
366
        return -1;
367
367
368
    const spritetype *const s = &sprite[iActor];
368
    const spritetype *const s = &sprite[iActor];
369
369
370
    const int32_t angincs =
370
    const int32_t angincs =
371
        ((!g_netServer && ud.multimode < 2) && ud.player_skill < 3) ? 2048/2 :
371
        ((!g_netServer && ud.multimode < 2) && ud.player_skill < 3) ? 2048/2 :
372
        tabledivide32_noinline(2048, 1+(krand()&1));
372
        tabledivide32_noinline(2048, 1+(krand()&1));
373
373
374
    hitdata_t hit;
374
    hitdata_t hit;
375
375
376
    for (int32_t j=ts->ang; j<(2048+ts->ang); j+=(angincs-(krand()&511)))
376
    for (int32_t j=ts->ang; j<(2048+ts->ang); j+=(angincs-(krand()&511)))
377
    {
377
    {
378
        ts->z -= (16<<8);
378
        ts->z -= (16<<8);
379
        hitscan((const vec3_t *)ts, ts->sectnum,
379
        hitscan((const vec3_t *)ts, ts->sectnum,
380
                sintable[(j+512)&2047],
380
                sintable[(j+512)&2047],
381
                sintable[j&2047], 16384-(krand()&32767),
381
                sintable[j&2047], 16384-(krand()&32767),
382
                &hit, CLIPMASK1);
382
                &hit, CLIPMASK1);
383
383
384
        ts->z += (16<<8);
384
        ts->z += (16<<8);
385
385
386
        const int32_t d = klabs(hit.pos.x-ts->x)+klabs(hit.pos.y-ts->y);
386
        const int32_t d = klabs(hit.pos.x-ts->x)+klabs(hit.pos.y-ts->y);
387
        const int32_t da = klabs(hit.pos.x-s->x)+klabs(hit.pos.y-s->y);
387
        const int32_t da = klabs(hit.pos.x-s->x)+klabs(hit.pos.y-s->y);
388
388
389
        if (d < da && hit.sect > -1)
389
        if (d < da && hit.sect > -1)
390
            if (cansee(hit.pos.x,hit.pos.y,hit.pos.z,
390
            if (cansee(hit.pos.x,hit.pos.y,hit.pos.z,
391
                       hit.sect,s->x,s->y,s->z-(16<<8),s->sectnum))
391
                       hit.sect,s->x,s->y,s->z-(16<<8),s->sectnum))
392
            {
392
            {
393
                *dax = hit.pos.x;
393
                *dax = hit.pos.x;
394
                *day = hit.pos.y;
394
                *day = hit.pos.y;
395
                return hit.sect;
395
                return hit.sect;
396
            }
396
            }
397
    }
397
    }
398
398
399
    return -1;
399
    return -1;
400
}
400
}
401
401
402
static void VM_GetZRange(int32_t iActor, int32_t *ceilhit, int32_t *florhit, int walldist)
402
static void VM_GetZRange(int32_t iActor, int32_t *ceilhit, int32_t *florhit, int walldist)
403
{
403
{
404
    spritetype *const s = &sprite[iActor];
404
    spritetype *const s = &sprite[iActor];
405
    const int32_t ocstat = s->cstat;
405
    const int32_t ocstat = s->cstat;
406
406
407
    s->cstat = 0;
407
    s->cstat = 0;
408
    s->z -= ZOFFSET;
408
    s->z -= ZOFFSET;
409
409
410
    getzrange((vec3_t *)s, s->sectnum,
410
    getzrange((vec3_t *)s, s->sectnum,
411
              &actor[iActor].ceilingz, ceilhit,
411
              &actor[iActor].ceilingz, ceilhit,
412
              &actor[iActor].floorz, florhit,
412
              &actor[iActor].floorz, florhit,
413
              walldist, CLIPMASK0);
413
              walldist, CLIPMASK0);
414
414
415
    s->z += ZOFFSET;
415
    s->z += ZOFFSET;
416
    s->cstat = ocstat;
416
    s->cstat = ocstat;
417
}
417
}
418
418
419
void A_GetZLimits(int32_t iActor)
419
void A_GetZLimits(int32_t iActor)
420
{
420
{
421
    spritetype *const s = &sprite[iActor];
421
    spritetype *const s = &sprite[iActor];
422
422
423
    int32_t ceilhit, florhit;
423
    int32_t ceilhit, florhit;
424
    const int walldist = (s->statnum == STAT_PROJECTILE) ? 4 : 127;
424
    const int walldist = (s->statnum == STAT_PROJECTILE) ? 4 : 127;
425
425
426
    VM_GetZRange(iActor, &ceilhit, &florhit, walldist);
426
    VM_GetZRange(iActor, &ceilhit, &florhit, walldist);
427
427
428
    actor[iActor].flags &= ~SFLAG_NOFLOORSHADOW;
428
    actor[iActor].flags &= ~SFLAG_NOFLOORSHADOW;
429
429
430
    if ((florhit&49152) == 49152 && (sprite[florhit&(MAXSPRITES-1)].cstat&48) == 0)
430
    if ((florhit&49152) == 49152 && (sprite[florhit&(MAXSPRITES-1)].cstat&48) == 0)
431
    {
431
    {
432
        const spritetype *hitspr = &sprite[florhit&(MAXSPRITES-1)];
432
        const spritetype *hitspr = &sprite[florhit&(MAXSPRITES-1)];
433
433
434
        florhit &= (MAXSPRITES-1);
434
        florhit &= (MAXSPRITES-1);
435
435
436
        // If a non-projectile would fall onto non-frozen enemy OR an enemy onto a player...
436
        // If a non-projectile would fall onto non-frozen enemy OR an enemy onto a player...
437
        if ((A_CheckEnemySprite(hitspr) && hitspr->pal != 1 && s->statnum != STAT_PROJECTILE)
437
        if ((A_CheckEnemySprite(hitspr) && hitspr->pal != 1 && s->statnum != STAT_PROJECTILE)
438
                || (hitspr->picnum == APLAYER && A_CheckEnemySprite(s)))
438
                || (hitspr->picnum == APLAYER && A_CheckEnemySprite(s)))
439
        {
439
        {
440
            actor[iActor].flags |= SFLAG_NOFLOORSHADOW;  // No shadows on actors
440
            actor[iActor].flags |= SFLAG_NOFLOORSHADOW;  // No shadows on actors
441
            s->xvel = -256;  // SLIDE_ABOVE_ENEMY
441
            s->xvel = -256;  // SLIDE_ABOVE_ENEMY
442
            A_SetSprite(iActor, CLIPMASK0);
442
            A_SetSprite(iActor, CLIPMASK0);
443
        }
443
        }
444
        else if (s->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && s->owner==florhit)
444
        else if (s->statnum == STAT_PROJECTILE && hitspr->picnum == APLAYER && s->owner==florhit)
445
        {
445
        {
446
            actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
446
            actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
447
            actor[iActor].floorz   = sector[s->sectnum].floorz;
447
            actor[iActor].floorz   = sector[s->sectnum].floorz;
448
        }
448
        }
449
    }
449
    }
450
}
450
}
451
451
452
void A_Fall(int32_t iActor)
452
void A_Fall(int32_t iActor)
453
{
453
{
454
    spritetype *const s = &sprite[iActor];
454
    spritetype *const s = &sprite[iActor];
455
    int c = g_spriteGravity;
455
    int c = g_spriteGravity;
456
456
457
    if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(s->sectnum)))
457
    if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(s->sectnum)))
458
        c = 0;
458
        c = 0;
459
    else if (sector[s->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(s->sectnum)))
459
    else if (sector[s->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(s->sectnum)))
460
        c = g_spriteGravity/6;
460
        c = g_spriteGravity/6;
461
461
462
    if (s->statnum == STAT_ACTOR || s->statnum == STAT_PLAYER || s->statnum == STAT_ZOMBIEACTOR || s->statnum == STAT_STANDABLE)
462
    if (s->statnum == STAT_ACTOR || s->statnum == STAT_PLAYER || s->statnum == STAT_ZOMBIEACTOR || s->statnum == STAT_STANDABLE)
463
    {
463
    {
464
        int32_t ceilhit, florhit;
464
        int32_t ceilhit, florhit;
465
        VM_GetZRange(iActor, &ceilhit, &florhit, 127);
465
        VM_GetZRange(iActor, &ceilhit, &florhit, 127);
466
    }
466
    }
467
    else
467
    else
468
    {
468
    {
469
        actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
469
        actor[iActor].ceilingz = sector[s->sectnum].ceilingz;
470
        actor[iActor].floorz   = sector[s->sectnum].floorz;
470
        actor[iActor].floorz   = sector[s->sectnum].floorz;
471
    }
471
    }
472
472
473
#ifdef YAX_ENABLE
473
#ifdef YAX_ENABLE
474
    int16_t fbunch = (sector[s->sectnum].floorstat&512) ? -1 : yax_getbunch(s->sectnum, YAX_FLOOR);
474
    int16_t fbunch = (sector[s->sectnum].floorstat&512) ? -1 : yax_getbunch(s->sectnum, YAX_FLOOR);
475
#endif
475
#endif
476
476
477
    if (s->z < actor[iActor].floorz-ZOFFSET
477
    if (s->z < actor[iActor].floorz-ZOFFSET
478
#ifdef YAX_ENABLE
478
#ifdef YAX_ENABLE
479
            || fbunch >= 0
479
            || fbunch >= 0
480
#endif
480
#endif
481
       )
481
       )
482
    {
482
    {
483
        if (sector[s->sectnum].lotag == ST_2_UNDERWATER && s->zvel > 3122)
483
        if (sector[s->sectnum].lotag == ST_2_UNDERWATER && s->zvel > 3122)
484
            s->zvel = 3144;
484
            s->zvel = 3144;
485
        s->z += s->zvel = min(6144, s->zvel+c);
485
        s->z += s->zvel = min(6144, s->zvel+c);
486
    }
486
    }
487
487
488
#ifdef YAX_ENABLE
488
#ifdef YAX_ENABLE
489
    if (fbunch >= 0)
489
    if (fbunch >= 0)
490
        setspritez(iActor, (vec3_t *)s);
490
        setspritez(iActor, (vec3_t *)s);
491
    else
491
    else
492
#endif
492
#endif
493
        if (s->z >= actor[iActor].floorz-ZOFFSET)
493
        if (s->z >= actor[iActor].floorz-ZOFFSET)
494
        {
494
        {
495
            s->z = actor[iActor].floorz-ZOFFSET;
495
            s->z = actor[iActor].floorz-ZOFFSET;
496
            s->zvel = 0;
496
            s->zvel = 0;
497
        }
497
        }
498
}
498
}
499
499
500
int32_t G_GetAngleDelta(int32_t a,int32_t na)
500
int32_t G_GetAngleDelta(int32_t a,int32_t na)
501
{
501
{
502
    a &= 2047;
502
    a &= 2047;
503
    na &= 2047;
503
    na &= 2047;
504
504
505
    if (klabs(a-na) < 1024)
505
    if (klabs(a-na) < 1024)
506
    {
506
    {
507
//        OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
507
//        OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
508
        return (na-a);
508
        return (na-a);
509
    }
509
    }
510
510
511
    if (na > 1024) na -= 2048;
511
    if (na > 1024) na -= 2048;
512
    if (a > 1024) a -= 2048;
512
    if (a > 1024) a -= 2048;
513
513
514
//    OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
514
//    OSD_Printf("G_GetAngleDelta() returning %d\n",na-a);
515
    return (na-a);
515
    return (na-a);
516
}
516
}
517
517
518
GAMEEXEC_STATIC void VM_AlterAng(int32_t movflags)
518
GAMEEXEC_STATIC void VM_AlterAng(int32_t movflags)
519
{
519
{
520
    const int32_t ticselapsed = (AC_COUNT(vm.g_t))&31;
520
    const int32_t ticselapsed = (AC_COUNT(vm.g_t))&31;
521
521
522
#if !defined LUNATIC
522
#if !defined LUNATIC
523
    const intptr_t *moveptr;
523
    const intptr_t *moveptr;
524
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.g_t) >= (unsigned)g_scriptSize-1))
524
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.g_t) >= (unsigned)g_scriptSize-1))
525
525
526
    {
526
    {
527
        AC_MOVE_ID(vm.g_t) = 0;
527
        AC_MOVE_ID(vm.g_t) = 0;
528
        OSD_Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
528
        OSD_Printf(OSD_ERROR "bad moveptr for actor %d (%d)!\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
529
        return;
529
        return;
530
    }
530
    }
531
531
532
    moveptr = script + AC_MOVE_ID(vm.g_t);
532
    moveptr = script + AC_MOVE_ID(vm.g_t);
533
533
534
    vm.g_sp->xvel += (moveptr[0] - vm.g_sp->xvel)/5;
534
    vm.g_sp->xvel += (moveptr[0] - vm.g_sp->xvel)/5;
535
    if (vm.g_sp->zvel < 648)
535
    if (vm.g_sp->zvel < 648)
536
        vm.g_sp->zvel += ((moveptr[1]<<4) - vm.g_sp->zvel)/5;
536
        vm.g_sp->zvel += ((moveptr[1]<<4) - vm.g_sp->zvel)/5;
537
#else
537
#else
538
    vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)/5;
538
    vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)/5;
539
    if (vm.g_sp->zvel < 648)
539
    if (vm.g_sp->zvel < 648)
540
        vm.g_sp->zvel += ((actor[vm.g_i].mv.vvel<<4) - vm.g_sp->zvel)/5;
540
        vm.g_sp->zvel += ((actor[vm.g_i].mv.vvel<<4) - vm.g_sp->zvel)/5;
541
#endif
541
#endif
542
542
543
    if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0) // hack
543
    if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0) // hack
544
        return;
544
        return;
545
545
546
    if (movflags&seekplayer)
546
    if (movflags&seekplayer)
547
    {
547
    {
548
        int32_t aang = vm.g_sp->ang, angdif, goalang;
548
        int32_t aang = vm.g_sp->ang, angdif, goalang;
549
        int32_t j = vm.g_pp->holoduke_on;
549
        int32_t j = vm.g_pp->holoduke_on;
550
550
551
        // NOTE: looks like 'owner' is set to target sprite ID...
551
        // NOTE: looks like 'owner' is set to target sprite ID...
552
552
553
        if (j >= 0 && cansee(sprite[j].x,sprite[j].y,sprite[j].z,sprite[j].sectnum,vm.g_sp->x,vm.g_sp->y,vm.g_sp->z,vm.g_sp->sectnum))
553
        if (j >= 0 && cansee(sprite[j].x,sprite[j].y,sprite[j].z,sprite[j].sectnum,vm.g_sp->x,vm.g_sp->y,vm.g_sp->z,vm.g_sp->sectnum))
554
            vm.g_sp->owner = j;
554
            vm.g_sp->owner = j;
555
        else vm.g_sp->owner = vm.g_pp->i;
555
        else vm.g_sp->owner = vm.g_pp->i;
556
556
557
        if (sprite[vm.g_sp->owner].picnum == APLAYER)
557
        if (sprite[vm.g_sp->owner].picnum == APLAYER)
558
            goalang = getangle(actor[vm.g_i].lastvx-vm.g_sp->x,actor[vm.g_i].lastvy-vm.g_sp->y);
558
            goalang = getangle(actor[vm.g_i].lastvx-vm.g_sp->x,actor[vm.g_i].lastvy-vm.g_sp->y);
559
        else
559
        else
560
            goalang = getangle(sprite[vm.g_sp->owner].x-vm.g_sp->x,sprite[vm.g_sp->owner].y-vm.g_sp->y);
560
            goalang = getangle(sprite[vm.g_sp->owner].x-vm.g_sp->x,sprite[vm.g_sp->owner].y-vm.g_sp->y);
561
561
562
        if (vm.g_sp->xvel && vm.g_sp->picnum != DRONE)
562
        if (vm.g_sp->xvel && vm.g_sp->picnum != DRONE)
563
        {
563
        {
564
            angdif = G_GetAngleDelta(aang,goalang);
564
            angdif = G_GetAngleDelta(aang,goalang);
565
565
566
            if (ticselapsed < 2)
566
            if (ticselapsed < 2)
567
            {
567
            {
568
                if (klabs(angdif) < 256)
568
                if (klabs(angdif) < 256)
569
                {
569
                {
570
                    j = 128-(krand()&256);
570
                    j = 128-(krand()&256);
571
                    vm.g_sp->ang += j;
571
                    vm.g_sp->ang += j;
572
                    if (A_GetHitscanRange(vm.g_i) < 844)
572
                    if (A_GetHitscanRange(vm.g_i) < 844)
573
                        vm.g_sp->ang -= j;
573
                        vm.g_sp->ang -= j;
574
                }
574
                }
575
            }
575
            }
576
            else if (ticselapsed > 18 && ticselapsed < GAMETICSPERSEC) // choose
576
            else if (ticselapsed > 18 && ticselapsed < GAMETICSPERSEC) // choose
577
            {
577
            {
578
                if (klabs(angdif>>2) < 128) vm.g_sp->ang = goalang;
578
                if (klabs(angdif>>2) < 128) vm.g_sp->ang = goalang;
579
                else vm.g_sp->ang += angdif>>2;
579
                else vm.g_sp->ang += angdif>>2;
580
            }
580
            }
581
        }
581
        }
582
        else vm.g_sp->ang = goalang;
582
        else vm.g_sp->ang = goalang;
583
    }
583
    }
584
584
585
    if (ticselapsed < 1)
585
    if (ticselapsed < 1)
586
    {
586
    {
587
        if (movflags&furthestdir)
587
        if (movflags&furthestdir)
588
        {
588
        {
589
            vm.g_sp->ang = A_GetFurthestAngle(vm.g_i, 2);
589
            vm.g_sp->ang = A_GetFurthestAngle(vm.g_i, 2);
590
            vm.g_sp->owner = vm.g_pp->i;
590
            vm.g_sp->owner = vm.g_pp->i;
591
        }
591
        }
592
592
593
        if (movflags&fleeenemy)
593
        if (movflags&fleeenemy)
594
            vm.g_sp->ang = A_GetFurthestAngle(vm.g_i, 2);
594
            vm.g_sp->ang = A_GetFurthestAngle(vm.g_i, 2);
595
    }
595
    }
596
}
596
}
597
597
598
static inline void VM_AddAngle(int32_t shr, int32_t goalang)
598
static inline void VM_AddAngle(int32_t shr, int32_t goalang)
599
{
599
{
600
    int32_t angdif = G_GetAngleDelta(vm.g_sp->ang,goalang)>>shr;
600
    int32_t angdif = G_GetAngleDelta(vm.g_sp->ang,goalang)>>shr;
601
601
602
    if ((angdif > -8 && angdif < 0) || (angdif < 8 && angdif > 0))
602
    if ((angdif > -8 && angdif < 0) || (angdif < 8 && angdif > 0))
603
        angdif *= 2;
603
        angdif *= 2;
604
604
605
    vm.g_sp->ang += angdif;
605
    vm.g_sp->ang += angdif;
606
}
606
}
607
607
608
static void VM_FacePlayer(int32_t shr)
608
static void VM_FacePlayer(int32_t shr)
609
{
609
{
610
    int32_t goalang;
610
    int32_t goalang;
611
611
612
    if (vm.g_pp->newowner >= 0)
612
    if (vm.g_pp->newowner >= 0)
613
        goalang = getangle(vm.g_pp->opos.x-vm.g_sp->x, vm.g_pp->opos.y-vm.g_sp->y);
613
        goalang = getangle(vm.g_pp->opos.x-vm.g_sp->x, vm.g_pp->opos.y-vm.g_sp->y);
614
    else
614
    else
615
        goalang = getangle(vm.g_pp->pos.x-vm.g_sp->x, vm.g_pp->pos.y-vm.g_sp->y);
615
        goalang = getangle(vm.g_pp->pos.x-vm.g_sp->x, vm.g_pp->pos.y-vm.g_sp->y);
616
616
617
    VM_AddAngle(shr, goalang);
617
    VM_AddAngle(shr, goalang);
618
}
618
}
619
619
620
////////// TROR get*zofslope //////////
620
////////// TROR get*zofslope //////////
621
// These rather belong into the engine.
621
// These rather belong into the engine.
622
622
623
static int32_t VM_GetCeilZOfSlope(void)
623
static int32_t VM_GetCeilZOfSlope(void)
624
{
624
{
625
    const int dax = vm.g_sp->x, day = vm.g_sp->y;
625
    const int dax = vm.g_sp->x, day = vm.g_sp->y;
626
    const int sectnum = vm.g_sp->sectnum;
626
    const int sectnum = vm.g_sp->sectnum;
627
627
628
#ifdef YAX_ENABLE
628
#ifdef YAX_ENABLE
629
    if ((sector[sectnum].ceilingstat&512)==0)
629
    if ((sector[sectnum].ceilingstat&512)==0)
630
    {
630
    {
631
        int32_t nsect = yax_getneighborsect(dax, day, sectnum, YAX_CEILING);
631
        int32_t nsect = yax_getneighborsect(dax, day, sectnum, YAX_CEILING);
632
        if (nsect >= 0)
632
        if (nsect >= 0)
633
            return getceilzofslope(nsect, dax, day);
633
            return getceilzofslope(nsect, dax, day);
634
    }
634
    }
635
#endif
635
#endif
636
    return getceilzofslope(sectnum, dax, day);
636
    return getceilzofslope(sectnum, dax, day);
637
}
637
}
638
638
639
static int32_t VM_GetFlorZOfSlope(void)
639
static int32_t VM_GetFlorZOfSlope(void)
640
{
640
{
641
    const int dax = vm.g_sp->x, day = vm.g_sp->y;
641
    const int dax = vm.g_sp->x, day = vm.g_sp->y;
642
    const int sectnum = vm.g_sp->sectnum;
642
    const int sectnum = vm.g_sp->sectnum;
643
643
644
#ifdef YAX_ENABLE
644
#ifdef YAX_ENABLE
645
    if ((sector[sectnum].floorstat&512)==0)
645
    if ((sector[sectnum].floorstat&512)==0)
646
    {
646
    {
647
        int32_t nsect = yax_getneighborsect(dax, day, sectnum, YAX_FLOOR);
647
        int32_t nsect = yax_getneighborsect(dax, day, sectnum, YAX_FLOOR);
648
        if (nsect >= 0)
648
        if (nsect >= 0)
649
            return getflorzofslope(nsect, dax, day);
649
            return getflorzofslope(nsect, dax, day);
650
    }
650
    }
651
#endif
651
#endif
652
    return getflorzofslope(sectnum, dax, day);
652
    return getflorzofslope(sectnum, dax, day);
653
}
653
}
654
654
655
////////////////////
655
////////////////////
656
656
657
static int32_t A_GetWaterZOffset(int spritenum);
657
static int32_t A_GetWaterZOffset(int spritenum);
658
658
659
GAMEEXEC_STATIC void VM_Move(void)
659
GAMEEXEC_STATIC void VM_Move(void)
660
{
660
{
661
#if !defined LUNATIC
661
#if !defined LUNATIC
662
    const intptr_t *moveptr;
662
    const intptr_t *moveptr;
663
#endif
663
#endif
664
    // NOTE: commented out condition is dead since r3159 (making hi/lotag unsigned).
664
    // NOTE: commented out condition is dead since r3159 (making hi/lotag unsigned).
665
    // XXX: Does it break anything? Where are movflags with all bits set created?
665
    // XXX: Does it break anything? Where are movflags with all bits set created?
666
    const uint16_t *movflagsptr = &AC_MOVFLAGS(vm.g_sp, &actor[vm.g_i]);
666
    const uint16_t *movflagsptr = &AC_MOVFLAGS(vm.g_sp, &actor[vm.g_i]);
667
    const int32_t movflags = /*(*movflagsptr==-1) ? 0 :*/ *movflagsptr;
667
    const int32_t movflags = /*(*movflagsptr==-1) ? 0 :*/ *movflagsptr;
668
    const int32_t deadflag = (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0);
668
    const int32_t deadflag = (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->extra <= 0);
669
669
670
    AC_COUNT(vm.g_t)++;
670
    AC_COUNT(vm.g_t)++;
671
671
672
    if (AC_MOVE_ID(vm.g_t) == 0 || movflags == 0)
672
    if (AC_MOVE_ID(vm.g_t) == 0 || movflags == 0)
673
    {
673
    {
674
        if (deadflag || (actor[vm.g_i].bpos.x != vm.g_sp->x) || (actor[vm.g_i].bpos.y != vm.g_sp->y))
674
        if (deadflag || (actor[vm.g_i].bpos.x != vm.g_sp->x) || (actor[vm.g_i].bpos.y != vm.g_sp->y))
675
        {
675
        {
676
            actor[vm.g_i].bpos.x = vm.g_sp->x;
676
            actor[vm.g_i].bpos.x = vm.g_sp->x;
677
            actor[vm.g_i].bpos.y = vm.g_sp->y;
677
            actor[vm.g_i].bpos.y = vm.g_sp->y;
678
            setsprite(vm.g_i, (vec3_t *)vm.g_sp);
678
            setsprite(vm.g_i, (vec3_t *)vm.g_sp);
679
        }
679
        }
680
        return;
680
        return;
681
    }
681
    }
682
682
683
    if (deadflag)
683
    if (deadflag)
684
        goto dead;
684
        goto dead;
685
685
686
    if (movflags&face_player)
686
    if (movflags&face_player)
687
        VM_FacePlayer(2);
687
        VM_FacePlayer(2);
688
688
689
    if (movflags&spin)
689
    if (movflags&spin)
690
        vm.g_sp->ang += sintable[((AC_COUNT(vm.g_t)<<3)&2047)]>>6;
690
        vm.g_sp->ang += sintable[((AC_COUNT(vm.g_t)<<3)&2047)]>>6;
691
691
692
    if (movflags&face_player_slow)
692
    if (movflags&face_player_slow)
693
        VM_FacePlayer(4);
693
        VM_FacePlayer(4);
694
694
695
    if ((movflags&jumptoplayer_bits) == jumptoplayer_bits)
695
    if ((movflags&jumptoplayer_bits) == jumptoplayer_bits)
696
    {
696
    {
697
        if (AC_COUNT(vm.g_t) < 16)
697
        if (AC_COUNT(vm.g_t) < 16)
698
            vm.g_sp->zvel -= (sintable[(512+(AC_COUNT(vm.g_t)<<4))&2047]>>5);
698
            vm.g_sp->zvel -= (sintable[(512+(AC_COUNT(vm.g_t)<<4))&2047]>>5);
699
    }
699
    }
700
700
701
    if (movflags&face_player_smart)
701
    if (movflags&face_player_smart)
702
    {
702
    {
703
        int32_t newx = vm.g_pp->pos.x + (vm.g_pp->vel.x/768);
703
        int32_t newx = vm.g_pp->pos.x + (vm.g_pp->vel.x/768);
704
        int32_t newy = vm.g_pp->pos.y + (vm.g_pp->vel.y/768);
704
        int32_t newy = vm.g_pp->pos.y + (vm.g_pp->vel.y/768);
705
        int32_t goalang = getangle(newx-vm.g_sp->x,newy-vm.g_sp->y);
705
        int32_t goalang = getangle(newx-vm.g_sp->x,newy-vm.g_sp->y);
706
        VM_AddAngle(2, goalang);
706
        VM_AddAngle(2, goalang);
707
    }
707
    }
708
708
709
dead:
709
dead:
710
#if !defined LUNATIC
710
#if !defined LUNATIC
711
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.g_t) >= (unsigned)g_scriptSize-1))
711
    if (EDUKE32_PREDICT_FALSE((unsigned)AC_MOVE_ID(vm.g_t) >= (unsigned)g_scriptSize-1))
712
    {
712
    {
713
        AC_MOVE_ID(vm.g_t) = 0;
713
        AC_MOVE_ID(vm.g_t) = 0;
714
        OSD_Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
714
        OSD_Printf(OSD_ERROR "clearing bad moveptr for actor %d (%d)\n", vm.g_i, TrackerCast(vm.g_sp->picnum));
715
        return;
715
        return;
716
    }
716
    }
717
717
718
    moveptr = script + AC_MOVE_ID(vm.g_t);
718
    moveptr = script + AC_MOVE_ID(vm.g_t);
719
719
720
    if (movflags&geth) vm.g_sp->xvel += ((moveptr[0])-vm.g_sp->xvel)>>1;
720
    if (movflags&geth) vm.g_sp->xvel += ((moveptr[0])-vm.g_sp->xvel)>>1;
721
    if (movflags&getv) vm.g_sp->zvel += ((moveptr[1]<<4)-vm.g_sp->zvel)>>1;
721
    if (movflags&getv) vm.g_sp->zvel += ((moveptr[1]<<4)-vm.g_sp->zvel)>>1;
722
#else
722
#else
723
    if (movflags&geth) vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)>>1;
723
    if (movflags&geth) vm.g_sp->xvel += (actor[vm.g_i].mv.hvel - vm.g_sp->xvel)>>1;
724
    if (movflags&getv) vm.g_sp->zvel += (16*actor[vm.g_i].mv.vvel - vm.g_sp->zvel)>>1;
724
    if (movflags&getv) vm.g_sp->zvel += (16*actor[vm.g_i].mv.vvel - vm.g_sp->zvel)>>1;
725
#endif
725
#endif
726
726
727
    if (movflags&dodgebullet && !deadflag)
727
    if (movflags&dodgebullet && !deadflag)
728
        A_Dodge(vm.g_sp);
728
        A_Dodge(vm.g_sp);
729
729
730
    if (vm.g_sp->picnum != APLAYER)
730
    if (vm.g_sp->picnum != APLAYER)
731
        VM_AlterAng(movflags);
731
        VM_AlterAng(movflags);
732
732
733
    if (vm.g_sp->xvel > -6 && vm.g_sp->xvel < 6)
733
    if (vm.g_sp->xvel > -6 && vm.g_sp->xvel < 6)
734
        vm.g_sp->xvel = 0;
734
        vm.g_sp->xvel = 0;
735
735
736
    int badguyp = A_CheckEnemySprite(vm.g_sp);
736
    int badguyp = A_CheckEnemySprite(vm.g_sp);
737
737
738
    if (vm.g_sp->xvel || vm.g_sp->zvel)
738
    if (vm.g_sp->xvel || vm.g_sp->zvel)
739
    {
739
    {
740
        int32_t daxvel = vm.g_sp->xvel;
740
        int32_t daxvel = vm.g_sp->xvel;
741
        int32_t angdif = vm.g_sp->ang;
741
        int32_t angdif = vm.g_sp->ang;
742
742
743
        if (badguyp && vm.g_sp->picnum != ROTATEGUN)
743
        if (badguyp && vm.g_sp->picnum != ROTATEGUN)
744
        {
744
        {
745
            if ((vm.g_sp->picnum == DRONE || vm.g_sp->picnum == COMMANDER) && vm.g_sp->extra > 0)
745
            if ((vm.g_sp->picnum == DRONE || vm.g_sp->picnum == COMMANDER) && vm.g_sp->extra > 0)
746
            {
746
            {
747
                if (vm.g_sp->picnum == COMMANDER)
747
                if (vm.g_sp->picnum == COMMANDER)
748
                {
748
                {
749
                    int32_t l;
749
                    int32_t l;
750
                    // NOTE: COMMANDER updates both actor[].floorz and
750
                    // NOTE: COMMANDER updates both actor[].floorz and
751
                    // .ceilingz regardless of its zvel.
751
                    // .ceilingz regardless of its zvel.
752
                    actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
752
                    actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
753
                    if (vm.g_sp->z > l-(8<<8))
753
                    if (vm.g_sp->z > l-(8<<8))
754
                    {
754
                    {
755
                        vm.g_sp->z = l-(8<<8);
755
                        vm.g_sp->z = l-(8<<8);
756
                        vm.g_sp->zvel = 0;
756
                        vm.g_sp->zvel = 0;
757
                    }
757
                    }
758
758
759
                    actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
759
                    actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
760
                    if (vm.g_sp->z < l+(80<<8))
760
                    if (vm.g_sp->z < l+(80<<8))
761
                    {
761
                    {
762
                        vm.g_sp->z = l+(80<<8);
762
                        vm.g_sp->z = l+(80<<8);
763
                        vm.g_sp->zvel = 0;
763
                        vm.g_sp->zvel = 0;
764
                    }
764
                    }
765
                }
765
                }
766
                else
766
                else
767
                {
767
                {
768
                    int32_t l;
768
                    int32_t l;
769
                    // The DRONE updates either .floorz or .ceilingz, not both.
769
                    // The DRONE updates either .floorz or .ceilingz, not both.
770
                    if (vm.g_sp->zvel > 0)
770
                    if (vm.g_sp->zvel > 0)
771
                    {
771
                    {
772
                        actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
772
                        actor[vm.g_i].floorz = l = VM_GetFlorZOfSlope();
773
                        if (vm.g_sp->z > l-(30<<8))
773
                        if (vm.g_sp->z > l-(30<<8))
774
                            vm.g_sp->z = l-(30<<8);
774
                            vm.g_sp->z = l-(30<<8);
775
                    }
775
                    }
776
                    else
776
                    else
777
                    {
777
                    {
778
                        actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
778
                        actor[vm.g_i].ceilingz = l = VM_GetCeilZOfSlope();
779
                        if (vm.g_sp->z < l+(50<<8))
779
                        if (vm.g_sp->z < l+(50<<8))
780
                        {
780
                        {
781
                            vm.g_sp->z = l+(50<<8);
781
                            vm.g_sp->z = l+(50<<8);
782
                            vm.g_sp->zvel = 0;
782
                            vm.g_sp->zvel = 0;
783
                        }
783
                        }
784
                    }
784
                    }
785
                }
785
                }
786
            }
786
            }
787
            else if (vm.g_sp->picnum != ORGANTIC)
787
            else if (vm.g_sp->picnum != ORGANTIC)
788
            {
788
            {
789
                // All other actors besides ORGANTIC don't update .floorz or
789
                // All other actors besides ORGANTIC don't update .floorz or
790
                // .ceilingz here.
790
                // .ceilingz here.
791
                if (vm.g_sp->zvel > 0)
791
                if (vm.g_sp->zvel > 0)
792
                {
792
                {
793
                    if (vm.g_sp->z > actor[vm.g_i].floorz)
793
                    if (vm.g_sp->z > actor[vm.g_i].floorz)
794
                        vm.g_sp->z = actor[vm.g_i].floorz;
794
                        vm.g_sp->z = actor[vm.g_i].floorz;
795
                    vm.g_sp->z += A_GetWaterZOffset(vm.g_i);
795
                    vm.g_sp->z += A_GetWaterZOffset(vm.g_i);
796
                }
796
                }
797
                else if (vm.g_sp->zvel < 0)
797
                else if (vm.g_sp->zvel < 0)
798
                {
798
                {
799
                    const int32_t l = VM_GetCeilZOfSlope();
799
                    const int32_t l = VM_GetCeilZOfSlope();
800
800
801
                    if (vm.g_sp->z < l+(66<<8))
801
                    if (vm.g_sp->z < l+(66<<8))
802
                    {
802
                    {
803
                        vm.g_sp->z = l+(66<<8);
803
                        vm.g_sp->z = l+(66<<8);
804
                        vm.g_sp->zvel >>= 1;
804
                        vm.g_sp->zvel >>= 1;
805
                    }
805
                    }
806
                }
806
                }
807
            }
807
            }
808
808
809
            if (vm.g_x < 960 && vm.g_sp->xrepeat > 16)
809
            if (vm.g_x < 960 && vm.g_sp->xrepeat > 16)
810
            {
810
            {
811
                daxvel = -(1024 - vm.g_x);
811
                daxvel = -(1024 - vm.g_x);
812
                angdif = getangle(vm.g_pp->pos.x - vm.g_sp->x, vm.g_pp->pos.y - vm.g_sp->y);
812
                angdif = getangle(vm.g_pp->pos.x - vm.g_sp->x, vm.g_pp->pos.y - vm.g_sp->y);
813
813
814
                if (vm.g_x < 512)
814
                if (vm.g_x < 512)
815
                {
815
                {
816
                    vm.g_pp->vel.x = 0;
816
                    vm.g_pp->vel.x = 0;
817
                    vm.g_pp->vel.y = 0;
817
                    vm.g_pp->vel.y = 0;
818
                }
818
                }
819
                else
819
                else
820
                {
820
                {
821
                    vm.g_pp->vel.x = mulscale16(vm.g_pp->vel.x, vm.g_pp->runspeed - 0x2000);
821
                    vm.g_pp->vel.x = mulscale16(vm.g_pp->vel.x, vm.g_pp->runspeed - 0x2000);
822
                    vm.g_pp->vel.y = mulscale16(vm.g_pp->vel.y, vm.g_pp->runspeed - 0x2000);
822
                    vm.g_pp->vel.y = mulscale16(vm.g_pp->vel.y, vm.g_pp->runspeed - 0x2000);
823
                }
823
                }
824
            }
824
            }
825
            else if (vm.g_sp->picnum != DRONE && vm.g_sp->picnum != SHARK && vm.g_sp->picnum != COMMANDER)
825
            else if (vm.g_sp->picnum != DRONE && vm.g_sp->picnum != SHARK && vm.g_sp->picnum != COMMANDER)
826
            {
826
            {
827
                if (vm.g_pp->actorsqu == vm.g_i)
827
                if (vm.g_pp->actorsqu == vm.g_i)
828
                    return;
828
                    return;
829
829
830
                if (!A_CheckSpriteFlags(vm.g_i, SFLAG_SMOOTHMOVE))
830
                if (!A_CheckSpriteFlags(vm.g_i, SFLAG_SMOOTHMOVE))
831
                {
831
                {
832
                    if (AC_COUNT(vm.g_t) & 1)
832
                    if (AC_COUNT(vm.g_t) & 1)
833
                        return;
833
                        return;
834
                    daxvel <<= 1;
834
                    daxvel <<= 1;
835
                }
835
                }
836
            }
836
            }
837
        }
837
        }
838
        else if (vm.g_sp->picnum == APLAYER)
838
        else if (vm.g_sp->picnum == APLAYER)
839
            if (vm.g_sp->z < actor[vm.g_i].ceilingz+(32<<8))
839
            if (vm.g_sp->z < actor[vm.g_i].ceilingz+(32<<8))
840
                vm.g_sp->z = actor[vm.g_i].ceilingz+(32<<8);
840
                vm.g_sp->z = actor[vm.g_i].ceilingz+(32<<8);
841
841
842
        vec3_t tmpvect = { (daxvel * (sintable[(angdif + 512) & 2047])) >> 14,
842
        vec3_t tmpvect = { (daxvel * (sintable[(angdif + 512) & 2047])) >> 14,
843
                           (daxvel * (sintable[angdif & 2047])) >> 14, vm.g_sp->zvel };
843
                           (daxvel * (sintable[angdif & 2047])) >> 14, vm.g_sp->zvel };
844
844
845
        actor[vm.g_i].movflag =
845
        actor[vm.g_i].movflag =
846
            A_MoveSprite(vm.g_i, &tmpvect, (A_CheckSpriteFlags(vm.g_i, SFLAG_NOCLIP) ? 0 : CLIPMASK0));
846
            A_MoveSprite(vm.g_i, &tmpvect, (A_CheckSpriteFlags(vm.g_i, SFLAG_NOCLIP) ? 0 : CLIPMASK0));
847
    }
847
    }
848
848
849
    if (!badguyp)
849
    if (!badguyp)
850
        return;
850
        return;
851
851
852
    vm.g_sp->shade += (sector[vm.g_sp->sectnum].ceilingstat & 1) ?
852
    vm.g_sp->shade += (sector[vm.g_sp->sectnum].ceilingstat & 1) ?
853
                      (sector[vm.g_sp->sectnum].ceilingshade - vm.g_sp->shade) >> 1 :
853
                      (sector[vm.g_sp->sectnum].ceilingshade - vm.g_sp->shade) >> 1 :
854
                      (sector[vm.g_sp->sectnum].floorshade - vm.g_sp->shade) >> 1;
854
                      (sector[vm.g_sp->sectnum].floorshade - vm.g_sp->shade) >> 1;
855
}
855
}
856
856
857
static void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap)
857
static void P_AddWeaponMaybeSwitch(DukePlayer_t *ps, int32_t weap)
858
{
858
{
859
    if ((ps->weaponswitch & (1|4)) == (1|4))
859
    if ((ps->weaponswitch & (1|4)) == (1|4))
860
    {
860
    {
861
        const int32_t snum = P_Get(ps->i);
861
        const int32_t snum = P_Get(ps->i);
862
        int32_t i, new_wchoice = -1, curr_wchoice = -1;
862
        int32_t i, new_wchoice = -1, curr_wchoice = -1;
863
863
864
        for (i=0; i<=FREEZE_WEAPON && (new_wchoice < 0 || curr_wchoice < 0); i++)
864
        for (i=0; i<=FREEZE_WEAPON && (new_wchoice < 0 || curr_wchoice < 0); i++)
865
        {
865
        {
866
            int32_t w = g_player[snum].wchoice[i];
866
            int32_t w = g_player[snum].wchoice[i];
867
867
868
            if (w == KNEE_WEAPON)
868
            if (w == KNEE_WEAPON)
869
                w = FREEZE_WEAPON;
869
                w = FREEZE_WEAPON;
870
            else w--;
870
            else w--;
871
871
872
            if (w == ps->curr_weapon)
872
            if (w == ps->curr_weapon)
873
                curr_wchoice = i;
873
                curr_wchoice = i;
874
            if (w == weap)
874
            if (w == weap)
875
                new_wchoice = i;
875
                new_wchoice = i;
876
        }
876
        }
877
877
878
        P_AddWeapon(ps, weap, (new_wchoice < curr_wchoice));
878
        P_AddWeapon(ps, weap, (new_wchoice < curr_wchoice));
879
    }
879
    }
880
    else
880
    else
881
    {
881
    {
882
        P_AddWeapon(ps, weap, (ps->weaponswitch & 1));
882
        P_AddWeapon(ps, weap, (ps->weaponswitch & 1));
883
    }
883
    }
884
}
884
}
885
885
886
#if defined LUNATIC
886
#if defined LUNATIC
887
void P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap)
887
void P_AddWeaponMaybeSwitchI(int32_t snum, int32_t weap)
888
{
888
{
889
    P_AddWeaponMaybeSwitch(g_player[snum].ps, weap);
889
    P_AddWeaponMaybeSwitch(g_player[snum].ps, weap);
890
}
890
}
891
#else
891
#else
892
static void P_AddWeaponAmmoCommon(DukePlayer_t *ps, int32_t weap, int32_t amount)
892
static void P_AddWeaponAmmoCommon(DukePlayer_t *ps, int32_t weap, int32_t amount)
893
{
893
{
894
    P_AddAmmo(weap, ps, amount);
894
    P_AddAmmo(weap, ps, amount);
895
895
896
    if (PWEAPON(vm.g_p, ps->curr_weapon, WorksLike) == KNEE_WEAPON && (ps->gotweapon & (1 << weap)))
896
    if (PWEAPON(vm.g_p, ps->curr_weapon, WorksLike) == KNEE_WEAPON && (ps->gotweapon & (1 << weap)))
897
        P_AddWeaponMaybeSwitch(ps, weap);
897
        P_AddWeaponMaybeSwitch(ps, weap);
898
}
898
}
899
899
900
static int32_t VM_AddWeapon(int32_t weap, int32_t amount, DukePlayer_t *ps)
900
static int32_t VM_AddWeapon(int32_t weap, int32_t amount, DukePlayer_t *ps)
901
{
901
{
902
    if (EDUKE32_PREDICT_FALSE((unsigned)weap >= MAX_WEAPONS))
902
    if (EDUKE32_PREDICT_FALSE((unsigned)weap >= MAX_WEAPONS))
903
    {
903
    {
904
        CON_ERRPRINTF("Invalid weapon ID %d\n", weap);
904
        CON_ERRPRINTF("Invalid weapon ID %d\n", weap);
905
        return 1;
905
        return 1;
906
    }
906
    }
907
907
908
    if ((ps->gotweapon & (1 << weap)) == 0)
908
    if ((ps->gotweapon & (1 << weap)) == 0)
909
    {
909
    {
910
        P_AddWeaponMaybeSwitch(ps, weap);
910
        P_AddWeaponMaybeSwitch(ps, weap);
911
    }
911
    }
912
    else if (ps->ammo_amount[weap] >= ps->max_ammo_amount[weap])
912
    else if (ps->ammo_amount[weap] >= ps->max_ammo_amount[weap])
913
    {
913
    {
914
        vm.g_flags |= VM_NOEXECUTE;
914
        vm.g_flags |= VM_NOEXECUTE;
915
        return 2;
915
        return 2;
916
    }
916
    }
917
917
918
    P_AddWeaponAmmoCommon(ps, weap, amount);
918
    P_AddWeaponAmmoCommon(ps, weap, amount);
919
919
920
    return 0;
920
    return 0;
921
}
921
}
922
#endif
922
#endif
923
923
924
static int32_t A_GetVerticalVel(const actor_t *ac)
924
static int32_t A_GetVerticalVel(const actor_t *ac)
925
{
925
{
926
#ifdef LUNATIC
926
#ifdef LUNATIC
927
    return ac->mv.vvel;
927
    return ac->mv.vvel;
928
#else
928
#else
929
    int32_t moveScriptOfs = AC_MOVE_ID(ac->t_data);
929
    int32_t moveScriptOfs = AC_MOVE_ID(ac->t_data);
930
930
931
    if ((unsigned)moveScriptOfs < (unsigned)g_scriptSize-1)
931
    if ((unsigned)moveScriptOfs < (unsigned)g_scriptSize-1)
932
        return script[moveScriptOfs + 1];
932
        return script[moveScriptOfs + 1];
933
    else
933
    else
934
        return 0;
934
        return 0;
935
#endif
935
#endif
936
}
936
}
937
937
938
static int32_t A_GetWaterZOffset(int spritenum)
938
static int32_t A_GetWaterZOffset(int spritenum)
939
{
939
{
940
    const spritetype *const sp = &sprite[spritenum];
940
    const spritetype *const sp = &sprite[spritenum];
941
    const actor_t *const ac = &actor[spritenum];
941
    const actor_t *const ac = &actor[spritenum];
942
942
943
    if (sector[sp->sectnum].lotag == ST_1_ABOVE_WATER)
943
    if (sector[sp->sectnum].lotag == ST_1_ABOVE_WATER)
944
    {
944
    {
945
        if (A_CheckSpriteFlags(spritenum, SFLAG_NOWATERDIP))
945
        if (A_CheckSpriteFlags(spritenum, SFLAG_NOWATERDIP))
946
            return 0;
946
            return 0;
947
947
948
        // fix for flying/jumping monsters getting stuck in water
948
        // fix for flying/jumping monsters getting stuck in water
949
        if ((AC_MOVFLAGS(sp, ac) & jumptoplayer_only) ||
949
        if ((AC_MOVFLAGS(sp, ac) & jumptoplayer_only) ||
950
            (G_HaveActor(sp->picnum) && A_GetVerticalVel(ac) != 0))
950
            (G_HaveActor(sp->picnum) && A_GetVerticalVel(ac) != 0))
951
            return 0;
951
            return 0;
952
952
953
        return ACTOR_ONWATER_ADDZ;
953
        return ACTOR_ONWATER_ADDZ;
954
    }
954
    }
955
955
956
    return 0;
956
    return 0;
957
}
957
}
958
958
959
static void VM_Fall(int32_t g_i, spritetype *g_sp)
959
static void VM_Fall(int32_t g_i, spritetype *g_sp)
960
{
960
{
961
    int32_t grav = g_spriteGravity;
961
    int32_t grav = g_spriteGravity;
962
962
963
    g_sp->xoffset = g_sp->yoffset = 0;
963
    g_sp->xoffset = g_sp->yoffset = 0;
964
964
965
    if (sector[g_sp->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(g_sp->sectnum)))
965
    if (sector[g_sp->sectnum].lotag == ST_2_UNDERWATER || EDUKE32_PREDICT_FALSE(G_CheckForSpaceCeiling(g_sp->sectnum)))
966
        grav = g_spriteGravity/6;
966
        grav = g_spriteGravity/6;
967
    else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(g_sp->sectnum)))
967
    else if (EDUKE32_PREDICT_FALSE(G_CheckForSpaceFloor(g_sp->sectnum)))
968
        grav = 0;
968
        grav = 0;
969
969
970
    if (!actor[g_i].cgg-- || (sector[g_sp->sectnum].floorstat&2))
970
    if (!actor[g_i].cgg-- || (sector[g_sp->sectnum].floorstat&2))
971
    {
971
    {
972
        A_GetZLimits(g_i);
972
        A_GetZLimits(g_i);
973
        actor[g_i].cgg = 3;
973
        actor[g_i].cgg = 3;
974
    }
974
    }
975
975
976
    if (g_sp->z < actor[g_i].floorz-ZOFFSET)
976
    if (g_sp->z < actor[g_i].floorz-ZOFFSET)
977
    {
977
    {
978
        // Free fall.
978
        // Free fall.
979
        g_sp->zvel = min(g_sp->zvel+grav, ACTOR_MAXFALLINGZVEL);
979
        g_sp->zvel = min(g_sp->zvel+grav, ACTOR_MAXFALLINGZVEL);
980
        int32_t z = g_sp->z + g_sp->zvel;
980
        int32_t z = g_sp->z + g_sp->zvel;
981
981
982
#ifdef YAX_ENABLE
982
#ifdef YAX_ENABLE
983
        if (yax_getbunch(g_sp->sectnum, YAX_FLOOR) >= 0 &&
983
        if (yax_getbunch(g_sp->sectnum, YAX_FLOOR) >= 0 &&
984
                (sector[g_sp->sectnum].floorstat&512)==0)
984
                (sector[g_sp->sectnum].floorstat&512)==0)
985
            setspritez(g_i, (vec3_t *)g_sp);
985
            setspritez(g_i, (vec3_t *)g_sp);
986
        else
986
        else
987
#endif
987
#endif
988
            if (z > actor[g_i].floorz - ZOFFSET)
988
            if (z > actor[g_i].floorz - ZOFFSET)
989
                z = actor[g_i].floorz - ZOFFSET;
989
                z = actor[g_i].floorz - ZOFFSET;
990
990
991
        g_sp->z = z;
991
        g_sp->z = z;
992
        return;
992
        return;
993
    }
993
    }
994
994
995
    // Preliminary new z position of the actor.
995
    // Preliminary new z position of the actor.
996
    int32_t z = actor[g_i].floorz - ZOFFSET;
996
    int32_t z = actor[g_i].floorz - ZOFFSET;
997
997
998
    if (A_CheckEnemySprite(g_sp) || (g_sp->picnum == APLAYER && g_sp->owner >= 0))
998
    if (A_CheckEnemySprite(g_sp) || (g_sp->picnum == APLAYER && g_sp->owner >= 0))
999
    {
999
    {
1000
        if (g_sp->zvel > 3084 && g_sp->extra <= 1)
1000
        if (g_sp->zvel > 3084 && g_sp->extra <= 1)
1001
        {
1001
        {
1002
            // I'm guessing this DRONE check is from a beta version of the game
1002
            // I'm guessing this DRONE check is from a beta version of the game
1003
            // where they crashed into the ground when killed
1003
            // where they crashed into the ground when killed
1004
            if (!(g_sp->picnum == APLAYER && g_sp->extra > 0) && g_sp->pal != 1 && g_sp->picnum != DRONE)
1004
            if (!(g_sp->picnum == APLAYER && g_sp->extra > 0) && g_sp->pal != 1 && g_sp->picnum != DRONE)
1005
            {
1005
            {
1006
                A_DoGuts(g_i,JIBS6,15);
1006
                A_DoGuts(g_i,JIBS6,15);
1007
                A_PlaySound(SQUISHED,g_i);
1007
                A_PlaySound(SQUISHED,g_i);
1008
                A_Spawn(g_i,BLOODPOOL);
1008
                A_Spawn(g_i,BLOODPOOL);
1009
            }
1009
            }
1010
1010
1011
            actor[g_i].picnum = SHOTSPARK1;
1011
            actor[g_i].picnum = SHOTSPARK1;
1012
            actor[g_i].extra = 1;
1012
            actor[g_i].extra = 1;
1013
            g_sp->zvel = 0;
1013
            g_sp->zvel = 0;
1014
        }
1014
        }
1015
        else if (g_sp->zvel > 2048 && sector[g_sp->sectnum].lotag != ST_1_ABOVE_WATER)
1015
        else if (g_sp->zvel > 2048 && sector[g_sp->sectnum].lotag != ST_1_ABOVE_WATER)
1016
        {
1016
        {
1017
            int16_t newsect = g_sp->sectnum;
1017
            int16_t newsect = g_sp->sectnum;
1018
1018
1019
            pushmove((vec3_t *)g_sp, &newsect, 128, 4<<8, 4<<8, CLIPMASK0);
1019
            pushmove((vec3_t *)g_sp, &newsect, 128, 4<<8, 4<<8, CLIPMASK0);
1020
            if ((unsigned)newsect < MAXSECTORS)
1020
            if ((unsigned)newsect < MAXSECTORS)
1021
                changespritesect(g_i, newsect);
1021
                changespritesect(g_i, newsect);
1022
1022
1023
            A_PlaySound(THUD, g_i);
1023
            A_PlaySound(THUD, g_i);
1024
        }
1024
        }
1025
    }
1025
    }
1026
1026
1027
    if (sector[g_sp->sectnum].lotag == ST_1_ABOVE_WATER)
1027
    if (sector[g_sp->sectnum].lotag == ST_1_ABOVE_WATER)
1028
    {
1028
    {
1029
        g_sp->z = z + A_GetWaterZOffset(g_i);
1029
        g_sp->z = z + A_GetWaterZOffset(g_i);
1030
        return;
1030
        return;
1031
    }
1031
    }
1032
1032
1033
    g_sp->z = z;
1033
    g_sp->z = z;
1034
    g_sp->zvel = 0;
1034
    g_sp->zvel = 0;
1035
}
1035
}
1036
1036
1037
static int32_t VM_ResetPlayer(int32_t g_p, int32_t g_flags)
1037
static int32_t VM_ResetPlayer(int32_t g_p, int32_t g_flags)
1038
{
1038
{
1039
    //AddLog("resetplayer");
1039
    //AddLog("resetplayer");
1040
    if (!g_netServer && ud.multimode < 2)
1040
    if (!g_netServer && ud.multimode < 2)
1041
    {
1041
    {
1042
        if (g_lastSaveSlot >= 0 && ud.recstat != 2)
1042
        if (g_lastSaveSlot >= 0 && ud.recstat != 2)
1043
        {
1043
        {
1044
            M_OpenMenu(g_p);
1044
            M_OpenMenu(g_p);
1045
            KB_ClearKeyDown(sc_Space);
1045
            KB_ClearKeyDown(sc_Space);
1046
            I_AdvanceTriggerClear();
1046
            I_AdvanceTriggerClear();
1047
            M_ChangeMenu(MENU_RESETPLAYER);
1047
            M_ChangeMenu(MENU_RESETPLAYER);
1048
        }
1048
        }
1049
        else g_player[g_p].ps->gm = MODE_RESTART;
1049
        else g_player[g_p].ps->gm = MODE_RESTART;
1050
#if !defined LUNATIC
1050
#if !defined LUNATIC
1051
        g_flags |= VM_NOEXECUTE;
1051
        g_flags |= VM_NOEXECUTE;
1052
#endif
1052
#endif
1053
    }
1053
    }
1054
    else
1054
    else
1055
    {
1055
    {
1056
        if (g_p == myconnectindex)
1056
        if (g_p == myconnectindex)
1057
        {
1057
        {
1058
            CAMERADIST = 0;
1058
            CAMERADIST = 0;
1059
            CAMERACLOCK = totalclock;
1059
            CAMERACLOCK = totalclock;
1060
        }
1060
        }
1061
1061
1062
        if (g_fakeMultiMode)
1062
        if (g_fakeMultiMode)
1063
            P_ResetPlayer(g_p);
1063
            P_ResetPlayer(g_p);
1064
#ifndef NETCODE_DISABLE
1064
#ifndef NETCODE_DISABLE
1065
        if (g_netServer)
1065
        if (g_netServer)
1066
        {
1066
        {
1067
            P_ResetPlayer(g_p);
1067
            P_ResetPlayer(g_p);
1068
            Net_SpawnPlayer(g_p);
1068
            Net_SpawnPlayer(g_p);
1069
        }
1069
        }
1070
#endif
1070
#endif
1071
    }
1071
    }
1072
1072
1073
    P_UpdateScreenPal(g_player[g_p].ps);
1073
    P_UpdateScreenPal(g_player[g_p].ps);
1074
    //AddLog("EOF: resetplayer");
1074
    //AddLog("EOF: resetplayer");
1075
1075
1076
    return g_flags;
1076
    return g_flags;
1077
}
1077
}
1078
1078
1079
void G_GetTimeDate(int32_t *vals)
1079
void G_GetTimeDate(int32_t *vals)
1080
{
1080
{
1081
    time_t rawtime;
1081
    time_t rawtime;
1082
    struct tm *ti;
1082
    struct tm *ti;
1083
1083
1084
    time(&rawtime);
1084
    time(&rawtime);
1085
    ti=localtime(&rawtime);
1085
    ti=localtime(&rawtime);
1086
    // initprintf("Time&date: %s\n",asctime (ti));
1086
    // initprintf("Time&date: %s\n",asctime (ti));
1087
1087
1088
    vals[0] = ti->tm_sec;
1088
    vals[0] = ti->tm_sec;
1089
    vals[1] = ti->tm_min;
1089
    vals[1] = ti->tm_min;
1090
    vals[2] = ti->tm_hour;
1090
    vals[2] = ti->tm_hour;
1091
    vals[3] = ti->tm_mday;
1091
    vals[3] = ti->tm_mday;
1092
    vals[4] = ti->tm_mon;
1092
    vals[4] = ti->tm_mon;
1093
    vals[5] = ti->tm_year+1900;
1093
    vals[5] = ti->tm_year+1900;
1094
    vals[6] = ti->tm_wday;
1094
    vals[6] = ti->tm_wday;
1095
    vals[7] = ti->tm_yday;
1095
    vals[7] = ti->tm_yday;
1096
}
1096
}
1097
1097
1098
int32_t G_StartTrack(int32_t level)
1098
int32_t G_StartTrack(int32_t level)
1099
{
1099
{
1100
    if ((unsigned)level < MAXLEVELS)
1100
    if ((unsigned)level < MAXLEVELS)
1101
    {
1101
    {
1102
        int32_t musicIndex = MAXLEVELS*ud.volume_number + level;
1102
        int32_t musicIndex = MAXLEVELS*ud.volume_number + level;
1103
1103
1104
        if (MapInfo[musicIndex].musicfn != NULL)
1104
        if (MapInfo[musicIndex].musicfn != NULL)
1105
        {
1105
        {
1106
            // Only set g_musicIndex on success.
1106
            // Only set g_musicIndex on success.
1107
            g_musicIndex = musicIndex;
1107
            g_musicIndex = musicIndex;
1108
            S_PlayMusic(MapInfo[musicIndex].musicfn);
1108
            S_PlayMusic(MapInfo[musicIndex].musicfn);
1109
1109
1110
            return 0;
1110
            return 0;
1111
        }
1111
        }
1112
    }
1112
    }
1113
1113
1114
    return 1;
1114
    return 1;
1115
}
1115
}
1116
1116
1117
LUNATIC_EXTERN void G_ShowView(int32_t x, int32_t y, int32_t z, int32_t a, int32_t horiz, int32_t sect,
1117
LUNATIC_EXTERN void G_ShowView(int32_t x, int32_t y, int32_t z, int32_t a, int32_t horiz, int32_t sect,
1118
                               int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp)
1118
                               int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t unbiasedp)
1119
{
1119
{
1120
    int32_t smoothratio = calc_smoothratio(totalclock, ototalclock);
1120
    int32_t smoothratio = calc_smoothratio(totalclock, ototalclock);
1121
#ifdef USE_OPENGL
1121
#ifdef USE_OPENGL
1122
    int32_t oprojhacks;
1122
    int32_t oprojhacks;
1123
#endif
1123
#endif
1124
1124
1125
    if (g_screenCapture)
1125
    if (g_screenCapture)
1126
        return;
1126
        return;
1127
1127
1128
    if (offscreenrendering)
1128
    if (offscreenrendering)
1129
    {
1129
    {
1130
        clearview(0);
1130
        clearview(0);
1131
        return;
1131
        return;
1132
    }
1132
    }
1133
1133
1134
    if (x1 > x2) swaplong(&x1,&x2);
1134
    if (x1 > x2) swaplong(&x1,&x2);
1135
    if (y1 > y2) swaplong(&y1,&y2);
1135
    if (y1 > y2) swaplong(&y1,&y2);
1136
1136
1137
    if (!unbiasedp)
1137
    if (!unbiasedp)
1138
    {
1138
    {
1139
        // The showview command has a rounding bias towards zero,
1139
        // The showview command has a rounding bias towards zero,
1140
        // e.g. floor((319*1680)/320) == 1674
1140
        // e.g. floor((319*1680)/320) == 1674
1141
        x1 = scale(x1,xdim,320);
1141
        x1 = scale(x1,xdim,320);
1142
        y1 = scale(y1,ydim,200);
1142
        y1 = scale(y1,ydim,200);
1143
        x2 = scale(x2,xdim,320);
1143
        x2 = scale(x2,xdim,320);
1144
        y2 = scale(y2,ydim,200);
1144
        y2 = scale(y2,ydim,200);
1145
    }
1145
    }
1146
    else
1146
    else
1147
    {
1147
    {
1148
        // This will map the maximum 320-based coordinate to the
1148
        // This will map the maximum 320-based coordinate to the
1149
        // maximum real screen coordinate:
1149
        // maximum real screen coordinate:
1150
        // floor((319*1679)/319) == 1679
1150
        // floor((319*1679)/319) == 1679
1151
        x1 = scale(x1,xdim-1,319);
1151
        x1 = scale(x1,xdim-1,319);
1152
        y1 = scale(y1,ydim-1,199);
1152
        y1 = scale(y1,ydim-1,199);
1153
        x2 = scale(x2,xdim-1,319);
1153
        x2 = scale(x2,xdim-1,319);
1154
        y2 = scale(y2,ydim-1,199);
1154
        y2 = scale(y2,ydim-1,199);
1155
    }
1155
    }
1156
1156
1157
    horiz = clamp(horiz, HORIZ_MIN, HORIZ_MAX);
1157
    horiz = clamp(horiz, HORIZ_MIN, HORIZ_MAX);
1158
1158
1159
#ifdef USE_OPENGL
1159
#ifdef USE_OPENGL
1160
    oprojhacks = glprojectionhacks;
1160
    oprojhacks = glprojectionhacks;
1161
    glprojectionhacks = 0;
1161
    glprojectionhacks = 0;
1162
#endif
1162
#endif
1163
    {
1163
    {
1164
        int32_t o = newaspect_enable;
1164
        int32_t o = newaspect_enable;
1165
        newaspect_enable = r_usenewaspect;
1165
        newaspect_enable = r_usenewaspect;
1166
        setaspect_new_use_dimen = 1;
1166
        setaspect_new_use_dimen = 1;
1167
1167
1168
        setview(x1,y1,x2,y2);
1168
        setview(x1,y1,x2,y2);
1169
1169
1170
        setaspect_new_use_dimen = 0;
1170
        setaspect_new_use_dimen = 0;
1171
        newaspect_enable = o;
1171
        newaspect_enable = o;
1172
    }
1172
    }
1173
1173
1174
    G_DoInterpolations(smoothratio);
1174
    G_DoInterpolations(smoothratio);
1175
1175
1176
    G_HandleMirror(x, y, z, a, horiz, smoothratio);
1176
    G_HandleMirror(x, y, z, a, horiz, smoothratio);
1177
#ifdef POLYMER
1177
#ifdef POLYMER
1178
    if (getrendermode() == REND_POLYMER)
1178
    if (getrendermode() == REND_POLYMER)
1179
        polymer_setanimatesprites(G_DoSpriteAnimations, x,y,a,smoothratio);
1179
        polymer_setanimatesprites(G_DoSpriteAnimations, x,y,a,smoothratio);
1180
#endif
1180
#endif
1181
    yax_preparedrawrooms();
1181
    yax_preparedrawrooms();
1182
    drawrooms(x,y,z,a,horiz,sect);
1182
    drawrooms(x,y,z,a,horiz,sect);
1183
    yax_drawrooms(G_DoSpriteAnimations, sect, 0, smoothratio);
1183
    yax_drawrooms(G_DoSpriteAnimations, sect, 0, smoothratio);
1184
1184
1185
    display_mirror = 2;
1185
    display_mirror = 2;
1186
    G_DoSpriteAnimations(x,y,a,smoothratio);
1186
    G_DoSpriteAnimations(x,y,a,smoothratio);
1187
    display_mirror = 0;
1187
    display_mirror = 0;
1188
    drawmasks();
1188
    drawmasks();
1189
    G_RestoreInterpolations();
1189
    G_RestoreInterpolations();
1190
    G_UpdateScreenArea();
1190
    G_UpdateScreenArea();
1191
#ifdef USE_OPENGL
1191
#ifdef USE_OPENGL
1192
    glprojectionhacks = oprojhacks;
1192
    glprojectionhacks = oprojhacks;
1193
#endif
1193
#endif
1194
}
1194
}
1195
1195
1196
#if !defined LUNATIC
1196
#if !defined LUNATIC
1197
GAMEEXEC_STATIC void VM_Execute(int loop)
1197
GAMEEXEC_STATIC void VM_Execute(int loop)
1198
{
1198
{
1199
    int tw = *insptr;
1199
    int tw = *insptr;
1200
    DukePlayer_t * const ps = vm.g_pp;
1200
    DukePlayer_t * const ps = vm.g_pp;
1201
1201
1202
    // jump directly into the loop, saving us from the checks during the first iteration
1202
    // jump directly into the loop, saving us from the checks during the first iteration
1203
    goto skip_check;
1203
    goto skip_check;
1204
1204
1205
    while (loop)
1205
    while (loop)
1206
    {
1206
    {
1207
        if (vm.g_flags & (VM_RETURN | VM_KILL | VM_NOEXECUTE))
1207
        if (vm.g_flags & (VM_RETURN | VM_KILL | VM_NOEXECUTE))
1208
            break;
1208
            break;
1209
1209
1210
        tw = *insptr;
1210
        tw = *insptr;
1211
1211
1212
skip_check:
1212
skip_check:
1213
        //      Bsprintf(g_szBuf,"Parsing: %d",*insptr);
1213
        //      Bsprintf(g_szBuf,"Parsing: %d",*insptr);
1214
        //      AddLog(g_szBuf);
1214
        //      AddLog(g_szBuf);
1215
1215
1216
        g_errorLineNum = tw>>12;
1216
        g_errorLineNum = tw>>12;
1217
        g_tw = tw &= VM_INSTMASK;
1217
        g_tw = tw &= VM_INSTMASK;
1218
1218
1219
        if (tw == CON_LEFTBRACE)
1219
        if (tw == CON_LEFTBRACE)
1220
        {
1220
        {
1221
            insptr++;
1221
            insptr++;
1222
            loop++;
1222
            loop++;
1223
            continue;
1223
            continue;
1224
        }
1224
        }
1225
        else if (tw == CON_RIGHTBRACE)
1225
        else if (tw == CON_RIGHTBRACE)
1226
        {
1226
        {
1227
            insptr++;
1227
            insptr++;
1228
            loop--;
1228
            loop--;
1229
            continue;
1229
            continue;
1230
        }
1230
        }
1231
        else if (tw == CON_ELSE)
1231
        else if (tw == CON_ELSE)
1232
        {
1232
        {
1233
            insptr = (intptr_t *) *(insptr+1);
1233
            insptr = (intptr_t *) *(insptr+1);
1234
            continue;
1234
            continue;
1235
        }
1235
        }
1236
        else if (tw == CON_STATE)
1236
        else if (tw == CON_STATE)
1237
        {
1237
        {
1238
            intptr_t const * const tempscrptr = insptr + 2;
1238
            intptr_t const * const tempscrptr = insptr + 2;
1239
            insptr = (intptr_t *)*(insptr + 1);
1239
            insptr = (intptr_t *)*(insptr + 1);
1240
            VM_Execute(1);
1240
            VM_Execute(1);
1241
            insptr = tempscrptr;
1241
            insptr = tempscrptr;
1242
            continue;
1242
            continue;
1243
        }
1243
        }
1244
1244
1245
        switch (tw)
1245
        switch (tw)
1246
        {
1246
        {
1247
        case CON_IFVARE:
1247
        case CON_IFVARE:
1248
            insptr++;
1248
            insptr++;
1249
            tw = Gv_GetVarX(*insptr++);
1249
            tw = Gv_GetVarX(*insptr++);
1250
            VM_CONDITIONAL(tw == *insptr);
1250
            VM_CONDITIONAL(tw == *insptr);
1251
            continue;
1251
            continue;
1252
1252
1253
        case CON_REDEFINEQUOTE:
1253
        case CON_REDEFINEQUOTE:
1254
            insptr++;
1254
            insptr++;
1255
            {
1255
            {
1256
                int32_t q = *insptr++, i = *insptr++;
1256
                int32_t q = *insptr++, i = *insptr++;
1257
                if (EDUKE32_PREDICT_FALSE((ScriptQuotes[q] == NULL || ScriptQuoteRedefinitions[i] == NULL)))
1257
                if (EDUKE32_PREDICT_FALSE((ScriptQuotes[q] == NULL || ScriptQuoteRedefinitions[i] == NULL)))
1258
                {
1258
                {
1259
                    CON_ERRPRINTF("%d %d null quote\n", q,i);
1259
                    CON_ERRPRINTF("%d %d null quote\n", q,i);
1260
                    break;
1260
                    break;
1261
                }
1261
                }
1262
                Bstrcpy(ScriptQuotes[q],ScriptQuoteRedefinitions[i]);
1262
                Bstrcpy(ScriptQuotes[q],ScriptQuoteRedefinitions[i]);
1263
                continue;
1263
                continue;
1264
            }
1264
            }
1265
1265
1266
        case CON_GETTHISPROJECTILE:
1266
        case CON_GETTHISPROJECTILE:
1267
        case CON_SETTHISPROJECTILE:
1267
        case CON_SETTHISPROJECTILE:
1268
            insptr++;
1268
            insptr++;
1269
            {
1269
            {
1270
                // syntax [gs]etplayer[<var>].x <VAR>
1270
                // syntax [gs]etplayer[<var>].x <VAR>
1271
                // <varid> <xxxid> <varid>
1271
                // <varid> <xxxid> <varid>
1272
                int32_t lVar1=*insptr++, lLabelID=*insptr++, lVar2=*insptr++;
1272
                int32_t lVar1=*insptr++, lLabelID=*insptr++, lVar2=*insptr++;
1273
1273
1274
                VM_AccessActiveProjectile(tw==CON_SETTHISPROJECTILE,lVar1,lLabelID,lVar2);
1274
                VM_AccessActiveProjectile(tw==CON_SETTHISPROJECTILE,lVar1,lLabelID,lVar2);
1275
                continue;
1275
                continue;
1276
            }
1276
            }
1277
1277
1278
        case CON_IFRND:
1278
        case CON_IFRND:
1279
            VM_CONDITIONAL(rnd(*(++insptr)));
1279
            VM_CONDITIONAL(rnd(*(++insptr)));
1280
            continue;
1280
            continue;
1281
1281
1282
        case CON_IFCANSHOOTTARGET:
1282
        case CON_IFCANSHOOTTARGET:
1283
        {
1283
        {
1284
            if (vm.g_x > 1024)
1284
            if (vm.g_x > 1024)
1285
            {
1285
            {
1286
                int16_t temphit;
1286
                int16_t temphit;
1287
1287
1288
                if ((tw = A_CheckHitSprite(vm.g_i, &temphit)) == (1 << 30))
1288
                if ((tw = A_CheckHitSprite(vm.g_i, &temphit)) == (1 << 30))
1289
                {
1289
                {
1290
                    VM_CONDITIONAL(1);
1290
                    VM_CONDITIONAL(1);
1291
                    continue;
1291
                    continue;
1292
                }
1292
                }
1293
1293
1294
                int32_t sclip = 768, angdif = 16;
1294
                int32_t sclip = 768, angdif = 16;
1295
1295
1296
                if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->xrepeat > 56)
1296
                if (A_CheckEnemySprite(vm.g_sp) && vm.g_sp->xrepeat > 56)
1297
                {
1297
                {
1298
                    sclip = 3084;
1298
                    sclip = 3084;
1299
                    angdif = 48;
1299
                    angdif = 48;
1300
                }
1300
                }
1301
1301
1302
#define CHECK(x) if (x >= 0 && sprite[x].picnum == vm.g_sp->picnum) { VM_CONDITIONAL(0); continue; }
1302
#define CHECK(x) if (x >= 0 && sprite[x].picnum == vm.g_sp->picnum) { VM_CONDITIONAL(0); continue; }
1303
#define CHECK2(x) do { vm.g_sp->ang += x; tw = A_CheckHitSprite(vm.g_i, &temphit); vm.g_sp->ang -= x; } while(0)
1303
#define CHECK2(x) do { vm.g_sp->ang += x; tw = A_CheckHitSprite(vm.g_i, &temphit); vm.g_sp->ang -= x; } while(0)
1304
1304
1305
                if (tw > sclip)
1305
                if (tw > sclip)
1306
                {
1306
                {
1307
                    CHECK(temphit);
1307
                    CHECK(temphit);
1308
                    CHECK2(angdif);
1308
                    CHECK2(angdif);
1309
1309
1310
                    if (tw > sclip)
1310
                    if (tw > sclip)
1311
                    {
1311
                    {
1312
                        CHECK(temphit);
1312
                        CHECK(temphit);
1313
                        CHECK2(-angdif);
1313
                        CHECK2(-angdif);
1314
1314
1315
                        if (tw > 768)
1315
                        if (tw > 768)
1316
                        {
1316
                        {
1317
                            CHECK(temphit);
1317
                            CHECK(temphit);
1318
                            VM_CONDITIONAL(1);
1318
                            VM_CONDITIONAL(1);
1319
                            continue;
1319
                            continue;
1320
                        }
1320
                        }
1321
                    }
1321
                    }
1322
                }
1322
                }
1323
            }
1323
            }
1324
            VM_CONDITIONAL(1);
1324
            VM_CONDITIONAL(1);
1325
        }
1325
        }
1326
        continue;
1326
        continue;
1327
1327
1328
        case CON_IFCANSEETARGET:
1328
        case CON_IFCANSEETARGET:
1329
            tw = cansee(vm.g_sp->x, vm.g_sp->y, vm.g_sp->z-((krand()&41)<<8),
1329
            tw = cansee(vm.g_sp->x, vm.g_sp->y, vm.g_sp->z-((krand()&41)<<8),
1330
                               vm.g_sp->sectnum, ps->pos.x, ps->pos.y,
1330
                               vm.g_sp->sectnum, ps->pos.x, ps->pos.y,
1331
                               ps->pos.z/*-((krand()&41)<<8)*/, sprite[ps->i].sectnum);
1331
                               ps->pos.z/*-((krand()&41)<<8)*/, sprite[ps->i].sectnum);
1332
            VM_CONDITIONAL(tw);
1332
            VM_CONDITIONAL(tw);
1333
            if (tw) actor[vm.g_i].timetosleep = SLEEPTIME;
1333
            if (tw) actor[vm.g_i].timetosleep = SLEEPTIME;
1334
        continue;
1334
        continue;
1335
1335
1336
        case CON_IFACTORNOTSTAYPUT:
1336
        case CON_IFACTORNOTSTAYPUT:
1337
            VM_CONDITIONAL(actor[vm.g_i].actorstayput == -1);
1337
            VM_CONDITIONAL(actor[vm.g_i].actorstayput == -1);
1338
            continue;
1338
            continue;
1339
1339
1340
        case CON_IFCANSEE:
1340
        case CON_IFCANSEE:
1341
        {
1341
        {
1342
            tspritetype *s = (tspritetype *)&sprite[ps->i];
1342
            tspritetype *s = (tspritetype *)&sprite[ps->i];
1343
1343
1344
            // select sprite for monster to target
1344
            // select sprite for monster to target
1345
            // if holoduke is on, let them target holoduke first.
1345
            // if holoduke is on, let them target holoduke first.
1346
            //
1346
            //
1347
            if (ps->holoduke_on >= 0)
1347
            if (ps->holoduke_on >= 0)
1348
            {
1348
            {
1349
                s = (tspritetype *)&sprite[ps->holoduke_on];
1349
                s = (tspritetype *)&sprite[ps->holoduke_on];
1350
                tw = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z-(krand()&((32<<8)-1)),vm.g_sp->sectnum,
1350
                tw = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z-(krand()&((32<<8)-1)),vm.g_sp->sectnum,
1351
                           s->x,s->y,s->z,s->sectnum);
1351
                           s->x,s->y,s->z,s->sectnum);
1352
1352
1353
                if (tw == 0)
1353
                if (tw == 0)
1354
                {
1354
                {
1355
                    // they can't see player's holoduke
1355
                    // they can't see player's holoduke
1356
                    // check for player...
1356
                    // check for player...
1357
                    s = (tspritetype *)&sprite[ps->i];
1357
                    s = (tspritetype *)&sprite[ps->i];
1358
                }
1358
                }
1359
            }
1359
            }
1360
1360
1361
            // can they see player, (or player's holoduke)
1361
            // can they see player, (or player's holoduke)
1362
            tw = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z-(krand()&((47<<8))),vm.g_sp->sectnum,
1362
            tw = cansee(vm.g_sp->x,vm.g_sp->y,vm.g_sp->z-(krand()&((47<<8))),vm.g_sp->sectnum,
1363
                       s->x,s->y,s->z-(24<<8),s->sectnum);
1363
                       s->x,s->y,s->z-(24<<8),s->sectnum);
1364
1364
1365
            if (tw == 0)
1365
            if (tw == 0)
1366
            {
1366
            {
1367
                // search around for target player
1367
                // search around for target player
1368
1368
1369
                // also modifies 'target' x&y if found..
1369
                // also modifies 'target' x&y if found..
1370
1370
1371
                tw = 1;
1371
                tw = 1;
1372
                if (A_FurthestVisiblePoint(vm.g_i,s,&actor[vm.g_i].lastvx,&actor[vm.g_i].lastvy) == -1)
1372
                if (A_FurthestVisiblePoint(vm.g_i,s,&actor[vm.g_i].lastvx,&actor[vm.g_i].lastvy) == -1)
1373
                    tw = 0;
1373
                    tw = 0;
1374
            }
1374
            }
1375
            else
1375
            else
1376
            {
1376
            {
1377
                // else, they did see it.
1377
                // else, they did see it.
1378
                // save where we were looking...
1378
                // save where we were looking...
1379
                actor[vm.g_i].lastvx = s->x;
1379
                actor[vm.g_i].lastvx = s->x;
1380
                actor[vm.g_i].lastvy = s->y;
1380
                actor[vm.g_i].lastvy = s->y;
1381
            }
1381
            }
1382
1382
1383
            if (tw && (vm.g_sp->statnum == STAT_ACTOR || vm.g_sp->statnum == STAT_STANDABLE))
1383
            if (tw && (vm.g_sp->statnum == STAT_ACTOR || vm.g_sp->statnum == STAT_STANDABLE))
1384
                actor[vm.g_i].timetosleep = SLEEPTIME;
1384
                actor[vm.g_i].timetosleep = SLEEPTIME;
1385
1385
1386
            VM_CONDITIONAL(tw);
1386
            VM_CONDITIONAL(tw);
1387
            continue;
1387
            continue;
1388
        }
1388
        }
1389
1389
1390
        case CON_IFHITWEAPON:
1390
        case CON_IFHITWEAPON:
1391
            VM_CONDITIONAL(A_IncurDamage(vm.g_i) >= 0);
1391
            VM_CONDITIONAL(A_IncurDamage(vm.g_i) >= 0);
1392
            continue;
1392
            continue;
1393
1393
1394
        case CON_IFSQUISHED:
1394
        case CON_IFSQUISHED:
1395
            VM_CONDITIONAL(VM_CheckSquished());
1395
            VM_CONDITIONAL(VM_CheckSquished());
1396
            continue;
1396
            continue;
1397
1397
1398
        case CON_IFDEAD:
1398
        case CON_IFDEAD:
1399
            VM_CONDITIONAL(vm.g_sp->extra <= 0);
1399
            VM_CONDITIONAL(vm.g_sp->extra <= 0);
1400
            continue;
1400
            continue;
1401
1401
1402
        case CON_AI:
1402
        case CON_AI:
1403
            insptr++;
1403
            insptr++;
1404
            //Following changed to use pointersizes
1404
            //Following changed to use pointersizes
1405
            AC_AI_ID(vm.g_t) = *insptr++; // Ai
1405
            AC_AI_ID(vm.g_t) = *insptr++; // Ai
1406
1406
1407
            AC_ACTION_ID(vm.g_t) = *(script + AC_AI_ID(vm.g_t));  // Action
1407
            AC_ACTION_ID(vm.g_t) = *(script + AC_AI_ID(vm.g_t));  // Action
1408
1408
1409
            // NOTE: "if" check added in r1155. It used to be a pointer though.
1409
            // NOTE: "if" check added in r1155. It used to be a pointer though.
1410
            if (AC_AI_ID(vm.g_t))
1410
            if (AC_AI_ID(vm.g_t))
1411
                AC_MOVE_ID(vm.g_t) = *(script + AC_AI_ID(vm.g_t) + 1);  // move
1411
                AC_MOVE_ID(vm.g_t) = *(script + AC_AI_ID(vm.g_t) + 1);  // move
1412
1412
1413
            vm.g_sp->hitag = *(script + AC_AI_ID(vm.g_t) + 2);  // move flags
1413
            vm.g_sp->hitag = *(script + AC_AI_ID(vm.g_t) + 2);  // move flags
1414
1414
1415
            AC_COUNT(vm.g_t) = AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
1415
            AC_COUNT(vm.g_t) = AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
1416
1416
1417
            if (!A_CheckEnemySprite(vm.g_sp) || vm.g_sp->extra > 0) // hack
1417
            if (!A_CheckEnemySprite(vm.g_sp) || vm.g_sp->extra > 0) // hack
1418
                if (vm.g_sp->hitag&random_angle)
1418
                if (vm.g_sp->hitag&random_angle)
1419
                    vm.g_sp->ang = krand()&2047;
1419
                    vm.g_sp->ang = krand()&2047;
1420
            continue;
1420
            continue;
1421
1421
1422
        case CON_ACTION:
1422
        case CON_ACTION:
1423
            insptr++;
1423
            insptr++;
1424
            AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
1424
            AC_ACTION_COUNT(vm.g_t) = AC_CURFRAME(vm.g_t) = 0;
1425
            AC_ACTION_ID(vm.g_t) = *insptr++;
1425
            AC_ACTION_ID(vm.g_t) = *insptr++;
1426
            continue;
1426
            continue;
1427
1427
1428
        case CON_IFPLAYERSL:
1428
        case CON_IFPLAYERSL:
1429
            VM_CONDITIONAL(numplayers < *(++insptr));
1429
            VM_CONDITIONAL(numplayers < *(++insptr));
1430
            continue;
1430
            continue;
1431
1431
1432
        case CON_IFPDISTL:
1432
        case CON_IFPDISTL:
1433
            VM_CONDITIONAL(vm.g_x < *(++insptr));
1433
            VM_CONDITIONAL(vm.g_x < *(++insptr));
1434
            if (vm.g_x > MAXSLEEPDIST && actor[vm.g_i].timetosleep == 0)
1434
            if (vm.g_x > MAXSLEEPDIST && actor[vm.g_i].timetosleep == 0)
1435
                actor[vm.g_i].timetosleep = SLEEPTIME;
1435
                actor[vm.g_i].timetosleep = SLEEPTIME;
1436
            continue;
1436
            continue;
1437
1437
1438
        case CON_IFPDISTG:
1438
        case CON_IFPDISTG:
1439
            VM_CONDITIONAL(vm.g_x > *(++insptr));
1439
            VM_CONDITIONAL(vm.g_x > *(++insptr));
1440
            if (vm.g_x > MAXSLEEPDIST && actor[vm.g_i].timetosleep == 0)
1440
            if (vm.g_x > MAXSLEEPDIST && actor[vm.g_i].timetosleep == 0)
1441
                actor[vm.g_i].timetosleep = SLEEPTIME;
1441
                actor[vm.g_i].timetosleep = SLEEPTIME;
1442
            continue;
1442
            continue;
1443
1443
1444
        case CON_ADDSTRENGTH:
1444
        case CON_ADDSTRENGTH:
1445
            insptr++;
1445
            insptr++;
1446
            vm.g_sp->extra += *insptr++;
1446
            vm.g_sp->extra += *insptr++;
1447
            continue;
1447
            continue;
1448
1448
1449
        case CON_STRENGTH:
1449
        case CON_STRENGTH:
1450
            insptr++;
1450
            insptr++;
1451
            vm.g_sp->extra = *insptr++;
1451
            vm.g_sp->extra = *insptr++;
1452
            continue;
1452
            continue;
1453
1453
1454
        case CON_IFGOTWEAPONCE:
1454
        case CON_IFGOTWEAPONCE:
1455
            insptr++;
1455
            insptr++;
1456
1456
1457
            if ((GametypeFlags[ud.coop]&GAMETYPE_WEAPSTAY) && (g_netServer || ud.multimode > 1))
1457
            if ((GametypeFlags[ud.coop]&GAMETYPE_WEAPSTAY) && (g_netServer || ud.multimode > 1))
1458
            {
1458
            {
1459
                if (*insptr == 0)
1459
                if (*insptr == 0)
1460
                {
1460
                {
1461
                    int32_t j = 0;
1461
                    int32_t j = 0;
1462
                    for (; j < ps->weapreccnt; j++)
1462
                    for (; j < ps->weapreccnt; j++)
1463
                        if (ps->weaprecs[j] == vm.g_sp->picnum)
1463
                        if (ps->weaprecs[j] == vm.g_sp->picnum)
1464
                            break;
1464
                            break;
1465
1465
1466
                    VM_CONDITIONAL(j < ps->weapreccnt && vm.g_sp->owner == vm.g_i);
1466
                    VM_CONDITIONAL(j < ps->weapreccnt && vm.g_sp->owner == vm.g_i);
1467
                    continue;
1467
                    continue;
1468
                }
1468
                }
1469
                else if (ps->weapreccnt < MAX_WEAPONS)
1469
                else if (ps->weapreccnt < MAX_WEAPONS)
1470
                {
1470
                {
1471
                    ps->weaprecs[ps->weapreccnt++] = vm.g_sp->picnum;
1471
                    ps->weaprecs[ps->weapreccnt++] = vm.g_sp->picnum;
1472
                    VM_CONDITIONAL(vm.g_sp->owner == vm.g_i);
1472
                    VM_CONDITIONAL(vm.g_sp->owner == vm.g_i);
1473
                    continue;
1473
                    continue;
1474
                }
1474
                }
1475
            }
1475
            }
1476
            VM_CONDITIONAL(0);
1476
            VM_CONDITIONAL(0);
1477
            continue;
1477
            continue;
1478
1478
1479
        case CON_GETLASTPAL:
1479
        case CON_GETLASTPAL:
1480
            insptr++;
1480
            insptr++;
1481
            if (vm.g_sp->picnum == APLAYER)
1481
            if (vm.g_sp->picnum == APLAYER)
1482
                vm.g_sp->pal = g_player[P_GetP(vm.g_sp)].ps->palookup;
1482
                vm.g_sp->pal = g_player[P_GetP(vm.g_sp)].ps->palookup;
1483
            else
1483
            else
1484
            {
1484
            {
1485
                if (vm.g_sp->pal == 1 && vm.g_sp->extra == 0) // hack for frozen
1485
                if (vm.g_sp->pal == 1 && vm.g_sp->extra == 0) // hack for frozen
1486
                    vm.g_sp->extra++;
1486
                    vm.g_sp->extra++;
1487
                vm.g_sp->pal = actor[vm.g_i].tempang;
1487
                vm.g_sp->pal = actor[vm.g_i].tempang;
1488
            }
1488
            }
1489
            actor[vm.g_i].tempang = 0;
1489
            actor[vm.g_i].tempang = 0;
1490
            continue;
1490
            continue;
1491
1491
1492
        case CON_TOSSWEAPON:
1492
        case CON_TOSSWEAPON:
1493
            insptr++;
1493
            insptr++;
1494
            // NOTE: assumes that current actor is APLAYER
1494
            // NOTE: assumes that current actor is APLAYER
1495
            P_DropWeapon(P_GetP(vm.g_sp));
1495
            P_DropWeapon(P_GetP(vm.g_sp));
1496
            continue;
1496
            continue;
1497
1497
1498
        case CON_MIKESND:
1498
        case CON_MIKESND:
1499
            insptr++;
1499
            insptr++;
1500
            if (EDUKE32_PREDICT_FALSE(((unsigned)vm.g_sp->yvel >= MAXSOUNDS)))
1500
            if (EDUKE32_PREDICT_FALSE(((unsigned)vm.g_sp->yvel >= MAXSOUNDS)))
1501
            {
1501
            {
1502
                CON_ERRPRINTF("Invalid sound %d\n", TrackerCast(vm.g_sp->yvel));
1502
                CON_ERRPRINTF("Invalid sound %d\n", TrackerCast(vm.g_sp->yvel));
1503
                continue;
1503
                continue;
1504
            }
1504
            }
1505
            if (!S_CheckSoundPlaying(vm.g_i,vm.g_sp->yvel))
1505
            if (!S_CheckSoundPlaying(vm.g_i,vm.g_sp->yvel))
1506
                A_PlaySound(vm.g_sp->yvel,vm.g_i);
1506
                A_PlaySound(vm.g_sp->yvel,vm.g_i);
1507
            continue;
1507
            continue;
1508
1508
1509
        case CON_PKICK:
1509
        case CON_PKICK:
1510
            insptr++;
1510
            insptr++;
1511
1511
1512
            if ((g_netServer || ud.multimode > 1) && vm.g_sp->picnum == APLAYER)
1512
            if ((g_netServer || ud.multimode > 1) && vm.g_sp->picnum == APLAYER)
1513
            {
1513
            {
1514
                if (g_player[otherp].ps->quick_kick == 0)
1514
                if (g_player[otherp].ps->quick_kick == 0)
1515
                    g_player[otherp].ps->quick_kick = 14;
1515
                    g_player[otherp].ps->quick_kick = 14;
1516
            }
1516
            }
1517
            else if (vm.g_sp->picnum != APLAYER && ps->quick_kick == 0)
1517
            else if (vm.g_sp->picnum != APLAYER && ps->quick_kick == 0)
1518
                ps->quick_kick = 14;
1518
                ps->quick_kick = 14;
1519
            continue;
1519
            continue;
1520
1520
1521
        case CON_SIZETO:
1521
        case CON_SIZETO:
1522
            insptr++;
1522
            insptr++;
1523
1523
1524
            tw = (*insptr++ - vm.g_sp->xrepeat)<<1;
1524
            tw = (*insptr++ - vm.g_sp->xrepeat)<<1;
1525
            vm.g_sp->xrepeat += ksgn(tw);
1525
            vm.g_sp->xrepeat += ksgn(tw);
1526
1526
1527
            if ((vm.g_sp->picnum == APLAYER && vm.g_sp->yrepeat < 36) || *insptr < vm.g_sp->yrepeat ||
1527
            if ((vm.g_sp->picnum == APLAYER && vm.g_sp->yrepeat < 36) || *insptr < vm.g_sp->yrepeat ||
1528
                    ((vm.g_sp->yrepeat*(tilesiz[vm.g_sp->picnum].y+8))<<2) < (actor[vm.g_i].floorz - actor[vm.g_i].ceilingz))
1528
                    ((vm.g_sp->yrepeat*(tilesiz[vm.g_sp->picnum].y+8))<<2) < (actor[vm.g_i].floorz - actor[vm.g_i].ceilingz))
1529
            {
1529
            {
1530
                tw = ((*insptr)-vm.g_sp->yrepeat)<<1;
1530
                tw = ((*insptr)-vm.g_sp->yrepeat)<<1;
1531
                if (klabs(tw)) vm.g_sp->yrepeat += ksgn(tw);
1531
                if (klabs(tw)) vm.g_sp->yrepeat += ksgn(tw);
1532
            }
1532
            }
1533
1533
1534
            insptr++;
1534
            insptr++;
1535
1535
1536
            continue;
1536
            continue;
1537
1537
1538
        case CON_SIZEAT:
1538
        case CON_SIZEAT:
1539
            insptr++;
1539
            insptr++;
1540
            vm.g_sp->xrepeat = (uint8_t) *insptr++;
1540
            vm.g_sp->xrepeat = (uint8_t) *insptr++;
1541
            vm.g_sp->yrepeat = (uint8_t) *insptr++;
1541
            vm.g_sp->yrepeat = (uint8_t) *insptr++;
1542
            continue;
1542
            continue;
1543
1543
1544
        case CON_SHOOT:
1544
        case CON_SHOOT:
1545
            insptr++;
1545
            insptr++;
1546
            A_Shoot(vm.g_i,*insptr++);
1546
            A_Shoot(vm.g_i,*insptr++);
1547
            continue;
1547
            continue;
1548
1548
1549
        case CON_SOUNDONCE:
1549
        case CON_SOUNDONCE:
1550
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1550
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1551
            {
1551
            {
1552
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr++);
1552
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr++);
1553
                continue;
1553
                continue;
1554
            }
1554
            }
1555
            if (!S_CheckSoundPlaying(vm.g_i,*insptr++))
1555
            if (!S_CheckSoundPlaying(vm.g_i,*insptr++))
1556
                A_PlaySound(*(insptr-1),vm.g_i);
1556
                A_PlaySound(*(insptr-1),vm.g_i);
1557
            continue;
1557
            continue;
1558
1558
1559
        case CON_IFACTORSOUND:
1559
        case CON_IFACTORSOUND:
1560
            insptr++;
1560
            insptr++;
1561
            {
1561
            {
1562
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
1562
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
1563
1563
1564
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSOUNDS))
1564
                if (EDUKE32_PREDICT_FALSE((unsigned)j >= MAXSOUNDS))
1565
                {
1565
                {
1566
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1566
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1567
                    insptr++;
1567
                    insptr++;
1568
                    continue;
1568
                    continue;
1569
                }
1569
                }
1570
                insptr--;
1570
                insptr--;
1571
                VM_CONDITIONAL(A_CheckSoundPlaying(i,j));
1571
                VM_CONDITIONAL(A_CheckSoundPlaying(i,j));
1572
            }
1572
            }
1573
            continue;
1573
            continue;
1574
1574
1575
        case CON_IFSOUND:
1575
        case CON_IFSOUND:
1576
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1576
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1577
            {
1577
            {
1578
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1578
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1579
                insptr++;
1579
                insptr++;
1580
                continue;
1580
                continue;
1581
            }
1581
            }
1582
            VM_CONDITIONAL(S_CheckSoundPlaying(vm.g_i,*insptr));
1582
            VM_CONDITIONAL(S_CheckSoundPlaying(vm.g_i,*insptr));
1583
            //    VM_DoConditional(SoundOwner[*insptr][0].ow == vm.g_i);
1583
            //    VM_DoConditional(SoundOwner[*insptr][0].ow == vm.g_i);
1584
            continue;
1584
            continue;
1585
1585
1586
        case CON_STOPSOUND:
1586
        case CON_STOPSOUND:
1587
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1587
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1588
            {
1588
            {
1589
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1589
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1590
                insptr++;
1590
                insptr++;
1591
                continue;
1591
                continue;
1592
            }
1592
            }
1593
            if (S_CheckSoundPlaying(vm.g_i,*insptr))
1593
            if (S_CheckSoundPlaying(vm.g_i,*insptr))
1594
                S_StopSound((int16_t)*insptr);
1594
                S_StopSound((int16_t)*insptr);
1595
            insptr++;
1595
            insptr++;
1596
            continue;
1596
            continue;
1597
1597
1598
        case CON_STOPACTORSOUND:
1598
        case CON_STOPACTORSOUND:
1599
            insptr++;
1599
            insptr++;
1600
            {
1600
            {
1601
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
1601
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++);
1602
1602
1603
                if (EDUKE32_PREDICT_FALSE((unsigned)j>=MAXSOUNDS))
1603
                if (EDUKE32_PREDICT_FALSE((unsigned)j>=MAXSOUNDS))
1604
                {
1604
                {
1605
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1605
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1606
                    continue;
1606
                    continue;
1607
                }
1607
                }
1608
1608
1609
                if (A_CheckSoundPlaying(i,j))
1609
                if (A_CheckSoundPlaying(i,j))
1610
                    S_StopEnvSound(j,i);
1610
                    S_StopEnvSound(j,i);
1611
1611
1612
                continue;
1612
                continue;
1613
            }
1613
            }
1614
1614
1615
        case CON_SETACTORSOUNDPITCH:
1615
        case CON_SETACTORSOUNDPITCH:
1616
            insptr++;
1616
            insptr++;
1617
            {
1617
            {
1618
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++), pitchoffset = Gv_GetVarX(*insptr++);
1618
                int32_t i = Gv_GetVarX(*insptr++), j = Gv_GetVarX(*insptr++), pitchoffset = Gv_GetVarX(*insptr++);
1619
1619
1620
                if (EDUKE32_PREDICT_FALSE((unsigned)j>=MAXSOUNDS))
1620
                if (EDUKE32_PREDICT_FALSE((unsigned)j>=MAXSOUNDS))
1621
                {
1621
                {
1622
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1622
                    CON_ERRPRINTF("Invalid sound %d\n", j);
1623
                    continue;
1623
                    continue;
1624
                }
1624
                }
1625
1625
1626
                S_ChangeSoundPitch(j,i,pitchoffset);
1626
                S_ChangeSoundPitch(j,i,pitchoffset);
1627
1627
1628
                continue;
1628
                continue;
1629
            }
1629
            }
1630
1630
1631
        case CON_GLOBALSOUND:
1631
        case CON_GLOBALSOUND:
1632
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1632
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1633
            {
1633
            {
1634
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1634
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1635
                insptr++;
1635
                insptr++;
1636
                continue;
1636
                continue;
1637
            }
1637
            }
1638
            if (vm.g_p == screenpeek || (GametypeFlags[ud.coop]&GAMETYPE_COOPSOUND)
1638
            if (vm.g_p == screenpeek || (GametypeFlags[ud.coop]&GAMETYPE_COOPSOUND)
1639
#ifdef SPLITSCREEN_MOD_HACKS
1639
#ifdef SPLITSCREEN_MOD_HACKS
1640
                || (g_fakeMultiMode==2)
1640
                || (g_fakeMultiMode==2)
1641
#endif
1641
#endif
1642
                )
1642
                )
1643
                A_PlaySound(*insptr,g_player[screenpeek].ps->i);
1643
                A_PlaySound(*insptr,g_player[screenpeek].ps->i);
1644
            insptr++;
1644
            insptr++;
1645
            continue;
1645
            continue;
1646
1646
1647
        case CON_SOUND:
1647
        case CON_SOUND:
1648
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1648
            if (EDUKE32_PREDICT_FALSE((unsigned)*(++insptr) >= MAXSOUNDS))
1649
            {
1649
            {
1650
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1650
                CON_ERRPRINTF("Invalid sound %d\n", (int32_t)*insptr);
1651
                insptr++;
1651
                insptr++;
1652
                continue;
1652
                continue;
1653
            }
1653
            }
1654
            A_PlaySound(*insptr++,vm.g_i);
1654
            A_PlaySound(*insptr++,vm.g_i);
1655
            continue;
1655
            continue;
1656
1656
1657
        case CON_TIP:
1657
        case CON_TIP:
1658
            insptr++;
1658
            insptr++;
1659
            ps->tipincs = GAMETICSPERSEC;
1659
            ps->tipincs = GAMETICSPERSEC;
1660
            continue;
1660
            continue;
1661
1661
1662
        case CON_FALL:
1662
        case CON_FALL:
1663
            insptr++;
1663
            insptr++;
1664
            VM_Fall(vm.g_i, vm.g_sp);
1664
            VM_Fall(vm.g_i, vm.g_sp);
1665
            continue;
1665
            continue;
1666
1666
1667
        case CON_RETURN:
1667
        case CON_RETURN:
1668
            vm.g_flags |= VM_RETURN;
1668
            vm.g_flags |= VM_RETURN;
1669
        case CON_ENDA:
1669
        case CON_ENDA:
1670
        case CON_BREAK:
1670
        case CON_BREAK:
1671
        case CON_ENDS:
1671
        case CON_ENDS:
1672
            return;
1672
            return;
1673
        case CON_NULLOP:
1673
        case CON_NULLOP:
1674
            insptr++;
1674
            insptr++;
1675
            continue;
1675
            continue;
1676
1676
1677
        case CON_ADDAMMO:
1677
        case CON_ADDAMMO:
1678
            insptr++;
1678
            insptr++;
1679
            {
1679
            {
1680
                int32_t weap=*insptr++, amount=*insptr++;
1680
                int32_t weap=*insptr++, amount=*insptr++;
1681
1681
1682
                if (EDUKE32_PREDICT_FALSE((unsigned)weap >= MAX_WEAPONS))
1682
                if (EDUKE32_PREDICT_FALSE((unsigned)weap >= MAX_WEAPONS))
1683
                {
1683
                {
1684
                    CON_ERRPRINTF("Invalid weapon ID %d\n", weap);
1684
                    CON_ERRPRINTF("Invalid weapon ID %d\n", weap);
1685
                    break;
1685
                    break;
1686
                }
1686
                }
1687
1687
1688
                if (ps->ammo_amount[weap] >= ps->max_ammo_amount[weap])
1688
                if (ps->ammo_amount[weap] >= ps->max_ammo_amount[weap])
1689
                {
1689
                {
1690
                    vm.g_flags |= VM_NOEXECUTE;
1690
                    vm.g_flags |= VM_NOEXECUTE;
1691
                    return;
1691
                    return;
1692
                }
1692
                }
1693
1693
1694
                P_AddWeaponAmmoCommon(ps, weap, amount);
1694
                P_AddWeaponAmmoCommon(ps, weap, amount);
1695
1695
1696
                continue;
1696
                continue;
1697
            }
1697
            }
1698
1698
1699
        case CON_MONEY:
1699
        case CON_MONEY:
1700
            insptr++;
1700
            insptr++;
1701
            A_SpawnMultiple(vm.g_i, MONEY, *insptr++);
1701
            A_SpawnMultiple(vm.g_i, MONEY, *insptr++);
1702
            continue;
1702
            continue;
1703
1703
1704
        case CON_MAIL:
1704
        case CON_MAIL:
1705
            insptr++;
1705
            insptr++;
1706
            A_SpawnMultiple(vm.g_i, MAIL, *insptr++);
1706
            A_SpawnMultiple(vm.g_i, MAIL, *insptr++);
1707
            continue;
1707
            continue;
1708
1708
1709
        case CON_SLEEPTIME:
1709
        case CON_SLEEPTIME:
1710
            insptr++;
1710
            insptr++;
1711
            actor[vm.g_i].timetosleep = (int16_t)*insptr++;
1711
            actor[vm.g_i].timetosleep = (int16_t)*insptr++;
1712
            continue;
1712
            continue;
1713
1713
1714
        case CON_PAPER:
1714
        case CON_PAPER:
1715
            insptr++;
1715
            insptr++;
1716
            A_SpawnMultiple(vm.g_i, PAPER, *insptr++);
1716
            A_SpawnMultiple(vm.g_i, PAPER, *insptr++);
1717
            continue;
1717
            continue;
1718
1718
1719
        case CON_ADDKILLS:
1719
        case CON_ADDKILLS:
1720
            insptr++;
1720
            insptr++;
1721
            ps->actors_killed += *insptr++;
1721
            ps->actors_killed += *insptr++;
1722
            actor[vm.g_i].actorstayput = -1;
1722
            actor[vm.g_i].actorstayput = -1;
1723
            continue;
1723
            continue;
1724
1724
1725
        case CON_LOTSOFGLASS:
1725
        case CON_LOTSOFGLASS:
1726
            insptr++;
1726
            insptr++;
1727
            A_SpawnGlass(vm.g_i,*insptr++);
1727
            A_SpawnGlass(vm.g_i,*insptr++);
1728
            continue;
1728
            continue;
1729
1729
1730
        case CON_KILLIT:
1730
        case CON_KILLIT:
1731
            insptr++;
1731
            insptr++;
1732
            vm.g_flags |= VM_KILL;
1732
            vm.g_flags |= VM_KILL;
1733
            return;
1733
            return;
1734
1734
1735
        case CON_ADDWEAPON:
1735
        case CON_ADDWEAPON:
1736
            insptr++;
1736
            insptr++;
1737
            {
1737
            {
1738
                int32_t weap=*insptr++, amount=*insptr++;
1738
                int32_t weap=*insptr++, amount=*insptr++;
1739
                VM_AddWeapon(weap, amount, ps);
1739
                VM_AddWeapon(weap, amount, ps);
1740
1740
1741
                continue;
1741
                continue;
1742
            }
1742
            }
1743
1743
1744
        case CON_DEBUG:
1744
        case CON_DEBUG:
1745