Subversion Repositories eduke32

Rev

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