Subversion Repositories eduke32

Rev

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

Rev Author Line No. Line
4555 hendricks2 1
// Ken Silverman's official web site: "http://www.advsys.net/ken"
2
// See the included license file "BUILDLIC.TXT" for license info.
3
//
4
// This file has been modified from Ken Silverman's original release
5
// by Jonathon Fowler (jf@jonof.id.au)
6
 
7
#include "compat.h"
8
#include "build.h"
9
#include "names.h"
10
#include "pragmas.h"
11
#include "cache1d.h"
12
#include "game.h"
13
#include "osd.h"
14
#include "mmulti.h"
15
#include "common.h"
16
 
17
#include "renderlayer.h"
18
 
19
#include "common_game.h"
20
 
5327 hendricks2 21
const char *AppProperName = "KenBuild";
22
const char *AppTechnicalName = "testgame";
4555 hendricks2 23
 
4562 hendricks2 24
#define SETUPFILENAME "testgame.cfg"
25
char setupfilename[BMAX_PATH] = SETUPFILENAME;
26
 
4555 hendricks2 27
#define TIMERINTSPERSECOND 140 //280
28
#define MOVESPERSECOND 40
29
#define TICSPERFRAME 3
30
#define MOVEFIFOSIZ 256
31
#define EYEHEIGHT (32<<8)   //Normally (32<<8), (51<<8) to make mirrors happy
32
 
33
#define TILE_TILT           (MAXTILES-2)
34
 
35
 
36
static int32_t setsprite_eyeheight(int16_t spritenum, const vec3_t *pos) ATTRIBUTE((nonnull(2)));
37
static int32_t setsprite_eyeheight(int16_t spritenum, const vec3_t *pos)
38
{
39
    vec3_t eyepos = *pos;
40
    eyepos.z += EYEHEIGHT;
41
    return setsprite(spritenum, &eyepos);
42
}
43
 
44
 
45
// declared in sound.c
46
void initsb(char,char,int,char,char,char,char);
47
void uninitsb(void);
48
void setears(int,int,int,int);
5551 hendricks2 49
void wsayfollow(char const *,int,int,int *,int *,char);
50
void wsay(char const *,int,int,int);
4555 hendricks2 51
void loadwaves(void);
5551 hendricks2 52
void loadsong(char const *);
4555 hendricks2 53
void musicon(void);
54
void musicoff(void);
55
void refreshaudio(void);
56
 
57
// declared in config.c
58
int loadsetup(const char *);
59
int writesetup(const char *);
60
 
61
/***************************************************************************
5327 hendricks2 62
    KEN'S TAG DEFINITIONS:      (Please define your own tags for your games)
4555 hendricks2 63
 
64
 sector[?].lotag = 0   Normal sector
65
 sector[?].lotag = 1   If you are on a sector with this tag, then all sectors
5327 hendricks2 66
                       with same hi tag as this are operated.  Once.
4555 hendricks2 67
 sector[?].lotag = 2   Same as sector[?].tag = 1 but this is retriggable.
68
 sector[?].lotag = 3   A really stupid sector that really does nothing now.
69
 sector[?].lotag = 4   A sector where you are put closer to the floor
5327 hendricks2 70
                       (such as the slime in DOOM1.DAT)
4555 hendricks2 71
 sector[?].lotag = 5   A really stupid sector that really does nothing now.
72
 sector[?].lotag = 6   A normal door - instead of pressing D, you tag the
5327 hendricks2 73
                       sector with a 6.  The reason I make you edit doors
74
                       this way is so that can program the doors
75
                       yourself.
4555 hendricks2 76
 sector[?].lotag = 7   A door the goes down to open.
77
 sector[?].lotag = 8   A door that opens horizontally in the middle.
78
 sector[?].lotag = 9   A sliding door that opens vertically in the middle.
5327 hendricks2 79
                       -Example of the advantages of not using BSP tree.
4555 hendricks2 80
 sector[?].lotag = 10  A warping sector with floor and walls that shade.
81
 sector[?].lotag = 11  A sector with all walls that do X-panning.
82
 sector[?].lotag = 12  A sector with walls using the dragging function.
83
 sector[?].lotag = 13  A sector with some swinging doors in it.
84
 sector[?].lotag = 14  A revolving door sector.
85
 sector[?].lotag = 15  A subway track.
86
 sector[?].lotag = 16  A true double-sliding door.
87
 
5327 hendricks2 88
    wall[?].lotag = 0   Normal wall
89
    wall[?].lotag = 1   Y-panning wall
90
    wall[?].lotag = 2   Switch - If you flip it, then all sectors with same hi
91
                        tag as this are operated.
92
    wall[?].lotag = 3   Marked wall to detemine starting dir. (sector tag 12)
93
    wall[?].lotag = 4   Mark on the shorter wall closest to the pivot point
94
                        of a swinging door. (sector tag 13)
95
    wall[?].lotag = 5   Mark where a subway should stop. (sector tag 15)
96
    wall[?].lotag = 6   Mark for true double-sliding doors (sector tag 16)
97
    wall[?].lotag = 7   Water fountain
98
    wall[?].lotag = 8   Bouncy wall!
4555 hendricks2 99
 
100
 sprite[?].lotag = 0   Normal sprite
101
 sprite[?].lotag = 1   If you press space bar on an AL, and the AL is tagged
5327 hendricks2 102
                       with a 1, he will turn evil.
4555 hendricks2 103
 sprite[?].lotag = 2   When this sprite is operated, a bomb is shot at its
5327 hendricks2 104
                       position.
4555 hendricks2 105
 sprite[?].lotag = 3   Rotating sprite.
106
 sprite[?].lotag = 4   Sprite switch.
107
 sprite[?].lotag = 5   Basketball hoop score.
108
 
5327 hendricks2 109
    KEN'S STATUS DEFINITIONS:  (Please define your own statuses for your games)
4555 hendricks2 110
 status = 0            Inactive sprite
111
 status = 1            Active monster sprite
112
 status = 2            Monster that becomes active only when it sees you
113
 status = 3            Smoke on the wall for chainguns
114
 status = 4            Splashing sprites (When you shoot slime)
115
 status = 5            Explosion!
116
 status = 6            Travelling bullet
117
 status = 7            Bomb sprial-out explosion
118
 status = 8            Player!
119
 status = 9            EVILALGRAVE shrinking list
120
 status = 10           EVILAL list
121
 status = 11           Sprite respawning list
122
 status = 12           Sprite which does not respawn (Andy's addition)
123
 status = MAXSTATUS    Non-existent sprite (this will be true for your
5327 hendricks2 124
                       code also)
4555 hendricks2 125
**************************************************************************/
126
 
127
typedef struct
128
{
5327 hendricks2 129
    signed char fvel, svel, avel;
130
    short bits;
4555 hendricks2 131
} input;
132
 
133
static int screentilt = 0, oscreentilt = 0;
134
 
135
 
136
static int fvel, svel, avel;
137
static int fvel2, svel2, avel2;
138
 
139
#define NUMOPTIONS 8
140
#define NUMGAMEKEYS 19
141
char option[NUMOPTIONS] = {0,0,0,0,0,0,1,0};
142
unsigned char keys[NUMGAMEKEYS] =
143
{
5327 hendricks2 144
    0xc8,0xd0,0xcb,0xcd,0x2a,0x9d,0x1d,0x39,
145
    0x1e,0x2c,0xd1,0xc9,0x33,0x34,
146
    0x9c,0x1c,0xd,0xc,0xf
4555 hendricks2 147
};
5327 hendricks2 148
int xdimgame = 320, ydimgame = 200, bppgame = 8, xdim2d = 640, ydim2d = 480;    // JBF 20050318: config.c expects to find these
4555 hendricks2 149
int forcesetup = 1;
150
 
151
static int digihz[8] = {6000,8000,11025,16000,22050,32000,44100,48000};
152
 
153
static char frame2draw[MAXPLAYERS];
154
static int frameskipcnt[MAXPLAYERS];
155
 
156
#define LAVASIZ 128
157
#define LAVALOGSIZ 7
158
#define LAVAMAXDROPS 32
159
static char lavabakpic[(LAVASIZ+4)*(LAVASIZ+4)], lavainc[LAVASIZ];
160
static int lavanumdrops, lavanumframes;
161
static int lavadropx[LAVAMAXDROPS], lavadropy[LAVAMAXDROPS];
162
static int lavadropsiz[LAVAMAXDROPS], lavadropsizlookup[LAVAMAXDROPS];
163
static int lavaradx[24][96], lavarady[24][96], lavaradcnt[32];
164
 
5327 hendricks2 165
//Shared player variables
4555 hendricks2 166
static vec3_t pos[MAXPLAYERS];
167
static int horiz[MAXPLAYERS], zoom[MAXPLAYERS], hvel[MAXPLAYERS];
168
static short ang[MAXPLAYERS], cursectnum[MAXPLAYERS], ocursectnum[MAXPLAYERS];
169
static short playersprite[MAXPLAYERS], deaths[MAXPLAYERS];
170
static int lastchaingun[MAXPLAYERS];
171
static int health[MAXPLAYERS], flytime[MAXPLAYERS];
172
static short oflags[MAXPLAYERS];
173
static short numbombs[MAXPLAYERS];
174
static short numgrabbers[MAXPLAYERS];   // Andy did this
175
static short nummissiles[MAXPLAYERS];   // Andy did this
176
static char dimensionmode[MAXPLAYERS];
177
static char revolvedoorstat[MAXPLAYERS];
178
static short revolvedoorang[MAXPLAYERS], revolvedoorrotang[MAXPLAYERS];
179
static int revolvedoorx[MAXPLAYERS], revolvedoory[MAXPLAYERS];
180
 
181
static int nummoves;
182
// Bug: NUMSTATS used to be equal to the greatest tag number,
183
// so that the last statrate[] entry was random memory junk
184
// because stats 0-NUMSTATS required NUMSTATS+1 bytes.   -Andy
185
#define NUMSTATS 13
186
static signed char statrate[NUMSTATS] = {-1,0,-1,0,0,0,1,3,0,3,15,-1,-1};
187
 
5327 hendricks2 188
//Input structures
4555 hendricks2 189
static char networkmode;     //0 is 2(n-1) mode, 1 is n(n-1) mode
190
static int locselectedgun, locselectedgun2;
191
static input loc, oloc, loc2;
192
static input ffsync[MAXPLAYERS], osync[MAXPLAYERS], ssync[MAXPLAYERS];
5327 hendricks2 193
//Input faketimerhandler -> movethings fifo
4555 hendricks2 194
static int movefifoplc, movefifoend[MAXPLAYERS];
195
static input baksync[MOVEFIFOSIZ][MAXPLAYERS];
5327 hendricks2 196
//Game recording variables
4555 hendricks2 197
static int reccnt, recstat = 1;
198
static input recsync[16384][2];
199
 
200
//static int myminlag[MAXPLAYERS], mymaxlag, otherminlag, bufferjitter = 1;
201
static signed char otherlag[MAXPLAYERS] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
202
static int averagelag[MAXPLAYERS] = {512,512,512,512,512,512,512,512,512,512,512,512,512,512,512,512};
203
 
204
static int fakemovefifoplc;
205
static vec3_t my, omy;
206
static int myzvel;
207
static int myhoriz, omyhoriz;
208
static short myang, omyang, mycursectnum;
209
static vec3_t mybak[MOVEFIFOSIZ];
210
static int myhorizbak[MOVEFIFOSIZ];
211
static short myangbak[MOVEFIFOSIZ];
212
 
5327 hendricks2 213
//GAME.C sync state variables
4555 hendricks2 214
static char syncstat, syncval[MOVEFIFOSIZ], othersyncval[MOVEFIFOSIZ];
215
static int syncvaltottail, syncvalhead, othersyncvalhead, syncvaltail;
216
 
217
static char detailmode = 0, ready2send = 0;
218
static int ototalclock = 0, gotlastpacketclock = 0, smoothratio;
219
static vec3_t opos[MAXPLAYERS];
220
static int ohoriz[MAXPLAYERS], ozoom[MAXPLAYERS];
221
static short oang[MAXPLAYERS];
222
 
223
static vec3_t osprite[MAXSPRITES];
224
 
225
#define MAXINTERPOLATIONS 1024
226
static int numinterpolations = 0, startofdynamicinterpolations = 0;
227
static int oldipos[MAXINTERPOLATIONS];
228
static int bakipos[MAXINTERPOLATIONS];
229
static int *curipos[MAXINTERPOLATIONS];
230
 
231
// extern int cachecount;
232
 
233
static char playerreadyflag[MAXPLAYERS];
234
 
5327 hendricks2 235
//Miscellaneous variables
4555 hendricks2 236
static unsigned char packbuf[MAXXDIM];
237
static char tempbuf[MAXXDIM];
238
static char boardfilename[BMAX_PATH];
239
static short tempshort[MAXSECTORS];
240
static short screenpeek = 0, oldmousebstatus = 0;
241
short brightness = 0;
242
static short screensize, screensizeflag = 0;
243
static short neartagsector, neartagwall, neartagsprite;
244
static int lockclock, neartagdist, neartaghitdist;
245
extern int pageoffset, ydim16;
246
static int globhiz, globloz, globhihit, globlohit;
247
 
5327 hendricks2 248
//Over the shoulder mode variables
4555 hendricks2 249
static int cameradist = -1, cameraang = 0, cameraclock = 0;
250
 
5327 hendricks2 251
//Board animation variables
4555 hendricks2 252
#define MAXMIRRORS 64
253
static short mirrorwall[MAXMIRRORS], mirrorsector[MAXMIRRORS], mirrorcnt;
254
static short floormirrorsector[64], floormirrorcnt;
255
static short turnspritelist[16], turnspritecnt;
256
static short warpsectorlist[64], warpsectorcnt;
257
static short xpanningsectorlist[16], xpanningsectorcnt;
258
static short ypanningwalllist[64], ypanningwallcnt;
259
static short floorpanninglist[64], floorpanningcnt;
260
static short dragsectorlist[16], dragxdir[16], dragydir[16], dragsectorcnt;
261
static int dragx1[16], dragy1[16], dragx2[16], dragy2[16], dragfloorz[16];
262
static short swingcnt, swingwall[32][5], swingsector[32];
263
static short swingangopen[32], swingangclosed[32], swingangopendir[32];
264
static short swingang[32], swinganginc[32];
265
static int swingx[32][8], swingy[32][8];
266
static short revolvesector[4], revolveang[4], revolvecnt;
267
static int revolvex[4][16], revolvey[4][16];
268
static int revolvepivotx[4], revolvepivoty[4];
269
static short subwaytracksector[4][128], subwaynumsectors[4], subwaytrackcnt;
270
static int subwaystop[4][8], subwaystopcnt[4];
271
static int subwaytrackx1[4], subwaytracky1[4];
272
static int subwaytrackx2[4], subwaytracky2[4];
273
static int subwayx[4], subwaygoalstop[4], subwayvel[4], subwaypausetime[4];
274
static short waterfountainwall[MAXPLAYERS], waterfountaincnt[MAXPLAYERS];
275
static short slimesoundcnt[MAXPLAYERS];
276
 
5327 hendricks2 277
//Variables that let you type messages to other player
4555 hendricks2 278
static char getmessage[162], getmessageleng;
279
static int getmessagetimeoff;
280
static char typemessage[162], typemessageleng = 0, typemode = 0;
281
#if 0
282
static char scantoasc[128] =
283
{
5327 hendricks2 284
    0,0,'1','2','3','4','5','6','7','8','9','0','-','=',0,0,
285
    'q','w','e','r','t','y','u','i','o','p','[',']',0,0,'a','s',
286
    'd','f','g','h','j','k','l',';',39,'`',0,92,'z','x','c','v',
287
    'b','n','m',',','.','/',0,'*',0,32,0,0,0,0,0,0,
288
    0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1',
289
    '2','3','0','.',0,0,0,0,0,0,0,0,0,0,0,0,
290
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
291
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4555 hendricks2 292
};
293
static char scantoascwithshift[128] =
294
{
5327 hendricks2 295
    0,0,'!','@','#','$','%','^','&','*','(',')','_','+',0,0,
296
    'Q','W','E','R','T','Y','U','I','O','P','{','}',0,0,'A','S',
297
    'D','F','G','H','J','K','L',':',34,'~',0,'|','Z','X','C','V',
298
    'B','N','M','<','>','?',0,'*',0,32,0,0,0,0,0,0,
299
    0,0,0,0,0,0,0,'7','8','9','-','4','5','6','+','1',
300
    '2','3','0','.',0,0,0,0,0,0,0,0,0,0,0,0,
301
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
302
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
4555 hendricks2 303
};
304
#endif
305
 
5327 hendricks2 306
//These variables are for animating x, y, or z-coordinates of sectors,
307
//walls, or sprites (They are NOT to be used for changing the [].picnum's)
308
//See the setanimation(), and getanimategoal() functions for more details.
4555 hendricks2 309
#define MAXANIMATES 512
310
static int *animateptr[MAXANIMATES], animategoal[MAXANIMATES];
311
static int animatevel[MAXANIMATES], animateacc[MAXANIMATES], animatecnt = 0;
312
 
313
#if defined USE_OPENGL
5327 hendricks2 314
//These parameters are in exact order of sprite structure in BUILD.H
4555 hendricks2 315
#define spawnsprite(newspriteindex2,x2,y2,z2,cstat2,shade2,pal2,        \
5327 hendricks2 316
                    clipdist2,xrepeat2,yrepeat2,xoffset2,yoffset2,picnum2,ang2,     \
317
                    xvel2,yvel2,zvel2,owner2,sectnum2,statnum2,lotag2,hitag2,extra2) \
318
    {                                                                       \
319
        spritetype *spr2;                                                   \
320
        newspriteindex2 = insertsprite(sectnum2,statnum2);                  \
321
        spr2 = &sprite[newspriteindex2];                                    \
322
        spr2->x = x2; spr2->y = y2; spr2->z = z2;                           \
323
        spr2->cstat = cstat2; spr2->shade = shade2;                         \
324
        spr2->pal = pal2; spr2->clipdist = clipdist2;                       \
325
        spr2->xrepeat = xrepeat2; spr2->yrepeat = yrepeat2;                 \
326
        spr2->xoffset = xoffset2; spr2->yoffset = yoffset2;                 \
327
        spr2->picnum = picnum2; spr2->ang = ang2;                           \
328
        spr2->xvel = xvel2; spr2->yvel = yvel2; spr2->zvel = zvel2;         \
329
        spr2->owner = owner2;                                               \
330
        spr2->lotag = lotag2; spr2->hitag = hitag2; spr2->extra = extra2;   \
331
        copybuf(&spr2->x,&osprite[newspriteindex2].x,3);                    \
332
        show2dsprite[newspriteindex2>>3] &= ~(1<<(newspriteindex2&7));      \
333
        if (show2dsector[sectnum2>>3]&(1<<(sectnum2&7)))                    \
334
            show2dsprite[newspriteindex2>>3] |= (1<<(newspriteindex2&7));   \
335
        clearbufbyte(&spriteext[newspriteindex2], sizeof(spriteext_t), 0);  \
336
    }
4555 hendricks2 337
#else
338
#define spawnsprite(newspriteindex2,x2,y2,z2,cstat2,shade2,pal2,        \
5327 hendricks2 339
                    clipdist2,xrepeat2,yrepeat2,xoffset2,yoffset2,picnum2,ang2,     \
340
                    xvel2,yvel2,zvel2,owner2,sectnum2,statnum2,lotag2,hitag2,extra2) \
341
    {                                                                       \
342
        spritetype *spr2;                                                   \
343
        newspriteindex2 = insertsprite(sectnum2,statnum2);                  \
344
        spr2 = &sprite[newspriteindex2];                                    \
345
        spr2->x = x2; spr2->y = y2; spr2->z = z2;                           \
346
        spr2->cstat = cstat2; spr2->shade = shade2;                         \
347
        spr2->pal = pal2; spr2->clipdist = clipdist2;                       \
348
        spr2->xrepeat = xrepeat2; spr2->yrepeat = yrepeat2;                 \
349
        spr2->xoffset = xoffset2; spr2->yoffset = yoffset2;                 \
350
        spr2->picnum = picnum2; spr2->ang = ang2;                           \
351
        spr2->xvel = xvel2; spr2->yvel = yvel2; spr2->zvel = zvel2;         \
352
        spr2->owner = owner2;                                               \
353
        spr2->lotag = lotag2; spr2->hitag = hitag2; spr2->extra = extra2;   \
354
        copybuf(&spr2->x,&osprite[newspriteindex2].x,3);                    \
355
        show2dsprite[newspriteindex2>>3] &= ~(1<<(newspriteindex2&7));      \
356
        if (show2dsector[sectnum2>>3]&(1<<(sectnum2&7)))                    \
357
            show2dsprite[newspriteindex2>>3] |= (1<<(newspriteindex2&7));   \
358
    }
4555 hendricks2 359
#endif
360
 
361
int nextvoxid = 0;
362
 
363
int osdcmd_restartvid(const osdfuncparm_t *parm)
364
{
365
    UNREFERENCED_PARAMETER(parm);
366
 
5327 hendricks2 367
    resetvideomode();
368
    if (setgamemode(fullscreen,xdim,ydim,bpp))
369
        buildputs("restartvid: Reset failed...\n");
4555 hendricks2 370
 
5327 hendricks2 371
    return OSDCMD_OK;
4555 hendricks2 372
}
373
 
374
static int osdcmd_vidmode(const osdfuncparm_t *parm)
375
{
5327 hendricks2 376
    int newx = xdim, newy = ydim, newbpp = bpp, newfullscreen = fullscreen;
4555 hendricks2 377
 
5327 hendricks2 378
    if (parm->numparms < 1 || parm->numparms > 4) return OSDCMD_SHOWHELP;
4555 hendricks2 379
 
5327 hendricks2 380
    switch (parm->numparms)
381
    {
382
    case 1:   // bpp switch
383
        newbpp = Batol(parm->parms[0]);
384
        break;
385
    case 2: // res switch
386
        newx = Batol(parm->parms[0]);
387
        newy = Batol(parm->parms[1]);
388
        break;
389
    case 3:   // res & bpp switch
390
    case 4:
391
        newx = Batol(parm->parms[0]);
392
        newy = Batol(parm->parms[1]);
393
        newbpp = Batol(parm->parms[2]);
394
        if (parm->numparms == 4)
395
            newfullscreen = (Batol(parm->parms[3]) != 0);
396
        break;
397
    }
4555 hendricks2 398
 
5327 hendricks2 399
    if (setgamemode(newfullscreen,newx,newy,newbpp))
400
        buildputs("vidmode: Mode change failed!\n");
401
    screensize = xdim+1;
402
    return OSDCMD_OK;
4555 hendricks2 403
}
404
 
5327 hendricks2 405
static int osdcmd_map(const osdfuncparm_t *parm)
406
{
407
    int i;
408
    char *dot, namebuf[BMAX_PATH+1];
4555 hendricks2 409
 
5327 hendricks2 410
    if (parm->numparms != 1) return OSDCMD_SHOWHELP;
4555 hendricks2 411
 
5327 hendricks2 412
    strncpy(namebuf, parm->parms[0], BMAX_PATH);
413
    namebuf[BMAX_PATH] = 0;
414
    dot = strrchr(namebuf, '.');
415
    if ((!dot || Bstrcasecmp(dot, ".map")) && strlen(namebuf) <= BMAX_PATH-4)
416
    {
417
        strcat(namebuf, ".map");
418
    }
4555 hendricks2 419
 
5327 hendricks2 420
    prepareboard(namebuf);
4555 hendricks2 421
 
5327 hendricks2 422
    screenpeek = myconnectindex;
423
    reccnt = 0;
424
    for (i=connecthead; i>=0; i=connectpoint2[i]) initplayersprite((short)i);
4555 hendricks2 425
 
5327 hendricks2 426
    waitforeverybody();
427
    totalclock = ototalclock = 0; gotlastpacketclock = 0; nummoves = 0;
4555 hendricks2 428
 
5327 hendricks2 429
    ready2send = 1;
430
    drawscreen(screenpeek,65536L);
4555 hendricks2 431
 
5327 hendricks2 432
    return OSDCMD_OK;
4555 hendricks2 433
}
434
 
5345 hendricks2 435
static void Ken_UninitAll(void)
436
{
437
    sendlogoff();         //Signing off
438
    musicoff();
439
    uninitmultiplayers();
440
    uninittimer();
441
    uninitinput();
442
    uninitengine();
443
    uninitsb();
444
    uninitgroupfile();
445
}
446
 
447
static void Ken_FatalEngineError(void)
448
{
449
    buildprintf("There was a problem initialising the engine: %s.\n", engineerrstr);
450
}
451
 
5552 hendricks2 452
int32_t app_main(int32_t argc, char const * const * argv)
4555 hendricks2 453
{
454
#if defined STARTUP_SETUP_WINDOW
5327 hendricks2 455
    int cmdsetup = 0;
4555 hendricks2 456
#endif
457
    int i, j, k /*, l, fil, waitplayers, x1, y1, x2, y2*/;
5327 hendricks2 458
    int /*other, packleng,*/ netparm;
4555 hendricks2 459
 
4558 hendricks2 460
    OSD_SetFunctions(
461
        NULL, NULL, NULL, NULL, NULL,
462
        COMMON_clearbackground,
463
        BGetTime,
464
        NULL
5327 hendricks2 465
        );
4555 hendricks2 466
 
4558 hendricks2 467
    OSD_SetParameters(0,2, 0,0, 4,0);
468
 
5327 hendricks2 469
    OSD_SetLogFile("testgame.log");
4558 hendricks2 470
    initprintf("%s %s %s\n", AppProperName, s_buildRev, s_buildInfo);
4555 hendricks2 471
    initprintf("Compiled %s\n", s_buildTimestamp);
472
 
473
#ifdef USE_OPENGL
5327 hendricks2 474
    OSD_RegisterFunction("restartvid","restartvid: reinitialise the video mode",osdcmd_restartvid);
475
    OSD_RegisterFunction("vidmode","vidmode [xdim ydim] [bpp] [fullscreen]: immediately change the video mode",osdcmd_vidmode);
476
    OSD_RegisterFunction("map", "map [filename]: load a map", osdcmd_map);
4555 hendricks2 477
#endif
478
 
5327 hendricks2 479
    wm_setapptitle(AppProperName);
4555 hendricks2 480
 
5327 hendricks2 481
    Bstrcpy(boardfilename, "nukeland.map");
482
    j = 0; netparm = argc;
483
    for (i=1; i<argc; i++)
484
    {
485
        if ((!Bstrcasecmp("-net",argv[i])) || (!Bstrcasecmp("/net",argv[i]))) { j = 1; netparm = i; continue; }
486
        if (j)
487
        {
488
            if (argv[i][0] == '-' || argv[i][0] == '/')
4555 hendricks2 489
            {
5327 hendricks2 490
                if (((argv[i][1] == 'n') || (argv[i][1] == 'N')) && (argv[i][2] == '0')) { networkmode = 0; continue; }
491
                if (((argv[i][1] == 'n') || (argv[i][1] == 'N')) && (argv[i][2] == '1')) { networkmode = 1; continue; }
492
            }
493
            if (isvalidipaddress(argv[i])) continue;
494
        }
495
        else
496
        {
497
            if (!Bstrcasecmp(argv[i], "-setup"))
498
            {
4555 hendricks2 499
#if defined STARTUP_SETUP_WINDOW
500
                cmdsetup = 1;
501
#endif
502
            }
5327 hendricks2 503
            else
504
            {
505
                Bstrcpy(boardfilename, argv[i]);
506
                if (!Bstrrchr(boardfilename,'.')) Bstrcat(boardfilename,".map");
507
            }
508
        }
509
    }
4555 hendricks2 510
 
5327 hendricks2 511
    if ((i = loadsetup(setupfilename)) < 0)
512
        buildputs("Configuration file not found, using defaults.\n");
4562 hendricks2 513
 
514
#if defined STARTUP_SETUP_WINDOW
5327 hendricks2 515
    if (i || forcesetup || cmdsetup)
516
    {
517
        if (quitevent || !startwin_run()) return -1;
518
    }
4562 hendricks2 519
#endif
5327 hendricks2 520
    writesetup(setupfilename);
4562 hendricks2 521
 
5327 hendricks2 522
    initgroupfile(G_GrpFile());
523
    if (initengine())
524
    {
5345 hendricks2 525
        Ken_FatalEngineError();
5327 hendricks2 526
        return -1;
527
    }
4555 hendricks2 528
 
4558 hendricks2 529
    Ken_InitMultiPsky();
4555 hendricks2 530
 
5327 hendricks2 531
    initinput();
532
    if (option[3] != 0) initmouse();
533
    inittimer(TIMERINTSPERSECOND);
4555 hendricks2 534
 
5327 hendricks2 535
    //initmultiplayers(argc-netparm,&argv[netparm],option[4],option[5],0);
536
    if (initmultiplayersparms(argc-netparm,&argv[netparm]))
537
    {
538
        buildputs("Waiting for players...\n");
539
        while (initmultiplayerscycle())
540
        {
541
            handleevents();
542
            if (quitevent)
543
            {
5345 hendricks2 544
                Ken_UninitAll();
5327 hendricks2 545
                return 0;
546
            }
547
        }
548
    }
549
    option[4] = (numplayers >= 2);
4555 hendricks2 550
 
5327 hendricks2 551
    loadpics("tiles000.art",1048576);                      //Load artwork
552
    if (!qloadkvx(nextvoxid,"voxel000.kvx"))
553
        tiletovox[PLAYER] = nextvoxid++;
554
    if (!qloadkvx(nextvoxid,"voxel001.kvx"))
555
        tiletovox[BROWNMONSTER] = nextvoxid++;
556
    if (!loaddefinitionsfile(G_DefFile())) buildputs("Definitions file loaded.\n");
4555 hendricks2 557
 
5345 hendricks2 558
    if (E_PostInit())
559
    {
560
        Ken_UninitAll();
561
        Ken_FatalEngineError();
562
        return -1;
563
    }
564
 
5327 hendricks2 565
    //Here's an example of TRUE ornamented walls
566
    //The allocatepermanenttile should be called right after loadpics
567
    //Since it resets the tile cache for each call.
568
    if (allocatepermanenttile(SLIME,128,128) == 0)    //If enough memory
569
    {
570
        buildputs("Not enough memory for slime!\n");
571
        exit(0);
572
    }
573
    if (allocatepermanenttile(MAXTILES-1,64,64) != 0)    //If enough memory
574
    {
575
        //My face with an explosion written over it
576
        copytilepiece(KENPICTURE,0,0,64,64,MAXTILES-1,0,0);
577
        copytilepiece(EXPLOSION,0,0,64,64,MAXTILES-1,0,0);
578
    }
4555 hendricks2 579
 
5327 hendricks2 580
    initlava();
4555 hendricks2 581
 
5327 hendricks2 582
    for (j=0; j<256; j++)
583
        tempbuf[j] = ((j+32)&255);  //remap colors for screwy palette sectors
584
    makepalookup(16,tempbuf,0,0,0,1);
4555 hendricks2 585
 
5327 hendricks2 586
    for (j=0; j<256; j++) tempbuf[j] = j;
5349 hendricks2 587
    makepalookup(17,tempbuf,96,96,96,1);
4555 hendricks2 588
 
5327 hendricks2 589
    for (j=0; j<256; j++) tempbuf[j] = j; //(j&31)+32;
5349 hendricks2 590
    makepalookup(18,tempbuf,32,32,192,1);
4555 hendricks2 591
 
5346 hendricks2 592
    fillemptylookups();
593
 
5327 hendricks2 594
    prepareboard(boardfilename);                   //Load board
4555 hendricks2 595
 
5327 hendricks2 596
    initsb(option[1],option[2],digihz[option[7]>>4],((option[7]&4)>0)+1,((option[7]&2)>0)+1,60,option[7]&1);
597
    //if (Bstrcmp(boardfilename,"klab.map") == 0)
598
    //   loadsong("klabsong.kdm");
599
    //else
600
    loadsong("neatsong.kdm");
601
    musicon();
4555 hendricks2 602
 
603
#if 0
5327 hendricks2 604
    if (option[4] > 0)
605
    {
606
        x1 = ((xdim-screensize)>>1);
607
        x2 = x1+screensize-1;
608
        y1 = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
609
        y2 = y1 + scale(screensize,ydim-32,xdim)-1;
4555 hendricks2 610
 
5327 hendricks2 611
        drawtilebackground(/*0L,0L,*/ BACKGROUND,8,x1,y1,x2,y2,0);
4555 hendricks2 612
 
5327 hendricks2 613
        sendlogon();
4555 hendricks2 614
 
5327 hendricks2 615
        if (option[4] < 5) waitplayers = 2; else waitplayers = option[4]-3;
616
        while (numplayers < waitplayers)
617
        {
618
            sprintf(tempbuf,"%ld of %ld players in...",numplayers,waitplayers);
619
            printext256(68L,84L,31,0,tempbuf,0);
620
            nextpage();
4555 hendricks2 621
 
5327 hendricks2 622
            if (getpacket(&other,packbuf) > 0)
623
                if (packbuf[0] == 255)
624
                    keystatus[1] = 1;
4555 hendricks2 625
 
5327 hendricks2 626
            if (handleevents())
627
            {
628
                if (quitevent)
629
                {
630
                    keystatus[1] = 1;
631
                    quitevent = 0;
632
                }
633
            }
4555 hendricks2 634
 
5327 hendricks2 635
            if (keystatus[1])
636
            {
5345 hendricks2 637
                Ken_UninitAll();
638
                return 0;
5327 hendricks2 639
            }
640
        }
641
        screenpeek = myconnectindex;
4555 hendricks2 642
 
5327 hendricks2 643
        if (numplayers <= 3)
644
            networkmode = 1;
645
        else
646
            networkmode = 0;
4555 hendricks2 647
 
5327 hendricks2 648
        j = 1;
649
        for (i=connecthead; i>=0; i=connectpoint2[i])
650
        {
651
            if (myconnectindex == i) break;
652
            j++;
653
        }
654
        sprintf(getmessage,"Player %ld",j);
655
        if (networkmode == 0)
656
        {
657
            if (j == 1) Bstrcat(getmessage," (Master)");
658
            else Bstrcat(getmessage," (Slave)");
659
        }
660
        else
661
            Bstrcat(getmessage," (Even)");
662
        getmessageleng = Bstrlen(getmessage);
663
        getmessagetimeoff = totalclock+120;
664
    }
4555 hendricks2 665
#endif
5327 hendricks2 666
    screenpeek = myconnectindex;
667
    reccnt = 0;
668
    for (i=connecthead; i>=0; i=connectpoint2[i]) initplayersprite((short)i);
4555 hendricks2 669
 
5327 hendricks2 670
    waitforeverybody();
671
    totalclock = ototalclock = 0; gotlastpacketclock = 0; nummoves = 0;
4555 hendricks2 672
 
5327 hendricks2 673
    ready2send = 1;
674
    drawscreen(screenpeek,65536L);
4555 hendricks2 675
 
5327 hendricks2 676
    while (!keystatus[1])       //Main loop starts here
677
    {
678
        if (handleevents())
679
        {
680
            if (quitevent)
681
            {
682
                keystatus[1] = 1;
683
                quitevent = 0;
684
            }
685
        }
4555 hendricks2 686
 
5327 hendricks2 687
        refreshaudio();
688
        OSD_DispatchQueued();
4555 hendricks2 689
 
5327 hendricks2 690
        // backslash (useful only with KDM)
4555 hendricks2 691
//      if (keystatus[0x2b]) { keystatus[0x2b] = 0; preparesndbuf(); }
692
 
5327 hendricks2 693
        if ((networkmode == 1) || (myconnectindex != connecthead))
694
            while (fakemovefifoplc != movefifoend[myconnectindex]) fakedomovethings();
4555 hendricks2 695
 
5327 hendricks2 696
        getpackets();
4555 hendricks2 697
 
5327 hendricks2 698
        if (typemode == 0)           //if normal game keys active
699
        {
700
            if ((keystatus[0x2a]&keystatus[0x36]&keystatus[0x13]) > 0)   //Sh.Sh.R (replay)
701
            {
702
                keystatus[0x13] = 0;
703
                playback();
704
            }
4555 hendricks2 705
 
5327 hendricks2 706
            if (keystatus[0x26]&(keystatus[0x1d]|keystatus[0x9d])) //Load game
707
            {
708
                keystatus[0x26] = 0;
709
                loadgame();
710
                drawstatusbar(screenpeek);   // Andy did this
711
            }
4555 hendricks2 712
 
5327 hendricks2 713
            if (keystatus[0x1f]&(keystatus[0x1d]|keystatus[0x9d])) //Save game
714
            {
715
                keystatus[0x1f] = 0;
716
                savegame();
717
            }
718
        }
4555 hendricks2 719
 
5327 hendricks2 720
        if ((networkmode == 0) || (option[4] == 0))
721
        {
722
            while (movefifoplc != movefifoend[0]) domovethings();
723
        }
724
        else
725
        {
726
            j = connecthead;
727
            if (j == myconnectindex) j = connectpoint2[j];
728
            averagelag[j] = ((averagelag[j]*7+(((movefifoend[myconnectindex]-movefifoend[j]+otherlag[j]+2)&255)<<8))>>3);
729
            j = max(averagelag[j]>>9,1);
730
            while (((movefifoend[myconnectindex]-movefifoplc)&(MOVEFIFOSIZ-1)) > j)
731
            {
732
                for (i=connecthead; i>=0; i=connectpoint2[i])
733
                    if (movefifoplc == movefifoend[i]) break;
734
                if (i >= 0) break;
735
                if (myconnectindex != connecthead)
736
                {
737
                    k = ((movefifoend[myconnectindex]-movefifoend[connecthead]-otherlag[connecthead]+128)&255);
738
                    if (k > 128+1) ototalclock++;
739
                    if (k < 128-1) ototalclock--;
740
                }
741
                domovethings();
742
            }
743
        }
744
        i = (totalclock-gotlastpacketclock)*(65536/(TIMERINTSPERSECOND/MOVESPERSECOND));
4555 hendricks2 745
 
5327 hendricks2 746
        drawscreen(screenpeek,i);
747
    }
4555 hendricks2 748
 
5345 hendricks2 749
    Ken_UninitAll();
4555 hendricks2 750
 
5327 hendricks2 751
    return 0;
4555 hendricks2 752
}
753
 
754
void operatesector(short dasector)
5327 hendricks2 755
{
756
    //Door code
757
    int i, j, /*k, s, nexti, good, cnt,*/ datag;
758
    int /*dax, day,*/ daz, dax2, day2, /*daz2,*/ centx, centy;
759
    short startwall, endwall, wallfind[2];
4555 hendricks2 760
 
5327 hendricks2 761
    datag = sector[dasector].lotag;
4555 hendricks2 762
 
5327 hendricks2 763
    startwall = sector[dasector].wallptr;
764
    endwall = startwall + sector[dasector].wallnum;
765
    centx = 0L, centy = 0L;
766
    for (i=startwall; i<endwall; i++)
767
    {
768
        centx += wall[i].x;
769
        centy += wall[i].y;
770
    }
771
    centx /= (endwall-startwall);
772
    centy /= (endwall-startwall);
4555 hendricks2 773
 
5327 hendricks2 774
    //Simple door that moves up  (tag 8 is a combination of tags 6 & 7)
775
    if ((datag == 6) || (datag == 8))    //If the sector in front is a door
776
    {
777
        i = getanimationgoal(&sector[dasector].ceilingz);
778
        if (i >= 0)      //If door already moving, reverse its direction
779
        {
780
            if (datag == 8)
781
                daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
782
            else
783
                daz = sector[dasector].floorz;
4555 hendricks2 784
 
5327 hendricks2 785
            if (animategoal[i] == daz)
786
                animategoal[i] = sector[nextsectorneighborz(dasector,sector[dasector].floorz,-1,-1)].ceilingz;
787
            else
788
                animategoal[i] = daz;
789
            animatevel[i] = 0;
790
        }
791
        else      //else insert the door's ceiling on the animation list
792
        {
793
            if (sector[dasector].ceilingz == sector[dasector].floorz)
794
                daz = sector[nextsectorneighborz(dasector,sector[dasector].floorz,-1,-1)].ceilingz;
795
            else
796
            {
797
                if (datag == 8)
798
                    daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
799
                else
800
                    daz = sector[dasector].floorz;
801
            }
802
            if ((j = setanimation(&sector[dasector].ceilingz,daz,6L,6L)) >= 0)
803
                wsayfollow("updowndr.wav",4096L+(krand()&255)-128,256L,&centx,&centy,0);
804
        }
805
    }
806
    //Simple door that moves down
807
    if ((datag == 7) || (datag == 8)) //If the sector in front's elevator
808
    {
809
        i = getanimationgoal(&sector[dasector].floorz);
810
        if (i >= 0)      //If elevator already moving, reverse its direction
811
        {
812
            if (datag == 8)
813
                daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
814
            else
815
                daz = sector[dasector].ceilingz;
4555 hendricks2 816
 
5327 hendricks2 817
            if (animategoal[i] == daz)
818
                animategoal[i] = sector[nextsectorneighborz(dasector,sector[dasector].ceilingz,1,1)].floorz;
819
            else
820
                animategoal[i] = daz;
821
            animatevel[i] = 0;
822
        }
823
        else      //else insert the elevator's ceiling on the animation list
824
        {
825
            if (sector[dasector].floorz == sector[dasector].ceilingz)
826
                daz = sector[nextsectorneighborz(dasector,sector[dasector].ceilingz,1,1)].floorz;
827
            else
828
            {
829
                if (datag == 8)
830
                    daz = ((sector[dasector].ceilingz+sector[dasector].floorz)>>1);
831
                else
832
                    daz = sector[dasector].ceilingz;
833
            }
834
            if ((j = setanimation(&sector[dasector].floorz,daz,6L,6L)) >= 0)
835
                wsayfollow("updowndr.wav",4096L+(krand()&255)-128,256L,&centx,&centy,0);
836
        }
837
    }
4555 hendricks2 838
 
5327 hendricks2 839
    if (datag == 9)   //Smooshy-wall sideways double-door
840
    {
841
        //find any points with either same x or same y coordinate
842
        //  as center (centx, centy) - should be 2 points found.
843
        wallfind[0] = -1;
844
        wallfind[1] = -1;
845
        for (i=startwall; i<endwall; i++)
846
            if ((wall[i].x == centx) || (wall[i].y == centy))
847
            {
848
                if (wallfind[0] == -1)
849
                    wallfind[0] = i;
850
                else
851
                    wallfind[1] = i;
852
            }
4555 hendricks2 853
 
5327 hendricks2 854
        for (j=0; j<2; j++)
855
        {
856
            if ((wall[wallfind[j]].x == centx) && (wall[wallfind[j]].y == centy))
857
            {
858
                //find what direction door should open by averaging the
859
                //  2 neighboring points of wallfind[0] & wallfind[1].
860
                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
861
                dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
862
                day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
863
                if (dax2 != 0)
864
                {
865
                    dax2 = wall[wall[wall[wallfind[j]].point2].point2].x;
866
                    dax2 -= wall[wall[wallfind[j]].point2].x;
867
                    setanimation(&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,4L,0L);
868
                    setanimation(&wall[i].x,wall[i].x+dax2,4L,0L);
869
                    setanimation(&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,4L,0L);
870
                }
871
                else if (day2 != 0)
872
                {
873
                    day2 = wall[wall[wall[wallfind[j]].point2].point2].y;
874
                    day2 -= wall[wall[wallfind[j]].point2].y;
875
                    setanimation(&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,4L,0L);
876
                    setanimation(&wall[i].y,wall[i].y+day2,4L,0L);
877
                    setanimation(&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,4L,0L);
878
                }
879
            }
880
            else
881
            {
882
                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
883
                dax2 = ((wall[i].x+wall[wall[wallfind[j]].point2].x)>>1)-wall[wallfind[j]].x;
884
                day2 = ((wall[i].y+wall[wall[wallfind[j]].point2].y)>>1)-wall[wallfind[j]].y;
885
                if (dax2 != 0)
886
                {
887
                    setanimation(&wall[wallfind[j]].x,centx,4L,0L);
888
                    setanimation(&wall[i].x,centx+dax2,4L,0L);
889
                    setanimation(&wall[wall[wallfind[j]].point2].x,centx+dax2,4L,0L);
890
                }
891
                else if (day2 != 0)
892
                {
893
                    setanimation(&wall[wallfind[j]].y,centy,4L,0L);
894
                    setanimation(&wall[i].y,centy+day2,4L,0L);
895
                    setanimation(&wall[wall[wallfind[j]].point2].y,centy+day2,4L,0L);
896
                }
897
            }
898
        }
899
        wsayfollow("updowndr.wav",4096L-256L,256L,&centx,&centy,0);
900
        wsayfollow("updowndr.wav",4096L+256L,256L,&centx,&centy,0);
901
    }
4555 hendricks2 902
 
5327 hendricks2 903
    if (datag == 13)  //Swinging door
904
    {
905
        for (i=0; i<swingcnt; i++)
906
        {
907
            if (swingsector[i] == dasector)
908
            {
909
                if (swinganginc[i] == 0)
910
                {
911
                    if (swingang[i] == swingangclosed[i])
912
                    {
913
                        swinganginc[i] = swingangopendir[i];
914
                        wsayfollow("opendoor.wav",4096L+(krand()&511)-256,256L,&centx,&centy,0);
915
                    }
916
                    else
917
                        swinganginc[i] = -swingangopendir[i];
918
                }
919
                else
920
                    swinganginc[i] = -swinganginc[i];
4555 hendricks2 921
 
5327 hendricks2 922
                for (j=1; j<=3; j++)
923
                {
924
                    setinterpolation(&wall[swingwall[i][j]].x);
925
                    setinterpolation(&wall[swingwall[i][j]].y);
926
                }
927
            }
928
        }
929
    }
4555 hendricks2 930
 
5327 hendricks2 931
    if (datag == 16)  //True sideways double-sliding door
932
    {
933
        //get 2 closest line segments to center (dax, day)
934
        wallfind[0] = -1;
935
        wallfind[1] = -1;
936
        for (i=startwall; i<endwall; i++)
937
            if (wall[i].lotag == 6)
938
            {
939
                if (wallfind[0] == -1)
940
                    wallfind[0] = i;
941
                else
942
                    wallfind[1] = i;
943
            }
4555 hendricks2 944
 
5327 hendricks2 945
        for (j=0; j<2; j++)
946
        {
947
            if ((((wall[wallfind[j]].x+wall[wall[wallfind[j]].point2].x)>>1) == centx) && (((wall[wallfind[j]].y+wall[wall[wallfind[j]].point2].y)>>1) == centy))
948
            {
949
                //door was closed
950
                //find what direction door should open
951
                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
952
                dax2 = wall[i].x-wall[wallfind[j]].x;
953
                day2 = wall[i].y-wall[wallfind[j]].y;
954
                if (dax2 != 0)
955
                {
956
                    dax2 = wall[wall[wall[wall[wallfind[j]].point2].point2].point2].x;
957
                    dax2 -= wall[wall[wall[wallfind[j]].point2].point2].x;
958
                    setanimation(&wall[wallfind[j]].x,wall[wallfind[j]].x+dax2,4L,0L);
959
                    setanimation(&wall[i].x,wall[i].x+dax2,4L,0L);
960
                    setanimation(&wall[wall[wallfind[j]].point2].x,wall[wall[wallfind[j]].point2].x+dax2,4L,0L);
961
                    setanimation(&wall[wall[wall[wallfind[j]].point2].point2].x,wall[wall[wall[wallfind[j]].point2].point2].x+dax2,4L,0L);
962
                }
963
                else if (day2 != 0)
964
                {
965
                    day2 = wall[wall[wall[wall[wallfind[j]].point2].point2].point2].y;
966
                    day2 -= wall[wall[wall[wallfind[j]].point2].point2].y;
967
                    setanimation(&wall[wallfind[j]].y,wall[wallfind[j]].y+day2,4L,0L);
968
                    setanimation(&wall[i].y,wall[i].y+day2,4L,0L);
969
                    setanimation(&wall[wall[wallfind[j]].point2].y,wall[wall[wallfind[j]].point2].y+day2,4L,0L);
970
                    setanimation(&wall[wall[wall[wallfind[j]].point2].point2].y,wall[wall[wall[wallfind[j]].point2].point2].y+day2,4L,0L);
971
                }
972
            }
973
            else
974
            {
975
                //door was not closed
976
                i = wallfind[j]-1; if (i < startwall) i = endwall-1;
977
                dax2 = wall[i].x-wall[wallfind[j]].x;
978
                day2 = wall[i].y-wall[wallfind[j]].y;
979
                if (dax2 != 0)
980
                {
981
                    setanimation(&wall[wallfind[j]].x,centx,4L,0L);
982
                    setanimation(&wall[i].x,centx+dax2,4L,0L);
983
                    setanimation(&wall[wall[wallfind[j]].point2].x,centx,4L,0L);
984
                    setanimation(&wall[wall[wall[wallfind[j]].point2].point2].x,centx+dax2,4L,0L);
985
                }
986
                else if (day2 != 0)
987
                {
988
                    setanimation(&wall[wallfind[j]].y,centy,4L,0L);
989
                    setanimation(&wall[i].y,centy+day2,4L,0L);
990
                    setanimation(&wall[wall[wallfind[j]].point2].y,centy,4L,0L);
991
                    setanimation(&wall[wall[wall[wallfind[j]].point2].point2].y,centy+day2,4L,0L);
992
                }
993
            }
994
        }
995
        wsayfollow("updowndr.wav",4096L-64L,256L,&centx,&centy,0);
996
        wsayfollow("updowndr.wav",4096L+64L,256L,&centx,&centy,0);
997
    }
4555 hendricks2 998
}
999
 
1000
void operatesprite(short dasprite)
1001
{
5327 hendricks2 1002
    int datag;
4555 hendricks2 1003
 
5327 hendricks2 1004
    datag = sprite[dasprite].lotag;
4555 hendricks2 1005
 
5327 hendricks2 1006
    if (datag == 2)    //A sprite that shoots a bomb
1007
    {
4555 hendricks2 1008
        vec3_t vector = { sprite[dasprite].x,sprite[dasprite].y,sprite[dasprite].z };
5327 hendricks2 1009
        shootgun(dasprite, &vector,
1010
                 sprite[dasprite].ang,100L,sprite[dasprite].sectnum,2);
1011
    }
4555 hendricks2 1012
}
1013
 
1014
int changehealth(short snum, short deltahealth)
1015
{
5327 hendricks2 1016
    // int dax, day;
1017
    // short good, k, startwall, endwall, s;
4555 hendricks2 1018
 
5327 hendricks2 1019
    if (health[snum] > 0)
1020
    {
1021
        health[snum] += deltahealth;
1022
        if (health[snum] > 999) health[snum] = 999;
4555 hendricks2 1023
 
5327 hendricks2 1024
        if (health[snum] <= 0)
1025
        {
1026
            health[snum] = -1;
1027
            wsayfollow("death.wav",4096L+(krand()&127)-64,256L,&pos[snum].x,&pos[snum].y,1);
1028
            sprite[playersprite[snum]].picnum = SKELETON;
1029
        }
4555 hendricks2 1030
 
5327 hendricks2 1031
        if ((snum == screenpeek) && (screensize <= xdim))
1032
        {
1033
            if (health[snum] > 0)
1034
                sprintf((char *)tempbuf,"Health:%3d",health[snum]);
1035
            else
1036
                sprintf((char *)tempbuf,"YOU STINK!");
4555 hendricks2 1037
 
5327 hendricks2 1038
            printext((xdim>>1)-(Bstrlen((char *)tempbuf)<<2),ydim-24,(char *)tempbuf,ALPHABET /*,80*/);
1039
        }
1040
    }
1041
    return health[snum] <= 0;       //You were just injured
4555 hendricks2 1042
}
1043
 
5327 hendricks2 1044
void changenumbombs(short snum, short deltanumbombs)     // Andy did this
1045
{
1046
    numbombs[snum] += deltanumbombs;
1047
    if (numbombs[snum] > 999) numbombs[snum] = 999;
1048
    if (numbombs[snum] <= 0)
1049
    {
1050
        wsayfollow("doh.wav",4096L+(krand()&127)-64,256L,&pos[snum].x,&pos[snum].y,1);
1051
        numbombs[snum] = 0;
1052
    }
4555 hendricks2 1053
 
5327 hendricks2 1054
    if ((snum == screenpeek) && (screensize <= xdim))
1055
    {
1056
        sprintf((char *)tempbuf,"B:%3d",numbombs[snum]);
1057
        printext(8L,(ydim - 28L),(char *)tempbuf,ALPHABET /*,80*/);
1058
    }
4555 hendricks2 1059
}
1060
 
5327 hendricks2 1061
void changenummissiles(short snum, short deltanummissiles)     // Andy did this
1062
{
1063
    nummissiles[snum] += deltanummissiles;
1064
    if (nummissiles[snum] > 999) nummissiles[snum] = 999;
1065
    if (nummissiles[snum] <= 0)
1066
    {
1067
        wsayfollow("doh.wav",4096L+(krand()&127)-64,256L,&pos[snum].x,&pos[snum].y,1);
1068
        nummissiles[snum] = 0;
1069
    }
4555 hendricks2 1070
 
5327 hendricks2 1071
    if ((snum == screenpeek) && (screensize <= xdim))
1072
    {
1073
        sprintf((char *)tempbuf,"M:%3d",nummissiles[snum]);
1074
        printext(8L,(ydim - 20L),(char *)tempbuf,ALPHABET /*,80*/);
1075
    }
4555 hendricks2 1076
}
1077
 
5327 hendricks2 1078
void changenumgrabbers(short snum, short deltanumgrabbers)     // Andy did this
1079
{
1080
    numgrabbers[snum] += deltanumgrabbers;
1081
    if (numgrabbers[snum] > 999) numgrabbers[snum] = 999;
1082
    if (numgrabbers[snum] <= 0)
1083
    {
1084
        wsayfollow("doh.wav",4096L+(krand()&127)-64,256L,&pos[snum].x,&pos[snum].y,1);
1085
        numgrabbers[snum] = 0;
1086
    }
4555 hendricks2 1087
 
5327 hendricks2 1088
    if ((snum == screenpeek) && (screensize <= xdim))
1089
    {
1090
        sprintf((char *)tempbuf,"G:%3d",numgrabbers[snum]);
1091
        printext(8L,(ydim - 12L),(char *)tempbuf,ALPHABET /*,80*/);
1092
    }
4555 hendricks2 1093
}
1094
 
1095
static int ostatusflytime = 0x80000000;
5327 hendricks2 1096
void drawstatusflytime(short snum)     // Andy did this
1097
{
1098
    int nstatusflytime;
4555 hendricks2 1099
 
5327 hendricks2 1100
    if ((snum == screenpeek) && (screensize <= xdim))
1101
    {
1102
        nstatusflytime = (((flytime[snum] + 119) - lockclock) / 120);
1103
        if (nstatusflytime > 1000) nstatusflytime = 1000;
1104
        else if (nstatusflytime < 0) nstatusflytime = 0;
1105
        if (nstatusflytime != ostatusflytime)
1106
        {
1107
            if (nstatusflytime > 999) sprintf((char *)tempbuf,"FT:BIG");
1108
            else sprintf((char *)tempbuf,"FT:%3d",nstatusflytime);
1109
            printext((xdim - 56L),(ydim - 20L),(char *)tempbuf,ALPHABET /*,80*/);
1110
            ostatusflytime = nstatusflytime;
1111
        }
1112
    }
4555 hendricks2 1113
}
1114
 
5327 hendricks2 1115
void drawstatusbar(short snum)     // Andy did this
1116
{
1117
    int nstatusflytime;
4555 hendricks2 1118
 
5327 hendricks2 1119
    if ((snum == screenpeek) && (screensize <= xdim))
1120
    {
1121
        sprintf((char *)tempbuf,"Deaths:%d",deaths[snum]);
1122
        printext((xdim>>1)-(strlen((char *)tempbuf)<<2),ydim-16,(char *)tempbuf,ALPHABET /*,80*/);
1123
        sprintf((char *)tempbuf,"Health:%3d",health[snum]);
1124
        printext((xdim>>1)-(strlen((char *)tempbuf)<<2),ydim-24,(char *)tempbuf,ALPHABET /*,80*/);
4555 hendricks2 1125
 
5327 hendricks2 1126
        sprintf((char *)tempbuf,"B:%3d",numbombs[snum]);
1127
        printext(8L,(ydim - 28L),(char *)tempbuf,ALPHABET /*,80*/);
1128
        sprintf((char *)tempbuf,"M:%3d",nummissiles[snum]);
1129
        printext(8L,(ydim - 20L),(char *)tempbuf,ALPHABET /*,80*/);
1130
        sprintf((char *)tempbuf,"G:%3d",numgrabbers[snum]);
1131
        printext(8L,(ydim - 12L),(char *)tempbuf,ALPHABET /*,80*/);
4555 hendricks2 1132
 
5327 hendricks2 1133
        nstatusflytime = (((flytime[snum] + 119) - lockclock) / 120);
1134
        if (nstatusflytime < 0)
1135
        {
1136
            sprintf((char *)tempbuf,"FT:  0");
1137
            ostatusflytime = 0;
1138
        }
1139
        else if (nstatusflytime > 999)
1140
        {
1141
            sprintf((char *)tempbuf,"FT:BIG");
1142
            ostatusflytime = 999;
1143
        }
1144
        else
1145
        {
1146
            sprintf((char *)tempbuf,"FT:%3d",nstatusflytime);
1147
            ostatusflytime = nstatusflytime;
1148
        }
1149
        printext((xdim - 56L),(ydim - 20L),(char *)tempbuf,ALPHABET /*,80*/);
1150
    }
4555 hendricks2 1151
}
1152
 
1153
void prepareboard(char *daboardfilename)
1154
{
5327 hendricks2 1155
    short startwall, endwall, dasector;
1156
    int i, j, k=0, s, dax, day, /*daz,*/ dax2, day2;
4555 hendricks2 1157
 
5327 hendricks2 1158
    getmessageleng = 0;
1159
    typemessageleng = 0;
4555 hendricks2 1160
 
5327 hendricks2 1161
    randomseed = 17L;
4555 hendricks2 1162
 
5327 hendricks2 1163
    //Clear (do)animation's list
1164
    animatecnt = 0;
1165
    typemode = 0;
1166
    locselectedgun = 0;
1167
    locselectedgun2 = 0;
4555 hendricks2 1168
 
5327 hendricks2 1169
    if (loadboard(daboardfilename,0,&pos[0],&ang[0],&cursectnum[0]) == -1)
1170
    {
1171
        musicoff();
1172
        uninitmultiplayers();
1173
        uninittimer();
1174
        uninitinput();
1175
        uninitengine();
1176
        uninitsb();
1177
        uninitgroupfile();
1178
        printf("Board not found\n");
1179
        exit(0);
1180
    }
1181
    else
1182
    {
1183
        char tempfn[BMAX_PATH + 1], *fp;
4555 hendricks2 1184
 
5327 hendricks2 1185
        strncpy(tempfn, daboardfilename, BMAX_PATH);
1186
        tempfn[BMAX_PATH] = 0;
4555 hendricks2 1187
 
5327 hendricks2 1188
        fp = strrchr(tempfn,'.');
1189
        if (fp) *fp = 0;
4555 hendricks2 1190
 
5327 hendricks2 1191
        if (strlen(tempfn) <= BMAX_PATH-4)
1192
        {
1193
            strcat(tempfn,".mhk");
1194
            loadmaphack(tempfn);
1195
        }
1196
    }
4555 hendricks2 1197
 
5327 hendricks2 1198
    setup3dscreen();
4555 hendricks2 1199
 
5327 hendricks2 1200
    for (i=0; i<MAXPLAYERS; i++)
1201
    {
1202
        pos[i] = pos[0];
1203
        ang[i] = ang[0];
1204
        cursectnum[i] = cursectnum[0];
1205
        ocursectnum[i] = cursectnum[0];
1206
        horiz[i] = 100;
1207
        lastchaingun[i] = 0;
1208
        health[i] = 100;
1209
        dimensionmode[i] = 3;
1210
        numbombs[i] = 0;
1211
        numgrabbers[i] = 0;
1212
        nummissiles[i] = 0;
1213
        flytime[i] = 0L;
1214
        zoom[i] = 768L;
1215
        deaths[i] = 0L;
1216
        playersprite[i] = -1;
1217
        screensize = xdim;
4555 hendricks2 1218
 
5327 hendricks2 1219
        opos[i] = pos[0];
1220
        ohoriz[i] = horiz[0];
1221
        ozoom[i] = zoom[0];
1222
        oang[i] = ang[0];
1223
    }
4555 hendricks2 1224
 
5327 hendricks2 1225
    my = omy = pos[myconnectindex];
1226
    myhoriz = omyhoriz = horiz[myconnectindex];
1227
    myang = omyang = ang[myconnectindex];
1228
    mycursectnum = cursectnum[myconnectindex];
1229
    myzvel = 0;
4555 hendricks2 1230
 
5327 hendricks2 1231
    movefifoplc = fakemovefifoplc = 0;
1232
    syncvalhead = 0L; othersyncvalhead = 0L;
1233
    syncvaltottail = 0L; syncvaltail = 0L;
1234
    numinterpolations = 0;
4555 hendricks2 1235
 
5327 hendricks2 1236
    clearbufbyte(&oloc,sizeof(input),0L);
1237
    for (i=0; i<MAXPLAYERS; i++)
1238
    {
1239
        movefifoend[i] = 0;
1240
        clearbufbyte(&ffsync[i],sizeof(input),0L);
1241
        clearbufbyte(&ssync[i],sizeof(input),0L);
1242
        clearbufbyte(&osync[i],sizeof(input),0L);
1243
    }
4555 hendricks2 1244
 
5327 hendricks2 1245
    //Scan sector tags
4555 hendricks2 1246
 
5327 hendricks2 1247
    for (i=0; i<MAXPLAYERS; i++)
1248
    {
1249
        waterfountainwall[i] = -1;
1250
        waterfountaincnt[i] = 0;
1251
        slimesoundcnt[i] = 0;
1252
    }
1253
    warpsectorcnt = 0;      //Make a list of warping sectors
1254
    xpanningsectorcnt = 0;  //Make a list of wall x-panning sectors
1255
    floorpanningcnt = 0;    //Make a list of slime sectors
1256
    dragsectorcnt = 0;      //Make a list of moving platforms
1257
    swingcnt = 0;           //Make a list of swinging doors
1258
    revolvecnt = 0;         //Make a list of revolving doors
1259
    subwaytrackcnt = 0;     //Make a list of subways
4555 hendricks2 1260
 
5327 hendricks2 1261
    floormirrorcnt = 0;
1262
    tilesiz[FLOORMIRROR].x = 0;
1263
    tilesiz[FLOORMIRROR].y = 0;
4555 hendricks2 1264
 
5327 hendricks2 1265
    for (i=0; i<numsectors; i++)
1266
    {
1267
        switch (sector[i].lotag)
1268
        {
1269
        case 4:
1270
            floorpanninglist[floorpanningcnt++] = i;
1271
            break;
1272
        case 10:
1273
            warpsectorlist[warpsectorcnt++] = i;
1274
            break;
1275
        case 11:
1276
            xpanningsectorlist[xpanningsectorcnt++] = i;
1277
            break;
1278
        case 12:
1279
            dasector = i;
1280
            dax = 0x7fffffff;
1281
            day = 0x7fffffff;
1282
            dax2 = 0x80000000;
1283
            day2 = 0x80000000;
1284
            startwall = sector[i].wallptr;
1285
            endwall = startwall+sector[i].wallnum;
1286
            for (j=startwall; j<endwall; j++)
1287
            {
1288
                if (wall[j].x < dax) dax = wall[j].x;
1289
                if (wall[j].y < day) day = wall[j].y;
1290
                if (wall[j].x > dax2) dax2 = wall[j].x;
1291
                if (wall[j].y > day2) day2 = wall[j].y;
1292
                if (wall[j].lotag == 3) k = j;
1293
            }
1294
            if (wall[k].x == dax) dragxdir[dragsectorcnt] = -16;
1295
            if (wall[k].y == day) dragydir[dragsectorcnt] = -16;
1296
            if (wall[k].x == dax2) dragxdir[dragsectorcnt] = 16;
1297
            if (wall[k].y == day2) dragydir[dragsectorcnt] = 16;
4555 hendricks2 1298
 
5327 hendricks2 1299
            dasector = wall[startwall].nextsector;
1300
            dragx1[dragsectorcnt] = 0x7fffffff;
1301
            dragy1[dragsectorcnt] = 0x7fffffff;
1302
            dragx2[dragsectorcnt] = 0x80000000;
1303
            dragy2[dragsectorcnt] = 0x80000000;
1304
            startwall = sector[dasector].wallptr;
1305
            endwall = startwall+sector[dasector].wallnum;
1306
            for (j=startwall; j<endwall; j++)
1307
            {
1308
                if (wall[j].x < dragx1[dragsectorcnt]) dragx1[dragsectorcnt] = wall[j].x;
1309
                if (wall[j].y < dragy1[dragsectorcnt]) dragy1[dragsectorcnt] = wall[j].y;
1310
                if (wall[j].x > dragx2[dragsectorcnt]) dragx2[dragsectorcnt] = wall[j].x;
1311
                if (wall[j].y > dragy2[dragsectorcnt]) dragy2[dragsectorcnt] = wall[j].y;
4555 hendricks2 1312
 
5327 hendricks2 1313
                setinterpolation(&sector[dasector].floorz);
1314
                setinterpolation(&wall[j].x);
1315
                setinterpolation(&wall[j].y);
1316
                setinterpolation(&wall[wall[j].nextwall].x);
1317
                setinterpolation(&wall[wall[j].nextwall].y);
1318
            }
4555 hendricks2 1319
 
5327 hendricks2 1320
            dragx1[dragsectorcnt] += (wall[sector[i].wallptr].x-dax);
1321
            dragy1[dragsectorcnt] += (wall[sector[i].wallptr].y-day);
1322
            dragx2[dragsectorcnt] -= (dax2-wall[sector[i].wallptr].x);
1323
            dragy2[dragsectorcnt] -= (day2-wall[sector[i].wallptr].y);
4555 hendricks2 1324
 
5327 hendricks2 1325
            dragfloorz[dragsectorcnt] = sector[i].floorz;
4555 hendricks2 1326
 
5327 hendricks2 1327
            dragsectorlist[dragsectorcnt++] = i;
1328
            break;
1329
        case 13:
1330
            startwall = sector[i].wallptr;
1331
            endwall = startwall+sector[i].wallnum;
1332
            for (j=startwall; j<endwall; j++)
1333
            {
1334
                if (wall[j].lotag == 4)
1335
                {
1336
                    k = wall[wall[wall[wall[j].point2].point2].point2].point2;
1337
                    if ((wall[j].x == wall[k].x) && (wall[j].y == wall[k].y))
1338
                    {
1339
                        //Door opens counterclockwise
1340
                        swingwall[swingcnt][0] = j;
1341
                        swingwall[swingcnt][1] = wall[j].point2;
1342
                        swingwall[swingcnt][2] = wall[wall[j].point2].point2;
1343
                        swingwall[swingcnt][3] = wall[wall[wall[j].point2].point2].point2;
1344
                        swingangopen[swingcnt] = 1536;
1345
                        swingangclosed[swingcnt] = 0;
1346
                        swingangopendir[swingcnt] = -1;
1347
                    }
1348
                    else
1349
                    {
1350
                        //Door opens clockwise
1351
                        swingwall[swingcnt][0] = wall[j].point2;
1352
                        swingwall[swingcnt][1] = j;
1353
                        swingwall[swingcnt][2] = lastwall(j);
1354
                        swingwall[swingcnt][3] = lastwall(swingwall[swingcnt][2]);
1355
                        swingwall[swingcnt][4] = lastwall(swingwall[swingcnt][3]);
1356
                        swingangopen[swingcnt] = 512;
1357
                        swingangclosed[swingcnt] = 0;
1358
                        swingangopendir[swingcnt] = 1;
1359
                    }
1360
                    for (k=0; k<4; k++)
1361
                    {
1362
                        swingx[swingcnt][k] = wall[swingwall[swingcnt][k]].x;
1363
                        swingy[swingcnt][k] = wall[swingwall[swingcnt][k]].y;
1364
                    }
4555 hendricks2 1365
 
5327 hendricks2 1366
                    swingsector[swingcnt] = i;
1367
                    swingang[swingcnt] = swingangclosed[swingcnt];
1368
                    swinganginc[swingcnt] = 0;
1369
                    swingcnt++;
1370
                }
1371
            }
1372
            break;
1373
        case 14:
1374
            startwall = sector[i].wallptr;
1375
            endwall = startwall+sector[i].wallnum;
1376
            dax = 0L;
1377
            day = 0L;
1378
            for (j=startwall; j<endwall; j++)
1379
            {
1380
                dax += wall[j].x;
1381
                day += wall[j].y;
1382
            }
1383
            revolvepivotx[revolvecnt] = dax / (endwall-startwall);
1384
            revolvepivoty[revolvecnt] = day / (endwall-startwall);
4555 hendricks2 1385
 
5327 hendricks2 1386
            k = 0;
1387
            for (j=startwall; j<endwall; j++)
1388
            {
1389
                revolvex[revolvecnt][k] = wall[j].x;
1390
                revolvey[revolvecnt][k] = wall[j].y;
4555 hendricks2 1391
 
5327 hendricks2 1392
                setinterpolation(&wall[j].x);
1393
                setinterpolation(&wall[j].y);
1394
                setinterpolation(&wall[wall[j].nextwall].x);
1395
                setinterpolation(&wall[wall[j].nextwall].y);
4555 hendricks2 1396
 
5327 hendricks2 1397
                k++;
1398
            }
1399
            revolvesector[revolvecnt] = i;
1400
            revolveang[revolvecnt] = 0;
4555 hendricks2 1401
 
5327 hendricks2 1402
            revolvecnt++;
1403
            break;
1404
        case 15:
1405
            subwaytracksector[subwaytrackcnt][0] = i;
4555 hendricks2 1406
 
5327 hendricks2 1407
            subwaystopcnt[subwaytrackcnt] = 0;
1408
            dax = 0x7fffffff;
1409
            day = 0x7fffffff;
1410
            dax2 = 0x80000000;
1411
            day2 = 0x80000000;
1412
            startwall = sector[i].wallptr;
1413
            endwall = startwall+sector[i].wallnum;
1414
            for (j=startwall; j<endwall; j++)
1415
            {
1416
                if (wall[j].x < dax) dax = wall[j].x;
1417
                if (wall[j].y < day) day = wall[j].y;
1418
                if (wall[j].x > dax2) dax2 = wall[j].x;
1419
                if (wall[j].y > day2) day2 = wall[j].y;
1420
            }
1421
            for (j=startwall; j<endwall; j++)
1422
            {
1423
                if (wall[j].lotag == 5)
1424
                {
1425
                    if ((wall[j].x > dax) && (wall[j].y > day) && (wall[j].x < dax2) && (wall[j].y < day2))
1426
                    {
1427
                        subwayx[subwaytrackcnt] = wall[j].x;
1428
                    }
1429
                    else
1430
                    {
1431
                        subwaystop[subwaytrackcnt][subwaystopcnt[subwaytrackcnt]] = wall[j].x;
1432
                        subwaystopcnt[subwaytrackcnt]++;
1433
                    }
1434
                }
1435
            }
4555 hendricks2 1436
 
5327 hendricks2 1437
            for (j=1; j<subwaystopcnt[subwaytrackcnt]; j++)
1438
                for (k=0; k<j; k++)
1439
                    if (subwaystop[subwaytrackcnt][j] < subwaystop[subwaytrackcnt][k])
1440
                    {
1441
                        s = subwaystop[subwaytrackcnt][j];
1442
                        subwaystop[subwaytrackcnt][j] = subwaystop[subwaytrackcnt][k];
1443
                        subwaystop[subwaytrackcnt][k] = s;
1444
                    }
4555 hendricks2 1445
 
5327 hendricks2 1446
            subwaygoalstop[subwaytrackcnt] = 0;
1447
            for (j=0; j<subwaystopcnt[subwaytrackcnt]; j++)
1448
                if (klabs(subwaystop[subwaytrackcnt][j]-subwayx[subwaytrackcnt]) < klabs(subwaystop[subwaytrackcnt][subwaygoalstop[subwaytrackcnt]]-subwayx[subwaytrackcnt]))
1449
                    subwaygoalstop[subwaytrackcnt] = j;
4555 hendricks2 1450
 
5327 hendricks2 1451
            subwaytrackx1[subwaytrackcnt] = dax;
1452
            subwaytracky1[subwaytrackcnt] = day;
1453
            subwaytrackx2[subwaytrackcnt] = dax2;
1454
            subwaytracky2[subwaytrackcnt] = day2;
4555 hendricks2 1455
 
5327 hendricks2 1456
            subwaynumsectors[subwaytrackcnt] = 1;
1457
            for (j=0; j<numsectors; j++)
1458
                if (j != i)
1459
                {
1460
                    startwall = sector[j].wallptr;
1461
                    if (wall[startwall].x > subwaytrackx1[subwaytrackcnt])
1462
                        if (wall[startwall].y > subwaytracky1[subwaytrackcnt])
1463
                            if (wall[startwall].x < subwaytrackx2[subwaytrackcnt])
1464
                                if (wall[startwall].y < subwaytracky2[subwaytrackcnt])
1465
                                {
1466
                                    if (sector[j].floorz != sector[i].floorz)
1467
                                    {
1468
                                        sector[j].ceilingstat |= 64;
1469
                                        sector[j].floorstat |= 64;
1470
                                    }
1471
                                    subwaytracksector[subwaytrackcnt][subwaynumsectors[subwaytrackcnt]] = j;
1472
                                    subwaynumsectors[subwaytrackcnt]++;
1473
                                }
1474
                }
4555 hendricks2 1475
 
5327 hendricks2 1476
            subwayvel[subwaytrackcnt] = 64;
1477
            subwaypausetime[subwaytrackcnt] = 720;
4555 hendricks2 1478
 
5327 hendricks2 1479
            startwall = sector[i].wallptr;
1480
            endwall = startwall+sector[i].wallnum;
1481
            for (k=startwall; k<endwall; k++)
1482
                if (wall[k].x > subwaytrackx1[subwaytrackcnt])
1483
                    if (wall[k].y > subwaytracky1[subwaytrackcnt])
1484
                        if (wall[k].x < subwaytrackx2[subwaytrackcnt])
1485
                            if (wall[k].y < subwaytracky2[subwaytrackcnt])
1486
                                setinterpolation(&wall[k].x);
4555 hendricks2 1487
 
5327 hendricks2 1488
            for (j=1; j<subwaynumsectors[subwaytrackcnt]; j++)
1489
            {
1490
                dasector = subwaytracksector[subwaytrackcnt][j];
4555 hendricks2 1491
 
5327 hendricks2 1492
                startwall = sector[dasector].wallptr;
1493
                endwall = startwall+sector[dasector].wallnum;
1494
                for (k=startwall; k<endwall; k++)
1495
                    setinterpolation(&wall[k].x);
4555 hendricks2 1496
 
5327 hendricks2 1497
                for (k=headspritesect[dasector]; k>=0; k=nextspritesect[k])
1498
                    if (statrate[sprite[k].statnum] < 0)
1499
                        setinterpolation(&sprite[k].x);
1500
            }
4555 hendricks2 1501
 
1502
 
5327 hendricks2 1503
            subwaytrackcnt++;
1504
            break;
1505
        }
1506
        if (sector[i].floorpicnum == FLOORMIRROR)
1507
            floormirrorsector[mirrorcnt++] = i;
1508
        //if (sector[i].ceilingpicnum == FLOORMIRROR) floormirrorsector[mirrorcnt++] = i; //SOS
1509
    }
4555 hendricks2 1510
 
5327 hendricks2 1511
    //Scan wall tags
4555 hendricks2 1512
 
5327 hendricks2 1513
    mirrorcnt = 0;
1514
    tilesiz[MIRROR].x = 0;
1515
    tilesiz[MIRROR].y = 0;
1516
    for (i=0; i<MAXMIRRORS; i++)
1517
    {
1518
        tilesiz[i+MIRRORLABEL].x = 0;
1519
        tilesiz[i+MIRRORLABEL].y = 0;
1520
    }
4555 hendricks2 1521
 
5327 hendricks2 1522
    ypanningwallcnt = 0;
1523
    for (i=0; i<numwalls; i++)
1524
    {
1525
        if (wall[i].lotag == 1) ypanningwalllist[ypanningwallcnt++] = i;
1526
        s = wall[i].nextsector;
1527
        if ((s >= 0) && (wall[i].overpicnum == MIRROR) && (wall[i].cstat&32))
1528
        {
1529
            if ((sector[s].floorstat&1) == 0)
1530
            {
1531
                wall[i].overpicnum = MIRRORLABEL+mirrorcnt;
1532
                sector[s].ceilingpicnum = MIRRORLABEL+mirrorcnt;
1533
                sector[s].floorpicnum = MIRRORLABEL+mirrorcnt;
1534
                sector[s].floorstat |= 1;
1535
                mirrorwall[mirrorcnt] = i;
1536
                mirrorsector[mirrorcnt] = s;
1537
                mirrorcnt++;
1538
            }
1539
            else
1540
                wall[i].overpicnum = sector[s].ceilingpicnum;
1541
        }
1542
    }
4555 hendricks2 1543
 
5327 hendricks2 1544
    //Invalidate textures in sector behind mirror
1545
    for (i=0; i<mirrorcnt; i++)
1546
    {
1547
        k = mirrorsector[i];
1548
        startwall = sector[k].wallptr;
1549
        endwall = startwall + sector[k].wallnum;
1550
        for (j=startwall; j<endwall; j++)
1551
        {
1552
            wall[j].picnum = MIRROR;
1553
            wall[j].overpicnum = MIRROR;
1554
        }
1555
    }
4555 hendricks2 1556
 
5327 hendricks2 1557
    //Scan sprite tags&picnum's
4555 hendricks2 1558
 
5327 hendricks2 1559
    turnspritecnt = 0;
1560
    for (i=0; i<MAXSPRITES; i++)
1561
    {
1562
        if (sprite[i].lotag == 3) turnspritelist[turnspritecnt++] = i;
4555 hendricks2 1563
 
5327 hendricks2 1564
        if (sprite[i].statnum < MAXSTATUS)    //That is, if sprite exists
1565
            switch (sprite[i].picnum)
1566
            {
1567
            case BROWNMONSTER:              //All cases here put the sprite
1568
                if ((sprite[i].cstat&128) == 0)
1569
                {
1570
                    sprite[i].z -= ((tilesiz[sprite[i].picnum].y*sprite[i].yrepeat)<<1);
1571
                    sprite[i].cstat |= 128;
1572
                }
1573
                sprite[i].extra = sprite[i].ang;
1574
                sprite[i].clipdist = mulscale7(sprite[i].xrepeat,tilesiz[sprite[i].picnum].x);
1575
                if (sprite[i].statnum != 1) changespritestat(i,2);   //on waiting for you (list 2)
1576
                sprite[i].lotag = mulscale5(sprite[i].xrepeat,sprite[i].yrepeat);
1577
                sprite[i].cstat |= 0x101;    //Set the hitscan sensitivity bit
1578
                break;
1579
            case AL:
1580
                sprite[i].cstat |= 0x101;    //Set the hitscan sensitivity bit
1581
                sprite[i].lotag = 0x60;
1582
                changespritestat(i,0);
1583
                break;
1584
            case EVILAL:
1585
                sprite[i].cstat |= 0x101;    //Set the hitscan sensitivity bit
1586
                sprite[i].lotag = 0x60;
1587
                changespritestat(i,10);
1588
                break;
1589
            }
1590
    }
4555 hendricks2 1591
 
5327 hendricks2 1592
    for (i=MAXSPRITES-1; i>=0; i--) copybuf(&sprite[i].x,&osprite[i].x,3);
4555 hendricks2 1593
 
5327 hendricks2 1594
    searchmap(cursectnum[connecthead]);
4555 hendricks2 1595
 
5327 hendricks2 1596
    lockclock = 0;
1597
    ototalclock = 0;
1598
    gotlastpacketclock = 0;
4555 hendricks2 1599
 
5327 hendricks2 1600
    screensize = xdim;
1601
    dax = ((xdim-screensize)>>1);
1602
    dax2 = dax+screensize-1;
1603
    day = (((ydim-32)-scale(screensize,ydim-32,xdim))>>1);
1604
    day2 = day + scale(screensize,ydim-32,xdim)-1;
1605
    setview(dax,day,dax2,day2);
4555 hendricks2 1606
 
5327 hendricks2 1607
    startofdynamicinterpolations = numinterpolations;
4555 hendricks2 1608
 
1609
#if 0
5327 hendricks2 1610
    for (i=connecthead; i>=0; i=connectpoint2[i]) myminlag[i] = 0;
1611
    otherminlag = mymaxlag = 0;
4555 hendricks2 1612
#endif
1613
}
1614
 
1615
void checktouchsprite(short snum, short sectnum)
1616
{
5327 hendricks2 1617
    int i, nexti;
4555 hendricks2 1618
 
5327 hendricks2 1619
    if ((sectnum < 0) || (sectnum >= numsectors)) return;
4555 hendricks2 1620
 
5327 hendricks2 1621
    for (i=headspritesect[sectnum]; i>=0; i=nexti)
1622
    {
1623
        nexti = nextspritesect[i];
1624
        if (sprite[i].cstat&0x8000) continue;
1625
        if ((klabs(pos[snum].x-sprite[i].x)+klabs(pos[snum].y-sprite[i].y) < 512) && (klabs((pos[snum].z>>8)-((sprite[i].z>>8)-(tilesiz[sprite[i].picnum].y>>1))) <= 40))
1626
        {
1627
            switch (sprite[i].picnum)
1628
            {
1629
            case COIN:
1630
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,192L,&sprite[i].x,&sprite[i].y,0);
1631
                changehealth(snum,5);
1632
                if (sprite[i].statnum == 12) deletesprite((short)i);
1633
                else
1634
                {
1635
                    sprite[i].cstat |= 0x8000;
1636
                    sprite[i].extra = 120*60;
1637
                    changespritestat((short)i,11);
1638
                }
1639
                break;
1640
            case DIAMONDS:
1641
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1642
                changehealth(snum,15);
1643
                if (sprite[i].statnum == 12) deletesprite((short)i);
1644
                else
1645
                {
1646
                    sprite[i].cstat |= 0x8000;
1647
                    sprite[i].extra = 120*120;
1648
                    changespritestat((short)i,11);
1649
                }
1650
                break;
1651
            case COINSTACK:
1652
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1653
                changehealth(snum,25);
1654
                if (sprite[i].statnum == 12) deletesprite((short)i);
1655
                else
1656
                {
1657
                    sprite[i].cstat |= 0x8000;
1658
                    sprite[i].extra = 120*180;
1659
                    changespritestat((short)i,11);
1660
                }
1661
                break;
1662
            case GIFTBOX:
1663
                wsayfollow("getstuff.wav",4096L+(krand()&127)+256-mulscale4(sprite[i].xrepeat,sprite[i].yrepeat),208L,&sprite[i].x,&sprite[i].y,0);
1664
                changehealth(snum,max(mulscale8(sprite[i].xrepeat,sprite[i].yrepeat),1));
1665
                if (sprite[i].statnum == 12) deletesprite((short)i);
1666
                else
1667
                {
1668
                    sprite[i].cstat |= 0x8000;
1669
                    sprite[i].extra = 90*(sprite[i].xrepeat+sprite[i].yrepeat);
1670
                    changespritestat((short)i,11);
1671
                }
1672
                break;
1673
            case CANNON:
1674
                wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1675
                if (snum == myconnectindex) keystatus[4] = 1;
1676
                changenumbombs(snum,((sprite[i].xrepeat+sprite[i].yrepeat)>>1));
1677
                if (sprite[i].statnum == 12) deletesprite((short)i);
1678
                else
1679
                {
1680
                    sprite[i].cstat |= 0x8000;
1681
                    sprite[i].extra = 60*(sprite[i].xrepeat+sprite[i].yrepeat);
1682
                    changespritestat((short)i,11);
1683
                }
1684
                break;
1685
            case LAUNCHER:
1686
                wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1687
                if (snum == myconnectindex) keystatus[5] = 1;
1688
                changenummissiles(snum,((sprite[i].xrepeat+sprite[i].yrepeat)>>1));
1689
                if (sprite[i].statnum == 12) deletesprite((short)i);
1690
                else
1691
                {
1692
                    sprite[i].cstat |= 0x8000;
1693
                    sprite[i].extra = 90*(sprite[i].xrepeat+sprite[i].yrepeat);
1694
                    changespritestat((short)i,11);
1695
                }
1696
                break;
1697
            case GRABCANNON:
1698
                wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1699
                if (snum == myconnectindex) keystatus[6] = 1;
1700
                changenumgrabbers(snum,((sprite[i].xrepeat+sprite[i].yrepeat)>>1));
1701
                if (sprite[i].statnum == 12) deletesprite((short)i);
1702
                else
1703
                {
1704
                    sprite[i].cstat |= 0x8000;
1705
                    sprite[i].extra = 120*(sprite[i].xrepeat+sprite[i].yrepeat);
1706
                    changespritestat((short)i,11);
1707
                }
1708
                break;
1709
            case AIRPLANE:
1710
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1711
                if (flytime[snum] < lockclock) flytime[snum] = lockclock;
1712
                flytime[snum] += 60*(sprite[i].xrepeat+sprite[i].yrepeat);
1713
                drawstatusflytime(snum);
1714
                if (sprite[i].statnum == 12) deletesprite((short)i);
1715
                else
1716
                {
1717
                    sprite[i].cstat |= 0x8000;
1718
                    sprite[i].extra = 120*(sprite[i].xrepeat+sprite[i].yrepeat);
1719
                    changespritestat((short)i,11);
1720
                }
1721
                break;
1722
            }
1723
        }
1724
    }
4555 hendricks2 1725
}
1726
 
1727
void checkgrabbertouchsprite(short snum, short sectnum)   // Andy did this
1728
{
5327 hendricks2 1729
    int i, nexti;
1730
    short onum;
4555 hendricks2 1731
 
5327 hendricks2 1732
    if ((sectnum < 0) || (sectnum >= numsectors)) return;
1733
    onum = (sprite[snum].owner & (MAXSPRITES - 1));
4555 hendricks2 1734
 
5327 hendricks2 1735
    for (i=headspritesect[sectnum]; i>=0; i=nexti)
1736
    {
1737
        nexti = nextspritesect[i];
1738
        if (sprite[i].cstat&0x8000) continue;
1739
        if ((klabs(sprite[snum].x-sprite[i].x)+klabs(sprite[snum].y-sprite[i].y) < 512) && (klabs((sprite[snum].z>>8)-((sprite[i].z>>8)-(tilesiz[sprite[i].picnum].y>>1))) <= 40))
1740
        {
1741
            switch (sprite[i].picnum)
1742
            {
1743
            case COIN:
1744
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,192L,&sprite[i].x,&sprite[i].y,0);
1745
                changehealth(onum,5);
1746
                if (sprite[i].statnum == 12) deletesprite((short)i);
1747
                else
1748
                {
1749
                    sprite[i].cstat |= 0x8000;
1750
                    sprite[i].extra = 120*60;
1751
                    changespritestat((short)i,11);
1752
                }
1753
                break;
1754
            case DIAMONDS:
1755
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1756
                changehealth(onum,15);
1757
                if (sprite[i].statnum == 12) deletesprite((short)i);
1758
                else
1759
                {
1760
                    sprite[i].cstat |= 0x8000;
1761
                    sprite[i].extra = 120*120;
1762
                    changespritestat((short)i,11);
1763
                }
1764
                break;
1765
            case COINSTACK:
1766
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1767
                changehealth(onum,25);
1768
                if (sprite[i].statnum == 12) deletesprite((short)i);
1769
                else
1770
                {
1771
                    sprite[i].cstat |= 0x8000;
1772
                    sprite[i].extra = 120*180;
1773
                    changespritestat((short)i,11);
1774
                }
1775
                break;
1776
            case GIFTBOX:
1777
                wsayfollow("getstuff.wav",4096L+(krand()&127)+256-mulscale4(sprite[i].xrepeat,sprite[i].yrepeat),208L,&sprite[i].x,&sprite[i].y,0);
1778
                changehealth(onum,max(mulscale8(sprite[i].xrepeat,sprite[i].yrepeat),1));
1779
                if (sprite[i].statnum == 12) deletesprite((short)i);
1780
                else
1781
                {
1782
                    sprite[i].cstat |= 0x8000;
1783
                    sprite[i].extra = 90*(sprite[i].xrepeat+sprite[i].yrepeat);
1784
                    changespritestat((short)i,11);
1785
                }
1786
                break;
1787
            case CANNON:
1788
                wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1789
                if (onum == myconnectindex) keystatus[4] = 1;
1790
                changenumbombs(onum,((sprite[i].xrepeat+sprite[i].yrepeat)>>1));
1791
                if (sprite[i].statnum == 12) deletesprite((short)i);
1792
                else
1793
                {
1794
                    sprite[i].cstat |= 0x8000;
1795
                    sprite[i].extra = 60*(sprite[i].xrepeat+sprite[i].yrepeat);
1796
                    changespritestat((short)i,11);
1797
                }
1798
                break;
1799
            case LAUNCHER:
1800
                wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1801
                if (onum == myconnectindex) keystatus[5] = 1;
1802
                changenummissiles(onum,((sprite[i].xrepeat+sprite[i].yrepeat)>>1));
1803
                if (sprite[i].statnum == 12) deletesprite((short)i);
1804
                else
1805
                {
1806
                    sprite[i].cstat |= 0x8000;
1807
                    sprite[i].extra = 90*(sprite[i].xrepeat+sprite[i].yrepeat);
1808
                    changespritestat((short)i,11);
1809
                }
1810
                break;
1811
            case GRABCANNON:
1812
                wsayfollow("getstuff.wav",3584L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1813
                if (onum == myconnectindex) keystatus[6] = 1;
1814
                changenumgrabbers(onum,((sprite[i].xrepeat+sprite[i].yrepeat)>>1));
1815
                if (sprite[i].statnum == 12) deletesprite((short)i);
1816
                else
1817
                {
1818
                    sprite[i].cstat |= 0x8000;
1819
                    sprite[i].extra = 120*(sprite[i].xrepeat+sprite[i].yrepeat);
1820
                    changespritestat((short)i,11);
1821
                }
1822
                break;
1823
            case AIRPLANE:
1824
                wsayfollow("getstuff.wav",4096L+(krand()&127)-64,256L,&sprite[i].x,&sprite[i].y,0);
1825
                if (flytime[snum] < lockclock) flytime[snum] = lockclock;
1826
                flytime[onum] += 60*(sprite[i].xrepeat+sprite[i].yrepeat);
1827
                drawstatusflytime(onum);
1828
                if (sprite[i].statnum == 12) deletesprite((short)i);
1829
                else
1830
                {
1831
                    sprite[i].cstat |= 0x8000;
1832
                    sprite[i].extra = 120*(sprite[i].xrepeat+sprite[i].yrepeat);
1833
                    changespritestat((short)i,11);
1834
                }
1835
                break;
1836
            }
1837
        }
1838
    }
4555 hendricks2 1839
}
1840
 
1841
void shootgun(short snum, const vec3_t *vector,
5327 hendricks2 1842
              short daang, int dahoriz, short dasectnum, char guntype)
4555 hendricks2 1843
{
5327 hendricks2 1844
    short daang2;
1845
    int /*i,*/ j, daz2;
4555 hendricks2 1846
    hitdata_t hitinfo;
1847
 
5327 hendricks2 1848
    switch (guntype)
1849
    {
1850
    case 0:    //Shoot chain gun
1851
        daang2 = ((daang + (krand()&31)-16)&2047);
1852
        daz2 = ((100-dahoriz)*2000) + ((krand()-32768)>>1);
4555 hendricks2 1853
 
5327 hendricks2 1854
        hitscan(vector,dasectnum,                   //Start position
1855
                sintable[(daang2+512)&2047],            //X vector of 3D ang
1856
                sintable[daang2&2047],                  //Y vector of 3D ang
1857
                daz2,                                   //Z vector of 3D ang
1858
                &hitinfo,CLIPMASK1);
4555 hendricks2 1859
 
5327 hendricks2 1860
        if (wall[hitinfo.wall].picnum == KENPICTURE)
1861
        {
1862
            if (waloff[MAXTILES-1] != 0) wall[hitinfo.wall].picnum = MAXTILES-1;
1863
            wsayfollow("hello.wav",4096L+(krand()&127)-64,256L,&wall[hitinfo.wall].x,&wall[hitinfo.wall].y,0);
1864
        }
1865
        else if (((hitinfo.wall < 0) && (hitinfo.sprite < 0) && (hitinfo.pos.z >= vector->z) && ((sector[hitinfo.sect].floorpicnum == SLIME) || (sector[hitinfo.sect].floorpicnum == FLOORMIRROR))) || ((hitinfo.wall >= 0) && (wall[hitinfo.wall].picnum == SLIME)))
1866
        {
1867
            //If you shoot slime, make a splash
1868
            wsayfollow("splash.wav",4096L+(krand()&511)-256,256L,&hitinfo.pos.x,&hitinfo.pos.y,0);
1869
            spawnsprite(j,hitinfo.pos.x,hitinfo.pos.y,hitinfo.pos.z,2,0,0,32,64,64,0,0,SPLASH,daang,
1870
                        0,0,0,snum+4096,hitinfo.sect,4,63,0,0); //63=time left for splash
1871
        }
1872
        else
1873
        {
1874
            wsayfollow("shoot.wav",4096L+(krand()&127)-64,256L,&hitinfo.pos.x,&hitinfo.pos.y,0);
4555 hendricks2 1875
 
5327 hendricks2 1876
            if ((hitinfo.sprite >= 0) && (sprite[hitinfo.sprite].statnum < MAXSTATUS))
1877
                switch (sprite[hitinfo.sprite].picnum)
1878
                {
1879
                case BROWNMONSTER:
1880
                    if (sprite[hitinfo.sprite].lotag > 0) sprite[hitinfo.sprite].lotag -= 10;
1881
                    if (sprite[hitinfo.sprite].lotag > 0)
1882
                    {
1883
                        wsayfollow("hurt.wav",4096L+(krand()&511)-256,256L,&hitinfo.pos.x,&hitinfo.pos.y,0);
1884
                        if (sprite[hitinfo.sprite].lotag <= 25)
1885
                            sprite[hitinfo.sprite].cstat |= 2;
1886
                    }
1887
                    else
1888
                    {
1889
                        wsayfollow("mondie.wav",4096L+(krand()&127)-64,256L,&hitinfo.pos.x,&hitinfo.pos.y,0);
1890
                        sprite[hitinfo.sprite].z += ((tilesiz[sprite[hitinfo.sprite].picnum].y*sprite[hitinfo.sprite].yrepeat)<<1);
1891
                        sprite[hitinfo.sprite].picnum = GIFTBOX;
1892
                        sprite[hitinfo.sprite].cstat &= ~0x83;    //Should not clip, foot-z
1893
                        changespritestat(hitinfo.sprite,12);
4555 hendricks2 1894
 
5327 hendricks2 1895
                        spawnsprite(j,hitinfo.pos.x,hitinfo.pos.y,hitinfo.pos.z+(32<<8),0,-4,0,32,64,64,
1896
                                    0,0,EXPLOSION,daang,0,0,0,snum+4096,
1897
                                    hitinfo.sect,5,31,0,0);
1898
                    }
1899
                    break;
1900
                case EVILAL:
1901
                    wsayfollow("blowup.wav",4096L+(krand()&127)-64,256L,&hitinfo.pos.x,&hitinfo.pos.y,0);
1902
                    sprite[hitinfo.sprite].picnum = EVILALGRAVE;
1903
                    sprite[hitinfo.sprite].cstat = 0;
1904
                    sprite[hitinfo.sprite].xvel = (krand()&255)-128;
1905
                    sprite[hitinfo.sprite].yvel = (krand()&255)-128;
1906
                    sprite[hitinfo.sprite].zvel = (krand()&4095)-3072;
1907
                    changespritestat(hitinfo.sprite,9);
4555 hendricks2 1908
 
5327 hendricks2 1909
                    spawnsprite(j,hitinfo.pos.x,hitinfo.pos.y,hitinfo.pos.z+(32<<8),0,-4,0,32,64,64,0,
1910
                                0,EXPLOSION,daang,0,0,0,snum+4096,hitinfo.sect,5,31,0,0);
1911
                    //31=time left for explosion
4555 hendricks2 1912
 
5327 hendricks2 1913
                    break;
1914
                case PLAYER:
1915
                    for (j=connecthead; j>=0; j=connectpoint2[j])
1916
                        if (playersprite[j] == hitinfo.sprite)
1917
                        {
1918
                            wsayfollow("ouch.wav",4096L+(krand()&127)-64,256L,&hitinfo.pos.x,&hitinfo.pos.y,0);
1919
                            changehealth(j,-10);
1920
                            break;
1921
                        }
1922
                    break;
1923
                }
4555 hendricks2 1924
 
5327 hendricks2 1925
            spawnsprite(j,hitinfo.pos.x,hitinfo.pos.y,hitinfo.pos.z+(8<<8),2,-4,0,32,16,16,0,0,
1926
                        EXPLOSION,daang,0,0,0,snum+4096,hitinfo.sect,3,63,0,0);
4555 hendricks2 1927
 
5327 hendricks2 1928
            //Sprite starts out with center exactly on wall.
1929
            //This moves it back enough to see it at all angles.
1930
            movesprite((short)j,-(((int)sintable[(512+daang)&2047]*TICSPERFRAME)<<4),-(((int)sintable[daang]*TICSPERFRAME)<<4),0L,4L<<8,4L<<8,CLIPMASK1);
1931
        }
1932
        break;
1933
    case 1:    //Shoot silver sphere bullet
1934
        spawnsprite(j,vector->x,vector->y,vector->z,1+128,0,0,16,64,64,0,0,BULLET,daang,
1935
                    sintable[(daang+512)&2047]>>5,sintable[daang&2047]>>5,
1936
                    (100-dahoriz)<<6,snum+4096,dasectnum,6,0,0,0);
1937
        wsayfollow("shoot2.wav",4096L+(krand()&127)-64,128L,&sprite[j].x,&sprite[j].y,1);
1938
        break;
1939
    case 2:    //Shoot bomb
1940
        spawnsprite(j,vector->x,vector->y,vector->z,128,0,0,12,16,16,0,0,BOMB,daang,
1941
                    sintable[(daang+512)&2047]*5>>8,sintable[daang&2047]*5>>8,
1942
                    (80-dahoriz)<<6,snum+4096,dasectnum,6,0,0,0);
1943
        wsayfollow("shoot3.wav",4096L+(krand()&127)-64,192L,&sprite[j].x,&sprite[j].y,1);
1944
        break;
1945
    case 3:    //Shoot missile (Andy did this)
1946
        spawnsprite(j,vector->x,vector->y,vector->z,1+128,0,0,16,32,32,0,0,MISSILE,daang,
1947
                    sintable[(daang+512)&2047]>>4,sintable[daang&2047]>>4,
1948
                    (100-dahoriz)<<7,snum+4096,dasectnum,6,0,0,0);
1949
        wsayfollow("shoot3.wav",4096L+(krand()&127)-64,192L,&sprite[j].x,&sprite[j].y,1);
1950
        break;
1951
    case 4:    //Shoot grabber (Andy did this)
1952
        spawnsprite(j,vector->x,vector->y,vector->z,1+128,0,0,16,64,64,0,0,GRABBER,daang,
1953
                    sintable[(daang+512)&2047]>>5,sintable[daang&2047]>>5,
1954
                    (100-dahoriz)<<6,snum+4096,dasectnum,6,0,0,0);
1955
        wsayfollow("shoot4.wav",4096L+(krand()&127)-64,128L,&sprite[j].x,&sprite[j].y,1);
1956
        break;
1957
    }
4555 hendricks2 1958
}
1959
 
1960
#define MAXVOXMIPS 5
1961
extern intptr_t voxoff[][MAXVOXMIPS];
1962
void analyzesprites(int dax, int day)
1963
{
5327 hendricks2 1964
    int i, j=0, k, *intptr;
1965
    vec3_t *ospr;
5736 hendricks2 1966
    tspritetype *tspr;
4555 hendricks2 1967
 
5327 hendricks2 1968
    //This function is called between drawrooms() and drawmasks()
1969
    //It has a list of possible sprites that may be drawn on this frame
4555 hendricks2 1970
 
5327 hendricks2 1971
    for (i=0,tspr=&tsprite[0]; i<spritesortcnt; i++,tspr++)
1972
    {
1973
        if (usevoxels && tiletovox[tspr->picnum] >= 0)
1974
            switch (tspr->picnum)
1975
            {
1976
            case PLAYER:
1977
                //   //Get which of the 8 angles of the sprite to draw (0-7)
1978
                //   //k ranges from 0-7
1979
                //k = getangle(tspr->x-dax,tspr->y-day);
1980
                //k = (((tspr->ang+3072+128-k)&2047)>>8)&7;
1981
                //   //This guy has only 5 pictures for 8 angles (3 are x-flipped)
1982
                //if (k <= 4)
1983
                //{
1984
                //   tspr->picnum += (k<<2);
1985
                //   tspr->cstat &= ~4;   //clear x-flipping bit
1986
                //}
1987
                //else
1988
                //{
1989
                //   tspr->picnum += ((8-k)<<2);
1990
                //   tspr->cstat |= 4;    //set x-flipping bit
1991
                //}
4555 hendricks2 1992
 
5327 hendricks2 1993
                if ((tspr->cstat&2) == 0)
1994
                {
1995
                    //tspr->cstat |= 48; tspr->picnum = tiletovox[tspr->picnum];
1996
                    intptr = (int *)voxoff[tiletovox[PLAYER]][0];
1997
                    tspr->xrepeat = scale(tspr->xrepeat,56,intptr[2]);
1998
                    tspr->yrepeat = scale(tspr->yrepeat,56,intptr[2]);
1999
                    tspr->shade -= 6;
2000
                }
2001
                break;
2002
            case BROWNMONSTER:
2003
                //tspr->cstat |= 48; tspr->picnum = tiletovox[tspr->picnum];
2004
                break;
2005
            }
4555 hendricks2 2006
 
5327 hendricks2 2007
        k = statrate[tspr->statnum];
2008
        if (k >= 0)  //Interpolate moving sprite
2009
        {
2010
            ospr = &osprite[tspr->owner];
2011
            switch (k)
2012
            {
2013
            case 0: j = smoothratio; break;
2014
            case 1: j = (smoothratio>>1)+(((nummoves-tspr->owner)&1)<<15); break;
2015
            case 3: j = (smoothratio>>2)+(((nummoves-tspr->owner)&3)<<14); break;
2016
            case 7: j = (smoothratio>>3)+(((nummoves-tspr->owner)&7)<<13); break;
2017
            case 15: j = (smoothratio>>4)+(((nummoves-tspr->owner)&15)<<12); break;
2018
            }
2019
            k = tspr->x-ospr->x; tspr->x = ospr->x;
2020
            if (k != 0) tspr->x += mulscale16(k,j);
2021
            k = tspr->y-ospr->y; tspr->y = ospr->y;
2022
            if (k != 0) tspr->y += mulscale16(k,j);
2023
            k = tspr->z-ospr->z; tspr->z = ospr->z;
2024
            if (k != 0) tspr->z += mulscale16(k,j);
2025
        }
4555 hendricks2 2026
 
5327 hendricks2 2027
        //Don't allow close explosion sprites to be transluscent
2028
        k = tspr->statnum;
2029
        if ((k == 3) || (k == 4) || (k == 5) || (k == 7))
2030
            if (klabs(dax-tspr->x) < 256)
2031
                if (klabs(day-tspr->y) < 256)
2032
                    tspr->cstat &= ~2;
4555 hendricks2 2033
 
5327 hendricks2 2034
        tspr->shade += 6;
2035
        if (sector[tspr->sectnum].ceilingstat&1)
2036
            tspr->shade += sector[tspr->sectnum].ceilingshade;
2037
        else
2038
            tspr->shade += sector[tspr->sectnum].floorshade;
2039
    }
4555 hendricks2 2040
}
2041
 
2042
void tagcode(void)
2043
{
5738 hendricks2 2044
    int i, /*nexti,*/ j, k, l, s, /*daz, dax2, day2,*/ cnt, good;
5327 hendricks2 2045
    short startwall, endwall, dasector, p, oldang;
4555 hendricks2 2046
 
5327 hendricks2 2047
    for (p=connecthead; p>=0; p=connectpoint2[p])
2048
    {
2049
        if (sector[cursectnum[p]].lotag == 1)
2050
        {
2051
            activatehitag(sector[cursectnum[p]].hitag);
2052
            sector[cursectnum[p]].lotag = 0;
2053
            sector[cursectnum[p]].hitag = 0;
2054
        }
2055
        if ((sector[cursectnum[p]].lotag == 2) && (cursectnum[p] != ocursectnum[p]))
2056
            activatehitag(sector[cursectnum[p]].hitag);
2057
    }
4555 hendricks2 2058
 
5327 hendricks2 2059
    for (i=0; i<warpsectorcnt; i++)
2060
    {
2061
        dasector = warpsectorlist[i];
2062
        j = ((lockclock&127)>>2);
2063
        if (j >= 16) j = 31-j;
2064
        {
2065
            sector[dasector].ceilingshade = j;
2066
            sector[dasector].floorshade = j;
2067
            startwall = sector[dasector].wallptr;
2068
            endwall = startwall+sector[dasector].wallnum;
2069
            for (s=startwall; s<endwall; s++)
2070
                wall[s].shade = j;
2071
        }
2072
    }
4555 hendricks2 2073
 
5327 hendricks2 2074
    for (p=connecthead; p>=0; p=connectpoint2[p])
2075
        if (sector[cursectnum[p]].lotag == 10)  //warp sector
2076
        {
2077
            if (cursectnum[p] != ocursectnum[p])
2078
            {
2079
                warpsprite(playersprite[p]);
2080
                pos[p].x = sprite[playersprite[p]].x;
2081
                pos[p].y = sprite[playersprite[p]].y;
2082
                pos[p].z = sprite[playersprite[p]].z;
2083
                ang[p] = sprite[playersprite[p]].ang;
2084
                cursectnum[p] = sprite[playersprite[p]].sectnum;
4555 hendricks2 2085
 
5327 hendricks2 2086
                sprite[playersprite[p]].z += EYEHEIGHT;
4555 hendricks2 2087
 
5327 hendricks2 2088
                //warp(&pos[p].x,&pos[p].y,&pos[p].z,&ang[p],&cursectnum[p]);
2089
                //Update sprite representation of player
2090
                //setsprite_eyeheight(playersprite[p],&pos[p]);
2091
                //sprite[playersprite[p]].ang = ang[p];
2092
            }
2093
        }
4555 hendricks2 2094
 
5327 hendricks2 2095
    for (i=0; i<xpanningsectorcnt; i++) //animate wall x-panning sectors
2096
    {
2097
        dasector = xpanningsectorlist[i];
4555 hendricks2 2098
 
5327 hendricks2 2099
        startwall = sector[dasector].wallptr;
2100
        endwall = startwall+sector[dasector].wallnum;
2101
        for (s=startwall; s<endwall; s++)
2102
            wall[s].xpanning = ((lockclock>>2)&255);
2103
    }
4555 hendricks2 2104
 
5327 hendricks2 2105
    for (i=0; i<ypanningwallcnt; i++)
2106
        wall[ypanningwalllist[i]].ypanning = ~(lockclock&255);
4555 hendricks2 2107
 
5327 hendricks2 2108
    for (i=0; i<turnspritecnt; i++)
2109
    {
2110
        sprite[turnspritelist[i]].ang += (TICSPERFRAME<<2);
2111
        sprite[turnspritelist[i]].ang &= 2047;
2112
    }
4555 hendricks2 2113
 
5327 hendricks2 2114
    for (i=0; i<floorpanningcnt; i++) //animate floor of slime sectors
2115
    {
2116
        sector[floorpanninglist[i]].floorxpanning = ((lockclock>>2)&255);
2117
        sector[floorpanninglist[i]].floorypanning = ((lockclock>>2)&255);
2118
    }
4555 hendricks2 2119
 
5327 hendricks2 2120
    for (i=0; i<dragsectorcnt; i++)
2121
    {
2122
        dasector = dragsectorlist[i];
4555 hendricks2 2123
 
5327 hendricks2 2124
        startwall = sector[dasector].wallptr;
2125
        endwall = startwall+sector[dasector].wallnum;
4555 hendricks2 2126
 
5327 hendricks2 2127
        if (wall[startwall].x+dragxdir[i] < dragx1[i]) dragxdir[i] = 16;
2128
        if (wall[startwall].y+dragydir[i] < dragy1[i]) dragydir[i] = 16;
2129
        if (wall[startwall].x+dragxdir[i] > dragx2[i]) dragxdir[i] = -16;
2130
        if (wall[startwall].y+dragydir[i] > dragy2[i]) dragydir[i] = -16;
4555 hendricks2 2131
 
5327 hendricks2 2132
        for (j=startwall; j<endwall; j++)
2133
            dragpoint(j,wall[j].x+dragxdir[i],wall[j].y+dragydir[i],0);
2134
        j = sector[dasector].floorz;
2135
        sector[dasector].floorz = dragfloorz[i]+(sintable[(lockclock<<4)&2047]>>3);
4555 hendricks2 2136
 
5327 hendricks2 2137
        for (p=connecthead; p>=0; p=connectpoint2[p])
2138
            if (cursectnum[p] == dasector)
2139
            {
2140
                pos[p].x += dragxdir[i];
2141
                pos[p].y += dragydir[i];
2142
                if (p == myconnectindex)
2143
                { my.x += dragxdir[i]; my.y += dragydir[i]; }
2144
                //pos[p].z += (sector[dasector].floorz-j);
4555 hendricks2 2145
 
5327 hendricks2 2146
                //Update sprite representation of player
2147
                setsprite_eyeheight(playersprite[p],&pos[p]);
2148
                sprite[playersprite[p]].ang = ang[p];
2149
            }
2150
    }
4555 hendricks2 2151
 
5327 hendricks2 2152
    for (i=0; i<swingcnt; i++)
2153
    {
2154
        if (swinganginc[i] != 0)
2155
        {
2156
            oldang = swingang[i];
2157
            for (j=0; j<(TICSPERFRAME<<2); j++)
2158
            {