Permalink
Find file
10924 lines (9268 sloc) 329 KB
//-------------------------------------------------------------------------
/*
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>
#elif defined(__APPLE__)
#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 <sys/types.h>
#include <sys/stat.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;
}
}
}
//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)
{
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 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;
sprintf(fps," %d", savedFps);
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);
}
}