summaryrefslogtreecommitdiffstats
path: root/apps/plugins/sdl/progs/duke3d/Game/src/game.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/sdl/progs/duke3d/Game/src/game.c')
-rw-r--r--apps/plugins/sdl/progs/duke3d/Game/src/game.c10966
1 files changed, 10966 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/duke3d/Game/src/game.c b/apps/plugins/sdl/progs/duke3d/Game/src/game.c
new file mode 100644
index 0000000000..303ac56ea9
--- /dev/null
+++ b/apps/plugins/sdl/progs/duke3d/Game/src/game.c
@@ -0,0 +1,10966 @@
+//-------------------------------------------------------------------------
+/*
+ Copyright (C) 1996, 2003 - 3D Realms Entertainment
+
+ This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
+
+ Duke Nukem 3D is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ aint32_t with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ Original Source: 1996 - Todd Replogle
+ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
+*/
+//-------------------------------------------------------------------------
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include "SDL.h"
+#endif
+
+#include "types.h"
+
+#include "develop.h"
+#include "scriplib.h"
+#include "file_lib.h"
+#include "gamedefs.h"
+#include "keyboard.h"
+#include "util_lib.h"
+#include "function.h"
+#include "control.h"
+#include "sounds.h"
+#include "config.h"
+#include "audiolib/sndcards.h"
+
+#include "duke3d.h"
+
+#include "console.h"
+#include "cvars.h"
+#include "cvar_defs.h"
+
+#include "global.h"
+
+
+#define MINITEXT_BLUE 0
+#define MINITEXT_RED 2
+#define MINITEXT_YELLOW 23
+#define MINITEXT_GRAY 17
+
+#define COLOR_ON MINITEXT_YELLOW
+#define COLOR_OFF MINITEXT_BLUE
+
+#define IDFSIZE 479985668
+// #define IDFSIZE 9961476
+// #define IDFSIZE 16384
+#define IDFILENAME "DUKE3D.IDF"
+
+#define TIMERUPDATESIZ 32
+
+int32_t cameradist = 0, cameraclock = 0;
+uint8_t eightytwofifty = 0;
+uint8_t playerswhenstarted;
+uint8_t qe,cp;
+
+uint8_t nHostForceDisableAutoaim = 0;
+
+// Game play speed
+int g_iTickRate = 120;
+int g_iTicksPerFrame = 26;
+
+int32 CommandSoundToggleOff = 0;
+int32 CommandMusicToggleOff = 0;
+
+// For addfaz's stun server. use /stun to activate
+uint16_t g_bStun = 0;
+
+char confilename[128] = {"GAME.CON"};
+char boardfilename[128] = {0};
+uint8_t waterpal[768], slimepal[768], titlepal[768], drealms[768], endingpal[768];
+char firstdemofile[80] = { '\0' };
+
+#define patchstatusbar(x1,y1,x2,y2) \
+ { \
+ rotatesprite(0,(200-34)<<16,65536L,0,BOTTOMSTATUSBAR,4,0,10+16+64+128, \
+ scale(x1,xdim,320),scale(y1,ydim,200), \
+ scale(x2,xdim,320)-1,scale(y2,ydim,200)-1); \
+ }
+
+void newint24( int errval, int ax, int bp, int si );
+
+int recfilep,totalreccnt;
+uint8_t debug_on = 0,actor_tog = 0,memorycheckoveride=0;
+uint8_t *rtsptr;
+
+
+extern uint8_t syncstate;
+extern int32 numlumps;
+
+FILE *frecfilep = (FILE *)NULL;
+void pitch_test( void );
+
+uint8_t restorepalette,screencapt,nomorelogohack;
+int sendmessagecommand = -1;
+
+#if PLATFORM_DOS
+task *TimerPtr=NULL;
+#endif
+
+extern int32_t lastvisinc;
+
+// Build Engine port implements this. --ryan.
+#if PLATFORM_DOS
+static void timerhandler(task *unused)
+{
+ totalclock++;
+}
+
+void inittimer()
+{
+ TimerPtr = TS_ScheduleTask( timerhandler,TICRATE, 1, NULL );
+ TS_Dispatch();
+}
+
+void uninittimer(void)
+{
+ if (TimerPtr)
+ TS_Terminate( TimerPtr );
+ TimerPtr = NULL;
+ TS_Shutdown();
+}
+#else
+void timerhandler(void)
+{
+ totalclock++;
+}
+#endif
+
+int gametext(int x,int y,char *t,uint8_t s,short dabits)
+{
+ short ac,newx;
+ char* oldt;
+ uint8_t centre;
+
+ centre = ( x == (320>>1) );
+ newx = 0;
+ oldt = t;
+
+ if(centre)
+ {
+ while(*t)
+ {
+ if(*t == 32) {newx+=5;t++;continue;}
+ else ac = *t - '!' + STARTALPHANUM;
+
+ if( ac < STARTALPHANUM || ac > ENDALPHANUM ) break;
+
+ if(*t >= '0' && *t <= '9')
+ newx += 8;
+ else newx += tiles[ac].dim.width;
+ t++;
+ }
+
+ t = oldt;
+ x = (320>>1)-(newx>>1);
+ }
+
+ while(*t)
+ {
+ if(*t == 32) {x+=5;t++;continue;}
+ else ac = *t - '!' + STARTALPHANUM;
+
+ if( ac < STARTALPHANUM || ac > ENDALPHANUM )
+ break;
+
+ rotatesprite(x<<16,y<<16,65536L,0,ac,s,0,dabits,0,0,xdim-1,ydim-1);
+
+ if(*t >= '0' && *t <= '9')
+ x += 8;
+ else x += tiles[ac].dim.width;
+
+ t++;
+ }
+
+ return (x);
+}
+
+int gametextpal(int x,int y,char *t,uint8_t s,uint8_t p)
+{
+ short ac,newx;
+ uint8_t centre;
+ char* oldt;
+
+ centre = ( x == (320>>1) );
+ newx = 0;
+ oldt = t;
+
+ if(centre)
+ {
+ while(*t)
+ {
+ if(*t == 32) {newx+=5;t++;continue;}
+ else ac = *t - '!' + STARTALPHANUM;
+
+ if( ac < STARTALPHANUM || ac > ENDALPHANUM ) break;
+
+ if(*t >= '0' && *t <= '9')
+ newx += 8;
+ else newx += tiles[ac].dim.width;
+ t++;
+ }
+
+ t = oldt;
+ x = (320>>1)-(newx>>1);
+ }
+
+ while(*t)
+ {
+ if(*t == 32) {x+=5;t++;continue;}
+ else ac = *t - '!' + STARTALPHANUM;
+
+ if( ac < STARTALPHANUM || ac > ENDALPHANUM )
+ break;
+
+ rotatesprite(x<<16,y<<16,65536L,0,ac,s,p,2+8+16,0,0,xdim-1,ydim-1);
+ if(*t >= '0' && *t <= '9')
+ x += 8;
+ else x += tiles[ac].dim.width;
+
+ t++;
+ }
+
+ return (x);
+}
+
+int gametextpart(int x,int y,char *t,uint8_t s,short p)
+{
+ short ac,newx, cnt;
+ uint8_t centre;
+ char * oldt;
+
+ centre = ( x == (320>>1) );
+ newx = 0;
+ oldt = t;
+ cnt = 0;
+
+ if(centre)
+ {
+ while(*t)
+ {
+ if(cnt == p) break;
+
+ if(*t == 32) {newx+=5;t++;continue;}
+ else ac = *t - '!' + STARTALPHANUM;
+
+ if( ac < STARTALPHANUM || ac > ENDALPHANUM ) break;
+
+ newx += tiles[ac].dim.width;
+ t++;
+ cnt++;
+
+ }
+
+ t = oldt;
+ x = (320>>1)-(newx>>1);
+ }
+
+ cnt = 0;
+ while(*t)
+ {
+ if(*t == 32) {x+=5;t++;continue;}
+ else ac = *t - '!' + STARTALPHANUM;
+
+ if( ac < STARTALPHANUM || ac > ENDALPHANUM ) break;
+
+ if(cnt == p)
+ {
+ rotatesprite(x<<16,y<<16,65536L,0,ac,s,1,2+8+16,0,0,xdim-1,ydim-1);
+ break;
+ }
+ else
+ rotatesprite(x<<16,y<<16,65536L,0,ac,s,0,2+8+16,0,0,xdim-1,ydim-1);
+
+ x += tiles[ac].dim.width;
+
+ t++;
+ cnt++;
+ }
+
+ return (x);
+}
+
+int minitext(int x,int y,char *str,uint8_t p,uint8_t sb)
+{
+ short ac;
+ char buf[128];
+ char *t;
+
+ strncpy (buf, str, 128);
+ buf[127] = 0;
+ t = buf;
+
+ while(*t)
+ {
+ *t = toupper(*t);
+ if(*t == 32) {x+=5;t++;continue;}
+ else ac = *t - '!' + MINIFONT;
+
+ rotatesprite(x<<16,y<<16,65536L,0,ac,0,p,sb,0,0,xdim-1,ydim-1);
+ x += 4; // tilesizx[ac]+1;
+
+ t++;
+ }
+ return (x);
+}
+
+int minitextshade(int x,int y,char *str,uint8_t s,uint8_t p,uint8_t sb)
+{
+ short ac;
+ char buf[128];
+ char *t;
+
+ strncpy (buf, str, 128);
+ buf[127] = 0;
+ t = buf;
+
+ while(*t)
+ {
+ *t = toupper(*t);
+ if(*t == 32) {x+=5;t++;continue;}
+ else ac = *t - '!' + MINIFONT;
+
+ rotatesprite(x<<16,y<<16,65536L,0,ac,s,p,sb,0,0,xdim-1,ydim-1);
+ x += 4; // tilesizx[ac]+1;
+
+ t++;
+ }
+ return (x);
+}
+
+void gamenumber(int32_t x,int32_t y,int32_t n,uint8_t s)
+{
+ char b[10];
+
+
+ //
+ // uint8_t * ltoa(int32_t l, uint8_t * buffer, int radix);
+ // is NON-STANDARD and equivalent to STANDARD
+ // (void) sprintf(buffer, "%ld", l);
+ //ltoa(n,b,10);
+ sprintf(b,"%d",n);
+ gametext(x,y,b,s,2+8+16);
+}
+
+
+char recbuf[80];
+void allowtimetocorrecterrorswhenquitting(void)
+{
+ int32_t i, j, oldtotalclock;
+
+ ready2send = 0;
+
+ for(j=0;j<8;j++)
+ {
+ oldtotalclock = totalclock;
+
+ while (totalclock < oldtotalclock+TICSPERFRAME)
+ getpackets();
+
+ if(KB_KeyPressed(sc_Escape)) return;
+
+ packbuf[0] = 127;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i != myconnectindex)
+ sendpacket(i,packbuf,1);
+ }
+}
+
+#define MAXUSERQUOTES 4
+int32_t quotebot, quotebotgoal;
+short user_quote_time[MAXUSERQUOTES];
+char user_quote[MAXUSERQUOTES][128];
+// uint8_t typebuflen,typebuf[41];
+
+static void adduserquote(char *daquote)
+{
+ int32_t i;
+
+ for(i=MAXUSERQUOTES-1;i>0;i--)
+ {
+ strcpy(user_quote[i],user_quote[i-1]);
+ user_quote_time[i] = user_quote_time[i-1];
+ }
+ strcpy(user_quote[0],daquote);
+ user_quote_time[0] = 180;
+ pub = NUMPAGES;
+}
+
+char *grpVersion2char_from_crc(unsigned int crc32_grp_to_identify)
+{
+ char *id;
+ int i=0;
+
+ id = crc32lookup[MAX_KNOWN_GRP].name; // unknown version
+
+ for(i=0; i<MAX_KNOWN_GRP; i++)
+ {
+ if(crc32lookup[i].crc32==crc32_grp_to_identify)
+ id = crc32lookup[i].name;
+ }
+
+ return(id);
+}
+
+char *grpVersion2char(uint8_t grp_to_identify)
+{
+ char *id;
+
+ switch(grp_to_identify)
+ {
+ case DUKEITOUTINDC_GRP:
+ id = "v1.5 DC PACK";
+ break;
+ case SHAREWARE_GRP13:
+ id = "v1.3 SHAREW.";
+ break;
+ case ATOMIC_GRP14_15:
+ id = "v1.5 ATOMIC";
+ break;
+ case REGULAR_GRP13D:
+ id = "v1.3D FULL";
+ break;
+ case UNKNOWN_GRP:
+ id = "vX.X UNKNOWN";
+ break;
+ default:
+ Error(EXIT_FAILURE,"Failed the GRP Identification\n");
+ break;
+ }
+
+ return(id);
+}
+
+//This is a function from the Engine module, used in getpackets.
+void sampletimer(void);
+
+void getpackets(void)
+{
+ int32_t i, j, k, l;
+ short other, packbufleng;
+ input *osyn, *nsyn;
+
+ sampletimer();
+ if(qe == 0 && KB_KeyPressed(sc_LeftControl) && KB_KeyPressed(sc_LeftAlt) && KB_KeyPressed(sc_Delete))
+ {
+ qe = 1;
+ gameexit("Quick Exit.");
+ }
+
+ // not a net game
+ if (numplayers < 2)
+ {
+ //printf("getpackets() numplayers < 2");
+ return;
+ }
+
+ while ((packbufleng = getpacket(&other,packbuf)) > 0)
+ {
+#ifdef _DEBUG_NETWORKING_
+ printf("RECEIVED PACKET: type: %d : len %d\n", packbuf[0], packbufleng);
+#endif
+
+ switch(packbuf[0])
+ {
+ case 253:
+ // This should have already been handled by mmulti.cpp so ignore it
+ printf("Invalid Packet: %d", packbuf[0]);
+ break;
+
+ case 125:
+ cp = 0;
+ break;
+
+ case 126:
+ multiflag = 2;
+ multiwhat = 0;
+ multiwho = other;
+ multipos = packbuf[1];
+ loadplayer( multipos );
+ multiflag = 0;
+ break;
+ case 0: //[0] (receive master sync buffer)
+ j = 1;
+
+ if ((movefifoend[other]&(TIMERUPDATESIZ-1)) == 0)
+ for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
+ {
+ if (playerquitflag[i] == 0) continue;
+ if (i == myconnectindex)
+ otherminlag = (int32_t)((int8_t )packbuf[j]);
+ j++;
+ }
+
+ osyn = (input *)&inputfifo[(movefifoend[connecthead]-1)&(MOVEFIFOSIZ-1)][0];
+ nsyn = (input *)&inputfifo[(movefifoend[connecthead])&(MOVEFIFOSIZ-1)][0];
+
+ k = j;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ j += playerquitflag[i];
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if (playerquitflag[i] == 0) continue;
+
+ l = packbuf[k++];
+ if (i == myconnectindex)
+ { j += ((l&1)<<1)+(l&2)+((l&4)>>2)+((l&8)>>3)+((l&16)>>4)+((l&32)>>5)+((l&64)>>6)+((l&128)>>7); continue; }
+
+ copybufbyte(&osyn[i],&nsyn[i],sizeof(input));
+ if (l&1) nsyn[i].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2;
+ if (l&2) nsyn[i].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2;
+ if (l&4) nsyn[i].avel = (int8_t )packbuf[j++];
+ if (l&8) nsyn[i].bits = ((nsyn[i].bits&0xffffff00)|((int32_t)packbuf[j++]));
+ if (l&16) nsyn[i].bits = ((nsyn[i].bits&0xffff00ff)|((int32_t)packbuf[j++])<<8);
+ if (l&32) nsyn[i].bits = ((nsyn[i].bits&0xff00ffff)|((int32_t)packbuf[j++])<<16);
+ if (l&64) nsyn[i].bits = ((nsyn[i].bits&0x00ffffff)|((int32_t)packbuf[j++])<<24);
+ if (l&128) nsyn[i].horz = (int8_t )packbuf[j++];
+
+ if (nsyn[i].bits&(1<<26)) playerquitflag[i] = 0;
+ movefifoend[i]++;
+ }
+
+ while (j != packbufleng)
+ {
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if(i != myconnectindex)
+ {
+ syncval[i][syncvalhead[i]&(MOVEFIFOSIZ-1)] = packbuf[j];
+ syncvalhead[i]++;
+ }
+ j++;
+ }
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i != myconnectindex)
+ for(j=1;j<movesperpacket;j++)
+ {
+ copybufbyte(&nsyn[i],&inputfifo[movefifoend[i]&(MOVEFIFOSIZ-1)][i],sizeof(input));
+ movefifoend[i]++;
+ }
+
+ movefifosendplc += movesperpacket;
+
+ break;
+ case 1: //[1] (receive slave sync buffer)
+ j = 2; k = packbuf[1];
+
+ osyn = (input *)&inputfifo[(movefifoend[other]-1)&(MOVEFIFOSIZ-1)][0];
+ nsyn = (input *)&inputfifo[(movefifoend[other])&(MOVEFIFOSIZ-1)][0];
+
+ copybufbyte(&osyn[other],&nsyn[other],sizeof(input));
+ if (k&1) nsyn[other].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2;
+ if (k&2) nsyn[other].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2;
+ if (k&4) nsyn[other].avel = (int8_t )packbuf[j++];
+ if (k&8) nsyn[other].bits = ((nsyn[other].bits&0xffffff00)|((int32_t)packbuf[j++]));
+ if (k&16) nsyn[other].bits = ((nsyn[other].bits&0xffff00ff)|((int32_t)packbuf[j++])<<8);
+ if (k&32) nsyn[other].bits = ((nsyn[other].bits&0xff00ffff)|((int32_t)packbuf[j++])<<16);
+ if (k&64) nsyn[other].bits = ((nsyn[other].bits&0x00ffffff)|((int32_t)packbuf[j++])<<24);
+ if (k&128) nsyn[other].horz = (int8_t )packbuf[j++];
+ movefifoend[other]++;
+
+ while (j != packbufleng)
+ {
+ syncval[other][syncvalhead[other]&(MOVEFIFOSIZ-1)] = packbuf[j++];
+ syncvalhead[other]++;
+ }
+
+ for(i=1;i<movesperpacket;i++)
+ {
+ copybufbyte(&nsyn[other],&inputfifo[movefifoend[other]&(MOVEFIFOSIZ-1)][other],sizeof(input));
+ movefifoend[other]++;
+ }
+
+ break;
+
+ case 4: // message talk T
+ strcpy(recbuf,(char*)packbuf+1);
+ recbuf[packbufleng-1] = 0;
+
+ adduserquote(recbuf);
+ sound(EXITMENUSOUND);
+
+ pus = NUMPAGES;
+ pub = NUMPAGES;
+
+ break;
+
+ case 5:
+ ud.m_level_number = ud.level_number = packbuf[1];
+ ud.m_volume_number = ud.volume_number = packbuf[2];
+ ud.m_player_skill = ud.player_skill = packbuf[3];
+ ud.m_monsters_off = ud.monsters_off = packbuf[4];
+ ud.m_respawn_monsters = ud.respawn_monsters = packbuf[5];
+ ud.m_respawn_items = ud.respawn_items = packbuf[6];
+ ud.m_respawn_inventory = ud.respawn_inventory = packbuf[7];
+ ud.m_coop = packbuf[8];
+ ud.m_marker = ud.marker = packbuf[9];
+ ud.m_ffire = ud.ffire = packbuf[10];
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ resetweapons(i);
+ resetinventory(i);
+ }
+
+ newgame(ud.volume_number,ud.level_number,ud.player_skill);
+ ud.coop = ud.m_coop;
+
+ enterlevel(MODE_GAME);
+
+ break;
+
+ case 6: // get names
+ for (i=2;packbuf[i] && i<=11;i++) // limit size of name
+ ud.user_name[other][i-2] = packbuf[i];
+ ud.user_name[other][i-2] = 0;
+
+ // we allow the old rancidmeat 19.1 to connect, using the old grpVersion system w/ BYTEVERSION
+ if(packbuf[1] == BYTEVERSION_27 || packbuf[1] == BYTEVERSION_117)
+ {
+ // Old rancid was using either BYTEVERSION_27 or BYTEVERSION_117
+ Error(EXIT_SUCCESS, "STOP: Your opponent is using an obsolete version\n"
+ "Please ask him to update to xDuke v%d.%d!\n", CHOCOLATE_DUKE_REV_X, CHOCOLATE_DUKE_REV_DOT_Y);
+ }
+ break;
+
+ case 9:
+ for (i=1;i<packbufleng;i++)
+ ud.wchoice[other][i-1] = packbuf[i];
+ break;
+
+ case 7:
+
+ if(numlumps == 0) break;
+
+ if (SoundToggle == 0 || ud.lockout == 1 || FXDevice == NumSoundCards)
+ break;
+ rtsptr = RTS_GetSound(packbuf[1]-1);
+ if (*rtsptr == 'C')
+ FX_PlayVOC3D(rtsptr,0,0,0,255,-packbuf[1]);
+ else
+ FX_PlayWAV3D(rtsptr,0,0,0,255,-packbuf[1]);
+ rtsplaying = 7;
+ break;
+ case 8:
+ ud.m_level_number = ud.level_number = packbuf[1];
+ ud.m_volume_number = ud.volume_number = packbuf[2];
+ ud.m_player_skill = ud.player_skill = packbuf[3];
+ ud.m_monsters_off = ud.monsters_off = packbuf[4];
+ ud.m_respawn_monsters = ud.respawn_monsters = packbuf[5];
+ ud.m_respawn_items = ud.respawn_items = packbuf[6];
+ ud.m_respawn_inventory = ud.respawn_inventory = packbuf[7];
+ ud.m_coop = ud.coop = packbuf[8];
+ ud.m_marker = ud.marker = packbuf[9];
+ ud.m_ffire = ud.ffire = packbuf[10];
+
+ copybufbyte(packbuf+10,boardfilename,packbufleng-11);
+ boardfilename[packbufleng-11] = 0;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ resetweapons(i);
+ resetinventory(i);
+ }
+
+ newgame(ud.volume_number,ud.level_number,ud.player_skill);
+ enterlevel(MODE_GAME);
+ break;
+
+ case 16:
+ movefifoend[other] = movefifoplc = movefifosendplc = fakemovefifoplc = 0;
+ syncvalhead[other] = syncvaltottail = 0L;
+
+ case 17:
+ j = 1;
+
+ if ((movefifoend[other]&(TIMERUPDATESIZ-1)) == 0)
+ if (other == connecthead)
+ for(i=connectpoint2[connecthead]; i>=0; i=connectpoint2[i])
+ {
+ if (i == myconnectindex)
+ {
+ otherminlag = (int32_t)((int8_t )packbuf[j]);
+ }
+
+ j++;
+ }
+
+ osyn = (input *)&inputfifo[(movefifoend[other]-1)&(MOVEFIFOSIZ-1)][0];
+ nsyn = (input *)&inputfifo[(movefifoend[other])&(MOVEFIFOSIZ-1)][0];
+
+ copybufbyte(&osyn[other],&nsyn[other],sizeof(input));
+ k = packbuf[j++];
+ if (k&1) nsyn[other].fvel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2;
+ if (k&2) nsyn[other].svel = packbuf[j]+((short)packbuf[j+1]<<8), j += 2;
+ if (k&4) nsyn[other].avel = (int8_t )packbuf[j++];
+ if (k&8) nsyn[other].bits = ((nsyn[other].bits&0xffffff00)|((int32_t)packbuf[j++]));
+ if (k&16) nsyn[other].bits = ((nsyn[other].bits&0xffff00ff)|((int32_t)packbuf[j++])<<8);
+ if (k&32) nsyn[other].bits = ((nsyn[other].bits&0xff00ffff)|((int32_t)packbuf[j++])<<16);
+ if (k&64) nsyn[other].bits = ((nsyn[other].bits&0x00ffffff)|((int32_t)packbuf[j++])<<24);
+ if (k&128) nsyn[other].horz = (int8_t )packbuf[j++];
+ movefifoend[other]++;
+
+ for(i=1;i<movesperpacket;i++)
+ {
+ copybufbyte(&nsyn[other],&inputfifo[movefifoend[other]&(MOVEFIFOSIZ-1)][other],sizeof(input));
+ movefifoend[other]++;
+ }
+
+ if (j > packbufleng)
+ {
+ printf("INVALID GAME PACKET!!! (%d too many bytes) (j= %d, packbuflen= %d, type: %d)\n",j-packbufleng, j, packbufleng, packbuf[0]);
+ }
+
+ while (j != packbufleng)
+ {
+ syncval[other][syncvalhead[other]&(MOVEFIFOSIZ-1)] = packbuf[j++];
+ syncvalhead[other]++;
+ }
+
+ break;
+ case 127:
+ break;
+
+#ifdef CHECK_XDUKE_REV
+ case 131: // xDuke Rev ID
+ memcpy(ud.rev[other], packbuf, 10);
+ break;
+#endif
+
+ case 132: // get map CRC of opponents (to debug out of synch)
+ ud.mapCRC[other] = (uint16_t)packbuf[1] + (uint16_t)(packbuf[2]<<8);
+ break;
+
+ case 133: // client refused to disable the autoaim by host
+
+ Error(EXIT_SUCCESS, "One or more players refused to play with AutoAim OFF because this breaks\n"
+ "the official Duke's gameplay. Please restart without this option...\n");
+
+ break;
+
+ case 134: // Get GRP CRC32 + Con size + exeCRC + conCRC
+ memcpy(ud.groupefil_crc32[other], packbuf+1, sizeof(groupefil_crc32));
+ memcpy(ud.conSize+other, packbuf+1+sizeof(groupefil_crc32), sizeof(ud.conSize[0]));
+ memcpy(ud.conCRC+other, packbuf+1+sizeof(groupefil_crc32)+sizeof(ud.conSize[0]), sizeof(ud.conCRC[0]));
+ memcpy(ud.exeCRC+other, packbuf+1+sizeof(groupefil_crc32)+sizeof(ud.conSize[0])+sizeof(ud.conCRC[0]), sizeof(ud.exeCRC[0]));
+ break;
+
+ case 250:
+ {
+ playerreadyflag[other]++;
+ printf("Player %d '%s' is ready...\n", other, ud.user_name[other]);
+ }
+ break;
+ case 255:
+ gameexitanycase();
+ break;
+ }
+ }
+ rb->yield();
+}
+
+//From player.c
+void computergetinput(int32_t snum, input *syn);
+void faketimerhandler()
+{
+ int32_t i, j, k;
+ input *osyn, *nsyn;
+
+ //Check if we should quit the game.
+ if ((qe == 0 && KB_KeyPressed(sc_LeftControl) && KB_KeyPressed(sc_LeftAlt) && KB_KeyPressed(sc_Delete)) ||
+ (qe == 0 && KB_KeyPressed(sc_LeftAlt) && KB_KeyPressed(sc_F4)))
+ {
+ qe = 1;
+ gameexit("Quick Exit.");
+ }
+
+ //Has it been 120ticks ?
+ if ((totalclock < ototalclock+TICSPERFRAME) || (ready2send == 0))
+ return; // Returns here when playing a demo.
+
+ //YES : Add 120tick
+ ototalclock += TICSPERFRAME;
+
+ //Check network stuff.
+ getpackets();
+ if (getoutputcirclesize() >= 16)
+ return;
+
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i != myconnectindex)
+ if (movefifoend[i] < movefifoend[myconnectindex]-200)
+ return;
+
+ if( !CONSOLE_IsActive())
+ {
+ getinput(myconnectindex);
+ }
+
+ avgfvel += loc.fvel; // x
+ avgsvel += loc.svel; // y
+ avgavel += loc.avel;
+ avghorz += loc.horz;
+ avgbits |= loc.bits;
+ if (movefifoend[myconnectindex]&(movesperpacket-1))
+ {
+ copybufbyte(&inputfifo[(movefifoend[myconnectindex]-1)&(MOVEFIFOSIZ-1)][myconnectindex],
+ &inputfifo[movefifoend[myconnectindex]&(MOVEFIFOSIZ-1)][myconnectindex],sizeof(input));
+ movefifoend[myconnectindex]++;
+ return;
+ }
+
+ nsyn = &inputfifo[movefifoend[myconnectindex]&(MOVEFIFOSIZ-1)][myconnectindex];
+ nsyn[0].fvel = avgfvel/movesperpacket;
+ nsyn[0].svel = avgsvel/movesperpacket;
+ nsyn[0].avel = avgavel/movesperpacket;
+ nsyn[0].horz = avghorz/movesperpacket;
+ nsyn[0].bits = avgbits;
+ avgfvel = avgsvel = avgavel = avghorz = avgbits = 0;
+ movefifoend[myconnectindex]++;
+
+ if (numplayers < 2)
+ {
+ if (ud.multimode > 1) for(i=connecthead;i>=0;i=connectpoint2[i])
+ if(i != myconnectindex)
+ {
+ //clearbufbyte(&inputfifo[movefifoend[i]&(MOVEFIFOSIZ-1)][i],sizeof(input),0L);
+ if(ud.playerai)
+ computergetinput(i,&inputfifo[movefifoend[i]&(MOVEFIFOSIZ-1)][i]);
+ movefifoend[i]++;
+ }
+ return;
+ }
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i != myconnectindex)
+ {
+ k = (movefifoend[myconnectindex]-1)-movefifoend[i];
+ myminlag[i] = min(myminlag[i],k);
+ mymaxlag = max(mymaxlag,k);
+ }
+
+ if (((movefifoend[myconnectindex]-1)&(TIMERUPDATESIZ-1)) == 0)
+ {
+ i = mymaxlag-bufferjitter; mymaxlag = 0;
+ if (i > 0) bufferjitter += ((3+i)>>2);
+ else if (i < 0) bufferjitter -= ((1-i)>>2);
+ }
+
+ if (networkmode == 1)
+ {
+ packbuf[0] = 17;
+
+ if ((movefifoend[myconnectindex]-1) == 0)
+ {
+ packbuf[0] = 16;
+ }
+
+ j = 1;
+
+ //Fix timers and buffer/jitter value
+ if (((movefifoend[myconnectindex]-1)&(TIMERUPDATESIZ-1)) == 0)
+ {
+ if (myconnectindex != connecthead)
+ {
+ i = myminlag[connecthead]-otherminlag;
+ if (klabs(i) > 8)
+ {
+ i >>= 1;
+ }
+ else
+ if (klabs(i) > 2)
+ {
+ i = ksgn(i);
+ }
+ else
+ {
+ i = 0;
+ }
+
+ totalclock -= TICSPERFRAME*i;
+ myminlag[connecthead] -= i; otherminlag += i;
+ }
+
+ if (myconnectindex == connecthead)
+ for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
+ packbuf[j++] = min(max(myminlag[i],-128),127);
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ myminlag[i] = 0x7fffffff;
+ }
+
+ osyn = (input *)&inputfifo[(movefifoend[myconnectindex]-2)&(MOVEFIFOSIZ-1)][myconnectindex];
+ nsyn = (input *)&inputfifo[(movefifoend[myconnectindex]-1)&(MOVEFIFOSIZ-1)][myconnectindex];
+
+ k = j;
+ packbuf[j++] = 0;
+
+ if (nsyn[0].fvel != osyn[0].fvel)
+ {
+ packbuf[j++] = (uint8_t )nsyn[0].fvel;
+ packbuf[j++] = (uint8_t )(nsyn[0].fvel>>8);
+ packbuf[k] |= 1;
+ }
+ if (nsyn[0].svel != osyn[0].svel)
+ {
+ packbuf[j++] = (uint8_t )nsyn[0].svel;
+ packbuf[j++] = (uint8_t )(nsyn[0].svel>>8);
+ packbuf[k] |= 2;
+ }
+ if (nsyn[0].avel != osyn[0].avel)
+ {
+ packbuf[j++] = (int8_t )nsyn[0].avel;
+ packbuf[k] |= 4;
+ }
+ if ((nsyn[0].bits^osyn[0].bits)&0x000000ff) packbuf[j++] = (nsyn[0].bits&255), packbuf[k] |= 8;
+ if ((nsyn[0].bits^osyn[0].bits)&0x0000ff00) packbuf[j++] = ((nsyn[0].bits>>8)&255), packbuf[k] |= 16;
+ if ((nsyn[0].bits^osyn[0].bits)&0x00ff0000) packbuf[j++] = ((nsyn[0].bits>>16)&255), packbuf[k] |= 32;
+ if ((nsyn[0].bits^osyn[0].bits)&0xff000000) packbuf[j++] = ((nsyn[0].bits>>24)&255), packbuf[k] |= 64;
+ if (nsyn[0].horz != osyn[0].horz)
+ {
+ packbuf[j++] = (uint8_t )nsyn[0].horz;
+ packbuf[k] |= 128;
+ }
+
+ while (syncvalhead[myconnectindex] != syncvaltail)
+ {
+ packbuf[j++] = syncval[myconnectindex][syncvaltail&(MOVEFIFOSIZ-1)];
+ syncvaltail++;
+ }
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i != myconnectindex)
+ sendpacket(i,packbuf,j);
+
+ return;
+ }
+ if (myconnectindex != connecthead) //Slave
+ {
+ //Fix timers and buffer/jitter value
+ if (((movefifoend[myconnectindex]-1)&(TIMERUPDATESIZ-1)) == 0)
+ {
+ i = myminlag[connecthead]-otherminlag;
+ if (klabs(i) > 8) i >>= 1;
+ else if (klabs(i) > 2) i = ksgn(i);
+ else i = 0;
+
+ totalclock -= TICSPERFRAME*i;
+ myminlag[connecthead] -= i; otherminlag += i;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ myminlag[i] = 0x7fffffff;
+ }
+
+ packbuf[0] = 1; packbuf[1] = 0; j = 2;
+
+ osyn = (input *)&inputfifo[(movefifoend[myconnectindex]-2)&(MOVEFIFOSIZ-1)][myconnectindex];
+ nsyn = (input *)&inputfifo[(movefifoend[myconnectindex]-1)&(MOVEFIFOSIZ-1)][myconnectindex];
+
+ if (nsyn[0].fvel != osyn[0].fvel)
+ {
+ packbuf[j++] = (uint8_t )nsyn[0].fvel;
+ packbuf[j++] = (uint8_t )(nsyn[0].fvel>>8);
+ packbuf[1] |= 1;
+ }
+ if (nsyn[0].svel != osyn[0].svel)
+ {
+ packbuf[j++] = (uint8_t )nsyn[0].svel;
+ packbuf[j++] = (uint8_t )(nsyn[0].svel>>8);
+ packbuf[1] |= 2;
+ }
+ if (nsyn[0].avel != osyn[0].avel)
+ {
+ packbuf[j++] = (int8_t )nsyn[0].avel;
+ packbuf[1] |= 4;
+ }
+ if ((nsyn[0].bits^osyn[0].bits)&0x000000ff) packbuf[j++] = (nsyn[0].bits&255), packbuf[1] |= 8;
+ if ((nsyn[0].bits^osyn[0].bits)&0x0000ff00) packbuf[j++] = ((nsyn[0].bits>>8)&255), packbuf[1] |= 16;
+ if ((nsyn[0].bits^osyn[0].bits)&0x00ff0000) packbuf[j++] = ((nsyn[0].bits>>16)&255), packbuf[1] |= 32;
+ if ((nsyn[0].bits^osyn[0].bits)&0xff000000) packbuf[j++] = ((nsyn[0].bits>>24)&255), packbuf[1] |= 64;
+ if (nsyn[0].horz != osyn[0].horz)
+ {
+ packbuf[j++] = (uint8_t )nsyn[0].horz;
+ packbuf[1] |= 128;
+ }
+
+ while (syncvalhead[myconnectindex] != syncvaltail)
+ {
+ packbuf[j++] = syncval[myconnectindex][syncvaltail&(MOVEFIFOSIZ-1)];
+ syncvaltail++;
+ }
+
+ sendpacket(connecthead,packbuf,j);
+ return;
+ }
+
+ //This allows allow packet-resends
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (movefifoend[i] <= movefifosendplc)
+ {
+ packbuf[0] = 127;
+ for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
+ sendpacket(i,packbuf,1);
+ return;
+ }
+
+ while (1) //Master
+ {
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (playerquitflag[i] && (movefifoend[i] <= movefifosendplc)) return;
+
+ osyn = (input *)&inputfifo[(movefifosendplc-1)&(MOVEFIFOSIZ-1)][0];
+ nsyn = (input *)&inputfifo[(movefifosendplc )&(MOVEFIFOSIZ-1)][0];
+
+ //MASTER -> SLAVE packet
+ packbuf[0] = 0; j = 1;
+
+ //Fix timers and buffer/jitter value
+ if ((movefifosendplc&(TIMERUPDATESIZ-1)) == 0)
+ {
+ for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
+ if (playerquitflag[i])
+ packbuf[j++] = min(max(myminlag[i],-128),127);
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ myminlag[i] = 0x7fffffff;
+ }
+
+ k = j;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ j += playerquitflag[i];
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if (playerquitflag[i] == 0) continue;
+
+ packbuf[k] = 0;
+ if (nsyn[i].fvel != osyn[i].fvel)
+ {
+ packbuf[j++] = (uint8_t )nsyn[i].fvel;
+ packbuf[j++] = (uint8_t )(nsyn[i].fvel>>8);
+ packbuf[k] |= 1;
+ }
+ if (nsyn[i].svel != osyn[i].svel)
+ {
+ packbuf[j++] = (uint8_t )nsyn[i].svel;
+ packbuf[j++] = (uint8_t )(nsyn[i].svel>>8);
+ packbuf[k] |= 2;
+ }
+ if (nsyn[i].avel != osyn[i].avel)
+ {
+ packbuf[j++] = (int8_t )nsyn[i].avel;
+ packbuf[k] |= 4;
+ }
+ if ((nsyn[i].bits^osyn[i].bits)&0x000000ff) packbuf[j++] = (nsyn[i].bits&255), packbuf[k] |= 8;
+ if ((nsyn[i].bits^osyn[i].bits)&0x0000ff00) packbuf[j++] = ((nsyn[i].bits>>8)&255), packbuf[k] |= 16;
+ if ((nsyn[i].bits^osyn[i].bits)&0x00ff0000) packbuf[j++] = ((nsyn[i].bits>>16)&255), packbuf[k] |= 32;
+ if ((nsyn[i].bits^osyn[i].bits)&0xff000000) packbuf[j++] = ((nsyn[i].bits>>24)&255), packbuf[k] |= 64;
+ if (nsyn[i].horz != osyn[i].horz)
+ {
+ packbuf[j++] = (uint8_t )nsyn[i].horz;
+ packbuf[k] |= 128;
+ }
+ k++;
+ }
+
+ while (syncvalhead[myconnectindex] != syncvaltail)
+ {
+ packbuf[j++] = syncval[myconnectindex][syncvaltail&(MOVEFIFOSIZ-1)];
+ syncvaltail++;
+ }
+
+ for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
+ if (playerquitflag[i])
+ {
+ sendpacket(i,packbuf,j);
+ if (nsyn[i].bits&(1<<26))
+ playerquitflag[i] = 0;
+ }
+
+ movefifosendplc += movesperpacket;
+ }
+}
+
+extern int32_t cacnum;
+
+typedef struct {
+ uint8_t *hand;
+ int32_t leng;
+ uint8_t *lock; }
+ cactype;
+extern cactype cac[];
+
+void caches(void)
+{
+ short i,k;
+ char text[512];
+
+ k = 0;
+ for(i=0;i<cacnum;i++)
+ if ((*cac[i].lock) >= 200)
+ {
+ sprintf(text,"Locked- %d: Leng:%d, Lock:%d",i,cac[i].leng,*cac[i].lock);
+ printext256(0L,k,31,-1,text,1); k += 6;
+ }
+
+ k += 6;
+
+ for(i=1;i<11;i++)
+ if (lumplockbyte[i] >= 200)
+ {
+ sprintf(text,"RTS Locked %hd:",i);
+ printext256(0L,k,31,-1,text,1); k += 6;
+ }
+
+
+}
+
+// FIX_00024: A key can be assigned to the new SHOW_INFO function. Display map CRC when
+// in deathmatch. Usefull to identify who loaded a wrong map in multiplayer.
+void dispVersion(void)
+{
+ int i;
+ int offx, offy, stepx, stepy;
+ char text[512];
+
+ offx = 21; offy = 30;
+ stepx = 73; stepy = 20;
+
+ // black translucent background underneath lists
+ rotatesprite(0<<16, 0<<16, 65536l<<5, 0, BLANK, 8, 0, 1+2+8+16+64,
+ scale(0,xdim,320),scale(26,ydim,200),
+ scale(320-0,xdim,320)-1,scale(200-((ud.multimode>4)?(161-1*7)-stepy:(161-1*7)),ydim,200)-1);
+
+ // FIX_00009: Show map CRC and GRP file version of each player in case of Out Of Synch
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ // Disp name
+ sprintf(text,"%s", ud.user_name[i]);
+ minitext(offx+(stepx*(i&3)),offy+0+((i&4)>>2)*stepy, text, sprite[ps[i].i].pal, 2+8+16);
+
+ // Disp MAP CRC
+ if(ps[i].fakeplayer)
+ sprintf(text,"MAP CRC: (bot)");
+ else
+ sprintf(text,"MAP CRC: %X", ud.mapCRC[i]);
+ minitext(offx+(stepx*(i&3)),offy+7+((i&4)>>2)*stepy, text, COLOR_ON,2+8+16);
+
+ }
+}
+
+void checksync(void)
+{
+ int32_t i;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (syncvalhead[i] == syncvaltottail) break;
+ if (i < 0)
+ {
+ syncstat = 0;
+ do
+ {
+ for(i=connectpoint2[connecthead];i>=0;i=connectpoint2[i])
+ {
+ if (syncval[i][syncvaltottail&(MOVEFIFOSIZ-1)] != syncval[connecthead][syncvaltottail&(MOVEFIFOSIZ-1)])
+ {
+ syncstat = 1;
+ }
+ }
+
+ syncvaltottail++;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if (syncvalhead[i] == syncvaltottail)
+ {
+ break;
+ }
+ }
+ } while (i < 0);
+ }
+
+ if (connectpoint2[connecthead] < 0)
+ {
+ syncstat = 0;
+ }
+
+ if (syncstat)
+ {
+ minitext(21,30+35+30, "Out Of Sync - Please restart game", COLOR_ON,2+8+16);
+ // FIX_00090: Removed info key. FPS were shown after CRC msg. CRC not always removed. (Turrican)
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if (ud.mapCRC[connecthead]!=ud.mapCRC[i])
+ {
+ minitext(21,30+42+30, "Map CRC mismatching. Please use exactly the same map.", COLOR_ON,2+8+16);
+ dispVersion();
+ }
+ else
+ minitext(21,30+42+30, "Verify the con files. Close your P2P if any", COLOR_ON,2+8+16);
+
+ }
+ }
+
+ if (syncstate)
+ {
+ //printext256(4L,160L,31,0,"Missed Network packet!",0);
+ //printext256(4L,138L,31,0,"RUN DN3DHELP.EXE for information.",0);
+ minitext(21,30+35+30, "Missed Network packet!", COLOR_ON,2+8+16);
+ }
+
+}
+
+
+void check_fta_sounds(short i)
+{
+ if(sprite[i].extra > 0) switch(PN)
+ {
+ case LIZTROOPONTOILET:
+ case LIZTROOPJUSTSIT:
+ case LIZTROOPSHOOT:
+ case LIZTROOPJETPACK:
+ case LIZTROOPDUCKING:
+ case LIZTROOPRUNNING:
+ case LIZTROOP:
+ spritesound(PRED_RECOG,i);
+ break;
+ case LIZMAN:
+ case LIZMANSPITTING:
+ case LIZMANFEEDING:
+ case LIZMANJUMP:
+ spritesound(CAPT_RECOG,i);
+ break;
+ case PIGCOP:
+ case PIGCOPDIVE:
+ spritesound(PIG_RECOG,i);
+ break;
+ case RECON:
+ spritesound(RECO_RECOG,i);
+ break;
+ case DRONE:
+ spritesound(DRON_RECOG,i);
+ break;
+ case COMMANDER:
+ case COMMANDERSTAYPUT:
+ spritesound(COMM_RECOG,i);
+ break;
+ case ORGANTIC:
+ spritesound(TURR_RECOG,i);
+ break;
+ case OCTABRAIN:
+ case OCTABRAINSTAYPUT:
+ spritesound(OCTA_RECOG,i);
+ break;
+ case BOSS1:
+ sound(BOS1_RECOG);
+ break;
+ case BOSS2:
+ if(sprite[i].pal == 1)
+ sound(BOS2_RECOG);
+ else sound(WHIPYOURASS);
+ break;
+ case BOSS3:
+ if(sprite[i].pal == 1)
+ sound(BOS3_RECOG);
+ else sound(RIPHEADNECK);
+ break;
+ case BOSS4:
+ case BOSS4STAYPUT:
+ if(sprite[i].pal == 1)
+ sound(BOS4_RECOG);
+ sound(BOSS4_FIRSTSEE);
+ break;
+ case GREENSLIME:
+ spritesound(SLIM_RECOG,i);
+ break;
+ }
+}
+
+short inventory(spritetype *s)
+{
+ switch(s->picnum)
+ {
+ case FIRSTAID:
+ case STEROIDS:
+ case HEATSENSOR:
+ case BOOTS:
+ case JETPACK:
+ case HOLODUKE:
+ case AIRTANK:
+ return 1;
+ }
+ return 0;
+}
+
+
+short badguy(spritetype *s)
+{
+
+ switch(s->picnum)
+ {
+ case SHARK:
+ case RECON:
+ case DRONE:
+ case LIZTROOPONTOILET:
+ case LIZTROOPJUSTSIT:
+ case LIZTROOPSTAYPUT:
+ case LIZTROOPSHOOT:
+ case LIZTROOPJETPACK:
+ case LIZTROOPDUCKING:
+ case LIZTROOPRUNNING:
+ case LIZTROOP:
+ case OCTABRAIN:
+ case COMMANDER:
+ case COMMANDERSTAYPUT:
+ case PIGCOP:
+ case EGG:
+ case PIGCOPSTAYPUT:
+ case PIGCOPDIVE:
+ case LIZMAN:
+ case LIZMANSPITTING:
+ case LIZMANFEEDING:
+ case LIZMANJUMP:
+ case ORGANTIC:
+ case BOSS1:
+ case BOSS2:
+ case BOSS3:
+ case BOSS4:
+ case GREENSLIME:
+ case GREENSLIME+1:
+ case GREENSLIME+2:
+ case GREENSLIME+3:
+ case GREENSLIME+4:
+ case GREENSLIME+5:
+ case GREENSLIME+6:
+ case GREENSLIME+7:
+ case RAT:
+ case ROTATEGUN:
+ return 1;
+ }
+ if( actortype[s->picnum] ) return 1;
+
+ return 0;
+}
+
+
+short badguypic(short pn)
+{
+
+ switch(pn)
+ {
+ case SHARK:
+ case RECON:
+ case DRONE:
+ case LIZTROOPONTOILET:
+ case LIZTROOPJUSTSIT:
+ case LIZTROOPSTAYPUT:
+ case LIZTROOPSHOOT:
+ case LIZTROOPJETPACK:
+ case LIZTROOPDUCKING:
+ case LIZTROOPRUNNING:
+ case LIZTROOP:
+ case OCTABRAIN:
+ case COMMANDER:
+ case COMMANDERSTAYPUT:
+ case PIGCOP:
+ case EGG:
+ case PIGCOPSTAYPUT:
+ case PIGCOPDIVE:
+ case LIZMAN:
+ case LIZMANSPITTING:
+ case LIZMANFEEDING:
+ case LIZMANJUMP:
+ case ORGANTIC:
+ case BOSS1:
+ case BOSS2:
+ case BOSS3:
+ case BOSS4:
+ case GREENSLIME:
+ case GREENSLIME+1:
+ case GREENSLIME+2:
+ case GREENSLIME+3:
+ case GREENSLIME+4:
+ case GREENSLIME+5:
+ case GREENSLIME+6:
+ case GREENSLIME+7:
+ case RAT:
+ case ROTATEGUN:
+ return 1;
+ }
+
+ if( actortype[pn] ) return 1;
+
+ return 0;
+}
+
+
+
+void myos(int32_t x, int32_t y, short tilenum, int8_t shade, uint8_t orientation)
+{
+ uint8_t p;
+ short a;
+
+ if(orientation&4)
+ a = 1024;
+ else a = 0;
+
+ p = sector[ps[screenpeek].cursectnum].floorpal;
+ rotatesprite(x<<16,y<<16,65536L,a,tilenum,shade,p,2|orientation,windowx1,windowy1,windowx2,windowy2);
+}
+
+void myospal(int32_t x, int32_t y, short tilenum, int8_t shade, uint8_t orientation, uint8_t p)
+{
+// uint8_t fp;
+ short a;
+
+ if(orientation&4)
+ a = 1024;
+ else a = 0;
+
+// fp = sector[ps[screenpeek].cursectnum].floorpal;
+
+ rotatesprite(x<<16,y<<16,65536L,a,tilenum,shade,p,2|orientation,windowx1,windowy1,windowx2,windowy2);
+
+}
+
+void invennum(int32_t x,int32_t y,uint8_t num1,uint8_t ha,uint8_t sbits)
+{
+ char dabuf[80] = {0};
+ sprintf(dabuf,"%d",num1);
+ if(num1 > 99)
+ {
+ rotatesprite((x-4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,sbits,0,0,xdim-1,ydim-1);
+ rotatesprite((x)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,sbits,0,0,xdim-1,ydim-1);
+ rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[2]-'0',ha,0,sbits,0,0,xdim-1,ydim-1);
+ }
+ else if(num1 > 9)
+ {
+ rotatesprite((x)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,sbits,0,0,xdim-1,ydim-1);
+ rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,sbits,0,0,xdim-1,ydim-1);
+ }
+ else
+ rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,sbits,0,0,xdim-1,ydim-1);
+}
+
+void orderweaponnum(short ind,int32_t x,int32_t y,int32_t num1, int32_t num2,uint8_t ha)
+{
+ rotatesprite((x-7)<<16,y<<16,65536L,0,THREEBYFIVE+ind+1,ha-10,7,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x-3)<<16,y<<16,65536L,0,THREEBYFIVE+10,ha,0,10+128,0,0,xdim-1,ydim-1);
+
+ minitextshade(x+1,y-4,"ORDER",26,6,2+8+16+128);
+}
+
+void weaponnum(short ind,int32_t x,int32_t y,int32_t num1, int32_t num2,uint8_t ha)
+{
+ char dabuf[80] = {0};
+
+ rotatesprite((x-7)<<16,y<<16,65536L,0,THREEBYFIVE+ind+1,ha-10,7,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x-3)<<16,y<<16,65536L,0,THREEBYFIVE+10,ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+9)<<16,y<<16,65536L,0,THREEBYFIVE+11,ha,0,10+128,0,0,xdim-1,ydim-1);
+
+ if(num1 > 99) num1 = 99;
+ if(num2 > 99) num2 = 99;
+
+ sprintf(dabuf,"%d",num1);
+ if(num1 > 9)
+ {
+ rotatesprite((x)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ }
+ else rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+
+ sprintf(dabuf,"%d",num2);
+ if(num2 > 9)
+ {
+ rotatesprite((x+13)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+17)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ }
+ else rotatesprite((x+13)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+}
+
+void weaponnum999(uint8_t ind,int32_t x,int32_t y,int32_t num1, int32_t num2,uint8_t ha)
+{
+ char dabuf[80] = {0};
+
+ rotatesprite((x-7)<<16,y<<16,65536L,0,THREEBYFIVE+ind+1,ha-10,7,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x-4)<<16,y<<16,65536L,0,THREEBYFIVE+10,ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+13)<<16,y<<16,65536L,0,THREEBYFIVE+11,ha,0,10+128,0,0,xdim-1,ydim-1);
+
+ sprintf(dabuf,"%d",num1);
+ if(num1 > 99)
+ {
+ rotatesprite((x)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+8)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[2]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ }
+ else if(num1 > 9)
+ {
+ rotatesprite((x+4)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+8)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ }
+ else rotatesprite((x+8)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+
+ sprintf(dabuf,"%d",num2);
+ if(num2 > 99)
+ {
+ rotatesprite((x+17)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+21)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+25)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[2]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ }
+ else if(num2 > 9)
+ {
+ rotatesprite((x+17)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ rotatesprite((x+21)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[1]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+ }
+ else rotatesprite((x+25)<<16,y<<16,65536L,0,THREEBYFIVE+dabuf[0]-'0',ha,0,10+128,0,0,xdim-1,ydim-1);
+}
+
+
+//REPLACE FULLY
+void weapon_amounts(struct player_struct *p,int32_t x,int32_t y,int32_t u)
+{
+ int cw;
+
+ cw = p->curr_weapon;
+
+ if (u&4)
+ {
+ if (u != 0xffffffff) patchstatusbar(96,178,96+12,178+6);
+ weaponnum999(PISTOL_WEAPON,x,y,
+ p->ammo_amount[PISTOL_WEAPON],max_ammo_amount[PISTOL_WEAPON],
+ 12-20*(cw == PISTOL_WEAPON) );
+ }
+ if (u&8)
+ {
+ if (u != 0xffffffff) patchstatusbar(96,184,96+12,184+6);
+ weaponnum999(SHOTGUN_WEAPON,x,y+6,
+ p->ammo_amount[SHOTGUN_WEAPON],max_ammo_amount[SHOTGUN_WEAPON],
+ (!p->gotweapon[SHOTGUN_WEAPON]*9)+12-18*
+ (cw == SHOTGUN_WEAPON) );
+ }
+ if (u&16)
+ {
+ if (u != 0xffffffff) patchstatusbar(96,190,96+12,190+6);
+ weaponnum999(CHAINGUN_WEAPON,x,y+12,
+ p->ammo_amount[CHAINGUN_WEAPON],max_ammo_amount[CHAINGUN_WEAPON],
+ (!p->gotweapon[CHAINGUN_WEAPON]*9)+12-18*
+ (cw == CHAINGUN_WEAPON) );
+ }
+ if (u&32)
+ {
+ if (u != 0xffffffff) patchstatusbar(135,178,135+8,178+6);
+ weaponnum(RPG_WEAPON,x+39,y,
+ p->ammo_amount[RPG_WEAPON],max_ammo_amount[RPG_WEAPON],
+ (!p->gotweapon[RPG_WEAPON]*9)+12-19*
+ (cw == RPG_WEAPON) );
+ }
+ if (u&64)
+ {
+ if (u != 0xffffffff) patchstatusbar(135,184,135+8,184+6);
+ weaponnum(HANDBOMB_WEAPON,x+39,y+6,
+ p->ammo_amount[HANDBOMB_WEAPON],max_ammo_amount[HANDBOMB_WEAPON],
+ (((!p->ammo_amount[HANDBOMB_WEAPON])|(!p->gotweapon[HANDBOMB_WEAPON]))*9)+12-19*
+ ((cw == HANDBOMB_WEAPON) || (cw == HANDREMOTE_WEAPON)));
+ }
+ if (u&128)
+ {
+ if (u != 0xffffffff) patchstatusbar(135,190,135+8,190+6);
+
+ if(VOLUMEONE)
+ {
+ orderweaponnum(SHRINKER_WEAPON,x+39,y+12,
+ p->ammo_amount[SHRINKER_WEAPON],max_ammo_amount[SHRINKER_WEAPON],
+ (!p->gotweapon[SHRINKER_WEAPON]*9)+12-18*
+ (cw == SHRINKER_WEAPON) );
+ }
+ else
+ {
+ if(p->subweapon&(1<<GROW_WEAPON))
+ weaponnum(SHRINKER_WEAPON,x+39,y+12,
+ p->ammo_amount[GROW_WEAPON],max_ammo_amount[GROW_WEAPON],
+ (!p->gotweapon[GROW_WEAPON]*9)+12-18*
+ (cw == GROW_WEAPON) );
+ else
+ weaponnum(SHRINKER_WEAPON,x+39,y+12,
+ p->ammo_amount[SHRINKER_WEAPON],max_ammo_amount[SHRINKER_WEAPON],
+ (!p->gotweapon[SHRINKER_WEAPON]*9)+12-18*
+ (cw == SHRINKER_WEAPON) );
+ }
+ }
+ if (u&256)
+ {
+ if (u != 0xffffffff) patchstatusbar(166,178,166+8,178+6);
+
+ if(VOLUMEONE)
+ {
+ orderweaponnum(DEVISTATOR_WEAPON,x+70,y,
+ p->ammo_amount[DEVISTATOR_WEAPON],max_ammo_amount[DEVISTATOR_WEAPON],
+ (!p->gotweapon[DEVISTATOR_WEAPON]*9)+12-18*
+ (cw == DEVISTATOR_WEAPON) );
+ }
+ else
+ {
+ weaponnum(DEVISTATOR_WEAPON,x+70,y,
+ p->ammo_amount[DEVISTATOR_WEAPON],max_ammo_amount[DEVISTATOR_WEAPON],
+ (!p->gotweapon[DEVISTATOR_WEAPON]*9)+12-18*
+ (cw == DEVISTATOR_WEAPON) );
+ }
+ }
+ if (u&512)
+ {
+ if (u != 0xffffffff) patchstatusbar(166,184,166+8,184+6);
+ if(VOLUMEONE)
+ {
+ orderweaponnum(TRIPBOMB_WEAPON,x+70,y+6,
+ p->ammo_amount[TRIPBOMB_WEAPON],max_ammo_amount[TRIPBOMB_WEAPON],
+ (!p->gotweapon[TRIPBOMB_WEAPON]*9)+12-18*
+ (cw == TRIPBOMB_WEAPON) );
+ }
+ else
+ {
+ weaponnum(TRIPBOMB_WEAPON,x+70,y+6,
+ p->ammo_amount[TRIPBOMB_WEAPON],max_ammo_amount[TRIPBOMB_WEAPON],
+ (!p->gotweapon[TRIPBOMB_WEAPON]*9)+12-18*
+ (cw == TRIPBOMB_WEAPON) );
+ }
+ }
+
+ if (u&65536L)
+ {
+ if (u != 0xffffffff) patchstatusbar(166,190,166+8,190+6);
+ if(VOLUMEONE)
+ {
+ orderweaponnum(-1,x+70,y+12,
+ p->ammo_amount[FREEZE_WEAPON],max_ammo_amount[FREEZE_WEAPON],
+ (!p->gotweapon[FREEZE_WEAPON]*9)+12-18*
+ (cw == FREEZE_WEAPON) );
+ }
+ else
+ {
+ weaponnum(-1,x+70,y+12,
+ p->ammo_amount[FREEZE_WEAPON],max_ammo_amount[FREEZE_WEAPON],
+ (!p->gotweapon[FREEZE_WEAPON]*9)+12-18*
+ (cw == FREEZE_WEAPON) );
+ }
+ }
+}
+
+void digitalnumber(int32_t x,int32_t y,int32_t n,uint8_t s,uint8_t cs)
+{
+ short i, j, k, p, c;
+ char b[10];
+
+ //
+ // uint8_t * ltoa(int32_t l, uint8_t * buffer, int radix);
+ // is NON-STANDARD and equivalent to STANDARD
+ // (void) sprintf(buffer, "%ld", l);
+ //ltoa(n,b,10);
+ sprintf(b,"%d",n);
+
+ i = strlen(b);
+ j = 0;
+
+ for(k=0;k<i;k++)
+ {
+ p = DIGITALNUM+*(b+k)-'0';
+ j += tiles[p].dim.width+1;
+ }
+ c = x-(j>>1);
+
+ j = 0;
+ for(k=0;k<i;k++)
+ {
+ p = DIGITALNUM+*(b+k)-'0';
+ rotatesprite((c+j)<<16,y<<16,65536L,0,p,s,0,cs,0,0,xdim-1,ydim-1);
+ j += tiles[p].dim.width+1;
+ }
+}
+
+/*
+
+ void scratchmarks(int32_t x,int32_t y,int32_t n,uint8_t s,uint8_t p)
+ {
+ int32_t i, ni;
+
+ ni = n/5;
+ for(i=ni;i >= 0;i--)
+ {
+ overwritesprite(x-2,y,SCRATCH+4,s,0,0);
+ x += tilesizx[SCRATCH+4]-1;
+ }
+
+ ni = n%5;
+ if(ni) overwritesprite(x,y,SCRATCH+ni-1,s,p,0);
+ }
+*/
+void displayinventory(struct player_struct *p)
+{
+ short n, j, xoff, y;
+
+ j = xoff = 0;
+
+ n = (p->jetpack_amount > 0)<<3; if(n&8) j++;
+ n |= ( p->scuba_amount > 0 )<<5; if(n&32) j++;
+ n |= (p->steroids_amount > 0)<<1; if(n&2) j++;
+ n |= ( p->holoduke_amount > 0)<<2; if(n&4) j++;
+ n |= (p->firstaid_amount > 0); if(n&1) j++;
+ n |= (p->heat_amount > 0)<<4; if(n&16) j++;
+ n |= (p->boot_amount > 0)<<6; if(n&64) j++;
+
+ xoff = 160-(j*11);
+
+ j = 0;
+
+ if(ud.screen_size > 4)
+ y = 154;
+ else y = 172;
+
+ if(ud.screen_size == 4)
+ {
+ if(ud.multimode > 1)
+ xoff += 56;
+ else xoff += 65;
+ }
+
+ while( j <= 9 )
+ {
+ if( n&(1<<j) )
+ {
+ switch( n&(1<<j) )
+ {
+ case 1:
+ rotatesprite(xoff<<16,y<<16,65536L,0,FIRSTAID_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ case 2:
+ rotatesprite((xoff+1)<<16,y<<16,65536L,0,STEROIDS_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ case 4:
+ rotatesprite((xoff+2)<<16,y<<16,65536L,0,HOLODUKE_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ case 8:
+ rotatesprite(xoff<<16,y<<16,65536L,0,JETPACK_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ case 16:
+ rotatesprite(xoff<<16,y<<16,65536L,0,HEAT_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ case 32:
+ rotatesprite(xoff<<16,y<<16,65536L,0,AIRTANK_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ case 64:
+ rotatesprite(xoff<<16,(y-1)<<16,65536L,0,BOOT_ICON,0,0,2+16,windowx1,windowy1,windowx2,windowy2);break;
+ }
+
+ xoff += 22;
+
+ if(p->inven_icon == j+1)
+ rotatesprite((xoff-2)<<16,(y+19)<<16,65536L,1024,ARROW,-32,0,2+16,windowx1,windowy1,windowx2,windowy2);
+ }
+
+ j++;
+ }
+}
+
+
+
+void displayfragbar(void)
+{
+ short i, j;
+ char text[512];
+
+ j = 0;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if(i > j) j = i;
+
+ rotatesprite(0,0,65600L,0,FRAGBAR,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ if(j >= 4) rotatesprite(319,(8)<<16,65600L,0,FRAGBAR,0,0,10+16+64+128,0,0,xdim-1,ydim-1);
+ if(j >= 8) rotatesprite(319,(16)<<16,65600L,0,FRAGBAR,0,0,10+16+64+128,0,0,xdim-1,ydim-1);
+ if(j >= 12) rotatesprite(319,(24)<<16,65600L,0,FRAGBAR,0,0,10+16+64+128,0,0,xdim-1,ydim-1);
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ minitext(21+(73*(i&3)),2+((i&28)<<1),&ud.user_name[i][0],sprite[ps[i].i].pal,2+8+16+128);
+ sprintf(text,"%d",ps[i].frag-ps[i].fraggedself);
+ minitext(17+50+(73*(i&3)),2+((i&28)<<1),text,sprite[ps[i].i].pal,2+8+16+128);
+ }
+}
+
+void display_boardfilename_FPS_weapon(short *offx, short *offy, short *stepx, short *stepy)
+{
+
+ short i;
+
+ // FIX_00025: Can toggle FPS and map name during a game (use dnrate OR toggle
+ // from menu when in deathmatch).
+
+ // Display boardfilename and FPS
+ if(ud.tickrate&1)
+ {
+ duke_tics(*offx, *offy, COLOR_ON);
+ *offy += *stepy;
+ }
+ if(ud.tickrate&2)
+ dispVersion();
+
+ // We display the weapons here instead of changing the function
+ // displayweapon() because the display will be much faster
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if (ud.hideweapon && i==screenpeek)
+ drawsmallweapon(ps[i].curr_weapon, 1, 130, (ud.screen_size<=4)?170:140);
+ }
+}
+
+
+// FIX_00026: Weapon can now be hidden (on your screen only).
+void drawsmallweapon(short weapon, float scale, short x, short y)
+{
+ float t = 60000;
+ int s;
+ float offsetx, offsety;
+
+
+ switch(weapon)
+ {
+ case KNEE_WEAPON : s=0; break;
+ case PISTOL_WEAPON : s=FIRSTGUNSPRITE;
+ offsetx = 8;
+ offsety = 7;
+ break;
+ case SHOTGUN_WEAPON : s=SHOTGUNSPRITE;
+ t = 45000;
+ offsetx = -1;
+ offsety = 9;
+ break;
+ case CHAINGUN_WEAPON : s=CHAINGUNSPRITE;
+ t = 45000;
+ offsetx = -1;
+ offsety = 9;
+ break;
+ case RPG_WEAPON : s=RPGSPRITE;
+ t = 45000;
+ offsetx = 4;
+ offsety = 9;
+ break;
+ case HANDBOMB_WEAPON : s=HEAVYHBOMB;
+ t=20000;
+ offsetx = 16;
+ offsety = 13;
+ break;
+ case SHRINKER_WEAPON : s=SHRINKERSPRITE;
+ t = 30000;
+ offsetx = 6;
+ offsety = 14;
+ break;
+ case DEVISTATOR_WEAPON : s=DEVISTATORSPRITE;
+ t = 45000;
+ offsetx = 3;
+ offsety = 9;
+ break;
+ case TRIPBOMB_WEAPON : s=TRIPBOMBSPRITE;
+ t = 75000;
+ offsetx = 10;
+ offsety = 12;
+ break;
+ case FREEZE_WEAPON : s=FREEZESPRITE;
+ t = 45000;
+ offsetx = 1;
+ offsety = 6;
+ break;
+ case HANDREMOTE_WEAPON : s=0;
+ break;
+ case GROW_WEAPON : s=GROWSPRITEICON;
+ t = 30000;
+ offsetx = 6;
+ offsety = 4;
+ break;
+ default : s=0;
+ }
+
+ if(s)
+ rotatesprite((x+(short)(offsetx*scale))<<16,(y+(short)(offsety*scale))<<16,(int)(t*scale),0,s,0,0,2+8+16,0,0,xdim-1,ydim-1);
+
+ return;
+}
+
+void coolgaugetext(short snum)
+{
+ struct player_struct *p;
+ int32_t i, j, o, ss, u;
+ uint8_t permbit;
+ short offx = 3, offy = 3, stepx=60, stepy=6;
+ char text[512];
+
+ p = &ps[snum];
+
+ if (p->invdisptime > 0)
+ {
+ displayinventory(p);
+ }
+
+
+ if(ps[snum].gm&MODE_MENU)
+ if( (current_menu >= 400 && current_menu <= 405) )
+ return;
+
+ offy += countfragbars(); //add fragbars
+ display_boardfilename_FPS_weapon(&offx, &offy, &stepx, &stepy);
+
+
+ ss = ud.screen_size; if (ss < 4) return;
+
+ // Draw the multi player frag status bar
+ if ( ud.multimode > 1 && ud.coop != 1 )
+ {
+ if (pus)
+ {
+ displayfragbar();
+ }
+ else
+ {
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if (ps[i].frag != sbar.frag[i])
+ {
+ displayfragbar();
+ break;
+ }
+ }
+ }
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i != myconnectindex)
+ sbar.frag[i] = ps[i].frag;
+ }
+
+ if (ss == 4) //DRAW MINI STATUS BAR:
+ {
+ // FIX_00027: Added an extra small statusbar (HUD)
+ if(ud.extended_screen_size>0)
+ {
+ offx = 5; offy = 160;
+
+ sprintf(text,"%d", ps[screenpeek].ammo_amount[ps[screenpeek].curr_weapon]);
+ minitext(offx+26,offy+21,text,COLOR_ON,2+8+16); //minitext: 2 red light, 23 yellow
+ sprintf(text,"%d", ps[screenpeek].last_extra);
+ gametext(offx,offy+20,text,ps[screenpeek].last_extra<=50?15:0,2+8+16); //minitext: 2 red light, 23 yellow
+ rotatesprite((offx+0*10)<<16,(offy+28)<<16,20000,0,SHIELD,ps[screenpeek].shield_amount?25:100,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+0*10)<<16,(offy+28)<<16,ksqrt(ps[screenpeek].shield_amount)*20000/10,0,SHIELD,0,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+1*10)<<16,(offy+28)<<16,35000,0,JETPACK_ICON,ps[screenpeek].jetpack_amount?25:100,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+1*10)<<16,(offy+28)<<16,ksqrt(ps[screenpeek].jetpack_amount)*35000/40,0,JETPACK_ICON,0,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+2*10-1)<<16,(offy+28)<<16,35000,0,STEROIDS_ICON,ps[screenpeek].steroids_amount?25:100,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+2*10-1)<<16,(offy+28)<<16,ksqrt(ps[screenpeek].steroids_amount)*35000/20,0,STEROIDS_ICON,5,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+3*10-3)<<16,(offy+28)<<16,40000,0,FIRSTAID_ICON,ps[screenpeek].firstaid_amount?25:100,0,2+8+16,0,0,xdim-1,ydim-1);
+ rotatesprite((offx+3*10-3)<<16,(offy+28)<<16,ksqrt(ps[screenpeek].firstaid_amount)*40000/10,0,FIRSTAID_ICON,0,0,2+8+16,0,0,xdim-1,ydim-1);
+ }
+ else
+ {
+ if (p->inven_icon)
+ rotatesprite(69<<16,(200-30)<<16,65536L,0,INVENTORYBOX,0,21,10+16,0,0,xdim-1,ydim-1);
+ rotatesprite(5<<16,(200-28)<<16,65536L,0,HEALTHBOX,0,21,10+16,0,0,xdim-1,ydim-1);
+
+ if(sprite[p->i].pal == 1 && p->last_extra < 2)
+ digitalnumber(20,200-17,1,-16,10+16);
+ else digitalnumber(20,200-17,p->last_extra,-16,10+16);
+
+ rotatesprite(37<<16,(200-28)<<16,65536L,0,AMMOBOX,0,21,10+16,0,0,xdim-1,ydim-1);
+
+ if (p->curr_weapon == HANDREMOTE_WEAPON) i = HANDBOMB_WEAPON; else i = p->curr_weapon;
+ digitalnumber(53,200-17,p->ammo_amount[i],-16,10+16);
+
+ o = 158; permbit = 0;
+ if (p->inven_icon)
+ {
+ switch(p->inven_icon)
+ {
+ case 1: i = FIRSTAID_ICON; break;
+ case 2: i = STEROIDS_ICON; break;
+ case 3: i = HOLODUKE_ICON; break;
+ case 4: i = JETPACK_ICON; break;
+ case 5: i = HEAT_ICON; break;
+ case 6: i = AIRTANK_ICON; break;
+ case 7: i = BOOT_ICON; break;
+ default: i = -1;
+ }
+ if (i >= 0) rotatesprite((231-o)<<16,(200-21)<<16,65536L,0,i,0,0,10+16+permbit,0,0,xdim-1,ydim-1);
+
+ minitext(292-30-o,190,"%",6,10+16+permbit);
+
+ j = 0x80000000;
+ switch(p->inven_icon)
+ {
+ case 1: i = p->firstaid_amount; break;
+ case 2: i = ((p->steroids_amount+3)>>2); break;
+ case 3: i = ((p->holoduke_amount+15)/24); j = p->holoduke_on; break;
+ case 4: i = ((p->jetpack_amount+15)>>4); j = p->jetpack_on; break;
+ case 5: i = p->heat_amount/12; j = p->heat_on; break;
+ case 6: i = ((p->scuba_amount+63)>>6); break;
+ case 7: i = (p->boot_amount>>1); break;
+ }
+ invennum(284-30-o,200-6,(uint8_t )i,0,10+permbit);
+ if (j > 0) minitext(288-30-o,180,"ON",0,10+16+permbit);
+ else if (j != 0x80000000) minitext(284-30-o,180,"OFF",2,10+16+permbit);
+ if (p->inven_icon >= 6) minitext(284-35-o,180,"AUTO",2,10+16+permbit);
+ }
+ }
+ return;
+ }
+
+ //DRAW/UPDATE FULL STATUS BAR:
+
+ if (pus) { pus = 0; u = 0xffffffff; } else u = 0;
+
+ if (sbar.frag[myconnectindex] != p->frag) { sbar.frag[myconnectindex] = p->frag; u |= 32768; }
+ if (sbar.got_access != p->got_access) { sbar.got_access = p->got_access; u |= 16384; }
+ if (sbar.last_extra != p->last_extra) { sbar.last_extra = p->last_extra; u |= 1; }
+ if (sbar.shield_amount != p->shield_amount) { sbar.shield_amount = p->shield_amount; u |= 2; }
+ if (sbar.curr_weapon != p->curr_weapon) { sbar.curr_weapon = p->curr_weapon; u |= (4+8+16+32+64+128+256+512+1024+65536L); }
+ for(i=1;i < 10;i++)
+ {
+ if (sbar.ammo_amount[i] != p->ammo_amount[i]) {
+ sbar.ammo_amount[i] = p->ammo_amount[i]; if(i < 9) u |= ((2<<i)+1024); else u |= 65536L+1024; }
+ if (sbar.gotweapon[i] != p->gotweapon[i]) { sbar.gotweapon[i] =
+ p->gotweapon[i]; if(i < 9 ) u |= ((2<<i)+1024); else u |= 65536L+1024; }
+ }
+ if (sbar.inven_icon != p->inven_icon) { sbar.inven_icon = p->inven_icon; u |= (2048+4096+8192); }
+ if (sbar.holoduke_on != p->holoduke_on) { sbar.holoduke_on = p->holoduke_on; u |= (4096+8192); }
+ if (sbar.jetpack_on != p->jetpack_on) { sbar.jetpack_on = p->jetpack_on; u |= (4096+8192); }
+ if (sbar.heat_on != p->heat_on) { sbar.heat_on = p->heat_on; u |= (4096+8192); }
+ if (sbar.firstaid_amount != p->firstaid_amount) { sbar.firstaid_amount = p->firstaid_amount; u |= 8192; }
+ if (sbar.steroids_amount != p->steroids_amount) { sbar.steroids_amount = p->steroids_amount; u |= 8192; }
+ if (sbar.holoduke_amount != p->holoduke_amount) { sbar.holoduke_amount = p->holoduke_amount; u |= 8192; }
+ if (sbar.jetpack_amount != p->jetpack_amount) { sbar.jetpack_amount = p->jetpack_amount; u |= 8192; }
+ if (sbar.heat_amount != p->heat_amount) { sbar.heat_amount = p->heat_amount; u |= 8192; }
+ if (sbar.scuba_amount != p->scuba_amount) { sbar.scuba_amount = p->scuba_amount; u |= 8192; }
+ if (sbar.boot_amount != p->boot_amount) { sbar.boot_amount = p->boot_amount; u |= 8192; }
+ if (u == 0) return;
+
+ //0 - update health
+ //1 - update armor
+ //2 - update PISTOL_WEAPON ammo
+ //3 - update SHOTGUN_WEAPON ammo
+ //4 - update CHAINGUN_WEAPON ammo
+ //5 - update RPG_WEAPON ammo
+ //6 - update HANDBOMB_WEAPON ammo
+ //7 - update SHRINKER_WEAPON ammo
+ //8 - update DEVISTATOR_WEAPON ammo
+ //9 - update TRIPBOMB_WEAPON ammo
+ //10 - update ammo display
+ //11 - update inventory icon
+ //12 - update inventory on/off
+ //13 - update inventory %
+ //14 - update keys
+ //15 - update kills
+ //16 - update FREEZE_WEAPON ammo
+
+ if (u == 0xffffffff)
+ {
+ patchstatusbar(0,0,320,200);
+ if (ud.multimode > 1 && ud.coop != 1)
+ rotatesprite(277<<16,(200-27)<<16,65536L,0,KILLSICON,0,0,10+16+128,0,0,xdim-1,ydim-1);
+ }
+ if (ud.multimode > 1 && ud.coop != 1)
+ {
+ if (u&32768)
+ {
+ if (u != 0xffffffff) patchstatusbar(276,183,299,193);
+ digitalnumber(287,200-17,max(p->frag-p->fraggedself,0),-16,10+16+128);
+ }
+ }
+ else
+ {
+ if (u&16384)
+ {
+ if (u != 0xffffffff) patchstatusbar(275,182,299,194);
+ if (p->got_access&4) rotatesprite(275<<16,182<<16,65536L,0,ACCESS_ICON,0,23,10+16+128,0,0,xdim-1,ydim-1);
+ if (p->got_access&2) rotatesprite(288<<16,182<<16,65536L,0,ACCESS_ICON,0,21,10+16+128,0,0,xdim-1,ydim-1);
+ if (p->got_access&1) rotatesprite(281<<16,189<<16,65536L,0,ACCESS_ICON,0,0,10+16+128,0,0,xdim-1,ydim-1);
+ }
+ }
+ if (u&(4+8+16+32+64+128+256+512+65536L)) weapon_amounts(p,96,182,u);
+
+ if (u&1)
+ {
+ if (u != 0xffffffff) patchstatusbar(20,183,43,193);
+ if(sprite[p->i].pal == 1 && p->last_extra < 2)
+ digitalnumber(32,200-17,1,-16,10+16+128);
+ else digitalnumber(32,200-17,p->last_extra,-16,10+16+128);
+ }
+ if (u&2)
+ {
+ if (u != 0xffffffff) patchstatusbar(52,183,75,193);
+ digitalnumber(64,200-17,p->shield_amount,-16,10+16+128);
+ }
+
+ if (u&1024)
+ {
+ if (u != 0xffffffff) patchstatusbar(196,183,219,193);
+ if (p->curr_weapon != KNEE_WEAPON)
+ {
+ if (p->curr_weapon == HANDREMOTE_WEAPON) i = HANDBOMB_WEAPON; else i = p->curr_weapon;
+ digitalnumber(230-22,200-17,p->ammo_amount[i],-16,10+16+128);
+ }
+ }
+
+ if (u&(2048+4096+8192))
+ {
+ if (u != 0xffffffff)
+ {
+ if (u&(2048+4096)) { patchstatusbar(231,179,265,197); }
+ else { patchstatusbar(250,190,261,195); }
+ }
+ if (p->inven_icon)
+ {
+ o = 0; permbit = 128;
+
+ if (u&(2048+4096))
+ {
+ switch(p->inven_icon)
+ {
+ case 1: i = FIRSTAID_ICON; break;
+ case 2: i = STEROIDS_ICON; break;
+ case 3: i = HOLODUKE_ICON; break;
+ case 4: i = JETPACK_ICON; break;
+ case 5: i = HEAT_ICON; break;
+ case 6: i = AIRTANK_ICON; break;
+ case 7: i = BOOT_ICON; break;
+ }
+ rotatesprite((231-o)<<16,(200-21)<<16,65536L,0,i,0,0,10+16+permbit,0,0,xdim-1,ydim-1);
+ minitext(292-30-o,190,"%",6,10+16+permbit);
+ if (p->inven_icon >= 6) minitext(284-35-o,180,"AUTO",2,10+16+permbit);
+ }
+ if (u&(2048+4096))
+ {
+ switch(p->inven_icon)
+ {
+ case 3: j = p->holoduke_on; break;
+ case 4: j = p->jetpack_on; break;
+ case 5: j = p->heat_on; break;
+ default: j = 0x80000000;
+ }
+ if (j > 0) minitext(288-30-o,180,"ON",0,10+16+permbit);
+ else if (j != 0x80000000) minitext(284-30-o,180,"OFF",2,10+16+permbit);
+ }
+ if (u&8192)
+ {
+ switch(p->inven_icon)
+ {
+ case 1: i = p->firstaid_amount; break;
+ case 2: i = ((p->steroids_amount+3)>>2); break;
+ case 3: i = ((p->holoduke_amount+15)/24); break;
+ case 4: i = ((p->jetpack_amount+15)>>4); break;
+ case 5: i = p->heat_amount/12; break;
+ case 6: i = ((p->scuba_amount+63)>>6); break;
+ case 7: i = (p->boot_amount>>1); break;
+ }
+ invennum(284-30-o,200-6,(uint8_t )i,0,10+permbit);
+ }
+ }
+ }
+}
+
+
+#define AVERAGEFRAMES 16
+static int32_t frameval[AVERAGEFRAMES], framecnt = 0;
+
+void duke_tics(short offx, short offy, short color)
+{
+ int32_t i;
+ char fps[512], mapname[512];
+ int32_t currentFps;
+ static int32_t fpsAvg = 0, savedFps = 0;
+ static boolean toggle = true;
+ char text[512];
+
+ strcpy(mapname,boardfilename);
+ for(i=0;i<512;i++)
+ if(mapname[i]=='.')
+ mapname[i]=0;
+
+ if( mapname[0] != 0 && ud.m_level_number == 7 && ud.m_volume_number == 0 )
+ sprintf(text, "%s", mapname);
+ else
+ //sprintf(tempbuf, "%s", level_names[ud.volume_number*11 + ud.level_number]);
+ sprintf(text, "e%dl%d", ud.volume_number+1, ud.level_number+1);
+
+
+ i = totalclock;
+
+ if (i != frameval[framecnt])
+ {
+ currentFps = (TICRATE*AVERAGEFRAMES)/(i-frameval[framecnt]);
+ fpsAvg = ((fpsAvg<<3)+(fpsAvg<<2) + (currentFps<<2))>>4;
+
+ frameval[framecnt] = i;
+ }
+
+ framecnt = ((framecnt+1)&(AVERAGEFRAMES-1));
+
+ // refresh screen and update visible FPS. This is to allow a refresh
+ // of the screen when the screensize > 4 w/o compromising the FPS.
+ if(ud.screen_size>8)
+ if ((totalclock%64) < 32)
+ {
+ if(toggle)
+ {
+ vscrn();
+ savedFps = fpsAvg;
+ }
+ toggle = false;
+ }
+ else
+ {
+ toggle = true;
+ }
+ else
+ savedFps = fpsAvg;
+
+ extern int rbaud_underruns;
+ sprintf(fps," %d %d", savedFps, rbaud_underruns);
+ strcat(text, fps);
+
+ minitext(offx,offy,text,color,2+8+16+128);
+}
+
+void coords(short snum)
+{
+ short x = 200, y = 0;
+ char text[512];
+ // x = 250 is too much on the right and
+ // will make the text going out of the screen
+ // if screen <= (320x200)
+ // This will also *write beyond the video
+ // buffer limit* and will crash the game.
+
+ if(ud.coop != 1)
+ {
+ if(ud.multimode > 1 && ud.multimode < 5)
+ y = 8;
+ else if(ud.multimode > 4)
+ y = 16;
+ }
+
+ sprintf(text,"X= %d",ps[snum].posx);
+ printext256(x,y,31,-1,text,1);
+ sprintf(text,"Y= %d",ps[snum].posy);
+ printext256(x,y+7L,31,-1,text,1);
+ sprintf(text,"Z= %d",ps[snum].posz);
+ printext256(x,y+14L,31,-1,text,1);
+ sprintf(text,"A= %d",ps[snum].ang);
+ printext256(x,y+21L,31,-1,text,1);
+ sprintf(text,"ZV= %d",ps[snum].poszv);
+ printext256(x,y+28L,31,-1,text,1);
+ sprintf(text,"OG= %d",ps[snum].on_ground);
+ printext256(x,y+35L,31,-1,text,1);
+ sprintf(text,"AM= %d",ps[snum].ammo_amount[GROW_WEAPON]);
+ printext256(x,y+43L,31,-1,text,1);
+ sprintf(text,"LFW= %d",ps[snum].last_full_weapon);
+ printext256(x,y+50L,31,-1,text,1);
+ sprintf(text,"SECTL= %d",sector[ps[snum].cursectnum].lotag);
+ printext256(x,y+57L,31,-1,text,1);
+ sprintf(text,"SEED= %d",randomseed);
+ printext256(x,y+64L,31,-1,text,1);
+ sprintf(text,"THOLD= %d",ps[snum].transporter_hold);
+ printext256(x,y+64L+7,31,-1,text,1);
+}
+
+void operatefta(void)
+{
+ int32_t i, j, k;
+
+ if(ud.screen_size > 0) j = 200-45; else j = 200-8;
+ quotebot = min(quotebot,j);
+ quotebotgoal = min(quotebotgoal,j);
+ if(ps[myconnectindex].gm&MODE_TYPE) j -= 8;
+ quotebotgoal = j; j = quotebot;
+ for(i=0;i<MAXUSERQUOTES;i++)
+ {
+ k = user_quote_time[i]; if (k <= 0) break;
+
+ if (k > 4)
+ gametext(320>>1,j,user_quote[i],0,2+8+16);
+ else if (k > 2) gametext(320>>1,j,user_quote[i],0,2+8+16+1);
+ else gametext(320>>1,j,user_quote[i],0,2+8+16+1+32);
+ j -= 8;
+ }
+
+ if (ps[screenpeek].fta <= 1) return;
+
+ if (ud.coop != 1 && ud.screen_size > 0 && ud.multimode > 1)
+ {
+ j = 0; k = 8;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (i > j) j = i;
+
+ if (j >= 4 && j <= 8) k += 8;
+ else if (j > 8 && j <= 12) k += 16;
+ else if (j > 12) k += 24;
+ }
+ else k = 0;
+
+ if (ps[screenpeek].ftq == 115 || ps[screenpeek].ftq == 116)
+ {
+ k = quotebot;
+ for(i=0;i<MAXUSERQUOTES;i++)
+ {
+ if (user_quote_time[i] <= 0) break;
+ k -= 8;
+ }
+ k -= 4;
+ }
+
+ j = ps[screenpeek].fta;
+ if (j > 4)
+ gametext(320>>1,k,fta_quotes[ps[screenpeek].ftq],0,2+8+16);
+ else
+ if (j > 2) gametext(320>>1,k,fta_quotes[ps[screenpeek].ftq],0,2+8+16+1);
+ else
+ gametext(320>>1,k,fta_quotes[ps[screenpeek].ftq],0,2+8+16+1+32);
+}
+
+void FTA(short q,struct player_struct *p, int mode)
+{
+ if( ud.fta_on == 1 || mode)
+ {
+ if( p->fta > 0 && q != 115 && q != 116 )
+ if( p->ftq == 115 || p->ftq == 116 ) return;
+
+ p->fta = 100;
+
+ if( p->ftq != q || q == 26 )
+ // || q == 26 || q == 115 || q ==116 || q == 117 || q == 122 )
+ {
+ p->ftq = q;
+ pub = NUMPAGES;
+ pus = NUMPAGES;
+ }
+ }
+}
+
+void showtwoscreens(void)
+{
+ short i;
+
+ if(VOLUMEONE)
+ {
+ setview(0,0,xdim-1,ydim-1);
+ flushperms();
+ ps[myconnectindex].palette = palette;
+ for(i=0;i<64;i+=7) palto(0,0,0,i);
+ KB_FlushKeyboardQueue();
+
+ rotatesprite(0,0,65536L,0,3291,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+
+ nextpage();
+ for(i=63;i>0;i-=7) palto(0,0,0,i);
+
+ while( !KB_KeyWaiting() ); // getpackets(); // Net already off. Trying to get packets here makes sporadic crash..
+
+ for(i=0;i<64;i+=7)
+ palto(0,0,0,i);
+
+ KB_FlushKeyboardQueue();
+
+ rotatesprite(0,0,65536L,0,3290,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage();
+
+ for(i=63;i>0;i-=7)
+ palto(0,0,0,i);
+
+ while( !KB_KeyWaiting() ); // getpackets();
+ }
+ else if(PLUTOPAK)
+ {
+ setview(0,0,xdim-1,ydim-1);
+ flushperms();
+ ps[myconnectindex].palette = palette;
+
+ for(i=0;i<64;i+=7)
+ palto(0,0,0,i);
+
+ KB_FlushKeyboardQueue();
+
+ clearview(0L);
+ rotatesprite(0,0,65536L,0,TENSCREEN,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage();
+
+ for(i=63;i>0;i-=7)
+ palto(0,0,0,i);
+
+ totalclock = 0;
+
+ while( !KB_KeyWaiting() );
+
+ }
+}
+
+
+void gameexit(char *msg)
+{
+ char t[256];
+
+ strncpy(t,msg,256); t[255] = 0;
+
+ if(*t != 0) ps[myconnectindex].palette = (uint8_t *) &palette[0];
+
+ if(numplayers > 1)
+ allowtimetocorrecterrorswhenquitting();
+
+ if(ud.recstat == 1)
+ closedemowrite();
+
+ if(frecfilep != NULL)
+ {
+ fclose(frecfilep);
+ frecfilep = NULL;
+ }
+
+ if(qe || cp)
+ goto GOTOHERE;
+
+ // FIX_00089: scoreboard not shown for last player who quits a DM. Only 19.7 affected. (Sarah)
+ if( ud.m_recstat != 2 && ud.last_level >= 0 && playerswhenstarted > 1 && ud.coop != 1 && *t == ' ')
+ {
+ dobonus(1);
+// CTW - MODIFICATION
+// setgamemode();
+// FIX_00028: No need to call the videodriver on gameexit()
+// setgamemode(ScreenMode,ScreenWidth,ScreenHeight);
+// CTW END - MODIFICATION
+ }
+
+ if(playerswhenstarted > 1)
+ uninitmultiplayers(); /* deinits network transport. */
+
+// CTW - MODIFICATION
+/* if( *t != 0 && *(t+1) != 'V' && *(t+1) != 'Y' && playonten == 0 )
+ showtwoscreens();*/
+ if( *t != 0 && *(t+1) != 'V' && *(t+1) != 'Y' && true)
+ if(ud.showcinematics) // FIX_00029: toggle cinematics on / off
+ showtwoscreens();
+// CTW END - MODIFICATION
+
+GOTOHERE:
+
+ Shutdown();
+
+ if(*t != 0)
+ {
+ setvmode(0x3);
+
+// CTW - MODIFICATION
+/* if(playonten == 0)
+ {
+ if(*t == ' ' && *(t+1) == 0) *t = 0;
+ printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+ printf("%s%s","\n",t);
+ }*/
+ if(true)
+ {
+ if(*t == ' ' && *(t+1) == 0) *t = 0;
+#if PLATFORM_DOS // Is there a good reason for this? --ryan.
+ printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
+#else
+ printf("\n%s\n",t);
+#endif
+ }
+// CTW END - MODIFICATION
+ }
+
+ uninitgroupfile();
+
+ unlink("duke3d.tmp");
+
+ Error(EXIT_SUCCESS, "");
+
+}
+
+
+
+
+short inputloc = 0;
+short strget(short x,short y,char *t,short dalen,short c)
+{
+ short ch,sc;
+
+ while(KB_KeyWaiting())
+ {
+ sc = 0;
+ ch = KB_Getch();
+
+ if (ch == 0)
+ {
+
+ sc = KB_Getch();
+ if( sc == 104) return(1);
+
+ continue;
+ }
+ else
+ {
+ if(ch == 8) // asc_BackSpace
+ {
+ if( inputloc > 0 )
+ {
+ inputloc--;
+ *(t+inputloc) = 0;
+ }
+ }
+ else
+ {
+ if(ch == asc_Enter || sc == 104)
+ {
+ KB_ClearKeyDown(sc_Enter);
+ KB_ClearKeyDown(sc_kpad_Enter);
+ return (1);
+ }
+ else if(ch == asc_Escape)
+ {
+ KB_ClearKeyDown(sc_Escape);
+ return (-1);
+ }
+ else if ( ch >= 32 && inputloc < dalen && ch < 127)
+ {
+ ch = toupper(ch);
+ *(t+inputloc) = ch;
+ *(t+inputloc+1) = 0;
+ inputloc++;
+ }
+ }
+ }
+ }
+
+ if( c == 999 ) return(0);
+ if( c == 998 )
+ {
+ char b[41],ii;
+ for(ii=0;ii<inputloc;ii++)
+ b[ii] = '*';
+ b[ii] = 0;
+ x = gametext(x,y,b,c,2+8+16);
+ }
+ else x = gametext(x,y,t,c,2+8+16);
+ c = 4-(sintable[(totalclock<<4)&2047]>>11);
+ rotatesprite((x+8)<<16,(y+4)<<16,32768L,0,SPINNINGNUKEICON+((totalclock>>3)%7),c,0,2+8,0,0,xdim-1,ydim-1);
+
+ return (0);
+}
+
+void typemode(void)
+{
+ short ch, hitstate, i, j;
+ char text[512];
+
+ if( ps[myconnectindex].gm&MODE_SENDTOWHOM )
+ {
+ if(sendmessagecommand != -1 || ud.multimode < 3 || movesperpacket == 4)
+ {
+ text[0] = 4; // message command
+ text[1] = 0;
+ recbuf[0] = 0;
+
+ if(ud.multimode < 3)
+ sendmessagecommand = 2;
+
+ strcat(recbuf,ud.user_name[myconnectindex]);
+ strcat(recbuf,": ");
+ strcat(recbuf,typebuf);
+ j = strlen(recbuf);
+ recbuf[j] = 0;
+ strcat(text+1,recbuf);
+
+ if(sendmessagecommand >= ud.multimode || movesperpacket == 4)
+ {
+ for(ch=connecthead;ch >= 0;ch=connectpoint2[ch])
+ if (ch != myconnectindex)
+ sendpacket(ch,(uint8_t*)tempbuf,j+1);
+
+ adduserquote(recbuf);
+ quotebot += 8;
+ quotebotgoal = quotebot;
+ }
+ else if(sendmessagecommand >= 0)
+ sendpacket(sendmessagecommand,(uint8_t*)tempbuf,j+1);
+
+ sendmessagecommand = -1;
+ ps[myconnectindex].gm &= ~(MODE_TYPE|MODE_SENDTOWHOM);
+ }
+ else if(sendmessagecommand == -1)
+ {
+ j = 50;
+ gametext(320>>1,j,"SEND MESSAGE TO...",0,2+8+16); j += 8;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+// for(i=0;i<ud.multimode;i++)
+ {
+ if (i == myconnectindex)
+ {
+ minitextshade((320>>1)-40+1,j+1,"A/ENTER - ALL",26,0,2+8+16);
+ minitext((320>>1)-40,j,"A/ENTER - ALL",0,2+8+16); j += 7;
+ }
+ else
+ {
+ sprintf(buf," %d - %s",i+1,ud.user_name[i]);
+ minitextshade((320>>1)-40-6+1,j+1,buf,26,0,2+8+16);
+ minitext((320>>1)-40-6,j,buf,0,2+8+16); j += 7;
+ }
+ }
+ minitextshade((320>>1)-40-4+1,j+1," ESC - Abort",26,0,2+8+16);
+ minitext((320>>1)-40-4,j," ESC - Abort",0,2+8+16); j += 7;
+
+ //sprintf(buf,"PRESS 1-%ld FOR INDIVIDUAL PLAYER.",ud.multimode);
+ //gametext(320>>1,j,buf,0,2+8+16); j += 8;
+ //gametext(320>>1,j,"'A' OR 'ENTER' FOR ALL PLAYERS",0,2+8+16); j += 8;
+ //gametext(320>>1,j,"ESC ABORTS",0,2+8+16); j += 8;
+
+ if (ud.screen_size > 0) j = 200-45; else j = 200-8;
+ gametext(320>>1,j,typebuf,0,2+8+16);
+
+ if( KB_KeyWaiting() )
+ {
+ i = KB_Getch();
+
+ if(i == 'A' || i == 'a' || i == 13)
+ sendmessagecommand = ud.multimode;
+ else if(i >= '1' || i <= (ud.multimode + '1') )
+ sendmessagecommand = i - '1';
+ else
+ {
+ sendmessagecommand = ud.multimode;
+ if(i == 27)
+ {
+ ps[myconnectindex].gm &= ~(MODE_TYPE|MODE_SENDTOWHOM);
+ sendmessagecommand = -1;
+ }
+ else
+ typebuf[0] = 0;
+ }
+
+ KB_ClearKeyDown(sc_1);
+ KB_ClearKeyDown(sc_2);
+ KB_ClearKeyDown(sc_3);
+ KB_ClearKeyDown(sc_4);
+ KB_ClearKeyDown(sc_5);
+ KB_ClearKeyDown(sc_6);
+ KB_ClearKeyDown(sc_7);
+ KB_ClearKeyDown(sc_8);
+ KB_ClearKeyDown(sc_A);
+ KB_ClearKeyDown(sc_Escape);
+ KB_ClearKeyDown(sc_Enter);
+ }
+ }
+ }
+ else
+ {
+ if(ud.screen_size > 0) j = 200-45; else j = 200-8;
+ hitstate = strget(320>>1,j,typebuf,30,1);
+
+ if(hitstate == 1)
+ {
+ KB_ClearKeyDown(sc_Enter);
+ ps[myconnectindex].gm |= MODE_SENDTOWHOM;
+ }
+ else if(hitstate == -1)
+ ps[myconnectindex].gm &= ~(MODE_TYPE|MODE_SENDTOWHOM);
+ else pub = NUMPAGES;
+ }
+}
+
+void moveclouds(void)
+{
+ if( totalclock > cloudtotalclock || totalclock < (cloudtotalclock-7))
+ {
+ short i;
+
+ cloudtotalclock = totalclock+6;
+
+ for(i=0;i<numclouds;i++)
+ {
+ cloudx[i] += (sintable[(ps[screenpeek].ang+512)&2047]>>9);
+ cloudy[i] += (sintable[ps[screenpeek].ang&2047]>>9);
+
+ sector[clouds[i]].ceilingxpanning = cloudx[i]>>6;
+ sector[clouds[i]].ceilingypanning = cloudy[i]>>6;
+ }
+ }
+}
+
+
+void displayrest(int32_t smoothratio)
+{
+ int32_t a, i, j;
+
+ struct player_struct *pp;
+ walltype *wal;
+ int32_t cposx,cposy,cang;
+
+ pp = &ps[screenpeek];
+
+
+ if(ud.show_help)
+ {
+ switch(ud.show_help)
+ {
+ case 1:
+ rotatesprite(0,0,65536L,0,TEXTSTORY,0,0,10+16+64, 0,0,xdim-1,ydim-1);
+ break;
+ case 2:
+ rotatesprite(0,0,65536L,0,F1HELP,0,0,10+16+64, 0,0,xdim-1,ydim-1);
+ break;
+ }
+
+ if ( KB_KeyPressed(sc_Escape ) )
+ {
+ KB_ClearKeyDown(sc_Escape);
+ ud.show_help = 0;
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 1;
+ totalclock = ototalclock;
+ }
+ vscrn();
+ }
+ return;
+ }
+
+ i = pp->cursectnum;
+
+ show2dsector[i>>3] |= (1<<(i&7));
+ wal = &wall[sector[i].wallptr];
+ for(j=sector[i].wallnum;j>0;j--,wal++)
+ {
+ i = wal->nextsector;
+ if (i < 0) continue;
+ if (wal->cstat&0x0071) continue;
+ if (wall[wal->nextwall].cstat&0x0071) continue;
+ if (sector[i].lotag == 32767) continue;
+ if (sector[i].ceilingz >= sector[i].floorz) continue;
+ show2dsector[i>>3] |= (1<<(i&7));
+ }
+
+ if(ud.camerasprite == -1)
+ {
+ if( ud.overhead_on != 2 )
+ {
+ if(pp->newowner >= 0)
+ cameratext(pp->newowner);
+ else
+ {
+ displayweapon(screenpeek);
+ if(pp->over_shoulder_on == 0 )
+ displaymasks(screenpeek);
+ }
+ moveclouds();
+ }
+
+ if( ud.overhead_on > 0 )
+ {
+ smoothratio = min(max(smoothratio,0),65536);
+ dointerpolations(smoothratio);
+ if( ud.scrollmode == 0 )
+ {
+ if(pp->newowner == -1)
+ {
+ if (screenpeek == myconnectindex && numplayers > 1)
+ {
+ cposx = omyx+mulscale16((int32_t)(myx-omyx),smoothratio);
+ cposy = omyy+mulscale16((int32_t)(myy-omyy),smoothratio);
+ cang = omyang+mulscale16((int32_t)(((myang+1024-omyang)&2047)-1024),smoothratio);
+ }
+ else
+ {
+ cposx = pp->oposx+mulscale16((int32_t)(pp->posx-pp->oposx),smoothratio);
+ cposy = pp->oposy+mulscale16((int32_t)(pp->posy-pp->oposy),smoothratio);
+ cang = pp->oang+mulscale16((int32_t)(((pp->ang+1024-pp->oang)&2047)-1024),smoothratio);
+ }
+ }
+ else
+ {
+ cposx = pp->oposx;
+ cposy = pp->oposy;
+ cang = pp->oang;
+ }
+ }
+ else
+ {
+
+ ud.fola += ud.folavel>>3;
+ ud.folx += (ud.folfvel*sintable[(512+2048-ud.fola)&2047])>>14;
+ ud.foly += (ud.folfvel*sintable[(512+1024-512-ud.fola)&2047])>>14;
+
+ cposx = ud.folx;
+ cposy = ud.foly;
+ cang = ud.fola;
+ }
+
+ if(ud.overhead_on == 2)
+ {
+ clearview(0L);
+ drawmapview(cposx,cposy,pp->zoom,cang);
+ }
+ drawoverheadmap( cposx,cposy,pp->zoom,cang);
+
+ restoreinterpolations();
+
+ if(ud.overhead_on == 2)
+ {
+ if(ud.screen_size > 0) a = 147;
+ else a = 182;
+
+ minitext(1,a+6,volume_names[ud.volume_number],0,2+8+16);
+ minitext(1,a+12,level_names[ud.volume_number*11 + ud.level_number],0,2+8+16);
+ }
+ }
+ }
+
+ coolgaugetext(screenpeek);
+ operatefta();
+
+ if( KB_KeyPressed(sc_Escape) && ud.overhead_on == 0
+ && ud.show_help == 0
+ && ps[myconnectindex].newowner == -1)
+ {
+ if( (ps[myconnectindex].gm&MODE_MENU) != MODE_MENU &&
+ ps[myconnectindex].newowner == -1 &&
+ (ps[myconnectindex].gm&MODE_TYPE) != MODE_TYPE)
+ {
+ KB_ClearKeyDown(sc_Escape);
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+ intomenusounds();
+
+ ps[myconnectindex].gm |= MODE_MENU;
+
+ if(ud.multimode < 2 && ud.recstat != 2) ready2send = 0;
+
+ if(ps[myconnectindex].gm&MODE_GAME) cmenu(50);
+ else cmenu(0);
+ screenpeek = myconnectindex;
+ }
+ }
+
+ if(ps[myconnectindex].newowner == -1 && ud.overhead_on == 0 && ud.crosshair && ud.camerasprite == -1)
+ rotatesprite((160L-(ps[myconnectindex].look_ang>>1))<<16,100L<<16,65536L,0,CROSSHAIR,0,0,2+1,windowx1,windowy1,windowx2,windowy2);
+
+ if(ps[myconnectindex].gm&MODE_TYPE)
+ typemode();
+ else
+ {
+ CONSOLE_HandleInput();
+ if( !CONSOLE_IsActive())
+ {
+ menus();
+ }
+ CONSOLE_Render();
+ }
+
+ if( ud.pause_on==1 && (ps[myconnectindex].gm&MODE_MENU) == 0 )
+ {
+ if (!CONSOLE_IsActive()) //Addfaz Console Pause Game line addition
+ {
+ menutext(160,100,0,0,"GAME PAUSED");
+ }
+ else
+ {
+ menutext(160,120,0,0,"GAME PAUSED");
+ }
+ }
+
+ if(ud.coords)
+ coords(screenpeek);
+
+ // FIX_00085: Optimized Video driver. FPS increases by +20%.
+ if( pp->pals_time > 0 && pp->loogcnt == 0)
+ {
+ palto( pp->pals[0],
+ pp->pals[1],
+ pp->pals[2],
+ pp->pals_time|128);
+
+ restorepalette = 1;
+ }
+ else if( restorepalette )
+ {
+ setbrightness(ud.brightness>>2,&pp->palette[0]);
+ restorepalette = 0;
+ }
+ else if(pp->loogcnt > 0) palto(0,64,0,(pp->loogcnt>>1)+128);
+
+}
+
+
+void updatesectorz(int32_t x, int32_t y, int32_t z, short *sectnum)
+{
+ walltype *wal;
+ int32_t i, j, cz, fz;
+
+ getzsofslope(*sectnum,x,y,&cz,&fz);
+ if ((z >= cz) && (z <= fz))
+ if (inside(x,y,*sectnum) != 0) return;
+
+ if ((*sectnum >= 0) && (*sectnum < numsectors))
+ {
+ wal = &wall[sector[*sectnum].wallptr];
+ j = sector[*sectnum].wallnum;
+ do
+ {
+ i = wal->nextsector;
+ if (i >= 0)
+ {
+ getzsofslope(i,x,y,&cz,&fz);
+ if ((z >= cz) && (z <= fz))
+ if (inside(x,y,(short)i) == 1)
+ { *sectnum = i; return; }
+ }
+ wal++; j--;
+ } while (j != 0);
+ }
+
+ for(i=numsectors-1;i>=0;i--)
+ {
+ getzsofslope(i,x,y,&cz,&fz);
+ if ((z >= cz) && (z <= fz))
+ if (inside(x,y,(short)i) == 1)
+ { *sectnum = i; return; }
+ }
+
+ *sectnum = -1;
+}
+
+void view(struct player_struct *pp, int32_t *vx, int32_t *vy,int32_t *vz,short *vsectnum, short ang, short horiz)
+{
+ spritetype *sp;
+ int32_t i, nx, ny, nz, hx, hy, hitx, hity, hitz;
+ short bakcstat, hitsect, hitwall, hitsprite, daang;
+
+ nx = (sintable[(ang+1536)&2047]>>4);
+ ny = (sintable[(ang+1024)&2047]>>4);
+ nz = (horiz-100)*128;
+
+ sp = &sprite[pp->i];
+
+ bakcstat = sp->cstat;
+ sp->cstat &= (short)~0x101;
+
+ updatesectorz(*vx,*vy,*vz,vsectnum);
+ hitscan(*vx,*vy,*vz,*vsectnum,nx,ny,nz,&hitsect,&hitwall,&hitsprite,&hitx,&hity,&hitz,CLIPMASK1);
+
+ if(*vsectnum < 0)
+ {
+ sp->cstat = bakcstat;
+ return;
+ }
+
+ hx = hitx-(*vx); hy = hity-(*vy);
+ if (klabs(nx)+klabs(ny) > klabs(hx)+klabs(hy))
+ {
+ *vsectnum = hitsect;
+ if (hitwall >= 0)
+ {
+ daang = getangle(wall[wall[hitwall].point2].x-wall[hitwall].x,
+ wall[wall[hitwall].point2].y-wall[hitwall].y);
+
+ i = nx*sintable[daang]+ny*sintable[(daang+1536)&2047];
+ if (klabs(nx) > klabs(ny)) hx -= mulscale28(nx,i);
+ else hy -= mulscale28(ny,i);
+ }
+ else if (hitsprite < 0)
+ {
+ if (klabs(nx) > klabs(ny)) hx -= (nx>>5);
+ else hy -= (ny>>5);
+ }
+ if (klabs(nx) > klabs(ny)) i = divscale16(hx,nx);
+ else i = divscale16(hy,ny);
+ if (i < cameradist) cameradist = i;
+ }
+ *vx = (*vx)+mulscale16(nx,cameradist);
+ *vy = (*vy)+mulscale16(ny,cameradist);
+ *vz = (*vz)+mulscale16(nz,cameradist);
+
+ cameradist = min(cameradist+((totalclock-cameraclock)<<10),65536);
+ cameraclock = totalclock;
+
+ updatesectorz(*vx,*vy,*vz,vsectnum);
+
+ sp->cstat = bakcstat;
+}
+
+//REPLACE FULLY
+void drawbackground(void)
+{
+ short dapicnum;
+ int32_t x,y,x1,y1,x2,y2;
+
+ flushperms();
+
+ switch(ud.m_volume_number)
+ {
+ default:dapicnum = BIGHOLE;break;
+ case 1:dapicnum = BIGHOLE;break;
+ case 2:dapicnum = BIGHOLE;break;
+ }
+
+ y1 = 0; y2 = ydim;
+ if( ready2send || ud.recstat == 2 )
+ {
+ if(ud.coop != 1)
+ {
+ if (ud.multimode > 1) y1 += scale(ydim,8,200);
+ if (ud.multimode > 4) y1 += scale(ydim,8,200);
+ }
+ if (ud.screen_size >= 8) y2 = scale(ydim,200-34,200);
+ }
+
+ for(y=y1;y<y2;y+=128)
+ for(x=0;x<xdim;x+=128)
+ rotatesprite(x<<16,y<<16,65536L,0,dapicnum,8,0,8+16+64+128,0,y1,xdim-1,y2-1);
+
+ // FIX_00081: Screen border in menu
+ if(ud.screen_size > 8 && (ps[myconnectindex].gm & MODE_GAME || ud.recstat == 2 )) // ud.recstat == 2 => playing demo
+ {
+ y = 0;
+ if(ud.coop != 1)
+ {
+ if (ud.multimode > 1) y += 8;
+ if (ud.multimode > 4) y += 8;
+ }
+
+ x1 = max(windowx1-4,0);
+ y1 = max(windowy1-4,y);
+ x2 = min(windowx2+4,xdim-1);
+ y2 = min(windowy2+4,scale(ydim,200-34,200)-1);
+
+ for(y=y1+4;y<y2-4;y+=64)
+ {
+ rotatesprite(x1<<16,y<<16,65536L,0,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
+ rotatesprite((x2+1)<<16,(y+64)<<16,65536L,1024,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
+ }
+
+ for(x=x1+4;x<x2-4;x+=64)
+ {
+ rotatesprite((x+64)<<16,y1<<16,65536L,512,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
+ rotatesprite(x<<16,(y2+1)<<16,65536L,1536,VIEWBORDER,0,0,8+16+64+128,x1,y1,x2,y2);
+ }
+
+ rotatesprite(x1<<16,y1<<16,65536L,0,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
+ rotatesprite((x2+1)<<16,y1<<16,65536L,512,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
+ rotatesprite((x2+1)<<16,(y2+1)<<16,65536L,1024,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
+ rotatesprite(x1<<16,(y2+1)<<16,65536L,1536,VIEWBORDER+1,0,0,8+16+64+128,x1,y1,x2,y2);
+ }
+}
+
+
+// Floor Over Floor
+
+// If standing in sector with SE42
+// then draw viewing to SE41 and raise all =hi SE43 cielings.
+
+// If standing in sector with SE43
+// then draw viewing to SE40 and lower all =hi SE42 floors.
+
+// If standing in sector with SE44
+// then draw viewing to SE40.
+
+// If standing in sector with SE45
+// then draw viewing to SE41.
+
+#define FOFTILE 13
+#define FOFTILEX 32
+#define FOFTILEY 32
+int32_t tempsectorz[MAXSECTORS];
+int32_t tempsectorpicnum[MAXSECTORS];
+//short tempcursectnum;
+
+static void SE40_Draw(int spnum,int32_t x,int32_t y,int32_t z,short a,short h,int32_t smoothratio)
+{
+ int i=0,j=0,k=0;
+ int floor1=0,floor2=0,ok=0,fofmode=0;
+ int32_t offx,offy;
+
+ if(sprite[spnum].ang!=512) return;
+
+ i = FOFTILE; //Effect TILE
+ if (!(gotpic[i>>3]&(1<<(i&7)))) return;
+ gotpic[i>>3] &= ~(1<<(i&7));
+
+ floor1=spnum;
+
+ if(sprite[spnum].lotag==42) fofmode=40;
+ if(sprite[spnum].lotag==43) fofmode=41;
+ if(sprite[spnum].lotag==44) fofmode=40;
+ if(sprite[spnum].lotag==45) fofmode=41;
+
+// fofmode=sprite[spnum].lotag-2;
+
+// sectnum=sprite[j].sectnum;
+// sectnum=cursectnum;
+ ok++;
+
+/* recursive?
+ for(j=0;j<MAXSPRITES;j++)
+ {
+ if(
+ sprite[j].sectnum==sectnum &&
+ sprite[j].picnum==1 &&
+ sprite[j].lotag==110
+ ) { DrawFloorOverFloor(j); break;}
+ }
+*/
+
+// if(ok==0) { Message("no fof",RED); return; }
+
+ for(j=0;j<MAXSPRITES;j++)
+ {
+ if(
+ sprite[j].picnum==1 &&
+ sprite[j].lotag==fofmode &&
+ sprite[j].hitag==sprite[floor1].hitag
+ ) { floor1=j; fofmode=sprite[j].lotag; ok++; break;}
+ }
+// if(ok==1) { Message("no floor1",RED); return; }
+
+ if(fofmode==40) k=41; else k=40;
+
+ for(j=0;j<MAXSPRITES;j++)
+ {
+ if(
+ sprite[j].picnum==1 &&
+ sprite[j].lotag==k &&
+ sprite[j].hitag==sprite[floor1].hitag
+ )
+ {
+ floor2=j;
+ ok++;
+ break;
+ }
+ }
+
+// if(ok==2) { Message("no floor2",RED); return; }
+
+ for(j=0;j<MAXSPRITES;j++) // raise ceiling or floor
+ {
+ if(sprite[j].picnum==1 &&
+ sprite[j].lotag==k+2 &&
+ sprite[j].hitag==sprite[floor1].hitag
+ )
+ {
+ if(k==40)
+ {tempsectorz[sprite[j].sectnum]=sector[sprite[j].sectnum].floorz;
+ sector[sprite[j].sectnum].floorz+=(((z-sector[sprite[j].sectnum].floorz)/32768)+1)*32768;
+ tempsectorpicnum[sprite[j].sectnum]=sector[sprite[j].sectnum].floorpicnum;
+ sector[sprite[j].sectnum].floorpicnum=13;
+ }
+ if(k==41)
+ {tempsectorz[sprite[j].sectnum]=sector[sprite[j].sectnum].ceilingz;
+ sector[sprite[j].sectnum].ceilingz+=(((z-sector[sprite[j].sectnum].ceilingz)/32768)-1)*32768;
+ tempsectorpicnum[sprite[j].sectnum]=sector[sprite[j].sectnum].ceilingpicnum;
+ sector[sprite[j].sectnum].ceilingpicnum=13;
+ }
+ }
+ }
+
+ i=floor1;
+ offx=x-sprite[i].x;
+ offy=y-sprite[i].y;
+ i=floor2;
+ drawrooms(offx+sprite[i].x,offy+sprite[i].y,z,a,h,sprite[i].sectnum);
+ animatesprites(x,y,a,smoothratio);
+ drawmasks();
+
+ for(j=0;j<MAXSPRITES;j++) // restore ceiling or floor
+ {
+ if(sprite[j].picnum==1 &&
+ sprite[j].lotag==k+2 &&
+ sprite[j].hitag==sprite[floor1].hitag
+ )
+ {
+ if(k==40)
+ {sector[sprite[j].sectnum].floorz=tempsectorz[sprite[j].sectnum];
+ sector[sprite[j].sectnum].floorpicnum=tempsectorpicnum[sprite[j].sectnum];
+ }
+ if(k==41)
+ {sector[sprite[j].sectnum].ceilingz=tempsectorz[sprite[j].sectnum];
+ sector[sprite[j].sectnum].ceilingpicnum=tempsectorpicnum[sprite[j].sectnum];
+ }
+ }// end if
+ }// end for
+
+} // end SE40
+
+
+
+
+static void se40code(int32_t x,int32_t y,int32_t z,int32_t a,int32_t h, int32_t smoothratio)
+{
+ int i;
+
+ i = headspritestat[15];
+ while(i >= 0)
+ {
+ switch(sprite[i].lotag)
+ {
+// case 40:
+// case 41:
+// SE40_Draw(i,x,y,a,smoothratio);
+// break;
+ case 42:
+ case 43:
+ case 44:
+ case 45:
+ if(ps[screenpeek].cursectnum == sprite[i].sectnum)
+ SE40_Draw(i,x,y,z,a,h,smoothratio);
+ break;
+ }
+ i = nextspritestat[i];
+ }
+}
+
+static int32_t oyrepeat=-1;
+
+void displayrooms(short snum,int32_t smoothratio)
+{
+ int32_t cposx,cposy,cposz,dst,j,fz,cz;
+ short sect, cang, k, choriz;
+ struct player_struct *p;
+ int32_t tposx,tposy,i;
+ short tang;
+
+ p = &ps[snum];
+
+ if(pub > 0)
+ {
+ if(ud.screen_size > 8) drawbackground();
+ pub = 0;
+ }
+
+ if( ud.overhead_on == 2 || ud.show_help || p->cursectnum == -1)
+ return;
+
+ smoothratio = min(max(smoothratio,0),65536);
+
+ visibility = p->visibility;
+
+ if(ud.pause_on || ps[snum].on_crane > -1) smoothratio = 65536;
+
+ sect = p->cursectnum;
+ if(sect < 0 || sect >= MAXSECTORS) return;
+
+ dointerpolations(smoothratio);
+
+ animatecamsprite();
+
+ if(ud.camerasprite >= 0)
+ {
+ spritetype *s;
+
+ s = &sprite[ud.camerasprite];
+
+ if(s->yvel < 0) s->yvel = -100;
+ else if(s->yvel > 199) s->yvel = 300;
+
+ cang = hittype[ud.camerasprite].tempang+mulscale16((int32_t)(((s->ang+1024-hittype[ud.camerasprite].tempang)&2047)-1024),smoothratio);
+
+ se40code(s->x,s->y,s->z,cang,s->yvel,smoothratio);
+
+ drawrooms(s->x,s->y,s->z-(4<<8),cang,s->yvel,s->sectnum);
+ animatesprites(s->x,s->y,cang,smoothratio);
+ drawmasks();
+ }
+ else
+ {
+ i = divscale22(1,sprite[p->i].yrepeat+28);
+ if (i != oyrepeat)
+ {
+ oyrepeat = i;
+ //printf("1: %d %d\n", oyrepeat,yxaspect);
+ setaspect(oyrepeat,yxaspect);
+ //printf("2: %d %d\n", oyrepeat,yxaspect);
+ }
+
+ if(screencapt)
+ {
+ tiles[MAXTILES-1].lock = 254;
+ if (tiles[MAXTILES-1].data == NULL)
+ allocache(&tiles[MAXTILES-1].data,100*160,&tiles[MAXTILES-1].lock);
+
+ setviewtotile(MAXTILES-1,100L,160L);
+ }
+ else if( ( ud.screen_tilting && p->rotscrnang ) || ud.detail==0 )
+ {
+ if (ud.screen_tilting) tang = p->rotscrnang; else tang = 0;
+
+ tiles[MAXTILES-2].lock = 255;
+ if (tiles[MAXTILES-2].data == NULL)
+ allocache(&tiles[MAXTILES-2].data,320L*320L,&tiles[MAXTILES-2].lock);
+ if ((tang&1023) == 0)
+ setviewtotile(MAXTILES-2,200L>>(1-ud.detail),320L>>(1-ud.detail));
+ else
+ setviewtotile(MAXTILES-2,320L>>(1-ud.detail),320L>>(1-ud.detail));
+ if ((tang&1023) == 512)
+ { //Block off unscreen section of 90ø tilted screen
+ j = ((320-60)>>(1-ud.detail));
+ for(i=(60>>(1-ud.detail))-1;i>=0;i--)
+ {
+ startumost[i] = 1; startumost[i+j] = 1;
+ startdmost[i] = 0; startdmost[i+j] = 0;
+ }
+ }
+
+ i = (tang&511); if (i > 256) i = 512-i;
+ i = sintable[i+512]*8 + sintable[i]*5L;
+ setaspect(i>>1,yxaspect);
+ }
+
+ if ( (snum == myconnectindex) && (numplayers > 1) )
+ {
+ cposx = omyx+mulscale16((int32_t)(myx-omyx),smoothratio);
+ cposy = omyy+mulscale16((int32_t)(myy-omyy),smoothratio);
+ cposz = omyz+mulscale16((int32_t)(myz-omyz),smoothratio);
+ cang = omyang+mulscale16((int32_t)(((myang+1024-omyang)&2047)-1024),smoothratio);
+ choriz = omyhoriz+omyhorizoff+mulscale16((int32_t)(myhoriz+myhorizoff-omyhoriz-omyhorizoff),smoothratio);
+ sect = mycursectnum;
+ }
+ else
+ {
+ cposx = p->oposx+mulscale16((int32_t)(p->posx-p->oposx),smoothratio);
+ cposy = p->oposy+mulscale16((int32_t)(p->posy-p->oposy),smoothratio);
+ cposz = p->oposz+mulscale16((int32_t)(p->posz-p->oposz),smoothratio);
+ cang = p->oang+mulscale16((int32_t)(((p->ang+1024-p->oang)&2047)-1024),smoothratio);
+ choriz = p->ohoriz+p->ohorizoff+mulscale16((int32_t)(p->horiz+p->horizoff-p->ohoriz-p->ohorizoff),smoothratio);
+ }
+ cang += p->look_ang;
+
+ if (p->newowner >= 0)
+ {
+ cang = p->ang+p->look_ang;
+ choriz = p->horiz+p->horizoff;
+ cposx = p->posx;
+ cposy = p->posy;
+ cposz = p->posz;
+ sect = sprite[p->newowner].sectnum;
+ smoothratio = 65536L;
+ }
+
+ else if( p->over_shoulder_on == 0 )
+ cposz += p->opyoff+mulscale16((int32_t)(p->pyoff-p->opyoff),smoothratio);
+ else view(p,&cposx,&cposy,&cposz,&sect,cang,choriz);
+
+ cz = hittype[p->i].ceilingz;
+ fz = hittype[p->i].floorz;
+
+ if(earthquaketime > 0 && p->on_ground == 1)
+ {
+ cposz += 256-(((earthquaketime)&1)<<9);
+ cang += (2-((earthquaketime)&2))<<2;
+ }
+
+ if(sprite[p->i].pal == 1) cposz -= (18<<8);
+
+ if(p->newowner >= 0)
+ choriz = 100+sprite[p->newowner].shade;
+ else if(p->spritebridge == 0)
+ {
+ if( cposz < ( p->truecz + (4<<8) ) ) cposz = cz + (4<<8);
+ else if( cposz > ( p->truefz - (4<<8) ) ) cposz = fz - (4<<8);
+ }
+
+ if (sect >= 0)
+ {
+ getzsofslope(sect,cposx,cposy,&cz,&fz);
+ if (cposz < cz+(4<<8)) cposz = cz+(4<<8);
+ if (cposz > fz-(4<<8)) cposz = fz-(4<<8);
+ }
+
+ if(choriz > 299) choriz = 299;
+ else if(choriz < -99) choriz = -99;
+
+ se40code(cposx,cposy,cposz,cang,choriz,smoothratio);
+
+ if ((gotpic[MIRROR>>3]&(1<<(MIRROR&7))) > 0)
+ {
+ dst = 0x7fffffff; i = 0;
+ for(k=0;k<mirrorcnt;k++)
+ {
+ j = klabs(wall[mirrorwall[k]].x-cposx);
+ j += klabs(wall[mirrorwall[k]].y-cposy);
+ if (j < dst) dst = j, i = k;
+ }
+
+ if( wall[mirrorwall[i]].overpicnum == MIRROR )
+ {
+ preparemirror(cposx,cposy,cposz,cang,choriz,mirrorwall[i],mirrorsector[i],&tposx,&tposy,&tang);
+
+ j = visibility;
+ visibility = (j>>1) + (j>>2);
+
+ drawrooms(tposx,tposy,cposz,tang,choriz,mirrorsector[i]+MAXSECTORS);
+
+ display_mirror = 1;
+ animatesprites(tposx,tposy,tang,smoothratio);
+ display_mirror = 0;
+
+ drawmasks();
+ completemirror(); //Reverse screen x-wise in this function
+ visibility = j;
+ }
+ gotpic[MIRROR>>3] &= ~(1<<(MIRROR&7));
+ }
+
+ drawrooms(cposx,cposy,cposz,cang,choriz,sect);
+ animatesprites(cposx,cposy,cang,smoothratio);
+ drawmasks();
+
+ if(screencapt == 1)
+ {
+ setviewback();
+ tiles[MAXTILES-1].lock = 1;
+ screencapt = 0;
+ }
+ else if( ( ud.screen_tilting && p->rotscrnang) || ud.detail==0 )
+ {
+ if (ud.screen_tilting) tang = p->rotscrnang; else tang = 0;
+ setviewback();
+ tiles[MAXTILES-2].animFlags &= 0xff0000ff;
+ i = (tang&511); if (i > 256) i = 512-i;
+ i = sintable[i+512]*8 + sintable[i]*5L;
+ if ((1-ud.detail) == 0) i >>= 1;
+ rotatesprite(160<<16,100<<16,i,tang+512,MAXTILES-2,0,0,4+2+64,windowx1,windowy1,windowx2,windowy2);
+ tiles[MAXTILES-2].lock = 199;
+ }
+ }
+
+ restoreinterpolations();
+
+ if (totalclock < lastvisinc)
+ {
+ if (klabs(p->visibility-ud.const_visibility) > 8)
+ p->visibility += (ud.const_visibility-p->visibility)>>2;
+ }
+ else p->visibility = ud.const_visibility;
+}
+
+
+
+
+
+short LocateTheLocator(short n,short sn)
+{
+ short i;
+
+ i = headspritestat[7];
+ while(i >= 0)
+ {
+ if( (sn == -1 || sn == SECT) && n == SLT )
+ return i;
+ i = nextspritestat[i];
+ }
+ return -1;
+}
+
+short EGS(short whatsect,int32_t s_x,int32_t s_y,int32_t s_z,short s_pn,int8_t s_s,int8_t s_xr,int8_t s_yr,short s_a,short s_ve,int32_t s_zv,short s_ow,int8_t s_ss)
+{
+ short i;
+ spritetype *s;
+
+ i = insertsprite(whatsect,s_ss);
+
+ if( i < 0 )
+ gameexit(" Too many sprites spawned. This may happen (for any duke port) if you have hacked the steroids trail in the *.con files. If so, delete your *.con files to use the internal ones and try again.");
+
+ hittype[i].bposx = s_x;
+ hittype[i].bposy = s_y;
+ hittype[i].bposz = s_z;
+
+ s = &sprite[i];
+
+ s->x = s_x;
+ s->y = s_y;
+ s->z = s_z;
+ s->cstat = 0;
+ s->picnum = s_pn;
+ s->shade = s_s;
+ s->xrepeat = s_xr;
+ s->yrepeat = s_yr;
+ s->pal = 0;
+
+ s->ang = s_a;
+ s->xvel = s_ve;
+ s->zvel = s_zv;
+ s->owner = s_ow;
+ s->xoffset = 0;
+ s->yoffset = 0;
+ s->yvel = 0;
+ s->clipdist = 0;
+ s->pal = 0;
+ s->lotag = 0;
+
+ hittype[i].picnum = sprite[s_ow].picnum;
+
+ hittype[i].lastvx = 0;
+ hittype[i].lastvy = 0;
+
+ hittype[i].timetosleep = 0;
+ hittype[i].actorstayput = -1;
+ hittype[i].extra = -1;
+ hittype[i].owner = s_ow;
+ hittype[i].cgg = 0;
+ hittype[i].movflag = 0;
+ hittype[i].tempang = 0;
+ hittype[i].dispicnum = 0;
+ hittype[i].floorz = hittype[s_ow].floorz;
+ hittype[i].ceilingz = hittype[s_ow].ceilingz;
+
+ T1=T3=T4=T6=0;
+ if( actorscrptr[s_pn] )
+ {
+ s->extra = *actorscrptr[s_pn];
+ T5 = *(actorscrptr[s_pn]+1);
+ T2 = *(actorscrptr[s_pn]+2);
+ s->hitag = *(actorscrptr[s_pn]+3);
+ }
+ else
+ {
+ T2=T5=0;
+ s->extra = 0;
+ s->hitag = 0;
+ }
+
+ if (show2dsector[SECT>>3]&(1<<(SECT&7))) show2dsprite[i>>3] |= (1<<(i&7));
+ else show2dsprite[i>>3] &= ~(1<<(i&7));
+/*
+ if(s->sectnum < 0)
+ {
+ s->xrepeat = s->yrepeat = 0;
+ changespritestat(i,5);
+ }
+*/
+ return(i);
+}
+
+uint8_t wallswitchcheck(short i)
+{
+ switch(PN)
+ {
+ case HANDPRINTSWITCH:
+ case HANDPRINTSWITCH+1:
+ case ALIENSWITCH:
+ case ALIENSWITCH+1:
+ case MULTISWITCH:
+ case MULTISWITCH+1:
+ case MULTISWITCH+2:
+ case MULTISWITCH+3:
+ case ACCESSSWITCH:
+ case ACCESSSWITCH2:
+ case PULLSWITCH:
+ case PULLSWITCH+1:
+ case HANDSWITCH:
+ case HANDSWITCH+1:
+ case SLOTDOOR:
+ case SLOTDOOR+1:
+ case LIGHTSWITCH:
+ case LIGHTSWITCH+1:
+ case SPACELIGHTSWITCH:
+ case SPACELIGHTSWITCH+1:
+ case SPACEDOORSWITCH:
+ case SPACEDOORSWITCH+1:
+ case FRANKENSTINESWITCH:
+ case FRANKENSTINESWITCH+1:
+ case LIGHTSWITCH2:
+ case LIGHTSWITCH2+1:
+ case POWERSWITCH1:
+ case POWERSWITCH1+1:
+ case LOCKSWITCH1:
+ case LOCKSWITCH1+1:
+ case POWERSWITCH2:
+ case POWERSWITCH2+1:
+ case DIPSWITCH:
+ case DIPSWITCH+1:
+ case DIPSWITCH2:
+ case DIPSWITCH2+1:
+ case TECHSWITCH:
+ case TECHSWITCH+1:
+ case DIPSWITCH3:
+ case DIPSWITCH3+1:
+ return 1;
+ }
+ return 0;
+}
+
+
+int32_t tempwallptr;
+short spawn( short j, short pn )
+{
+ short i, s, startwall, endwall, sect, clostest;
+ int32_t x, y, d;
+ spritetype *sp;
+ char text[512];
+
+ if(j >= 0)
+ {
+ i = EGS(sprite[j].sectnum,sprite[j].x,sprite[j].y,sprite[j].z
+ ,pn,0,0,0,0,0,0,j,0);
+ hittype[i].picnum = sprite[j].picnum;
+ }
+ else
+ {
+ i = pn;
+
+ hittype[i].picnum = PN;
+ hittype[i].timetosleep = 0;
+ hittype[i].extra = -1;
+
+ hittype[i].bposx = SX;
+ hittype[i].bposy = SY;
+ hittype[i].bposz = SZ;
+
+ OW = hittype[i].owner = i;
+ hittype[i].cgg = 0;
+ hittype[i].movflag = 0;
+ hittype[i].tempang = 0;
+ hittype[i].dispicnum = 0;
+ hittype[i].floorz = sector[SECT].floorz;
+ hittype[i].ceilingz = sector[SECT].ceilingz;
+
+ hittype[i].lastvx = 0;
+ hittype[i].lastvy = 0;
+ hittype[i].actorstayput = -1;
+
+ T1 = T2 = T3 = T4 = T5 = T6 = 0;
+
+ if( PN != SPEAKER && PN != LETTER && PN != DUCK && PN != TARGET && PN != TRIPBOMB && PN != VIEWSCREEN && PN != VIEWSCREEN2 && (CS&48) )
+ if( !(PN >= CRACK1 && PN <= CRACK4) )
+ {
+ if(SS == 127) return i;
+ if( wallswitchcheck(i) == 1 && (CS&16) )
+ {
+ if( PN != ACCESSSWITCH && PN != ACCESSSWITCH2 && sprite[i].pal)
+ {
+ if( (ud.multimode < 2) || (ud.multimode > 1 && ud.coop==1) )
+ {
+ sprite[i].xrepeat = sprite[i].yrepeat = 0;
+ sprite[i].cstat = SLT = SHT = 0;
+ return i;
+ }
+ }
+ CS |= 257;
+ if( sprite[i].pal && PN != ACCESSSWITCH && PN != ACCESSSWITCH2)
+ sprite[i].pal = 0;
+ return i;
+ }
+
+ if( SHT )
+ {
+ changespritestat(i,12);
+ CS |= 257;
+ SH = impact_damage;
+ return i;
+ }
+ }
+
+ s = PN;
+
+ if( CS&1 ) CS |= 256;
+
+ if( actorscrptr[s] )
+ {
+ SH = *(actorscrptr[s]);
+ T5 = *(actorscrptr[s]+1);
+ T2 = *(actorscrptr[s]+2);
+ if( *(actorscrptr[s]+3) && SHT == 0 )
+ SHT = *(actorscrptr[s]+3);
+ }
+ else T2 = T5 = 0;
+ }
+
+ sp = &sprite[i];
+ sect = sp->sectnum;
+
+ switch(sp->picnum)
+ {
+ default:
+
+ if( actorscrptr[sp->picnum] )
+ {
+ if( j == -1 && sp->lotag > ud.player_skill )
+ {
+ sp->xrepeat=sp->yrepeat=0;
+ changespritestat(i,5);
+ break;
+ }
+
+ // Init the size
+ if(sp->xrepeat == 0 || sp->yrepeat == 0)
+ sp->xrepeat = sp->yrepeat = 1;
+
+ if( actortype[sp->picnum] & 3)
+ {
+ if( ud.monsters_off == 1 )
+ {
+ sp->xrepeat=sp->yrepeat=0;
+ changespritestat(i,5);
+ break;
+ }
+
+ makeitfall(i);
+
+ if( actortype[sp->picnum] & 2)
+ hittype[i].actorstayput = sp->sectnum;
+
+ ps[myconnectindex].max_actors_killed++;
+ sp->clipdist = 80;
+ if(j >= 0)
+ {
+ if(sprite[j].picnum == RESPAWN)
+ hittype[i].tempang = sprite[i].pal = sprite[j].pal;
+ changespritestat(i,1);
+ }
+ else changespritestat(i,2);
+ }
+ else
+ {
+ sp->clipdist = 40;
+ sp->owner = i;
+ changespritestat(i,1);
+ }
+
+ hittype[i].timetosleep = 0;
+
+ if(j >= 0)
+ sp->ang = sprite[j].ang;
+ }
+ break;
+ case FOF:
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ case WATERSPLASH2:
+ if(j >= 0)
+ {
+ setsprite(i,sprite[j].x,sprite[j].y,sprite[j].z);
+ sp->xrepeat = sp->yrepeat = 8+(TRAND&7);
+ }
+ else sp->xrepeat = sp->yrepeat = 16+(TRAND&15);
+
+ sp->shade = -16;
+ sp->cstat |= 128;
+ if(j >= 0)
+ {
+ if(sector[sprite[j].sectnum].lotag == 2)
+ {
+ sp->z = getceilzofslope(SECT,SX,SY)+(16<<8);
+ sp->cstat |= 8;
+ }
+ else if( sector[sprite[j].sectnum].lotag == 1)
+ sp->z = getflorzofslope(SECT,SX,SY);
+ }
+
+ if(sector[sect].floorpicnum == FLOORSLIME ||
+ sector[sect].ceilingpicnum == FLOORSLIME)
+ sp->pal = 7;
+ case NEON1:
+ case NEON2:
+ case NEON3:
+ case NEON4:
+ case NEON5:
+ case NEON6:
+ case DOMELITE:
+ if(sp->picnum != WATERSPLASH2)
+ sp->cstat |= 257;
+ case NUKEBUTTON:
+ if(sp->picnum == DOMELITE)
+ sp->cstat |= 257;
+ case JIBS1:
+ case JIBS2:
+ case JIBS3:
+ case JIBS4:
+ case JIBS5:
+ case JIBS6:
+ case HEADJIB1:
+ case ARMJIB1:
+ case LEGJIB1:
+ case LIZMANHEAD1:
+ case LIZMANARM1:
+ case LIZMANLEG1:
+ case DUKETORSO:
+ case DUKEGUN:
+ case DUKELEG:
+ changespritestat(i,5);
+ break;
+ case TONGUE:
+ if(j >= 0)
+ sp->ang = sprite[j].ang;
+ sp->z -= 38<<8;
+ sp->zvel = 256-(TRAND&511);
+ sp->xvel = 64-(TRAND&127);
+ changespritestat(i,4);
+ break;
+ case NATURALLIGHTNING:
+ sp->cstat &= ~257;
+ sp->cstat |= 32768;
+ break;
+ case TRANSPORTERSTAR:
+ case TRANSPORTERBEAM:
+ if(j == -1) break;
+ if(sp->picnum == TRANSPORTERBEAM)
+ {
+ sp->xrepeat = 31;
+ sp->yrepeat = 1;
+ sp->z = sector[sprite[j].sectnum].floorz-(40<<8);
+ }
+ else
+ {
+ if(sprite[j].statnum == 4)
+ {
+ sp->xrepeat = 8;
+ sp->yrepeat = 8;
+ }
+ else
+ {
+ sp->xrepeat = 48;
+ sp->yrepeat = 64;
+ if(sprite[j].statnum == 10 || badguy(&sprite[j]) )
+ sp->z -= (32<<8);
+ }
+ }
+
+ sp->shade = -127;
+ sp->cstat = 128|2;
+ sp->ang = sprite[j].ang;
+
+ sp->xvel = 128;
+ changespritestat(i,5);
+ ssp(i,CLIPMASK0);
+ setsprite(i,sp->x,sp->y,sp->z);
+ break;
+
+ case FRAMEEFFECT1:
+ case FRAMEEFFECT1_13CON:
+ if(j >= 0)
+ {
+ sp->xrepeat = sprite[j].xrepeat;
+ sp->yrepeat = sprite[j].yrepeat;
+ T2 = sprite[j].picnum;
+ }
+ else sp->xrepeat = sp->yrepeat = 0;
+
+ changespritestat(i,5);
+
+ break;
+
+ case LASERLINE:
+ sp->yrepeat = 6;
+ sp->xrepeat = 32;
+
+ if(lasermode == 1)
+ sp->cstat = 16 + 2;
+ else if(lasermode == 0 || lasermode == 2)
+ sp->cstat = 16;
+ else
+ {
+ sp->xrepeat = 0;
+ sp->yrepeat = 0;
+ }
+
+ if(j >= 0) sp->ang = hittype[j].temp_data[5]+512;
+ changespritestat(i,5);
+ break;
+
+ case FORCESPHERE:
+ if(j == -1 )
+ {
+ sp->cstat = (short) 32768;
+ changespritestat(i,2);
+ }
+ else
+ {
+ sp->xrepeat = sp->yrepeat = 1;
+ changespritestat(i,5);
+ }
+ break;
+
+ case BLOOD:
+ sp->xrepeat = sp->yrepeat = 16;
+ sp->z -= (26<<8);
+ if( j >= 0 && sprite[j].pal == 6 )
+ sp->pal = 6;
+ changespritestat(i,5);
+ break;
+ case BLOODPOOL:
+ case PUKE:
+ {
+ short s1;
+ s1 = sp->sectnum;
+
+ updatesector(sp->x+108,sp->y+108,&s1);
+ if(s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
+ {
+ updatesector(sp->x-108,sp->y-108,&s1);
+ if(s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
+ {
+ updatesector(sp->x+108,sp->y-108,&s1);
+ if(s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
+ {
+ updatesector(sp->x-108,sp->y+108,&s1);
+ if(s1 >= 0 && sector[s1].floorz != sector[sp->sectnum].floorz)
+ { sp->xrepeat = sp->yrepeat = 0;changespritestat(i,5);break;}
+ }
+ else { sp->xrepeat = sp->yrepeat = 0;changespritestat(i,5);break;}
+ }
+ else { sp->xrepeat = sp->yrepeat = 0;changespritestat(i,5);break;}
+ }
+ else { sp->xrepeat = sp->yrepeat = 0;changespritestat(i,5);break;}
+ }
+
+ if( sector[SECT].lotag == 1 )
+ {
+ changespritestat(i,5);
+ break;
+ }
+
+ if(j >= 0 && sp->picnum != PUKE)
+ {
+ if( sprite[j].pal == 1)
+ sp->pal = 1;
+ else if( sprite[j].pal != 6 && sprite[j].picnum != NUKEBARREL && sprite[j].picnum != TIRE )
+ {
+ if(sprite[j].picnum == FECES)
+ sp->pal = 7; // Brown
+ else sp->pal = 2; // Red
+ }
+ else sp->pal = 0; // green
+
+ if(sprite[j].picnum == TIRE)
+ sp->shade = 127;
+ }
+ sp->cstat |= 32;
+ case FECES:
+ if( j >= 0)
+ sp->xrepeat = sp->yrepeat = 1;
+ changespritestat(i,5);
+ break;
+
+ case BLOODSPLAT1:
+ case BLOODSPLAT2:
+ case BLOODSPLAT3:
+ case BLOODSPLAT4:
+ sp->cstat |= 16;
+ sp->xrepeat = 7+(TRAND&7);
+ sp->yrepeat = 7+(TRAND&7);
+ sp->z -= (16<<8);
+ if(j >= 0 && sprite[j].pal == 6)
+ sp->pal = 6;
+ insertspriteq(i);
+ changespritestat(i,5);
+ break;
+
+ case TRIPBOMB:
+ if( sp->lotag > ud.player_skill )
+ {
+ sp->xrepeat=sp->yrepeat=0;
+ changespritestat(i,5);
+ break;
+ }
+
+ sp->xrepeat=4;
+ sp->yrepeat=5;
+
+ sp->owner = i;
+ sp->hitag = i;
+
+ sp->xvel = 16;
+ ssp(i,CLIPMASK0);
+ hittype[i].temp_data[0] = 17;
+ hittype[i].temp_data[2] = 0;
+ hittype[i].temp_data[5] = sp->ang;
+
+ case SPACEMARINE:
+ if(sp->picnum == SPACEMARINE)
+ {
+ sp->extra = 20;
+ sp->cstat |= 257;
+ }
+ changespritestat(i,2);
+ break;
+
+ case HYDRENT:
+ case PANNEL1:
+ case PANNEL2:
+ case SATELITE:
+ case FUELPOD:
+ case SOLARPANNEL:
+ case ANTENNA:
+ case GRATE1:
+ case CHAIR1:
+ case CHAIR2:
+ case CHAIR3:
+ case BOTTLE1:
+ case BOTTLE2:
+ case BOTTLE3:
+ case BOTTLE4:
+ case BOTTLE5:
+ case BOTTLE6:
+ case BOTTLE7:
+ case BOTTLE8:
+ case BOTTLE10:
+ case BOTTLE11:
+ case BOTTLE12:
+ case BOTTLE13:
+ case BOTTLE14:
+ case BOTTLE15:
+ case BOTTLE16:
+ case BOTTLE17:
+ case BOTTLE18:
+ case BOTTLE19:
+ case OCEANSPRITE1:
+ case OCEANSPRITE2:
+ case OCEANSPRITE3:
+ case OCEANSPRITE5:
+ case MONK:
+ case INDY:
+ case LUKE:
+ case JURYGUY:
+ case SCALE:
+ case VACUUM:
+ case FANSPRITE:
+ case CACTUS:
+ case CACTUSBROKE:
+ case HANGLIGHT:
+ case FETUS:
+ case FETUSBROKE:
+ case CAMERALIGHT:
+ case MOVIECAMERA:
+ case IVUNIT:
+ case POT1:
+ case POT2:
+ case POT3:
+ case TRIPODCAMERA:
+ case SUSHIPLATE1:
+ case SUSHIPLATE2:
+ case SUSHIPLATE3:
+ case SUSHIPLATE4:
+ case SUSHIPLATE5:
+ case WAITTOBESEATED:
+ case VASE:
+ case PIPE1:
+ case PIPE2:
+ case PIPE3:
+ case PIPE4:
+ case PIPE5:
+ case PIPE6:
+ sp->clipdist = 32;
+ sp->cstat |= 257;
+ case OCEANSPRITE4:
+ changespritestat(i,0);
+ break;
+ case FEMMAG1:
+ case FEMMAG2:
+ sp->cstat &= ~257;
+ changespritestat(i,0);
+ break;
+ case DUKETAG:
+ case SIGN1:
+ case SIGN2:
+ if(ud.multimode < 2 && sp->pal)
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ }
+ else sp->pal = 0;
+ break;
+ case MASKWALL1:
+ case MASKWALL2:
+ case MASKWALL3:
+ case MASKWALL4:
+ case MASKWALL5:
+ case MASKWALL6:
+ case MASKWALL7:
+ case MASKWALL8:
+ case MASKWALL9:
+ case MASKWALL10:
+ case MASKWALL11:
+ case MASKWALL12:
+ case MASKWALL13:
+ case MASKWALL14:
+ case MASKWALL15:
+ j = sp->cstat&60;
+ sp->cstat = j|1;
+ changespritestat(i,0);
+ break;
+ case FOOTPRINTS:
+ case FOOTPRINTS2:
+ case FOOTPRINTS3:
+ case FOOTPRINTS4:
+ if(j >= 0)
+ {
+ short s1;
+ s1 = sp->sectnum;
+
+ updatesector(sp->x+84,sp->y+84,&s1);
+ if(s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
+ {
+ updatesector(sp->x-84,sp->y-84,&s1);
+ if(s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
+ {
+ updatesector(sp->x+84,sp->y-84,&s1);
+ if(s1 >= 0 && sector[s1].floorz == sector[sp->sectnum].floorz)
+ {
+ updatesector(sp->x-84,sp->y+84,&s1);
+ if(s1 >= 0 && sector[s1].floorz != sector[sp->sectnum].floorz)
+ { sp->xrepeat = sp->yrepeat = 0;changespritestat(i,5);break;}
+ }
+ else { sp->xrepeat = sp->yrepeat = 0;break;}
+ }
+ else { sp->xrepeat = sp->yrepeat = 0;break;}
+ }
+ else { sp->xrepeat = sp->yrepeat = 0;break;}
+
+ sp->cstat = 32+((ps[sprite[j].yvel].footprintcount&1)<<2);
+ sp->ang = sprite[j].ang;
+ }
+
+ sp->z = sector[sect].floorz;
+ if(sector[sect].lotag != 1 && sector[sect].lotag != 2)
+ sp->xrepeat = sp->yrepeat = 32;
+
+ insertspriteq(i);
+ changespritestat(i,5);
+ break;
+
+ case FEM1:
+ case FEM2:
+ case FEM3:
+ case FEM4:
+ case FEM5:
+ case FEM6:
+ case FEM7:
+ case FEM8:
+ case FEM9:
+ case FEM10:
+ case PODFEM1:
+ case NAKED1:
+ case STATUE:
+ case TOUGHGAL:
+ sp->yvel = sp->hitag;
+ sp->hitag = -1;
+ if(sp->picnum == PODFEM1) sp->extra <<= 1;
+ case BLOODYPOLE:
+
+ case QUEBALL:
+ case STRIPEBALL:
+
+ if(sp->picnum == QUEBALL || sp->picnum == STRIPEBALL)
+ {
+ sp->cstat = 256;
+ sp->clipdist = 8;
+ }
+ else
+ {
+ sp->cstat |= 257;
+ sp->clipdist = 32;
+ }
+
+ changespritestat(i,2);
+ break;
+
+ case DUKELYINGDEAD:
+ if(j >= 0 && sprite[j].picnum == APLAYER)
+ {
+ sp->xrepeat = sprite[j].xrepeat;
+ sp->yrepeat = sprite[j].yrepeat;
+ sp->shade = sprite[j].shade;
+ sp->pal = ps[sprite[j].yvel].palookup;
+ }
+ case DUKECAR:
+ case HELECOPT:
+// if(sp->picnum == HELECOPT || sp->picnum == DUKECAR) sp->xvel = 1024;
+ sp->cstat = 0;
+ sp->extra = 1;
+ sp->xvel = 292;
+ sp->zvel = 360;
+ case RESPAWNMARKERRED:
+ case BLIMP:
+
+ if(sp->picnum == RESPAWNMARKERRED)
+ {
+ sp->xrepeat = sp->yrepeat = 24;
+ if(j >= 0) sp->z = hittype[j].floorz; // -(1<<4);
+ }
+ else
+ {
+ sp->cstat |= 257;
+ sp->clipdist = 128;
+ }
+ case MIKE:
+ if(sp->picnum == MIKE)
+ sp->yvel = sp->hitag;
+ case WEATHERWARN:
+ changespritestat(i,1);
+ break;
+
+ case SPOTLITE:
+ T1 = sp->x;
+ T2 = sp->y;
+ break;
+ case BULLETHOLE:
+ sp->xrepeat = sp->yrepeat = 3;
+ sp->cstat = 16+(TRAND&12);
+ insertspriteq(i);
+ case MONEY:
+ case MAIL:
+ case PAPER:
+ if( sp->picnum == MONEY || sp->picnum == MAIL || sp->picnum == PAPER )
+ {
+ hittype[i].temp_data[0] = TRAND&2047;
+ sp->cstat = TRAND&12;
+ sp->xrepeat = sp->yrepeat = 8;
+ sp->ang = TRAND&2047;
+ }
+ changespritestat(i,5);
+ break;
+
+ case VIEWSCREEN:
+ case VIEWSCREEN2:
+ sp->owner = i;
+ sp->lotag = 1;
+ sp->extra = 1;
+ changespritestat(i,6);
+ break;
+
+ case SHELL: //From the player
+ case SHOTGUNSHELL:
+ if( j >= 0 )
+ {
+ short snum,a;
+
+ if(sprite[j].picnum == APLAYER)
+ {
+ snum = sprite[j].yvel;
+ a = ps[snum].ang-(TRAND&63)+8; //Fine tune
+
+ T1 = TRAND&1;
+ if(sp->picnum == SHOTGUNSHELL)
+ sp->z = (6<<8)+ps[snum].pyoff+ps[snum].posz-((ps[snum].horizoff+ps[snum].horiz-100)<<4);
+ else sp->z = (3<<8)+ps[snum].pyoff+ps[snum].posz-((ps[snum].horizoff+ps[snum].horiz-100)<<4);
+ sp->zvel = -(TRAND&255);
+ }
+ else
+ {
+ a = sp->ang;
+ sp->z = sprite[j].z-PHEIGHT+(3<<8);
+ }
+
+ sp->x = sprite[j].x+(sintable[(a+512)&2047]>>7);
+ sp->y = sprite[j].y+(sintable[a&2047]>>7);
+
+ sp->shade = -8;
+
+ sp->ang = a-512;
+ sp->xvel = 20;
+
+ // do not try to make it 0 when ud.hideweapon Will make OOS when shooting in water
+ sp->xrepeat=sp->yrepeat=4;
+
+ changespritestat(i,5);
+ }
+ break;
+
+ case RESPAWN:
+ sp->extra = 66-13;
+ case MUSICANDSFX:
+ if( ud.multimode < 2 && sp->pal == 1)
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+ sp->cstat = (short)32768;
+ changespritestat(i,11);
+ break;
+
+ case EXPLOSION2:
+ case EXPLOSION2BOT:
+ case BURNING:
+ case BURNING2:
+ case SMALLSMOKE:
+ case SHRINKEREXPLOSION:
+ case COOLEXPLOSION1:
+
+ if(j >= 0)
+ {
+ sp->ang = sprite[j].ang;
+ sp->shade = -64;
+ sp->cstat = 128|(TRAND&4);
+ }
+
+ if(sp->picnum == EXPLOSION2 || sp->picnum == EXPLOSION2BOT)
+ {
+ sp->xrepeat = 48;
+ sp->yrepeat = 48;
+ sp->shade = -127;
+ sp->cstat |= 128;
+ }
+ else if(sp->picnum == SHRINKEREXPLOSION )
+ {
+ sp->xrepeat = 32;
+ sp->yrepeat = 32;
+ }
+ else if( sp->picnum == SMALLSMOKE )
+ {
+ // 64 "money"
+ sp->xrepeat = 24;
+ sp->yrepeat = 24;
+ }
+ else if(sp->picnum == BURNING || sp->picnum == BURNING2)
+ {
+ sp->xrepeat = 4;
+ sp->yrepeat = 4;
+ }
+
+ if(j >= 0)
+ {
+ x = getflorzofslope(sp->sectnum,sp->x,sp->y);
+ if(sp->z > x-(12<<8) )
+ sp->z = x-(12<<8);
+ }
+
+ changespritestat(i,5);
+
+ break;
+
+ case PLAYERONWATER:
+ if(j >= 0)
+ {
+ sp->xrepeat = sprite[j].xrepeat;
+ sp->yrepeat = sprite[j].yrepeat;
+ sp->zvel = 128;
+ if(sector[sp->sectnum].lotag != 2)
+ sp->cstat |= 32768;
+ }
+ changespritestat(i,13);
+ break;
+
+ case APLAYER:
+ sp->xrepeat = sp->yrepeat = 0;
+ j = ud.coop;
+ if(j == 2) j = 0;
+
+ if( ud.multimode < 2 || (ud.multimode > 1 && j != sp->lotag) )
+ changespritestat(i,5);
+ else
+ changespritestat(i,10);
+ break;
+ case WATERBUBBLE:
+ if(j >= 0 && sprite[j].picnum == APLAYER)
+ sp->z -= (16<<8);
+ if( sp->picnum == WATERBUBBLE)
+ {
+ if( j >= 0 )
+ sp->ang = sprite[j].ang;
+ sp->xrepeat = sp->yrepeat = 4;
+ }
+ else sp->xrepeat = sp->yrepeat = 32;
+
+ changespritestat(i,5);
+ break;
+
+ case CRANE:
+
+ sp->cstat |= 64|257;
+
+ sp->picnum += 2;
+ sp->z = sector[sect].ceilingz+(48<<8);
+ T5 = tempwallptr;
+
+ msx[tempwallptr] = sp->x;
+ msy[tempwallptr] = sp->y;
+ msx[tempwallptr+2] = sp->z;
+
+ s = headspritestat[0];
+ while(s >= 0)
+ {
+ if( sprite[s].picnum == CRANEPOLE && SHT == (sprite[s].hitag) )
+ {
+ msy[tempwallptr+2] = s;
+
+ T2 = sprite[s].sectnum;
+
+ sprite[s].xrepeat = 48;
+ sprite[s].yrepeat = 128;
+
+ msx[tempwallptr+1] = sprite[s].x;
+ msy[tempwallptr+1] = sprite[s].y;
+
+ sprite[s].x = sp->x;
+ sprite[s].y = sp->y;
+ sprite[s].z = sp->z;
+ sprite[s].shade = sp->shade;
+
+ setsprite(s,sprite[s].x,sprite[s].y,sprite[s].z);
+ break;
+ }
+ s = nextspritestat[s];
+ }
+
+ tempwallptr += 3;
+ sp->owner = -1;
+ sp->extra = 8;
+ changespritestat(i,6);
+ break;
+
+ case WATERDRIP:
+ if((j >= 0 && sprite[j].statnum == 10) || sprite[j].statnum == 1)
+ {
+ sp->shade = 32;
+ if(sprite[j].pal != 1)
+ {
+ sp->pal = 2;
+ sp->z -= (18<<8);
+ }
+ else sp->z -= (13<<8);
+ sp->ang = getangle(ps[connecthead].posx-sp->x,ps[connecthead].posy-sp->y);
+ sp->xvel = 48-(TRAND&31);
+ ssp(i,CLIPMASK0);
+ }
+ else if(j == -1)
+ {
+ sp->z += (4<<8);
+ T1 = sp->z;
+ T2 = TRAND&127;
+ }
+ case TRASH:
+
+ if(sp->picnum != WATERDRIP)
+ sp->ang = TRAND&2047;
+
+ case WATERDRIPSPLASH:
+
+ sp->xrepeat = 24;
+ sp->yrepeat = 24;
+
+
+ changespritestat(i,6);
+ break;
+
+ case PLUG:
+ sp->lotag = 9999;
+ changespritestat(i,6);
+ break;
+ case TOUCHPLATE:
+ T3 = sector[sect].floorz;
+ if(sector[sect].lotag != 1 && sector[sect].lotag != 2)
+ sector[sect].floorz = sp->z;
+ if(sp->pal && ud.multimode > 1)
+ {
+ sp->xrepeat=sp->yrepeat=0;
+ changespritestat(i,5);
+ break;
+ }
+ case WATERBUBBLEMAKER:
+ sp->cstat |= 32768;
+ changespritestat(i,6);
+ break;
+ case BOLT1:
+ case BOLT1+1:
+ case BOLT1+2:
+ case BOLT1+3:
+ case SIDEBOLT1:
+ case SIDEBOLT1+1:
+ case SIDEBOLT1+2:
+ case SIDEBOLT1+3:
+ T1 = sp->xrepeat;
+ T2 = sp->yrepeat;
+ case MASTERSWITCH:
+ if(sp->picnum == MASTERSWITCH)
+ sp->cstat |= 32768;
+ sp->yvel = 0;
+ changespritestat(i,6);
+ break;
+ case TARGET:
+ case DUCK:
+ case LETTER:
+ sp->extra = 1;
+ sp->cstat |= 257;
+ changespritestat(i,1);
+ break;
+ case OCTABRAINSTAYPUT:
+ case LIZTROOPSTAYPUT:
+ case PIGCOPSTAYPUT:
+ case LIZMANSTAYPUT:
+ case BOSS1STAYPUT:
+ case PIGCOPDIVE:
+ case COMMANDERSTAYPUT:
+ case BOSS4STAYPUT:
+ hittype[i].actorstayput = sp->sectnum;
+ case BOSS1:
+ case BOSS2:
+ case BOSS3:
+ case BOSS4:
+ case ROTATEGUN:
+ case GREENSLIME:
+ if(sp->picnum == GREENSLIME)
+ sp->extra = 1;
+ case DRONE:
+ case LIZTROOPONTOILET:
+ case LIZTROOPJUSTSIT:
+ case LIZTROOPSHOOT:
+ case LIZTROOPJETPACK:
+ case LIZTROOPDUCKING:
+ case LIZTROOPRUNNING:
+ case LIZTROOP:
+ case OCTABRAIN:
+ case COMMANDER:
+ case PIGCOP:
+ case LIZMAN:
+ case LIZMANSPITTING:
+ case LIZMANFEEDING:
+ case LIZMANJUMP:
+ case ORGANTIC:
+ case RAT:
+ case SHARK:
+
+ if(sp->pal == 0)
+ {
+ switch(sp->picnum)
+ {
+ case LIZTROOPONTOILET:
+ case LIZTROOPSHOOT:
+ case LIZTROOPJETPACK:
+ case LIZTROOPDUCKING:
+ case LIZTROOPRUNNING:
+ case LIZTROOPSTAYPUT:
+ case LIZTROOPJUSTSIT:
+ case LIZTROOP:
+ sp->pal = 22;
+ break;
+ }
+ }
+
+ if( sp->picnum == BOSS4STAYPUT || sp->picnum == BOSS1 || sp->picnum == BOSS2 || sp->picnum == BOSS1STAYPUT || sp->picnum == BOSS3 || sp->picnum == BOSS4 )
+ {
+ if(j >= 0 && sprite[j].picnum == RESPAWN)
+ sp->pal = sprite[j].pal;
+ if(sp->pal)
+ {
+ sp->clipdist = 80;
+ sp->xrepeat = 40;
+ sp->yrepeat = 40;
+ }
+ else
+ {
+ sp->xrepeat = 80;
+ sp->yrepeat = 80;
+ sp->clipdist = 164;
+ }
+ }
+ else
+ {
+ if(sp->picnum != SHARK)
+ {
+ sp->xrepeat = 40;
+ sp->yrepeat = 40;
+ sp->clipdist = 80;
+ }
+ else
+ {
+ sp->xrepeat = 60;
+ sp->yrepeat = 60;
+ sp->clipdist = 40;
+ }
+ }
+
+ if(j >= 0) sp->lotag = 0;
+
+ if( ( sp->lotag > ud.player_skill ) || ud.monsters_off == 1 )
+ {
+ sp->xrepeat=sp->yrepeat=0;
+ changespritestat(i,5);
+ break;
+ }
+ else
+ {
+ makeitfall(i);
+
+ if(sp->picnum == RAT)
+ {
+ sp->ang = TRAND&2047;
+ sp->xrepeat = sp->yrepeat = 48;
+ sp->cstat = 0;
+ }
+ else
+ {
+ sp->cstat |= 257;
+
+ if(sp->picnum != SHARK)
+ ps[myconnectindex].max_actors_killed++;
+ }
+
+ if(sp->picnum == ORGANTIC) sp->cstat |= 128;
+
+ if(j >= 0)
+ {
+ hittype[i].timetosleep = 0;
+ check_fta_sounds(i);
+ changespritestat(i,1);
+ }
+ else changespritestat(i,2);
+ }
+
+ if(sp->picnum == ROTATEGUN)
+ sp->zvel = 0;
+
+ break;
+
+ case LOCATORS:
+ sp->cstat |= 32768;
+ changespritestat(i,7);
+ break;
+
+ case ACTIVATORLOCKED:
+ case ACTIVATOR:
+ sp->cstat = (short) 32768;
+ if(sp->picnum == ACTIVATORLOCKED)
+ sector[sp->sectnum].lotag |= 16384;
+ changespritestat(i,8);
+ break;
+
+ case DOORSHOCK:
+ sp->cstat |= 1+256;
+ sp->shade = -12;
+ changespritestat(i,6);
+ break;
+
+ case OOZ:
+ case OOZ2:
+ sp->shade = -12;
+
+ if(j >= 0)
+ {
+ if( sprite[j].picnum == NUKEBARREL )
+ sp->pal = 8;
+ insertspriteq(i);
+ }
+
+ changespritestat(i,1);
+
+ getglobalz(i);
+
+ j = (hittype[i].floorz-hittype[i].ceilingz)>>9;
+
+ sp->yrepeat = j;
+ sp->xrepeat = 25-(j>>1);
+ sp->cstat |= (TRAND&4);
+
+ break;
+
+ case HEAVYHBOMB:
+ if(j >= 0)
+ sp->owner = j;
+ else sp->owner = i;
+ sp->xrepeat = sp->yrepeat = 9;
+ sp->yvel = 4;
+ case REACTOR2:
+ case REACTOR:
+ case RECON:
+
+ if(sp->picnum == RECON)
+ {
+ if( sp->lotag > ud.player_skill )
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ return i;
+ }
+ ps[myconnectindex].max_actors_killed++;
+ hittype[i].temp_data[5] = 0;
+ if(ud.monsters_off == 1)
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+ sp->extra = 130;
+ }
+
+ if(sp->picnum == REACTOR || sp->picnum == REACTOR2)
+ sp->extra = impact_damage;
+
+ CS |= 257; // Make it hitable
+
+ if( ud.multimode < 2 && sp->pal != 0)
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+ sp->pal = 0;
+ SS = -17;
+
+ changespritestat(i,2);
+ break;
+
+ case ATOMICHEALTH:
+ case STEROIDS:
+ case HEATSENSOR:
+ case SHIELD:
+ case AIRTANK:
+ case TRIPBOMBSPRITE:
+ case JETPACK:
+ case HOLODUKE:
+
+ case FIRSTGUNSPRITE:
+ case CHAINGUNSPRITE:
+ case SHOTGUNSPRITE:
+ case RPGSPRITE:
+ case SHRINKERSPRITE:
+ case FREEZESPRITE:
+ case DEVISTATORSPRITE:
+
+ case SHOTGUNAMMO:
+ case FREEZEAMMO:
+ case HBOMBAMMO:
+ case CRYSTALAMMO:
+ case GROWAMMO:
+ case BATTERYAMMO:
+ case DEVISTATORAMMO:
+ case RPGAMMO:
+ case BOOTS:
+ case AMMO:
+ case AMMOLOTS:
+ case COLA:
+ case FIRSTAID:
+ case SIXPAK:
+ if(j >= 0)
+ {
+ sp->lotag = 0;
+ sp->z -= (32<<8);
+ sp->zvel = -1024;
+ ssp(i,CLIPMASK0);
+ sp->cstat = TRAND&4;
+ }
+ else
+ {
+ sp->owner = i;
+ sp->cstat = 0;
+ }
+
+ if( ( ud.multimode < 2 && sp->pal != 0) || (sp->lotag > ud.player_skill) )
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+
+ sp->pal = 0;
+
+ case ACCESSCARD:
+
+ if(sp->picnum == ATOMICHEALTH)
+ sp->cstat |= 128;
+
+ if(ud.multimode > 1 && ud.coop != 1 && sp->picnum == ACCESSCARD)
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+ else
+ {
+ if(sp->picnum == AMMO)
+ sp->xrepeat = sp->yrepeat = 16;
+ else sp->xrepeat = sp->yrepeat = 32;
+ }
+
+ sp->shade = -17;
+
+ if(j >= 0) changespritestat(i,1);
+ else
+ {
+ changespritestat(i,2);
+ makeitfall(i);
+ }
+ break;
+
+ case WATERFOUNTAIN:
+ SLT = 1;
+
+ case TREE1:
+ case TREE2:
+ case TIRE:
+ case CONE:
+ case BOX:
+ CS = 257; // Make it hitable
+ sprite[i].extra = 1;
+ changespritestat(i,6);
+ break;
+
+ case FLOORFLAME:
+ sp->shade = -127;
+ changespritestat(i,6);
+ break;
+
+ case BOUNCEMINE:
+ sp->owner = i;
+ sp->cstat |= 1+256; //Make it hitable
+ sp->xrepeat = sp->yrepeat = 24;
+ sp->shade = -127;
+ sp->extra = impact_damage<<2;
+ changespritestat(i,2);
+ break;
+
+ case CAMERA1:
+ case CAMERA1+1:
+ case CAMERA1+2:
+ case CAMERA1+3:
+ case CAMERA1+4:
+ case CAMERAPOLE:
+ sp->extra = 1;
+
+ if(camerashitable) sp->cstat = 257;
+ else sp->cstat = 0;
+
+ case GENERICPOLE:
+
+ if( ud.multimode < 2 && sp->pal != 0 )
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+ else sp->pal = 0;
+ if(sp->picnum == CAMERAPOLE || sp->picnum == GENERICPOLE) break;
+ sp->picnum = CAMERA1;
+ changespritestat(i,1);
+ break;
+ case STEAM:
+ if(j >= 0)
+ {
+ sp->ang = sprite[j].ang;
+ sp->cstat = 16+128+2;
+ sp->xrepeat=sp->yrepeat=1;
+ sp->xvel = -8;
+ ssp(i,CLIPMASK0);
+ }
+ case CEILINGSTEAM:
+ changespritestat(i,6);
+ break;
+
+ case SECTOREFFECTOR:
+ sp->yvel = sector[sect].extra;
+ sp->cstat |= 32768;
+ sp->xrepeat = sp->yrepeat = 0;
+
+ switch(sp->lotag)
+ {
+ case 28:
+ T6 = 65;// Delay for lightning
+ break;
+ case 7: // Transporters!!!!
+ case 23:// XPTR END
+ if(sp->lotag != 23)
+ {
+ for(j=0;j<MAXSPRITES;j++)
+ if(sprite[j].statnum < MAXSTATUS && sprite[j].picnum == SECTOREFFECTOR && ( sprite[j].lotag == 7 || sprite[j].lotag == 23 ) && i != j && sprite[j].hitag == SHT)
+ {
+ OW = j;
+ break;
+ }
+ }
+ else OW = i;
+
+ T5 = sector[sect].floorz == SZ;
+ sp->cstat = 0;
+ changespritestat(i,9);
+ return i;
+ case 1:
+ sp->owner = -1;
+ T1 = 1;
+ break;
+ case 18:
+
+ if(sp->ang == 512)
+ {
+ T2 = sector[sect].ceilingz;
+ if(sp->pal)
+ sector[sect].ceilingz = sp->z;
+ }
+ else
+ {
+ T2 = sector[sect].floorz;
+ if(sp->pal)
+ sector[sect].floorz = sp->z;
+ }
+
+ sp->hitag <<= 2;
+ break;
+
+ case 19:
+ sp->owner = -1;
+ break;
+ case 25: // Pistons
+ T4 = sector[sect].ceilingz;
+ T5 = 1;
+ sector[sect].ceilingz = sp->z;
+ setinterpolation(&sector[sect].ceilingz);
+ break;
+ case 35:
+ sector[sect].ceilingz = sp->z;
+ break;
+ case 27:
+ if(ud.recstat == 1)
+ {
+ sp->xrepeat=sp->yrepeat=64;
+ sp->cstat &= 32767;
+ }
+ break;
+ case 12:
+
+ T2 = sector[sect].floorshade;
+ T3 = sector[sect].ceilingshade;
+ break;
+
+ case 13:
+
+ T1 = sector[sect].ceilingz;
+ T2 = sector[sect].floorz;
+
+ if( klabs(T1-sp->z) < klabs(T2-sp->z) )
+ sp->owner = 1;
+ else sp->owner = 0;
+
+ if(sp->ang == 512)
+ {
+ if(sp->owner)
+ sector[sect].ceilingz = sp->z;
+ else
+ sector[sect].floorz = sp->z;
+ }
+ else
+ sector[sect].ceilingz = sector[sect].floorz = sp->z;
+
+ if( sector[sect].ceilingstat&1 )
+ {
+ sector[sect].ceilingstat ^= 1;
+ T4 = 1;
+
+ if(!sp->owner && sp->ang==512)
+ {
+ sector[sect].ceilingstat ^= 1;
+ T4 = 0;
+ }
+
+ sector[sect].ceilingshade =
+ sector[sect].floorshade;
+
+ if(sp->ang==512)
+ {
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+ for(j=startwall;j<endwall;j++)
+ {
+ x = wall[j].nextsector;
+ if(x >= 0)
+ if( !(sector[x].ceilingstat&1) )
+ {
+ sector[sect].ceilingpicnum =
+ sector[x].ceilingpicnum;
+ sector[sect].ceilingshade =
+ sector[x].ceilingshade;
+ break; //Leave earily
+ }
+ }
+ }
+ }
+
+ break;
+
+ case 17:
+
+ T3 = sector[sect].floorz; //Stopping loc
+
+ j = nextsectorneighborz(sect,sector[sect].floorz,-1,-1);
+ T4 = sector[j].ceilingz;
+
+ j = nextsectorneighborz(sect,sector[sect].ceilingz,1,1);
+ T5 = sector[j].floorz;
+
+ if(numplayers < 2)
+ {
+ setinterpolation(&sector[sect].floorz);
+ setinterpolation(&sector[sect].ceilingz);
+ }
+
+ break;
+
+ case 24:
+ sp->yvel <<= 1;
+ case 36:
+ break;
+
+ case 20:
+ {
+ int32_t q;
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ //find the two most clostest wall x's and y's
+ q = 0x7fffffff;
+
+ for(s=startwall;s<endwall;s++)
+ {
+ x = wall[s].x;
+ y = wall[s].y;
+
+ d = FindDistance2D(sp->x-x,sp->y-y);
+ if( d < q )
+ {
+ q = d;
+ clostest = s;
+ }
+ }
+
+ T2 = clostest;
+
+ q = 0x7fffffff;
+
+ for(s=startwall;s<endwall;s++)
+ {
+ x = wall[s].x;
+ y = wall[s].y;
+
+ d = FindDistance2D(sp->x-x,sp->y-y);
+ if(d < q && s != T2)
+ {
+ q = d;
+ clostest = s;
+ }
+ }
+
+ T3 = clostest;
+ }
+
+ break;
+
+ case 3:
+
+ T4=sector[sect].floorshade;
+
+ sector[sect].floorshade = sp->shade;
+ sector[sect].ceilingshade = sp->shade;
+
+ sp->owner = sector[sect].ceilingpal<<8;
+ sp->owner |= sector[sect].floorpal;
+
+ //fix all the walls;
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ for(s=startwall;s<endwall;s++)
+ {
+ if(!(wall[s].hitag&1))
+ wall[s].shade=sp->shade;
+ if( (wall[s].cstat&2) && wall[s].nextwall >= 0)
+ wall[wall[s].nextwall].shade = sp->shade;
+ }
+ break;
+
+ case 31:
+ T2 = sector[sect].floorz;
+ // T3 = sp->hitag;
+ if(sp->ang != 1536) sector[sect].floorz = sp->z;
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ for(s=startwall;s<endwall;s++)
+ if(wall[s].hitag == 0) wall[s].hitag = 9999;
+
+ setinterpolation(&sector[sect].floorz);
+
+ break;
+ case 32:
+ T2 = sector[sect].ceilingz;
+ T3 = sp->hitag;
+ if(sp->ang != 1536) sector[sect].ceilingz = sp->z;
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ for(s=startwall;s<endwall;s++)
+ if(wall[s].hitag == 0) wall[s].hitag = 9999;
+
+ setinterpolation(&sector[sect].ceilingz);
+
+ break;
+
+ case 4: //Flashing lights
+
+ T3 = sector[sect].floorshade;
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ sp->owner = sector[sect].ceilingpal<<8;
+ sp->owner |= sector[sect].floorpal;
+
+ for(s=startwall;s<endwall;s++)
+ if(wall[s].shade > T4)
+ T4 = wall[s].shade;
+
+ break;
+
+ case 9:
+ if( sector[sect].lotag &&
+ labs(sector[sect].ceilingz-sp->z) > 1024)
+ sector[sect].lotag |= 32768; //If its open
+ case 8:
+ //First, get the ceiling-floor shade
+
+ T1 = sector[sect].floorshade;
+ T2 = sector[sect].ceilingshade;
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ for(s=startwall;s<endwall;s++)
+ if(wall[s].shade > T3)
+ T3 = wall[s].shade;
+
+ T4 = 1; //Take Out;
+
+ break;
+
+ case 11://Pivitor rotater
+ if(sp->ang>1024) T4 = 2;
+ else T4 = -2;
+ case 0:
+ case 2://Earthquakemakers
+ case 5://Boss Creature
+ case 6://Subway
+ case 14://Caboos
+ case 15://Subwaytype sliding door
+ case 16://That rotating blocker reactor thing
+ case 26://ESCELATOR
+ case 30://No rotational subways
+
+ if(sp->lotag == 0)
+ {
+ if( sector[sect].lotag == 30 )
+ {
+ if(sp->pal) sprite[i].clipdist = 1;
+ else sprite[i].clipdist = 0;
+ T4 = sector[sect].floorz;
+ sector[sect].hitag = i;
+ }
+
+ for(j = 0;j < MAXSPRITES;j++)
+ {
+ if( sprite[j].statnum < MAXSTATUS )
+ if( sprite[j].picnum == SECTOREFFECTOR &&
+ sprite[j].lotag == 1 &&
+ sprite[j].hitag == sp->hitag)
+ {
+ if( sp->ang == 512 )
+ {
+ sp->x = sprite[j].x;
+ sp->y = sprite[j].y;
+ }
+ break;
+ }
+ }
+ if(j == MAXSPRITES)
+ {
+ sprintf(text,"Found lonely Sector Effector (lotag 0) at (%d,%d)\n",sp->x,sp->y);
+ gameexit(text);
+ }
+ sp->owner = j;
+ }
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ T2 = tempwallptr;
+ for(s=startwall;s<endwall;s++)
+ {
+ msx[tempwallptr] = wall[s].x-sp->x;
+ msy[tempwallptr] = wall[s].y-sp->y;
+ tempwallptr++;
+ if(tempwallptr > 2047)
+ {
+ sprintf(text,"Too many moving sectors at (%d,%d).\n",wall[s].x,wall[s].y);
+ gameexit(text);
+ }
+ }
+ if( sp->lotag == 30 || sp->lotag == 6 || sp->lotag == 14 || sp->lotag == 5 )
+ {
+
+ startwall = sector[sect].wallptr;
+ endwall = startwall+sector[sect].wallnum;
+
+ if(sector[sect].hitag == -1)
+ sp->extra = 0;
+ else sp->extra = 1;
+
+ sector[sect].hitag = i;
+
+ j = 0;
+
+ for(s=startwall;s<endwall;s++)
+ {
+ if( wall[ s ].nextsector >= 0 &&
+ sector[ wall[ s ].nextsector].hitag == 0 &&
+ sector[ wall[ s ].nextsector].lotag < 3 )
+ {
+ s = wall[s].nextsector;
+ j = 1;
+ break;
+ }
+ }
+
+ if(j == 0)
+ {
+ sprintf(text,"Subway found no zero'd sectors with locators\nat (%d,%d).\n",sp->x,sp->y);
+ gameexit(text);
+ }
+
+ sp->owner = -1;
+ T1 = s;
+
+ if(sp->lotag != 30)
+ T4 = sp->hitag;
+ }
+
+ else if(sp->lotag == 16)
+ T4 = sector[sect].ceilingz;
+
+ else if( sp->lotag == 26 )
+ {
+ T4 = sp->x;
+ T5 = sp->y;
+ if(sp->shade==sector[sect].floorshade) //UP
+ sp->zvel = -256;
+ else
+ sp->zvel = 256;
+
+ sp->shade = 0;
+ }
+ else if( sp->lotag == 2)
+ {
+ T6 = sector[sp->sectnum].floorheinum;
+ sector[sp->sectnum].floorheinum = 0;
+ }
+ }
+
+ switch(sp->lotag)
+ {
+ case 6:
+ case 14:
+ j = callsound(sect,i);
+ if(j == -1) j = SUBWAY;
+ hittype[i].lastvx = j;
+ case 30:
+ if(numplayers > 1) break;
+ case 0:
+ case 1:
+ case 5:
+ case 11:
+ case 15:
+ case 16:
+ case 26:
+ setsectinterpolate(i);
+ break;
+ }
+
+ switch(sprite[i].lotag)
+ {
+ case 40:
+ case 41:
+ case 43:
+ case 44:
+ case 45:
+ changespritestat(i,15);
+ break;
+ default:
+ changespritestat(i,3);
+ break;
+ }
+
+ break;
+
+
+ case SEENINE:
+ case OOZFILTER:
+
+ sp->shade = -16;
+ if(sp->xrepeat <= 8)
+ {
+ sp->cstat = (short)32768;
+ sp->xrepeat=sp->yrepeat=0;
+ }
+ else sp->cstat = 1+256;
+ sp->extra = impact_damage<<2;
+ sp->owner = i;
+
+ changespritestat(i,6);
+ break;
+
+ case CRACK1:
+ case CRACK2:
+ case CRACK3:
+ case CRACK4:
+ case FIREEXT:
+ if(sp->picnum == FIREEXT)
+ {
+ sp->cstat = 257;
+ sp->extra = impact_damage<<2;
+ }
+ else
+ {
+ sp->cstat |= 17;
+ sp->extra = 1;
+ }
+
+ if( ud.multimode < 2 && sp->pal != 0)
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ break;
+ }
+
+ sp->pal = 0;
+ sp->owner = i;
+ changespritestat(i,6);
+ sp->xvel = 8;
+ ssp(i,CLIPMASK0);
+ break;
+
+ case TOILET:
+ case STALL:
+ sp->lotag = 1;
+ sp->cstat |= 257;
+ sp->clipdist = 8;
+ sp->owner = i;
+ break;
+ case CANWITHSOMETHING:
+ case CANWITHSOMETHING2:
+ case CANWITHSOMETHING3:
+ case CANWITHSOMETHING4:
+ case RUBBERCAN:
+ sp->extra = 0;
+ case EXPLODINGBARREL:
+ case HORSEONSIDE:
+ case FIREBARREL:
+ case NUKEBARREL:
+ case FIREVASE:
+ case NUKEBARRELDENTED:
+ case NUKEBARRELLEAKED:
+ case WOODENHORSE:
+
+ if(j >= 0)
+ sp->xrepeat = sp->yrepeat = 32;
+ sp->clipdist = 72;
+ makeitfall(i);
+ if(j >= 0)
+ sp->owner = j;
+ else sp->owner = i;
+ case EGG:
+ if( ud.monsters_off == 1 && sp->picnum == EGG )
+ {
+ sp->xrepeat = sp->yrepeat = 0;
+ changespritestat(i,5);
+ }
+ else
+ {
+ if(sp->picnum == EGG)
+ sp->clipdist = 24;
+ sp->cstat = 257|(TRAND&4);
+ changespritestat(i,2);
+ }
+ break;
+ case TOILETWATER:
+ sp->shade = -16;
+ changespritestat(i,6);
+ break;
+ }
+ return i;
+}
+
+
+void animatesprites(int32_t x,int32_t y,short a,int32_t smoothratio)
+{
+ short i, j, k, p, sect;
+ int32_t l, t1,t3,t4;
+ spritetype *s,*t;
+
+ for(j=0;j < spritesortcnt; j++)
+ {
+ t = &tsprite[j];
+ i = t->owner;
+ s = &sprite[t->owner];
+
+ switch(t->picnum)
+ {
+ case BLOODPOOL:
+ case PUKE:
+ case FOOTPRINTS:
+ case FOOTPRINTS2:
+ case FOOTPRINTS3:
+ case FOOTPRINTS4:
+ if(t->shade == 127) continue;
+ break;
+ case RESPAWNMARKERRED:
+ case RESPAWNMARKERYELLOW:
+ case RESPAWNMARKERGREEN:
+ if(ud.marker == 0)
+ t->xrepeat = t->yrepeat = 0;
+ continue;
+ case CHAIR3:
+
+ k = (((t->ang+3072+128-a)&2047)>>8)&7;
+ if(k>4)
+ {
+ k = 8-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+ t->picnum = s->picnum+k;
+ break;
+ case BLOODSPLAT1:
+ case BLOODSPLAT2:
+ case BLOODSPLAT3:
+ case BLOODSPLAT4:
+ if(ud.lockout) t->xrepeat = t->yrepeat = 0;
+ else if(t->pal == 6)
+ {
+ t->shade = -127;
+ continue;
+ }
+ case BULLETHOLE:
+ case CRACK1:
+ case CRACK2:
+ case CRACK3:
+ case CRACK4:
+ t->shade = 16;
+ continue;
+ case NEON1:
+ case NEON2:
+ case NEON3:
+ case NEON4:
+ case NEON5:
+ case NEON6:
+ continue;
+ case GREENSLIME:
+ case GREENSLIME+1:
+ case GREENSLIME+2:
+ case GREENSLIME+3:
+ case GREENSLIME+4:
+ case GREENSLIME+5:
+ case GREENSLIME+6:
+ case GREENSLIME+7:
+ break;
+ default:
+ if( ( (t->cstat&16) ) || ( badguy(t) && t->extra > 0) || t->statnum == 10)
+ continue;
+ }
+
+ if (sector[t->sectnum].ceilingstat&1)
+ l = sector[t->sectnum].ceilingshade;
+ else
+ l = sector[t->sectnum].floorshade;
+
+ if(l < -127) l = -127;
+ if(l > 128) l = 127;
+ t->shade = l;
+ }
+
+
+ for(j=0;j < spritesortcnt; j++ ) //Between drawrooms() and drawmasks()
+ { //is the perfect time to animate sprites
+ t = &tsprite[j];
+ i = t->owner;
+ s = &sprite[i];
+
+ switch(s->picnum)
+ {
+ case SECTOREFFECTOR:
+ if(t->lotag == 27 && ud.recstat == 1)
+ {
+ t->picnum = 11+((totalclock>>3)&1);
+ t->cstat |= 128;
+ }
+ else
+ t->xrepeat = t->yrepeat = 0;
+ break;
+ case NATURALLIGHTNING:
+ t->shade = -127;
+ break;
+ case FEM1:
+ case FEM2:
+ case FEM3:
+ case FEM4:
+ case FEM5:
+ case FEM6:
+ case FEM7:
+ case FEM8:
+ case FEM9:
+ case FEM10:
+ case MAN:
+ case MAN2:
+ case WOMAN:
+ case NAKED1:
+ case PODFEM1:
+ case FEMMAG1:
+ case FEMMAG2:
+ case FEMPIC1:
+ case FEMPIC2:
+ case FEMPIC3:
+ case FEMPIC4:
+ case FEMPIC5:
+ case FEMPIC6:
+ case FEMPIC7:
+ case BLOODYPOLE:
+ case FEM6PAD:
+ case STATUE:
+ case STATUEFLASH:
+ case OOZ:
+ case OOZ2:
+ case WALLBLOOD1:
+ case WALLBLOOD2:
+ case WALLBLOOD3:
+ case WALLBLOOD4:
+ case WALLBLOOD5:
+ case WALLBLOOD7:
+ case WALLBLOOD8:
+ case SUSHIPLATE1:
+ case SUSHIPLATE2:
+ case SUSHIPLATE3:
+ case SUSHIPLATE4:
+ case FETUS:
+ case FETUSJIB:
+ case FETUSBROKE:
+ case HOTMEAT:
+ case FOODOBJECT16:
+ case DOLPHIN1:
+ case DOLPHIN2:
+ case TOUGHGAL:
+ case TAMPON:
+ case XXXSTACY:
+ case 4946:
+ case 4947:
+ case 693:
+ case 2254:
+ case 4560:
+ case 4561:
+ case 4562:
+ case 4498:
+ case 4957:
+ if(ud.lockout)
+ {
+ t->xrepeat = t->yrepeat = 0;
+ continue;
+ }
+ }
+
+ if( t->statnum == 99 ) continue;
+ if( s->statnum != 1 && s->picnum == APLAYER && ps[s->yvel].newowner == -1 && s->owner >= 0 )
+ {
+ t->x -= mulscale16(65536-smoothratio,ps[s->yvel].posx-ps[s->yvel].oposx);
+ t->y -= mulscale16(65536-smoothratio,ps[s->yvel].posy-ps[s->yvel].oposy);
+ t->z = ps[s->yvel].oposz + mulscale16(smoothratio,ps[s->yvel].posz-ps[s->yvel].oposz);
+ t->z += (40<<8);
+ }
+ else if( ( s->statnum == 0 && s->picnum != CRANEPOLE) || s->statnum == 10 || s->statnum == 6 || s->statnum == 4 || s->statnum == 5 || s->statnum == 1 )
+ {
+ t->x -= mulscale16(65536-smoothratio,s->x-hittype[i].bposx);
+ t->y -= mulscale16(65536-smoothratio,s->y-hittype[i].bposy);
+ t->z -= mulscale16(65536-smoothratio,s->z-hittype[i].bposz);
+ }
+
+ sect = s->sectnum;
+ t1 = T2;t3 = T4;t4 = T5;
+
+ switch(s->picnum)
+ {
+ case DUKELYINGDEAD:
+ t->z += (24<<8);
+ break;
+ case BLOODPOOL:
+ case FOOTPRINTS:
+ case FOOTPRINTS2:
+ case FOOTPRINTS3:
+ case FOOTPRINTS4:
+ if(t->pal == 6)
+ t->shade = -127;
+ case PUKE:
+ case MONEY:
+ case MONEY+1:
+ case MAIL:
+ case MAIL+1:
+ case PAPER:
+ case PAPER+1:
+ if(ud.lockout && s->pal == 2)
+ {
+ t->xrepeat = t->yrepeat = 0;
+ continue;
+ }
+ break;
+ case TRIPBOMB:
+ continue;
+ case FORCESPHERE:
+ if(t->statnum == 5)
+ {
+ short sqa,sqb;
+
+ sqa =
+ getangle(
+ sprite[s->owner].x-ps[screenpeek].posx,
+ sprite[s->owner].y-ps[screenpeek].posy);
+ sqb =
+ getangle(
+ sprite[s->owner].x-t->x,
+ sprite[s->owner].y-t->y);
+
+ if( klabs(getincangle(sqa,sqb)) > 512 )
+ if( ldist(&sprite[s->owner],t) < ldist(&sprite[ps[screenpeek].i],&sprite[s->owner]) )
+ t->xrepeat = t->yrepeat = 0;
+ }
+ continue;
+ case BURNING:
+ case BURNING2:
+ if( sprite[s->owner].statnum == 10 )
+ {
+ if( display_mirror == 0 && sprite[s->owner].yvel == screenpeek && ps[sprite[s->owner].yvel].over_shoulder_on == 0 )
+ t->xrepeat = 0;
+ else
+ {
+ t->ang = getangle(x-t->x,y-t->y);
+ t->x = sprite[s->owner].x;
+ t->y = sprite[s->owner].y;
+ t->x += sintable[(t->ang+512)&2047]>>10;
+ t->y += sintable[t->ang&2047]>>10;
+ }
+ }
+ break;
+
+ case ATOMICHEALTH:
+ t->z -= (4<<8);
+ break;
+ case CRYSTALAMMO:
+ t->shade = (sintable[(totalclock<<4)&2047]>>10);
+ continue;
+ case VIEWSCREEN:
+ case VIEWSCREEN2:
+ if(camsprite >= 0 && hittype[OW].temp_data[0] == 1)
+ {
+ t->picnum = STATIC;
+ t->cstat |= (rand()&12);
+ t->xrepeat += 8;
+ t->yrepeat += 8;
+ }
+ break;
+
+ case SHRINKSPARK:
+ t->picnum = SHRINKSPARK+( (totalclock>>4)&3 );
+ break;
+ case GROWSPARK:
+ t->picnum = GROWSPARK+( (totalclock>>4)&3 );
+ break;
+ case RPG:
+ k = getangle(s->x-x,s->y-y);
+ k = (((s->ang+3072+128-k)&2047)/170);
+ if(k > 6)
+ {
+ k = 12-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+ t->picnum = RPG+k;
+ break;
+
+ case RECON:
+
+ k = getangle(s->x-x,s->y-y);
+ if( T1 < 4 )
+ k = (((s->ang+3072+128-k)&2047)/170);
+ else k = (((s->ang+3072+128-k)&2047)/170);
+
+ if(k>6)
+ {
+ k = 12-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+
+ if( klabs(t3) > 64 ) k += 7;
+ t->picnum = RECON+k;
+
+ break;
+
+ case APLAYER:
+
+ p = s->yvel;
+
+ if(t->pal == 1) t->z -= (18<<8);
+
+ if(ps[p].over_shoulder_on > 0 && ps[p].newowner < 0 )
+ {
+ t->cstat |= 2;
+ if ( screenpeek == myconnectindex && numplayers >= 2 )
+ {
+ t->x = omyx+mulscale16((int32_t)(myx-omyx),smoothratio);
+ t->y = omyy+mulscale16((int32_t)(myy-omyy),smoothratio);
+ t->z = omyz+mulscale16((int32_t)(myz-omyz),smoothratio)+(40<<8);
+ t->ang = omyang+mulscale16((int32_t)(((myang+1024-omyang)&2047)-1024),smoothratio);
+ t->sectnum = mycursectnum;
+ }
+ }
+
+ if( ( display_mirror == 1 || screenpeek != p || s->owner == -1 ) && ud.multimode > 1 && ud.showweapons && sprite[ps[p].i].extra > 0 && ps[p].curr_weapon > 0 )
+ {
+ memcpy((spritetype *)&tsprite[spritesortcnt],(spritetype *)t,sizeof(spritetype));
+
+ tsprite[spritesortcnt].statnum = 99;
+
+ tsprite[spritesortcnt].yrepeat = ( t->yrepeat>>3 );
+ if(t->yrepeat < 4) t->yrepeat = 4;
+
+ tsprite[spritesortcnt].shade = t->shade;
+ tsprite[spritesortcnt].cstat = 0;
+
+ switch(ps[p].curr_weapon)
+ {
+ case PISTOL_WEAPON: tsprite[spritesortcnt].picnum = FIRSTGUNSPRITE; break;
+ case SHOTGUN_WEAPON: tsprite[spritesortcnt].picnum = SHOTGUNSPRITE; break;
+ case CHAINGUN_WEAPON: tsprite[spritesortcnt].picnum = CHAINGUNSPRITE; break;
+ case RPG_WEAPON: tsprite[spritesortcnt].picnum = RPGSPRITE; break;
+ case HANDREMOTE_WEAPON:
+ case HANDBOMB_WEAPON: tsprite[spritesortcnt].picnum = HEAVYHBOMB; break;
+ case TRIPBOMB_WEAPON: tsprite[spritesortcnt].picnum = TRIPBOMBSPRITE; break;
+ case GROW_WEAPON: tsprite[spritesortcnt].picnum = GROWSPRITEICON; break;
+ case SHRINKER_WEAPON: tsprite[spritesortcnt].picnum = SHRINKERSPRITE; break;
+ case FREEZE_WEAPON: tsprite[spritesortcnt].picnum = FREEZESPRITE; break;
+ case DEVISTATOR_WEAPON: tsprite[spritesortcnt].picnum = DEVISTATORSPRITE; break;
+ }
+
+ if(s->owner >= 0)
+ tsprite[spritesortcnt].z = ps[p].posz-(12<<8);
+ else tsprite[spritesortcnt].z = s->z-(51<<8);
+ if(ps[p].curr_weapon == HANDBOMB_WEAPON)
+ {
+ tsprite[spritesortcnt].xrepeat = 10;
+ tsprite[spritesortcnt].yrepeat = 10;
+ }
+ else
+ {
+ tsprite[spritesortcnt].xrepeat = 16;
+ tsprite[spritesortcnt].yrepeat = 16;
+ }
+ tsprite[spritesortcnt].pal = 0;
+ spritesortcnt++;
+ }
+
+ if(s->owner == -1)
+ {
+ k = (((s->ang+3072+128-a)&2047)>>8)&7;
+ if(k>4)
+ {
+ k = 8-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+
+ if(sector[t->sectnum].lotag == 2) k += 1795-1405;
+ else if( (hittype[i].floorz-s->z) > (64<<8) ) k += 60;
+
+ t->picnum += k;
+ t->pal = ps[p].palookup;
+
+ goto PALONLY;
+ }
+
+ if( ps[p].on_crane == -1 && (sector[s->sectnum].lotag&0x7ff) != 1 )
+ {
+ l = s->z-hittype[ps[p].i].floorz+(3<<8);
+ if( l > 1024 && s->yrepeat > 32 && s->extra > 0 )
+ s->yoffset = (int8_t )(l/(s->yrepeat<<2));
+ else s->yoffset=0;
+ }
+
+ if(ps[p].newowner > -1)
+ {
+ t4 = *(actorscrptr[APLAYER]+1);
+ t3 = 0;
+ t1 = *(actorscrptr[APLAYER]+2);
+ }
+
+ if(ud.camerasprite == -1 && ps[p].newowner == -1)
+ if(s->owner >= 0 && display_mirror == 0 && ps[p].over_shoulder_on == 0 )
+ if( ud.multimode < 2 || ( ud.multimode > 1 && p == screenpeek ) )
+ {
+ t->owner = -1;
+ t->xrepeat = t->yrepeat = 0;
+ continue;
+ }
+
+ PALONLY:
+
+ if( sector[sect].floorpal )
+ t->pal = sector[sect].floorpal;
+
+ if(s->owner == -1) continue;
+
+ if( t->z > hittype[i].floorz && t->xrepeat < 32 )
+ t->z = hittype[i].floorz;
+
+ break;
+
+ case JIBS1:
+ case JIBS2:
+ case JIBS3:
+ case JIBS4:
+ case JIBS5:
+ case JIBS6:
+ case HEADJIB1:
+ case LEGJIB1:
+ case ARMJIB1:
+ case LIZMANHEAD1:
+ case LIZMANARM1:
+ case LIZMANLEG1:
+ case DUKELEG:
+ case DUKEGUN:
+ case DUKETORSO:
+ if(ud.lockout)
+ {
+ t->xrepeat = t->yrepeat = 0;
+ continue;
+ }
+ if(t->pal == 6) t->shade = -120;
+
+ case SCRAP1:
+ case SCRAP2:
+ case SCRAP3:
+ case SCRAP4:
+ case SCRAP5:
+ case SCRAP6:
+ case SCRAP6+1:
+ case SCRAP6+2:
+ case SCRAP6+3:
+ case SCRAP6+4:
+ case SCRAP6+5:
+ case SCRAP6+6:
+ case SCRAP6+7:
+
+ if(hittype[i].picnum == BLIMP && t->picnum == SCRAP1 && s->yvel >= 0)
+ t->picnum = s->yvel;
+ else t->picnum += T1;
+ t->shade -= 6;
+
+ if( sector[sect].floorpal )
+ t->pal = sector[sect].floorpal;
+ break;
+
+ case WATERBUBBLE:
+ if(sector[t->sectnum].floorpicnum == FLOORSLIME)
+ {
+ t->pal = 7;
+ break;
+ }
+ default:
+
+ if( sector[sect].floorpal )
+ t->pal = sector[sect].floorpal;
+ break;
+ }
+
+ if( actorscrptr[s->picnum] )
+ {
+ if(t4>10000)
+ // FIX_00093: fixed crashbugs in multiplayer (mine/blimp)
+ // This is the mine issue (confusion bug in hittype[i].temp_data[4] usage)
+ // close to blimp bug (search for BLIMP)
+ // -> t4 aka macro T5 is incremented at DETONATEB: in actor.c
+ // for a time counter. Instead we want an address.
+ // Issue happens in confessn.map (do a dnclip + dnkroz + dncoords,
+ // start with duke3d_w32 /m /q2 -map confessn.map)
+ // go through the Guilty logo till x = -2932, y = 42174, z = 18416.
+ // blow up the bomb. Wait in the water. Look at the respawn sign
+ // at the bottom of the chain. Crashes when it's about to respawn.
+ // Lame fix. ok for w32. Doesn't work for other plateform.
+ // How to make a differene between a timer and an address??
+ {
+ l = *(int32_t *)(t4+8);
+
+ switch( l )
+ {
+ case 2:
+ k = (((s->ang+3072+128-a)&2047)>>8)&1;
+ break;
+
+ case 3:
+ case 4:
+ k = (((s->ang+3072+128-a)&2047)>>7)&7;
+ if(k > 3)
+ {
+ t->cstat |= 4;
+ k = 7-k;
+ }
+ else t->cstat &= ~4;
+ break;
+
+ case 5:
+ k = getangle(s->x-x,s->y-y);
+ k = (((s->ang+3072+128-k)&2047)>>8)&7;
+ if(k>4)
+ {
+ k = 8-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+ break;
+ case 7:
+ k = getangle(s->x-x,s->y-y);
+ k = (((s->ang+3072+128-k)&2047)/170);
+ if(k>6)
+ {
+ k = 12-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+ break;
+ case 8:
+ k = (((s->ang+3072+128-a)&2047)>>8)&7;
+ t->cstat &= ~4;
+ break;
+ default:
+ k = 0;
+ break;
+ }
+
+ t->picnum += k + ( *(int32_t *)t4 ) + l * t3;
+
+ if(l > 0)
+ while(tiles[t->picnum].dim.width == 0 && t->picnum > 0 )
+ t->picnum -= l; //Hack, for actors
+
+ if( hittype[i].dispicnum >= 0)
+ hittype[i].dispicnum = t->picnum;
+ }
+ else if(display_mirror == 1)
+ t->cstat |= 4;
+ }
+
+ if( s->statnum == 13 || badguy(s) || (s->picnum == APLAYER && s->owner >= 0) )
+ if(t->statnum != 99 && s->picnum != EXPLOSION2 && s->picnum != HANGLIGHT && s->picnum != DOMELITE)
+ if(s->picnum != HOTMEAT)
+ {
+ if( hittype[i].dispicnum < 0 )
+ {
+ hittype[i].dispicnum++;
+ continue;
+ }
+ else if( ud.shadows && spritesortcnt < (MAXSPRITESONSCREEN-2))
+ {
+ int32_t daz,xrep,yrep;
+
+ if( (sector[sect].lotag&0xff) > 2 || s->statnum == 4 || s->statnum == 5 || s->picnum == DRONE || s->picnum == COMMANDER )
+ daz = sector[sect].floorz;
+ else
+ daz = hittype[i].floorz;
+
+ if( (s->z-daz) < (8<<8) )
+ if( ps[screenpeek].posz < daz )
+ {
+ memcpy((spritetype *)&tsprite[spritesortcnt],(spritetype *)t,sizeof(spritetype));
+
+ tsprite[spritesortcnt].statnum = 99;
+
+ tsprite[spritesortcnt].yrepeat = ( t->yrepeat>>3 );
+ if(t->yrepeat < 4) t->yrepeat = 4;
+
+ tsprite[spritesortcnt].shade = 127;
+ tsprite[spritesortcnt].cstat |= 2;
+
+ tsprite[spritesortcnt].z = daz;
+ xrep = tsprite[spritesortcnt].xrepeat;// - (klabs(daz-t->z)>>11);
+ tsprite[spritesortcnt].xrepeat = xrep;
+ tsprite[spritesortcnt].pal = 4;
+
+ yrep = tsprite[spritesortcnt].yrepeat;// - (klabs(daz-t->z)>>11);
+ tsprite[spritesortcnt].yrepeat = yrep;
+ spritesortcnt++;
+ }
+ }
+
+ if( ps[screenpeek].heat_amount > 0 && ps[screenpeek].heat_on )
+ {
+ t->pal = 6;
+ t->shade = 0;
+ }
+ }
+
+
+ switch(s->picnum)
+ {
+ case LASERLINE:
+ if(sector[t->sectnum].lotag == 2) t->pal = 8;
+ t->z = sprite[s->owner].z-(3<<8);
+ if(lasermode == 2 && ps[screenpeek].heat_on == 0 )
+ t->yrepeat = 0;
+ case EXPLOSION2:
+ case EXPLOSION2BOT:
+ case FREEZEBLAST:
+ case ATOMICHEALTH:
+ case FIRELASER:
+ case SHRINKSPARK:
+ case GROWSPARK:
+ case CHAINGUN:
+ case SHRINKEREXPLOSION:
+ case RPG:
+ case FLOORFLAME:
+ if(t->picnum == EXPLOSION2)
+ {
+ ps[screenpeek].visibility = -127;
+ lastvisinc = totalclock+32;
+ restorepalette = 1;
+ }
+ t->shade = -127;
+ break;
+ case FIRE:
+ case FIRE2:
+ case BURNING:
+ case BURNING2:
+ if( sprite[s->owner].picnum != TREE1 && sprite[s->owner].picnum != TREE2 )
+ t->z = sector[t->sectnum].floorz;
+ t->shade = -127;
+ break;
+ case COOLEXPLOSION1:
+ t->shade = -127;
+ t->picnum += (s->shade>>1);
+ break;
+ case PLAYERONWATER:
+
+ k = (((t->ang+3072+128-a)&2047)>>8)&7;
+ if(k>4)
+ {
+ k = 8-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+
+ t->picnum = s->picnum+k+((T1<4)*5);
+ t->shade = sprite[s->owner].shade;
+
+ break;
+
+ case WATERSPLASH2:
+ t->picnum = WATERSPLASH2+t1;
+ break;
+ case REACTOR2:
+ t->picnum = s->picnum + T3;
+ break;
+ case SHELL:
+ t->picnum = s->picnum+(T1&1);
+ case SHOTGUNSHELL:
+ t->cstat |= 12;
+ if(T1 > 1) t->cstat &= ~4;
+ if(T1 > 2) t->cstat &= ~12;
+ break;
+ case FRAMEEFFECT1:
+ case FRAMEEFFECT1_13CON:
+ if(s->owner >= 0 && sprite[s->owner].statnum < MAXSTATUS)
+ {
+ if(sprite[s->owner].picnum == APLAYER)
+ if(ud.camerasprite == -1)
+ if(screenpeek == sprite[s->owner].yvel && display_mirror == 0)
+ {
+ t->owner = -1;
+ break;
+ }
+ if( (sprite[s->owner].cstat&32768) == 0 )
+ {
+ t->picnum = hittype[s->owner].dispicnum;
+ t->pal = sprite[s->owner].pal;
+ t->shade = sprite[s->owner].shade;
+ t->ang = sprite[s->owner].ang;
+ t->cstat = 2|sprite[s->owner].cstat;
+ }
+ }
+ break;
+
+ case CAMERA1:
+ case RAT:
+ k = (((t->ang+3072+128-a)&2047)>>8)&7;
+ if(k>4)
+ {
+ k = 8-k;
+ t->cstat |= 4;
+ }
+ else t->cstat &= ~4;
+ t->picnum = s->picnum+k;
+ break;
+ }
+
+ hittype[i].dispicnum = t->picnum;
+ if(sector[t->sectnum].floorpicnum == MIRROR)
+ t->xrepeat = t->yrepeat = 0;
+ }
+}
+
+
+
+#define NUMCHEATCODES 26
+uint8_t cheatquotes[NUMCHEATCODES][14] = {
+ {"cornholio"}, // 0
+ {"stuff"}, // 1
+ {"scotty###"}, // 2
+ {"coords"}, // 3
+ {"view"}, // 4
+ {"time"}, // 5
+ {"unlock"}, // 6
+ {"cashman"}, // 7
+ {"items"}, // 8
+ {"rate"}, // 9
+ {"skill#"}, // 10
+ {"beta"}, // 11
+ {"hyper"}, // 12
+ {"monsters"}, // 13
+ {"<RESERVED>"}, // 14
+ {"<RESERVED>"}, // 15
+ {"todd"}, // 16
+ {"showmap"}, // 17
+ {"kroz"}, // 18
+ {"allen"}, // 19
+ {"clip"}, // 20
+ {"weapons"}, // 21
+ {"inventory"}, // 22
+ {"keys"}, // 23
+ {"debug"} // 24
+// {"ending"}
+
+};
+
+
+uint8_t cheatbuf[10],cheatbuflen;
+void cheats(void)
+{
+ short ch, i, j, k, weapon;
+
+ if( (ps[myconnectindex].gm&MODE_TYPE) || (ps[myconnectindex].gm&MODE_MENU))
+ return;
+
+ if ( ps[myconnectindex].cheat_phase == 1)
+ {
+ while (KB_KeyWaiting())
+ {
+ ch = KB_Getch();
+ ch = tolower(ch);
+
+ if( !( (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') ) )
+ {
+ ps[myconnectindex].cheat_phase = 0;
+// FTA(46,&ps[myconnectindex]);
+ return;
+ }
+
+ cheatbuf[cheatbuflen++] = ch;
+ cheatbuf[cheatbuflen] = 0;
+
+ if(cheatbuflen > 11)
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ return;
+ }
+
+ for(k = 0;k < NUMCHEATCODES;k++)
+ {
+ for(j = 0;j<cheatbuflen;j++)
+ {
+ if( cheatbuf[j] == cheatquotes[k][j] || (cheatquotes[k][j] == '#' && ch >= '0' && ch <= '9') )
+ {
+ if( cheatquotes[k][j+1] == 0 ) goto FOUNDCHEAT;
+ if(j == cheatbuflen-1) return;
+ }
+ else break;
+ }
+ }
+
+ ps[myconnectindex].cheat_phase = 0;
+ return;
+
+ FOUNDCHEAT:
+ {
+ switch(k)
+ {
+ case 0: // cornholio
+ case 18: // kroz
+
+ ud.god = 1-ud.god;
+
+ if(ud.god)
+ { // set on
+ pus = 1;
+ pub = 1;
+ sprite[ps[myconnectindex].i].cstat = 257;
+
+ hittype[ps[myconnectindex].i].temp_data[0] = 0;
+ hittype[ps[myconnectindex].i].temp_data[1] = 0;
+ hittype[ps[myconnectindex].i].temp_data[2] = 0;
+ hittype[ps[myconnectindex].i].temp_data[3] = 0;
+ hittype[ps[myconnectindex].i].temp_data[4] = 0;
+ hittype[ps[myconnectindex].i].temp_data[5] = 0;
+
+ sprite[ps[myconnectindex].i].hitag = 0;
+ sprite[ps[myconnectindex].i].lotag = 0;
+ sprite[ps[myconnectindex].i].pal =
+ ps[myconnectindex].palookup;
+
+ FTA(17,&ps[myconnectindex],1);
+ }
+ else // set off
+ {
+ ud.god = 0;
+ sprite[ps[myconnectindex].i].extra = max_player_health;
+ hittype[ps[myconnectindex].i].extra = -1;
+ ps[myconnectindex].last_extra = max_player_health;
+ FTA(18,&ps[myconnectindex],1);
+ }
+
+ sprite[ps[myconnectindex].i].extra = max_player_health;
+ hittype[ps[myconnectindex].i].extra = 0;
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+
+ return;
+
+ case 1: // stuff
+
+ if(VOLUMEONE)
+ j = 6;
+ else
+ j = 0;
+
+ for ( weapon = PISTOL_WEAPON;weapon < MAX_WEAPONS-j;weapon++ )
+ ps[myconnectindex].gotweapon[weapon] = 1;
+
+ for ( weapon = PISTOL_WEAPON;
+ weapon < (MAX_WEAPONS-j);
+ weapon++ )
+ addammo( weapon, &ps[myconnectindex], max_ammo_amount[weapon] );
+
+ ps[myconnectindex].ammo_amount[GROW_WEAPON] = 50;
+
+ ps[myconnectindex].steroids_amount = 400;
+ ps[myconnectindex].heat_amount = 1200;
+ ps[myconnectindex].boot_amount = 200;
+ ps[myconnectindex].shield_amount = 100;
+ ps[myconnectindex].scuba_amount = 6400;
+ ps[myconnectindex].holoduke_amount = 2400;
+ ps[myconnectindex].jetpack_amount = 1600;
+ ps[myconnectindex].firstaid_amount = max_player_health;
+
+ ps[myconnectindex].got_access = 7;
+ FTA(5,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].inven_icon = 1;
+ return;
+
+ case 2: // dnscotty###
+ case 10: // skill#
+
+ if(k == 2)
+ {
+ short volnume,levnume;
+ volnume = cheatbuf[6] - '0';
+ levnume = (cheatbuf[7] - '0')*10+(cheatbuf[8]-'0');
+
+ volnume--;
+ levnume--;
+ if (VOLUMEONE)
+ {
+ if( volnume > 0 )
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+ }
+ }
+
+ if((volnume > 4)&&PLUTOPAK)
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+ }
+ else
+ if((volnume > 3)&&!PLUTOPAK)
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+ }
+ else
+
+ if(volnume == 0)
+ {
+ if(levnume > 5)
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+ }
+ }
+ else
+ {
+ if(levnume >= 11)
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+ }
+ }
+
+ ud.m_volume_number = ud.volume_number = volnume;
+ ud.m_level_number = ud.level_number = levnume;
+
+ }
+ else ud.m_player_skill = ud.player_skill =
+ cheatbuf[5] - '1';
+
+ if(numplayers > 1 && myconnectindex == connecthead)
+ {
+ tempbuf[0] = 5;
+ tempbuf[1] = ud.m_level_number;
+ tempbuf[2] = ud.m_volume_number;
+ tempbuf[3] = ud.m_player_skill;
+ tempbuf[4] = ud.m_monsters_off;
+ tempbuf[5] = ud.m_respawn_monsters;
+ tempbuf[6] = ud.m_respawn_items;
+ tempbuf[7] = ud.m_respawn_inventory;
+ tempbuf[8] = ud.m_coop;
+ tempbuf[9] = ud.m_marker;
+ tempbuf[10] = ud.m_ffire;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ sendpacket(i,(uint8_t*)tempbuf,11);
+ }
+ else ps[myconnectindex].gm |= MODE_RESTART;
+
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 3: // coords
+ ps[myconnectindex].cheat_phase = 0;
+ ud.coords = 1-ud.coords;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 4: // view
+ if( ps[myconnectindex].over_shoulder_on )
+ ps[myconnectindex].over_shoulder_on = 0;
+ else
+ {
+ ps[myconnectindex].over_shoulder_on = 1;
+ cameradist = 0;
+ cameraclock = totalclock;
+ }
+ // FTA(22,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 5: // time
+ // FTA(21,&ps[myconnectindex]);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 6: // unlock
+ for(i=numsectors-1;i>=0;i--) //Unlock
+ {
+ j = sector[i].lotag;
+ if(j == -1 || j == 32767) continue;
+ if( (j & 0x7fff) > 2 )
+ {
+ if( j&(0xffff-16384) )
+ sector[i].lotag &= (0xffff-16384);
+ operatesectors(i,ps[myconnectindex].i);
+ }
+ }
+ operateforcefields(ps[myconnectindex].i,-1);
+
+ FTA(100,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 7: // cashman
+ ud.cashman = 1-ud.cashman;
+ KB_ClearKeyDown(sc_N);
+ ps[myconnectindex].cheat_phase = 0;
+ return;
+
+ case 8: // items
+ ps[myconnectindex].steroids_amount = 400;
+ ps[myconnectindex].heat_amount = 1200;
+ ps[myconnectindex].boot_amount = 200;
+ ps[myconnectindex].shield_amount = 100;
+ ps[myconnectindex].scuba_amount = 6400;
+ ps[myconnectindex].holoduke_amount = 2400;
+ ps[myconnectindex].jetpack_amount = 1600;
+
+ ps[myconnectindex].firstaid_amount = max_player_health;
+ ps[myconnectindex].got_access = 7;
+ FTA(5,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 9: // rate
+ ud.tickrate ^= 1;
+ vscrn(); // FIX_00056: Refresh issue w/FPS, small Weapon and custom FTA, when screen resized down
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 11: // beta
+ FTA(105,&ps[myconnectindex],1);
+ KB_ClearKeyDown(sc_H);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 12: // hyper
+ ps[myconnectindex].steroids_amount = 399;
+ ps[myconnectindex].heat_amount = 1200;
+ ps[myconnectindex].cheat_phase = 0;
+ FTA(37,&ps[myconnectindex],1);
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 13: // monsters
+ if(actor_tog == 3) actor_tog = 0;
+ actor_tog++;
+ ps[screenpeek].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 14: // <RESERVED>
+ case 25: // ??
+ ud.eog = 1;
+ ps[myconnectindex].gm |= MODE_EOL;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 15: // <RESERVED>
+ ps[myconnectindex].gm = MODE_EOL;
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 16: // todd
+ FTA(99,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 17: // showmap
+ ud.showallmap = 1-ud.showallmap;
+ if(ud.showallmap)
+ {
+ for(i=0;i<(MAXSECTORS>>3);i++)
+ show2dsector[i] = 255;
+ for(i=0;i<(MAXWALLS>>3);i++)
+ show2dwall[i] = 255;
+ FTA(111,&ps[myconnectindex],1);
+ }
+ else
+ {
+ for(i=0;i<(MAXSECTORS>>3);i++)
+ show2dsector[i] = 0;
+ for(i=0;i<(MAXWALLS>>3);i++)
+ show2dwall[i] = 0;
+ FTA(1,&ps[myconnectindex],1);
+ }
+ ps[myconnectindex].cheat_phase = 0;
+ KB_FlushKeyboardQueue();
+ return;
+
+ case 19: // allen
+ FTA(79,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ KB_ClearKeyDown(sc_N);
+ return;
+
+ case 20: // clip
+ ud.clipping = 1-ud.clipping;
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].cheat_phase = 0;
+ FTA(112+ud.clipping,&ps[myconnectindex],1);
+ return;
+
+ case 21: // weapons
+ if(VOLUMEONE)
+ j = 6;
+ else
+ j = 0;
+
+ for ( weapon = PISTOL_WEAPON;weapon < MAX_WEAPONS-j;weapon++ )
+ {
+ addammo( weapon, &ps[myconnectindex], max_ammo_amount[weapon] );
+ ps[myconnectindex].gotweapon[weapon] = 1;
+ }
+
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].cheat_phase = 0;
+ FTA(119,&ps[myconnectindex],1);
+ return;
+
+ case 22: // inventory
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].cheat_phase = 0;
+ ps[myconnectindex].steroids_amount = 400;
+ ps[myconnectindex].heat_amount = 1200;
+ ps[myconnectindex].boot_amount = 200;
+ ps[myconnectindex].shield_amount = 100;
+ ps[myconnectindex].scuba_amount = 6400;
+ ps[myconnectindex].holoduke_amount = 2400;
+ ps[myconnectindex].jetpack_amount = 1600;
+ ps[myconnectindex].firstaid_amount = max_player_health;
+ FTA(120,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ return;
+
+ case 23: // keys
+ ps[myconnectindex].got_access = 7;
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].cheat_phase = 0;
+ FTA(121,&ps[myconnectindex],1);
+ return;
+
+ case 24: // debug
+ debug_on = 1-debug_on;
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].cheat_phase = 0;
+ break;
+ }
+ }
+ }
+ }
+
+ else
+ {
+ if( KB_KeyPressed(sc_D) )
+ {
+ if( ps[myconnectindex].cheat_phase >= 0 && numplayers < 2 && ud.recstat == 0)
+ ps[myconnectindex].cheat_phase = -1;
+ }
+
+ if( KB_KeyPressed(sc_N) )
+ {
+ if( ps[myconnectindex].cheat_phase == -1 )
+ {
+ if(ud.player_skill == 4)
+ {
+ FTA(22,&ps[myconnectindex],1);
+ ps[myconnectindex].cheat_phase = 0;
+ }
+ else
+ {
+ ps[myconnectindex].cheat_phase = 1;
+// FTA(25,&ps[myconnectindex]);
+ cheatbuflen = 0;
+ }
+ KB_FlushKeyboardQueue();
+ }
+ else if(ps[myconnectindex].cheat_phase != 0)
+ {
+ ps[myconnectindex].cheat_phase = 0;
+ KB_ClearKeyDown(sc_D);
+ KB_ClearKeyDown(sc_N);
+ }
+ }
+ }
+}
+
+
+int32_t nonsharedtimer;
+void nonsharedkeys(void)
+{
+ short i,ch;
+ int32_t j;
+ char text[512];
+
+ if(ud.recstat == 2)
+ {
+ ControlInfo noshareinfo;
+ CONTROL_GetInput( &noshareinfo );
+ }
+
+ if( KB_KeyPressed( sc_F12 ) )
+ {
+ KB_ClearKeyDown( sc_F12 );
+ takescreenshot();
+ // FTA(103,&ps[myconnectindex]); done better in takescreenshot()
+ }
+
+ if( !ALT_IS_PRESSED && ud.overhead_on == 0)
+ {
+ if( ACTION( gamefunc_Enlarge_Screen ) )
+ {
+ CONTROL_ClearAction( gamefunc_Enlarge_Screen );
+ if(ud.screen_size > 0)
+ sound(THUD);
+
+ // FIX_00027: Added an extra small statusbar (HUD)
+ if (ud.screen_size==4)
+ {
+ ud.extended_screen_size++;
+ if(ud.extended_screen_size==2)
+ {
+ ud.extended_screen_size = 1;
+ ud.screen_size -= 4;
+ }
+ }
+ else
+ ud.screen_size -= 4;
+ vscrn();
+ }
+ if( ACTION( gamefunc_Shrink_Screen ) )
+ {
+ CONTROL_ClearAction( gamefunc_Shrink_Screen );
+ if(ud.screen_size < 64) sound(THUD);
+
+ // FIX_00027: Added an extra small statusbar (HUD)
+ if (ud.screen_size==4)
+ {
+ ud.extended_screen_size--;
+ if(ud.extended_screen_size<0)
+ {
+ ud.extended_screen_size=0;
+ ud.screen_size += 4;
+ }
+ }
+ else
+ ud.screen_size += 4;
+ vscrn();
+ }
+
+ if(ud.screen_size < 4)
+ ud.extended_screen_size = 1;
+ else if(ud.screen_size > 4)
+ ud.extended_screen_size = 0;
+
+ }
+
+ if( ps[myconnectindex].cheat_phase == 1 || ps[myconnectindex].gm&(MODE_MENU|MODE_TYPE)) return;
+
+ if( ACTION(gamefunc_See_Coop_View) && ( ud.coop == 1 || ud.recstat == 2) )
+ {
+ CONTROL_ClearAction( gamefunc_See_Coop_View );
+ screenpeek = connectpoint2[screenpeek];
+ if(screenpeek == -1) screenpeek = connecthead;
+ restorepalette = 1;
+ }
+
+ if( ud.multimode > 1 && ACTION(gamefunc_Show_Opponents_Weapon) )
+ {
+ CONTROL_ClearAction(gamefunc_Show_Opponents_Weapon);
+ ud.showweapons = 1-ud.showweapons;
+ FTA(82-ud.showweapons,&ps[screenpeek],1);
+ }
+
+ if( ACTION(gamefunc_Toggle_Crosshair) )
+ {
+ CONTROL_ClearAction(gamefunc_Toggle_Crosshair);
+ ud.crosshair = 1-ud.crosshair;
+ FTA(21-ud.crosshair,&ps[screenpeek],1);
+ }
+
+ if(ud.overhead_on && ACTION(gamefunc_Map_Follow_Mode) )
+ {
+ CONTROL_ClearAction(gamefunc_Map_Follow_Mode);
+ ud.scrollmode = 1-ud.scrollmode;
+ if(ud.scrollmode)
+ {
+ ud.folx = ps[screenpeek].oposx;
+ ud.foly = ps[screenpeek].oposy;
+ ud.fola = ps[screenpeek].oang;
+ }
+ FTA(83+ud.scrollmode,&ps[myconnectindex],1);
+ }
+
+ if( SHIFTS_IS_PRESSED || ALT_IS_PRESSED )
+ {
+ i = 0;
+ if( KB_KeyPressed( sc_F1) ) { KB_ClearKeyDown(sc_F1);i = 1; }
+ if( KB_KeyPressed( sc_F2) ) { KB_ClearKeyDown(sc_F2);i = 2; }
+ if( KB_KeyPressed( sc_F3) ) { KB_ClearKeyDown(sc_F3);i = 3; }
+ if( KB_KeyPressed( sc_F4) ) { KB_ClearKeyDown(sc_F4);i = 4; }
+ if( KB_KeyPressed( sc_F5) ) { KB_ClearKeyDown(sc_F5);i = 5; }
+ if( KB_KeyPressed( sc_F6) ) { KB_ClearKeyDown(sc_F6);i = 6; }
+ if( KB_KeyPressed( sc_F7) ) { KB_ClearKeyDown(sc_F7);i = 7; }
+ if( KB_KeyPressed( sc_F8) ) { KB_ClearKeyDown(sc_F8);i = 8; }
+ if( KB_KeyPressed( sc_F9) ) { KB_ClearKeyDown(sc_F9);i = 9; }
+ if( KB_KeyPressed( sc_F10) ) {KB_ClearKeyDown(sc_F10);i = 10; }
+
+ if(i)
+ {
+ if(SHIFTS_IS_PRESSED)
+ {
+ if(i == 5 && ps[myconnectindex].fta > 0 && ps[myconnectindex].ftq == 26)
+ {
+ music_select++;
+
+ // FIX_00065: Music cycling with F5 and SHIFT-F5 messed up
+ if(VOLUMEALL) // Then its 1.3d reg
+ {
+ if(music_select == 33) music_select = 0;
+ }
+ else if (VOLUMEONE)
+ {
+ if(music_select == 6) music_select = 0;
+ }
+ else // assume 1.5 or plutopak
+ {
+ if(music_select == 44) music_select = 0;
+ }
+
+ strcpy(text,"PLAYING ");
+ strcat(text,&music_fn[0][music_select][0]);
+ MUSIC_StopSong(); // FIX_00074: Shift f5 doesn't change hi-res tunes, but only midi tunes.
+ playmusic(&music_fn[0][music_select][0]);
+ strcpy(&fta_quotes[26][0],text);
+ FTA(26,&ps[myconnectindex],1);
+ return;
+ }
+
+ adduserquote(ud.ridecule[i-1]);
+
+ ch = 0;
+
+ tempbuf[ch] = 4;
+ tempbuf[ch+1] = 0;
+ strcat((char*)tempbuf+1,ud.ridecule[i-1]);
+
+ i = 1+strlen(ud.ridecule[i-1]);
+
+ if(ud.multimode > 1)
+ for(ch=connecthead;ch>=0;ch=connectpoint2[ch])
+ if (ch != myconnectindex)
+ sendpacket(ch,tempbuf,i);
+
+ pus = NUMPAGES;
+ pub = NUMPAGES;
+
+ return;
+
+ }
+
+ if(ud.lockout == 0)
+ if(SoundToggle && ALT_IS_PRESSED && ( RTS_NumSounds() > 0 ) && rtsplaying == 0 && VoiceToggle )
+ {
+ rtsptr = RTS_GetSound (i-1);
+ if(*rtsptr == 'C')
+ FX_PlayVOC3D( rtsptr,0,0,0,255,-i);
+ else FX_PlayWAV3D( rtsptr,0,0,0,255,-i);
+
+ rtsplaying = 7;
+
+ if(ud.multimode > 1)
+ {
+ tempbuf[0] = 7;
+ tempbuf[1] = i;
+
+ for(ch=connecthead;ch>=0;ch=connectpoint2[ch])
+ if(ch != myconnectindex)
+ sendpacket(ch,(uint8_t*)tempbuf,2);
+ }
+
+ pus = NUMPAGES;
+ pub = NUMPAGES;
+
+ return;
+ }
+ }
+ }
+
+ if(!ALT_IS_PRESSED && !SHIFTS_IS_PRESSED)
+ {
+
+ if( ud.multimode > 1 && ACTION(gamefunc_SendMessage) )
+ {
+ KB_FlushKeyboardQueue();
+ CONTROL_ClearAction( gamefunc_SendMessage );
+ ps[myconnectindex].gm |= MODE_TYPE;
+ typebuf[0] = 0;
+ inputloc = 0;
+ }
+
+ if( KB_KeyPressed(sc_F1) || ( ud.show_help && ( KB_KeyPressed(sc_Space) || KB_KeyPressed(sc_Enter) || KB_KeyPressed(sc_kpad_Enter) ) ) )
+ {
+ KB_ClearKeyDown(sc_F1);
+ KB_ClearKeyDown(sc_Space);
+ KB_ClearKeyDown(sc_kpad_Enter);
+ KB_ClearKeyDown(sc_Enter);
+ ud.show_help ++;
+
+ if( ud.show_help > 2 )
+ {
+ ud.show_help = 0;
+ if(ud.multimode < 2 && ud.recstat != 2) ready2send = 1;
+ vscrn();
+ }
+ else
+ {
+ setview(0,0,xdim-1,ydim-1);
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ }
+ }
+ }
+
+// if(ud.multimode < 2)
+ {
+ if(ud.recstat != 2 && KB_KeyPressed( sc_F2 ) )
+ {
+ KB_ClearKeyDown( sc_F2 );
+
+ if(movesperpacket == 4 && connecthead != myconnectindex)
+ return;
+
+ FAKE_F2:
+ if(sprite[ps[myconnectindex].i].extra <= 0)
+ {
+ FTA(118,&ps[myconnectindex],1);
+ return;
+ }
+ cmenu(350);
+ screencapt = 1;
+ displayrooms(myconnectindex,65536);
+ savetemp("duke3d.tmp",tiles[MAXTILES-1].data,160*100);
+ screencapt = 0;
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+// setview(0,0,xdim-1,ydim-1);
+ ps[myconnectindex].gm |= MODE_MENU;
+
+ if(ud.multimode < 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ screenpeek = myconnectindex;
+ }
+ }
+
+ if(KB_KeyPressed( sc_F3 ))
+ {
+ KB_ClearKeyDown( sc_F3 );
+
+ if(movesperpacket == 4 && connecthead != myconnectindex)
+ return;
+
+ cmenu(300);
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+// setview(0,0,xdim-1,ydim-1);
+ ps[myconnectindex].gm |= MODE_MENU;
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ }
+ screenpeek = myconnectindex;
+ }
+ }
+
+ if(KB_KeyPressed( sc_F4 ) && FXDevice != NumSoundCards )
+ {
+ KB_ClearKeyDown( sc_F4 );
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+ ps[myconnectindex].gm |= MODE_MENU;
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ }
+ cmenu(700);
+
+ }
+
+ if( KB_KeyPressed( sc_F6 ) && (ps[myconnectindex].gm&MODE_GAME))
+ {
+ KB_ClearKeyDown( sc_F6 );
+
+ if(movesperpacket == 4 && connecthead != myconnectindex)
+ return;
+
+ if(lastsavedpos == -1) goto FAKE_F2;
+
+ KB_FlushKeyboardQueue();
+
+ if(sprite[ps[myconnectindex].i].extra <= 0)
+ {
+ FTA(118,&ps[myconnectindex],1);
+ return;
+ }
+ screencapt = 1;
+ displayrooms(myconnectindex,65536);
+ savetemp("duke3d.tmp",tiles[MAXTILES-1].data,160*100);
+ screencapt = 0;
+ if( lastsavedpos >= 0 )
+ {
+ inputloc = strlen(&ud.savegame[lastsavedpos][0]);
+ current_menu = 360+lastsavedpos;
+ probey = lastsavedpos;
+ }
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+ setview(0,0,xdim-1,ydim-1);
+ ps[myconnectindex].gm |= MODE_MENU;
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ }
+ }
+
+ if(KB_KeyPressed( sc_F7 ) )
+ {
+ KB_ClearKeyDown(sc_F7);
+ if( ps[myconnectindex].over_shoulder_on )
+ ps[myconnectindex].over_shoulder_on = 0;
+ else
+ {
+ ps[myconnectindex].over_shoulder_on = 1;
+ cameradist = 0;
+ cameraclock = totalclock;
+ }
+ FTA(109+ps[myconnectindex].over_shoulder_on,&ps[myconnectindex],1);
+ }
+
+ if( KB_KeyPressed( sc_F5 ) && MusicDevice != NumSoundCards )
+ {
+ KB_ClearKeyDown( sc_F5 );
+ strcpy(text,&music_fn[0][music_select][0]);
+ strcat(text,". USE SHIFT-F5 TO CHANGE.");
+ strcpy(fta_quotes[26],text);
+ FTA(26,&ps[myconnectindex],1);
+
+ }
+
+ if(KB_KeyPressed( sc_F8 ))
+ {
+ KB_ClearKeyDown( sc_F8 );
+ ud.fta_on = !ud.fta_on;
+ FTA(24-ud.fta_on,&ps[myconnectindex],1);
+ }
+
+ if(KB_KeyPressed( sc_F9 ) && (ps[myconnectindex].gm&MODE_GAME) )
+ {
+ KB_ClearKeyDown( sc_F9 );
+
+ if(movesperpacket == 4 && myconnectindex != connecthead)
+ return;
+
+ if( lastsavedpos >= 0 ) cmenu(15001);
+ else cmenu(25000);
+ FX_StopAllSounds();
+ clearsoundlocks();
+ ps[myconnectindex].gm |= MODE_MENU;
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ }
+ }
+
+ if(KB_KeyPressed( sc_F10 ))
+ {
+ KB_ClearKeyDown( sc_F10 );
+ cmenu(500);
+ FX_StopAllSounds();
+ clearsoundlocks();
+ ps[myconnectindex].gm |= MODE_MENU;
+ if(ud.multimode < 2 && ud.recstat != 2)
+ {
+ ready2send = 0;
+ totalclock = ototalclock;
+ }
+ }
+
+
+ if( ud.overhead_on != 0)
+ {
+
+ j = totalclock-nonsharedtimer; nonsharedtimer += j;
+ if ( ACTION( gamefunc_Enlarge_Screen ) )
+ ps[myconnectindex].zoom += mulscale6(j,max(ps[myconnectindex].zoom,256));
+ if ( ACTION( gamefunc_Shrink_Screen ) )
+ ps[myconnectindex].zoom -= mulscale6(j,max(ps[myconnectindex].zoom,256));
+
+ if( (ps[myconnectindex].zoom > 2048) )
+ ps[myconnectindex].zoom = 2048;
+ if( (ps[myconnectindex].zoom < 48) )
+ ps[myconnectindex].zoom = 48;
+
+ }
+ }
+
+ if( KB_KeyPressed(sc_Escape) && ud.overhead_on && ps[myconnectindex].newowner == -1 )
+ {
+ KB_ClearKeyDown( sc_Escape );
+ ud.last_overhead = ud.overhead_on;
+ ud.overhead_on = 0;
+ ud.scrollmode = 0;
+ vscrn();
+ }
+
+ if( ACTION(gamefunc_AutoRun) )
+ {
+ CONTROL_ClearAction(gamefunc_AutoRun);
+ ud.auto_run = 1-ud.auto_run;
+ FTA(85+ud.auto_run,&ps[myconnectindex],1);
+ }
+
+ if( ACTION(gamefunc_Map) )
+ {
+ CONTROL_ClearAction( gamefunc_Map );
+ if( ud.last_overhead != ud.overhead_on && ud.last_overhead)
+ {
+ ud.overhead_on = ud.last_overhead;
+ ud.last_overhead = 0;
+ }
+ else
+ {
+ ud.overhead_on++;
+ if(ud.overhead_on == 3 ) ud.overhead_on = 0;
+ ud.last_overhead = ud.overhead_on;
+ }
+ restorepalette = 1;
+ vscrn();
+ }
+
+ if(KB_KeyPressed( sc_F11 ))
+ {
+ KB_ClearKeyDown( sc_F11 );
+ // FIX_00030: Brightness step was not the same from the keys vs menu
+ if(SHIFTS_IS_PRESSED) ud.brightness-=8; // Keyboard step must be 8, as the brightness cursor step.
+ else ud.brightness+=8;
+
+ if (ud.brightness > 56 )
+ ud.brightness = 0;
+ else if(ud.brightness < 0)
+ ud.brightness = 56;
+
+ setbrightness(ud.brightness>>2,&ps[myconnectindex].palette[0]);
+ if(ud.brightness < 40) FTA( 29 + (ud.brightness>>3) ,&ps[myconnectindex],1);
+ else if(ud.brightness < 80) FTA( 96 + (ud.brightness>>3) - 5,&ps[myconnectindex],1);
+ }
+}
+
+
+
+void comlinehelp(char **argv)
+{
+ printf("Command line help. %s [/flags...]\n",argv[0]);
+ puts(" ?, /? This help message");
+ puts(" /l## Level (1-11)");
+ puts(" /v# Volume (1-4)");
+ puts(" /s# Skill (1-4)");
+ puts(" /r Record demo");
+ puts(" /dFILE Start to play demo FILE");
+ puts(" /m No monsters");
+ puts(" /ns No sound");
+ puts(" /nm No music");
+ puts(" /t# Respawn, 1 = Monsters, 2 = Items, 3 = Inventory, x = All");
+ puts(" /c# MP mode, 1 = DukeMatch(spawn), 2 = Coop, 3 = Dukematch(no spawn)");
+ puts(" /q# Fake multiplayer (2-8 players)");
+ puts(" /a Use player AI (fake multiplayer only)");
+ puts(" /i# Network mode (1/0) (multiplayer only) (default == 1)");
+ puts(" /f# Send fewer packets (1, 2, 4) (multiplayer only)");
+ puts(" /gFILE, /g... Use multiple group files (must be last on command line)");
+ puts(" /xFILE Compile FILE (default GAME.CON)");
+ puts(" /u######### User's favorite weapon order (default: 3425689071)");
+ puts(" /# Load and run a game (slot 0-9)");
+ puts(" /z Skip memory check");
+ puts(" -map FILE Use a map FILE");
+ puts(" -name NAME Foward NAME");
+ puts(" -net Net mode game");
+ printf("\n");
+}
+
+void checkcommandline(int argc,char **argv)
+{
+ short i, j;
+ char *c;
+ char kbdKey;
+
+ ud.fta_on = 1;
+ ud.god = 0;
+ ud.m_respawn_items = 0;
+ ud.m_respawn_monsters = 0;
+ ud.m_respawn_inventory = 0;
+ ud.warp_on = 0;
+ ud.cashman = 0;
+ ud.m_player_skill = ud.player_skill = 2;
+ ud.multimode_bot = 0;
+
+#ifdef BETA
+ return;
+#endif
+
+ printf("Commands: ");
+ i=1;
+ while(i < argc)
+ {
+ printf("%s ",argv[i]);
+ i++;
+ }
+ printf("\n");
+
+ i = 1;
+
+ if(argc > 1)
+ {
+ while(i < argc)
+ {
+ c = argv[i];
+
+ if (stricmp(c, "-map") == 0)
+ {
+ i++;
+ strcpy(boardfilename,argv[i]);
+ if( strchr(boardfilename,'.') == 0)
+ strcat(boardfilename,".map");
+ printf("Using level: '%s'.\n",boardfilename);
+ continue;
+
+ }
+
+ if (stricmp(c, "-net") == 0)
+ {
+ i += 2; // skip filename.
+ // FIX_00044: Markers are now on by default in netgames (as real DOS duke3d)
+ ud.m_marker = ud.marker = 1;
+ continue;
+ }
+
+ if (stricmp(c, "-game_dir") == 0)
+ {
+ // Get the file name
+ i++;
+ c = argv[i];
+ setGameDir(c);
+
+ // skip over the file name now that we have it.
+ i++;
+
+ continue;
+ }
+
+ if (stricmp(c, "-stun") == 0)
+ {
+ g_bStun = 1;
+
+ i++;
+ continue;
+ }
+
+ if (stricmp(c, "/disableautoaim") == 0)
+ {
+
+ printf( "\nThe Host used the /disableautoaim option to turn your Weapon AutoAim OFF\n"
+ "Playing without AutoAim is usually extremely difficult and can make boring\n"
+ "games ruining Duke's playability. Duke3D was not designed to play with\n"
+ "AutoAim OFF like in modern FPS.\n\n"
+ "Do you authorize the HOST to turn your AutoAim OFF (Y/N)? ");
+
+ do
+ kbdKey = getch()|' ';
+ while(kbdKey != 'n' && kbdKey != 'y');
+
+ printf("%c \n", kbdKey);
+
+ if(kbdKey == 'y')
+ nHostForceDisableAutoaim = 1;
+ else
+ nHostForceDisableAutoaim = 2;
+
+ i++;
+ continue;
+ }
+
+ if(*c == '-')
+ {
+ if( *(c+1) == '8' ) eightytwofifty = 1;
+ i++;
+ continue;
+ }
+
+ if(*c == '?')
+ {
+ comlinehelp(argv);
+ Error(EXIT_SUCCESS, "");
+ }
+
+ if(*c == '/')
+ {
+ c++;
+ switch(*c)
+ {
+ case 'x':
+ case 'X':
+ c++;
+ if(*c)
+ {
+ if(getGameDir()[0] != '\0'){
+ sprintf(confilename, "%s\\%s", getGameDir(), c);
+ }
+ else{
+ strcpy(confilename,c);
+ }
+
+ if(SafeFileExists(confilename) == 0){
+ Error(EXIT_SUCCESS, "Could not find con file '%s'.\n",confilename);
+ }
+ else printf("Using con file: '%s'\n",confilename);
+ }
+ break;
+ case 'g':
+ case 'G':
+ c++;
+ if(*c){
+ char fullpathgrpfile[16]; // 16 not enough
+ memset(fullpathgrpfile, 0, 16);
+
+ if( strchr(c,'.') == 0){
+ strcat(c,".grp"); // crap!
+ }
+
+ if(getGameDir()[0] != '\0'){
+ sprintf(fullpathgrpfile, "%s\\%s", getGameDir(), c);
+ }
+ else{
+ strcpy(fullpathgrpfile, c);
+ }
+
+ j = initgroupfile(fullpathgrpfile);
+ if( j == -1 )
+ printf("Could not find group file %s.\n",fullpathgrpfile);
+ }
+
+ break;
+ case 'a':
+ case 'A':
+ ud.playerai = 1;
+ puts("Other player AI.");
+ break;
+ case 'n':
+ case 'N':
+ c++;
+ if(*c == 's' || *c == 'S'){
+ CommandSoundToggleOff = 2;
+ puts("Sound off.");
+ }
+ else
+ if(*c == 'm' || *c == 'M'){
+ CommandMusicToggleOff = 1;
+ puts("Music off.");
+ }
+ else{
+ comlinehelp(argv);
+ Error(EXIT_SUCCESS, "");
+ }
+ break;
+ case 'i':
+ case 'I':
+ c++;
+ if(*c == '0')
+ networkmode = 0;
+ if(*c == '1')
+ networkmode = 1;
+ printf("Network Mode %d\n",networkmode);
+ break;
+ case 'c':
+ case 'C':
+ c++;
+ if(*c == '1' || *c == '2' || *c == '3' ) // C1 = DM; C2 =COOP
+ ud.m_coop = *c - '0' - 1; // 0 = DM 1 = COOP
+ else ud.m_coop = 0;
+
+ switch(ud.m_coop)
+ {
+ case 0:
+ puts("Dukematch (spawn).");
+ break;
+ case 1:
+ puts("Cooperative play.");
+ break;
+ case 2:
+ puts("Dukematch (no spawn).");
+ break;
+ }
+
+ break;
+ case 'z':
+ case 'Z':
+ memorycheckoveride = 1;
+ break;
+ case 'f':
+ case 'F':
+ c++;
+ if(*c == '1')
+ movesperpacket = 1;
+ if(*c == '2')
+ movesperpacket = 2;
+ if(*c == '4')
+ {
+ movesperpacket = 4;
+ setpackettimeout(0x3fffffff,0x3fffffff);
+ }
+ break;
+ case 't':
+ case 'T':
+ c++;
+ if(*c == '1') ud.m_respawn_monsters = 1;
+ else if(*c == '2') ud.m_respawn_items = 1;
+ else if(*c == '3') ud.m_respawn_inventory = 1;
+ else
+ {
+ ud.m_respawn_monsters = 1;
+ ud.m_respawn_items = 1;
+ ud.m_respawn_inventory = 1;
+ }
+ puts("Respawn on.");
+ break;
+ case 'm':
+ case 'M':
+ if( *(c+1) != 'a' && *(c+1) != 'A' )
+ {
+ ud.m_monsters_off = 1;
+ ud.m_player_skill = ud.player_skill = 0;
+ puts("Monsters off.");
+ }
+ break;
+ case 'w':
+ case 'W':
+ ud.coords = 1;
+ break;
+ case 'q':
+ case 'Q':
+ puts("Fake multiplayer mode.");
+ if( *(++c) == 0) ud.multimode_bot = 1;
+ else ud.multimode_bot = atol(c)%17;
+ ud.multimode = ud.multimode_bot;
+ ud.m_coop = ud.coop = 0;
+ ud.m_marker = ud.marker = 1;
+ ud.m_respawn_monsters = ud.respawn_monsters = 1;
+ ud.m_respawn_items = ud.respawn_items = 1;
+ ud.m_respawn_inventory = ud.respawn_inventory = 1;
+
+ break;
+ case 'r':
+ case 'R':
+ ud.m_recstat = 1;
+ puts("Demo record mode on.");
+ break;
+ case 'd':
+ case 'D':
+ c++;
+ if( strchr(c,'.') == 0)
+ strcat(c,".dmo");
+ printf("Play demo %s.\n",c);
+ strcpy(firstdemofile,c);
+ break;
+ case 'l':
+ case 'L':
+ ud.warp_on = 1;
+ c++;
+ ud.m_level_number = ud.level_number = (atol(c)-1)%11;
+ break;
+ case 'j':
+ case 'J':
+ Error(EXIT_SUCCESS, "This port has a auto adaptive version system. All versions supported, simply change your duke3d.grp\n");
+ break;
+
+ case 'v':
+ case 'V':
+ c++;
+ ud.warp_on = 1;
+ ud.m_volume_number = ud.volume_number = atol(c)-1;
+ break;
+ case 's':
+ case 'S':
+ c++;
+ ud.m_player_skill = ud.player_skill = (atol(c)%5);
+ if(ud.m_player_skill == 4)
+ ud.m_respawn_monsters = ud.respawn_monsters = 1;
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ ud.warp_on = 2 + (*c) - '0';
+ break;
+ case 'u':
+ case 'U':
+ c++;
+ j = 0;
+ if(*c)
+ {
+ puts("Using favorite weapon order(s).");
+ while(*c)
+ {
+ ud.mywchoice[j] = *c-'0';
+ c++;
+ j++;
+ }
+ while(j < 10)
+ {
+ if(j == 9)
+ ud.mywchoice[9] = 1;
+ else
+ ud.mywchoice[j] = 2;
+
+ j++;
+ }
+ }
+ else
+ {
+ puts("Using default weapon orders.");
+ }
+
+ break;
+
+ case '?': // Show help
+ default:
+
+ comlinehelp(argv);
+ Error(EXIT_SUCCESS, "");
+ break;
+ }
+ }
+ i++;
+ }
+ }
+}
+
+
+
+void printstr(short x, short y, uint8_t string[81], uint8_t attribute)
+{
+ uint8_t character;
+ short i, pos;
+
+ pos = (y*80+x)<<1;
+ i = 0;
+ while (string[i] != 0)
+ {
+ character = string[i];
+ printchrasm(0xb8000+(int32_t)pos,1L,(((int32_t)attribute<<8)+(int32_t)character));
+ i++;
+ pos+=2;
+ }
+}
+
+void Logo(void)
+{
+ short i,soundanm;
+
+ soundanm = 0;
+
+ ready2send = 0;
+
+ KB_FlushKeyboardQueue();
+
+ setview(0,0,xdim-1,ydim-1);
+ clearview(0L);
+ palto(0,0,0,63);
+
+ flushperms();
+ nextpage();
+
+ MUSIC_StopSong();
+
+ if(ud.showcinematics && numplayers < 2)
+ {
+ ////This plays the explosion from the nuclear sign at the beginning.
+ if(!VOLUMEONE)
+ {
+ if(!KB_KeyWaiting() && nomorelogohack == 0)
+ {
+ getpackets();
+
+#if 1
+ playanm("logo.anm",5);
+ palto(0,0,0,63);
+#endif
+
+#if 0
+ playanm("cineov2.anm",1);
+ clearview(0L);
+ nextpage();
+ playanm("vol4e1.anm",8);
+ clearview(0L);
+ nextpage();
+ playanm("vol4e2.anm",10);
+ clearview(0L);
+ nextpage();
+ playanm("vol4e3.anm",11);
+ clearview(0L);
+ nextpage();
+ playanm("DUKETEAM.ANM",4);
+ clearview(0L);
+ nextpage();
+ playanm("cineov3.anm",2);
+ clearview(0L);
+ nextpage();
+ playanm("RADLOGO.ANM",3);
+ clearview(0L);
+ nextpage();
+
+ playanm("vol41a.anm",6);
+ clearview(0L);
+ nextpage();
+ playanm("vol42a.anm",7);
+ clearview(0L);
+ nextpage();
+ playanm("vol43a.anm",9);
+ clearview(0L);
+ nextpage();
+#endif
+
+ KB_FlushKeyboardQueue();
+ }
+
+ clearview(0L);
+ nextpage();
+ }
+
+ //MIDI start here
+ playmusic(&env_music_fn[0][0]);
+
+ //"REALITY IS OUR GAME" Screen
+ for(i=0;i<64;i+=7)
+ palto(0,0,0,i);
+ ps[myconnectindex].palette = drealms;
+ palto(0,0,0,63);
+ rotatesprite(0,0,65536L,0,DREALMS,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage();
+ for(i=63;i>0;i-=7)
+ palto(0,0,0,i);
+
+
+
+ totalclock = 0;
+ while( totalclock < (120*7) && !KB_KeyWaiting() )
+ getpackets();
+
+
+
+
+
+ for(i=0;i<64;i+=7)
+ palto(0,0,0,i);
+ clearview(0L);
+ nextpage();
+ ps[myconnectindex].palette = titlepal;
+ flushperms();
+ rotatesprite(0,0,65536L,0,BETASCREEN,0,0,2+8+16+64,0,0,xdim-1,ydim-1);
+ KB_FlushKeyboardQueue();
+ nextpage();
+ for(i=63;i>0;i-=7)
+ palto(0,0,0,i);
+
+ totalclock = 0;
+
+ //Animate screen (Duke picture wiht "DUKE" "NUKEM 3D" coming from far away and hitting the screen"
+ while(totalclock < (860+120) && !KB_KeyWaiting())
+ {
+ rotatesprite(0,0,65536L,0,BETASCREEN,0,0,2+8+16+64,0,0,xdim-1,ydim-1);
+
+ if( totalclock > 120 && totalclock < (120+60) )
+ {
+ if(soundanm == 0)
+ {
+ soundanm = 1;
+ sound(PIPEBOMB_EXPLODE);
+ }
+ rotatesprite(160<<16,104<<16,(totalclock-120)<<10,0,DUKENUKEM,0,0,2+8,0,0,xdim-1,ydim-1);
+ }
+ else if( totalclock >= (120+60) )
+ rotatesprite(160<<16,(104)<<16,60<<10,0,DUKENUKEM,0,0,2+8,0,0,xdim-1,ydim-1);
+
+ if( totalclock > 220 && totalclock < (220+30) )
+ {
+ if( soundanm == 1)
+ {
+ soundanm = 2;
+ sound(PIPEBOMB_EXPLODE);
+ }
+
+ rotatesprite(160<<16,(104)<<16,60<<10,0,DUKENUKEM,0,0,2+8,0,0,xdim-1,ydim-1);
+ rotatesprite(160<<16,(129)<<16,(totalclock - 220 )<<11,0,THREEDEE,0,0,2+8,0,0,xdim-1,ydim-1);
+ }
+ else if( totalclock >= (220+30) )
+ rotatesprite(160<<16,(129)<<16,30<<11,0,THREEDEE,0,0,2+8,0,0,xdim-1,ydim-1);
+
+ if(PLUTOPAK) // FIX_00064: Cinematics explosions were not right for 1.3/1.3d grp.
+ {
+
+ if( totalclock >= 280 && totalclock < 395 )
+ {
+ rotatesprite(160<<16,(151)<<16,(410-totalclock)<<12,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1);
+ if(soundanm == 2)
+ {
+ soundanm = 3;
+ sound(FLY_BY);
+ }
+ }
+ else if( totalclock >= 395 )
+ {
+ if(soundanm == 3)
+ {
+ soundanm = 4;
+ sound(PIPEBOMB_EXPLODE);
+ }
+ rotatesprite(160<<16,(151)<<16,30<<11,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1);
+ }
+ }
+
+ getpackets();
+ nextpage();
+ }
+ // FIX_00077: Menu goes directly to the "NEW GAME" sub-menu when starting new game (Turrican)
+ KB_FlushKeyboardQueue();
+ }
+ else if(numplayers > 1)
+ {
+ // FIX_00079: "waiting player" screen not showing up (black screen)
+ playmusic(&env_music_fn[0][0]);
+
+ ps[myconnectindex].palette = titlepal;
+ for(i=63;i>0;i-=7) palto(0,0,0,i);
+
+ rotatesprite(0,0,65536L,0,BETASCREEN,0,0,2+8+16+64,0,0,xdim-1,ydim-1);
+ rotatesprite(160<<16,(104)<<16,60<<10,0,DUKENUKEM,0,0,2+8,0,0,xdim-1,ydim-1);
+ rotatesprite(160<<16,(129)<<16,30<<11,0,THREEDEE,0,0,2+8,0,0,xdim-1,ydim-1);
+ rotatesprite(160<<16,(151)<<16,30<<11,0,PLUTOPAKSPRITE+1,0,0,2+8,0,0,xdim-1,ydim-1);
+
+ gametext(160,190,"WAITING FOR PLAYERS",14,2);
+ nextpage();
+ }
+ else
+ {
+ // FIX_00091: Main theme starting too early (Bryzian/Turrican)
+ playmusic(&env_music_fn[0][0]);
+ }
+
+ waitforeverybody();
+
+ flushperms();
+ clearview(0L);
+ nextpage();
+
+ ps[myconnectindex].palette = palette;
+ sound(NITEVISION_ONOFF);
+
+ palto(0,0,0,0);
+ clearview(0L);
+}
+
+void loadtmb(void)
+{
+ uint8_t tmb[8000];
+ int32_t fil, l;
+
+ fil = kopen4load("d3dtimbr.tmb",0);
+
+ if(fil == -1)
+ return;
+
+ l = kfilelength(fil);
+
+ kread(fil,(uint8_t *)tmb,l);
+
+ MUSIC_RegisterTimbreBank(tmb);
+
+ kclose(fil);
+}
+
+/*
+ ===================
+ =
+ = ShutDown
+ =
+ ===================
+*/
+
+void ShutDown( void )
+{
+ SoundShutdown();
+ MusicShutdown();
+ uninittimer();
+ uninitengine();
+ CONTROL_Shutdown();
+ CONFIG_WriteSetup();
+ KB_Shutdown();
+ CONSOLE_Term();
+}
+
+
+/*
+ ===================
+ =
+ = Startup
+ =
+ ===================
+*/
+
+void compilecons(void)
+{
+ char userconfilename[512];
+
+ mymembuf = (char *)hittype;
+ labelcode = (int32_t *)&sector[0];
+ label = (char *)sprite;
+
+ sprintf(userconfilename, "%s", confilename);
+
+ loadefs(userconfilename,mymembuf, 0);
+
+}
+
+
+void Startup(void)
+{
+ int i;
+
+ // Init the Console
+ CONSOLE_Init();
+
+ KB_Startup();
+
+ CONFIG_GetSetupFilename();
+ CONFIG_ReadSetup();
+
+ compilecons();
+
+#ifdef AUSTRALIA
+ ud.lockout = 1;
+#endif
+
+ if(CommandSoundToggleOff) SoundToggle = 0;
+ if(CommandMusicToggleOff) MusicToggle = 0;
+
+//if(VOLUMEONE)
+//{
+// printf("\n*** You have run Duke Nukem 3D %ld times. ***\n",ud.executions);
+// if(ud.executions >= 50) puts("IT IS NOW TIME TO UPGRADE TO THE COMPLETE VERSION!!!\n");
+//}
+
+ CONTROL_Startup( ControllerType, &GetTime, TICRATE );
+
+// CTW - MODIFICATION
+// initengine(ScreenMode,ScreenWidth,ScreenHeight);
+ initengine();
+// CTW END - MODIFICATION
+ inittimer(TICRATE);
+
+ puts("Loading art header.");
+
+ loadpics("tiles000.art", "\0");
+
+ readsavenames();
+
+ tiles[MIRROR].dim.width = tiles[MIRROR].dim.height = 0;
+
+ for(i=0;i<MAXPLAYERS;i++) playerreadyflag[i] = 0;
+ initmultiplayers(0,0,0);
+
+ if(numplayers > 1)
+ puts("Multiplayer initialized.");
+
+ ps[myconnectindex].palette = (uint8_t *) &palette[0];
+ SetupGameButtons();
+
+ if(networkmode == 255)
+ networkmode = 1;
+
+#ifdef PLATFORM_DOS
+ puts("Checking music inits.");
+ MusicStartup();
+ puts("Checking sound inits.");
+ SoundStartup();
+#else
+ /* SBF - wasn't sure if swapping them would harm anything. */
+ puts("Checking sound inits.");
+ SoundStartup();
+ puts("Checking music inits.");
+ MusicStartup();
+#endif
+
+ // AutoAim
+ if(nHostForceDisableAutoaim)
+ ud.auto_aim = 0;
+
+ puts("loadtmb()");
+ loadtmb();
+}
+
+
+void sendscore(char *s)
+{
+ if(numplayers > 1)
+ genericmultifunction(-1,s,strlen(s)+1,5);
+}
+
+
+void getnames(void)
+{
+ short i,j,l;
+
+ // FIX_00031: Names now limited to 10 chars max that is the fragbar field limit.
+ for(l=0; l<=9 && myname[l];l++)
+ {
+ ud.user_name[myconnectindex][l] = toupper(myname[l]);
+ buf[l+2] = toupper(myname[l]);
+ }
+
+#ifdef CHECK_XDUKE_REV // must not be under "if(numplayers > 1)" so it runs in any case
+ ud.rev[myconnectindex][0] = true; // always true. Used to check who we validated
+ ud.rev[myconnectindex][1] = DUKE_ID;
+ ud.rev[myconnectindex][2] = CHOCOLATE_DUKE_REV_X;
+ ud.rev[myconnectindex][3] = CHOCOLATE_DUKE_REV_DOT_Y;
+#endif
+
+ memcpy(ud.groupefil_crc32[myconnectindex],groupefil_crc32, sizeof(groupefil_crc32));
+ ud.conSize[myconnectindex] = ud.conSize[0]; // [0] still containing the original value
+ ud.conCRC[myconnectindex] = ud.conCRC[0];
+ ud.exeCRC[myconnectindex] = ud.exeCRC[0];
+
+ if(numplayers > 1)
+ {
+
+ buf[0] = 6;
+ buf[1] = grpVersion;
+
+ buf[l+2] = 0;
+ l += 3;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if( i != myconnectindex )
+ sendpacket(i,(uint8_t*)buf,l);
+
+ if(nHostForceDisableAutoaim==2) // user doesn't want AA off.
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ buf[0] = 133; // request to stop the game.
+ sendpacket(i,(uint8_t*)buf,l);
+ }
+
+
+#ifdef CHECK_XDUKE_REV
+ buf[0] = 131; // xDuke TAG ID
+ buf[1] = ud.rev[myconnectindex][1];
+ buf[2] = ud.rev[myconnectindex][2]; // version x
+ buf[3] = ud.rev[myconnectindex][3]; // version .y
+
+ buf[4] = 0; // reserved
+ buf[5] = 0; // reserved...
+ buf[9] = 0; // reserved.
+ // See below for single player mode.
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if( i != myconnectindex )
+ sendpacket(i,&buf[0],10);
+#endif
+
+ // getpackets();
+
+
+ l = 1;
+ buf[0] = 9; // send weapon order
+
+ for(i=0;i<10;i++)
+ {
+ ud.wchoice[myconnectindex][i] = ud.mywchoice[i];
+ buf[l] = (uint8_t ) ud.mywchoice[i];
+ l++;
+ }
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if(i != myconnectindex)
+ sendpacket(i,(uint8_t*)&buf[0],11);
+
+ buf[0] = 134; // GRP CRC + CON SIZE + conCRC + exeCRC
+ memcpy(buf+1, groupefil_crc32, sizeof(groupefil_crc32));
+ memcpy(buf+1+sizeof(groupefil_crc32), ud.conSize, sizeof(ud.conSize[0]));
+ memcpy(buf+1+sizeof(groupefil_crc32)+sizeof(ud.conSize[0]), ud.conCRC, sizeof(ud.conCRC[0]));
+ memcpy(buf+1+sizeof(groupefil_crc32)+sizeof(ud.conSize[0])+sizeof(ud.conCRC[0]), ud.exeCRC, sizeof(ud.exeCRC[0]));
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if( i != myconnectindex )
+ sendpacket(i,(uint8_t*)buf,1+sizeof(groupefil_crc32)+sizeof(ud.conSize[0])+sizeof(ud.conCRC[0])+
+ sizeof(ud.exeCRC[0]));
+
+// getpackets();
+
+ buf[0] = 10;
+ buf[1] = ps[0].aim_mode;
+ ps[myconnectindex].aim_mode = ps[0].aim_mode;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if(i != myconnectindex)
+ sendpacket(i,(uint8_t*)buf,2);
+
+// getpackets();
+
+ if(cp == 0)
+ {
+ buf[0] = 125;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if(i != myconnectindex)
+ sendpacket(i,(uint8_t*)buf,1);
+ }
+
+// getpackets();
+
+ waitforeverybody();
+
+#ifdef CHECK_XDUKE_REV
+ // from command "case 131:"
+ for(l=0,i=connecthead;i>=0;i=connectpoint2[i])
+ if(((ud.rev[i][2]<<8)+ud.rev[i][3]) != ((CHOCOLATE_DUKE_REV_X<<8)+CHOCOLATE_DUKE_REV_DOT_Y))
+ l=1;
+ else
+ ud.rev[i][0] = true; // means we validated this guy
+
+ if(l)
+ {
+ printf("\n*** One or more players do not have the same xDuke version:\n\n");
+ for(l=0,i=connecthead;i>=0;i=connectpoint2[i])
+ printf("Player [%-10s] is using Chocolate DukeNukem3D v%d.%d\n", ud.user_name[i],
+ ud.rev[i][2],ud.rev[i][3]);
+ Error(EXIT_SUCCESS, "");
+ }
+#endif
+
+ // checking GRP/CON size from "case 134"
+ for(l=0,i=connecthead;i>=0;i=connectpoint2[i])
+ for(j=0; j<MAXGROUPFILES; j++)
+ {
+ if(ud.groupefil_crc32[i][j]!=ud.groupefil_crc32[myconnectindex][j] || ud.conSize[i] != ud.conSize[myconnectindex])
+ l=1;
+ }
+
+ if(l)
+ {
+ printf("\n*** One or more players do not have the same GRP/CON version:\n\n");
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ for(j=0; j<MAXGROUPFILES && ud.groupefil_crc32[i][j]; j++)
+ {
+ if(j)
+ printf(" GRP (Add-on) : %s CRC=%X\n",
+ grpVersion2char_from_crc(ud.groupefil_crc32[i][j]),
+ ud.groupefil_crc32[i][j]);
+ else
+ printf("Player [%-10s] GRP (base) : %s CRC=%X\n", ud.user_name[i],
+ grpVersion2char_from_crc(ud.groupefil_crc32[i][j]),
+ ud.groupefil_crc32[i][j]);
+ }
+ printf(" CON code size: %d\n\n",ud.conSize[i]);
+ }
+ Error(EXIT_SUCCESS, "");
+ }
+ }
+ else if(nHostForceDisableAutoaim==2)
+ {
+ nHostForceDisableAutoaim=0;
+ ud.auto_aim = 2;
+ }
+
+ if(cp == 1)
+ gameexit("Please put Duke Nukem 3D Atomic Edition CD in drive.");
+}
+
+
+const char* const baseDir="duke3d*.grp";
+#ifdef _WIN32
+
+void findGRPToUse(uint8_t * groupfilefullpath)
+{
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind = INVALID_HANDLE_VALUE;
+ int i=0,kbdKey ;
+ char groupfile[9][512];
+ int grpID ;
+
+ if(getGameDir()[0] != '\0')
+ {
+ sprintf(groupfilefullpath, "%s\\%s", getGameDir(), baseDir);
+ hFind = FindFirstFile(groupfilefullpath, &FindFileData);
+ if (hFind == INVALID_HANDLE_VALUE)
+ {
+ sprintf(groupfilefullpath, "%s", baseDir);
+ }
+ else
+ FindClose(hFind);
+ }
+ else
+ sprintf(groupfilefullpath, "%s", baseDir);
+
+ printf("Searching '%d':\n\n",groupfilefullpath);
+ hFind = FindFirstFile(groupfilefullpath,&FindFileData);
+
+ if ( hFind==INVALID_HANDLE_VALUE )
+ Error(EXIT_SUCCESS, "Can't find '%s'\n", groupfilefullpath);
+
+ do
+ {
+ i++;
+ sprintf(groupfile[i-1], "%s", FindFileData.cFileName);
+ printf("Found GRP #%d:\t%d Bytes\t %s \n", i, FindFileData.nFileSizeLow, groupfile[i-1]);
+ } while ( FindNextFile(hFind, &FindFileData) && i < 9 );
+
+ if(i==1)
+ grpID = 0;
+ else
+ {
+ printf("\n-> Choose a base GRP file from 1 to %c: ",'0' + i);
+ do
+ kbdKey = getch();
+ while(kbdKey < '1' || kbdKey > ('0' + i));
+ printf("%c\n", kbdKey);
+ grpID = groupfile[kbdKey-'1'];
+
+ }
+
+ FindClose(hFind);
+ if (strlen(getGameDir()) == 0)
+ sprintf(groupfilefullpath, "./%s", groupfile[grpID]);
+ else
+ sprintf(groupfilefullpath, "%s//%s", getGameDir(), groupfile[grpID]);
+}
+
+#else
+
+int dukeGRP_Match(char* filename,int length)
+{
+ char* cursor = filename+length-4;
+
+ if (strncasecmp(cursor,".grp",4))
+ return 0;
+
+ return !strncasecmp(filename,"duke3d",6);
+}
+
+
+void findGRPToUse(char * groupfilefullpath){
+
+ char directoryToScan[512];
+ struct dirent* dirEntry ;
+
+ directoryToScan[0] = '\0';
+
+ if (getGameDir()[0] != '\0')
+ {
+ strcat(directoryToScan,getGameDir());
+ if (directoryToScan[strlen(directoryToScan)-1] != '/')
+ strcat(directoryToScan,"/");
+ }
+ else{
+ strcat(directoryToScan, "/");
+ }
+
+ printf("Scanning directory '%s' for a GRP file like '%s'.\n",directoryToScan,baseDir);
+
+ DIR* dir = opendir(directoryToScan);
+
+ while ((dirEntry = readdir(dir)) != NULL)
+ {
+
+#ifdef __linux__
+ if (dukeGRP_Match(dirEntry->d_name, _D_EXACT_NAMLEN(dirEntry)))
+#else
+ if (dukeGRP_Match(dirEntry->d_name,strlen(dirEntry->d_name)))
+#endif
+ {
+ sprintf(groupfilefullpath,"%s%s",directoryToScan,dirEntry->d_name);
+ return;
+ }
+
+ }
+}
+
+#endif
+
+static int load_duke3d_groupfile(void)
+{
+ // FIX_00032: Added multi base GRP manager. Use duke3d*.grp to handle multiple grp.
+
+ char groupfilefullpath[512];
+ groupfilefullpath[0] = '\0';
+
+ findGRPToUse(groupfilefullpath);
+
+ if (groupfilefullpath[0] == '\0')
+ return false;
+
+
+ FixFilePath(groupfilefullpath);
+
+ return(initgroupfile(groupfilefullpath) != -1);
+}
+
+#ifdef COMBINED_SDL
+#define main duke3d_main
+#else
+#define main my_main
+#endif
+
+int main(int argc,char **argv)
+{
+ int32_t i, j;
+ int32_t filehandle;
+
+
+ uint8_t kbdKey;
+ uint8_t *exe;
+
+
+ //printf( "This is a debug version 19.7.1 only Based on 19.7\n"
+ // "Fully compliant with v19.7. Added the following:\n\n"
+ // "FIX_00086: grp loaded by smaller sucessive chunks to avoid\n"
+ // " overloading low ram computers (Spanator)\n"
+ // "FIX_00087: intro in 1024x768 mode being slow. Undone FIX_00070\n"
+ // " and fixed font issue again (Bryzian)\n"
+ // "FIX_00088: crash on maps using a bad palette index like the end\n"
+ // " of roch3.map (NY00123)\n"
+ // "FIX_00089: scoreboard not shown for last player who quits a DM.\n"
+ // " Only 19.7 affected. (Sarah)\n"
+ // "FIX_00090: Removed showinfo key. FPS were shown after CRC msg. \n"
+ // " CRC not always removed. (Turrican)\n"
+ // "FIX_00091: Main theme starting too early (Bryzian/Turrican)\n"
+ // "FIX_00092: corrupted saved files making the following saved\n"
+ // " files invisible (Bryzian)\n\n"
+ // "This version should not be distributed. It's not secret but it\n"
+ // "would create a bad mess in the duke community if people start\n"
+ // "using it as it may contain new unsuspected bugs. Only a select\n"
+ // "group of known dukers who know what they are doing should be using\n"
+ // "it. Please report new bugs at xd@m-klein.com or on DX forums. Thx!\n\n");
+
+ printf("*** Chocolate DukeNukem3D v%d.%d ***\n\n", CHOCOLATE_DUKE_REV_X, CHOCOLATE_DUKE_REV_DOT_Y);
+
+ // FIX_00033: Fake multi and AI are now fully working
+ ud.multimode = 1; // xduke: must be done before checkcommandline or that will prevent Fakeplayer and AI
+
+ if (!load_duke3d_groupfile())
+ {
+ Error(EXIT_SUCCESS, "Could not initialize any original BASE duke3d*.grp file\n"
+ "Even if you are playing a custom GRP you still need\n"
+ "an original base GRP file as Shareware/Full 1.3D GRP or\n"
+ "the v1.5 ATOMIC GRP file. Such a file seems to be missing\n"
+ "or is corrupted\n");
+ }
+
+ rb->splashf(0, "point 1");
+ // FIX_00022: Automatically recognize the shareware grp (v1.3) + full version (1.3d) +
+ // atomic (1.4/1.5 grp) and the con files version (either 1.3 or 1.4) (JonoF's idea)
+
+ // Detecting grp version
+ // We keep the old GRP scheme detection for 19.6 compliance. Will be obsolete.
+ filehandle = kopen4load("DUKEDC9.MAP",1);
+ kclose(filehandle);
+
+ rb->splashf(0, "point 2");
+ if (filehandle == -1) // not DC pack
+ {
+ rb->splashf(0, "point 3");
+ filehandle = kopen4load("DUKESW.BIN",1);
+ kclose(filehandle);
+ rb->splashf(0, "point 4");
+
+ if (filehandle == -1) // not Shareware version 1.3
+ {
+ rb->splashf(0, "point 5");
+ filehandle = kopen4load("E4L11.MAP",1);
+ kclose(filehandle);
+ rb->splashf(0, "point 6");
+
+ if (filehandle == -1) // not Atomic Edition 1.4/1.5
+ {
+ rb->splashf(0, "point 7");
+ filehandle = kopen4load("E3L11.MAP",1);
+ kclose(filehandle);
+
+ rb->splashf(0, "point 8");
+
+ if (filehandle == -1) // not Regular version 1.3d
+ {
+ grpVersion = UNKNOWN_GRP;
+ }
+ else
+ {
+ grpVersion = REGULAR_GRP13D;
+ }
+ }
+ else
+ {
+ grpVersion = ATOMIC_GRP14_15;
+ }
+ }
+ else
+ {
+ grpVersion = SHAREWARE_GRP13;
+ }
+ }
+ else
+ {
+ grpVersion = DUKEITOUTINDC_GRP;
+ }
+
+ rb->splashf(0, "point 9");
+ // FIX_00062: Better support and identification for GRP and CON files for 1.3/1.3d/1.4/1.5
+ if ( groupefil_crc32[0]==CRC_BASE_GRP_SHAREWARE_13 ||
+ groupefil_crc32[0]==CRC_BASE_GRP_FULL_13 ||
+ groupefil_crc32[0]==CRC_BASE_GRP_PLUTONIUM_14 ||
+ groupefil_crc32[0]==CRC_BASE_GRP_ATOMIC_15 )
+ {
+ rb->splashf(0, "point 10");
+ printf("GRP identified as: %s\n", grpVersion2char_from_crc(groupefil_crc32[0]));
+ }
+ else
+ {
+ rb->splashf(0, "point 11");
+ printf( "The content of your original BASE *.GRP is corrupted. CRC=%X\n"
+ "You may run in troubles. Official GRP are:\n\n", groupefil_crc32[0]);
+
+ for(i=0; i<MAX_KNOWN_GRP; i++)
+ printf("%s -> CRC32=%X Size=%d bytes\n", crc32lookup[i].name, crc32lookup[i].crc32, crc32lookup[i].size);
+
+ printf( "\nYou should try to get one of these GRP only as a base GRP\n"
+ "Do you want to continue anyway? (Y/N): ");
+ do
+ kbdKey = getch() | ' ';
+ while(kbdKey != 'y' && kbdKey != 'n');
+ printf("%c\n", kbdKey);
+
+ if(kbdKey == 'n')
+ Error(EXIT_SUCCESS,"");
+ }
+
+ // computing exe crc
+ ud.exeCRC[0] = 0;
+ exe = NULL;
+ //filehandle = open(argv[0],O_BINARY|O_RDONLY);
+ filehandle = -1;
+ if(filehandle!=-1)
+ {
+ exe = malloc(filelength(filehandle));
+ if(exe)
+ {
+ read(filehandle, exe, filelength(filehandle));
+ ud.exeCRC[0] = crc32_update(exe, filelength(filehandle), ud.exeCRC[0]);
+ free(exe);
+ }
+ close(filehandle);
+ }
+
+ checkcommandline(argc,argv);
+
+ _platform_init(argc, argv, "Duke Nukem 3D", "Duke3D");
+
+ totalmemory = Z_AvailHeap();
+
+ if(memorycheckoveride == 0)
+ {
+ if(totalmemory < (3162000-350000))
+ {
+ puts("You don't have enough free memory to run Duke Nukem 3D.");
+ puts("The DOS \"mem\" command should report 6,800K (or 6.8 megs)");
+ puts("of \"total memory free\".\n");
+ printf("Duke Nukem 3D requires %d more bytes to run.\n",3162000-350000-totalmemory);
+ Error(EXIT_SUCCESS, "");
+ }
+ }
+ else
+ printf("Using %d bytes for heap.\n",totalmemory);
+
+ RegisterShutdownFunction( ShutDown );
+
+ Startup();
+
+ if( eightytwofifty && numplayers > 1 && (MusicDevice != NumSoundCards) )
+ {
+ puts("\n=========================================================================");
+ puts("WARNING: 8250 UART detected.");
+ puts("Music is being disabled and lower quality sound is being set. We apologize");
+ puts("for this, but it is necessary to maintain high frame rates while trying to");
+ puts("play the game on an 8250. We suggest upgrading to a 16550 or better UART");
+ puts("for maximum performance. Press any key to continue.");
+ puts("=========================================================================\n");
+
+ while( !KB_KeyWaiting() ) getpackets();
+ }
+
+ if(g_bStun)
+ {
+ waitforeverybody();
+ }
+
+ if(numplayers > 1) // if multimode > 1 and numplayer == 1 => fake player mode on
+ {
+ ud.multimode = numplayers;
+ sendlogon();
+ }
+ else if(boardfilename[0] != 0)
+ {
+ ud.m_level_number = 7;
+ ud.m_volume_number = 0;
+ ud.warp_on = 1;
+ }
+
+ /* crashes */
+ //rb->sleep(HZ/5);
+ ud.last_level = -1;
+
+ getnames();
+
+ //if(ud.multimode > 1)
+ //{
+ // playerswhenstarted = ud.multimode;
+
+ // AddFaz fix.
+ // This would cause monsters not to spawn when loading a usermap
+ /*
+ if(ud.warp_on == 0)
+ {
+ ud.m_monsters_off = 1;
+ ud.m_player_skill = 0;
+ }
+ */
+//}
+
+
+ RTS_Init(ud.rtsname);
+ if(numlumps)
+ printf("Using .RTS file:%s\n",ud.rtsname);
+
+ if (CONTROL_JoystickEnabled)
+ CONTROL_CenterJoystick(CenterCenter,UpperLeft,LowerRight,CenterThrottle,CenterRudder);
+
+ puts("Loading palette/lookups.");
+ if( setgamemode(ScreenMode,ScreenWidth,ScreenHeight) < 0 )
+ {
+ printf("\nVESA driver for ( %i * %i ) not found/supported!\n",xdim,ydim);
+ ScreenMode = 2;
+ ScreenWidth = 320;
+ ScreenHeight = 200;
+ setgamemode(ScreenMode,ScreenWidth,ScreenHeight);
+ }
+
+ printf("genspriteremaps()\n");
+ genspriteremaps();
+
+ extern bool printf_enabled;
+ printf_enabled = false;
+
+ setbrightness(ud.brightness>>2,&ps[myconnectindex].palette[0]);
+
+ if(KB_KeyPressed( sc_Escape ) )
+ gameexit(" ");
+
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+ if(ud.warp_on > 1 && ud.multimode < 2)
+ {
+ clearview(0L);
+ ps[myconnectindex].palette = palette;
+ palto(0,0,0,0);
+ rotatesprite(320<<15,200<<15,65536L,0,LOADSCREEN,0,0,2+8+64,0,0,xdim-1,ydim-1);
+ menutext(160,105,0,0,"LOADING SAVED GAME...");
+ nextpage();
+
+ j = loadplayer(ud.warp_on-2);
+ if(j)
+ ud.warp_on = 0;
+ }
+
+MAIN_LOOP_RESTART:
+
+ if(ud.warp_on == 0) //if game is loaded without /V or /L cmd arguments.
+ {
+
+ if (numplayers > 1 && boardfilename[0] != 0) //check if a user map is loaded and in multiplayer.
+ {
+ int c;
+
+ ud.level_number = ud.m_level_number = 7; // 7 = usermap.
+ ud.volume_number = ud.m_volume_number;
+ ud.player_skill = ud.m_player_skill;
+
+ switch(ud.m_coop) //set item spawn options, as they would be if
+ { //game was started via main menu.
+ case 0:
+ ud.respawn_inventory = ud.m_respawn_inventory = 1;
+ ud.respawn_items = ud.m_respawn_items = 1;
+ break;
+ case 1:
+ ud.respawn_inventory = ud.m_respawn_inventory = 1;
+ ud.respawn_items = ud.m_respawn_items = 0;
+ break;
+ case 2:
+ ud.respawn_inventory = ud.m_respawn_inventory = 0;
+ ud.respawn_items = ud.m_respawn_items = 0;
+ break;
+ }
+
+ if( ud.m_player_skill == 4 )
+ {
+ ud.m_respawn_monsters = 1; //set skill
+ }
+ else
+ {
+ ud.m_respawn_monsters = 0;
+ }
+
+ waitforeverybody();
+
+ for(c=connecthead;c>=0;c=connectpoint2[c])
+ {
+ resetweapons(c);
+ resetinventory(c);
+ }
+
+ newgame(ud.m_volume_number,ud.m_level_number,ud.m_player_skill);
+
+ enterlevel(MODE_GAME); //start game.
+
+ }
+ else
+ {
+ Logo(); //play logo, (game must be started via menus).
+ }
+ }
+
+
+
+ else if(ud.warp_on == 1) //if cmd arguments /V and /L are given.
+ {
+
+ if (numplayers > 1) //if in multiplayer reset everyones weapon status.
+ {
+ int c;
+
+ switch(ud.m_coop) //set item spawn options, as they would be if
+ { //game was started via main menu.
+ case 0:
+ ud.respawn_inventory = ud.m_respawn_inventory = 1;
+ ud.respawn_items = ud.m_respawn_items = 1;
+ break;
+ case 1:
+ ud.respawn_inventory = ud.m_respawn_inventory = 1;
+ ud.respawn_items = ud.m_respawn_items = 0;
+ break;
+ case 2:
+ ud.respawn_inventory = ud.m_respawn_inventory = 0;
+ ud.respawn_items = ud.m_respawn_items = 0;
+ break;
+ }
+
+ if( ud.m_player_skill == 4 )
+ {
+ ud.m_respawn_monsters = 1; //set skill
+ }
+ else
+ {
+ ud.m_respawn_monsters = 0;
+ }
+
+ waitforeverybody();
+
+ for(c=connecthead;c>=0;c=connectpoint2[c])
+ {
+ resetweapons(c); //without this players would spawn with no weapon.
+ resetinventory(c);
+ }
+
+ }
+
+ newgame(ud.m_volume_number,ud.m_level_number,ud.m_player_skill);
+ enterlevel(MODE_GAME); //start game.
+
+ }
+ else
+ {
+ vscrn();
+ }
+
+ if( ud.warp_on == 0 && playback() )
+ {
+ FX_StopAllSounds();
+ clearsoundlocks();
+ nomorelogohack = 1;
+ goto MAIN_LOOP_RESTART;
+ }
+
+ ud.warp_on = 0;
+
+ //The main game loop is here.
+ while ( !(ps[myconnectindex].gm&MODE_END) )
+ {
+ sampletimer();
+ if( ud.recstat == 2 || ud.multimode > 1 || ( ud.show_help == 0 && (ps[myconnectindex].gm&MODE_MENU) != MODE_MENU ) )
+ if( ps[myconnectindex].gm&MODE_GAME )
+ {
+ // (" It's stuck here ")
+ //printf("ps[myconnectindex].gm&MODE_GAME\n");
+ if( moveloop() )
+ {
+ continue;
+ }
+ }
+
+ if( ps[myconnectindex].gm&MODE_EOL || ps[myconnectindex].gm&MODE_RESTART )
+ {
+
+ if( ps[myconnectindex].gm&MODE_EOL )
+ {
+ closedemowrite();
+
+ ready2send = 0;
+
+ i = ud.screen_size;
+ ud.screen_size = 0;
+ vscrn();
+ ud.screen_size = i;
+ dobonus(0);
+
+ if(ud.eog)
+ {
+ ud.eog = 0;
+ if(ud.multimode < 2)
+ {
+ if(VOLUMEONE)
+ doorders();
+
+ ps[myconnectindex].gm = MODE_MENU;
+ cmenu(0);
+ probey = 0;
+ goto MAIN_LOOP_RESTART;
+ }
+ else
+ {
+ ud.m_level_number = 0;
+ ud.level_number = 0;
+ }
+ }
+ }
+
+ ready2send = 0;
+ if(numplayers > 1) ps[myconnectindex].gm = MODE_GAME;
+
+ enterlevel(ps[myconnectindex].gm);
+ continue;
+ }
+
+ cheats();
+
+ if( !CONSOLE_IsActive() )
+ nonsharedkeys();
+
+
+ if( (ud.show_help == 0 && ud.multimode < 2 && !(ps[myconnectindex].gm&MODE_MENU) ) || ud.multimode > 1 || ud.recstat == 2)
+ i = min(max((totalclock-ototalclock)*(65536L/TICSPERFRAME),0),65536);
+ else
+ i = 65536;
+
+ displayrooms(screenpeek,i);
+ displayrest(i);
+
+ if(ps[myconnectindex].gm&MODE_DEMO)
+ goto MAIN_LOOP_RESTART;
+
+ if(debug_on)
+ caches();
+
+ checksync();
+
+ if (VOLUMEONE)
+ if(ud.show_help == 0 && show_shareware > 0 && (ps[myconnectindex].gm&MODE_MENU) == 0 )
+ rotatesprite((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128,0,0,xdim-1,ydim-1);
+
+ nextpage();
+ }
+
+ gameexit(" ");
+ return(0);
+}
+
+uint8_t opendemoread(uint8_t which_demo) // 0 = mine
+{
+ char d[] = "demo_.dmo";
+ char *fname = d;
+ uint8_t ver;
+ short i,j;
+
+ int32 dummy;
+ int32_t groupefil_crc32_from_demo[MAXGROUPFILES];
+
+ if(which_demo == 10)
+ d[4] = 'x';
+ else
+ d[4] = '0' + which_demo;
+
+ ud.reccnt = 0;
+
+ if(which_demo == 1 && firstdemofile[0] != 0)
+ {
+ fname = firstdemofile;
+ if ((recfilep = TCkopen4load(firstdemofile,0)) == -1)
+ {
+ return(0);
+ }
+ }
+ else
+ {
+ if ((recfilep = TCkopen4load(d,0)) == -1)
+ {
+ return(0);
+ }
+ }
+
+ kread(recfilep,&ud.reccnt,sizeof(int32_t));
+ kread(recfilep,&ver,sizeof(uint8_t ));
+
+ printf("%s has version = %d\n", fname, ver);
+
+ // FIX_00015: Backward compliance with older demos (down to demos v27, 28, 116, 117 and 118)
+ if (PLUTOPAK)
+ {
+ if( (ver != BYTEVERSION && ver != BYTEVERSION_116 && ver != BYTEVERSION_117 && ver != BYTEVERSION_118) ) // || (ud.reccnt < 512) )
+ {
+ printf("%s is a demo version %d. We want v. %d, %d, %d, or %d (1.5 Atomic versions)\n",
+ fname, (int) ver, BYTEVERSION_116, BYTEVERSION_117, BYTEVERSION_118, BYTEVERSION);
+ kclose(recfilep);
+ return 0;
+ }
+ }
+ else // 1.3/1.3d style
+ {
+ if( (ver != BYTEVERSION && ver != BYTEVERSION_27 && ver != BYTEVERSION_28 && ver != BYTEVERSION_29) ) // || (ud.reccnt < 512) )
+ {
+ printf("%s is a demo version %d. We want v. %d, %d, %d or %d (1.3/1.3d versions)\n",
+ fname, (int) ver, BYTEVERSION_27, BYTEVERSION_28, BYTEVERSION_29, BYTEVERSION);
+ kclose(recfilep);
+ return 0;
+ }
+ }
+
+ // FIX_00062: Better support and identification for GRP and CON files for 1.3/1.3d/1.4/1.5
+ if(ver==BYTEVERSION)
+ {
+ kread(recfilep, (int32_t *)groupefil_crc32_from_demo, sizeof(groupefil_crc32_from_demo));
+
+ for(i=0; i<MAXGROUPFILES; i++)
+ if(groupefil_crc32_from_demo[i]!=groupefil_crc32[i])
+ {
+ for(j=0; j<=i; j++)
+ {
+ printf("You have GRP #%d: %s (CRC32=%X)\n"
+ "this demo expects %s (CRC32=%X)\n",
+ j, grpVersion2char_from_crc(groupefil_crc32[j]),groupefil_crc32[j],
+ grpVersion2char_from_crc(groupefil_crc32_from_demo[j]),groupefil_crc32_from_demo[j]);
+
+ }
+ kclose(recfilep);
+ return 0;
+ }
+
+
+ }
+
+ ud.playing_demo_rev = ver;
+
+ kread(recfilep,(uint8_t *)&ud.volume_number,sizeof(uint8_t ));
+ kread(recfilep,(uint8_t *)&ud.level_number,sizeof(uint8_t ));
+ kread(recfilep,(uint8_t *)&ud.player_skill,sizeof(uint8_t ));
+ kread(recfilep,(uint8_t *)&ud.m_coop,sizeof(uint8_t ));
+ kread(recfilep,(uint8_t *)&ud.m_ffire,sizeof(uint8_t ));
+ kread(recfilep,(short *)&ud.multimode,sizeof(short));
+ kread(recfilep,(short *)&ud.m_monsters_off,sizeof(short));
+ kread(recfilep,(int32 *)&ud.m_respawn_monsters,sizeof(int32));
+ kread(recfilep,(int32 *)&ud.m_respawn_items,sizeof(int32));
+ kread(recfilep,(int32 *)&ud.m_respawn_inventory,sizeof(int32));
+ kread(recfilep,(int32 *)&ud.playerai,sizeof(int32));
+ kread(recfilep,(uint8_t *)&ud.user_name[0][0],sizeof(ud.user_name));
+ // FIX_00034: Demos do not turn your run mode off anymore:
+ kread(recfilep,(int32 *)&dummy /*ud.auto_run*/,sizeof(int32)); // not needed and would affect autorun status in duke3d.cfg when quitting duke from a demo
+ kread(recfilep,(uint8_t *)boardfilename,sizeof(boardfilename));
+ if( boardfilename[0] != 0 )
+ {
+ ud.m_level_number = 7;
+ ud.m_volume_number = 0;
+ }
+
+ for(i=0;i<ud.multimode;i++)
+ {
+ kread(recfilep,(int32 *)&ps[i].aim_mode,sizeof(uint8_t ));
+
+ // FIX_00080: Out Of Synch in demos. Tries recovering OOS in old demos v27/28/29/116/117/118. New: v30/v119.
+ if(ver==BYTEVERSION)
+ kread(recfilep,ud.wchoice[i],sizeof(ud.wchoice[0]));
+ }
+
+ ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
+ ud.clipping = ud.scrollmode = ud.overhead_on = 0;
+ // FIX_00034: Demos do not turn your run mode off anymore:
+ /* ud.showweapons = */ ud.pause_on /*= ud.auto_run */ = 0; // makes no sense to reset those 2 value!
+
+ newgame(ud.volume_number,ud.level_number,ud.player_skill);
+ return(1);
+}
+
+
+void opendemowrite(void)
+{
+ char d[] = "demo1.dmo";
+ int32_t dummylong = 0;
+ uint8_t ver;
+ short i;
+ char fullpathdemofilename[16];
+
+ if(ud.recstat == 2) kclose(recfilep);
+
+ ver = BYTEVERSION;
+
+ // Are we loading a TC?
+ if(getGameDir()[0] != '\0'){
+ // Yes
+ sprintf(fullpathdemofilename, "%s\\%s", getGameDir(), d);
+ }
+ else{
+ // No
+ sprintf(fullpathdemofilename, "%s", d);
+ }
+
+// CTW - MODIFICATION
+// if ((frecfilep = fopen(d,"wb")) == -1) return;
+ if ((frecfilep = fopen(fullpathdemofilename,"wb")) == NULL) return;
+// CTW END - MODIFICATION
+ fwrite(&dummylong,4,1,frecfilep);
+ fwrite(&ver,sizeof(uint8_t ),1,frecfilep);
+ // FIX_00062: Better support and identification for GRP and CON files for 1.3/1.3d/1.4/1.5
+ fwrite((int32_t *)groupefil_crc32,sizeof(groupefil_crc32),1,frecfilep);
+ fwrite((uint8_t *)&ud.volume_number,sizeof(uint8_t ),1,frecfilep);
+ fwrite((uint8_t *)&ud.level_number,sizeof(uint8_t ),1,frecfilep);
+ fwrite((uint8_t *)&ud.player_skill,sizeof(uint8_t ),1,frecfilep);
+ fwrite((uint8_t *)&ud.m_coop,sizeof(uint8_t ),1,frecfilep);
+ fwrite((uint8_t *)&ud.m_ffire,sizeof(uint8_t ),1,frecfilep);
+ fwrite((short *)&ud.multimode,sizeof(short),1,frecfilep);
+ fwrite((short *)&ud.m_monsters_off,sizeof(short),1,frecfilep);
+ fwrite((int32 *)&ud.m_respawn_monsters,sizeof(int32),1,frecfilep);
+ fwrite((int32 *)&ud.m_respawn_items,sizeof(int32),1,frecfilep);
+ fwrite((int32 *)&ud.m_respawn_inventory,sizeof(int32),1,frecfilep);
+ fwrite((int32 *)&ud.playerai,sizeof(int32),1,frecfilep);
+ fwrite((uint8_t *)&ud.user_name[0][0],sizeof(ud.user_name),1,frecfilep);
+ fwrite((int32 *)&ud.auto_run,sizeof(int32),1,frecfilep);
+ fwrite((uint8_t *)boardfilename,sizeof(boardfilename),1,frecfilep);
+
+ for(i=0;i<ud.multimode;i++)
+ {
+ fwrite((int32 *)&ps[i].aim_mode,sizeof(uint8_t ),1,frecfilep); // seems wrong; prolly not needed anyway
+ // FIX_00080: Out Of Synch in demos. Tries recovering OOS in old demos v27/28/29/116/117/118. New: v30/v119.
+ fwrite(ud.wchoice[i],sizeof(ud.wchoice[0]),1,frecfilep);
+ }
+
+ totalreccnt = 0;
+ ud.reccnt = 0;
+}
+
+void record(void)
+{
+ short i;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ copybufbyte(&sync[i],&recsync[ud.reccnt],sizeof(input));
+ ud.reccnt++;
+ totalreccnt++;
+ if (ud.reccnt >= RECSYNCBUFSIZ)
+ {
+ dfwrite(recsync,sizeof(input)*ud.multimode,ud.reccnt/ud.multimode,frecfilep);
+ ud.reccnt = 0;
+ }
+ }
+}
+
+void closedemowrite(void)
+{
+ if (ud.recstat == 1)
+ {
+ if (ud.reccnt > 0)
+ {
+ dfwrite(recsync,sizeof(input)*ud.multimode,ud.reccnt/ud.multimode,frecfilep);
+
+ fseek(frecfilep,SEEK_SET,0L);
+ fwrite(&totalreccnt,sizeof(int32_t),1,frecfilep);
+ ud.recstat = ud.m_recstat = 0;
+ }
+ fclose(frecfilep);
+ frecfilep = NULL;
+ }
+}
+
+// CTW - MODIFICATION
+// On my XP machine, demo playback causes the game to crash shortly in.
+// Only bug found so far, not sure if it's OS dependent or compiler or what.
+// Seems to happen when player input starts being simulated, but just guessing.
+// This change effectively disables it. The related code is still enabled.
+// (This is working on Linux, so I flipped it back to '1'. --ryan.)
+ uint8_t which_demo = 0;
+// CTW END - MODIFICATION
+
+uint8_t in_menu = 0;
+
+// extern int32_t syncs[];
+int32_t playback(void)
+{
+ int32_t i,j,k,l,t;
+ uint8_t foundemo;
+
+ if( ready2send )
+ {
+ return 0;
+ }
+
+ /*
+ if(numplayers > 1)
+ return 1;
+ */
+
+ foundemo = 0;
+
+ RECHECK:
+
+ in_menu = ps[myconnectindex].gm&MODE_MENU;
+
+ pub = NUMPAGES;
+ pus = NUMPAGES;
+
+ flushperms();
+
+ if(numplayers < 2 && ud.multimode_bot<2) foundemo = opendemoread(which_demo);
+
+ if(foundemo == 0)
+ {
+
+ if(which_demo > 1)
+ {
+ which_demo = 1;
+ goto RECHECK;
+ }
+ for(t=0;t<63;t+=7) palto(0,0,0,t);
+ drawbackground();
+
+ CONSOLE_HandleInput();
+ if( !CONSOLE_IsActive())
+ {
+ menus();
+ }
+ CONSOLE_Render();
+ ps[myconnectindex].palette = palette;
+ nextpage();
+ for(t=63;t>0;t-=7)
+ {
+ palto(0,0,0,t);
+ }
+
+ ud.reccnt = 0;
+ }
+ else
+ {
+ ud.recstat = 2;
+ which_demo++;
+ if(which_demo == 10)
+ {
+ which_demo = 1;
+ }
+
+ enterlevel(MODE_DEMO);
+ }
+
+ if(foundemo == 0 || in_menu || KB_KeyWaiting() || numplayers > 1)
+ {
+ FX_StopAllSounds();
+ clearsoundlocks();
+ ps[myconnectindex].gm |= MODE_MENU;
+ }
+
+ ready2send = 0;
+ i = 0;
+
+ KB_FlushKeyboardQueue();
+
+ k = 0;
+
+ while (ud.reccnt > 0 || foundemo == 0)
+ {
+
+ if(foundemo) while ( totalclock >= (lockclock+TICSPERFRAME) )
+ {
+ if ((i == 0) || (i >= RECSYNCBUFSIZ))
+ {
+ i = 0;
+ l = min(ud.reccnt,RECSYNCBUFSIZ);
+ kdfread(recsync,sizeof(input)*ud.multimode,l/ud.multimode,recfilep);
+ }
+
+ for(j=connecthead;j>=0;j=connectpoint2[j])
+ {
+ copybufbyte(&recsync[i],&inputfifo[movefifoend[j]&(MOVEFIFOSIZ-1)][j],sizeof(input));
+
+ movefifoend[j]++;
+ i++;
+ ud.reccnt--;
+ }
+ domovethings();
+ }
+
+ if(foundemo == 0)
+ drawbackground();
+ else
+ {
+ if( !CONSOLE_IsActive() )
+ {
+ nonsharedkeys();
+ }
+
+ j = min(max((totalclock-lockclock)*(65536/TICSPERFRAME),0),65536);
+ displayrooms(screenpeek,j);
+ displayrest(j);
+
+ if(ud.multimode > 1 && ps[myconnectindex].gm )
+ getpackets();
+ }
+
+ if( (ps[myconnectindex].gm&MODE_MENU) && (ps[myconnectindex].gm&MODE_EOL) )
+ {
+ printf("playback(1) :: goto RECHECK:\n");
+ goto RECHECK;
+ }
+
+ if(ps[myconnectindex].gm&MODE_TYPE)
+ {
+ typemode();
+ if((ps[myconnectindex].gm&MODE_TYPE) != MODE_TYPE)
+ ps[myconnectindex].gm = MODE_MENU;
+ }
+ else
+ {
+ CONSOLE_HandleInput();
+ if( !CONSOLE_IsActive())
+ {
+ menus();
+ }
+ CONSOLE_Render();
+ if( ud.multimode > 1 )
+ {
+ ControlInfo noshareinfo;
+ if( !CONSOLE_IsActive() )
+ {
+ CONTROL_GetInput( &noshareinfo );
+ if( ACTION(gamefunc_SendMessage) )
+ {
+ KB_FlushKeyboardQueue();
+ CONTROL_ClearAction( gamefunc_SendMessage );
+ ps[myconnectindex].gm = MODE_TYPE;
+ typebuf[0] = 0;
+ inputloc = 0;
+ }
+ }
+
+ }
+ }
+
+ operatefta();
+
+ if(ud.last_camsprite != ud.camerasprite)
+ {
+ ud.last_camsprite = ud.camerasprite;
+ ud.camera_time = totalclock+(TICRATE*2);
+ }
+
+ if (VOLUMEONE)
+ if( ud.show_help == 0 && (ps[myconnectindex].gm&MODE_MENU) == 0 )
+ rotatesprite((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128,0,0,xdim-1,ydim-1);
+
+ getpackets();
+ nextpage();
+
+ if( ps[myconnectindex].gm==MODE_END || ps[myconnectindex].gm==MODE_GAME )
+ {
+ if(foundemo)
+ kclose(recfilep);
+ ud.playing_demo_rev = 0;
+ return 0;
+ }
+ }
+ kclose(recfilep);
+ ud.playing_demo_rev = 0;
+ if(ps[myconnectindex].gm&MODE_MENU)
+ {
+ goto RECHECK;
+ }
+
+ return 1;
+}
+
+uint8_t moveloop()
+{
+ int32_t i;
+
+ if (numplayers > 1)
+ {
+ while (fakemovefifoplc < movefifoend[myconnectindex])
+ {
+ fakedomovethings();
+ }
+ }
+
+
+ getpackets();
+
+ if (numplayers < 2) bufferjitter = 0;
+ while (movefifoend[myconnectindex]-movefifoplc > bufferjitter)
+ {
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if (movefifoplc == movefifoend[i]) break;
+ if (i >= 0) break;
+ if( domovethings() ) return 1;
+ }
+ return 0;
+}
+
+void fakedomovethingscorrect(void)
+{
+ int32_t i;
+ struct player_struct *p;
+
+ if (numplayers < 2) return;
+
+ i = ((movefifoplc-1)&(MOVEFIFOSIZ-1));
+ p = &ps[myconnectindex];
+
+ if (p->posx == myxbak[i] && p->posy == myybak[i] && p->posz == myzbak[i]
+ && p->horiz == myhorizbak[i] && p->ang == myangbak[i]) return;
+
+ myx = p->posx; omyx = p->oposx; myxvel = p->posxv;
+ myy = p->posy; omyy = p->oposy; myyvel = p->posyv;
+ myz = p->posz; omyz = p->oposz; myzvel = p->poszv;
+ myang = p->ang; omyang = p->oang;
+ mycursectnum = p->cursectnum;
+ myhoriz = p->horiz; omyhoriz = p->ohoriz;
+ myhorizoff = p->horizoff; omyhorizoff = p->ohorizoff;
+ myjumpingcounter = p->jumping_counter;
+ myjumpingtoggle = p->jumping_toggle;
+ myonground = p->on_ground;
+ myhardlanding = p->hard_landing;
+ myreturntocenter = p->return_to_center;
+
+ fakemovefifoplc = movefifoplc;
+ while (fakemovefifoplc < movefifoend[myconnectindex])
+ fakedomovethings();
+
+}
+
+void fakedomovethings(void)
+{
+ input *syn;
+ struct player_struct *p;
+ int32_t i, j, k, doubvel, fz, cz, hz, lz, x, y;
+ uint32_t sb_snum;
+ short psect, psectlotag, tempsect, backcstat;
+ uint8_t shrunk, spritebridge;
+
+ syn = (input *)&inputfifo[fakemovefifoplc&(MOVEFIFOSIZ-1)][myconnectindex];
+
+ p = &ps[myconnectindex];
+
+ backcstat = sprite[p->i].cstat;
+ sprite[p->i].cstat &= ~257;
+
+ sb_snum = syn->bits;
+
+ psect = mycursectnum;
+ psectlotag = sector[psect].lotag;
+ spritebridge = 0;
+
+ shrunk = (sprite[p->i].yrepeat < 32);
+
+ if( ud.clipping == 0 && ( sector[psect].floorpicnum == MIRROR || psect < 0 || psect >= MAXSECTORS) )
+ {
+ myx = omyx;
+ myy = omyy;
+ }
+ else
+ {
+ omyx = myx;
+ omyy = myy;
+ }
+
+ omyhoriz = myhoriz;
+ omyhorizoff = myhorizoff;
+ omyz = myz;
+ omyang = myang;
+
+ getzrange(myx,myy,myz,psect,&cz,&hz,&fz,&lz,163L,CLIPMASK0);
+
+ j = getflorzofslope(psect,myx,myy);
+
+ if( (lz&49152) == 16384 && psectlotag == 1 && klabs(myz-j) > PHEIGHT+(16<<8) )
+ psectlotag = 0;
+
+ if( p->aim_mode == 0 && myonground && psectlotag != 2 && (sector[psect].floorstat&2) )
+ {
+ x = myx+(sintable[(myang+512)&2047]>>5);
+ y = myy+(sintable[myang&2047]>>5);
+ tempsect = psect;
+ updatesector(x,y,&tempsect);
+ if (tempsect >= 0)
+ {
+ k = getflorzofslope(psect,x,y);
+ if (psect == tempsect)
+ myhorizoff += mulscale16(j-k,160);
+ else if (klabs(getflorzofslope(tempsect,x,y)-k) <= (4<<8))
+ myhorizoff += mulscale16(j-k,160);
+ }
+ }
+ if (myhorizoff > 0) myhorizoff -= ((myhorizoff>>3)+1);
+ else if (myhorizoff < 0) myhorizoff += (((-myhorizoff)>>3)+1);
+
+ if(hz >= 0 && (hz&49152) == 49152)
+ {
+ hz &= (MAXSPRITES-1);
+ if (sprite[hz].statnum == 1 && sprite[hz].extra >= 0)
+ {
+ hz = 0;
+ cz = getceilzofslope(psect,myx,myy);
+ }
+ }
+
+ if(lz >= 0 && (lz&49152) == 49152)
+ {
+ j = lz&(MAXSPRITES-1);
+ if ((sprite[j].cstat&33) == 33)
+ {
+ psectlotag = 0;
+ spritebridge = 1;
+ }
+ if(badguy(&sprite[j]) && sprite[j].xrepeat > 24 && klabs(sprite[p->i].z-sprite[j].z) < (84<<8) )
+ {
+ j = getangle( sprite[j].x-myx,sprite[j].y-myy);
+ myxvel -= sintable[(j+512)&2047]<<4;
+ myyvel -= sintable[j&2047]<<4;
+ }
+ }
+
+ if( sprite[p->i].extra <= 0 )
+ {
+ if( psectlotag == 2 )
+ {
+ if(p->on_warping_sector == 0)
+ {
+ if( klabs(myz-fz) > (PHEIGHT>>1))
+ myz += 348;
+ }
+ clipmove(&myx,&myy,&myz,&mycursectnum,0,0,164L,(4L<<8),(4L<<8),CLIPMASK0);
+ }
+
+ updatesector(myx,myy,&mycursectnum);
+ pushmove(&myx,&myy,&myz,&mycursectnum,128L,(4L<<8),(20L<<8),CLIPMASK0);
+
+ myhoriz = 100;
+ myhorizoff = 0;
+
+ goto ENDFAKEPROCESSINPUT;
+ }
+
+ doubvel = TICSPERFRAME;
+
+ if(p->on_crane >= 0) goto FAKEHORIZONLY;
+
+ if(p->one_eighty_count < 0) myang += 128;
+
+ i = 40;
+
+ if( psectlotag == 2)
+ {
+ myjumpingcounter = 0;
+
+ if ( sb_snum&1 )
+ {
+ if(myzvel > 0) myzvel = 0;
+ myzvel -= 348;
+ if(myzvel < -(256*6)) myzvel = -(256*6);
+ }
+ else if (sb_snum&(1<<1))
+ {
+ if(myzvel < 0) myzvel = 0;
+ myzvel += 348;
+ if(myzvel > (256*6)) myzvel = (256*6);
+ }
+ else
+ {
+ if(myzvel < 0)
+ {
+ myzvel += 256;
+ if(myzvel > 0)
+ myzvel = 0;
+ }
+ if(myzvel > 0)
+ {
+ myzvel -= 256;
+ if(myzvel < 0)
+ myzvel = 0;
+ }
+ }
+
+ if(myzvel > 2048) myzvel >>= 1;
+
+ myz += myzvel;
+
+ if(myz > (fz-(15<<8)) )
+ myz += ((fz-(15<<8))-myz)>>1;
+
+ if(myz < (cz+(4<<8)) )
+ {
+ myz = cz+(4<<8);
+ myzvel = 0;
+ }
+ }
+
+ else if(p->jetpack_on)
+ {
+ myonground = 0;
+ myjumpingcounter = 0;
+ myhardlanding = 0;
+
+ if(p->jetpack_on < 11)
+ myz -= (p->jetpack_on<<7); //Goin up
+
+ if(shrunk) j = 512;
+ else j = 2048;
+
+ if (sb_snum&1) //A
+ myz -= j;
+ if (sb_snum&(1<<1)) //Z
+ myz += j;
+
+ if(shrunk == 0 && ( psectlotag == 0 || psectlotag == 2 ) ) k = 32;
+ else k = 16;
+
+ if(myz > (fz-(k<<8)) )
+ myz += ((fz-(k<<8))-myz)>>1;
+ if(myz < (cz+(18<<8)) )
+ myz = cz+(18<<8);
+ }
+ else if( psectlotag != 2 )
+ {
+ if (psectlotag == 1 && p->spritebridge == 0)
+ {
+ if(shrunk == 0) i = 34;
+ else i = 12;
+ }
+ if(myz < (fz-(i<<8)) && (floorspace(psect)|ceilingspace(psect)) == 0 ) //falling
+ {
+ if( (sb_snum&3) == 0 && myonground && (sector[psect].floorstat&2) && myz >= (fz-(i<<8)-(16<<8) ) )
+ myz = fz-(i<<8);
+ else
+ {
+ myonground = 0;
+
+ myzvel += (gc+80);
+
+ if(myzvel >= (4096+2048)) myzvel = (4096+2048);
+ }
+ }
+
+ else
+ {
+ if(psectlotag != 1 && psectlotag != 2 && myonground == 0 && myzvel > (6144>>1))
+ myhardlanding = myzvel>>10;
+ myonground = 1;
+
+ if(i==40)
+ {
+ //Smooth on the ground
+
+ k = ((fz-(i<<8))-myz)>>1;
+ if( klabs(k) < 256 ) k = 0;
+ myz += k; // ((fz-(i<<8))-myz)>>1;
+ myzvel -= 768; // 412;
+ if(myzvel < 0) myzvel = 0;
+ }
+ else if(myjumpingcounter == 0)
+ {
+ myz += ((fz-(i<<7))-myz)>>1; //Smooth on the water
+ if(p->on_warping_sector == 0 && myz > fz-(16<<8))
+ {
+ myz = fz-(16<<8);
+ myzvel >>= 1;
+ }
+ }
+
+ if( sb_snum&2 )
+ myz += (2048+768);
+
+ if( (sb_snum&1) == 0 && myjumpingtoggle == 1)
+ myjumpingtoggle = 0;
+
+ else if( (sb_snum&1) && myjumpingtoggle == 0 )
+ {
+ if( myjumpingcounter == 0 )
+ if( (fz-cz) > (56<<8) )
+ {
+ myjumpingcounter = 1;
+ myjumpingtoggle = 1;
+ }
+ }
+ if( myjumpingcounter && (sb_snum&1) == 0 )
+ myjumpingcounter = 0;
+ }
+
+ if(myjumpingcounter)
+ {
+ if( (sb_snum&1) == 0 && myjumpingtoggle == 1)
+ myjumpingtoggle = 0;
+
+ if( myjumpingcounter < (1024+256) )
+ {
+ if(psectlotag == 1 && myjumpingcounter > 768)
+ {
+ myjumpingcounter = 0;
+ myzvel = -512;
+ }
+ else
+ {
+ myzvel -= (sintable[(2048-128+myjumpingcounter)&2047])/12;
+ myjumpingcounter += 180;
+
+ myonground = 0;
+ }
+ }
+ else
+ {
+ myjumpingcounter = 0;
+ myzvel = 0;
+ }
+ }
+
+ myz += myzvel;
+
+ if(myz < (cz+(4<<8)) )
+ {
+ myjumpingcounter = 0;
+ if(myzvel < 0) myxvel = myyvel = 0;
+ myzvel = 128;
+ myz = cz+(4<<8);
+ }
+
+ }
+
+ if ( p->fist_incs ||
+ p->transporter_hold > 2 ||
+ myhardlanding ||
+ p->access_incs > 0 ||
+ p->knee_incs > 0 ||
+ (p->curr_weapon == TRIPBOMB_WEAPON &&
+ p->kickback_pic > 1 &&
+ p->kickback_pic < 4 ) )
+ {
+ doubvel = 0;
+ myxvel = 0;
+ myyvel = 0;
+ }
+ else if ( syn->avel ) //p->ang += syncangvel * constant
+ { //ENGINE calculates angvel for you
+ int32_t tempang;
+
+ tempang = syn->avel<<1;
+
+ if(psectlotag == 2)
+ myang += (tempang-(tempang>>3))*sgn(doubvel);
+ else myang += (tempang)*sgn(doubvel);
+ myang &= 2047;
+ }
+
+ if ( myxvel || myyvel || syn->fvel || syn->svel )
+ {
+ if(p->steroids_amount > 0 && p->steroids_amount < 400)
+ doubvel <<= 1;
+
+ myxvel += ((syn->fvel*doubvel)<<6);
+ myyvel += ((syn->svel*doubvel)<<6);
+
+ if( ( p->curr_weapon == KNEE_WEAPON && p->kickback_pic > 10 && myonground ) || ( myonground && (sb_snum&2) ) )
+ {
+ myxvel = mulscale16(myxvel,dukefriction-0x2000);
+ myyvel = mulscale16(myyvel,dukefriction-0x2000);
+ }
+ else
+ {
+ if(psectlotag == 2)
+ {
+ myxvel = mulscale16(myxvel,dukefriction-0x1400);
+ myyvel = mulscale16(myyvel,dukefriction-0x1400);
+ }
+ else
+ {
+ myxvel = mulscale16(myxvel,dukefriction);
+ myyvel = mulscale16(myyvel,dukefriction);
+ }
+ }
+
+ if( abs(myxvel) < 2048 && abs(myyvel) < 2048 )
+ myxvel = myyvel = 0;
+
+ if( shrunk )
+ {
+ myxvel =
+ mulscale16(myxvel,(dukefriction)-(dukefriction>>1)+(dukefriction>>2));
+ myyvel =
+ mulscale16(myyvel,(dukefriction)-(dukefriction>>1)+(dukefriction>>2));
+ }
+ }
+
+FAKEHORIZONLY:
+ if(psectlotag == 1 || spritebridge == 1) i = (4L<<8); else i = (20L<<8);
+
+ clipmove(&myx,&myy,&myz,&mycursectnum,myxvel,myyvel,164L,4L<<8,i,CLIPMASK0);
+ pushmove(&myx,&myy,&myz,&mycursectnum,164L,4L<<8,4L<<8,CLIPMASK0);
+
+ if( p->jetpack_on == 0 && psectlotag != 1 && psectlotag != 2 && shrunk)
+ myz += 30<<8;
+
+ if ((sb_snum&(1<<18)) || myhardlanding)
+ myreturntocenter = 9;
+
+ if (sb_snum&(1<<13))
+ {
+ myreturntocenter = 9;
+ if (sb_snum&(1<<5)) myhoriz += 6;
+ myhoriz += 6;
+ }
+ else if (sb_snum&(1<<14))
+ {
+ myreturntocenter = 9;
+ if (sb_snum&(1<<5)) myhoriz -= 6;
+ myhoriz -= 6;
+ }
+ else if (sb_snum&(1<<3))
+ {
+ if (sb_snum&(1<<5)) myhoriz += 6;
+ myhoriz += 6;
+ }
+ else if (sb_snum&(1<<4))
+ {
+ if (sb_snum&(1<<5)) myhoriz -= 6;
+ myhoriz -= 6;
+ }
+
+ if (myreturntocenter > 0)
+ if ((sb_snum&(1<<13)) == 0 && (sb_snum&(1<<14)) == 0)
+ {
+ myreturntocenter--;
+ myhoriz += 33-(myhoriz/3);
+ }
+
+ if(p->aim_mode)
+ myhoriz += syn->horz>>1;
+ else
+ {
+ if( myhoriz > 95 && myhoriz < 105) myhoriz = 100;
+ if( myhorizoff > -5 && myhorizoff < 5) myhorizoff = 0;
+ }
+
+ if (myhardlanding > 0)
+ {
+ myhardlanding--;
+ myhoriz -= (myhardlanding<<4);
+ }
+
+ if (myhoriz > 299) myhoriz = 299;
+ else if (myhoriz < -99) myhoriz = -99;
+
+ if(p->knee_incs > 0)
+ {
+ myhoriz -= 48;
+ myreturntocenter = 9;
+ }
+
+
+ENDFAKEPROCESSINPUT:
+
+ myxbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myx;
+ myybak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myy;
+ myzbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myz;
+ myangbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myang;
+ myhorizbak[fakemovefifoplc&(MOVEFIFOSIZ-1)] = myhoriz;
+ fakemovefifoplc++;
+
+ sprite[p->i].cstat = backcstat;
+}
+
+
+uint8_t domovethings(void)
+{
+ short i, j;
+ uint8_t ch;
+
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ if( sync[i].bits&(1<<17) )
+ {
+ multiflag = 2;
+ multiwhat = (sync[i].bits>>18)&1;
+ multipos = (uint32_t) (sync[i].bits>>19)&15;
+ multiwho = i;
+
+ if( multiwhat )
+ {
+ // FIX_00058: Save/load game crash in both single and multiplayer
+ screencapt = 1;
+ displayrooms(myconnectindex,65536);
+ savetemp("duke3d.tmp",tiles[MAXTILES-1].data,160*100);
+ screencapt = 0;
+
+ saveplayer( multipos );
+ multiflag = 0;
+
+ if(multiwho != myconnectindex)
+ {
+ strcpy(fta_quotes[122],&ud.user_name[multiwho][0]);
+ strcat(fta_quotes[122]," SAVED A MULTIPLAYER GAME");
+ FTA(122,&ps[myconnectindex],1);
+ }
+ else
+ {
+ strcpy(fta_quotes[122],"MULTIPLAYER GAME SAVED");
+ FTA(122,&ps[myconnectindex],1);
+ }
+ break;
+ }
+ else
+ {
+// waitforeverybody();
+
+ j = loadplayer( multipos );
+
+ multiflag = 0;
+
+ if(j == 0)
+ {
+ if(multiwho != myconnectindex)
+ {
+ strcpy(fta_quotes[122],&ud.user_name[multiwho][0]);
+ strcat(fta_quotes[122]," LOADED A MULTIPLAYER GAME");
+ FTA(122,&ps[myconnectindex],1);
+ }
+ else
+ {
+ strcpy(fta_quotes[122],"MULTIPLAYER GAME LOADED");
+ FTA(122,&ps[myconnectindex],1);
+ }
+ return 1;
+ }
+ }
+ }
+
+ ud.camerasprite = -1;
+ lockclock += TICSPERFRAME;
+
+ if(earthquaketime > 0) earthquaketime--;
+ if(rtsplaying > 0) rtsplaying--;
+
+ for(i=0;i<MAXUSERQUOTES;i++)
+ if (user_quote_time[i])
+ {
+ user_quote_time[i]--;
+ if (!user_quote_time[i]) pub = NUMPAGES;
+ }
+ if ((klabs(quotebotgoal-quotebot) <= 16) && (ud.screen_size <= 8))
+ quotebot += ksgn(quotebotgoal-quotebot);
+ else
+ quotebot = quotebotgoal;
+
+ if( show_shareware > 0 )
+ {
+ show_shareware--;
+ if(show_shareware == 0)
+ {
+ pus = NUMPAGES;
+ pub = NUMPAGES;
+ }
+ }
+
+ everyothertime++;
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ copybufbyte(&inputfifo[movefifoplc&(MOVEFIFOSIZ-1)][i],&sync[i],sizeof(input));
+ movefifoplc++;
+
+ updateinterpolations();
+
+ j = -1;
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if ((sync[i].bits&(1<<26)) == 0) { j = i; continue; }
+
+ closedemowrite();
+
+ if (i == myconnectindex) gameexit(" ");
+ if (screenpeek == i)
+ {
+ screenpeek = connectpoint2[i];
+ if (screenpeek < 0) screenpeek = connecthead;
+ }
+
+ if (i == connecthead) connecthead = connectpoint2[connecthead];
+ else connectpoint2[j] = connectpoint2[i];
+
+ numplayers--;
+ ud.multimode--;
+
+ if (numplayers < 2)
+ sound(GENERIC_AMBIENCE17);
+
+ pub = NUMPAGES;
+ pus = NUMPAGES;
+ vscrn();
+
+ sprintf(buf,"%s is history!",ud.user_name[i]);
+
+ quickkill(&ps[i]);
+ deletesprite(ps[i].i);
+
+ adduserquote(buf);
+
+ if(j < 0 && networkmode == 0 )
+ gameexit( " \nThe 'MASTER/First player' just quit the game. All\nplayers are returned from the game. This only happens in 5-8\nplayer mode as a different network scheme is used.");
+ }
+
+ if ((numplayers >= 2) && ((movefifoplc&7) == 7))
+ {
+ ch = (uint8_t )(randomseed&255);
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ ch += ((ps[i].posx+ps[i].posy+ps[i].posz+ps[i].ang+ps[i].horiz)&255);
+ syncval[myconnectindex][syncvalhead[myconnectindex]&(MOVEFIFOSIZ-1)] = ch;
+ syncvalhead[myconnectindex]++;
+
+
+ }
+
+ if(ud.recstat == 1) record();
+
+ if( ud.pause_on == 0 )
+ {
+ global_random = TRAND;
+ movedummyplayers();//ST 13
+ }
+
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ cheatkeys(i);
+
+ if( ud.pause_on == 0 )
+ {
+ processinput(i);
+ checksectors(i);
+ }
+ }
+
+ if( ud.pause_on == 0 )
+ {
+ movefta();//ST 2
+ moveweapons(); //ST 5 (must be last)
+ movetransports(); //ST 9
+
+ moveplayers(); //ST 10
+ movefallers(); //ST 12
+ moveexplosions(); //ST 4
+
+ moveactors(); //ST 1
+ moveeffectors(); //ST 3
+
+ movestandables(); //ST 6
+ doanimations();
+ movefx(); //ST 11
+ }
+
+ fakedomovethingscorrect();
+
+ if( (everyothertime&1) == 0)
+ {
+ animatewalls();
+ movecyclers();
+ pan3dsound();
+ }
+
+
+ return 0;
+}
+
+
+void doorders(void)
+{
+ short i;
+
+ setview(0,0,xdim-1,ydim-1);
+
+ for(i=0;i<63;i+=7) palto(0,0,0,i);
+ ps[myconnectindex].palette = palette;
+ totalclock = 0;
+ KB_FlushKeyboardQueue();
+ rotatesprite(0,0,65536L,0,ORDERING,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
+ totalclock = 0;while( !KB_KeyWaiting() ) getpackets();
+
+ for(i=0;i<63;i+=7) palto(0,0,0,i);
+ totalclock = 0;
+ KB_FlushKeyboardQueue();
+ rotatesprite(0,0,65536L,0,ORDERING+1,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
+ totalclock = 0;while( !KB_KeyWaiting() ) getpackets();
+
+ for(i=0;i<63;i+=7) palto(0,0,0,i);
+ totalclock = 0;
+ KB_FlushKeyboardQueue();
+ rotatesprite(0,0,65536L,0,ORDERING+2,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
+ totalclock = 0;while( !KB_KeyWaiting() ) getpackets();
+
+ for(i=0;i<63;i+=7) palto(0,0,0,i);
+ totalclock = 0;
+ KB_FlushKeyboardQueue();
+ rotatesprite(0,0,65536L,0,ORDERING+3,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage(); for(i=63;i>0;i-=7) palto(0,0,0,i);
+ totalclock = 0;while( !KB_KeyWaiting() ) getpackets();
+}
+
+void dobonus(uint8_t bonusonly)
+{
+ short t, gfx_offset;
+// short tinc;
+ int32_t i, y,xfragtotal,yfragtotal;
+ short bonuscnt;
+ char text[512];
+
+ int32_t breathe[] =
+ {
+ 0, 30,VICTORY1+1,176,59,
+ 30, 60,VICTORY1+2,176,59,
+ 60, 90,VICTORY1+1,176,59,
+ 90, 120,0 ,176,59
+ };
+
+ int32_t bossmove[] =
+ {
+ 0, 120,VICTORY1+3,86,59,
+ 220, 260,VICTORY1+4,86,59,
+ 260, 290,VICTORY1+5,86,59,
+ 290, 320,VICTORY1+6,86,59,
+ 320, 350,VICTORY1+7,86,59,
+ 350, 380,VICTORY1+8,86,59
+ };
+
+ bonuscnt = 0;
+
+ for(t=0;t<64;t+=7) palto(0,0,0,t);
+ setview(0,0,xdim-1,ydim-1);
+ clearview(0L);
+ nextpage();
+ flushperms();
+
+ FX_StopAllSounds();
+ clearsoundlocks();
+ FX_SetReverb(0L);
+
+ if(bonusonly) goto FRAGBONUS;
+
+ if(numplayers < 2 && ud.eog && ud.from_bonus == 0)
+ switch(ud.volume_number)
+ {
+ case 0:
+ if(ud.lockout == 0)
+ {
+ clearview(0L);
+ rotatesprite(0,50<<16,65536L,0,VICTORY1,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ nextpage();
+ ps[myconnectindex].palette = endingpal;
+ for(t=63;t>=0;t--) palto(0,0,0,t);
+
+ KB_FlushKeyboardQueue();
+ totalclock = 0; //tinc = 0;
+ while( 1 )
+ {
+ clearview(0L);
+ rotatesprite(0,50<<16,65536L,0,VICTORY1,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+
+ // boss
+ if( totalclock > 390 && totalclock < 780 )
+ for(t=0;t<35;t+=5) if( bossmove[t+2] && (totalclock%390) > bossmove[t] && (totalclock%390) <= bossmove[t+1] )
+ {
+ if(t==10 && bonuscnt == 1) { sound(SHOTGUN_FIRE);sound(SQUISHED); bonuscnt++; }
+ rotatesprite(bossmove[t+3]<<16,bossmove[t+4]<<16,65536L,0,bossmove[t+2],0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ }
+
+ // Breathe
+ if( totalclock < 450 || totalclock >= 750 )
+ {
+ if(totalclock >= 750)
+ {
+ rotatesprite(86<<16,59<<16,65536L,0,VICTORY1+8,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ if(totalclock >= 750 && bonuscnt == 2) { sound(DUKETALKTOBOSS); bonuscnt++; }
+ }
+ for(t=0;t<20;t+=5)
+ if( breathe[t+2] && (totalclock%120) > breathe[t] && (totalclock%120) <= breathe[t+1] )
+ {
+ if(t==5 && bonuscnt == 0)
+ {
+ sound(BOSSTALKTODUKE);
+ bonuscnt++;
+ }
+ rotatesprite(breathe[t+3]<<16,breathe[t+4]<<16,65536L,0,breathe[t+2],0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ }
+ }
+
+ getpackets();
+ nextpage();
+ if( KB_KeyWaiting() ) break;
+ }
+ }
+
+ for(t=0;t<64;t++) palto(0,0,0,t);
+
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].palette = palette;
+
+ rotatesprite(0,0,65536L,0,3292,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage(); for(t=63;t>0;t--) palto(0,0,0,t);
+ while( !KB_KeyWaiting() ) getpackets();
+ for(t=0;t<64;t++) palto(0,0,0,t);
+ MUSIC_StopSong();
+ FX_StopAllSounds();
+ clearsoundlocks();
+ break;
+ case 1:
+ MUSIC_StopSong();
+ clearview(0L);
+ nextpage();
+
+ if(ud.lockout == 0)
+ {
+ playanm("cineov2.anm",1);
+ KB_FlushKeyboardQueue();
+ clearview(0L);
+ nextpage();
+ }
+
+ sound(PIPEBOMB_EXPLODE);
+
+ for(t=0;t<64;t++) palto(0,0,0,t);
+ setview(0,0,xdim-1,ydim-1);
+ KB_FlushKeyboardQueue();
+ ps[myconnectindex].palette = palette;
+ rotatesprite(0,0,65536L,0,3293,0,0,2+8+16+64, 0,0,xdim-1,ydim-1);
+ nextpage(); for(t=63;t>0;t--) palto(0,0,0,t);
+ while( !KB_KeyWaiting() ) getpackets();
+ for(t=0;t<64;t++) palto(0,0,0,t);
+
+ break;
+
+ case 3:
+
+ setview(0,0,xdim-1,ydim-1);
+
+ MUSIC_StopSong();
+ clearview(0L);
+ nextpage();
+
+ if(ud.lockout == 0)
+ {
+ KB_FlushKeyboardQueue();
+ playanm("vol4e1.anm",8);
+ clearview(0L);
+ nextpage();
+ playanm("vol4e2.anm",10);
+ clearview(0L);
+ nextpage();
+ playanm("vol4e3.anm",11);
+ clearview(0L);
+ nextpage();
+ }
+
+ FX_StopAllSounds();
+ clearsoundlocks();
+ sound(ENDSEQVOL3SND4);
+ KB_FlushKeyboardQueue();
+
+ ps[myconnectindex].palette = palette;
+ palto(0,0,0,63);
+ clearview(0L);
+ menutext(160,60,0,0,"THANKS TO ALL OUR");
+ menutext(160,60+16,0,0,"FANS FOR GIVING");
+ menutext(160,60+16+16,0,0,"US BIG HEADS.");
+ menutext(160,70+16+16+16,0,0,"LOOK FOR A DUKE NUKEM 3D");
+ menutext(160,70+16+16+16+16,0,0,"SEQUEL SOON.");
+ nextpage();
+
+ for(t=63;t>0;t-=3) palto(0,0,0,t);
+ KB_FlushKeyboardQueue();
+ while(!KB_KeyWaiting()) getpackets();
+ for(t=0;t<64;t+=3) palto(0,0,0,t);
+
+ clearview(0L);
+ nextpage();
+
+ playanm("DUKETEAM.ANM",4);
+
+ KB_FlushKeyboardQueue();
+ while(!KB_KeyWaiting()) getpackets();
+
+ clearview(0L);
+ nextpage();
+ palto(0,0,0,63);
+
+ FX_StopAllSounds();
+ clearsoundlocks();
+ KB_FlushKeyboardQueue();
+
+ break;
+
+ case 2:
+
+ MUSIC_StopSong();
+ clearview(0L);
+ nextpage();
+ if(ud.lockout == 0)
+ {
+ for(t=63;t>=0;t--) palto(0,0,0,t);
+ playanm("cineov3.anm",2);
+ KB_FlushKeyboardQueue();
+ ototalclock = totalclock+200;
+ while(totalclock < ototalclock) getpackets();
+ clearview(0L);
+ nextpage();
+
+ FX_StopAllSounds();
+ clearsoundlocks();
+ }
+
+ playanm("RADLOGO.ANM",3);
+
+ if( ud.lockout == 0 && !KB_KeyWaiting() )
+ {
+ sound(ENDSEQVOL3SND5);
+ while(Sound[ENDSEQVOL3SND5].lock>=200) getpackets();
+ if(KB_KeyWaiting()) goto ENDANM;
+ sound(ENDSEQVOL3SND6);
+ while(Sound[ENDSEQVOL3SND6].lock>=200) getpackets();
+ if(KB_KeyWaiting()) goto ENDANM;
+ sound(ENDSEQVOL3SND7);
+ while(Sound[ENDSEQVOL3SND7].lock>=200) getpackets();
+ if(KB_KeyWaiting()) goto ENDANM;
+ sound(ENDSEQVOL3SND8);
+ while(Sound[ENDSEQVOL3SND8].lock>=200) getpackets();
+ if(KB_KeyWaiting()) goto ENDANM;
+ sound(ENDSEQVOL3SND9);
+ while(Sound[ENDSEQVOL3SND9].lock>=200) getpackets();
+ }
+
+ KB_FlushKeyboardQueue();
+ totalclock = 0;
+ while(!KB_KeyWaiting() && totalclock < 120) getpackets();
+
+ ENDANM:
+
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+ KB_FlushKeyboardQueue();
+
+ clearview(0L);
+
+ break;
+ }
+
+ FRAGBONUS:
+
+ ps[myconnectindex].palette = palette;
+ KB_FlushKeyboardQueue();
+ totalclock = 0; //tinc = 0;
+ bonuscnt = 0;
+
+ MUSIC_StopSong();
+ FX_StopAllSounds();
+ clearsoundlocks();
+
+ if(playerswhenstarted > 1 && ud.coop != 1 )
+ {
+ if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
+ sound(BONUSMUSIC);
+
+ rotatesprite(0,0,65536L,0,MENUSCREEN,16,0,2+8+16+64,0,0,xdim-1,ydim-1);
+ rotatesprite(160<<16,34<<16,65536L,0,INGAMEDUKETHREEDEE,0,0,10,0,0,xdim-1,ydim-1);
+ rotatesprite((260)<<16,36<<16,65536L,0,PLUTOPAKSPRITE+2,0,0,2+8,0,0,xdim-1,ydim-1);
+ gametext(160,58+2,"MULTIPLAYER TOTALS",0,2+8+16);
+ gametext(160,58+10,level_names[(ud.volume_number*11)+ud.last_level-1],0,2+8+16);
+
+ gametext(160,165,"PRESS ANY KEY TO CONTINUE",0,2+8+16);
+
+
+ t = 0;
+ minitext(23,80," NAME KILLS",8,2+8+16+128);
+ for(i=0;i<playerswhenstarted;i++)
+ {
+ sprintf(text,"%-4d",i+1);
+ minitext(92+(i*23),80,text,3,2+8+16+128);
+ }
+
+ for(i=0;i<playerswhenstarted;i++)
+ {
+ xfragtotal = 0;
+ sprintf(text,"%d",i+1);
+
+ minitext(30,90+t,text,0,2+8+16+128);
+ minitext(38,90+t,ud.user_name[i],ps[i].palookup,2+8+16+128);
+
+ for(y=0;y<playerswhenstarted;y++)
+ {
+ if(i == y)
+ {
+ sprintf(text,"%-4d",ps[y].fraggedself);
+ minitext(92+(y*23),90+t,text,2,2+8+16+128);
+ xfragtotal -= ps[y].fraggedself;
+ }
+ else
+ {
+ sprintf(text,"%-4d",frags[i][y]);
+ minitext(92+(y*23),90+t,text,0,2+8+16+128);
+ xfragtotal += frags[i][y];
+ }
+
+ if(myconnectindex == connecthead)
+ {
+ sprintf(text,"stats %d killed %d %d\n",i+1,y+1,frags[i][y]);
+ sendscore(text);
+ }
+ }
+
+ sprintf(text,"%-4d",xfragtotal);
+ minitext(101+(8*23),90+t,text,2,2+8+16+128);
+
+ t += 7;
+ }
+
+ for(y=0;y<playerswhenstarted;y++)
+ {
+ yfragtotal = 0;
+ for(i=0;i<playerswhenstarted;i++)
+ {
+ if(i == y)
+ yfragtotal += ps[i].fraggedself;
+ yfragtotal += frags[i][y];
+ }
+ sprintf(text,"%-4d",yfragtotal);
+ minitext(92+(y*23),96+(8*7),text,2,2+8+16+128);
+ }
+
+ minitext(45,96+(8*7),"DEATHS",8,2+8+16+128);
+ nextpage();
+
+ for(t=0;t<64;t+=7)
+ palto(0,0,0,63-t);
+
+ KB_FlushKeyboardQueue();
+ while(KB_KeyWaiting()==0) getpackets();
+
+ if( KB_KeyPressed( sc_F12 ) )
+ {
+ KB_ClearKeyDown( sc_F12 );
+ takescreenshot();
+ }
+
+ if(bonusonly || ud.multimode > 1) return;
+
+ for(t=0;t<64;t+=7) palto(0,0,0,t);
+ }
+
+ if(bonusonly || ud.multimode > 1) return;
+
+ switch(ud.volume_number)
+ {
+ case 1:
+ gfx_offset = 5;
+ break;
+ default:
+ gfx_offset = 0;
+ break;
+ }
+
+ rotatesprite(0,0,65536L,0,BONUSSCREEN+gfx_offset,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+
+ menutext(160,20-6,0,0,&level_names[(ud.volume_number*11)+ud.last_level-1][0]);
+ menutext(160,36-6,0,0,"COMPLETED");
+
+ gametext(160,192,"PRESS ANY KEY TO CONTINUE",16,2+8+16);
+
+ if(!(MusicToggle == 0 || MusicDevice == NumSoundCards))
+ sound(BONUSMUSIC);
+
+ nextpage();
+ KB_FlushKeyboardQueue();
+ for(t=0;t<64;t++) palto(0,0,0,63-t);
+ bonuscnt = 0;
+ totalclock = 0; //tinc = 0;
+
+ while( 1 )
+ {
+ sampletimer();
+ if(ps[myconnectindex].gm&MODE_EOL)
+ {
+ rotatesprite(0,0,65536L,0,BONUSSCREEN+gfx_offset,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+
+ if( totalclock > (1000000000L) && totalclock < (1000000320L) )
+ {
+ switch( (totalclock>>4)%15 )
+ {
+ case 0:
+ if(bonuscnt == 6)
+ {
+ bonuscnt++;
+ sound(SHOTGUN_COCK);
+ switch(rand()&3)
+ {
+ case 0:
+ sound(BONUS_SPEECH1);
+ break;
+ case 1:
+ sound(BONUS_SPEECH2);
+ break;
+ case 2:
+ sound(BONUS_SPEECH3);
+ break;
+ case 3:
+ sound(BONUS_SPEECH4);
+ break;
+ }
+ }
+ case 1:
+ case 4:
+ case 5:
+ rotatesprite(199<<16,31<<16,65536L,0,BONUSSCREEN+3+gfx_offset,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ break;
+ case 2:
+ case 3:
+ rotatesprite(199<<16,31<<16,65536L,0,BONUSSCREEN+4+gfx_offset,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ break;
+ }
+ }
+ else if( totalclock > (10240+120L) ) break;
+ else
+ {
+ switch( (totalclock>>5)&3 )
+ {
+ case 1:
+ case 3:
+ rotatesprite(199<<16,31<<16,65536L,0,BONUSSCREEN+1+gfx_offset,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ break;
+ case 2:
+ rotatesprite(199<<16,31<<16,65536L,0,BONUSSCREEN+2+gfx_offset,0,0,2+8+16+64+128,0,0,xdim-1,ydim-1);
+ break;
+ }
+ }
+
+ menutext(160,20-6,0,0,&level_names[(ud.volume_number*11)+ud.last_level-1][0]);
+ menutext(160,36-6,0,0,"COMPLETED");
+
+ gametext(160,192,"PRESS ANY KEY TO CONTINUE",16,2+8+16);
+
+ if( totalclock > (60*3) )
+ {
+ gametext(10,59+9,"Your Time:",0,2+8+16);
+ gametext(10,69+9,"Par time:",0,2+8+16);
+ gametext(10,78+9,"3D Realms' Time:",0,2+8+16);
+ if(bonuscnt == 0)
+ bonuscnt++;
+
+ if( totalclock > (60*4) )
+ {
+ if(bonuscnt == 1)
+ {
+ bonuscnt++;
+ sound(PIPEBOMB_EXPLODE);
+ }
+ sprintf(text,"%02d:%02d",
+ (ps[myconnectindex].player_par/(26*60))%60,
+ (ps[myconnectindex].player_par/26)%60);
+ gametext((320>>2)+71,60+9,text,0,2+8+16);
+
+ sprintf(text,"%02d:%02d",
+ (partime[ud.volume_number*11+ud.last_level-1]/(26*60))%60,
+ (partime[ud.volume_number*11+ud.last_level-1]/26)%60);
+ gametext((320>>2)+71,69+9,text,0,2+8+16);
+
+ sprintf(text,"%02d:%02d",
+ (designertime[ud.volume_number*11+ud.last_level-1]/(26*60))%60,
+ (designertime[ud.volume_number*11+ud.last_level-1]/26)%60);
+ gametext((320>>2)+71,78+9,text,0,2+8+16);
+
+ }
+ }
+ if( totalclock > (60*6) )
+ {
+ gametext(10,94+9,"Enemies Killed:",0,2+8+16);
+ gametext(10,99+4+9,"Enemies Left:",0,2+8+16);
+
+ if(bonuscnt == 2)
+ {
+ bonuscnt++;
+ sound(FLY_BY);
+ }
+
+ if( totalclock > (60*7) )
+ {
+ if(bonuscnt == 3)
+ {
+ bonuscnt++;
+ sound(PIPEBOMB_EXPLODE);
+ }
+ sprintf(text,"%-3hhd",ps[myconnectindex].actors_killed);
+ gametext((320>>2)+70,93+9,text,0,2+8+16);
+ if(ud.player_skill > 3 )
+ {
+ sprintf(text,"N/A");
+ gametext((320>>2)+70,99+4+9,text,0,2+8+16);
+ }
+ else
+ {
+ if( (ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed) < 0 )
+ sprintf(text,"%-3d",0);
+ else sprintf(text,"%-3d",ps[myconnectindex].max_actors_killed-ps[myconnectindex].actors_killed);
+ gametext((320>>2)+70,99+4+9,text,0,2+8+16);
+ }
+ }
+ }
+ if( totalclock > (60*9) )
+ {
+ gametext(10,120+9,"Secrets Found:",0,2+8+16);
+ gametext(10,130+9,"Secrets Missed:",0,2+8+16);
+ if(bonuscnt == 4) bonuscnt++;
+
+ if( totalclock > (60*10) )
+ {
+ if(bonuscnt == 5)
+ {
+ bonuscnt++;
+ sound(PIPEBOMB_EXPLODE);
+ }
+ sprintf(text,"%-3d",ps[myconnectindex].secret_rooms);
+ gametext((320>>2)+70,120+9,text,0,2+8+16);
+ if( ps[myconnectindex].secret_rooms > 0 )
+ sprintf(text,"%-3d",(100*ps[myconnectindex].secret_rooms/ps[myconnectindex].max_secret_rooms));
+ sprintf(text,"%-3d",ps[myconnectindex].max_secret_rooms-ps[myconnectindex].secret_rooms);
+ gametext((320>>2)+70,130+9,text,0,2+8+16);
+ }
+ }
+
+ if(totalclock > 10240 && totalclock < 10240+10240)
+ totalclock = 1024;
+
+ if( KB_KeyWaiting() && totalclock > (60*2) )
+ {
+ if( KB_KeyPressed( sc_F12 ) )
+ {
+ KB_ClearKeyDown( sc_F12 );
+ takescreenshot();
+ }
+
+ if( totalclock < (60*13) )
+ {
+ KB_FlushKeyboardQueue();
+ totalclock = (60*13);
+ }
+ else if( totalclock < (1000000000L))
+ totalclock = (1000000000L);
+ }
+ }
+ else break;
+ nextpage();
+ }
+}
+
+
+void cameratext(short i)
+{
+ uint8_t flipbits;
+ int32_t x , y;
+
+ if(!T1)
+ {
+ rotatesprite(24<<16,33<<16,65536L,0,CAMCORNER,0,0,2,windowx1,windowy1,windowx2,windowy2);
+ rotatesprite((320-26)<<16,34<<16,65536L,0,CAMCORNER+1,0,0,2,windowx1,windowy1,windowx2,windowy2);
+ rotatesprite(22<<16,163<<16,65536L,512,CAMCORNER+1,0,0,2+4,windowx1,windowy1,windowx2,windowy2);
+ rotatesprite((310-10)<<16,163<<16,65536L,512,CAMCORNER+1,0,0,2,windowx1,windowy1,windowx2,windowy2);
+ if(totalclock&16)
+ rotatesprite(46<<16,32<<16,65536L,0,CAMLIGHT,0,0,2,windowx1,windowy1,windowx2,windowy2);
+ }
+ else
+ {
+ flipbits = (totalclock<<1)&48;
+ for(x=0;x<394;x+=64)
+ for(y=0;y<200;y+=64)
+ rotatesprite(x<<16,y<<16,65536L,0,STATIC,0,0,2+flipbits,windowx1,windowy1,windowx2,windowy2);
+ }
+}
+
+void vglass(int32_t x,int32_t y,short a,short wn,short n)
+{
+ int32_t z, zincs;
+ short sect;
+
+ sect = wall[wn].nextsector;
+ if(sect == -1) return;
+ zincs = ( sector[sect].floorz-sector[sect].ceilingz ) / n;
+
+ for(z = sector[sect].ceilingz;z < sector[sect].floorz; z += zincs )
+ EGS(sect,x,y,z-(TRAND&8191),GLASSPIECES+(z&(TRAND%3)),-32,36,36,a+128-(TRAND&255),16+(TRAND&31),0,-1,5);
+}
+
+void lotsofglass(short i,short wallnum,short n)
+{
+ int32_t j, xv, yv, z, x1, y1;
+ short sect, a;
+
+ sect = -1;
+
+ if(wallnum < 0)
+ {
+ for(j=n-1; j >= 0 ;j--)
+ {
+ a = SA-256+(TRAND&511)+1024;
+ EGS(SECT,SX,SY,SZ,GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),1024-(TRAND&1023),i,5);
+ }
+ return;
+ }
+
+ j = n+1;
+
+ x1 = wall[wallnum].x;
+ y1 = wall[wallnum].y;
+
+ xv = wall[wall[wallnum].point2].x-x1;
+ yv = wall[wall[wallnum].point2].y-y1;
+
+ x1 -= ksgn(yv);
+ y1 += ksgn(xv);
+
+ xv /= j;
+ yv /= j;
+
+ for(j=n;j>0;j--)
+ {
+ x1 += xv;
+ y1 += yv;
+
+ updatesector(x1,y1,&sect);
+ if(sect >= 0)
+ {
+ z = sector[sect].floorz-(TRAND&(klabs(sector[sect].ceilingz-sector[sect].floorz)));
+ if( z < -(32<<8) || z > (32<<8) )
+ z = SZ-(32<<8)+(TRAND&((64<<8)-1));
+ a = SA-1024;
+ EGS(SECT,x1,y1,z,GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),-(TRAND&1023),i,5);
+ }
+ }
+}
+
+void spriteglass(short i,short n)
+{
+ int32_t j, k, a, z;
+
+ for(j=n;j>0;j--)
+ {
+ a = TRAND&2047;
+ z = SZ-((TRAND&16)<<8);
+ k = EGS(SECT,SX,SY,z,GLASSPIECES+(j%3),TRAND&15,36,36,a,32+(TRAND&63),-512-(TRAND&2047),i,5);
+ sprite[k].pal = sprite[i].pal;
+ }
+}
+
+void ceilingglass(short i,short sectnum,short n)
+{
+ int32_t j, xv, yv, z, x1, y1;
+ short a,s, startwall,endwall;
+
+ startwall = sector[sectnum].wallptr;
+ endwall = startwall+sector[sectnum].wallnum;
+
+ for(s=startwall;s<(endwall-1);s++)
+ {
+ x1 = wall[s].x;
+ y1 = wall[s].y;
+
+ xv = (wall[s+1].x-x1)/(n+1);
+ yv = (wall[s+1].y-y1)/(n+1);
+
+ for(j=n;j>0;j--)
+ {
+ x1 += xv;
+ y1 += yv;
+ a = TRAND&2047;
+ z = sector[sectnum].ceilingz+((TRAND&15)<<8);
+ EGS(sectnum,x1,y1,z,GLASSPIECES+(j%3),-32,36,36,a,(TRAND&31),0,i,5);
+ }
+ }
+}
+
+
+
+void lotsofcolourglass(short i,short wallnum,short n)
+{
+ int32_t j, xv, yv, z, x1, y1;
+ short sect = -1, a, k;
+
+ if(wallnum < 0)
+ {
+ for(j=n-1; j >= 0 ;j--)
+ {
+ a = TRAND&2047;
+ k = EGS(SECT,SX,SY,SZ-(TRAND&(63<<8)),GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),1024-(TRAND&2047),i,5);
+ sprite[k].pal = TRAND&15;
+ }
+ return;
+ }
+
+ j = n+1;
+ x1 = wall[wallnum].x;
+ y1 = wall[wallnum].y;
+
+ xv = (wall[wall[wallnum].point2].x-wall[wallnum].x)/j;
+ yv = (wall[wall[wallnum].point2].y-wall[wallnum].y)/j;
+
+ for(j=n;j>0;j--)
+ {
+ x1 += xv;
+ y1 += yv;
+
+ updatesector(x1,y1,&sect);
+ z = sector[sect].floorz-(TRAND&(klabs(sector[sect].ceilingz-sector[sect].floorz)));
+ if( z < -(32<<8) || z > (32<<8) )
+ z = SZ-(32<<8)+(TRAND&((64<<8)-1));
+ a = SA-1024;
+ k = EGS(SECT,x1,y1,z,GLASSPIECES+(j%3),-32,36,36,a,32+(TRAND&63),-(TRAND&2047),i,5);
+ sprite[k].pal = TRAND&7;
+ }
+}
+
+void SetupGameButtons( void )
+{
+ CONTROL_DefineFlag(gamefunc_Move_Forward,false);
+ CONTROL_DefineFlag(gamefunc_Move_Backward,false);
+ CONTROL_DefineFlag(gamefunc_Turn_Left,false);
+ CONTROL_DefineFlag(gamefunc_Turn_Right,false);
+ CONTROL_DefineFlag(gamefunc_Strafe,false);
+ CONTROL_DefineFlag(gamefunc_Fire,false);
+ CONTROL_DefineFlag(gamefunc_Open,false);
+ CONTROL_DefineFlag(gamefunc_Run,false);
+ CONTROL_DefineFlag(gamefunc_AutoRun,false);
+ CONTROL_DefineFlag(gamefunc_Jump,false);
+ CONTROL_DefineFlag(gamefunc_Crouch,false);
+ CONTROL_DefineFlag(gamefunc_Look_Up,false);
+ CONTROL_DefineFlag(gamefunc_Look_Down,false);
+ CONTROL_DefineFlag(gamefunc_Look_Left,false);
+ CONTROL_DefineFlag(gamefunc_Look_Right,false);
+ CONTROL_DefineFlag(gamefunc_Strafe_Left,false);
+ CONTROL_DefineFlag(gamefunc_Strafe_Right,false);
+ CONTROL_DefineFlag(gamefunc_Aim_Up,false);
+ CONTROL_DefineFlag(gamefunc_Aim_Down,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_1,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_2,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_3,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_4,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_5,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_6,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_7,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_8,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_9,false);
+ CONTROL_DefineFlag(gamefunc_Weapon_10,false);
+ CONTROL_DefineFlag(gamefunc_Inventory,false);
+ CONTROL_DefineFlag(gamefunc_Inventory_Left,false);
+ CONTROL_DefineFlag(gamefunc_Inventory_Right,false);
+ CONTROL_DefineFlag(gamefunc_Holo_Duke,false);
+ CONTROL_DefineFlag(gamefunc_Jetpack,false);
+ CONTROL_DefineFlag(gamefunc_NightVision,false);
+ CONTROL_DefineFlag(gamefunc_MedKit,false);
+ CONTROL_DefineFlag(gamefunc_TurnAround,false);
+ CONTROL_DefineFlag(gamefunc_SendMessage,false);
+ CONTROL_DefineFlag(gamefunc_Map,false);
+ CONTROL_DefineFlag(gamefunc_Shrink_Screen,false);
+ CONTROL_DefineFlag(gamefunc_Enlarge_Screen,false);
+ CONTROL_DefineFlag(gamefunc_Center_View,false);
+ CONTROL_DefineFlag(gamefunc_Holster_Weapon,false);
+ CONTROL_DefineFlag(gamefunc_Show_Opponents_Weapon,false);
+ CONTROL_DefineFlag(gamefunc_Map_Follow_Mode,false);
+ CONTROL_DefineFlag(gamefunc_See_Coop_View,false);
+ CONTROL_DefineFlag(gamefunc_Mouse_Aiming,false);
+ CONTROL_DefineFlag(gamefunc_Toggle_Crosshair,false);
+ CONTROL_DefineFlag(gamefunc_Steroids,false);
+ CONTROL_DefineFlag(gamefunc_Quick_Kick,false);
+ CONTROL_DefineFlag(gamefunc_Next_Weapon,false);
+ CONTROL_DefineFlag(gamefunc_Previous_Weapon,false);
+ CONTROL_DefineFlag(gamefunc_Console,false);
+}
+
+/*
+===================
+=
+= GetTime
+=
+===================
+*/
+
+int32_t GetTime(void)
+ {
+ return totalclock;
+ }
+
+
+/*
+===================
+=
+= CenterCenter
+=
+===================
+*/
+
+void CenterCenter(void)
+ {
+ printf("Center the joystick and press a button\n");
+ }
+
+/*
+===================
+=
+= UpperLeft
+=
+===================
+*/
+
+void UpperLeft(void)
+ {
+ printf("Move joystick to upper-left corner and press a button\n");
+ }
+
+/*
+===================
+=
+= LowerRight
+=
+===================
+*/
+
+void LowerRight(void)
+ {
+ printf("Move joystick to lower-right corner and press a button\n");
+ }
+
+/*
+===================
+=
+= CenterThrottle
+=
+===================
+*/
+
+void CenterThrottle(void)
+ {
+ printf("Center the throttle control and press a button\n");
+ }
+
+/*
+===================
+=
+= CenterRudder
+=
+===================
+*/
+
+void CenterRudder(void)
+{
+ printf("Center the rudder control and press a button\n");
+}
+
+// FIX_00006: better naming system for screenshots + message when pic is taken.
+// Use ./screenshots folder. Screenshot code rerwritten. Faster and
+// makes smaller files. Doesn't freeze or lag the game anymore.
+void takescreenshot(void)
+{
+ char szFilename[256];
+ int i;
+ char score[20];
+ time_t time4file;
+ char text[512];
+
+ // xduke: Build a nice name w/ date and players name if in multi mode.
+ time(&time4file);
+
+ sprintf(text, "Chocolate DukeNukem3D(v%d.%d) %d",
+ CHOCOLATE_DUKE_REV_X,
+ CHOCOLATE_DUKE_REV_DOT_Y,
+ time(NULL));
+
+ if(ud.multimode>1) // if more than 1 player, we add name. Then add score if DM
+ {
+ text[0] = '\0';
+ strcat((char *)text, " [");
+ for(i=connecthead;i>=0;i=connectpoint2[i])
+ {
+ if(!ud.user_name[i][0])
+ strcat(text, "NoName");
+ else
+ strcat(text, &ud.user_name[i][0]);
+
+ if(ud.m_coop==0 || ud.m_coop==2) // if DM or DM No spawn. Add Score as well
+ {
+ strcat(text, "(");
+ snprintf(score, sizeof(score), "%d",ps[i].frag-ps[i].fraggedself);
+ strcat(text, score);
+ strcat(text, ") vs ");
+ }
+ else
+ strcat(text, " vs ");
+ }
+ tempbuf[strlen(text)-4]=0; // remove last vs
+ strcat(text, "]");
+ }
+ strcat(text, ".bmp");
+
+
+ // If this is a TC save it to the TC's directory
+ if(getGameDir()[0] != '\0')
+ {
+ sprintf(szFilename, "%s\\%s", getGameDir(), SCREENSHOTPATH);
+ mkdir(szFilename);
+ sprintf(szFilename, "%s\\%s\\%s", getGameDir(), SCREENSHOTPATH, tempbuf);
+ }
+ // otherwise let's save it to the root.
+ else
+ {
+ mkdir(SCREENSHOTPATH);
+ sprintf(szFilename, "%s\\%s", SCREENSHOTPATH, tempbuf);
+ }
+
+ if(SafeFileExists(szFilename) == 0)
+ {
+ screencapture(szFilename,0);
+ sprintf(fta_quotes[103],"SCREEN SAVED");
+ sound(EXITMENUSOUND);
+ }
+ else
+ sprintf(fta_quotes[103],"CAN'T WRITE FILE!");
+
+ FTA(103,&ps[screenpeek],1);
+
+}
+
+
+// Rare Multiplayer, when dead, total screen screwup back again!
+// E3l1 (Coop /w monsters) sprite list corrupt 50%
+// Univbe exit, instead, default to screen buffer.
+// Check all caches bounds and memory usages
+// Fix enlarger weapon selections to perfection
+// Need sounds.c
+// Spawning a couple of sounds at the same time
+// Check Weapon Switching
+// FIRE and FIRE2
+// Where should I flash the screen white???
+// Jittery on subs in mp?
+// Check accurate memory amounts!
+// Why squish sound at hit space when dead?
+// Falling Counter Not reset in mp
+// Wierd small freezer
+// Double freeze on player?, still firing
+// Do Mouse Flip option
+// Save mouse aiming
+// Laser bounce off mirrors
+// GEORGE: Ten in text screen.
+// Alien:
+// Freeze: change
+// Press space holding player
+// Press space
+// tank broke
+// 2d mode fucked in fake mp mode
+// 207
+// Mail not rolling up on conveyers
+// Fix all alien animations
+// Do episode names in .CONS
+// do syntak check for "{?????"
+// Make commline parms set approiate multiplayer flags
+
+// Check all breakables to see if they are exploding properly
+// Fix freezing palette on Alien
+
+// Do a demo make run overnite
+// Fix Super Duck
+// Slime Guies, use quickkick.
+
+// Make Lasers from trip bombs reflect off mirrors
+// Remember for lockout of sound swears
+// Pass sender in packed, NOT
+// Fatal sync give no message for TEN
+// Hitting TEN BUTTON(OPTION) no TEN SCreen
+// Check multioperateswitches for se 31,32
+// Fix pal for ceilings (SE#18)
+// case 31: sprites up one high
+// E1l1 No Kill All troops in room, sleep time
+
+// Fifo for message list
+
+// Bloodsplat on conveyers
+
+// Meclanical
+// Increase sound
+// Mouse Delay at death
+// Wierd slowdown
+
+// Footprints on stuff floating
+
+// Ken, The inside function is called a lot in -1 sectors
+// No loading Univbe message rewrite
+// Expander must cycle with rest of weapons
+// Duck SHOOT PIPEBOMB, red wall
+
+// Get commit source from mark
+
+/*
+ 1. fix pipebomb bug
+ 2. check george maps
+ 4. Save/Restore check (MP and SP)
+ 5. Check TEN
+ 6. Get Commit fixed
+ 8. Is mail slow?
+ 9. Cacheing
+ 10. Blue out "PLAY ON TEN" in MULTIPLAYER
+ 11. Eight Player test
+ 12. Postal.voc not found.
+ 13. All Monsters explode in arcade,
+ check SEENINE STRENGTH,
+ Change 28<<8 back to 16<<8 in hitradius
+ Compare 1.3d to 1.4
+ 14. Check sounds/gfx for for parr lock
+ 15. Player # Loaded a game
+ 16. Replace Crane code 1.3d to 1.4
+ 17. Fix Greenslime
+ 18. Small Freeze sprite,below floor
+ 19. Vesa message auto abort in mp?
+ 20. Fucked Palette in my skip ahead in MP
+ 21. Load in main menu
+ 22. Rotated frag screen no game screen
+ 23. Jibs sounds when killed other dukes
+ 24. Ten code and /f4 mode
+ 25. Fix All MP Glitches!!
+ 26. Unrem Menues anim tenbn
+ 27. buy groc,clothes,scanner
+ 28. Why Double Defs in global and game, is so at work
+ 29. Check that all .objs are erased
+ 30. Check why 1.3ds gotweapon gamedef coop code no workie
+ 31. Heavy mods to net code
+ 32. Make sure all commline stuff works,
+ 33. killed all waitfor???
+ 34. 90k stack
+ 35. double door probs
+ 36: copy protection
+ * when you start a game the duke saying that is played when you choose a skill the sound is cut off.
+ * NEWBEASTJUMPING is not deleted at premap in multi-play
+ if(*c == '4') no work need objs ask ken, commit
+ {
+ movesperpacket = 4;
+ setpackettimeout(0x3fffffff,0x3fffffff);
+ }
+ remember, netcode load
+*/
+// Ai Problem in god mode.
+// Checkplayerhurtwall for forcefields bigforce
+// Nuddie, posters. IMF
+// Release commit.c to public?
+// Document Save bug with mp
+// Check moves per packet /f4 waitforeverybody over net?
+// Kill IDF OBJ
+// No shotguns under water @ tanker
+// Unrem copyprotect
+// Look for printf and puts
+// Check con rewrites
+// erase mmulti.c, or get newest objs
+// Why nomonsters screwy in load menu in mp
+// load last > 'y' == NOT
+// Check xptr oos when dead rising to surface.
+// diaginal warping with shotguns
+// Test white room. Lasertripbomb arming crash
+// The Bog
+// Run Duke Out of windows
+// Put Version number in con files
+// Test diff. version playing together
+// Reorganize dukecd
+// Put out patch w/ two weeks testing
+// Print draw3d
+// Double Klick
+
+/*
+ Duke Nukem V
+
+ Layout:
+
+ Settings:
+ Suburbs
+ Duke inflitrating neighborhoods inf. by aliens
+ Death Valley:
+ Sorta like a western. Bull-skulls half buried in the sand
+ Military compound: Aliens take over nuke-missle silo, duke
+ must destroy.
+ Abondend Aircraft field
+ Vegas:
+ Blast anything bright! Alien lights camoflauged.
+ Alien Drug factory. The Blue Liquid
+ Mountainal Cave:
+ Interior cave battles.
+ Jungle:
+ Trees, canopee, animals, a mysterious hole in the earth with
+ gas seaping thru.
+ Penetencury:
+ Good use of spotlights:
+ Mental ward:
+ People whom have claimed to be slowly changing into an
+ alien species
+
+ Inventory:
+ Wood,
+ Metal,
+ Torch,
+ Rope,
+ Plastique,
+ Cloth,
+ Wiring,
+ Glue,
+ Cigars,
+ Food,
+ Duck Tape,
+ Nails,
+ Piping,
+ Petrol,
+ Uranium,
+ Gold,
+ Prism,
+ Power Cell,
+
+ Hand spikes (Limited usage, they become dull)
+ Oxygent (Oxygen mixed with stimulant)
+
+
+ Player Skills:
+ R-Left,R-Right,Foward,Back
+ Strafe, Jump, Double Flip Jump for distance
+ Help, Escape
+ Fire/Use
+ Use Menu
+
+ After a brief resbit, Duke decides to get back to work.
+
+ Cmdr: "Duke, we've got a lot of scared people down there.
+ Some reports even claim that people are already
+ slowly changing into aliens."
+ Duke: "No problem, my speciality is in croud control."
+ Cmdr: "Croud control, my ass! Remember that incident
+ during the war? You created nuthin' but death and
+ destruction."
+ Duke: "Not destruction, justice."
+ Cmdr: "I'll take no responsibility for your actions. Your on
+ your own! Behave your self, damnit! You got that,
+ soldger?"
+ Duke: "I've always been on my own... Face it, it's ass kickin' time,
+ SIR!"
+ Cmdr: "Get outta here...!"
+ (Duke gives the Cmdr a hard stair, then cocks his weapon and
+ walks out of the room)
+ Cmdr: In a wisper: "Good luck, my friend."
+
+ (Cut to a scene where aliens are injecting genetic material
+ into an unconcious subject)
+
+ Programming: ( the functions I need )
+ Images: Polys
+ Actors:
+ Multi-Object sections for change (head,arms,legs,torsoe,all change)
+ Facial expressions. Pal lookup per poly?
+
+ struct imagetype
+ {
+ int *itable; // AngX,AngY,AngZ,Xoff,Yoff,Zoff;
+ int *idata;
+ struct imagetype *prev, *next;
+ }
+
+*/
+
+
+// Test frag screen name fuckup
+// Test all xptrs
+// Make Jibs stick to ceiling
+// Save Game menu crash
+// Cache len sum err
+// Loading in main (MP), reset totalclock?
+// White Room
+// Sound hitch with repeat bits
+// Rewrite saved menues so no crash
+// Put a getpackets after loadplayer in menus
+// Put "loading..." before waitfor in loadpla
+// No ready2send = 0 for loading
+// Test Joystick
+// Ten
+// Bog
+// Test Blimp respawn
+// move 1 in player???