/***************************************************************************/ /* */ /* */ /* Raven 3D Engine */ /* Copyright (C) 1996 by Softdisk Publishing */ /* */ /* Original Design: */ /* John Carmack of id Software */ /* */ /* Enhancements by: */ /* Robert Morgan of Channel 7............................Main Engine Code */ /* Todd Lewis of Softdisk Publishing......Tools,Utilities,Special Effects */ /* John Bianca of Softdisk Publishing..............Low-level Optimization */ /* Carlos Hasan..........................................Music/Sound Code */ /* */ /* */ /***************************************************************************/ #include #include #include #include #include #include "d_global.h" #include "d_ints.h" #include "d_misc.h" #include "r_public.h" #include "protos.h" #include "d_disk.h" #include "r_refdef.h" #include "audio.h" /**** CONSTANTS ****/ #define CMD_SEND 1 #define CMD_GET 2 #define GREEDCOM_ID 0xC7C7C7C7L #define NETIPX 1 #define NETSERIAL 2 #define NETMODEM 3 #define INITEVENTID 1 #define PLAYEREVENTID 2 #define SPAWNEVENTID 3 #define QUITEVENTID 4 #define DOOREVENTID 5 #define FRAGEVENTID 6 #define NEWPLAYEREVENTID 7 #define ITEMEVENTID 8 #define BONUSEVENTID 9 #define PAUSEEVENTID 10 #define UNPAUSEEVENTID 11 #define TRIGGEREVENTID 12 #define SOUNDEVENTID 13 #define JAMMEREVENTID 14 #define EVENTEVENTID 15 #define MESSAGEEVENTID 16 #define REG_TX uart #define REG_RX uart #define REG_INT_EN (uart+0x01) #define IER_RX_DATA_READY 0x01 #define IER_TX_HOLDING_REGISTER_EMPTY 0x02 #define IER_LINE_STATUS 0x04 #define IER_MODEM_STATUS 0x08 #define REG_INT_ID (uart+0x02) #define IIR_NOPEND 0x01 #define IIR_MSTAT 0x00 #define IIR_TX 0x02 #define IIR_RX 0x04 #define IIR_LSTAT 0x06 #define REG_FCONT (uart+0x02) #define FCR_FIFO_ENABLE 0x01 #define FCR_RCVR_FIFO_RESET 0x02 #define FCR_XMIT_FIFO_RESET 0x04 #define FCR_RCVR_TRIGGER_LSB 0x40 #define FCR_RCVR_TRIGGER_MSB 0x80 #define FCR_TRIGGER_01 0x00 #define FCR_TRIGGER_04 0x40 #define FCR_TRIGGER_08 0x80 #define FCR_TRIGGER_14 0xc0 #define REG_LCONT (uart+0x03) #define LCONT_WORD_LENGTH_MASK 0x03 #define LCONT_WORD_LENGTH_SELECT_0 0x01 #define LCONT_WORD_LENGTH_SELECT_1 0x02 #define LCONT_STOP_BITS 0x04 #define LCONT_PARITY_MASK 0x38 #define LCONT_PARITY_ENABLE 0x08 #define LCONT_EVEN_PARITY_SELECT 0x10 #define LCONT_STICK_PARITY 0x20 #define LCONT_SET_BREAK 0x40 #define LCONT_DLAB 0x80 #define REG_MCONT (uart+0x04) #define MCONT_DTR 0x01 #define MCONT_RTS 0x02 #define MCONT_OUT1 0x04 #define MCONT_OUT2 0x08 #define MCONT_LOOPBACK 0x10 #define REG_LSTAT (uart+0x05) #define LSTAT_DATA_READY 0x01 #define LSTAT_OVERRUN_ERROR 0x02 #define LSTAT_PARITY_ERROR 0x04 #define LSTAT_FRAMING_ERROR 0x08 #define LSTAT_BREAK_DETECT 0x10 #define LSTAT_THRE 0x20 #define REG_MSTAT (uart+0x06) #define MSTAT_DELTA_CTS 0x01 #define MSTAT_DELTA_DSR 0x02 #define MSTAT_TERI 0x04 #define MSTAT_DELTA_CD 0x08 #define MSTAT_CTS 0x10 #define MSTAT_DSR 0x20 #define MSTAT_RI 0x40 #define MSTAT_CD 0x80 #define QUESIZE 4095 #define PEL_WRITE_ADR 0x3c8 #define PEL_DATA 0x3c9 #define I_ColorBlack(r,g,b) outp(PEL_WRITE_ADR,0); \ outp(PEL_DATA,r); \ outp(PEL_DATA,g); \ outp(PEL_DATA,b) #define NETINT() intr(greedcom->intnum,&r) /**** TYPES ****/ typedef struct { int id; int playerid; int found; int start; char netname[13]; int map; int difficulty; } ievent_t; // initialization typedef struct { int id; int playerid; int value; fixed_t x; fixed_t y; fixed_t z; fixed_t zadj; int angle; int angle2; int active; int spawnid; } sevent_t; // spawn typedef struct { int id; int playerid; } qevent_t; // quit game typedef struct { int id; int playerid; fixed_t x, y; int angle; } devent_t; // door open (by player) / trigger flipped typedef struct { int id; int playerid; int bulletid; } fevent_t; // frag typedef struct { int id; int playerid; int time, score; int tilex, tiley; int num; } bevent_t; // bonus item spawn typedef struct { int id; int playerid; int tilex, tiley, mapspot; int type, chartype; } ipevent_t; // item pickup typedef struct { int id; int playerid; fixed_t x, y; int effect, variation; } eevent_t; // sound effect typedef struct { int id; int playerid; char message[30]; } mevent_t; enum {UART_8250, UART_16550} uart_type; typedef struct { long head, tail; // bytes are put on head and pulled from tail byte data[QUESIZE+1]; } que_t; typedef struct { que_t in; que_t out; short uart, uarttype, irqintnum; short intseg, intofs; short rsent, rreceived; short psent, preceived; } ques_t; /**** VARIABLES ****/ pevent_t *pevent; sevent_t *sevent; ievent_t *ievent; qevent_t *qevent; devent_t *devent; fevent_t *fevent; bevent_t *bevent; ipevent_t *ipevent; eevent_t *eevent; mevent_t *mevent; greedcom_t *greedcom; union REGPACK r; char msg[60]; scaleobj_t *playersprites[MAXPLAYERS], *sprite_p, *sprite2_p, *temp_p; pevent_t playerdata[MAXPLAYERS]; char netnames[MAXPLAYERS][13]; int playernum=1, netpaused, netwarpjamtime; boolean netwarpjammer; int playermapspot[MAXPLAYERS], pmapspot, oldsprites[MAXPLAYERS]; ques_t *que; int uart, irqintnum, maxcount; int pseg, pofs, rseg, rofs; int fragcount[MAXPLAYERS]; extern SoundCard SC; /**** FUNCTIONS ****/ void interrupt ISR_8250(void) { int count; STI; while (1) { switch(inbyte(REG_INT_ID) & 7) { case IIR_RX: // receive que->in.data[que->in.head&QUESIZE]=inbyte(REG_RX); que->in.head++; que->preceived++; continue; case IIR_TX: // transmit for (count=0;countout.tailout.head;count++) { outbyte(REG_TX,que->out.data[que->out.tail&QUESIZE]); que->out.tail++; que->psent++; } continue; case IIR_MSTAT: inbyte(REG_MSTAT); continue; case IIR_LSTAT: inbyte(REG_LSTAT); continue; default: // done outbyte(0x20,0x20); return; } } } void netstub2(void) { } void SetupModem(void) { int parm, seraddr; union REGS r; parm=MS_CheckParm("serial"); if (parm && parmuart; uart_type=que->uarttype; irqintnum=que->irqintnum; if (uart_type==UART_16550) maxcount=14; else maxcount=1; lock_region((void near *)ISR_8250,(char *)netstub2 - (char near *)ISR_8250); lock_region(&que,4); lock_region(&uart,4); lock_region(&maxcount,4); lock_region(&uart_type,4); r.x.eax=0x204; // get prot r.h.bl=irqintnum; int386(0x31,&r,&r); if (r.x.cflag) MS_Error("Error getting prot handler"); pseg=r.x.ecx; pofs=r.x.edx; r.x.eax=0x0200; // get real r.h.bl=irqintnum; int386(0x31,&r,&r); if (r.x.cflag) MS_Error("Error getting real handler"); rseg=r.x.ecx; rofs=r.x.edx; r.x.eax=0x205; // set prot r.h.bl=irqintnum; r.x.edx=FP_OFF(ISR_8250); r.x.ecx=FP_SEG(ISR_8250); int386(0x31,&r,&r); if (r.x.cflag) MS_Error("Error setting prot handler"); r.x.eax=0x0201; // set real r.h.bl=irqintnum; r.x.ecx=que->intseg; r.x.edx=que->intofs; int386(0x31,&r,&r); if (r.x.cflag) MS_Error("Error setting real handler"); } /***************************************************************************/ void netstub(void); void SpawnNewPlayer() { sprite_p=RF_GetSprite(); playersprites[pevent->playerid]=sprite_p; sprite_p->rotate=rt_eight; sprite_p->basepic=CA_GetNamedNum(charnames[pevent->chartype]); DemandLoadMonster(sprite_p->basepic,48); sprite_p->scale=1; sprite_p->startpic=sprite_p->basepic; sprite_p->intelligence=255; sprite_p->x=pevent->x; sprite_p->y=pevent->y; sprite_p->z=pevent->z; sprite_p->angle=pevent->angle; sprite_p->type=S_NETPLAYER; sprite_p->hitpoints=500; sprite_p->height=60<y>>FRACTILESHIFT)*MAPCOLS+(sprite_p->x>>FRACTILESHIFT); playermapspot[pevent->playerid]=pmapspot; if (mapsprites[pmapspot]==0) mapsprites[pmapspot]=SM_NETPLAYER; } void NetInit(void *addr) { printf("Multiplayer:\n"); greedcom=(greedcom_t *)addr; if (greedcom->id!=GREEDCOM_ID) MS_Error("Invalid ComData Address! ID=0x%X",greedcom->id); printf("\tPlayers=%i\n",greedcom->numplayers); playernum=greedcom->consoleplayer; printf("\tYou are player #%i\n",playernum+1); printf("\tNetMode="); if (greedcom->nettype==NETIPX) printf("IPX Net"); else if (greedcom->nettype==NETSERIAL) printf("Serial"); else if (greedcom->nettype==NETMODEM) printf("Modem"); else MS_Error("Unknown net type!"); printf("\n"); if (greedcom->nettype==NETMODEM || greedcom->nettype==NETSERIAL) SetupModem(); pevent=(pevent_t *)greedcom->data; sevent=(sevent_t *)greedcom->data; ievent=(ievent_t *)greedcom->data; qevent=(qevent_t *)greedcom->data; devent=(devent_t *)greedcom->data; fevent=(fevent_t *)greedcom->data; bevent=(bevent_t *)greedcom->data; ipevent=(ipevent_t *)greedcom->data; eevent=(eevent_t *)greedcom->data; mevent=(mevent_t *)greedcom->data; lock_region((void near *)NetOpenDoor,(char *)netstub - (char near *)NetOpenDoor); lock_region(&greedcom,sizeof(greedcom)); lock_region(&devent,sizeof(devent)); lock_region(&r,sizeof(r)); memset(&r,0,sizeof(r)); } void PlayerCommand(void); void NetWaitStart(void) { int players[MAXPLAYERS], found, playersfound[MAXPLAYERS], ready, i; longint timeout, waittime; INT_TimerHook(NULL); StartWait(); memset(players,0,sizeof(players)); memset(playersfound,0,sizeof(playersfound)); strncpy(netnames[playernum],SC.netname,12); if (netnames[playernum][10]==' ') { i=10; while (i>0 && netnames[playernum][i]==' ') { netnames[playernum][i]=0; i--; } } players[playernum]=1; // found ourself found=1; ready=0; timeout=timecount+42000; // 10 minute wait newascii=false; waittime=timecount+70; while (1) { UpdateWait(); if (timecount>timeout) MS_Error("Multiplayer synch time-out error"); if (newascii && lastascii==27) MS_Error("Multiplay Cancelled"); newascii=false; if (timecount>waittime) { found=0; for(i=0;inumplayers;i++) if (players[i]) found++; // count how many we've found playersfound[playernum]=found; greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; // broadcast greedcom->datalength=sizeof(ievent_t); ievent->id=INITEVENTID; ievent->playerid=playernum; // tell who we are ievent->found=found; // tell how many we've found ievent->start=ready; // player 0 tells when to start ievent->map=player.map; ievent->difficulty=player.difficulty; strncpy(ievent->netname,netnames[playernum],12); NETINT(); waittime=timecount + 140; } if (ievent->start==greedcom->numplayers) break; greedcom->command=CMD_GET; NETINT(); if (greedcom->remotenode==-1) continue; // no broadcasts if (ievent->id!=INITEVENTID) continue; // wrong packet id! if (greedcom->nettype!=NETIPX && ievent->start==greedcom->numplayers) break; // we can start now if (ievent->playerid==0) player.difficulty=ievent->difficulty; if (ievent->map!=player.map) MS_Error("Player #%i is playing a different map!",ievent->playerid); players[ievent->playerid]=1; // found new player playersfound[ievent->playerid]=ievent->found; // how many they've found strncpy(netnames[ievent->playerid],ievent->netname,12); if (playernum==0) // player 0 checks for readiness { ready=0; for(i=0;inumplayers;i++) if (playersfound[i]==greedcom->numplayers) ready++; // check everybody } } timecount=0; greedcom->maxusage=0; EndWait(); NetNewPlayerData(); INT_TimerHook(PlayerCommand); if (greedcom->nettype!=NETIPX && greedcom->consoleplayer==0) timecount=19; NetGetData(); } void NetGetData(void) { static int i, angle, angleinc; do { /* if (greedcom->nettype==NETIPX && greedcom->maxusage==25) MS_Error("Network Overload\n" "Possible solutions:\n" " 1. increase the speed of this machine\n" " 2. remove other non-game machines from the net\n" " 3. reduce number of players in game\n"); */ greedcom->command=CMD_GET; NETINT(); if (greedcom->remotenode==-1) return; if (pevent->playerid==playernum) continue; switch (pevent->id) { case PLAYEREVENTID: sprite_p=playersprites[pevent->playerid]; if (sprite_p==NULL) continue; sprite_p->x=pevent->x; sprite_p->y=pevent->y; sprite_p->z=pevent->z-pevent->height; sprite_p->angle=pevent->angle; sprite_p->hitpoints=500; pmapspot=playermapspot[pevent->playerid]; if (mapsprites[pmapspot]==SM_NETPLAYER) mapsprites[pmapspot]=0; pmapspot=(sprite_p->y>>FRACTILESHIFT)*MAPCOLS+(sprite_p->x>>FRACTILESHIFT); if (mapsprites[pmapspot]==0) mapsprites[pmapspot]=SM_NETPLAYER; playermapspot[pevent->playerid]=pmapspot; if (pevent->status==1) // hit { sprite_p->basepic=sprite_p->startpic+32; sprite_p->modetime=timecount+12; } else if (pevent->status==2) // firing { sprite_p->basepic=sprite_p->startpic+24; sprite_p->modetime=timecount+12; playerdata[pevent->playerid].x=-1; // so it draws the walk frame } if (timecount>sprite_p->modetime) { if (playerdata[pevent->playerid].x!=pevent->x || playerdata[pevent->playerid].y!=pevent->y) { if (sprite_p->movemode==3) { sprite_p->movemode=0; sprite_p->basepic=sprite_p->startpic; } else if (sprite_p->movemode==2) { sprite_p->basepic=sprite_p->startpic + 8; // midstep ++sprite_p->movemode; } else { ++sprite_p->movemode; sprite_p->basepic=sprite_p->startpic+sprite_p->movemode*8; } } sprite_p->modetime=timecount+12; } memcpy(&playerdata[pevent->playerid],pevent,sizeof(pevent_t)); if (pevent->holopic) { // if (MS_RndT()>253) // { // sprite_p->basepic=sprite_p->startpic; // sprite_p->scale=1; // sprite_p->rotate=rt_eight; // } // else // { sprite_p->basepic=pevent->holopic; sprite_p->scale=pevent->holoscale; sprite_p->rotate=rt_one; // } } if (pevent->specialeffect==SE_INVISIBILITY) sprite_p->specialtype=st_transparent; else sprite_p->specialtype=0; break; case SPAWNEVENTID: gameloading=true; if (sevent->value==S_BULLET18) { angleinc=ANGLES/12; angle=0; for(i=0,angle=0;i<12;i++,angle+=angleinc) SpawnSprite(sevent->value,sevent->x,sevent->y,sevent->z,sevent->zadj,angle,sevent->angle2,sevent->active,sevent->spawnid); } else if (sevent->value==S_SOULBULLET) { angleinc=ANGLES/16; angle=0; for(i=0,angle=0;i<16;i++,angle+=angleinc) SpawnSprite(sevent->value,sevent->x,sevent->y,sevent->z,sevent->zadj,angle,sevent->angle2,sevent->active,sevent->spawnid); } else SpawnSprite(sevent->value,sevent->x,sevent->y,sevent->z,sevent->zadj,sevent->angle,sevent->angle2,sevent->active,sevent->spawnid); gameloading=false; break; case DOOREVENTID: TryDoor(devent->x,devent->y); break; case ITEMEVENTID: mapsprites[ipevent->mapspot]=ipevent->type; CheckItems(ipevent->tilex,ipevent->tiley,false,ipevent->chartype); mapsprites[ipevent->mapspot]=0; break; case SOUNDEVENTID: SoundEffect(eevent->effect,eevent->variation,eevent->x,eevent->y); break; case BONUSEVENTID: if (BonusItem.score>0) { for (sprite_p=firstscaleobj.next; sprite_p!=&lastscaleobj;sprite_p=sprite_p->next) if (sprite_p->type==S_BONUSITEM) { RF_RemoveSprite(sprite_p); mapsprites[BonusItem.mapspot]=0; break; } SpawnSprite(S_WARP,(BonusItem.tilex*MAPSIZE+32)<tilex; BonusItem.tiley=bevent->tiley; BonusItem.mapspot=BonusItem.tiley*MAPCOLS + BonusItem.tilex; } while (floorpic[BonusItem.mapspot]==0 || mapsprites[BonusItem.mapspot]>0 || mapeffects[BonusItem.mapspot]&FL_FLOOR); BonusItem.score=bevent->score; BonusItem.time=bevent->time; BonusItem.num=bevent->num; BonusItem.name=randnames[BonusItem.num]; BonusItem.sprite=SpawnSprite(S_BONUSITEM,(BonusItem.tilex*MAPSIZE+32)<basepic+=BonusItem.num; oldgoalitem=-1; writemsg("Bonus item located!"); break; case TRIGGEREVENTID: CheckHere(false,devent->x,devent->y,devent->angle); break; case FRAGEVENTID: if (fevent->bulletidbulletid]++; goalitem=fevent->bulletid+1; } if (playernum==fevent->bulletid) { player.frags[fevent->playerid]++; addscore(5000); sprintf(msg,"Fragged %s! %i of %i",netnames[fevent->playerid],player.frags[fevent->playerid],fragcount[playernum]); writemsg(msg); } else if (fevent->bulletidbulletid],netnames[fevent->playerid]); writemsg(msg); } else { sprintf(msg,"%s was killed.",netnames[fevent->playerid]); writemsg(msg); } sprite_p=playersprites[fevent->playerid]; if (sprite_p->startpic==CA_GetNamedNum(charnames[0])) { gameloading=true; // do not transmit sprite2_p=SpawnSprite(S_TIMEMINE,sprite_p->x,sprite_p->y,0,0,0,0,false,playernum); gameloading=false; sprite2_p->basepic=sprite_p->startpic+40; sprite_p->basepic=sprite_p->startpic+40; sprite2_p->scale=1; sprite_p->animation=0 + (0<<1) + (0<<5) + (0<<9) + ANIM_SELFDEST; } else { sprite_p->basepic=sprite_p->startpic + 40; sprite_p->animation = 0 + (0<<1) + (8<<5) + ((6+(MS_RndT()&3))<<9); } sprite_p->rotate=rt_one; sprite_p->heat=0; sprite_p->active=false; sprite_p->moveSpeed=0; sprite_p->hitpoints=0; sprite_p->intelligence=0; mapsprites[playermapspot[fevent->playerid]]=0; playersprites[fevent->playerid]=NULL; break; case NEWPLAYEREVENTID: SpawnNewPlayer(); // new player break; case PAUSEEVENTID: netpaused=true; break; case UNPAUSEEVENTID: netpaused=false; break; case JAMMEREVENTID: for (sprite_p=firstscaleobj.next; sprite_p!=&lastscaleobj;sprite_p=sprite_p->next) if (sprite_p->type==S_GENERATOR || (sprite_p->type>=S_GENSTART && sprite_p->type<=S_GENEND)) { mapsprites[(sprite_p->y>>FRACTILESHIFT)*MAPCOLS + (sprite_p->x>>FRACTILESHIFT)]=0; temp_p=sprite_p; sprite_p=sprite_p->next; RF_RemoveSprite(temp_p); } else sprite_p=sprite_p->next; sprintf(msg,"%s activated Warp Jammer!",netnames[qevent->playerid]); writemsg(msg); netwarpjammer=true; netwarpjamtime=timecount+70*60; break; case EVENTEVENTID: Event(fevent->bulletid,false); break; case QUITEVENTID: sprintf(msg,"%s has left the game!",netnames[qevent->playerid]); writemsg(msg); break; case MESSAGEEVENTID: sprintf(msg,"%s: %s",netnames[mevent->playerid],mevent->message); writemsg(msg); SoundEffect(SN_NEXUS,0,player.x,player.y); break; } } while (1); } void NetSendPlayerData(void) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; // broadcast greedcom->datalength=sizeof(pevent_t); pevent->playerid=playernum; pevent->id=PLAYEREVENTID; pevent->x=player.x; pevent->y=player.y; pevent->z=player.z; pevent->angle=player.angle; pevent->angst=player.angst; pevent->height=player.height; pevent->chartype=player.chartype; pevent->status=player.status; pevent->holopic=player.holopic; pevent->holoscale=player.holoscale; pevent->specialeffect=specialeffect; player.status=0; memcpy(&playerdata[playernum],pevent,sizeof(pevent_t)); NETINT(); } void NetNewPlayerData(void) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; // broadcast greedcom->datalength=sizeof(pevent_t); pevent->playerid=playernum; pevent->id=NEWPLAYEREVENTID; pevent->x=player.x; pevent->y=player.y; pevent->z=player.z; pevent->angle=player.angle; pevent->angst=player.angst; pevent->height=player.height; pevent->chartype=player.chartype; pevent->status=player.status; pevent->holopic=player.holopic; pevent->specialeffect=specialeffect; player.status=0; memcpy(&playerdata[playernum],pevent,sizeof(pevent_t)); NETINT(); } void NetSendSpawn(int value, fixed_t x, fixed_t y, fixed_t z,fixed_t zadj,int angle,int angle2,boolean active,int spawnid) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; // broadcast greedcom->datalength=sizeof(sevent_t); sevent->id=SPAWNEVENTID; sevent->value=value; sevent->x=x; sevent->y=y; sevent->z=z; sevent->zadj=zadj; sevent->angle=angle; sevent->angle2=angle2; sevent->active=active; sevent->spawnid=spawnid; sevent->playerid=playernum; NETINT(); } void NetQuitGame(void) { NetDeath(255); greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(qevent_t); qevent->id=QUITEVENTID; qevent->playerid=playernum; NETINT(); } void NetOpenDoor(fixed_t x,fixed_t y) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(devent_t); devent->id=DOOREVENTID; devent->playerid=playernum; devent->x=x; devent->y=y; NETINT(); } void netstub(void) { } void NetDeath(int bulletid) { char str1[50]; greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(fevent_t); fevent->id=FRAGEVENTID; fevent->playerid=playernum; fevent->bulletid=bulletid; if (fevent->bulletidbulletid]); writemsg(str1); } NETINT(); } void NetItemPickup(int x,int y) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(ipevent_t); ipevent->id=ITEMEVENTID; ipevent->playerid=playernum; ipevent->tilex=x; ipevent->tiley=y; ipevent->mapspot=y*MAPCOLS+x; ipevent->type=mapsprites[ipevent->mapspot]; ipevent->chartype=player.chartype; NETINT(); } void NetBonusItem(void) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(bevent_t); bevent->id=BONUSEVENTID; bevent->playerid=playernum; bevent->time=BonusItem.time; bevent->score=BonusItem.score; bevent->tilex=BonusItem.tilex; bevent->tiley=BonusItem.tiley; bevent->num=BonusItem.num; NETINT(); } void NetGetClosestPlayer(int sx,int sy) { longint mindist, minplayer, dist; int i, px, py; minplayer=-1; mindist=0x7FFFFFFFL; for(i=0;inumplayers;i++) if (playerdata[i].angst && playerdata[i].specialeffect!=SE_INVISIBILITY) // gotta be alive && visible { px=playerdata[i].x>>FRACTILESHIFT; py=playerdata[i].y>>FRACTILESHIFT; dist=(px-sx)*(px-sx) + (py-sy)*(py-sy); if (distcommand=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(qevent_t); qevent->id=PAUSEEVENTID; qevent->playerid=playernum; NETINT(); } void NetUnPause(void) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(qevent_t); qevent->id=UNPAUSEEVENTID; qevent->playerid=playernum; NETINT(); } void NetCheckHere(fixed_t centerx,fixed_t centery,int angle) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(devent_t); devent->id=TRIGGEREVENTID; devent->playerid=playernum; devent->x=centerx; devent->y=centery; devent->angle=angle; NETINT(); } void NetSoundEffect(int n,int variation,fixed_t x,fixed_t y) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(eevent_t); eevent->id=SOUNDEVENTID; eevent->playerid=playernum; eevent->x=x; eevent->y=y; eevent->variation=variation; eevent->effect=n; NETINT(); } void NetWarpJam(void) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(qevent_t); qevent->id=JAMMEREVENTID; qevent->playerid=playernum; NETINT(); } void NetEvent(int n) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(fevent_t); fevent->id=EVENTEVENTID; fevent->playerid=playernum; fevent->bulletid=n; NETINT(); } void NetSendMessage(char *s) { greedcom->command=CMD_SEND; greedcom->remotenode=MAXPLAYERS; greedcom->datalength=sizeof(mevent_t); mevent->id=MESSAGEEVENTID; mevent->playerid=playernum; strcpy(mevent->message,s); NETINT(); }