diff --git a/engine/Makefile b/engine/Makefile index c028b5e1f..de8cbe3c5 100644 --- a/engine/Makefile +++ b/engine/Makefile @@ -266,6 +266,9 @@ CLIENT_OBJS = $(CLIENT_ASM_OBJS) \ net_master.o \ r_bulleten.o \ r_part.o \ + p_script.o \ + p_null.o \ + p_classic.o \ r_partset.o \ r_efrag.o \ renderer.o \ diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index fbc6b15f7..49c627f5f 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -33,7 +33,8 @@ char *VMQ3_StringFromHandle(int handle); int VMQ3_StringToHandle(char *str); extern model_t mod_known[]; -#define VM_FROMMHANDLE(a) (a?mod_known+a-1:NULL) +extern int mod_numknown; +#define VM_FROMMHANDLE(a) ((a&&((unsigned int)a)<=mod_numknown)?mod_known+a-1:NULL) #define VM_TOMHANDLE(a) (a?a-mod_known+1:0) extern shader_t r_shaders[]; @@ -1031,13 +1032,13 @@ vec3_t listener_up; break; case CG_FTE_FINDPARTICLEEFFECT: - return P_FindParticleType(VM_POINTER(arg[0])); + return pe->FindParticleType(VM_POINTER(arg[0])); case CG_FTE_SPAWNPARTICLEEFFECT: - return P_RunParticleEffectState(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_FLOAT(arg[2]), VM_LONG(arg[3]), VM_POINTER(arg[4])); + return pe->RunParticleEffectState(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_FLOAT(arg[2]), VM_LONG(arg[3]), VM_POINTER(arg[4])); case CG_FTE_SPAWNPARTICLETRAIL: - return P_ParticleTrail(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), VM_POINTER(arg[3])); + return pe->ParticleTrail(VM_POINTER(arg[0]), VM_POINTER(arg[1]), VM_LONG(arg[2]), VM_POINTER(arg[3])); case CG_FTE_FREEPARTICLESTATE: - P_DelinkTrailstate(VM_POINTER(arg[0])); + pe->DelinkTrailstate(VM_POINTER(arg[0])); break; default: Con_Printf("Q3CG: Bad system trap: %d\n", fn); diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 0aa81a1c4..4bc04efe7 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -1155,7 +1155,7 @@ void CL_Record_f (void) else MSG_WriteByte (&buf, j); - MSG_WriteByte (&buf, ent->frame); + MSG_WriteByte (&buf, ent->frame1); MSG_WriteByte (&buf, 0); MSG_WriteByte (&buf, ent->skinnum); for (j=0 ; j<3 ; j++) diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 62c5dd70e..d3fad8cbe 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -972,6 +972,7 @@ void CLNQ_ParseEntity(unsigned int bits) { pack->max_entities = pack->num_entities+1; pack->entities = BZ_Realloc(pack->entities, sizeof(entity_state_t)*pack->max_entities); + memset(pack->entities + pack->num_entities, 0, sizeof(entity_state_t)); } lasttime = realtime; state = &pack->entities[pack->num_entities++]; @@ -1166,9 +1167,17 @@ void CL_RotateAroundTag(entity_t *ent, int num, int tagent, int tagnum) int model = 0; //these two are only initialised because msvc sucks at detecting usage. int frame = 0; - int frame2 = cl.lerpents[tagent].frame; + int frame2; float frame2ness; + if (tagent > cl.maxlerpents) + { + Con_Printf("tag entity out of range!\n"); + return; + } + + frame2 = cl.lerpents[tagent].frame; + ent->keynum = tagent; ps = CL_FindPacketEntity(tagent); @@ -1684,8 +1693,8 @@ void CL_LinkPacketEntities (void) ent->drawflags = state->hexen2flags; // set frame - ent->frame = state->frame; - ent->oldframe = le->frame; + ent->frame1 = state->frame; + ent->frame2 = le->frame; ent->frame1time = cl.servertime - le->framechange; ent->frame2time = cl.servertime - le->oldframechange; @@ -1759,8 +1768,8 @@ void CL_LinkPacketEntities (void) } if (i == cl_oldnumvisedicts) { - P_DelinkTrailstate(&(cl.lerpents[state->number].trailstate)); - P_DelinkTrailstate(&(cl.lerpents[state->number].emitstate)); + pe->DelinkTrailstate(&(cl.lerpents[state->number].trailstate)); + pe->DelinkTrailstate(&(cl.lerpents[state->number].emitstate)); continue; // not in last message } @@ -1775,8 +1784,8 @@ void CL_LinkPacketEntities (void) if (model->particletrail >= 0) { - if (P_ParticleTrail (old_origin, ent->origin, model->particletrail, &(le->trailstate))) - P_ParticleTrailIndex(old_origin, ent->origin, model->traildefaultindex, 0, &(le->trailstate)); + if (pe->ParticleTrail (old_origin, ent->origin, model->particletrail, &(le->trailstate))) + pe->ParticleTrailIndex(old_origin, ent->origin, model->traildefaultindex, 0, &(le->trailstate)); } { @@ -1805,15 +1814,15 @@ void CL_LinkPacketEntities (void) dclr[2] = 0.05; } } - else if (model->flags & EF_FIREBALL) + else if (model->flags & EFH2_FIREBALL) { rad = 120 - (rand() % 20); } - else if (model->flags & EF_ACIDBALL) + else if (model->flags & EFH2_ACIDBALL) { rad = 120 - (rand() % 20); } - else if (model->flags & EF_SPIT) + else if (model->flags & EFH2_SPIT) { // as far as I can tell this effect inverses the light... dclr[0] = -dclr[0]; @@ -2235,7 +2244,7 @@ void CL_LinkProjectiles (void) #endif ent->model = cl.model_precache[pr->modelindex]; ent->skinnum = 0; - ent->frame = 0; + ent->frame1 = 0; ent->flags = 0; #ifdef SWQUAKE ent->palremap = D_IdentityRemap(); @@ -2493,7 +2502,7 @@ void CL_ParsePlayerinfo (void) else state->weaponframe = 0; - if (cl.worldmodel && (cl.worldmodel->fromgame == fg_quake || cl.worldmodel->fromgame == fg_halflife)) + if (cl.worldmodel && cl.worldmodel->fromgame == fg_quake) state->hullnum = 1; else state->hullnum = 56; @@ -2629,27 +2638,27 @@ void CL_AddFlagModels (entity_t *ent, int team) return; f = 14; - if (ent->frame >= 29 && ent->frame <= 40) { - if (ent->frame >= 29 && ent->frame <= 34) { //axpain - if (ent->frame == 29) f = f + 2; - else if (ent->frame == 30) f = f + 8; - else if (ent->frame == 31) f = f + 12; - else if (ent->frame == 32) f = f + 11; - else if (ent->frame == 33) f = f + 10; - else if (ent->frame == 34) f = f + 4; - } else if (ent->frame >= 35 && ent->frame <= 40) { // pain - if (ent->frame == 35) f = f + 2; - else if (ent->frame == 36) f = f + 10; - else if (ent->frame == 37) f = f + 10; - else if (ent->frame == 38) f = f + 8; - else if (ent->frame == 39) f = f + 4; - else if (ent->frame == 40) f = f + 2; + if (ent->frame1 >= 29 && ent->frame1 <= 40) { + if (ent->frame1 >= 29 && ent->frame1 <= 34) { //axpain + if (ent->frame1 == 29) f = f + 2; + else if (ent->frame1 == 30) f = f + 8; + else if (ent->frame1 == 31) f = f + 12; + else if (ent->frame1 == 32) f = f + 11; + else if (ent->frame1 == 33) f = f + 10; + else if (ent->frame1 == 34) f = f + 4; + } else if (ent->frame1 >= 35 && ent->frame1 <= 40) { // pain + if (ent->frame1 == 35) f = f + 2; + else if (ent->frame1 == 36) f = f + 10; + else if (ent->frame1 == 37) f = f + 10; + else if (ent->frame1 == 38) f = f + 8; + else if (ent->frame1 == 39) f = f + 4; + else if (ent->frame1 == 40) f = f + 2; } - } else if (ent->frame >= 103 && ent->frame <= 118) { - if (ent->frame >= 103 && ent->frame <= 104) f = f + 6; //nailattack - else if (ent->frame >= 105 && ent->frame <= 106) f = f + 6; //light - else if (ent->frame >= 107 && ent->frame <= 112) f = f + 7; //rocketattack - else if (ent->frame >= 112 && ent->frame <= 118) f = f + 7; //shotattack + } else if (ent->frame1 >= 103 && ent->frame1 <= 118) { + if (ent->frame1 >= 103 && ent->frame1 <= 104) f = f + 6; //nailattack + else if (ent->frame1 >= 105 && ent->frame1 <= 106) f = f + 6; //light + else if (ent->frame1 >= 107 && ent->frame1 <= 112) f = f + 7; //rocketattack + else if (ent->frame1 >= 112 && ent->frame1 <= 118) f = f + 7; //shotattack } newent = CL_NewTempEntity (); @@ -2681,7 +2690,7 @@ void CL_AddVWeapModel(entity_t *player, int model) VectorCopy(player->angles, newent->angles); newent->skinnum = player->skinnum; newent->model = cl.model_precache[model]; - newent->frame = player->frame; + newent->frame1 = player->frame1; VectorCopy(newent->angles, angles); angles[0]*=-1; @@ -2770,10 +2779,10 @@ void CL_LinkPlayers (void) ent->frame1time = cl.time - cl.lerpplayers[j].framechange; ent->frame2time = cl.time - cl.lerpplayers[j].oldframechange; - if (ent->frame != cl.lerpplayers[j].frame) + if (ent->frame1 != cl.lerpplayers[j].frame) { - ent->oldframe = ent->frame; - ent->frame = cl.lerpplayers[j].frame; + ent->frame2 = ent->frame1; + ent->frame1 = cl.lerpplayers[j].frame; } ent->lerpfrac = 1-(realtime - cl.lerpplayers[j].framechange)*10; @@ -2880,8 +2889,6 @@ void CL_LinkPlayers (void) pmove.numphysent = oldphysent; VectorCopy (exact.origin, ent->origin); } - if (cl.worldmodel->fromgame == fg_halflife) - ent->origin[2]-=12; if (state->effects & QWEF_FLAG1) CL_AddFlagModels (ent, 0); @@ -2973,20 +2980,20 @@ void CL_LinkViewModel(void) ent.shaderRGBAf[2] = 1; ent.shaderRGBAf[3] = alpha; - ent.frame = cl.viewent[r_refdef.currentplayernum].frame; - ent.oldframe = oldframe[r_refdef.currentplayernum]; + ent.frame1 = cl.viewent[r_refdef.currentplayernum].frame1; + ent.frame2 = oldframe[r_refdef.currentplayernum]; - if (ent.frame != prevframe[r_refdef.currentplayernum]) + if (ent.frame1 != prevframe[r_refdef.currentplayernum]) { - oldframe[r_refdef.currentplayernum] = ent.oldframe = prevframe[r_refdef.currentplayernum]; + oldframe[r_refdef.currentplayernum] = ent.frame2 = prevframe[r_refdef.currentplayernum]; lerptime[r_refdef.currentplayernum] = realtime; } - prevframe[r_refdef.currentplayernum] = ent.frame; + prevframe[r_refdef.currentplayernum] = ent.frame1; if (ent.model != oldmodel[r_refdef.currentplayernum]) { oldmodel[r_refdef.currentplayernum] = ent.model; - oldframe[r_refdef.currentplayernum] = ent.oldframe = ent.frame; + oldframe[r_refdef.currentplayernum] = ent.frame2 = ent.frame1; lerptime[r_refdef.currentplayernum] = realtime; } ent.lerpfrac = 1-(realtime-lerptime[r_refdef.currentplayernum])*10; diff --git a/engine/client/cl_ignore.c b/engine/client/cl_ignore.c index fdd422c41..54cdc1e63 100644 --- a/engine/client/cl_ignore.c +++ b/engine/client/cl_ignore.c @@ -352,15 +352,15 @@ char Ignore_Check_Flood(char *s, int flags, int offset) { char name[MAX_INFO_STRING]; if ( !( - ( (ignore_flood.value == 1 && (flags == 1 || flags == 4)) || + ( (ignore_flood.value == 1 && (flags & TPM_NORMAL || flags & TPM_SPECTATOR)) || (ignore_flood.value == 2 && flags != 0) ) ) ) return NO_IGNORE_NO_ADD; - if (flags == 1 || flags == 4) { + if (flags == 1 || flags == TPM_SPECTATOR) { p = 0; q = offset - 3; - } else if (flags == 2) { + } else if (flags == TPM_TEAM) { p = 1; q = offset - 4; } else if (flags == 8) { diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index 9c9a09c81..15021d6c1 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -842,8 +842,8 @@ void CLNQ_SendCmd(sizebuf_t *buf) if (nq_dp_protocol > 0 && cls.signon == 4) { - MSG_WriteByte(&cls.netchan.message, 50); - MSG_WriteLong(&cls.netchan.message, cl_latestframenum); + MSG_WriteByte(buf, clcdp_ackframe); + MSG_WriteLong(buf, cl_latestframenum); } memset(&independantphysics[0], 0, sizeof(independantphysics[0])); @@ -872,7 +872,11 @@ float CL_FilterTime (double time, float wantfps) //now returns the extra time no else { fpscap = cls.maxfps ? max (30.0, cls.maxfps) : 0x7fff; - +#ifdef IRCCONNECT + if (cls.netchan.remote_address.type == NA_IRC) + fps = bound (0.1, wantfps, fpscap); //if we're connected via irc, allow a greatly reduced minimum cap + else +#endif if (wantfps < 1) fps = fpscap; else @@ -1466,6 +1470,9 @@ void CL_SendCmd (double frametime) buf.cursize = 0; buf.data = data; +#ifdef IRCCONNECT + if (cls.netchan.remote_address.type != NA_IRC) +#endif if (msecs>150) //q2 has 200 slop. msecs=150; @@ -1476,6 +1483,9 @@ void CL_SendCmd (double frametime) msecs=0; //erm. msecstouse = (int)msecs; //casts round down. +#ifdef IRCCONNECT + if (cls.netchan.remote_address.type != NA_IRC) +#endif if (msecstouse > 200) // cap at 200 to avoid servers splitting movement more than four times msecstouse = 200; @@ -1494,13 +1504,21 @@ void CL_SendCmd (double frametime) if (!cl_indepphysics.value) { // while we're not playing send a slow keepalive fullsend to stop mvdsv from screwing up - if (cls.state < ca_active && CL_FilterTime(msecstouse, 12.5) == false) + if (cls.state < ca_active && CL_FilterTime(msecstouse, +#ifdef IRCCONNECT //don't spam irc. + cls.netchan.remote_address.type == NA_IRC?0.5: +#endif + 12.5) == false) fullsend = false; else if (cl_netfps.value > 0) { int spare; spare = CL_FilterTime(msecstouse, cl_netfps.value); - if (!spare && msecstouse < 200) + if (!spare && (msecstouse < 200 +#ifdef IRCCONNECT + || cls.netchan.remote_address.type == NA_IRC +#endif + )) fullsend = false; if (spare > cl_sparemsec.value) spare = cl_sparemsec.value; @@ -1548,13 +1566,18 @@ void CL_SendCmd (double frametime) next = clientcmdlist->next; if (clientcmdlist->reliable) { + if (cls.netchan.message.cursize + 2+strlen(clientcmdlist->command) > cls.netchan.message.maxsize) + break; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, clientcmdlist->command); } else { - MSG_WriteByte (&buf, clc_stringcmd); - MSG_WriteString (&buf, clientcmdlist->command); + if (buf.cursize + 2+strlen(clientcmdlist->command) <= buf.maxsize) + { + MSG_WriteByte (&buf, clc_stringcmd); + MSG_WriteString (&buf, clientcmdlist->command); + } } Con_DPrintf("Sending stringcmd %s\n", clientcmdlist->command); Z_Free(clientcmdlist); @@ -1613,8 +1636,27 @@ void CL_SendCmd (double frametime) if (cls.demorecording) CL_WriteDemoCmd(cmd); -//shamelessly stolen from fuhquake - if (cl_c2spps.value>0) +#ifdef IRCCONNECT + if (cls.netchan.remote_address.type == NA_IRC) + { + if (dropcount >= 2) + { + dropcount = 0; + } + else + { + // don't count this message when calculating PL + cl.frames[i].receivedtime = -3; + // drop this message + cls.netchan.outgoing_sequence++; + dropcount++; + return; + } + } + else +#endif + //shamelessly stolen from fuhquake + if (cl_c2spps.value>0) { pps_balance += frametime; // never drop more than 2 messages in a row -- that'll cause PL diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index f9b01cca5..4300856db 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -129,14 +129,15 @@ cvar_t cl_gunanglex = SCVAR("cl_gunanglex", "0"); cvar_t cl_gunangley = SCVAR("cl_gunangley", "0"); cvar_t cl_gunanglez = SCVAR("cl_gunanglez", "0"); -cvar_t allow_download_csprogs = SCVAR("allow_download_csprogs", "0"); +cvar_t allow_download_csprogs = SCVARF("allow_download_csprogs", "0", CVAR_NOTFROMSERVER); +cvar_t allow_download_redirection = SCVARF("allow_download_redirection", "0", CVAR_NOTFROMSERVER); +cvar_t requiredownloads = SCVARF("requiredownloads","1", CVAR_ARCHIVE); cvar_t cl_muzzleflash = SCVAR("cl_muzzleflash", "1"); cvar_t cl_item_bobbing = SCVAR("cl_model_bobbing", "0"); cvar_t cl_countpendingpl = SCVAR("cl_countpendingpl", "0"); -cvar_t requiredownloads = SCVARF("requiredownloads","1", CVAR_ARCHIVE); cvar_t cl_standardchat = SCVARF("cl_standardchat", "0", CVAR_ARCHIVE); cvar_t msg_filter = SCVAR("msg_filter", "0"); //0 for neither, 1 for mm1, 2 for mm2, 3 for both cvar_t cl_standardmsg = SCVARF("cl_standardmsg", "0", CVAR_ARCHIVE); @@ -396,6 +397,7 @@ void CL_SendConnectPacket ( int compressioncrc /*, ...*/) //dmw new parms { + extern cvar_t qport; netadr_t adr; char data[2048]; char playerinfo2[MAX_INFO_STRING]; @@ -456,7 +458,8 @@ void CL_SendConnectPacket ( connect_time = realtime+t2-t1; // for retransmit requests - cls.qport = Cvar_VariableValue("qport"); + cls.qport = qport.value; + Cvar_SetValue(&qport, (cls.qport+1)&0xffff); // Info_SetValueForStarKey (cls.userinfo, "*ip", NET_AdrToString(adr), MAX_INFO_STRING); @@ -641,6 +644,9 @@ void CL_CheckForResend (void) CLQ3_SendAuthPacket(adr); #endif + if (connect_tries == 0) + NET_EnsureRoute(cls.sockets, "conn", cls.servername); + #ifdef NQPROT if (connect_type || ((connect_tries&3)==3)) { @@ -796,72 +802,28 @@ void CLNQ_Connect_f (void) } #endif +#ifdef IRCCONNECT +struct ftenet_generic_connection_s *FTENET_IRCConnect_EstablishConnection(qboolean isserver, char *address); +void CL_IRCConnect_f (void) +{ + CL_Disconnect_f (); + + if (FTENET_AddToCollection(cls.sockets, "TCP", Cmd_Argv(2), FTENET_IRCConnect_EstablishConnection)) + { + char *server; + server = Cmd_Argv (1); + + strcpy(cls.servername, "irc://"); + Q_strncpyz (cls.servername+6, server, sizeof(cls.servername)-6); + CL_BeginServerConnect(); + } +} +#endif + #ifdef TCPCONNECT void CL_TCPConnect_f (void) { - char buffer[6]; - int newsocket; - int len; - int _true = true; - - float giveuptime; - - char *server; - - if (Cmd_Argc() != 2) - { - Con_TPrintf (TLC_SYNTAX_CONNECT); - return; - } - - server = Cmd_Argv (1); - - CL_Disconnect_f (); - - Q_strncpyz (cls.servername, server, sizeof(cls.servername)); - - NET_StringToAdr(cls.servername, &cls.sockettcpdest); - - if (cls.sockettcp != INVALID_SOCKET) - closesocket (cls.sockettcp); - cls.sockettcp = INVALID_SOCKET; - cls.tcpinlen = 0; - - newsocket = TCP_OpenStream(cls.sockettcpdest); - if (newsocket == INVALID_SOCKET) - { - //failed - Con_Printf("Failed to connect, server is either down, firewalled, or on a different port\n"); - return; - } - - Con_Printf("Waiting for confirmation of server (10 secs)\n"); - - giveuptime = Sys_DoubleTime() + 10; - - while(giveuptime > Sys_DoubleTime()) - { - len = recv(newsocket, buffer, sizeof(buffer), 0); - if (!strncmp(buffer, "qizmo\n", 6)) - { - cls.sockettcp = newsocket; - break; - } - SCR_UpdateScreen(); - } - - if (cls.sockettcp == INVALID_SOCKET) - { - Con_Printf("Timeout - wrong server type\n"); - closesocket(newsocket); - return; - } - Con_Printf("Confirmed\n"); - - send(cls.sockettcp, buffer, sizeof(buffer), 0); - setsockopt(cls.sockettcp, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); - - CL_BeginServerConnect(); + Cbuf_InsertText(va("connect tcp://%s", Cmd_Argv(1)), Cmd_ExecLevel, true); } #endif @@ -990,7 +952,10 @@ void CL_ClearState (void) for (i = 0; i < UPDATE_BACKUP; i++) { if (cl.frames[i].packet_entities.entities) + { Z_Free(cl.frames[i].packet_entities.entities); + cl.frames[i].packet_entities.entities = NULL; + } } if (cl.lerpents) @@ -1049,6 +1014,8 @@ void CL_ClearState (void) cl.oldgametime = 0; cl.gametime = 0; cl.gametimemark = 0; + + CL_RegisterParticles(); } /* @@ -1124,6 +1091,7 @@ void CL_Disconnect (void) } cls.state = ca_disconnected; + cls.protocol = CP_UNKNOWN; cls.demoplayback = DPB_NONE; cls.demorecording = cls.timedemo = false; @@ -1192,7 +1160,6 @@ void CL_Disconnect (void) V_ClearCShifts(); } - cls.protocol = CP_UNKNOWN; cl.servercount = 0; cls.findtrack = false; cls.realserverip.type = NA_INVALID; @@ -1200,15 +1167,10 @@ void CL_Disconnect (void) Validation_DelatchRulesets(); #ifdef TCPCONNECT - if (cls.sockettcp != INVALID_SOCKET) - { - closesocket(cls.sockettcp); - cls.sockettcp = INVALID_SOCKET; - } + //disconnects it, without disconnecting the others. + FTENET_AddToCollection(cls.sockets, "TCP", NULL, NULL); #endif - cls.qport++; //a hack I picked up from qizmo - Cvar_ForceSet(&cl_servername, "none"); } @@ -1402,9 +1364,6 @@ void CL_CheckServerInfo(void) if (cl.spectator || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "mirrors"))) cls.allow_mirrors=true; - if (cl.spectator || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "allow_shaders"))) - cls.allow_shaders=true; - if (cl.spectator || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "allow_luma"))) cls.allow_luma=true; @@ -1774,18 +1733,7 @@ void CL_Packet_f (void) } *out = 0; -#ifdef TCPCONNECT - { - int tcpsock; //extra code to stop the packet command from sending to the server via tcp - tcpsock = cls.sockettcp; - cls.sockettcp = -1; - NET_SendPacket (NS_CLIENT, out-send, send, adr); - cls.sockettcp = tcpsock; - } -#else NET_SendPacket (NS_CLIENT, out-send, send, adr); -#endif - if (Cmd_FromGamecode()) { @@ -1925,8 +1873,13 @@ void CL_Changing_f (void) S_StopAllSounds (true); cl.intermission = 0; - cls.state = ca_connected; // not active anymore, but not disconnected - Con_TPrintf (TLC_CHANGINGMAP); + if (cls.state) + { + cls.state = ca_connected; // not active anymore, but not disconnected + Con_TPrintf (TLC_CHANGINGMAP); + } + else + Con_Printf("Changing while not connected\n"); #ifdef NQPROT cls.signon=0; @@ -2031,6 +1984,30 @@ void CL_ConnectionlessPacket (void) return; } + if (c == A2C_PRINT) + { + if (!strncmp(net_message.data+msg_readcount, "\\chunk", 6)) + { + if (NET_CompareBaseAdr(cls.netchan.remote_address, net_from) == false) + if (cls.realserverip.type == NA_INVALID || NET_CompareBaseAdr(cls.realserverip, net_from) == false) + return; //only use it if it came from the real server's ip (this breaks on proxies). + + MSG_ReadLong(); + MSG_ReadChar(); + MSG_ReadChar(); + + if (CL_ParseOOBDownload()) + { + if (msg_readcount != net_message.cursize) + { + Con_Printf ("junk on the end of the packet\n"); + CL_Disconnect_f(); + } + } + return; + } + } + if (cls.demoplayback == DPB_NONE) Con_TPrintf (TL_ST_COLON, NET_AdrToString (adr, sizeof(adr), net_from)); // Con_DPrintf ("%s", net_message.data + 4); @@ -2626,38 +2603,62 @@ void CL_Download_f (void) return; } - CL_CheckOrEnqueDownloadFile(url, url); + CL_CheckOrEnqueDownloadFile(url, url, DLLF_REQUIRED|DLLF_VERBOSE); return; } - CL_EnqueDownload(url, url, true, true); + CL_EnqueDownload(url, url, DLLF_REQUIRED|DLLF_OVERWRITE|DLLF_VERBOSE); +} - /* - strcpy(cls.downloadname, url); +void CL_DownloadSize_f(void) +{ + downloadlist_t *dl; + char *name; + char *size; + char *redirection; - _snprintf (cls.downloadname, sizeof(cls.downloadname), "%s/%s", com_gamedir, url); + //if this is a demo.. urm? + //ignore it. This saves any spam. + if (cls.demoplayback) + return; - p = cls.downloadname; - for (;;) + name = Cmd_Argv(1); + size = Cmd_Argv(2); + if (!strcmp(size, "e")) { - if ((q = strchr(p, '/')) != NULL) - { - *q = 0; - Sys_mkdir(cls.downloadname); - *q = '/'; - p = q + 1; - } else - break; + Con_Printf("Download of \"%s\" failed. Not found.\n", name); + CL_DownloadFailed(name); } + else if (!strcmp(size, "p")) + { + Con_Printf("Download of \"%s\" failed. Not allowed.\n", name); + CL_DownloadFailed(name); + } + else if (!strcmp(size, "r")) + { + redirection = Cmd_Argv(3); - COM_StripExtension(cls.downloadname, cls.downloadtempname); - COM_DefaultExtension(cls.downloadtempname, ".tmp"); - if (cls.down -// cls.downloadqw = fopen (cls.downloadname, "wb"); - cls.downloadmethod = DL_QWPENDING; + dl = CL_DownloadFailed(name); - - CL_SendClientCommand("download %s\n",url);*/ + if (allow_download_redirection.value) + { + Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", name, redirection); + CL_CheckOrEnqueDownloadFile(redirection, NULL, dl->flags); + } + else + Con_Printf("Download of \"%s\" redirected to \"%s\". Prevented by allow_download_redirection.\n", name, redirection); + } + else + { + for (dl = cl.downloadlist; dl; dl = dl->next) + { + if (!strcmp(dl->name, name)) + { + dl->size = strtoul(size, NULL, 0); + return; + } + } + } } void CL_FinishDownload(char *filename, char *tempname); @@ -2676,9 +2677,10 @@ void CL_ForceStopDownload (qboolean finish) } VFS_CLOSE (cls.downloadqw); + cls.downloadqw = NULL; if (finish) - CL_FinishDownload(cls.downloadname, cls.downloadtempname); + CL_DownloadFinished(cls.downloadname, cls.downloadtempname); else { char *tempname; @@ -2694,7 +2696,6 @@ void CL_ForceStopDownload (qboolean finish) FS_Remove(tempname+6, FS_SKINS); } *cls.downloadname = '\0'; - cls.downloadqw = NULL; cls.downloadpercent = 0; // get another file if needed @@ -2962,6 +2963,9 @@ void CL_Init (void) #ifdef TCPCONNECT Cmd_AddCommand ("tcpconnect", CL_TCPConnect_f); #endif +#ifdef IRCCONNECT + Cmd_AddCommand ("ircconnect", CL_IRCConnect_f); +#endif #ifdef NQPROT Cmd_AddCommand ("nqconnect", CLNQ_Connect_f); #endif @@ -2980,6 +2984,7 @@ void CL_Init (void) Cmd_AddCommand ("color", CL_Color_f); Cmd_AddCommand ("download", CL_Download_f); + Cmd_AddCommand ("dlsize", CL_DownloadSize_f); Cmd_AddCommand ("nextul", CL_NextUpload); Cmd_AddCommand ("stopul", CL_StopUpload); @@ -3373,6 +3378,8 @@ void Host_Frame (double time) CL_QTVPoll(); + + TP_UpdateAutoStatus(); } static void simple_crypt(char *buf, int len) diff --git a/engine/client/cl_master.h b/engine/client/cl_master.h index 953966d79..36876b0a9 100644 --- a/engine/client/cl_master.h +++ b/engine/client/cl_master.h @@ -45,6 +45,15 @@ typedef enum{ SLKEY_TIMELIMIT, SLKEY_FRAGLIMIT, + SLKEY_MOD, + SLKEY_PROTOCOL, + SLKEY_NUMBOTS, + SLKEY_NUMHUMANS, + SLKEY_QCSTATUS, +// SLKEY_PLAYERS, //eep! + SLKEY_ISFAVORITE,//eep! + + SLKEY_TOOMANY, SLKEY_CUSTOM } hostcachekey_t; @@ -90,12 +99,22 @@ typedef struct serverinfo_s { qbyte sends; qbyte insortedlist; + qbyte numhumans; + qbyte numbots; + qbyte freeslots; + qbyte protocol; + + char modname[8+1]; + char qcstatus[8+1]; + + char gamedir[8+1]; + char map[16]; + + unsigned short gameversion; unsigned short ping; short tl; short fl; - char gamedir[8+1]; - char map[16]; float refreshtime; @@ -153,6 +172,7 @@ int Master_KeyForName(char *keyname); float Master_ReadKeyFloat(serverinfo_t *server, int keynum); char *Master_ReadKeyString(serverinfo_t *server, int keynum); +void Master_SortServers(void); void Master_SetSortField(hostcachekey_t field, qboolean descending); hostcachekey_t Master_GetSortField(void); qboolean Master_GetSortDescending(void); diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 6a11d7ef5..46fd35043 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -29,6 +29,7 @@ void CL_SetStatInt (int pnum, int stat, int value); int nq_dp_protocol; int msgflags; +char cl_dp_csqc_progsname[128]; int cl_dp_csqc_progssize; int cl_dp_csqc_progscrc; @@ -185,15 +186,18 @@ char *svc_nqstrings[] = "NEW PROTOCOL", "NEW PROTOCOL", "dpsvc_downloaddata", //50 - "dpsvc_updatestatubyte", - "dpsvc_effect", - "dpsvc_effect2", - "dp6svc_precache/dp5svc_sound2", - "dpsvc_spawnbaseline2", - "dpsvc_spawnstatic2", - "dpsvc_entities", - "NEW PROTOCOL", - "dpsvc_spawnstaticsound2" + "dpsvc_updatestatubyte", //51 + "dpsvc_effect", //52 + "dpsvc_effect2", //53 + "dp6svc_precache/dp5svc_sound2", //54 + "dpsvc_spawnbaseline2", //55 + "dpsvc_spawnstatic2", //56 obsolete + "dpsvc_entities", //57 + "NEW PROTOCOL", //58 + "dpsvc_spawnstaticsound2", //59 + "dpsvc_trailparticles", //60 + "dpsvc_pointparticles", //61 + "dpsvc_pointparticles1" //62 }; extern cvar_t requiredownloads, cl_standardchat, msg_filter, cl_countpendingpl; @@ -280,7 +284,7 @@ int CL_CalcNet (void) //note: this will overwrite existing files. //returns true if the download is going to be downloaded after the call. -qboolean CL_EnqueDownload(char *filename, char *localname, qboolean verbose, qboolean ignorefailedlist) +qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) { downloadlist_t *dl; if (!localname) @@ -295,13 +299,13 @@ qboolean CL_EnqueDownload(char *filename, char *localname, qboolean verbose, qbo if (cls.demoplayback && cls.demoplayback != DPB_EZTV) return false; - if (!ignorefailedlist) + if (!(flags & DLLF_IGNOREFAILED)) { for (dl = cl.faileddownloads; dl; dl = dl->next) //yeah, so it failed... Ignore it. { if (!strcmp(dl->name, filename)) { - if (verbose) + if (flags & DLLF_VERBOSE) Con_Printf("We've failed to download \"%s\" already\n", filename); return false; } @@ -312,7 +316,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, qboolean verbose, qbo { if (!strcmp(dl->name, filename)) { - if (verbose) + if (flags & DLLF_VERBOSE) Con_Printf("Already waiting for \"%s\"\n", filename); return true; } @@ -320,23 +324,64 @@ qboolean CL_EnqueDownload(char *filename, char *localname, qboolean verbose, qbo if (!strcmp(cls.downloadname, filename)) { - if (verbose) + if (flags & DLLF_VERBOSE) Con_Printf("Already downloading \"%s\"\n", filename); return true; } + if (!*filename) + { + Con_Printf("Download \"\"? Huh?\n"); + return true; + } + dl = Z_Malloc(sizeof(downloadlist_t)); Q_strncpyz(dl->name, filename, sizeof(dl->name)); Q_strncpyz(dl->localname, localname, sizeof(dl->localname)); dl->next = cl.downloadlist; cl.downloadlist = dl; + dl->size = 0; + dl->flags = flags | DLLF_SIZEUNKNOWN; - if (verbose) + if (cls.fteprotocolextensions & (PEXT_CHUNKEDDOWNLOADS +#ifdef PEXT_PK3DOWNLOADS + | PEXT_PK3DOWNLOADS +#endif + )) + CL_SendClientCommand(true, "dlsize \"%s\"", dl->name); + + if (flags & DLLF_VERBOSE) Con_Printf("Enqued download of \"%s\"\n", filename); return true; } +#pragma message("fix this") +int downloadsize; +void CL_GetDownloadSizes(unsigned int *filecount, unsigned int *totalsize, qboolean *somesizesunknown) +{ + downloadlist_t *dl; + *filecount = 0; + *totalsize = 0; + *somesizesunknown = false; + for(dl = cl.downloadlist; dl; dl = dl->next) + { + *filecount++; + if (dl->flags & DLLF_SIZEUNKNOWN) + *somesizesunknown = true; + else + *totalsize += dl->size; + } + + if (cls.downloadmethod == DL_QW) + { + *totalsize += downloadsize; + *somesizesunknown = true; + } + if (cls.downloadmethod == DL_QWCHUNKS) + *totalsize += downloadsize; +} + void CL_DisenqueDownload(char *filename) { downloadlist_t *dl, *nxt; @@ -385,10 +430,11 @@ void CL_SendDownloadRequest(char *filename, char *localname) } //Do any reloading for the file that just reloaded. -void CL_FinishDownload(char *filename, char *tempname) +void CL_DownloadFinished(char *filename, char *tempname) { int i; extern int mod_numknown; + char *ext; extern model_t mod_known[]; COM_RefreshFSCache_f(); @@ -413,28 +459,38 @@ void CL_FinishDownload(char *filename, char *tempname) } } - if (!strcmp(filename, "gfx/palette.lmp")) + ext = COM_FileExtension(filename); + + + + if (!strcmp(ext, "pk3") || !strcmp(ext, "pak")) + FS_ReloadPackFiles(); + else if (!strcmp(filename, "gfx/palette.lmp")) { Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); } else { - for (i = 0; i < mod_numknown; i++) //go and load this model now. + CL_CheckModelResources(); + if (!cl.sendprespawn) { - if (!strcmp(mod_known[i].name, filename)) + for (i = 0; i < mod_numknown; i++) //go and load this model now. { - Mod_ForName(mod_known[i].name, false); //throw away result. - break; + if (!strcmp(mod_known[i].name, filename)) + { + Mod_ForName(mod_known[i].name, false); //throw away result. + break; + } } - } - for (i = 0; i < MAX_MODELS; i++) //go and load this model now. - { - if (!strcmp(cl.model_name[i], filename)) + for (i = 0; i < MAX_MODELS; i++) //go and load this model now. { - cl.model_precache[i] = Mod_ForName(cl.model_name[i], false); //throw away result. - if (i == 1) - cl.worldmodel = cl.model_precache[i]; - break; + if (!strcmp(cl.model_name[i], filename)) + { + cl.model_precache[i] = Mod_ForName(cl.model_name[i], false); //throw away result. + if (i == 1) + cl.worldmodel = cl.model_precache[i]; + break; + } } } S_ResetFailedLoad(); //okay, so this can still get a little spammy in bad places... @@ -477,12 +533,12 @@ to start a download from the server. =============== */ -qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname) +qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname, unsigned int flags) { //returns false if we don't have the file yet. if (!localname) localname = filename; - if (CL_CheckFile(localname)) + if (!(flags & DLLF_OVERWRITE) && CL_CheckFile(localname)) return true; //ZOID - can't download when recording @@ -506,58 +562,165 @@ qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname) HTTP_CL_Get(va("http://maps.quakeworld.nu/%s/download/", base), filename, MapDownload); } */ - CL_EnqueDownload(filename, localname, false, false); + CL_EnqueDownload(filename, localname, flags); + + + if (!(flags & DLLF_IGNOREFAILED)) + { + downloadlist_t *dl; + for (dl = cl.faileddownloads; dl; dl = dl->next) + { + if (!strcmp(dl->name, filename)) + { + //if its on the failed list, don't block waiting for it to download + return true; + } + } + } return false; } -qboolean CL_CheckMD2Skins (char *name) + + +static qboolean CL_CheckMD2Skins (qbyte *precache_model) { + qboolean ret = false; md2_t *pheader; - qbyte *precache_model; - int precache_model_skin = 1; + int skin = 1; char *str; - // checking for skins in the model - precache_model = COM_LoadMallocFile (name); - if (!precache_model) { - precache_model_skin = 0; - return false; // couldn't load it - } - if (LittleLong(*(unsigned *)precache_model) != MD2IDALIASHEADER) { - // not an alias model - BZ_Free(precache_model); - precache_model = 0; - precache_model_skin = 0; - return false; - } pheader = (md2_t *)precache_model; - if (LittleLong (pheader->version) != MD2ALIAS_VERSION) { - BZ_Free(precache_model); - precache_model = 0; - precache_model_skin = 0; + if (LittleLong (pheader->version) != MD2ALIAS_VERSION) + { + //bad version. return false; } pheader = (md2_t *)precache_model; - - while (precache_model_skin - 1 < LittleLong(pheader->num_skins)) + for (skin = 0; skin < LittleLong(pheader->num_skins); skin++) { str = (char *)precache_model + LittleLong(pheader->ofs_skins) + - (precache_model_skin - 1)*MD2MAX_SKINNAME; + skin*MD2MAX_SKINNAME; COM_CleanUpPath(str); - CL_CheckOrEnqueDownloadFile(str, str); - precache_model_skin++; + if (!CL_CheckOrEnqueDownloadFile(str, str, 0)) + ret = true; } - if (precache_model) { - BZ_Free(precache_model); - precache_model=NULL; - } - precache_model_skin = 0; + return ret; +} +qboolean CL_CheckHLBspWads(char *file) +{ + lump_t lump; + dheader_t *dh; + char *s; + char *w; + char key[256]; + char wads[4096]; + dh = (dheader_t *)file; + + lump.fileofs = LittleLong(dh->lumps[LUMP_ENTITIES].fileofs); + lump.filelen = LittleLong(dh->lumps[LUMP_ENTITIES].filelen); + + s = file + lump.fileofs; + + s = COM_Parse(s); + if (strcmp(com_token, "{")) + return false; + + while (*s) + { + s = COM_ParseOut(s, key, sizeof(key)); + if (!strcmp(key, "}")) + break; + + s = COM_ParseOut(s, wads, sizeof(wads)); + + if (!strcmp(key, "wad")) + { + s = wads; + while (s = COM_ParseToken(s, ";")) + { + if (!strcmp(com_token, ";")) + continue; + while (w = strchr(com_token, '\\')) + *w = '/'; + w = COM_SkipPath(com_token); + Con_Printf("wads: %s\n", w); + if (!CL_CheckFile(w)) + CL_CheckOrEnqueDownloadFile(va("textures/%s", w), NULL, DLLF_REQUIRED); + } + return false; + } + } return false; } +qboolean CL_CheckQ2BspWals(char *file) +{ + qboolean gotone = false; + + q2dheader_t *dh; + lump_t lump; + q2texinfo_t *tinf; + unsigned int i, j, count; + + dh = (q2dheader_t*)file; + if (LittleLong(dh->version) != Q2BSPVERSION) + { + //quake3? unknown? + return false; + } + lump.fileofs = LittleLong(dh->lumps[Q2LUMP_TEXINFO].fileofs); + lump.filelen = LittleLong(dh->lumps[Q2LUMP_TEXINFO].filelen); + + count = lump.filelen / sizeof(*tinf); + if (lump.filelen != count*sizeof(*tinf)) + return false; + + tinf = (q2texinfo_t*)(file + lump.fileofs); + for (i = 0; i < count; i++) + { + //ignore duplicate files (to save filesystem hits) + for (j = 0; j < i; j++) + if (!strcmp(tinf[i].texture, tinf[j].texture)) + break; + + if (i == j) + if (!CL_CheckOrEnqueDownloadFile(tinf[i].texture, NULL, 0)) + gotone = true; + } + return gotone; +} + +qboolean CL_CheckModelResources (char *name) +{ + //returns true if we triggered a download + qboolean ret; + qbyte *file; + + if (!(strstr(name, ".md2") || strstr(name, ".bsp"))) + return false; + + // checking for skins in the model + file = COM_LoadMallocFile (name); + if (!file) + { + return false; // couldn't load it + } + if (LittleLong(*(unsigned *)file) == MD2IDALIASHEADER) + ret = CL_CheckMD2Skins(file); + else if (LittleLong(*(unsigned *)file) == BSPVERSIONHL) + ret = CL_CheckHLBspWads(file); + else if (LittleLong(*(unsigned *)file) == IDBSPHEADER) + ret = CL_CheckQ2BspWals(file); + else + ret = false; + BZ_Free(file); + + return ret; +} + /* ================= Model_NextDownload @@ -591,7 +754,7 @@ void Model_NextDownload (void) if (!*cl.image_name[i]) continue; sprintf(picname, "pics/%s.pcx", cl.image_name[i]); - CL_CheckOrEnqueDownloadFile(picname, picname); + CL_CheckOrEnqueDownloadFile(picname, picname, 0); } if (!CLQ2_RegisterTEntModels()) return; @@ -612,11 +775,8 @@ void Model_NextDownload (void) continue; #endif - CL_CheckOrEnqueDownloadFile(s, s); //world is required to be loaded. - - if (strstr(s, ".md2")) - if (CL_CheckMD2Skins(s)) - return; + CL_CheckOrEnqueDownloadFile(s, s, (i==1)?DLLF_REQUIRED:0); //world is required to be loaded. + CL_CheckModelResources(s); } CL_AllowIndependantSendCmd(false); //stop it now, the indep stuff *could* require model tracing. @@ -652,7 +812,8 @@ int CL_LoadModels(int stage) if (allow_download_csprogs.value) { char *str = va("csprogsvers/%x.dat", chksum); - CL_CheckOrEnqueDownloadFile("csprogs.dat", str); + if (CL_CheckOrEnqueDownloadFile("csprogs.dat", str, DLLF_REQUIRED)) + return stage; //its kinda required } else { @@ -667,25 +828,24 @@ int CL_LoadModels(int stage) #ifdef PEXT_CSQC if (atstage()) { - if (cls.fteprotocolextensions & PEXT_CSQC) + char *s; + s = Info_ValueForKey(cl.serverinfo, "*csprogs"); +#ifndef FTE_DEBUG + if (*s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. +#endif { - char *s; - s = Info_ValueForKey(cl.serverinfo, "*csprogs"); - if (*s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. + unsigned int chksum = strtoul(s, NULL, 0); + if (CSQC_Init(chksum)) { - unsigned int chksum = strtoul(s, NULL, 0); - if (CSQC_Init(chksum)) - { - CL_SendClientCommand(true, "enablecsqc"); - } - else - { - CL_SendClientCommand(true, "disablecsqc"); - Sbar_Start(); //try and start this before we're actually on the server, - //this'll stop the mod from sending so much stuffed data at us, whilst we're frozen while trying to load. - //hopefully this'll make it more robust. - //csqc is expected to use it's own huds, or to run on decent servers. :p - } + CL_SendClientCommand(true, "enablecsqc"); + } + else + { + CL_SendClientCommand(true, "disablecsqc"); + Sbar_Start(); //try and start this before we're actually on the server, + //this'll stop the mod from sending so much stuffed data at us, whilst we're frozen while trying to load. + //hopefully this'll make it more robust. + //csqc is expected to use it's own huds, or to run on decent servers. :p } } endstage(); @@ -715,6 +875,13 @@ int CL_LoadModels(int stage) if (atstage()) { +#ifdef CSQC_DAT + if (i == 1) + CSQC_LoadResource(cl.model_name[i], "map"); + else + CSQC_LoadResource(cl.model_name[i], "model"); +#endif + cl.model_precache[i] = Mod_ForName (cl.model_name[i], false); Hunk_Check(); @@ -731,7 +898,12 @@ int CL_LoadModels(int stage) { cl.worldmodel = cl.model_precache[1]; if (!cl.worldmodel || cl.worldmodel->type == mod_dummy) - Host_EndGame("Worldmodel wasn't sent\n"); + { + if (!cl.model_name[1][0]) + Host_EndGame("Worldmodel name wasn't sent\n"); + else + Host_EndGame("Worldmodel wasn't loaded\n"); + } if (cl.worldmodel->fromgame == fg_quake) cl.hexen2pickups = cl.worldmodel->hulls[MAX_MAP_HULLSDH2-1].available; @@ -751,6 +923,12 @@ int CL_LoadModels(int stage) continue; if (atstage()) { +#ifdef CSQC_DAT + if (i == 1) + CSQC_LoadResource(cl.model_csqcname[i], "map"); + else + CSQC_LoadResource(cl.model_csqcname[i], "model"); +#endif cl.model_csqcprecache[i] = Mod_ForName (cl.model_csqcname[i], false); Hunk_Check(); @@ -794,6 +972,33 @@ int CL_LoadModels(int stage) return stage; } +int CL_LoadSounds(int stage) +{ + int i; + float giveuptime = Sys_DoubleTime()+0.1; //small things get padded into a single frame + +#define atstage() ((cl.contentstage == stage++)?++cl.contentstage:false) +#define endstage() if (giveuptimelocalname)) - CL_SendDownloadRequest(cl.downloadlist->name, cl.downloadlist->localname); + downloadlist_t *dl; + for (dl = cl.downloadlist; dl; dl = dl->next) + { + if (dl->flags & DLLF_REQUIRED) + break; + } + if (!dl) + dl = cl.downloadlist; + + if ((dl->flags & DLLF_OVERWRITE) || !COM_FCheckExists (dl->localname)) + CL_SendDownloadRequest(dl->name, dl->localname); else { - Con_Printf("Already have %s\n", cl.downloadlist->localname); - CL_DisenqueDownload(cl.downloadlist->name); + Con_Printf("Already have %s\n", dl->localname); + CL_DisenqueDownload(dl->name); + + //recurse a bit. + CL_RequestNextDownload(); + return; } - if (requiredownloads.value || !cl.worldmodel) + + if (requiredownloads.value || (dl->flags & DLLF_REQUIRED)) return; } if (cl.sendprespawn) { // get next signon phase - - if (CL_LoadModels(0) < 0) + stage = 0; + stage = CL_LoadModels(stage); + if (stage < 0) return; //not yet + stage = CL_LoadSounds(stage); + if (stage < 0) + return; cl.sendprespawn = false; #ifdef _MSC_VER @@ -984,14 +1212,15 @@ void CL_SendDownloadReq(sizebuf_t *msg) #ifdef PEXT_CHUNKEDDOWNLOADS if (cls.downloadmethod == DL_QWCHUNKS) { - int i = CL_RequestADownloadChunk(); - if (i < 0) + extern int download_file_number; + int p; + for (p = 0; p < 8; p++) { - //we can stop downloading now. - } - else - { - CL_SendClientCommand(false, "nextdl %i\n", i); + int i = CL_RequestADownloadChunk(); + if (i >= 0) + CL_SendClientCommand(false, "nextdl %i - %i\n", i, download_file_number); + else + break;//we can stop downloading now. } return; } @@ -1044,16 +1273,44 @@ char *ZLibDownloadDecode(int *messagesize, char *input, int finalsize) } #endif -void CL_DownloadFailed(char *name) +downloadlist_t *CL_DownloadFailed(char *name) { //add this to our failed list. (so we don't try downloading it again...) - downloadlist_t *failed; + downloadlist_t *failed, **link, *dl; failed = Z_Malloc(sizeof(downloadlist_t)); failed->next = cl.faileddownloads; cl.faileddownloads = failed; Q_strncpyz(failed->name, name, sizeof(failed->name)); - cls.downloadmethod = DL_NONE; + //if this is what we're currently downloading, close it up now. + if (!stricmp(cls.downloadname, name) || !*name) + { + cls.downloadmethod = DL_NONE; + + if (cls.downloadqw) + { + VFS_CLOSE(cls.downloadqw); + cls.downloadqw = NULL; + CL_SendClientCommand(true, "stopdownload"); + } + *cls.downloadname = 0; + } + + link = &cl.downloadlist; + while(*link) + { + dl = *link; + if (!strcmp(dl->name, name)) + { + *link = dl->next; + failed->flags |= dl->flags; + Z_Free(dl); + } + else + link = &(*link)->next; + } + + return failed; } float downloadstarttime; @@ -1065,6 +1322,13 @@ int receivedbytes; int recievedblock[MAXBLOCKS]; int firstblock; int blockcycle; +int download_file_number; + +int CL_DownloadRate(void) +{ + return receivedbytes/(Sys_DoubleTime() - downloadstarttime); +} + void CL_ParseChunkedDownload(void) { qbyte *svname; @@ -1081,12 +1345,26 @@ void CL_ParseChunkedDownload(void) if (cls.demoplayback) return; + if (!*svname) + { + //stupid mvdsv. + /*if (totalsize < 0) + svname = cls.downloadname; + else*/ + { + Con_Printf("ignoring nameless download\n"); + return; + } + } + if (totalsize < 0) { - if (totalsize == -2) - Con_Printf("Server permissions deny downloading file %s\n", svname); + if (totalsize == -3) + Con_Printf("Server reported an error when downloading file \"%s\"\n", svname); + else if (totalsize == -2) + Con_Printf("Server permissions deny downloading file \"%s\"\n", svname); else - Con_Printf("Couldn't find file %s on the server\n", svname); + Con_Printf("Couldn't find file \"%s\" on the server\n", svname); CL_DownloadFailed(svname); @@ -1132,6 +1410,7 @@ void CL_ParseChunkedDownload(void) return; } + download_file_number++; firstblock = 0; receivedbytes = 0; blockcycle = -1; //so it requests 0 first. :) @@ -1203,7 +1482,7 @@ int CL_RequestADownloadChunk(void) if (cls.downloadmethod != DL_QWCHUNKS) { Con_Printf("download not initiated\n"); - return 0; + return -1; } blockcycle++; @@ -1223,13 +1502,14 @@ int CL_RequestADownloadChunk(void) // Con_Printf("^1 EOF?\n"); VFS_CLOSE(cls.downloadqw); + cls.downloadqw = NULL; + CL_SendClientCommand(true, "stopdownload"); - CL_FinishDownload(cls.downloadname, cls.downloadtempname); + CL_DownloadFinished(cls.downloadname, cls.downloadtempname); Con_Printf("Download took %i seconds (%i more)\n", (int)(Sys_DoubleTime() - downloadstarttime), CL_CountQueuedDownloads()); *cls.downloadname = '\0'; - cls.downloadqw = NULL; cls.downloadpercent = 0; return -1; @@ -1326,6 +1606,7 @@ void CL_ParseDownload (void) } downloadstarttime = Sys_DoubleTime(); + receivedbytes = 0; SCR_EndLoadingPlaque(); } #ifdef PEXT_ZLIBDL @@ -1346,6 +1627,10 @@ void CL_ParseDownload (void) msg_readcount += size; } + receivedbytes += size; + if (cls.downloadpercent != percent) //try and guess the size (its most acurate when the percent value changes) + downloadsize = ((float)receivedbytes*100)/percent; + if (cls.downloadmethod == DL_QWPENDING) cls.downloadmethod = DL_QW; @@ -1367,7 +1652,7 @@ void CL_ParseDownload (void) { VFS_CLOSE (cls.downloadqw); - CL_FinishDownload(cls.downloadname, cls.downloadtempname); + CL_DownloadFinished(cls.downloadname, cls.downloadtempname); *cls.downloadname = '\0'; cls.downloadqw = NULL; cls.downloadpercent = 0; @@ -1380,6 +1665,18 @@ void CL_ParseDownload (void) } } +qboolean CL_ParseOOBDownload(void) +{ + if (MSG_ReadLong() != download_file_number) + return false; + + if (MSG_ReadChar() != svc_download) + return false; + + CL_ParseDownload(); + return true; +} + void CLDP_ParseDownloadData(void) { unsigned char buffer[1<<16]; @@ -1486,7 +1783,7 @@ void CLDP_ParseDownloadFinished(char *s) return; } - CL_FinishDownload(cls.downloadname, cls.downloadtempname); + CL_DownloadFinished(cls.downloadname, cls.downloadtempname); *cls.downloadname = '\0'; cls.downloadqw = NULL; cls.downloadpercent = 0; @@ -1700,7 +1997,7 @@ void CL_ParseServerData (void) } CL_ClearState (); - Cvar_ForceCallback(&r_particlesdesc); + Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc")); Stats_NewMap(); cl.servercount = svcnt; @@ -1914,7 +2211,7 @@ void CLQ2_ParseServerData (void) //cl.refresh_prepped = false; } - Cvar_ForceCallback(&r_particlesdesc); + Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc")); if (R_PreNewMap) R_PreNewMap(); @@ -1927,16 +2224,15 @@ void CLQ2_ParseServerData (void) void CL_KeepaliveMessage(void){} void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. { - int nummodels, numsounds, i; + int nummodels, numsounds; char *str; + int gametype; int protover; if (developer.value) Con_TPrintf (TLC_GOTSVDATAPACKET); CL_ClearState (); Stats_NewMap(); - Cvar_ForceCallback(&r_particlesdesc); - - Info_SetValueForStarKey(cl.serverinfo, "*csprogs", va("%i", cl_dp_csqc_progscrc), sizeof(cl.serverinfo)); + Cvar_ForceCallback(Cvar_FindVar("r_particlesdesc")); protover = MSG_ReadLong (); @@ -1996,7 +2292,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. cl.splitclients = 1; CL_RegisterSplitCommands(); - /*cl.gametype =*/ MSG_ReadByte (); + gametype = MSG_ReadByte (); str = MSG_ReadString (); Q_strncpyz (cl.levelname, str, sizeof(cl.levelname)); @@ -2022,9 +2318,8 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. return; } strcpy (cl.model_name[nummodels], str); + CL_CheckOrEnqueDownloadFile(str, NULL, 0); Mod_TouchModel (str); - -// cl.model_precache[nummodels] = Mod_ForName (cl.model_name[nummodels], false); } memset (cl.sound_name, 0, sizeof(cl.sound_name)); @@ -2040,47 +2335,34 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } strcpy (cl.sound_name[numsounds], str); S_TouchSound (str); - -// cl.sound_precache[numsounds] = S_PrecacheSound (cl.sound_name[numsounds]); } -// -// now we try to load everything else until a cache allocation fails -// + cls.signon = 0; + cls.state = ca_onserver; - for (i=1 ; iDelinkTrailstate (&cl_static_emit[i]); break; } @@ -2682,7 +2963,7 @@ void CL_ParseStatic (int version) // copy it to the current state ent->model = cl.model_precache[es.modelindex]; - ent->oldframe = ent->frame = es.frame; + ent->frame2 = ent->frame1 = es.frame; #ifdef SWQUAKE ent->palremap = D_IdentityRemap(); #endif @@ -2877,6 +3158,9 @@ void CLQ2_ParseStartSoundPacket(void) #ifdef NQPROT #define NQSND_VOLUME (1<<0) // a qbyte #define NQSND_ATTENUATION (1<<1) // a qbyte +#define DPSND_LOOPING (1<<2) // a long, supposedly +#define DPSND_LARGEENTITY (1<<3) +#define DPSND_LARGESOUND (1<<4) void CLNQ_ParseStartSoundPacket(void) { vec3_t pos; @@ -2899,11 +3183,22 @@ void CLNQ_ParseStartSoundPacket(void) else attenuation = DEFAULT_SOUND_PACKET_ATTENUATION; - channel = MSG_ReadShort (); - sound_num = MSG_ReadByte (); + if (field_mask & DPSND_LARGEENTITY) + { + ent = (unsigned short)MSG_ReadShort(); + channel = MSG_ReadByte(); + } + else + { //regular + channel = MSG_ReadShort (); + ent = channel >> 3; + channel &= 7; + } - ent = channel >> 3; - channel &= 7; + if (field_mask & DPSND_LARGESOUND) + sound_num = (unsigned short)MSG_ReadShort(); + else + sound_num = MSG_ReadByte (); if (ent > MAX_EDICTS) Host_EndGame ("CL_ParseStartSoundPacket: ent = %i", ent); @@ -3612,9 +3907,13 @@ char *CL_ParseChat(char *text, player_info_t **player) return NULL; #endif - if (flags == 2 && !TP_FilterMessage(text + offset)) + if (flags & (TPM_TEAM|TPM_OBSERVEDTEAM) && !TP_FilterMessage(text + offset)) return NULL; + if (flags & (TPM_TEAM|TPM_OBSERVEDTEAM) && Sbar_UpdateTeamStatus(*player, text+offset)) + return NULL; + + if ((int)msg_filter.value & flags) return NULL; //filter chat @@ -3643,7 +3942,7 @@ char *CL_ParseChat(char *text, player_info_t **player) if (!suppress_talksound) { - if (flags == 2 && cl.teamplay) + if (flags & (TPM_OBSERVEDTEAM|TPM_TEAM) && cl.teamplay) S_LocalSound (cl_teamchatsound.string); else S_LocalSound (cl_enemychatsound.string); @@ -3815,7 +4114,7 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) if (plrflags & TPM_SPECTATOR) // is an observer { // TODO: we don't even check for this yet... - if (plrflags & TPM_TEAM) // is on team + if (plrflags & (TPM_TEAM | TPM_OBSERVEDTEAM)) // is on team c = 0; // blacken () on observers else { @@ -3846,7 +4145,7 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) Con_Printf ("* "); } - if (plrflags & TPM_TEAM) // for team chat don't highlight the name, just the brackets + if (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)) // for team chat don't highlight the name, just the brackets { // color is reset every printf so we're safe here con_ormask = name_ormask; @@ -3877,7 +4176,7 @@ void CL_PrintChat(player_info_t *plr, char *rawmsg, char *msg, int plrflags) // print message con_ormask = CON_HIGHCHARSMASK; - if (cl_parsewhitetext.value && (cl_parsewhitetext.value == 1 || (plrflags & TPM_TEAM))) + if (cl_parsewhitetext.value && (cl_parsewhitetext.value == 1 || (plrflags & (TPM_TEAM|TPM_OBSERVEDTEAM)))) { char *t, *u; @@ -4060,7 +4359,7 @@ void CL_ParsePrecache(void) if (i >= 1 && i < MAX_MODELS) { model_t *model; - CL_CheckOrEnqueDownloadFile(s, s); + CL_CheckOrEnqueDownloadFile(s, s, 0); model = Mod_ForName(s, i == 1); if (!model) Con_Printf("svc_precache: Mod_ForName(\"%s\") failed\n", s); @@ -4076,7 +4375,7 @@ void CL_ParsePrecache(void) if (i >= 1 && i < MAX_SOUNDS) { sfx_t *sfx; - CL_CheckOrEnqueDownloadFile(va("sound/%s", s), NULL); + CL_CheckOrEnqueDownloadFile(va("sound/%s", s), NULL, 0); sfx = S_PrecacheSound (s); if (!sfx) Con_Printf("svc_precache: S_PrecacheSound(\"%s\") failed\n", s); @@ -4111,7 +4410,7 @@ void CL_DumpPacket(void) { if (pos >= net_message.cursize) Con_Printf("X"); - else if (packet[pos] == 0) + else if (packet[pos] == 0 || packet[pos] == '\n') Con_Printf("."); else Con_Printf("%c", (unsigned char)packet[pos]); @@ -4254,7 +4553,7 @@ void CL_ParseServerMessage (void) #ifdef PLUGINS if (Plug_CenterPrintMessage(s, destsplit)) #endif - SCR_CenterPrint (destsplit, s); + SCR_CenterPrint (destsplit, s, false); break; case svc_stufftext: @@ -4275,8 +4574,10 @@ void CL_ParseServerMessage (void) #ifdef PEXT_SETVIEW case svc_setview: if (!(cls.fteprotocolextensions & PEXT_SETVIEW)) - Host_EndGame("PEXT_SETVIEW is meant to be disabled\n"); + Con_Printf("^1PEXT_SETVIEW is meant to be disabled\n"); cl.viewentity[destsplit]=MSG_ReadShort(); + if (cl.viewentity[destsplit] == cl.playernum[destsplit]+1) + cl.viewentity[destsplit] = 0; break; #endif case svc_setangle: @@ -4464,7 +4765,7 @@ void CL_ParseServerMessage (void) cl.intermission = 2; cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen - SCR_CenterPrint (destsplit, MSG_ReadString ()); + SCR_CenterPrint (destsplit, MSG_ReadString (), false); break; case svc_sellscreen: @@ -4608,6 +4909,16 @@ void CL_ParseServerMessage (void) case svcfte_precache: CL_ParsePrecache(); break; + + case svcfte_trailparticles: + CLDP_ParseTrailParticles(true); + break; + case svcfte_pointparticles: + CLDP_ParsePointParticles(false); + break; + case svcfte_pointparticles1: + CLDP_ParsePointParticles(true); + break; } } } @@ -4757,7 +5068,7 @@ void CLQ2_ParseServerMessage (void) #ifdef PLUGINS if (Plug_CenterPrintMessage(s, 0)) #endif - SCR_CenterPrint (0, s); + SCR_CenterPrint (0, s, false); break; case svcq2_download: //16 // [short] size [size bytes] CL_ParseDownload(); @@ -4979,7 +5290,7 @@ void CLNQ_ParseServerMessage (void) #ifdef PLUGINS if (Plug_CenterPrintMessage(s, 0)) #endif - SCR_CenterPrint (0, s); + SCR_CenterPrint (0, s, false); break; case svc_stufftext: @@ -5000,9 +5311,7 @@ void CLNQ_ParseServerMessage (void) else if (!strncmp(s, "\ncl_downloadfinished ", 17)) CLDP_ParseDownloadFinished(s); else if (!strncmp(s, "csqc_progname ", 14)) - { -// Info_SetValueForStarKey(cl.serverinfo, "*cspname", s+14, sizeof(cl.serverinfo)); - } + COM_ParseOut(s+14, cl_dp_csqc_progsname, sizeof(cl_dp_csqc_progsname)); else if (!strncmp(s, "csqc_progsize ", 14)) cl_dp_csqc_progssize = atoi(s+14); else if (!strncmp(s, "csqc_progcrc ", 13)) @@ -5204,14 +5513,14 @@ void CLNQ_ParseServerMessage (void) cl.intermission = 2; cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen - SCR_CenterPrint (0, MSG_ReadString ()); + SCR_CenterPrint (0, MSG_ReadString (), false); break; case svc_cutscene: cl.intermission = 3; cl.completed_time = cl.servertime; vid.recalc_refdef = true; // go to full screen - SCR_CenterPrint (0, MSG_ReadString ()); + SCR_CenterPrint (0, MSG_ReadString (), false); break; case svc_sellscreen: //pantsie @@ -5246,6 +5555,16 @@ void CLNQ_ParseServerMessage (void) case svcdp_downloaddata: CLDP_ParseDownloadData(); break; + + case svcdp_trailparticles: + CLDP_ParseTrailParticles(); + break; + case svcdp_pointparticles: + CLDP_ParsePointParticles(false); + break; + case svcdp_pointparticles1: + CLDP_ParsePointParticles(true); + break; } } diff --git a/engine/client/cl_plugin.inc b/engine/client/cl_plugin.inc index e7ba68d7e..e8cfff0a2 100644 --- a/engine/client/cl_plugin.inc +++ b/engine/client/cl_plugin.inc @@ -59,7 +59,7 @@ int VARGS Plug_SCR_CenterPrint(void *offset, unsigned int mask, const int *arg) if (qrenderer <= 0) return 0; - SCR_CenterPrint(0, VM_POINTER(arg[0])); + SCR_CenterPrint(0, VM_POINTER(arg[0]), true); return 0; } int VARGS Plug_Media_ShowFrameRGBA_32(void *offset, unsigned int mask, const int *arg) diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 5962f4a85..83ba4fad7 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -400,7 +400,7 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user pmove.onladder = false; pmove.hullnum = from->hullnum; - if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3 || pmove.hullnum > MAX_MAP_HULLSM) + if (cl.worldmodel->fromgame != fg_quake) { player_mins[0] = -16; player_mins[1] = -16; @@ -418,7 +418,7 @@ void CL_PredictUsercmd (int pnum, player_state_t *from, player_state_t *to, user VectorCopy(cl.worldmodel->hulls[pmove.hullnum].clip_maxs, player_maxs); } if (DEFAULT_VIEWHEIGHT > player_maxs[2]) - { + { //this hack is for hexen2. player_maxs[2] -= player_mins[2]; player_mins[2] = 0; } diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 8e3eac4b5..9d44a69b1 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -431,12 +431,15 @@ Called for important messages that should stay in the center of the screen for a few moments ============== */ -void SCR_CenterPrint (int pnum, char *str) +void SCR_CenterPrint (int pnum, char *str, qboolean fromgamecode) { + if (!fromgamecode) + { #ifdef CSQC_DAT - if (CSQC_CenterPrint(str)) //csqc nabbed it. - return; + if (CSQC_CenterPrint(str)) //csqc nabbed it. + return; #endif + } if (Cmd_AliasExist("f_centerprint", RESTRICT_LOCAL)) { @@ -808,7 +811,7 @@ void SCR_ShowPic_Create(void) sp->x = MSG_ReadShort(); sp->y = MSG_ReadShort(); - CL_CheckOrEnqueDownloadFile(sp->picname, sp->picname); + CL_CheckOrEnqueDownloadFile(sp->picname, sp->picname, 0); } void SCR_ShowPic_Hide(void) @@ -856,7 +859,7 @@ void SCR_ShowPic_Update(void) sp->picname = Z_Malloc(strlen(s)+1); strcpy(sp->picname, s); - CL_CheckOrEnqueDownloadFile(sp->picname, sp->picname); + CL_CheckOrEnqueDownloadFile(sp->picname, sp->picname, 0); } void SCR_ShowPic_Script_f(void) @@ -1442,7 +1445,11 @@ void SCR_DrawLoading (void) { if(Draw_ScalePic) Draw_ScalePic(0, 0, vid.width, vid.height, Draw_SafeCachePic (levelshotname)); + else + Draw_ConsoleBackground(vid.height); } + else + Draw_ConsoleBackground(vid.height); if (COM_FDepthFile("gfx/loading.lmp", true) < COM_FDepthFile("gfx/menu/loading.lmp", true)) { //quake files diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 5e82f9b4f..e7f120eaf 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -25,6 +25,64 @@ entity_state_t *CL_FindPacketEntity(int num); #define R_AddDecals(a) //disabled for now +int + pt_gunshot=P_INVALID, + ptdp_gunshotquad=P_INVALID, + pt_spike=P_INVALID, + ptdp_spikequad=P_INVALID, + pt_superspike=P_INVALID, + ptdp_superspikequad=P_INVALID, + pt_wizspike=P_INVALID, + pt_knightspike=P_INVALID, + pt_explosion=P_INVALID, + ptdp_explosionquad=P_INVALID, + pt_tarexplosion=P_INVALID, + pt_teleportsplash=P_INVALID, + pt_lavasplash=P_INVALID, + ptdp_smallflash=P_INVALID, + ptdp_flamejet=P_INVALID, + ptdp_flame=P_INVALID, + ptdp_blood=P_INVALID, + ptdp_spark=P_INVALID, + ptdp_plasmaburn=P_INVALID, + ptdp_tei_g3=P_INVALID, + ptdp_tei_smoke=P_INVALID, + ptdp_tei_bigexplosion=P_INVALID, + ptdp_tei_plasmahit=P_INVALID, + ptdp_stardust=P_INVALID, + rt_rocket=P_INVALID, + rt_grenade=P_INVALID, + rt_blood=P_INVALID, + rt_wizspike=P_INVALID, + rt_slightblood=P_INVALID, + rt_knightspike=P_INVALID, + rt_vorespike=P_INVALID, + rtdp_neharasmoke=P_INVALID, + rtdp_nexuizplasma=P_INVALID, + rtdp_glowtrail=P_INVALID, + + ptqw_blood=P_INVALID, + ptqw_lightningblood=P_INVALID, + + ptq2_blood=P_INVALID, + rtq2_railtrail=P_INVALID, + rtq2_blastertrail=P_INVALID, + ptq2_blasterparticles=P_INVALID, + rtq2_bubbletrail=P_INVALID, + rtq2_gib=P_INVALID, + rtq2_rocket=P_INVALID, + rtq2_grenade=P_INVALID, + + rtqw_railtrail=P_INVALID, + rtfte_lightning1=P_INVALID, + ptfte_lightning1_end=P_INVALID, + rtfte_lightning2=P_INVALID, + ptfte_lightning2_end=P_INVALID, + rtfte_lightning3=P_INVALID, + ptfte_lightning3_end=P_INVALID, + ptfte_bullet=P_INVALID, + ptfte_superbullet=P_INVALID; + #ifdef Q2CLIENT typedef enum { @@ -219,6 +277,67 @@ void CL_InitTEnts (void) Cvar_Register (&r_explosionlight, "Temporary entity control"); } +void CL_RegisterParticles(void) +{ + pt_gunshot = P_ParticleTypeForName("TE_GUNSHOT"); /*shotgun*/ + ptdp_gunshotquad = P_ParticleTypeForName("TE_GUNSHOTQUAD"); /*DP: quadded shotgun*/ + pt_spike = P_ParticleTypeForName("TE_SPIKE"); /*nailgun*/ + ptdp_spikequad = P_ParticleTypeForName("TE_SPIKEQUAD"); /*DP: quadded nailgun*/ + pt_superspike = P_ParticleTypeForName("TE_SUPERSPIKE"); /*nailgun*/ + ptdp_superspikequad = P_ParticleTypeForName("TE_SUPERSPIKEQUAD"); /*DP: quadded nailgun*/ + pt_wizspike = P_ParticleTypeForName("TE_WIZSPIKE"); //scrag missile impact + pt_knightspike = P_ParticleTypeForName("TE_KNIGHTSPIKE"); //hellknight missile impact + pt_explosion = P_ParticleTypeForName("TE_EXPLOSION");/*rocket/grenade launcher impacts/far too many things*/ + ptdp_explosionquad = P_ParticleTypeForName("TE_EXPLOSIONQUAD"); /*nailgun*/ + pt_tarexplosion = P_ParticleTypeForName("TE_TAREXPLOSION");//tarbaby/spawn dying. + pt_teleportsplash = P_ParticleTypeForName("TE_TELEPORT");/*teleporters*/ + pt_lavasplash = P_ParticleTypeForName("TE_LAVASPLASH"); //e1m7 boss dying. + ptdp_smallflash = P_ParticleTypeForName("TE_SMALLFLASH"); //DP: + ptdp_flamejet = P_ParticleTypeForName("TE_FLAMEJET"); //DP: + ptdp_flame = P_ParticleTypeForName("EF_FLAME"); //DP: + ptdp_blood = P_ParticleTypeForName("TE_BLOOD"); /*when you hit something with the shotgun/axe/nailgun - nq uses the general particle builtin*/ + ptdp_spark = P_ParticleTypeForName("TE_SPARK");//DPTE_SPARK + ptdp_plasmaburn = P_ParticleTypeForName("TE_PLASMABURN"); + ptdp_tei_g3 = P_ParticleTypeForName("TE_TEI_G3"); + ptdp_tei_smoke = P_ParticleTypeForName("TE_TEI_SMOKE"); + ptdp_tei_bigexplosion = P_ParticleTypeForName("TE_TEI_BIGEXPLOSION"); + ptdp_tei_plasmahit = P_ParticleTypeForName("TE_TEI_PLASMAHIT"); + ptdp_stardust = P_ParticleTypeForName("EF_STARDUST"); + rt_rocket = P_ParticleTypeForName("TR_ROCKET"); /*rocket trail*/ + rt_grenade = P_ParticleTypeForName("TR_GRENADE"); /*grenade trail*/ + rt_blood = P_ParticleTypeForName("TR_BLOOD"); /*blood trail*/ + rt_wizspike = P_ParticleTypeForName("TR_WIZSPIKE"); + rt_slightblood = P_ParticleTypeForName("TR_SLIGHTBLOOD"); + rt_knightspike = P_ParticleTypeForName("TR_KNIGHTSPIKE"); + rt_vorespike = P_ParticleTypeForName("TR_VORESPIKE"); + rtdp_neharasmoke = P_ParticleTypeForName("TR_NEHAHRASMOKE"); + rtdp_nexuizplasma = P_ParticleTypeForName("TR_NEXUIZPLASMA"); + rtdp_glowtrail = P_ParticleTypeForName("TR_GLOWTRAIL"); + /*internal to psystem*/ P_ParticleTypeForName("SVC_PARTICLE"); + + ptqw_blood = P_ParticleTypeForName("TE_BLOOD"); + ptqw_lightningblood = P_ParticleTypeForName("TE_LIGHTNINGBLOOD"); + + ptq2_blood = P_ParticleTypeForName("TE_BLOOD"); + rtq2_railtrail = P_ParticleTypeForName("TR_RAILTRAIL"); + rtq2_blastertrail = P_ParticleTypeForName("TR_BLASTERTRAIL"); + ptq2_blasterparticles = P_ParticleTypeForName("TE_BLASTERPARTICLES"); + rtq2_bubbletrail = P_ParticleTypeForName("TE_BUBBLETRAIL"); + rtq2_gib = P_ParticleTypeForName("TR_GIB"); + rtq2_rocket = P_ParticleTypeForName("TR_ROCKET"); + rtq2_grenade = P_ParticleTypeForName("TR_GRENADE"); + + rtqw_railtrail = P_ParticleTypeForName("TE_RAILTRAIL"); + rtfte_lightning1 = P_ParticleTypeForName("TE_LIGHTNING1"); + ptfte_lightning1_end = P_ParticleTypeForName("TE_LIGHTNING1_END"); + rtfte_lightning2 = P_ParticleTypeForName("TE_LIGHTNING2"); + ptfte_lightning2_end = P_ParticleTypeForName("TE_LIGHTNING2_END"); + rtfte_lightning3 = P_ParticleTypeForName("TE_LIGHTNING3"); + ptfte_lightning3_end = P_ParticleTypeForName("TE_LIGHTNING3_END"); + ptfte_bullet = P_ParticleTypeForName("TE_BULLET"); + ptfte_superbullet = P_ParticleTypeForName("TE_SUPERBULLET"); +} + #ifdef Q2CLIENT enum { q2cl_mod_explode, @@ -368,14 +487,14 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n if (ent < 0 && ent >= -512) //a zquake concept. ent between -1 and -maxplayers is to be taken to be a railtrail from a particular player instead of a beam. { // TODO: add support for those finnicky colored railtrails... - if (P_ParticleTrail(start, end, rt_railtrail, NULL)) + if (P_ParticleTrail(start, end, rtqw_railtrail, NULL)) P_ParticleTrailIndex(start, end, 208, 8, NULL); return; } default: m = Mod_ForName("progs/bolt.mdl", false); - btype = rt_lightning1; - etype = pt_lightning1_end; + btype = rtfte_lightning1; + etype = ptfte_lightning1_end; break; case 1: if (ent < 0 && ent >= -MAX_CLIENTS) //based on the railgun concept - this adds a rogue style TE_BEAM effect. @@ -388,14 +507,14 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n else { m = Mod_ForName("progs/bolt2.mdl", false); - btype = rt_lightning2; - etype = pt_lightning2_end; + btype = rtfte_lightning2; + etype = ptfte_lightning2_end; } break; case 2: m = Mod_ForName("progs/bolt3.mdl", false); - btype = rt_lightning3; - etype = pt_lightning3_end; + btype = rtfte_lightning3; + etype = ptfte_lightning3_end; break; #ifdef Q2CLIENT case 3: @@ -424,7 +543,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n } } - if (etype >= 0 && cls.state == ca_active && P_TypeIsLoaded(etype)) + if (etype >= 0 && cls.state == ca_active && etype != P_INVALID) { if (cl_beam_trace.value) { @@ -530,12 +649,12 @@ void CL_ParseStream (int type) case TE_STREAM_ICECHUNKS: b->model = Mod_ForName("models/stice.mdl", true); b->flags |= 2; - b->particleeffect = P_AllocateParticleType("te_stream_icechunks"); + b->particleeffect = P_FindParticleType("te_stream_icechunks"); R_AddStain(end, -10, -10, 0, 20); break; case TE_STREAM_SUNSTAFF1: b->model = Mod_ForName("models/stsunsf1.mdl", true); - b->particleeffect = P_AllocateParticleType("te_stream_sunstaff1"); + b->particleeffect = P_FindParticleType("te_stream_sunstaff1"); if (b->particleeffect < 0) { b2 = CL_NewBeam(ent, tag+128); @@ -549,7 +668,7 @@ void CL_ParseStream (int type) break; case TE_STREAM_SUNSTAFF2: b->model = Mod_ForName("models/stsunsf1.mdl", true); - b->particleeffect = P_AllocateParticleType("te_stream_sunstaff2"); + b->particleeffect = P_FindParticleType("te_stream_sunstaff2"); R_AddStain(end, -10, -10, -10, 20); break; } @@ -578,6 +697,17 @@ void CL_ParseTEnt (void) int cnt, colour; type = MSG_ReadByte (); + +#ifdef CSQC_DAT + if (type != TE_GUNSHOT) + { + //I know I'm going to regret this. + if (CSQC_ParseTempEntity((unsigned char)type)) + return; + } +#endif + + switch (type) { case TE_WIZSPIKE: // spike hitting wall @@ -614,7 +744,7 @@ void CL_ParseTEnt (void) R_AddStain(pos, -10, -10, -10, 20); R_AddDecals(pos); - if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_spikequad")) + if (P_RunParticleEffectType(pos, NULL, 1, ptdp_spikequad)) if (P_RunParticleEffectType(pos, NULL, 1, pt_spike)) if (P_RunParticleEffectType(pos, NULL, 10, pt_gunshot)) P_RunParticleEffect (pos, vec3_origin, 0, 10); @@ -665,7 +795,7 @@ void CL_ParseTEnt (void) R_AddStain(pos, -10, -10, -10, 20); R_AddDecals(pos); - if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_superspikequad")) + if (P_RunParticleEffectType(pos, NULL, 1, ptdp_superspikequad)) if (P_RunParticleEffectType(pos, NULL, 1, pt_superspike)) if (P_RunParticleEffectType(pos, NULL, 2, pt_spike)) if (P_RunParticleEffectType(pos, NULL, 20, pt_gunshot)) @@ -722,7 +852,7 @@ void CL_ParseTEnt (void) R_AddStain(pos, -10, -10, -10, 20); R_AddDecals(pos); - if (P_RunParticleEffectType(pos, NULL, 1, pt_bullet)) + if (P_RunParticleEffectType(pos, NULL, 1, ptfte_bullet)) if (P_RunParticleEffectType(pos, NULL, 10, pt_gunshot)) P_RunParticleEffect (pos, vec3_origin, 0, 10); @@ -747,8 +877,8 @@ void CL_ParseTEnt (void) R_AddStain(pos, -10, -10, -10, 20); R_AddDecals(pos); - if (P_RunParticleEffectType(pos, NULL, 1, pt_superbullet)) - if (P_RunParticleEffectType(pos, NULL, 2, pt_bullet)) + if (P_RunParticleEffectType(pos, NULL, 1, ptfte_superbullet)) + if (P_RunParticleEffectType(pos, NULL, 2, ptfte_bullet)) if (P_RunParticleEffectType(pos, NULL, 20, pt_gunshot)) P_RunParticleEffect (pos, vec3_origin, 0, 20); @@ -772,7 +902,7 @@ void CL_ParseTEnt (void) pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); - if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_explosionquad")) + if (P_RunParticleEffectType(pos, NULL, 1, ptdp_explosionquad)) if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion)) P_RunParticleEffect(pos, NULL, 107, 1024); // should be 97-111 @@ -883,7 +1013,7 @@ void CL_ParseTEnt (void) pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); - if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_tei_bigexplosion")) + if (P_RunParticleEffectType(pos, NULL, 1, ptdp_tei_bigexplosion)) if (P_RunParticleEffectType(pos, NULL, 1, pt_explosion)) P_RunParticleEffect(pos, NULL, 107, 1024); // should be 97-111 @@ -914,7 +1044,7 @@ void CL_ParseTEnt (void) pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); - P_BlobExplosion (pos); + P_RunParticleEffectType(pos, NULL, 1, pt_tarexplosion); S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1); break; @@ -931,7 +1061,7 @@ void CL_ParseTEnt (void) pos[0] = MSG_ReadCoord (); pos[1] = MSG_ReadCoord (); pos[2] = MSG_ReadCoord (); - P_LavaSplash (pos); + P_RunParticleEffectType(pos, NULL, 1, pt_lavasplash); break; case TE_TELEPORT: @@ -948,7 +1078,7 @@ void CL_ParseTEnt (void) R_AddStain(pos, -10, -10, -10, 20); - if (P_RunParticleEffectTypeString(pos, NULL, 1, "te_gunshotquad")) + if (P_RunParticleEffectType(pos, NULL, 1, ptdp_gunshotquad)) if (P_RunParticleEffectType(pos, NULL, 1, pt_gunshot)) P_RunParticleEffect (pos, vec3_origin, 0, 20); @@ -977,8 +1107,9 @@ void CL_ParseTEnt (void) R_AddStain(pos, 0, -10, -10, 40); - if (P_RunParticleEffectType(pos, NULL, cnt, pt_blood)) - P_RunParticleEffect (pos, vec3_origin, 73, 20*cnt); + if (P_RunParticleEffectType(pos, NULL, cnt, ptqw_blood)) + if (P_RunParticleEffectType(pos, NULL, cnt, ptdp_blood)) + P_RunParticleEffect (pos, vec3_origin, 73, 20*cnt); break; @@ -989,7 +1120,7 @@ void CL_ParseTEnt (void) R_AddStain(pos, 1, -10, -10, 20); - if (P_RunParticleEffectType(pos, NULL, 1, pt_lightningblood)) + if (P_RunParticleEffectType(pos, NULL, 1, ptqw_lightningblood)) P_RunParticleEffect (pos, vec3_origin, 225, 50); break; @@ -1003,8 +1134,9 @@ void CL_ParseTEnt (void) pos2[1] = MSG_ReadCoord (); pos2[2] = MSG_ReadCoord (); - if (P_ParticleTrail(pos, pos2, rt_railtrail, NULL)) - P_ParticleTrailIndex(pos, pos2, 208, 8, NULL); + if (P_ParticleTrail(pos, pos2, rtqw_railtrail, NULL)) + if (P_ParticleTrail(pos, pos2, rtq2_railtrail, NULL)) + P_ParticleTrailIndex(pos, pos2, 208, 8, NULL); break; case TE_STREAM_CHAIN: @@ -1029,7 +1161,7 @@ void CL_ParseTEnt (void) cnt = MSG_ReadByte (); - P_RunParticleEffectType(pos, pos2, cnt, pt_blood); + P_RunParticleEffectType(pos, pos2, cnt, ptdp_blood); break; case DPTE_SPARK: @@ -1043,8 +1175,7 @@ void CL_ParseTEnt (void) cnt = MSG_ReadByte (); { - extern int pt_spark; - P_RunParticleEffectType(pos, pos2, cnt, pt_spark); + P_RunParticleEffectType(pos, pos2, cnt, ptdp_spark); } break; @@ -1118,7 +1249,7 @@ void CL_ParseTEnt (void) // count cnt = MSG_ReadByte (); - if (P_RunParticleEffectTypeString(pos, pos2, cnt, "te_flamejet")) + if (P_RunParticleEffectType(pos, pos2, cnt, ptdp_flamejet)) P_RunParticleEffect (pos, pos2, 232, cnt); break; @@ -1177,8 +1308,7 @@ void CL_ParseTEnt (void) //count cnt = MSG_ReadByte (); { - extern int pt_smoke; - P_RunParticleEffectType(pos, pos2, cnt, pt_smoke); + P_RunParticleEffectType(pos, pos2, cnt, ptdp_tei_smoke); } break; @@ -1194,8 +1324,7 @@ void CL_ParseTEnt (void) cnt = MSG_ReadByte (); { - extern int pt_plasma; - P_RunParticleEffectType(pos, pos2, cnt, pt_plasma); + P_RunParticleEffectType(pos, pos2, cnt, ptdp_tei_plasmahit); } break; @@ -1324,7 +1453,7 @@ void CL_ParseCustomTEnt(void) t->netstyle = MSG_ReadByte(); str = MSG_ReadString(); - t->particleeffecttype = P_AllocateParticleType(str); + t->particleeffecttype = P_ParticleTypeForName(str); if (t->netstyle & CTE_STAINS) { @@ -1431,6 +1560,60 @@ void CL_ClearCustomTEnts(void) customtenttype[i].particleeffecttype = -1; } +void CLDP_ParseTrailParticles(void) +{ + int entityindex; + int effectindex; + vec3_t start, end; + trailstate_t **ts; + + entityindex = (unsigned short)MSG_ReadShort(); + effectindex = (unsigned short)MSG_ReadShort(); + + start[0] = MSG_ReadCoord(); + start[1] = MSG_ReadCoord(); + start[2] = MSG_ReadCoord(); + end[0] = MSG_ReadCoord(); + end[1] = MSG_ReadCoord(); + end[2] = MSG_ReadCoord(); + + if (entityindex && (unsigned int)entityindex < MAX_EDICTS) + ts = &cl.lerpents[entityindex].trailstate; + else + ts = NULL; + + effectindex = P_ParticleTypeForName(COM_Effectinfo_ForNumber(effectindex)); + if (P_ParticleTrail(start, end, effectindex, ts)) + P_ParticleTrail(start, end, rt_blood, ts); +} + +void CLDP_ParsePointParticles(qboolean compact) +{ + vec3_t org, dir; + unsigned int count, effectindex; + + effectindex = (unsigned short)MSG_ReadShort(); + org[0] = MSG_ReadCoord(); + org[1] = MSG_ReadCoord(); + org[2] = MSG_ReadCoord(); + if (compact) + { + dir[0] = dir[1] = dir[2] = 0; + count = 1; + } + else + { + dir[0] = MSG_ReadCoord(); + dir[1] = MSG_ReadCoord(); + dir[2] = MSG_ReadCoord(); + count = (unsigned short)MSG_ReadShort(); + } + + effectindex = P_ParticleTypeForName(COM_Effectinfo_ForNumber(effectindex)); + if (P_RunParticleEffectType(org, dir, count, effectindex)) + P_RunParticleEffect (org, dir, 15, 15); +} + void CLNQ_ParseParticleEffect (void) { vec3_t org, dir; @@ -1612,8 +1795,9 @@ void CLQ2_ParseTEnt (void) case Q2TE_BLOOD: // bullet hitting flesh MSG_ReadPos (pos); MSG_ReadDir (dir); - if (P_RunParticleEffectType(pos, dir, 1, pt_blood)) - P_RunParticleEffect(pos, dir, 0xe8, 60); + if (P_RunParticleEffectType(pos, dir, 1, ptq2_blood)) + if (P_RunParticleEffectType(pos, dir, 1, ptqw_blood)) + P_RunParticleEffect(pos, dir, 0xe8, 60); R_AddStain(pos, 0, -10, -10, 40); break; @@ -1707,7 +1891,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_BLUEHYPERBLASTER: MSG_ReadPos (pos); MSG_ReadPos (dir); - if (P_RunParticleEffectType(pos, dir, 1, pt_blasterparticles)) + if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles)) P_RunParticleEffect (pos, dir, 0xe0, 40); break; @@ -1715,7 +1899,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadPos (pos); MSG_ReadDir (dir); - if (P_RunParticleEffectType(pos, dir, 1, pt_blasterparticles)) + if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles)) P_RunParticleEffect (pos, dir, 0xe0, 40); R_AddStain(pos, 0, -5, -10, 20); @@ -1764,7 +1948,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_RAILTRAIL: // railgun effect MSG_ReadPos (pos); MSG_ReadPos (pos2); - if (P_ParticleTrail(pos, pos2, rt_railtrail, NULL)) + if (P_ParticleTrail(pos, pos2, rtq2_railtrail, NULL)) P_ParticleTrailIndex(pos, pos2, 0x74, 8, NULL); Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/railgf1a.wav"), 1, ATTN_NORM, 0); break; @@ -1971,7 +2155,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_BUBBLETRAIL: MSG_ReadPos (pos); MSG_ReadPos (pos2); - if (P_ParticleTrail(pos, pos2, rt_bubbletrail, NULL)) + if (P_ParticleTrail(pos, pos2, rtq2_bubbletrail, NULL)) P_ParticleTrailIndex(pos, pos2, 4, 8, NULL); break; @@ -2042,7 +2226,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadDir (dir); if (P_RunParticleEffectTypeString(pos, dir, 1, "te_blaster2")) - if (P_RunParticleEffectType(pos, dir, 1, pt_blasterparticles)) + if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles)) P_RunParticleEffect (pos, dir, 0xd0, 40); R_AddStain(pos, -10, 0, -10, 20); @@ -2092,7 +2276,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadDir (dir); if (P_RunParticleEffectTypeString(pos, dir, 1, "te_blaster2")) - if (P_RunParticleEffectType(pos, dir, 1, pt_blasterparticles)) + if (P_RunParticleEffectType(pos, dir, 1, ptq2_blasterparticles)) P_RunParticleEffect (pos, dir, 0x6f, 40); R_AddStain(pos, -10, -2, 0, 20); @@ -2146,7 +2330,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_DEBUGTRAIL: MSG_ReadPos (pos); MSG_ReadPos (pos2); - if (P_ParticleTrail(pos, pos2, P_AllocateParticleType("te_debugtrail"), NULL)) + if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), NULL)) P_ParticleTrailIndex(pos, pos2, 116, 8, NULL); break; @@ -2251,7 +2435,7 @@ void CLQ2_ParseTEnt (void) MSG_ReadPos (pos); MSG_ReadDir (dir); if (P_RunParticleEffectTypeString(pos, dir, 1, "te_moreblood")) - if (P_RunParticleEffectType(pos, dir, 4, pt_blood)) + if (P_RunParticleEffectType(pos, dir, 4, ptqw_blood)) P_RunParticleEffect(pos, dir, 0xe8, 250); break; /* @@ -2673,8 +2857,8 @@ void CL_UpdateExplosions (void) AngleVectors(ent->angles, ent->axis[0], ent->axis[1], ent->axis[2]); VectorInverse(ent->axis[1]); ent->model = ex->model; - ent->frame = (int)f+firstframe; - ent->oldframe = of+firstframe; + ent->frame1 = (int)f+firstframe; + ent->frame2 = of+firstframe; ent->lerpfrac = 1-(f - (int)f); ent->shaderRGBAf[3] = 1.0 - f/(numframes); ent->flags = ex->flags; diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index c20a35995..ccd880d03 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -347,9 +347,12 @@ typedef struct q3refEntity_s { #define Q2RF_DEPTHHACK 16 // for view weapon Z crunching +#define Q3RF_MINLIGHT 1 #define Q3RF_THIRD_PERSON 2 // don't draw through eyes, only mirrors (player bodies, chat sprites) #define Q3RF_FIRST_PERSON 4 // only draw through eyes (view weapon, damage blood blob) #define Q3RF_DEPTHHACK 8 // for view weapon Z crunching +#define Q3RF_NOSHADOW 64 +#define Q3RF_LIGHTING_ORIGIN 128 #define MAX_VMQ3_CACHED_STRINGS 1024 char *stringcache[1024]; @@ -394,8 +397,8 @@ void VQ3_AddEntity(const q3refEntity_t *q3) cl_visedicts = cl_visedicts_list[0]; memset(&ent, 0, sizeof(ent)); ent.model = VM_FROMMHANDLE(q3->hModel); - ent.frame = q3->frame; - ent.oldframe = q3->oldframe; + ent.frame1 = q3->frame; + ent.frame2 = q3->oldframe; memcpy(ent.axis, q3->axis, sizeof(q3->axis)); ent.lerpfrac = q3->backlerp; ent.scale = q3->radius; @@ -409,6 +412,10 @@ void VQ3_AddEntity(const q3refEntity_t *q3) ent.shaderRGBAf[1] = q3->shaderRGBA[1]/255.0f; ent.shaderRGBAf[2] = q3->shaderRGBA[2]/255.0f; ent.shaderRGBAf[3] = q3->shaderRGBA[3]/255.0f; + +// if (ent.shaderRGBAf[3] <= 0) +// return; + #ifdef Q3SHADERS ent.forcedshader = VM_FROMSHANDLE(q3->customShader); ent.shaderTime = q3->shaderTime; diff --git a/engine/client/client.h b/engine/client/client.h index b757ced38..ca2faa0f8 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -140,6 +140,7 @@ typedef struct player_info_s { int userid; char userinfo[EXTENDED_INFO_STRING]; + char teamstatus[128]; // scoreboard information char name[MAX_SCOREBOARDNAME]; @@ -330,16 +331,8 @@ typedef struct char servername[MAX_OSPATH]; // name of server from original connect int qport; - int socketip; - int socketip6; - int socketipx; -#ifdef TCPCONNECT - int sockettcp; - netadr_t sockettcpdest; - unsigned char tcpinbuffer[1500]; - int tcpinlen; -#endif + struct ftenet_connections_s *sockets; enum {DL_NONE, DL_QW, DL_QWCHUNKS, DL_Q3, DL_DARKPLACES, DL_QWPENDING, DL_HTTP, DL_FTP} downloadmethod; vfsfile_t *downloadqw; // file transfer from server @@ -410,6 +403,13 @@ extern int nq_dp_protocol; typedef struct downloadlist_s { char name[128]; char localname[128]; + unsigned int size; + unsigned int flags; +#define DLLF_VERBOSE 1 //tell the user that its downloading +#define DLLF_REQUIRED 2 //means that it won't load models etc until its downloaded (ie: requiredownloads 0 makes no difference) +#define DLLF_OVERWRITE 4 //overwrite it even if it already exists +#define DLLF_SIZEUNKNOWN 8 +#define DLLF_IGNOREFAILED 16 struct downloadlist_s *next; } downloadlist_t; @@ -723,6 +723,7 @@ extern entity_t cl_visedicts_list[2][MAX_VISEDICTS]; extern char emodel_name[], pmodel_name[], prespawn_name[], modellist_name[], soundlist_name[]; qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); +qboolean Q2TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); // // cl_input @@ -810,8 +811,9 @@ void CLNQ_ParseServerMessage (void); void CLQ2_ParseServerMessage (void); #endif void CL_NewTranslation (int slot); -qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname); -qboolean CL_EnqueDownload(char *filename, char *localname, qboolean verbose, qboolean ignorefailedlist); +qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname, unsigned int flags); +qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags); +downloadlist_t *CL_DownloadFailed(char *name); qboolean CL_IsUploading(void); void CL_NextUpload(void); void CL_StartUpload (qbyte *data, int size); @@ -843,6 +845,7 @@ void DropPunchAngle (int pnum); // // cl_tent // +void CL_RegisterParticles(void); void CL_InitTEnts (void); void CL_ClearTEnts (void); void CL_ClearCustomTEnts(void); @@ -854,6 +857,9 @@ void CL_ParseParticleEffect2 (void); void CL_ParseParticleEffect3 (void); void CL_ParseParticleEffect4 (void); +void CLDP_ParseTrailParticles(void); +void CLDP_ParsePointParticles(qboolean compact); + // // cl_ents.c // @@ -901,7 +907,11 @@ void CSQC_RegisterCvarsAndThings(void); qboolean CSQC_DrawView(void); void CSQC_Shutdown(void); qboolean CSQC_StuffCmd(char *cmd); +qboolean CSQC_LoadResource(char *resname, char *restype); qboolean CSQC_CenterPrint(char *cmd); +void CSQC_Input_Frame(usercmd_t *cmd); +void CSQC_WorldLoaded(void); +qboolean CSQC_ParseTempEntity(unsigned char firstbyte); qboolean CSQC_ConsoleCommand(char *cmd); qboolean CSQC_KeyPress(int key, qboolean down); int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation); @@ -953,6 +963,7 @@ void vectoangles(vec3_t vec, vec3_t ang); #define TPM_TEAM 2 #define TPM_SPECTATOR 4 #define TPM_FAKED 16 +#define TPM_OBSERVEDTEAM 32 void CL_Say (qboolean team, char *extra); int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr); @@ -974,6 +985,7 @@ void TP_SearchForMsgTriggers (char *s, int level); qboolean TP_SoundTrigger(char *message); void TP_StatChanged (int stat, int value); qboolean TP_SuppressMessage(char *buf); +colourised_t *TP_FindColours(char *name); // // skin.c @@ -1081,6 +1093,14 @@ struct cin_s *Media_StartCin(char *name); int Media_UpdateForShader(int texnum, cin_t *cin); void Media_ShutdownCin(cin_t *cin); +//these accept NULL for cin to mean the current fullscreen video +void Media_Gecko_KeyPress (struct cin_s *cin, int code, int event); +void Media_Send_Command(cin_t *cin, char *command); +void Media_Send_MouseMove(cin_t *cin, float x, float y); +void Media_Send_Resize(cin_t *cin, int x, int y); +void Media_Send_GetSize(cin_t *cin, int *x, int *y); +void Media_Send_KeyEvent(cin_t *cin, int button, int event); + void MVD_Interpolate(void); int Stats_GetKills(int playernum); diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 073b57607..b25ab55ce 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1354,15 +1354,15 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) // set frame if (effects & Q2EF_ANIM01) - ent.frame = autoanim & 1; + ent.frame1 = autoanim & 1; else if (effects & Q2EF_ANIM23) - ent.frame = 2 + (autoanim & 1); + ent.frame1 = 2 + (autoanim & 1); else if (effects & Q2EF_ANIM_ALL) - ent.frame = autoanim; + ent.frame1 = autoanim; else if (effects & Q2EF_ANIM_ALLFAST) - ent.frame = cl.time / 100; + ent.frame1 = cl.time / 100; else - ent.frame = s1->frame; + ent.frame1 = s1->frame; // quad and pent can do different things on client if (effects & Q2EF_PENT) @@ -1395,7 +1395,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } // pmm //====== - ent.oldframe = cent->prev.frame; + ent.frame2 = cent->prev.frame; ent.lerpfrac = cl.lerpfrac; if (renderfx & (Q2RF_FRAMELERP|Q2RF_BEAM)) @@ -1719,7 +1719,8 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) { if (effects & Q2EF_ROCKET) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_rocket, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xdc, 4, ¢->trailstate); V_AddLight (ent.origin, 200, 0.2, 0.2, 0); @@ -1736,7 +1737,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } else { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blastertrail, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_blastertrail, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe0, 1, ¢->trailstate); V_AddLight (ent.origin, 200, 0.2, 0.2, 0); } @@ -1751,13 +1752,15 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } else if (effects & Q2EF_GIB) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_gib, ¢->trailstate)) - P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe8, 8, ¢->trailstate); + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_gib, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blood, ¢->trailstate)) + P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe8, 8, ¢->trailstate); } else if (effects & Q2EF_GRENADE) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ¢->trailstate)) - P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 4, 8, ¢->trailstate); + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_grenade, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ¢->trailstate)) + P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 4, 8, ¢->trailstate); } else if (effects & Q2EF_FLIES) { @@ -1854,7 +1857,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) { if (effects & Q2EF_ANIM_ALLFAST) { - P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blastertrail, ¢->trailstate); + P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_blastertrail, ¢->trailstate); } V_AddLight (ent.origin, 130, 0.2, 0.1, 0.1); } @@ -1925,11 +1928,11 @@ void CLQ2_AddViewWeapon (q2player_state_t *ps, q2player_state_t *ops) gun.angles[1] = cl_gunangley.value; gun.angles[2] = cl_gunanglez.value; - gun.frame = ps->gunframe; - if (gun.frame == 0) - gun.oldframe = 0; // just changed weapons, don't lerp from old + gun.frame1 = ps->gunframe; + if (gun.frame1 == 0) + gun.frame2 = 0; // just changed weapons, don't lerp from old else - gun.oldframe = ops->gunframe; + gun.frame2 = ops->gunframe; gun.flags = Q2RF_MINLIGHT | Q2RF_DEPTHHACK | Q2RF_WEAPONMODEL; gun.lerpfrac = 1-cl.lerpfrac; diff --git a/engine/client/clq3_parse.c b/engine/client/clq3_parse.c index 468b91c24..b0aa927e7 100644 --- a/engine/client/clq3_parse.c +++ b/engine/client/clq3_parse.c @@ -1,6 +1,7 @@ #include "quakedef.h" #include "shader.h" + //urm, yeah, this is more than just parse. #ifdef Q3CLIENT @@ -536,7 +537,7 @@ void CLQ3_ParseGameState(void) if(msg_badread) { - Host_EndGame("CL_ParseGameState: read past end of server message"); + Host_EndGame("CLQ3_ParseGameState: read past end of server message"); } if(c == svcq3_eom) @@ -549,17 +550,17 @@ void CLQ3_ParseGameState(void) switch(c) { default: - Host_EndGame("CL_ParseGameState: bad command byte"); + Host_EndGame("CLQ3_ParseGameState: bad command byte"); break; case svcq3_configstring: - index = MSG_ReadShort(); + index = MSG_ReadBits(16); if (index < 0 || index >= MAX_Q3_CONFIGSTRINGS) { - Host_EndGame("CL_ParseGameState: configString index %i out of range", index); + Host_EndGame("CLQ3_ParseGameState: configString index %i out of range", index); } configString = MSG_ReadString(); - if (index == 1) + if (index == CFGSTR_SYSINFO) { //check some things. cl.servercount = atoi(Info_ValueForKey(configString, "sv_serverid")); @@ -572,7 +573,7 @@ void CLQ3_ParseGameState(void) index = MSG_ReadBits(GENTITYNUM_BITS); if (index < 0 || index >= MAX_GENTITIES) { - Host_EndGame("CL_ParseGameState: baseline index %i out of range", index); + Host_EndGame("CLQ3_ParseGameState: baseline index %i out of range", index); } MSG_Q3_ReadDeltaEntity(NULL, &ccs.baselines[index], index); break; @@ -582,7 +583,7 @@ void CLQ3_ParseGameState(void) cl.playernum[0] = MSG_ReadLong(); ccs.fs_key = MSG_ReadLong(); - if (!CLQ3_SystemInfoChanged(CG_GetConfigString(1))) + if (!CLQ3_SystemInfoChanged(CG_GetConfigString(CFGSTR_SYSINFO))) return; CG_Restart_f(); diff --git a/engine/client/clq3defs.h b/engine/client/clq3defs.h index d56705c57..51e7930d2 100644 --- a/engine/client/clq3defs.h +++ b/engine/client/clq3defs.h @@ -211,6 +211,7 @@ typedef struct frame_s { #define TEXTCMD_MASK (TEXTCMD_BACKUP-1) #define MAX_Q3_CONFIGSTRINGS 1024 +#define CFGSTR_SYSINFO 1 #define GENTITYNUM_BITS 10 #define MAX_GENTITIES (1<numsurfaces) { progresstext = "light"; - progresspercent = (relitsurface*100.0f) / lightmodel->numsurfaces; + progresspercent = (int)((relitsurface*100.0f) / lightmodel->numsurfaces); + sprintf(progresspercenttext, " %02d%%", progresspercent); } } #endif @@ -1438,17 +1460,18 @@ void Con_DrawConsole (int lines, qboolean noback) else txt = progresstext; - x = curcon->linewidth - ((curcon->linewidth * 7) / 40); - y = x - strlen(txt) - 8; + x = curcon->linewidth;// - ((curcon->linewidth * 7) / 40); + y = x - strlen(txt) - 4; i = curcon->linewidth/3; if (strlen(txt) > i) { - y = x - i - 11; + y = x - i - 7; Q_strncpyN(dlbar, txt, i); strcat(dlbar, "..."); } else strcpy(dlbar, txt); + y -= strlen(progresspercenttext); strcat(dlbar, ": "); i = strlen(dlbar); dlbar[i++] = '\x80'; @@ -1469,7 +1492,7 @@ void Con_DrawConsole (int lines, qboolean noback) dlbar[i++] = '\x82'; dlbar[i] = 0; - sprintf(dlbar + strlen(dlbar), " %02d%%", (int)progresspercent); + strcpy(dlbar + strlen(dlbar), progresspercenttext); // draw it y = curcon->vislines-22 + 8; diff --git a/engine/client/keys.c b/engine/client/keys.c index 2c716a89d..776ef179f 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -58,6 +58,7 @@ void Con_Selectioncolour_Callback(struct cvar_s *var, char *oldvalue); extern cvar_t con_displaypossibilities; cvar_t con_selectioncolour = SCVARFC("con_selectioncolour", "0", CVAR_RENDERERCALLBACK, Con_Selectioncolour_Callback); +cvar_t con_echochat = SCVAR("con_echochat", "0"); extern cvar_t cl_chatmode; static int KeyModifier (qboolean shift, qboolean alt, qboolean ctrl) @@ -359,6 +360,8 @@ void CompleteCommand (qboolean force) //lines typed at the main console enter here void Con_ExecuteLine(console_t *con, char *line) { + qboolean waschat = false; + con_commandmatch=1; if (line[0] == '\\' || line[0] == '/') Cbuf_AddText (line+1, RESTRICT_LOCAL); // skip the > @@ -368,7 +371,7 @@ void Con_ExecuteLine(console_t *con, char *line) else if (cls.protocol == CP_QUAKE2) Cbuf_AddText (line, RESTRICT_LOCAL); // send the command to the server via console, and let the server convert to chat #endif - else + else if (*line) { // convert to a chat message if (cl_chatmode.value == 1 || ((cls.state >= ca_connected && cl_chatmode.value == 2) && (strncmp(line, "say ", 4)))) { @@ -376,12 +379,14 @@ void Con_ExecuteLine(console_t *con, char *line) Cbuf_AddText ("say_team ", RESTRICT_LOCAL); else Cbuf_AddText ("say ", RESTRICT_LOCAL); + waschat = true; } Cbuf_AddText (line, RESTRICT_LOCAL); // skip the > } Cbuf_AddText ("\n", RESTRICT_LOCAL); - Con_Printf ("]%s\n",line); + if (!waschat || con_echochat.value) + Con_Printf ("]%s\n",line); if (cls.state == ca_disconnected) SCR_UpdateScreen (); // force an update, because the command // may take some time @@ -1337,6 +1342,7 @@ void Key_Init (void) Cmd_AddCommand ("unbindall",Key_Unbindall_f); Cvar_Register (&con_selectioncolour, "Console variables"); + Cvar_Register (&con_echochat, "Console variables"); } qboolean Key_MouseShouldBeFree(void) @@ -1493,6 +1499,16 @@ void Key_Event (int key, qboolean down) if (key == K_SHIFT) shift_down = down; + if (key == K_ESCAPE) + if (shift_down) + { + if (down) + { + Con_ToggleConsole_f(); + return; + } + } + //yes, csqc is allowed to steal the escape key. if (key != '`' && key != '~') if (key_dest == key_game) @@ -1556,6 +1572,14 @@ void Key_Event (int key, qboolean down) return; } +#ifndef NOMEDIA + if (key_dest == key_game && Media_PlayingFullScreen()) + { + Media_Send_KeyEvent(NULL, key, down?0:1); + return; + } +#endif + // // key up events only generate commands if the game key binding is // a button command (leading + sign). These will occur even in console mode, diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index 99facde32..f99a9d9d8 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -6,8 +6,6 @@ #include "glquake.h"//fixme #endif - - #if !defined(NOMEDIA) @@ -785,7 +783,10 @@ char *Media_NextTrack(void) #undef lTime - +#ifdef OFFSCREENGECKO +#include "offscreengecko/embedding.h" +#include "offscreengecko/browser.h" +#endif ///temporary residence for media handling @@ -809,19 +810,39 @@ typedef enum { MFT_STATIC, //non-moving, PCX, no sound MFT_ROQ, MFT_AVI, - MFT_CIN + MFT_CIN, + MFT_OFSGECKO } media_filmtype_t; +typedef enum { + MOT_NONE, + MOT_PALETTE, + MOT_RGBA, + MOT_BGRA, + MOT_BGR_FLIP +} media_outputtype_t; + struct cin_s { //these are the outputs (not always power of two!) - int outtype; + media_outputtype_t outtype; int outwidth; int outheight; qbyte *outdata; qbyte *outpalette; int outunchanged; + qboolean (*decodeframe)(cin_t *cin, qboolean nosound); + void (*doneframe)(cin_t *cin); + void (*shutdown)(cin_t *cin); //warning: don't free cin_t + //these are any interactivity functions you might want... + void (*cursormove) (struct cin_s *cin, float posx, float posy); //pos is 0-1 + void (*key) (struct cin_s *cin, int code, int event); + qboolean (*setsize) (struct cin_s *cin, int width, int height); + void (*getsize) (struct cin_s *cin, int *width, int *height); + void (*changestream) (struct cin_s *cin, char *streamname); + + // media_filmtype_t filmtype; @@ -836,9 +857,24 @@ struct cin_s { LPWAVEFORMAT pWaveFormat; HWND capturewindow; + + //sound stuff + int soundpos; + + //source info + float filmfps; + int num_frames; } avi; #endif +#ifdef OFFSCREENGECKO + struct { + OSGK_Browser *gbrowser; + int bwidth; + int bheight; + } gecko; +#endif + struct { qbyte *filmimage; //rgba int imagewidth; @@ -864,97 +900,358 @@ struct cin_s { int currentframe; //last frame in buffer qbyte *framedata; //Z_Malloced buffer - - //sound stuff - int soundpos; - - //source sizes - int filmwidth; - int filmheight; - - //source info - float filmfps; - int num_frames; }; cin_t *fullscreenvid; -qboolean Media_PlayingFullScreen(void) +////////////////////////////////////////////////////////////////////////////////// +//AVI Support (windows) +#ifdef WINAVI +void Media_WINAVI_Shutdown(struct cin_s *cin) { - return fullscreenvid!=NULL; + AVIStreamGetFrameClose(cin->avi.pgf); + AVIStreamEndStreaming(cin->avi.pavivideo); + AVIStreamRelease(cin->avi.pavivideo); + //we don't need to free the file (we freed it immediatly after getting the stream handles) } - -void Media_ShutdownCin(cin_t *cin) +qboolean Media_WinAvi_DecodeFrame(cin_t *cin, qboolean nosound) { - soundcardinfo_t *sc; - sfx_t *s; + LPBITMAPINFOHEADER lpbi; // Holds The Bitmap Header Information + float newframe; + int newframei; - if (!cin) - return; + float curtime = Sys_DoubleTime(); - for (sc = sndcardinfo; sc; sc=sc->next) + newframe = (curtime - cin->filmstarttime)*cin->avi.filmfps; + newframei = newframe; + + if (newframe == cin->currentframe) { - s = sc->channel[NUM_AMBIENTS].sfx; - if (s && s == &cin->mediaaudio) - { - sc->channel[NUM_AMBIENTS].pos = 0; - sc->channel[NUM_AMBIENTS].end = 0; - sc->channel[NUM_AMBIENTS].sfx = NULL; - } + cin->outunchanged = true; + return true; } - switch(cin->filmtype) //shut down the old media. + if (cin->currentframe < newframei-1) + Con_DPrintf("Dropped %i frame(s)\n", (newframei - cin->currentframe)-1); + + cin->currentframe = newframei; + Con_DPrintf("%i\n", newframei); + + if (cin->currentframe>=cin->avi.num_frames) { - case MFT_ROQ: - roq_close(cin->roq.roqfilm); - cin->roq.roqfilm=NULL; - break; + return false; + } - case MFT_STATIC: - BZ_Free(cin->image.filmimage); - cin->image.filmimage = NULL; - break; + lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(cin->avi.pgf, cin->currentframe); // Grab Data From The AVI Stream + cin->currentframe++; + if (!lpbi || lpbi->biBitCount != 24)//oops + { + SCR_SetUpToDrawConsole(); +#ifdef SWQUAKE + D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly +#endif + Draw_ConsoleBackground(vid.height); + Draw_String(0, 0, "Video stream is corrupt\n"); + } + else + { + cin->outtype = MOT_BGR_FLIP; + cin->outwidth = lpbi->biWidth; + cin->outheight = lpbi->biHeight; + cin->outdata = (char*)lpbi+lpbi->biSize; + } + + if (cin->avi.pavisound) + { + LONG lSize; + LPBYTE pBuffer; + LONG samples; + + AVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, + NULL, 0, &lSize, &samples); + + cin->avi.soundpos+=samples; + + pBuffer = cin->framedata; + + AVIStreamRead(cin->avi.pavisound, cin->avi.soundpos, AVISTREAMREAD_CONVENIENT, pBuffer, lSize, NULL, &samples); + + S_RawAudio(-1, pBuffer, cin->avi.pWaveFormat->nSamplesPerSec, samples, cin->avi.pWaveFormat->nChannels, 2); + } + return true; +} +cin_t *Media_WinAvi_TryLoad(char *name) +{ + cin_t *cin; + PAVIFILE pavi; + + if (!aviinited) + { + aviinited=true; + AVIFileInit(); + } + if (!AVIFileOpen(&pavi, name, OF_READ, NULL))//!AVIStreamOpenFromFile(&pavi, name, streamtypeVIDEO, 0, OF_READ, NULL)) + { + int filmwidth; + int filmheight; + + cin = Z_Malloc(sizeof(cin_t)); + cin->filmtype = MFT_AVI; + cin->avi.pavi = pavi; + + if (AVIFileGetStream(cin->avi.pavi, &cin->avi.pavivideo, streamtypeVIDEO, 0)) //retrieve video stream + { + AVIFileRelease(pavi); + Con_Printf("%s contains no video stream\n", name); + return NULL; + } + if (AVIFileGetStream(cin->avi.pavi, &cin->avi.pavisound, streamtypeAUDIO, 0)) //retrieve audio stream + { + Con_DPrintf("%s contains no audio stream\n", name); + cin->avi.pavisound=NULL; + } + AVIFileRelease(cin->avi.pavi); + +//play with video + AVIStreamInfo(cin->avi.pavivideo, &cin->avi.psi, sizeof(cin->avi.psi)); + filmwidth=cin->avi.psi.rcFrame.right-cin->avi.psi.rcFrame.left; // Width Is Right Side Of Frame Minus Left + filmheight=cin->avi.psi.rcFrame.bottom-cin->avi.psi.rcFrame.top; // Height Is Bottom Of Frame Minus Top + cin->framedata = BZ_Malloc(filmwidth*filmheight*4); + + cin->avi.num_frames=AVIStreamLength(cin->avi.pavivideo); // The Last Frame Of The Stream + cin->avi.filmfps=1000.0f*(float)cin->avi.num_frames/(float)AVIStreamSampleToTime(cin->avi.pavivideo,cin->avi.num_frames); // Calculate Rough Milliseconds Per Frame + + + AVIStreamBeginStreaming(cin->avi.pavivideo, 0, cin->avi.num_frames, 100); + + cin->avi.pgf=AVIStreamGetFrameOpen(cin->avi.pavivideo, NULL); + + cin->currentframe=0; + cin->filmstarttime = Sys_DoubleTime(); + + cin->avi.soundpos=0; + + +//play with sound + if (cin->avi.pavisound) + { + LONG lSize; + LPBYTE pChunk; + AVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, NULL); + + if (!lSize) + cin->avi.pWaveFormat = NULL; + else + { + + pChunk = BZ_Malloc(sizeof(qbyte)*lSize); + + + if(AVIStreamReadFormat(cin->avi.pavisound, AVIStreamStart(cin->avi.pavisound), pChunk, &lSize)) + { + // error + Con_Printf("Failiure reading sound info\n"); + } + cin->avi.pWaveFormat = (LPWAVEFORMAT)pChunk; + } + + if (!cin->avi.pWaveFormat) + { + Con_Printf("VFW is broken\n"); + AVIStreamRelease(cin->avi.pavisound); + cin->avi.pavisound=NULL; + } + else if (cin->avi.pWaveFormat->wFormatTag != 1) + { + Con_Printf("Audio stream is not PCM\n"); //FIXME: so that it no longer is... + AVIStreamRelease(cin->avi.pavisound); + cin->avi.pavisound=NULL; + } + + } + + cin->filmtype = MFT_AVI; + cin->decodeframe = Media_WinAvi_DecodeFrame; + cin->shutdown = Media_WINAVI_Shutdown; + return cin; + } + return NULL; +} -#ifdef WINAVI - case MFT_AVI: - AVIStreamGetFrameClose(cin->avi.pgf); - AVIStreamEndStreaming(cin->avi.pavivideo); - AVIStreamRelease(cin->avi.pavivideo); - //we don't need to free the file (we freed it immediatly after getting the stream handles) - break; #else - case MFT_AVI: - break; +cin_t *Media_WinAvi_TryLoad(char *name) +{ + return NULL; +} #endif +//AVI Support (windows) +////////////////////////////////////////////////////////////////////////////////// +//Quake3 RoQ Support - case MFT_CIN: - CIN_FinishCinematic(); - break; - - case MFT_NONE: - break; - } - - if (cin->framedata) - { - BZ_Free(cin->framedata); - cin->framedata = NULL; - } - - Z_Free(cin); +void Media_Roq_Shutdown(struct cin_s *cin) +{ + roq_close(cin->roq.roqfilm); + cin->roq.roqfilm=NULL; } - -cin_t *Media_StartCin(char *name) +qboolean Media_Roq_DecodeFrame (cin_t *cin, qboolean nosound) { - cin_t *cin = NULL; - char *dot; + float curtime = Sys_DoubleTime(); - if (!name || !*name) //clear only. - return NULL; + if ((int)(cin->filmlasttime*30) == (int)((float)realtime*30)) + { + cin->outunchanged = !!cin->outtype; + return true; + } + else if (curtimenextframetime || roq_read_frame(cin->roq.roqfilm)==1) //0 if end, -1 if error, 1 if success + { + //#define LIMIT(x) ((x)<0xFFFF)?(x)>>16:0xFF; +#define LIMIT(x) ((((x) > 0xffffff) ? 0xff0000 : (((x) <= 0xffff) ? 0 : (x) & 0xff0000)) >> 16) + unsigned char *pa=cin->roq.roqfilm->y[0]; + unsigned char *pb=cin->roq.roqfilm->u[0]; + unsigned char *pc=cin->roq.roqfilm->v[0]; + int pix=0; + int num_columns=(cin->roq.roqfilm->width)>>1; + int num_rows=cin->roq.roqfilm->height; + int y; + int x; + + qbyte *framedata; + + cin->filmlasttime = (float)realtime; + + if (!(curtimenextframetime)) //roq file was read properly + { + cin->nextframetime += 1/30.0; //add a little bit of extra speed so we cover up a little bit of glitchy sound... :o) + + if (cin->nextframetime < curtime) + cin->nextframetime = curtime; + + framedata = cin->framedata; + + for(y = 0; y < num_rows; ++y) //roq playing doesn't give nice data. It's still fairly raw. + { //convert it properly. + for(x = 0; x < num_columns; ++x) + { + + int r, g, b, y1, y2, u, v, t; + y1 = *(pa++); y2 = *(pa++); + u = pb[x] - 128; + v = pc[x] - 128; + + y1 <<= 16; + y2 <<= 16; + r = 91881 * v; + g = -22554 * u + -46802 * v; + b = 116130 * u; + + t=r+y1; + framedata[pix] =(unsigned char) LIMIT(t); + t=g+y1; + framedata[pix+1] =(unsigned char) LIMIT(t); + t=b+y1; + framedata[pix+2] =(unsigned char) LIMIT(t); + + t=r+y2; + framedata[pix+4] =(unsigned char) LIMIT(t); + t=g+y2; + framedata[pix+5] =(unsigned char) LIMIT(t); + t=b+y2; + framedata[pix+6] =(unsigned char) LIMIT(t); + pix+=8; + + } + if(y & 0x01) { pb += num_columns; pc += num_columns; } + } + } + + cin->outunchanged = false; + cin->outtype = MOT_RGBA; + cin->outwidth = cin->roq.roqfilm->width; + cin->outheight = cin->roq.roqfilm->height; + cin->outdata = cin->framedata; + + if (!nosound) + if (cin->roq.roqfilm->audio_channels && sndcardinfo && cin->roq.roqfilm->aud_pos < cin->roq.roqfilm->vid_pos) + if (roq_read_audio(cin->roq.roqfilm)>0) + { +/* FILE *f; + char wav[] = "\x52\x49\x46\x46\xea\x5f\x04\x00\x57\x41\x56\x45\x66\x6d\x74\x20\x12\x00\x00\x00\x01\x00\x02\x00\x22\x56\x00\x00\x88\x58\x01\x00\x04\x00\x10\x00\x00\x00\x66\x61\x63\x74\x04\x00\x00\x00\xee\x17\x01\x00\x64\x61\x74\x61\xb8\x5f\x04\x00"; + int size; + + f = fopen("d:/quake/id1/sound/raw.wav", "r+b"); + if (!f) + f = fopen("d:/quake/id1/sound/raw.wav", "w+b"); + fseek(f, 0, SEEK_SET); + fwrite(&wav, sizeof(wav), 1, f); + fseek(f, 0, SEEK_END); + fwrite(roqfilm->audio, roqfilm->audio_size, 2, f); + size = ftell(f) - sizeof(wav); + fseek(f, 54, SEEK_SET); + fwrite(&size, sizeof(size), 1, f); + fclose(f); +*/ + S_RawAudio(-1, cin->roq.roqfilm->audio, 22050, cin->roq.roqfilm->audio_size/cin->roq.roqfilm->audio_channels, cin->roq.roqfilm->audio_channels, 2); + } + + return true; + } + else + { + cin->roq.roqfilm->frame_num = 0; + cin->roq.roqfilm->aud_pos = cin->roq.roqfilm->roq_start; + cin->roq.roqfilm->vid_pos = cin->roq.roqfilm->roq_start; + } + + return false; +} + +cin_t *Media_RoQ_TryLoad(char *name) +{ + cin_t *cin; + roq_info *roqfilm; + if ((roqfilm = roq_open(name))) + { + cin = Z_Malloc(sizeof(cin_t)); + cin->filmtype = MFT_ROQ; + cin->decodeframe = Media_Roq_DecodeFrame; + cin->shutdown = Media_Roq_Shutdown; + + cin->roq.roqfilm = roqfilm; + cin->nextframetime = Sys_DoubleTime(); + + cin->framedata = BZ_Malloc(roqfilm->width*roqfilm->height*4); + return cin; + } + return NULL; +} + +//Quake3 RoQ Support +////////////////////////////////////////////////////////////////////////////////// +//Static Image Support + +void Media_Static_Shutdown(struct cin_s *cin) +{ + BZ_Free(cin->image.filmimage); + cin->image.filmimage = NULL; +} + +qboolean Media_Static_DecodeFrame(cin_t *cin, qboolean nosound) +{ + cin->outunchanged = cin->outtype==MOT_RGBA?true:false;//handy + cin->outtype = MOT_RGBA; + cin->outwidth = cin->image.imagewidth; + cin->outheight = cin->image.imageheight; + cin->outdata = cin->image.filmimage; + return true; +} + +cin_t *Media_Static_TryLoad(char *name) +{ + cin_t *cin; + char *dot = strrchr(name, '.'); - dot = strchr(name, '.'); //q2 cinematics work like this. if (dot && (!strcmp(dot, ".pcx") || !strcmp(dot, ".tga") || !strcmp(dot, ".png") || !strcmp(dot, ".jpg"))) { qbyte *staticfilmimage; @@ -999,13 +1296,42 @@ cin_t *Media_StartCin(char *name) cin = Z_Malloc(sizeof(cin_t)); cin->filmtype = MFT_STATIC; + cin->decodeframe = Media_Static_DecodeFrame; + cin->shutdown = Media_Static_Shutdown; + cin->image.filmimage = staticfilmimage; cin->image.imagewidth = imagewidth; cin->image.imageheight = imageheight; return cin; } + return NULL; +} +//Static Image Support +////////////////////////////////////////////////////////////////////////////////// +//Quake2 CIN Support + +void Media_Cin_Shutdown(struct cin_s *cin) +{ + CIN_FinishCinematic(); +} + +qboolean Media_Cin_DecodeFrame(cin_t *cin, qboolean nosound) +{ + //FIXME! + if (CIN_RunCinematic()) + { + CIN_DrawCinematic(); + return true; + } + return false; +} + +cin_t *Media_Cin_TryLoad(char *name) +{ + cin_t *cin; + char *dot = strrchr(name, '.'); if (dot && (!strcmp(dot, ".cin"))) { @@ -1013,330 +1339,361 @@ cin_t *Media_StartCin(char *name) { cin = Z_Malloc(sizeof(cin_t)); cin->filmtype = MFT_CIN; - } - return cin; - } - - { - roq_info *roqfilm; - if ((roqfilm = roq_open(name))) - { - cin = Z_Malloc(sizeof(cin_t)); - cin->filmtype = MFT_ROQ; - cin->roq.roqfilm = roqfilm; - cin->nextframetime = Sys_DoubleTime(); - - cin->framedata = BZ_Malloc(roqfilm->width*roqfilm->height*4); + cin->decodeframe = Media_Cin_DecodeFrame; + cin->shutdown = Media_Cin_Shutdown; return cin; } } - - - - - - - - -#ifdef WINAVI - { - PAVIFILE pavi; - - if (!aviinited) - { - aviinited=true; - AVIFileInit(); - } - if (!AVIFileOpen(&pavi, name, OF_READ, NULL))//!AVIStreamOpenFromFile(&pavi, name, streamtypeVIDEO, 0, OF_READ, NULL)) - { - cin = Z_Malloc(sizeof(cin_t)); - cin->filmtype = MFT_AVI; - cin->avi.pavi = pavi; - - if (AVIFileGetStream(cin->avi.pavi, &cin->avi.pavivideo, streamtypeVIDEO, 0)) //retrieve video stream - { - AVIFileRelease(pavi); - Con_Printf("%s contains no video stream\n", name); - return NULL; - } - if (AVIFileGetStream(cin->avi.pavi, &cin->avi.pavisound, streamtypeAUDIO, 0)) //retrieve audio stream - { - Con_DPrintf("%s contains no audio stream\n", name); - cin->avi.pavisound=NULL; - } - AVIFileRelease(cin->avi.pavi); - - //play with video - AVIStreamInfo(cin->avi.pavivideo, &cin->avi.psi, sizeof(cin->avi.psi)); - cin->filmwidth=cin->avi.psi.rcFrame.right-cin->avi.psi.rcFrame.left; // Width Is Right Side Of Frame Minus Left - cin->filmheight=cin->avi.psi.rcFrame.bottom-cin->avi.psi.rcFrame.top; // Height Is Bottom Of Frame Minus Top - cin->framedata = BZ_Malloc(cin->filmwidth*cin->filmheight*4); - - cin->num_frames=AVIStreamLength(cin->avi.pavivideo); // The Last Frame Of The Stream - cin->filmfps=1000.0f*(float)cin->num_frames/(float)AVIStreamSampleToTime(cin->avi.pavivideo,cin->num_frames); // Calculate Rough Milliseconds Per Frame - - - AVIStreamBeginStreaming(cin->avi.pavivideo, 0, cin->num_frames, 100); - - cin->avi.pgf=AVIStreamGetFrameOpen(cin->avi.pavivideo, NULL); - - cin->currentframe=0; - cin->filmstarttime = Sys_DoubleTime(); - - cin->soundpos=0; - - - //play with sound - if (cin->avi.pavisound) - { - LONG lSize; - LPBYTE pChunk; - AVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, NULL, 0, &lSize, NULL); - - if (!lSize) - cin->avi.pWaveFormat = NULL; - else - { - - pChunk = BZ_Malloc(sizeof(qbyte)*lSize); - - - if(AVIStreamReadFormat(cin->avi.pavisound, AVIStreamStart(cin->avi.pavisound), pChunk, &lSize)) - { - // error - Con_Printf("Failiure reading sound info\n"); - } - cin->avi.pWaveFormat = (LPWAVEFORMAT)pChunk; - } - - if (!cin->avi.pWaveFormat) - { - Con_Printf("VFW is broken\n"); - AVIStreamRelease(cin->avi.pavisound); - cin->avi.pavisound=NULL; - } - else if (cin->avi.pWaveFormat->wFormatTag != 1) - { - Con_Printf("Audio stream is not PCM\n"); //FIXME: so that it no longer is... - AVIStreamRelease(cin->avi.pavisound); - cin->avi.pavisound=NULL; - } - - } - - cin->filmtype = MFT_AVI; - return cin; - } - } -#endif - return NULL; } -qboolean Media_DecodeFrame(cin_t *cin, qboolean nosound) +//Quake2 CIN Support +////////////////////////////////////////////////////////////////////////////////// +//Gecko Support + +#ifdef OFFSCREENGECKO + +int (*posgk_release) (OSGK_BaseObject* obj); + +OSGK_Browser* (*posgk_browser_create) (OSGK_Embedding* embedding, int width, int height); +void (*posgk_browser_resize) (OSGK_Browser* browser, int width, int height); +void (*posgk_browser_navigate) (OSGK_Browser* browser, const char* uri); +const unsigned char* (*posgk_browser_lock_data) (OSGK_Browser* browser, int* isDirty); +void (*posgk_browser_unlock_data) (OSGK_Browser* browser, const unsigned char* data); + +void (*posgk_browser_event_mouse_move) (OSGK_Browser* browser, int x, int y); +void (*posgk_browser_event_mouse_button) (OSGK_Browser* browser, OSGK_MouseButton button, OSGK_MouseButtonEventType eventType); +int (*posgk_browser_event_key) (OSGK_Browser* browser, unsigned int key, OSGK_KeyboardEventType eventType); + +OSGK_EmbeddingOptions* (*posgk_embedding_options_create) (void); +OSGK_Embedding* (*posgk_embedding_create2) (unsigned int apiVer, OSGK_EmbeddingOptions* options, OSGK_GeckoResult* geckoResult); +void (*posgk_embedding_options_set_profile_dir) (OSGK_EmbeddingOptions* options, const char* profileDir, const char* localProfileDir); +void (*posgk_embedding_options_add_search_path) (OSGK_EmbeddingOptions* options, const char* path); + +dllhandle_t geckodll; +dllfunction_t gecko_functions[] = { - float curtime = Sys_DoubleTime(); + {(void**)&posgk_release, "osgk_release"}, - switch (cin->filmtype) - { - case MFT_ROQ: - if ((int)(cin->filmlasttime*30) == (int)((float)realtime*30)) - { - cin->outunchanged = !!cin->outtype; - return true; - } - else if (curtimenextframetime || roq_read_frame(cin->roq.roqfilm)==1) //0 if end, -1 if error, 1 if success - { - //#define LIMIT(x) ((x)<0xFFFF)?(x)>>16:0xFF; -#define LIMIT(x) ((((x) > 0xffffff) ? 0xff0000 : (((x) <= 0xffff) ? 0 : (x) & 0xff0000)) >> 16) - unsigned char *pa=cin->roq.roqfilm->y[0]; - unsigned char *pb=cin->roq.roqfilm->u[0]; - unsigned char *pc=cin->roq.roqfilm->v[0]; - int pix=0; - int num_columns=(cin->roq.roqfilm->width)>>1; - int num_rows=cin->roq.roqfilm->height; - int y; - int x; + {(void**)&posgk_browser_create, "osgk_browser_create"}, + {(void**)&posgk_browser_resize, "osgk_browser_resize"}, + {(void**)&posgk_browser_navigate, "osgk_browser_navigate"}, + {(void**)&posgk_browser_lock_data, "osgk_browser_lock_data"}, + {(void**)&posgk_browser_unlock_data, "osgk_browser_unlock_data"}, - qbyte *framedata; + {(void**)&posgk_browser_event_mouse_move, "osgk_browser_event_mouse_move"}, + {(void**)&posgk_browser_event_mouse_move, "osgk_browser_event_mouse_move"}, + {(void**)&posgk_browser_event_mouse_button, "osgk_browser_event_mouse_button"}, + {(void**)&posgk_browser_event_key, "osgk_browser_event_key"}, - cin->filmlasttime = (float)realtime; + {(void**)&posgk_embedding_options_create, "osgk_embedding_options_create"}, + {(void**)&posgk_embedding_create2, "osgk_embedding_create2"}, + {(void**)&posgk_embedding_options_set_profile_dir, "osgk_embedding_options_set_profile_dir"}, + {(void**)&posgk_embedding_options_add_search_path, "osgk_embedding_options_add_search_path"}, + {NULL} +}; +OSGK_Embedding *gecko_embedding; - if (!(curtimenextframetime)) //roq file was read properly - { - cin->nextframetime += 1/30.0; //add a little bit of extra speed so we cover up a little bit of glitchy sound... :o) - - if (cin->nextframetime < curtime) - cin->nextframetime = curtime; - - framedata = cin->framedata; - - for(y = 0; y < num_rows; ++y) //roq playing doesn't give nice data. It's still fairly raw. - { //convert it properly. - for(x = 0; x < num_columns; ++x) - { - - int r, g, b, y1, y2, u, v, t; - y1 = *(pa++); y2 = *(pa++); - u = pb[x] - 128; - v = pc[x] - 128; - - y1 <<= 16; - y2 <<= 16; - r = 91881 * v; - g = -22554 * u + -46802 * v; - b = 116130 * u; - - t=r+y1; - framedata[pix] =(unsigned char) LIMIT(t); - t=g+y1; - framedata[pix+1] =(unsigned char) LIMIT(t); - t=b+y1; - framedata[pix+2] =(unsigned char) LIMIT(t); - - t=r+y2; - framedata[pix+4] =(unsigned char) LIMIT(t); - t=g+y2; - framedata[pix+5] =(unsigned char) LIMIT(t); - t=b+y2; - framedata[pix+6] =(unsigned char) LIMIT(t); - pix+=8; - - } - if(y & 0x01) { pb += num_columns; pc += num_columns; } - } - } - - cin->outunchanged = false; - cin->outtype = 1; - cin->outwidth = cin->roq.roqfilm->width; - cin->outheight = cin->roq.roqfilm->height; - cin->outdata = cin->framedata; - - if (!nosound) - if (cin->roq.roqfilm->audio_channels && sndcardinfo && cin->roq.roqfilm->aud_pos < cin->roq.roqfilm->vid_pos) - if (roq_read_audio(cin->roq.roqfilm)>0) - { -/* FILE *f; - char wav[] = "\x52\x49\x46\x46\xea\x5f\x04\x00\x57\x41\x56\x45\x66\x6d\x74\x20\x12\x00\x00\x00\x01\x00\x02\x00\x22\x56\x00\x00\x88\x58\x01\x00\x04\x00\x10\x00\x00\x00\x66\x61\x63\x74\x04\x00\x00\x00\xee\x17\x01\x00\x64\x61\x74\x61\xb8\x5f\x04\x00"; - int size; - - f = fopen("d:/quake/id1/sound/raw.wav", "r+b"); - if (!f) - f = fopen("d:/quake/id1/sound/raw.wav", "w+b"); - fseek(f, 0, SEEK_SET); - fwrite(&wav, sizeof(wav), 1, f); - fseek(f, 0, SEEK_END); - fwrite(roqfilm->audio, roqfilm->audio_size, 2, f); - size = ftell(f) - sizeof(wav); - fseek(f, 54, SEEK_SET); - fwrite(&size, sizeof(size), 1, f); - fclose(f); -*/ - S_RawAudio(-1, cin->roq.roqfilm->audio, 22050, cin->roq.roqfilm->audio_size/cin->roq.roqfilm->audio_channels, cin->roq.roqfilm->audio_channels, 2); - } - - return true; - } - else - { - cin->roq.roqfilm->frame_num = 0; - cin->roq.roqfilm->aud_pos = cin->roq.roqfilm->roq_start; - cin->roq.roqfilm->vid_pos = cin->roq.roqfilm->roq_start; - } - break; - - case MFT_STATIC: - cin->outunchanged = cin->outtype;//handy - cin->outtype = 1; - cin->outwidth = cin->image.imagewidth; - cin->outheight = cin->image.imageheight; - cin->outdata = cin->image.filmimage; - return true; - - case MFT_CIN: - //FIXME! - if (CIN_RunCinematic()) - { - CIN_DrawCinematic(); - return true; - } - break; - - case MFT_AVI: -#ifdef WINAVI - { - LPBITMAPINFOHEADER lpbi; // Holds The Bitmap Header Information - float newframe; - int newframei; - - newframe = (curtime - cin->filmstarttime)*cin->filmfps; - newframei = newframe; - - if (newframe == cin->currentframe) - { - cin->outunchanged = true; - return true; - } - - if (cin->currentframe < newframei-1) - Con_DPrintf("Dropped %i frame(s)\n", (newframei - cin->currentframe)-1); - - cin->currentframe = newframei; - Con_DPrintf("%i\n", newframei); - - if (cin->currentframe>=cin->num_frames) - { - return false; - } - - lpbi = (LPBITMAPINFOHEADER)AVIStreamGetFrame(cin->avi.pgf, cin->currentframe); // Grab Data From The AVI Stream - cin->currentframe++; - if (!lpbi || lpbi->biBitCount != 24)//oops - { - SCR_SetUpToDrawConsole(); -#ifdef SWQUAKE - D_EnableBackBufferAccess (); // of all overlay stuff if drawing directly -#endif - Draw_ConsoleBackground(vid.height); - Draw_String(0, 0, "Video stream is corrupt\n"); - } - else - { - cin->outtype = 3; - cin->outwidth = lpbi->biWidth; - cin->outheight = lpbi->biHeight; - cin->outdata = (char*)lpbi+lpbi->biSize; - } - - if (cin->avi.pavisound) - { - LONG lSize; - LPBYTE pBuffer; - LONG samples; - - AVIStreamRead(cin->avi.pavisound, 0, AVISTREAMREAD_CONVENIENT, - NULL, 0, &lSize, &samples); - - cin->soundpos+=samples; - - pBuffer = cin->framedata; - - AVIStreamRead(cin->avi.pavisound, cin->soundpos, AVISTREAMREAD_CONVENIENT, pBuffer, lSize, NULL, &samples); - - S_RawAudio(-1, pBuffer, cin->avi.pWaveFormat->nSamplesPerSec, samples, cin->avi.pWaveFormat->nChannels, 2); - } - } - return true; -#endif - case MFT_NONE: - break; - } - return false; +void Media_Gecko_Shutdown(struct cin_s *cin) +{ + posgk_release(&cin->gecko.gbrowser->baseobj); } +qboolean Media_Gecko_DecodeFrame(cin_t *cin, qboolean nosound) +{ + cin->outdata = (char*)posgk_browser_lock_data(cin->gecko.gbrowser, &cin->outunchanged); + cin->outwidth = cin->gecko.bwidth; + cin->outheight = cin->gecko.bheight; + cin->outtype = MOT_BGRA; + return !!cin->gecko.gbrowser; +} +void Media_Gecko_DoneFrame(cin_t *cin) +{ + posgk_browser_unlock_data(cin->gecko.gbrowser, cin->outdata); + cin->outdata = NULL; +} + +void Media_Gecko_MoveCursor (struct cin_s *cin, float posx, float posy) +{ + posgk_browser_event_mouse_move(cin->gecko.gbrowser, posx*cin->gecko.bwidth, posy*cin->gecko.bheight); +} + +void Media_Gecko_KeyPress (struct cin_s *cin, int code, int event) +{ + if (code >= K_MOUSE1 && code < K_MOUSE10) + { + posgk_browser_event_mouse_button(cin->gecko.gbrowser, code - K_MOUSE1, (event==3)?2:event); + } + else + { + switch(code) + { + case K_BACKSPACE: + code = OSGKKey_Backspace; + break; + case K_TAB: + code = OSGKKey_Tab; + break; + case K_ENTER: + code = OSGKKey_Return; + break; + case K_SHIFT: + code = OSGKKey_Shift; + break; + case K_CTRL: + code = OSGKKey_Control; + break; + case K_ALT: + code = OSGKKey_Alt; + break; + case K_CAPSLOCK: + code = OSGKKey_CapsLock; + break; + case K_ESCAPE: + code = OSGKKey_Escape; + break; + case K_SPACE: + code = OSGKKey_Space; + break; + case K_PGUP: + code = OSGKKey_PageUp; + break; + case K_PGDN: + code = OSGKKey_PageDown; + break; + case K_END: + code = OSGKKey_End; + break; + case K_HOME: + code = OSGKKey_Home; + break; + case K_LEFTARROW: + code = OSGKKey_Left; + break; + case K_UPARROW: + code = OSGKKey_Up; + break; + case K_RIGHTARROW: + code = OSGKKey_Right; + break; + case K_DOWNARROW: + code = OSGKKey_Down; + break; + case K_INS: + code = OSGKKey_Insert; + break; + case K_DEL: + code = OSGKKey_Delete; + break; + case K_F1: + code = OSGKKey_F1; + break; + case K_F2: + code = OSGKKey_F2; + break; + case K_F3: + code = OSGKKey_F3; + break; + case K_F4: + code = OSGKKey_F4; + break; + case K_F5: + code = OSGKKey_F5; + break; + case K_F6: + code = OSGKKey_F6; + break; + case K_F7: + code = OSGKKey_F7; + break; + case K_F8: + code = OSGKKey_F8; + break; + case K_F9: + code = OSGKKey_F9; + break; + case K_F10: + code = OSGKKey_F10; + break; + case K_F11: + code = OSGKKey_F11; + break; + case K_F12: + code = OSGKKey_F12; + break; + case K_KP_NUMLOCK: + code = OSGKKey_NumLock; + break; + case K_SCRLCK: + code = OSGKKey_ScrollLock; + break; + case K_LWIN: + code = OSGKKey_Meta; + break; + } + Con_Printf("Sending %c\n", code); + posgk_browser_event_key(cin->gecko.gbrowser, code, kePress); + //posgk_browser_event_key(cin->gecko.gbrowser, code, event); + } +} + +qboolean Media_Gecko_SetSize (struct cin_s *cin, int width, int height) +{ + if (width < 4 || height < 4) + return false; + + posgk_browser_resize(cin->gecko.gbrowser, width, height); + cin->gecko.bwidth = width; + cin->gecko.bheight = height; + return true; +} + +void Media_Gecko_GetSize (struct cin_s *cin, int *width, int *height) +{ + *width = cin->gecko.bwidth; + *height = cin->gecko.bheight; +} + +void Media_Gecko_ChangeStream (struct cin_s *cin, char *streamname) +{ + posgk_browser_navigate(cin->gecko.gbrowser, streamname); +} + +cin_t *Media_Gecko_TryLoad(char *name) +{ + cin_t *cin; + + if (!strncmp(name, "http://", 7)) + { + OSGK_GeckoResult result; + + OSGK_EmbeddingOptions *opts; + + if (!gecko_embedding) + { + geckodll = Sys_LoadLibrary("OffscreenGecko", gecko_functions); + if (!geckodll) + { + Con_Printf("OffscreenGecko not installed\n"); + return NULL; + } + + opts = posgk_embedding_options_create(); + if (!opts) + return NULL; + + posgk_embedding_options_add_search_path(opts, "./xulrunner/"); + posgk_embedding_options_set_profile_dir(opts, va("%s/xulrunner_profile/", com_gamedir), 0); + + gecko_embedding = posgk_embedding_create2(OSGK_API_VERSION, opts, &result); + posgk_release(&opts->baseobj); + if (!gecko_embedding) + return NULL; + } + + cin = Z_Malloc(sizeof(cin_t)); + cin->filmtype = MFT_OFSGECKO; + cin->decodeframe = Media_Gecko_DecodeFrame; + cin->doneframe = Media_Gecko_DoneFrame; + cin->shutdown = Media_Gecko_Shutdown; + + cin->cursormove = Media_Gecko_MoveCursor; + cin->key = Media_Gecko_KeyPress; + cin->setsize = Media_Gecko_SetSize; + cin->getsize = Media_Gecko_GetSize; + cin->changestream = Media_Gecko_ChangeStream; + + cin->gecko.bwidth = 1024; + cin->gecko.bheight = 1024; + + cin->gecko.gbrowser = posgk_browser_create(gecko_embedding, cin->gecko.bwidth, cin->gecko.bheight); + if (!cin->gecko.gbrowser) + { + Z_Free(cin); + return NULL; + } + posgk_browser_navigate(cin->gecko.gbrowser, name); + return cin; + } + return NULL; +} +#else +cin_t *Media_Gecko_TryLoad(char *name) +{ + return NULL; +} +#endif + +//Gecko Support +////////////////////////////////////////////////////////////////////////////////// + +qboolean Media_PlayingFullScreen(void) +{ + return fullscreenvid!=NULL; +} + +void Media_ShutdownCin(cin_t *cin) +{ + soundcardinfo_t *sc; + sfx_t *s; + + if (!cin) + return; + + for (sc = sndcardinfo; sc; sc=sc->next) + { + s = sc->channel[NUM_AMBIENTS].sfx; + if (s && s == &cin->mediaaudio) + { + sc->channel[NUM_AMBIENTS].pos = 0; + sc->channel[NUM_AMBIENTS].end = 0; + sc->channel[NUM_AMBIENTS].sfx = NULL; + } + } + + if (cin->shutdown) + cin->shutdown(cin); + + if (cin->framedata) + { + BZ_Free(cin->framedata); + cin->framedata = NULL; + } + + Z_Free(cin); +} + +cin_t *Media_StartCin(char *name) +{ + cin_t *cin = NULL; + + if (!name || !*name) //clear only. + return NULL; + + if (!cin) + cin = Media_Gecko_TryLoad(name); + + if (!cin) + cin = Media_Static_TryLoad(name); + + if (!cin) + cin = Media_Cin_TryLoad(name); + + if (!cin) + cin = Media_RoQ_TryLoad(name); + + if (!cin) + cin = Media_WinAvi_TryLoad(name); + + return cin; +} + +qboolean Media_DecodeFrame(cin_t *cin, qboolean nosound) +{ + return cin->decodeframe(cin, nosound); +} qboolean Media_PlayFilm(char *name) { @@ -1371,17 +1728,25 @@ qboolean Media_ShowFilm(void) switch(fullscreenvid->outtype) { - case 1: + case MOT_RGBA: Media_ShowFrameRGBA_32(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight); break; - case 2: + case MOT_PALETTE: Media_ShowFrame8bit(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight, fullscreenvid->outpalette); break; - case 3: + case MOT_BGR_FLIP: Media_ShowFrameBGR_24_Flip(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight); break; + case MOT_BGRA: +#pragma message("Media_ShowFilm: BGRA comes out as RGBA") +// Media_ShowFrameBGRA_32 + Media_ShowFrameRGBA_32(fullscreenvid->outdata, fullscreenvid->outwidth, fullscreenvid->outheight); + break; } + if (fullscreenvid->doneframe) + fullscreenvid->doneframe(fullscreenvid); + return true; } @@ -1400,23 +1765,66 @@ int Media_UpdateForShader(int texnum, cin_t *cin) GL_Bind(texnum); switch(cin->outtype) { - case 1: + case MOT_RGBA: GL_Upload32("cin", (unsigned int*)cin->outdata, cin->outwidth, cin->outheight, false, false); break; - case 2: + case MOT_PALETTE: GL_Upload8("cin", cin->outdata, cin->outwidth, cin->outheight, false, false); break; - case 3: + case MOT_BGR_FLIP: GL_Upload24BGR_Flip ("cin", cin->outdata, cin->outwidth, cin->outheight, false, false); break; + case MOT_BGRA: + GL_Upload32_BGRA("cin", (unsigned int*)cin->outdata, cin->outwidth, cin->outheight, false, false); + break; } } + if (cin->doneframe) + cin->doneframe(cin); + return texnum; } #endif +void Media_Send_Command(cin_t *cin, char *command) +{ + if (!cin) + cin = fullscreenvid; + if (!cin || !cin->key) + return; + cin->changestream(cin, command); +} +void Media_Send_KeyEvent(cin_t *cin, int button, int event) +{ + if (!cin) + cin = fullscreenvid; + if (!cin || !cin->key) + return; + cin->key(cin, button, event); +} +void Media_Send_MouseMove(cin_t *cin, float x, float y) +{ + if (!cin) + cin = fullscreenvid; + if (!cin || !cin->key) + return; + cin->cursormove(cin, x, y); +} +void Media_Send_Resize(cin_t *cin, int x, int y) +{ + cin->setsize(cin, x, y); +} +void Media_Send_GetSize(cin_t *cin, int *x, int *y) +{ + if (!cin) + cin = fullscreenvid; + if (!cin || !cin->key) + return; + cin->getsize(cin, x, y); +} + void Media_PlayFilm_f (void) diff --git a/engine/client/m_single.c b/engine/client/m_single.c index f57eecbe6..d3faa465d 100644 --- a/engine/client/m_single.c +++ b/engine/client/m_single.c @@ -157,10 +157,11 @@ void M_Menu_SinglePlayer_f (void) cvar_t *pc; static char *classlist[] = { "Random", - "Barbarian", - "Crusader", "Paladin", + "Crusader", + "Necromancer", "Assasin", + "Demoness", NULL }; static char *classvalues[] = { @@ -169,6 +170,7 @@ void M_Menu_SinglePlayer_f (void) "2", "3", "4", + "5", NULL }; menu = M_CreateMenu(0); diff --git a/engine/client/menu.c b/engine/client/menu.c index f4050d681..e1b6f0d4a 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -217,6 +217,12 @@ M_ToggleMenu_f */ void M_ToggleMenu_f (void) { + if (m_state) + { + key_dest = key_menu; + return; + } + #ifdef MENU_DAT if (MP_Toggle()) return; diff --git a/engine/client/merged.h b/engine/client/merged.h index 98547188a..9a0a7db7e 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -86,7 +86,7 @@ extern void SCR_EndLoadingPlaque (void); extern void SCR_DrawConsole (qboolean noback); extern void SCR_SetUpToDrawConsole (void); extern void SCR_EraseCenterString (void); -extern void SCR_CenterPrint (int pnum, char *str); +extern void SCR_CenterPrint (int pnum, char *str, qboolean fromgamecode); #endif diff --git a/engine/client/net_master.c b/engine/client/net_master.c index ae3379b6a..054d98a85 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -49,7 +49,7 @@ static serverinfo_t **visibleservers; static int numvisibleservers; static int maxvisibleservers; -static qboolean needsort; +static double nextsort; static hostcachekey_t sortfield; static qboolean decreasingorder; @@ -241,7 +241,13 @@ qboolean Master_PassesMasks(serverinfo_t *a) res = Master_CompareInteger(a->maxplayers, visrules[i].operandi, visrules[i].compareop); break; case SLKEY_FREEPLAYERS: - res = Master_CompareInteger(a->maxplayers-a->players, visrules[i].operandi, visrules[i].compareop); + res = Master_CompareInteger(a->freeslots, visrules[i].operandi, visrules[i].compareop); + break; + case SLKEY_NUMBOTS: + res = Master_CompareInteger(a->numbots, visrules[i].operandi, visrules[i].compareop); + break; + case SLKEY_NUMHUMANS: + res = Master_CompareInteger(a->numhumans, visrules[i].operandi, visrules[i].compareop); break; case SLKEY_TIMELIMIT: res = Master_CompareInteger(a->tl, visrules[i].operandi, visrules[i].compareop); @@ -249,6 +255,9 @@ qboolean Master_PassesMasks(serverinfo_t *a) case SLKEY_FRAGLIMIT: res = Master_CompareInteger(a->fl, visrules[i].operandi, visrules[i].compareop); break; + case SLKEY_PROTOCOL: + res = Master_CompareInteger(a->fl, visrules[i].operandi, visrules[i].compareop); + break; case SLKEY_MAP: res = Master_CompareString(a->map, visrules[i].operands, visrules[i].compareop); @@ -263,6 +272,12 @@ qboolean Master_PassesMasks(serverinfo_t *a) case SLKEY_BASEGAME: res = Master_CompareInteger(a->special, visrules[i].operandi, visrules[i].compareop); break; + case SLKEY_MOD: + res = Master_CompareString(a->modname, visrules[i].operands, visrules[i].compareop); + break; + case SLKEY_QCSTATUS: + res = Master_CompareString(a->qcstatus, visrules[i].operands, visrules[i].compareop); + break; default: continue; } @@ -285,6 +300,7 @@ void Master_SetMaskString(qboolean or, hostcachekey_t field, char *param, slist_ if (numvisrules == MAX_VISRULES) return; //just don't add it. + nextsort = 0; visrules[numvisrules].fieldindex = field; visrules[numvisrules].compareop = testop; visrules[numvisrules].operands = param; @@ -296,6 +312,7 @@ void Master_SetMaskInteger(qboolean or, hostcachekey_t field, int param, slist_t if (numvisrules == MAX_VISRULES) return; //just don't add it. + nextsort = 0; visrules[numvisrules].fieldindex = field; visrules[numvisrules].compareop = testop; visrules[numvisrules].operandi = param; @@ -304,6 +321,7 @@ void Master_SetMaskInteger(qboolean or, hostcachekey_t field, int param, slist_t } void Master_SetSortField(hostcachekey_t field, qboolean descending) { + nextsort = 0; sortfield = field; decreasingorder = descending; } @@ -388,13 +406,13 @@ void Master_SortServers(void) Master_ResortServer(server); } - needsort = false; + nextsort = Sys_DoubleTime() + 8; } serverinfo_t *Master_SortedServer(int idx) { - if (needsort) - Master_SortServers(); +// if (nextsort < Sys_DoubleTime()) +// Master_SortServers(); if (idx < 0 || idx >= numvisibleservers) return NULL; @@ -404,7 +422,7 @@ serverinfo_t *Master_SortedServer(int idx) int Master_NumSorted(void) { -// if (needsort) + if (nextsort < Sys_DoubleTime()) Master_SortServers(); return numvisibleservers; @@ -434,6 +452,14 @@ float Master_ReadKeyFloat(serverinfo_t *server, int keynum) return server->tl; case SLKEY_FRAGLIMIT: return server->fl; + case SLKEY_PROTOCOL: + return server->protocol; + case SLKEY_NUMBOTS: + return server->numbots; + case SLKEY_NUMHUMANS: + return server->numhumans; + case SLKEY_ISFAVORITE: + return !!(server->special & SS_FAVORITE); default: return atof(Master_ReadKeyString(server, keynum)); @@ -462,6 +488,11 @@ char *Master_ReadKeyString(serverinfo_t *server, int keynum) case SLKEY_GAMEDIR: return server->gamedir; + case SLKEY_MOD: + return server->modname; + case SLKEY_QCSTATUS: + return server->qcstatus; + default: { static char s[64]; @@ -491,12 +522,24 @@ int Master_KeyForName(char *keyname) return SLKEY_MAXPLAYERS; else if (!strcmp(keyname, "numplayers")) return SLKEY_NUMPLAYERS; - else if (!strcmp(keyname, "freeplayers")) + else if (!strcmp(keyname, "freeplayers") || !strcmp(keyname, "freeslots")) return SLKEY_FREEPLAYERS; - else if (!strcmp(keyname, "gamedir") || !strcmp(keyname, "game") || !strcmp(keyname, "*gamedir") || !strcmp(keyname, "mod")) + else if (!strcmp(keyname, "gamedir") || !strcmp(keyname, "game") || !strcmp(keyname, "*gamedir")) return SLKEY_GAMEDIR; else if (!strcmp(keyname, "special")) return SLKEY_BASEGAME; + else if (!strcmp(keyname, "mod")) + return SLKEY_MOD; + else if (!strcmp(keyname, "protocol")) + return SLKEY_PROTOCOL; + else if (!strcmp(keyname, "numbots")) + return SLKEY_NUMBOTS; + else if (!strcmp(keyname, "numhumans")) + return SLKEY_NUMHUMANS; + else if (!strcmp(keyname, "qcstatus")) + return SLKEY_QCSTATUS; + else if (!strcmp(keyname, "isfavorite")) + return SLKEY_ISFAVORITE; else if (slist_customkeys == SLIST_MAXKEYS) return SLKEY_TOOMANY; @@ -531,6 +574,13 @@ void Master_AddMaster (char *address, int type, char *description) return; } +#pragma message("Master_AddMaster: add ipv6. don't care about tcp/irc.") + if (adr.type != NA_IP && adr.type != NA_IPX) + { + Con_Printf("Fixme: unable to poll address family\n", address); + return; + } + if (type < MT_SINGLEQW) //broadcasts { if (adr.type == NA_IP) @@ -726,6 +776,8 @@ void NET_SendPollPacket(int len, void *data, netadr_t to) int ret; struct sockaddr_qstorage addr; +#pragma message("NET_SendPollPacket: no support for ipv6") + NetadrToSockadr (&to, &addr); #ifdef USEIPX if (((struct sockaddr*)&addr)->sa_family == AF_IPX) @@ -741,6 +793,7 @@ void NET_SendPollPacket(int len, void *data, netadr_t to) } else #endif + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { lastpollsockUDP++; if (lastpollsockUDP>=POLLUDPSOCKETS) @@ -751,6 +804,8 @@ void NET_SendPollPacket(int len, void *data, netadr_t to) return; //bother ret = sendto (pollsocketsUDP[lastpollsockUDP], data, len, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in) ); } + else + return; if (ret == -1) { @@ -1036,6 +1091,8 @@ void MasterInfo_ProcessHTTP(char *name, qboolean success, int type) info->next = firstserver; firstserver = info; + + Master_ResortServer(info); } } @@ -1572,6 +1629,15 @@ int CL_ReadServerInfo(char *msg, int servertype, qboolean favorite) Q_strncpyz(info->gamedir, Info_ValueForKey(msg, "*gamedir"), sizeof(info->gamedir)); Q_strncpyz(info->map, Info_ValueForKey(msg, "map"), sizeof(info->map)); } + Q_strncpyz(info->qcstatus, Info_ValueForKey(msg, "qcstatus"), sizeof(info->qcstatus)); + Q_strncpyz(info->modname, Info_ValueForKey(msg, "modname"), sizeof(info->modname)); + + info->protocol = atoi(Info_ValueForKey(msg, "protocol")); + info->gameversion = atoi(Info_ValueForKey(msg, "gameversion")); + + info->numbots = atoi(Info_ValueForKey(msg, "bots")); + info->numhumans = info->players - info->numbots; + info->freeslots = info->maxplayers - info->players; strcpy(details.info, msg); msg = msg+strlen(msg)+1; @@ -1744,6 +1810,8 @@ void CL_MasterListParse(int type, qboolean slashpad) info->next = last; last = info; + + Master_ResortServer(info); } } diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c new file mode 100644 index 000000000..5c3c29a82 --- /dev/null +++ b/engine/client/p_classic.c @@ -0,0 +1,753 @@ +#include "quakedef.h" + +#ifdef PSET_CLASSIC + +#include "glquake.h" + +void D_DrawParticleTrans (vec3_t porg, float palpha, float pscale, unsigned int pcolour, blendmode_t blendmode); + + + +cvar_t gl_solidparticles = SCVAR("gl_solidparticles", "0"); + + +typedef enum { + DODGY, + + ROCKET_TRAIL, + ALT_ROCKET_TRAIL, + BLOOD_TRAIL, + GRENADE_TRAIL, + BIG_BLOOD_TRAIL, + TRACER1_TRAIL, + TRACER2_TRAIL, + VOOR_TRAIL, + + BLOBEXPLOSION_POINT, + LAVASPLASH_POINT, + EXPLOSION_POINT, + TELEPORTSPLASH_POINT, + + EFFECTTYPE_MAX +} effect_type_t; + + +typedef struct cparticle_s { + enum { + pt_static, + pt_fire, + pt_explode, + pt_explode2, + pt_blob, + pt_blob2, + pt_grav, + pt_slowgrav + } type; + float die; + vec3_t org; + vec3_t vel; + float ramp; + unsigned char color; + struct cparticle_s *next; +} cparticle_t; + +#define DEFAULT_NUM_PARTICLES 2048 +#define ABSOLUTE_MIN_PARTICLES 512 +#define ABSOLUTE_MAX_PARTICLES 8192 +static int r_numparticles; +static cparticle_t *particles, *active_particles, *free_particles; + +static int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; +static int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; +static int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; + + +//obtains an index for the name, even if it is unknown (one can be loaded after. will only fail if the effect limit is reached) +//technically this function is not meant to fail often, but thats fine so long as the other functions are meant to safely reject invalid effect numbers. +static int PClassic_ParticleTypeForName(char *name) +{ + if (!stricmp("tr_rocket", name)) + return ROCKET_TRAIL; + if (!stricmp("tr_altrocket", name)) + return ALT_ROCKET_TRAIL; + if (!stricmp("tr_slightblood", name)) + return BLOOD_TRAIL; + if (!stricmp("tr_grenade", name)) + return GRENADE_TRAIL; + if (!stricmp("tr_blood", name)) + return BIG_BLOOD_TRAIL; + if (!stricmp("tr_wizspike", name)) + return TRACER1_TRAIL; + if (!stricmp("tr_knightspike", name)) + return TRACER2_TRAIL; + if (!stricmp("tr_vorespike", name)) + return VOOR_TRAIL; + + if (!stricmp("te_tarexplosion", name)) + return BLOBEXPLOSION_POINT; + if (!stricmp("te_lavasplash", name)) + return LAVASPLASH_POINT; + if (!stricmp("te_lavasplash", name)) + return LAVASPLASH_POINT; + if (!stricmp("te_explosion", name)) + return EXPLOSION_POINT; + if (!stricmp("te_teleport", name)) + return TELEPORTSPLASH_POINT; + + return P_INVALID; +} + +//returns a valid effect if both its existance is known, and it is fully functional +static int PClassic_FindParticleType(char *name) +{ + return P_ParticleTypeForName(name); +} + +//a convienience function. +static int PClassic_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name) +{ + int efnum = P_FindParticleType(name); + return P_RunParticleEffectState(org, dir, count, efnum, NULL); +} + +//DP extension: add particles within a box that look like rain or snow. +static void PClassic_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname) +{ +} + +//DP extension: add particles within a box. +static void PClassic_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter) +{ +} + +//hexen2 support: add particles flying out from a point with a randomized speed +static void PClassic_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count) +{ +} + +//hexen2 support: add particles within a box. +static void PClassic_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int effect, int count) +{ +} + +//hexen2 support: add particles around the spot in a radius. no idea what the 'effect' field is. +static void PClassic_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count) +{ +} + +//this function is used as a fallback in case a trail effect is unknown. +static void PClassic_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk) +{ +} + +//this function is called to tell the particle system about surfaces that might emit particles at map startup. +static void PClassic_EmitSkyEffectTris(model_t *mod, msurface_t *fa) +{ +} + +//the one-time initialisation function, called no mater which renderer is active. +static void PClassic_InitParticles (void) +{ + int i; + + if ((i = COM_CheckParm ("-particles")) && i + 1 < com_argc) { + r_numparticles = (int) (Q_atoi(com_argv[i + 1])); + r_numparticles = bound(ABSOLUTE_MIN_PARTICLES, r_numparticles, ABSOLUTE_MAX_PARTICLES); + } else { + r_numparticles = DEFAULT_NUM_PARTICLES; + } + + particles = (cparticle_t *) BZ_Malloc (r_numparticles * sizeof(cparticle_t), "classic:particles"); + + CL_RegisterParticles(); +} + +static void PClassic_ShutdownParticles(void) +{ + BZ_Free(particles); +} + +//called when an entity is removed from the world, taking its trailstate with it. +static void PClassic_DelinkTrailstate(trailstate_t **tsk) +{ + //classic has no concept of trail states. +} + +//wipes all the particles ready for the next map. +static void PClassic_ClearParticles (void) +{ + int i; + + free_particles = &particles[0]; + active_particles = NULL; + + for (i = 0;i < r_numparticles; i++) + particles[i].next = &particles[i+1]; + particles[r_numparticles - 1].next = NULL; +} + +//draws all the active particles. +static void PClassic_DrawParticles(void) +{ + RSpeedLocals(); + + cparticle_t *p, *kill; + int i; + float time2, time3, time1, dvel, frametime, grav; +#ifdef RGLQUAKE + unsigned char *at, theAlpha; + vec3_t up, right; + float dist, scale, r_partscale; +#endif + + if (!active_particles) + return; + + switch(qrenderer) + { +#ifdef RGLQUAKE + case QR_OPENGL: + r_partscale = 0.004 * tan (r_refdef.fov_x * (M_PI / 180) * 0.5f); + + GL_Bind(particlecqtexture); + + qglEnable (GL_BLEND); + if (!gl_solidparticles.value) + qglDepthMask (GL_FALSE); + qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + qglBegin (GL_TRIANGLES); + + VectorScale (vup, 1.5, up); + VectorScale (vright, 1.5, right); + break; +#endif +#ifdef SWQUAKE + case QR_SOFTWARE: + VectorScale (vright, xscaleshrink, r_pright); + VectorScale (vup, yscaleshrink, r_pup); + VectorCopy (vpn, r_ppn); + break; +#endif + default: + return; + } + + frametime = host_frametime; + if (cl.paused) + frametime = 0; + time3 = frametime * 15; + time2 = frametime * 10; // 15; + time1 = frametime * 5; + grav = frametime * 800 * 0.05; + dvel = 4 * frametime; + + while(1) + { + kill = active_particles; + if (kill && kill->die < cl.time) + { + active_particles = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + for (p = active_particles; p ; p = p->next) + { + while (1) + { + kill = p->next; + if (kill && kill->die < cl.time) + { + p->next = kill->next; + kill->next = free_particles; + free_particles = kill; + continue; + } + break; + } + + switch(qrenderer) + { +#ifdef RGLQUAKE + case QR_OPENGL: + // hack a scale up to keep particles from disapearing + dist = (p->org[0] - r_origin[0]) * vpn[0] + (p->org[1] - r_origin[1]) * vpn[1] + (p->org[2] - r_origin[2]) * vpn[2]; + scale = 1 + dist * r_partscale; + + at = (qbyte *) &d_8to24rgbtable[(int)p->color]; + if (p->type == pt_fire) + theAlpha = 255 * (6 - p->ramp) / 6; + else + theAlpha = 255; + qglColor4ub (*at, *(at + 1), *(at + 2), theAlpha); + qglTexCoord2f (0, 0); qglVertex3fv (p->org); + qglTexCoord2f (1, 0); qglVertex3f (p->org[0] + up[0] * scale, p->org[1] + up[1] * scale, p->org[2] + up[2] * scale); + qglTexCoord2f (0, 1); qglVertex3f (p->org[0] + right[0] * scale, p->org[1] + right[1] * scale, p->org[2] + right[2] * scale); + break; +#endif +#ifdef SWQUAKE + case QR_SOFTWARE: + D_DrawParticleTrans (p->org, 1, 1, p->color, BM_BLEND); + break; +#endif + } + + p->org[0] += p->vel[0] * frametime; + p->org[1] += p->vel[1] * frametime; + p->org[2] += p->vel[2] * frametime; + + switch (p->type) + { + case pt_static: + break; + case pt_fire: + p->ramp += time1; + if (p->ramp >= 6) + p->die = -1; + else + p->color = ramp3[(int) p->ramp]; + p->vel[2] += grav; + break; + case pt_explode: + p->ramp += time2; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp1[(int) p->ramp]; + for (i = 0; i < 3; i++) + p->vel[i] += p->vel[i] * dvel; + p->vel[2] -= grav * 30; + break; + case pt_explode2: + p->ramp += time3; + if (p->ramp >=8) + p->die = -1; + else + p->color = ramp2[(int) p->ramp]; + for (i = 0; i < 3; i++) + p->vel[i] -= p->vel[i] * frametime; + p->vel[2] -= grav * 30; + break; + case pt_blob: + for (i = 0; i < 3; i++) + p->vel[i] += p->vel[i] * dvel; + p->vel[2] -= grav; + break; + case pt_blob2: + for (i = 0; i < 2; i++) + p->vel[i] -= p->vel[i] * dvel; + p->vel[2] -= grav; + break; + case pt_slowgrav: + case pt_grav: + p->vel[2] -= grav; + break; + } + } + + switch(qrenderer) + { +#ifdef RGLQUAKE + case QR_OPENGL: + qglEnd (); + qglDisable (GL_BLEND); + qglDepthMask (GL_TRUE); + qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + qglColor3ub (255, 255, 255); + break; +#endif + default: + break; + } + + + + + +//this... is hard to explain. +//please don't make me do so. +#ifdef RGLQUAKE + RSpeedRemark(); + qglBegin(GL_QUADS); + RQ_RenderDistAndClear(); + qglEnd(); + RSpeedEnd(RSPEED_PARTICLESDRAW); +#endif +} + +//called to set up the rendering state (opengl) +static void PClassic_FlushRenderer(void) +{ +} + + + +static void Classic_ParticleExplosion (vec3_t org) +{ + int i, j; + cparticle_t *p; + + for (i = 0; i < 1024; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 5; + p->color = ramp1[0]; + p->ramp = rand() & 3; + if (i & 1) + { + p->type = pt_explode; + for (j = 0; j < 3; j++) + { + p->org[j] = org[j] + ((rand() % 32) - 16); + p->vel[j] = (rand() % 512) - 256; + } + } + else + { + p->type = pt_explode2; + for (j = 0; j < 3; j++) + { + p->org[j] = org[j] + ((rand() % 32) - 16); + p->vel[j] = (rand()%512) - 256; + } + } + } +} + +static void Classic_BlobExplosion (vec3_t org) +{ + int i, j; + cparticle_t *p; + + for (i = 0; i < 1024; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 1 + (rand() & 8) * 0.05; + + if (i & 1) + { + p->type = pt_blob; + p->color = 66 + rand() % 6; + for (j = 0; j < 3; j++) + { + p->org[j] = org[j] + ((rand() % 32) - 16); + p->vel[j] = (rand() % 512) - 256; + } + } + else + { + p->type = pt_blob2; + p->color = 150 + rand() % 6; + for (j = 0; j < 3; j++) + { + p->org[j] = org[j] + ((rand() % 32) - 16); + p->vel[j] = (rand() % 512) - 256; + } + } + } +} + +static void Classic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + int i, j, scale; + cparticle_t *p; + + if (!dir) + dir = vec3_origin; + + scale = (count > 130) ? 3 : (count > 20) ? 2 : 1; + + for (i = 0; i < count; i++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.1 * (rand() % 5); + p->color = (color & ~7) + (rand() & 7); + p->type = pt_grav; + for (j = 0; j < 3; j++) + { + p->org[j] = org[j] + scale * ((rand() & 15) - 8); + p->vel[j] = dir[j] * 15; + } + } +} + +static void Classic_LavaSplash (vec3_t org) +{ + int i, j, k; + cparticle_t *p; + float vel; + vec3_t dir; + + for (i = -16; i < 16; i++) + { + for (j = -16; j < 16; j++) + { + for (k = 0; k < 1; k++) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 2 + (rand() & 31) * 0.02; + p->color = 224 + (rand() & 7); + p->type = pt_grav; + + dir[0] = j * 8 + (rand() & 7); + dir[1] = i * 8 + (rand() & 7); + dir[2] = 256; + + p->org[0] = org[0] + dir[0]; + p->org[1] = org[1] + dir[1]; + p->org[2] = org[2] + (rand() & 63); + + VectorNormalizeFast (dir); + vel = 50 + (rand() & 63); + VectorScale (dir, vel, p->vel); + } + } + } +} + +static void Classic_TeleportSplash (vec3_t org) +{ + int i, j, k; + cparticle_t *p; + float vel; + vec3_t dir; + + for (i = -16; i < 16; i += 4) + { + for (j = -16; j < 16; j += 4) + { + for (k = -24; k < 32; k += 4) + { + if (!free_particles) + return; + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + p->die = cl.time + 0.2 + (rand() & 7) * 0.02; + p->color = 7 + (rand() & 7); + p->type = pt_grav; + + dir[0] = j * 8; + dir[1] = i * 8; + dir[2] = k * 8; + + p->org[0] = org[0] + i + (rand() & 3); + p->org[1] = org[1] + j + (rand() & 3); + p->org[2] = org[2] + k + (rand() & 3); + + VectorNormalizeFast (dir); + vel = 50 + (rand() & 63); + VectorScale (dir, vel, p->vel); + } + } + } +} + +static void Classic_ParticleTrail (vec3_t start, vec3_t end, vec3_t *trail_origin, effect_type_t type) +{ + vec3_t point, delta, dir; + float len; + int i, j, num_particles; + cparticle_t *p; + static int tracercount; + + VectorCopy (start, point); + VectorSubtract (end, start, delta); + if (!(len = VectorLength (delta))) + goto done; + VectorScale(delta, 1 / len, dir); //unit vector in direction of trail + + switch (type) { + case ALT_ROCKET_TRAIL: + len /= 1.5; break; + case BLOOD_TRAIL: + len /= 6; break; + default: + len /= 3; break; + } + + if (!(num_particles = (int) len)) + goto done; + + VectorScale (delta, 1.0 / num_particles, delta); + + for (i = 0; i < num_particles && free_particles; i++) { + p = free_particles; + free_particles = p->next; + p->next = active_particles; + active_particles = p; + + VectorClear (p->vel); + p->die = cl.time + 2; + + switch(type) { + case GRENADE_TRAIL: + p->ramp = (rand() & 3) + 2; + p->color = ramp3[(int) p->ramp]; + p->type = pt_fire; + for (j = 0; j < 3; j++) + p->org[j] = point[j] + ((rand() % 6) - 3); + break; + case BLOOD_TRAIL: + p->type = pt_slowgrav; + p->color = 67 + (rand() & 3); + for (j = 0; j < 3; j++) + p->org[j] = point[j] + ((rand() % 6) - 3); + break; + case BIG_BLOOD_TRAIL: + p->type = pt_slowgrav; + p->color = 67 + (rand() & 3); + for (j = 0; j < 3; j++) + p->org[j] = point[j] + ((rand() % 6) - 3); + break; + case TRACER1_TRAIL: + case TRACER2_TRAIL: + p->die = cl.time + 0.5; + p->type = pt_static; + if (type == TRACER1_TRAIL) + p->color = 52 + ((tracercount & 4) << 1); + else + p->color = 230 + ((tracercount & 4) << 1); + + tracercount++; + + VectorCopy (point, p->org); + if (tracercount & 1) { + p->vel[0] = 90 * dir[1]; + p->vel[1] = 90 * -dir[0]; + } else { + p->vel[0] = 90 * -dir[1]; + p->vel[1] = 90 * dir[0]; + } + break; + case VOOR_TRAIL: + p->color = 9 * 16 + 8 + (rand() & 3); + p->type = pt_static; + p->die = cl.time + 0.3; + for (j = 0; j < 3; j++) + p->org[j] = point[j] + ((rand() & 15) - 8); + break; + case ALT_ROCKET_TRAIL: + p->ramp = (rand() & 3); + p->color = ramp3[(int) p->ramp]; + p->type = pt_fire; + for (j = 0; j < 3; j++) + p->org[j] = point[j] + ((rand() % 6) - 3); + break; + case ROCKET_TRAIL: + default: + p->ramp = (rand() & 3); + p->color = ramp3[(int) p->ramp]; + p->type = pt_fire; + for (j = 0; j < 3; j++) + p->org[j] = point[j] + ((rand() % 6) - 3); + break; + } + VectorAdd (point, delta, point); + } +done: + if (trail_origin) + VectorCopy(point, *trail_origin); +} + + + +//builds a trail from here to there. The trail state can be used to remember how far you got last frame. +static int PClassic_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk) +{ + if (type == P_INVALID) + return 1; + + Classic_ParticleTrail(startpos, end, NULL, type); + return 0; +} + +//svc_tempentity support: this is the function that handles 'special' point effects. +//use the trail state so fast/slow frames keep the correct particle counts on certain every-frame effects +static int PClassic_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk) +{ + switch(typenum) + { + case BLOBEXPLOSION_POINT: + Classic_BlobExplosion(org); + break; + case LAVASPLASH_POINT: + Classic_LavaSplash(org); + break; + case EXPLOSION_POINT: + Classic_ParticleExplosion(org); + break; + case TELEPORTSPLASH_POINT: + Classic_TeleportSplash(org); + break; + default: + return 1; + } + return 0; +} + +//svc_particle support: add X particles with the given colour, velocity, and aproximate origin. +static void PClassic_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + Classic_RunParticleEffect(org, dir, color, count); +} + + +particleengine_t pe_classic = +{ + "Classic", + NULL, + + PClassic_ParticleTypeForName, + PClassic_FindParticleType, + + PClassic_RunParticleEffectTypeString, + PClassic_ParticleTrail, + PClassic_RunParticleEffectState, + PClassic_RunParticleWeather, + PClassic_RunParticleCube, + PClassic_RunParticleEffect, + PClassic_RunParticleEffect2, + PClassic_RunParticleEffect3, + PClassic_RunParticleEffect4, + + PClassic_ParticleTrailIndex, + PClassic_EmitSkyEffectTris, + PClassic_InitParticles, + PClassic_ShutdownParticles, + PClassic_DelinkTrailstate, + PClassic_ClearParticles, + PClassic_DrawParticles, + PClassic_FlushRenderer +}; + +#endif diff --git a/engine/client/p_null.c b/engine/client/p_null.c new file mode 100644 index 000000000..dda443984 --- /dev/null +++ b/engine/client/p_null.c @@ -0,0 +1,87 @@ +#include "quakedef.h" +#include "glquake.h" + +#include "particles.h" + +//obtains an index for the name, even if it is unknown (one can be loaded after. will only fail if the effect limit is reached) +static int PNULL_ParticleTypeForName(char *name) +{ + Con_Printf("P_ParticleTypeForName %s\n", name); + return P_INVALID; +} + +//returns a valid effect if its existance is known, even if simply referenced. This should be phased out. +static int PNULL_FindParticleType(char *name) +{ + Con_Printf("P_FindParticleType %s\n", name); + return P_INVALID; +} + +static int PNULL_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name){return 1;} +static int PNULL_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk){return 1;} +static int PNULL_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk){return 1;} +static void PNULL_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname){} +static void PNULL_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter){} +static void PNULL_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count){} +static void PNULL_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count){} +static void PNULL_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int effect, int count){} +static void PNULL_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count){} + +static void PNULL_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk){} +static void PNULL_EmitSkyEffectTris(model_t *mod, msurface_t *fa){} + +static void PNULL_InitParticles (void) +{ + CL_RegisterParticles(); +} + +static void PNULL_ShutdownParticles(void) +{ +} + +static void PNULL_DelinkTrailstate(trailstate_t **tsk){} +static void PNULL_ClearParticles (void){} +static void PNULL_DrawParticles(void) +{ + RSpeedLocals(); + + RSpeedRemark(); +#ifdef GLQUAKE + qglBegin(GL_QUADS); + RQ_RenderDistAndClear(); + qglEnd(); +#endif + RSpeedEnd(RSPEED_PARTICLESDRAW); +} +static void PNULL_FlushRenderer(void) +{ +} + + +particleengine_t pe_null = +{ + "null", + "none", + + PNULL_ParticleTypeForName, + PNULL_FindParticleType, + + PNULL_RunParticleEffectTypeString, + PNULL_ParticleTrail, + PNULL_RunParticleEffectState, + PNULL_RunParticleWeather, + PNULL_RunParticleCube, + PNULL_RunParticleEffect, + PNULL_RunParticleEffect2, + PNULL_RunParticleEffect3, + PNULL_RunParticleEffect4, + + PNULL_ParticleTrailIndex, + PNULL_EmitSkyEffectTris, + PNULL_InitParticles, + PNULL_ShutdownParticles, + PNULL_DelinkTrailstate, + PNULL_ClearParticles, + PNULL_DrawParticles, + PNULL_FlushRenderer +}; \ No newline at end of file diff --git a/engine/client/p_script.c b/engine/client/p_script.c new file mode 100644 index 000000000..b4d3776c9 --- /dev/null +++ b/engine/client/p_script.c @@ -0,0 +1,4340 @@ +/* +Copyright (C) 1996-1997 Id Software, Inc. + +This program 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 +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +/* +The aim of this particle system is to have as much as possible configurable. +Some parts still fail here, and are marked FIXME +Effects are flushed on new maps. +The engine has a few builtins. +*/ + +#include "quakedef.h" + +#ifdef PSET_SCRIPT + +#ifdef SWQUAKE +#include "r_local.h" +#endif +#ifdef RGLQUAKE +#include "glquake.h"//hack +#endif + +#ifdef D3DQUAKE +//d3d is awkward +//we can't include two versions of header files +extern void *d3dexplosiontexture; +extern void *d3dballtexture; +#endif + +#include "renderque.h" + +#include "r_partset.h" + +extern qbyte *host_basepal; + +static int pt_pointfile = P_INVALID; +static int pe_default = P_INVALID; +static int pe_size2 = P_INVALID; +static int pe_size3 = P_INVALID; +static int pe_defaulttrail = P_INVALID; + +// !!! if this is changed, it must be changed in d_ifacea.h too !!! +typedef struct particle_s +{ + struct particle_s *next; + float die; + +// driver-usable fields + vec3_t org; + float color; //used by sw renderer. To be removed. + vec3_t rgb; + float alpha; + float scale; + + vec3_t vel; //renderer uses for sparks + float angle; + union { + float nextemit; + trailstate_t *trailstate; + } state; +// drivers never touch the following fields + float rotationspeed; +} particle_t; + +typedef struct clippeddecal_s +{ + struct clippeddecal_s *next; + float die; + + vec3_t center; + vec3_t vertex[3]; + vec2_t texcoords[3]; + + vec3_t rgb; + float alpha; +} clippeddecal_t; + +#define BS_LASTSEG 0x1 // no draw to next, no delete +#define BS_DEAD 0x2 // segment is dead +#define BS_NODRAW 0x4 // only used for lerp switching + +typedef struct beamseg_s +{ + struct beamseg_s *next; // next in beamseg list + + particle_t *p; + int flags; // flags for beamseg + vec3_t dir; + + float texture_s; +} beamseg_t; + + + +typedef struct skytris_s { + struct skytris_s *next; + vec3_t org; + vec3_t x; + vec3_t y; + float area; + float nexttime; + struct msurface_s *face; +} skytris_t; + +//these could be deltas or absolutes depending on ramping mode. +typedef struct { + vec3_t rgb; + float alpha; + float scale; + float rotation; +} ramp_t; +// TODO: merge in alpha with rgb to gain benefit of vector opts +typedef struct part_type_s { + char name[MAX_QPATH]; + char texname[MAX_QPATH]; + vec3_t rgb; + vec3_t rgbchange; + vec3_t rgbrand; + int colorindex; + int colorrand; + float rgbchangetime; + vec3_t rgbrandsync; + float scale, alpha; + float alphachange; + float die, randdie; + float randomvel, veladd; + float orgadd; + float offsetspread; + float offsetspreadvert; + float randomvelvert; + float randscale; + + float spawntime; + float spawnchance; + + enum {PT_NORMAL, PT_SPARK, PT_SPARKFAN, PT_TEXTUREDSPARK, PT_BEAM, PT_DECAL} type; + blendmode_t blendmode; + + float rotationstartmin, rotationstartrand; + float rotationmin, rotationrand; + + float scaledelta; + float count; + float countrand; + int texturenum; +#ifdef D3DQUAKE + void *d3dtexture; +#endif + int assoc; + int cliptype; + int inwater; + float clipcount; + int emit; + float emittime; + float emitrand; + float emitstart; + + float areaspread; + float areaspreadvert; + float scalefactor; + float invscalefactor; + + float spawnparam1; + float spawnparam2; +/* float spawnparam3; */ + + float offsetup; // make this into a vec3_t later with dir, possibly for mdls + + enum { + SM_BOX, //box = even spread within the area + SM_CIRCLE, //circle = around edge of a circle + SM_BALL, //ball = filled sphere + SM_SPIRAL, //spiral = spiral trail + SM_TRACER, //tracer = tracer trail + SM_TELEBOX, //telebox = q1-style telebox + SM_LAVASPLASH, //lavasplash = q1-style lavasplash + SM_UNICIRCLE, //unicircle = uniform circle + SM_FIELD, //field = synced field (brightfield, etc) + SM_DISTBALL // uneven distributed ball + } spawnmode; + + float gravity; + vec3_t friction; + float clipbounce; + int stains; + + enum {RAMP_NONE, RAMP_DELTA, RAMP_ABSOLUTE} rampmode; + int rampindexes; + ramp_t *ramp; + + int loaded; + particle_t *particles; + clippeddecal_t *clippeddecals; + beamseg_t *beams; + skytris_t *skytris; + struct part_type_s *nexttorun; + + unsigned int flags; +#define PT_VELOCITY 0x001 +#define PT_FRICTION 0x002 +#define PT_CHANGESCOLOUR 0x004 +#define PT_CITRACER 0x008 // Q1-style tracer behavior for colorindex +#define PT_INVFRAMETIME 0x010 // apply inverse frametime to count (causes emits to be per frame) +#define PT_AVERAGETRAIL 0x020 // average trail points from start to end, useful with t_lightning, etc +#define PT_NOSTATE 0x040 // don't use trailstate for this emitter (careful with assoc...) +#define PT_NOSPREADFIRST 0x080 // don't randomize org/vel for first generated particle +#define PT_NOSPREADLAST 0x100 // don't randomize org/vel for last generated particle + unsigned int state; +#define PS_INRUNLIST 0x1 // particle type is currently in execution list +} part_type_t; + +void PScript_DrawParticleTypes (void (*texturedparticles)(particle_t *,part_type_t*), void (*sparklineparticles)(particle_t*,part_type_t*), void (*sparkfanparticles)(particle_t*,part_type_t*), void (*sparktexturedparticles)(particle_t*,part_type_t*), void (*beamparticlest)(beamseg_t*,part_type_t*), void (*beamparticlesut)(beamseg_t*,part_type_t*), void (*drawdecalparticles)(clippeddecal_t*,part_type_t*)); + +#ifndef TYPESONLY + +//triangle fan sparks use these. +static double sint[7] = {0.000000, 0.781832, 0.974928, 0.433884, -0.433884, -0.974928, -0.781832}; +static double cost[7] = {1.000000, 0.623490, -0.222521, -0.900969, -0.900969, -0.222521, 0.623490}; + +#define crand() (rand()%32767/16383.5f-1) + +void D_DrawParticleTrans (vec3_t porg, float palpha, float pscale, unsigned int pcolour, blendmode_t blendmode); + +static void P_ReadPointFile_f (void); +static void P_ExportBuiltinSet_f(void); + +#define MAX_BEAMSEGS 2048 // default max # of beam segments +#define MAX_PARTICLES 32768 // default max # of particles at one + // time +#define MAX_DECALS 4096 // this is going to be expensive +#define MAX_TRAILSTATES 512 // default max # of trailstates + +//int ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61}; +//int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; +//int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3, 2, 1}; + +particle_t *free_particles; +particle_t *particles; //contains the initial list of alloced particles. +int r_numparticles; + +beamseg_t *free_beams; +beamseg_t *beams; +int r_numbeams; + +clippeddecal_t *free_decals; +clippeddecal_t *decals; +int r_numdecals; + +trailstate_t *trailstates; +int ts_cycle; // current cyclic index of trailstates +int r_numtrailstates; + +vec3_t r_pright, r_pup, r_ppn; + +extern cvar_t r_bouncysparks; +extern cvar_t r_part_rain; +extern cvar_t r_bloodstains; +extern cvar_t gl_part_flame; + +// callbacks +static void R_ParticlesDesc_Callback(struct cvar_s *var, char *oldvalue); + +extern cvar_t r_particlesdesc; +extern cvar_t r_part_rain_quantity; +extern cvar_t r_particle_tracelimit; +extern cvar_t r_part_sparks; +extern cvar_t r_part_sparks_trifan; +extern cvar_t r_part_sparks_textured; +extern cvar_t r_part_beams; +extern cvar_t r_part_beams_textured; +extern cvar_t r_part_contentswitch; + +static float particletime; + +#define APPLYBLEND(bm) \ + switch (bm) \ + { \ + case BM_ADD: \ + qglBlendFunc(GL_SRC_ALPHA, GL_ONE); \ + break; \ + case BM_SUBTRACT: \ + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR); \ + break; \ + case BM_BLENDCOLOUR: \ + qglBlendFunc(GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR); \ + break; \ + case BM_BLEND: \ + default: \ + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); \ + break; \ + } + +static int numparticletypes; +static part_type_t *part_type; +static part_type_t *part_run_list; + +static struct { + char *oldn; + char *newn; +} legacynames[] = +{ + {"t_rocket", "TR_ROCKET"}, + {"te_explosion", "TE_EXPLOSION"}, + + {"t_blastertrail", "TR_BLASTERTRAIL"}, + {"t_rocket", "TR_ROCKET"}, + {"t_grenade", "TR_GRENADE"}, + {"t_gib", "TR_BLOOD"}, + + {"te_plasma", "TE_TEI_PLASMAHIT"}, + {"te_smoke", "TE_TEI_SMOKE"}, + + {NULL} +}; + +static part_type_t *P_GetParticleType(char *name) +{ + int i; + part_type_t *ptype; + part_type_t *oldlist = part_type; + for (i = 0; legacynames[i].oldn; i++) + { + if (!strcmp(name, legacynames[i].oldn)) + { + name = legacynames[i].newn; + break; + } + } + for (i = 0; i < numparticletypes; i++) + { + ptype = &part_type[i]; + if (!stricmp(ptype->name, name)) + return ptype; + } + part_type = BZ_Realloc(part_type, sizeof(part_type_t)*(numparticletypes+1)); + ptype = &part_type[numparticletypes++]; + strcpy(ptype->name, name); + ptype->assoc=P_INVALID; + ptype->cliptype = P_INVALID; + ptype->emit = P_INVALID; + + if (oldlist) + { + part_run_list=NULL; + + for (i = 0; i < numparticletypes; i++) + if (part_type[i].nexttorun) + part_type[i].nexttorun = (part_type_t*)((char*)part_type[i].nexttorun - (char*)oldlist + (char*)part_type); + } + + ptype->loaded = 0; + ptype->ramp = NULL; + ptype->particles = NULL; + ptype->beams = NULL; + return ptype; +} + +static int P_AllocateParticleType(char *name) //guarentees that the particle type exists, returning it's index. +{ + part_type_t *pt = P_GetParticleType(name); + return pt - part_type; +} + +static int PScript_ParticleTypeForName(char *name) +{ + int to; + + to = P_GetParticleType(name) - part_type; + if (to < 0 || to >= numparticletypes) + { + return P_INVALID; + } + + return to; +} + +static int PScript_FindParticleType(char *name) +{ + int i; + part_type_t *ptype = NULL; + + for (i = 0; legacynames[i].oldn; i++) + { + if (!strcmp(name, legacynames[i].oldn)) + { + name = legacynames[i].newn; + break; + } + } + + for (i = 0; i < numparticletypes; i++) + { + if (!stricmp(part_type[i].name, name)) + { + ptype = &part_type[i]; + break; + } + } + if (!ptype) + return P_INVALID; + if (!ptype->loaded) + return P_INVALID; + return i; +} + +static void P_SetModified(void) //called when the particle system changes (from console). +{ + if (Cmd_FromGamecode()) + return; //server stuffed particle descriptions don't count. + + f_modified_particles = true; + + if (care_f_modified) + { + care_f_modified = false; + Cbuf_AddText("say particles description has changed\n", RESTRICT_LOCAL); + } +} +static int CheckAssosiation(char *name, int from) +{ + int to, orig; + + orig = to = P_AllocateParticleType(name); + + while(to != P_INVALID) + { + if (to == from) + { + Con_Printf("Assosiation of %s would cause infinate loop\n", name); + return P_INVALID; + } + to = part_type[to].assoc; + } + return orig; +} + +static void P_LoadTexture(part_type_t *ptype, qboolean warn) +{ + switch (qrenderer) + { +#ifdef RGLQUAKE + case QR_OPENGL: + if (*ptype->texname && strcmp(ptype->texname, "default")) + { + ptype->texturenum = Mod_LoadHiResTexture(ptype->texname, "particles", true, true, true); + + if (!ptype->texturenum) + { + if (warn) + Con_DPrintf("Couldn't load texture %s for particle effect %s\n", ptype->texname, ptype->name); + + if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball")) + ptype->texturenum = balltexture; + else + ptype->texturenum = explosiontexture; + } + } + else + ptype->texturenum = explosiontexture; + break; +#endif +#ifdef D3DQUAKE + case QR_DIRECT3D: + if (*ptype->texname && strcmp(ptype->texname, "default")) + { + ptype->d3dtexture = NULL;//Mod_LoadHiResTexture(ptype->texname, "particles", true, true, true); + + if (!ptype->d3dtexture) + { + if (warn) + Con_DPrintf("Couldn't load texture %s for particle effect %s\n", ptype->texname, ptype->name); + + if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball")) + ptype->d3dtexture = d3dballtexture; + else + ptype->d3dtexture = d3dexplosiontexture; + } + } + else + ptype->d3dtexture = d3dexplosiontexture; + break; +#endif + default: + break; + } +} + +//Uses FTE's multiline console stuff. +//This is the function that loads the effect descriptions (via console). +static void P_ParticleEffect_f(void) +{ + char *var, *value; + char *buf; + particle_t *parts; + beamseg_t *beamsegs; + skytris_t *st; + qboolean settype = false; + qboolean setalphadelta = false; + qboolean setbeamlen = false; + + part_type_t *ptype, *torun; + char tnamebuf[sizeof(ptype->name)]; + int pnum, assoc; + + if (Cmd_Argc()!=2) + { + Con_Printf("No name for particle effect\n"); + return; + } + + buf = Cbuf_GetNext(Cmd_ExecLevel); + while (*buf && *buf <= ' ') + buf++; //no whitespace please. + if (*buf != '{') + { + Cbuf_InsertText(buf, Cmd_ExecLevel, true); + Con_Printf("This is a multiline command and should be used within config files\n"); + return; + } + + ptype = P_GetParticleType(Cmd_Argv(1)); + if (!ptype) + { + Con_Printf("Bad name\n"); + return; + } + + P_SetModified(); + + pnum = ptype-part_type; + + st = ptype->skytris; + if (ptype->ramp) + BZ_Free(ptype->ramp); + + while (ptype->particles) // empty particle list + { + parts = ptype->particles->next; + ptype->particles->next = free_particles; + free_particles = ptype->particles; + ptype->particles = parts; + } + + // go with a lazy clear of list.. mark everything as DEAD and let + // the beam rendering handle removing nodes + beamsegs = ptype->beams; + while (beamsegs) + { + beamsegs->flags |= BS_DEAD; + beamsegs = beamsegs->next; + } + + beamsegs = ptype->beams; + + // if we're in the runstate loop through and remove from linked list + if (ptype->state & PS_INRUNLIST) + { + if (part_run_list == ptype) + part_run_list = part_run_list->nexttorun; + else + { + for (torun = part_run_list; torun != NULL; torun = torun->nexttorun) + { + if (torun->nexttorun == ptype) + torun->nexttorun = torun->nexttorun->nexttorun; + } + } + } + + strcpy(tnamebuf, ptype->name); + memset(ptype, 0, sizeof(*ptype)); +// ptype->particles = parts; + ptype->beams = beamsegs; + ptype->skytris = st; + strcpy(ptype->name, tnamebuf); + ptype->assoc=P_INVALID; + ptype->inwater = P_INVALID; + ptype->cliptype = P_INVALID; + ptype->emit = P_INVALID; + ptype->alpha = 1; + ptype->alphachange = 1; + ptype->clipbounce = 0.8; + ptype->colorindex = -1; + ptype->rotationstartmin = -M_PI; //start with a random angle + ptype->rotationstartrand = M_PI-ptype->rotationstartmin; + ptype->spawnchance = 1; + + while(1) + { + buf = Cbuf_GetNext(Cmd_ExecLevel); + if (!*buf) + { + Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name); + return; + } + + while (*buf && *buf <= ' ') + buf++; //no whitespace please. + if (*buf == '}') + break; + + Cmd_TokenizeString(buf, true, true); + var = Cmd_Argv(0); + value = Cmd_Argv(1); + + // TODO: switch this mess to some sort of binary tree to increase + // parse speed + if (!strcmp(var, "texture")) + Q_strncpyz(ptype->texname, value, sizeof(ptype->texname)); + else if (!strcmp(var, "rotationstart")) + { + ptype->rotationstartmin = atof(value)*M_PI/180; + if (Cmd_Argc()>2) + ptype->rotationstartrand = atof(Cmd_Argv(2))*M_PI/180-ptype->rotationstartmin; + else + ptype->rotationstartrand = 0; + } + else if (!strcmp(var, "rotationspeed")) + { + ptype->rotationmin = atof(value)*M_PI/180; + if (Cmd_Argc()>2) + ptype->rotationrand = atof(Cmd_Argv(2))*M_PI/180-ptype->rotationmin; + else + ptype->rotationrand = 0; + } + else if (!strcmp(var, "beamtexstep")) + { + ptype->rotationstartmin = 1/atof(value); + setbeamlen = true; + } + else if (!strcmp(var, "beamtexspeed")) + { + ptype->rotationmin = atof(value); + } + else if (!strcmp(var, "scale")) + { + ptype->scale = atof(value); + if (Cmd_Argc()>2) + ptype->randscale = atof(Cmd_Argv(2)) - ptype->scale; + } + else if (!strcmp(var, "scalerand")) + ptype->randscale = atof(value); + + else if (!strcmp(var, "scalefactor")) + ptype->scalefactor = atof(value); + else if (!strcmp(var, "scaledelta")) + ptype->scaledelta = atof(value); + + + else if (!strcmp(var, "step")) + { + ptype->count = 1/atof(value); + if (Cmd_Argc()>2) + ptype->countrand = 1/atof(Cmd_Argv(2)); + } + else if (!strcmp(var, "count")) + { + ptype->count = atof(value); + if (Cmd_Argc()>2) + ptype->countrand = atof(Cmd_Argv(2)); + } + + else if (!strcmp(var, "alpha")) + ptype->alpha = atof(value); + else if (!strcmp(var, "alphachange")) + { + Con_DPrintf("alphachange is deprechiated, use alphadelta\n"); + ptype->alphachange = atof(value); + } + else if (!strcmp(var, "alphadelta")) + { + ptype->alphachange = atof(value); + setalphadelta = true; + } + else if (!strcmp(var, "die")) + ptype->die = atof(value); + else if (!strcmp(var, "diesubrand")) + ptype->randdie = atof(value); + + else if (!strcmp(var, "randomvel")) + { + ptype->randomvel = atof(value); + if (Cmd_Argc()>2) + ptype->randomvelvert = atof(Cmd_Argv(2)); + else + ptype->randomvelvert = ptype->randomvel; + } + else if (!strcmp(var, "veladd")) + ptype->veladd = atof(value); + else if (!strcmp(var, "orgadd")) + ptype->orgadd = atof(value); + else if (!strcmp(var, "friction")) + { + ptype->friction[2] = ptype->friction[1] = ptype->friction[0] = atof(value); + + if (Cmd_Argc()>3) + { + ptype->friction[2] = atof(Cmd_Argv(3)); + ptype->friction[1] = atof(Cmd_Argv(2)); + } + else if (Cmd_Argc()>2) + { + ptype->friction[2] = atof(Cmd_Argv(2)); + } + } + else if (!strcmp(var, "gravity")) + ptype->gravity = atof(value); + else if (!strcmp(var, "clipbounce")) + ptype->clipbounce = atof(value); + + else if (!strcmp(var, "assoc")) + { + assoc = CheckAssosiation(value, pnum); //careful - this can realloc all the particle types + ptype = &part_type[pnum]; + ptype->assoc = assoc; + } + else if (!strcmp(var, "inwater")) + { + // the underwater effect switch should only occur for + // 1 level so the standard assoc check works + assoc = CheckAssosiation(value, pnum); + ptype = &part_type[pnum]; + ptype->inwater = assoc; + } + else if (!strcmp(var, "colorindex")) + { + if (Cmd_Argc()>2) + ptype->colorrand = atof(Cmd_Argv(2)); + ptype->colorindex = atoi(value); + } + else if (!strcmp(var, "colorrand")) + ptype->colorrand = atoi(value); // now obsolete + else if (!strcmp(var, "citracer")) + ptype->flags |= PT_CITRACER; + + else if (!strcmp(var, "red")) + ptype->rgb[0] = atof(value)/255; + else if (!strcmp(var, "green")) + ptype->rgb[1] = atof(value)/255; + else if (!strcmp(var, "blue")) + ptype->rgb[2] = atof(value)/255; + else if (!strcmp(var, "rgb")) + { + ptype->rgb[0] = ptype->rgb[1] = ptype->rgb[2] = atof(value)/255; + if (Cmd_Argc()>3) + { + ptype->rgb[1] = atof(Cmd_Argv(2))/255; + ptype->rgb[2] = atof(Cmd_Argv(3))/255; + } + } + + else if (!strcmp(var, "reddelta")) + { + ptype->rgbchange[0] = atof(value)/255; + if (!ptype->rgbchangetime) + ptype->rgbchangetime = ptype->die; + } + else if (!strcmp(var, "greendelta")) + { + ptype->rgbchange[1] = atof(value)/255; + if (!ptype->rgbchangetime) + ptype->rgbchangetime = ptype->die; + } + else if (!strcmp(var, "bluedelta")) + { + ptype->rgbchange[2] = atof(value)/255; + if (!ptype->rgbchangetime) + ptype->rgbchangetime = ptype->die; + } + else if (!strcmp(var, "rgbdelta")) + { + ptype->rgbchange[0] = ptype->rgbchange[1] = ptype->rgbchange[2] = atof(value)/255; + if (Cmd_Argc()>3) + { + ptype->rgbchange[1] = atof(Cmd_Argv(2))/255; + ptype->rgbchange[2] = atof(Cmd_Argv(3))/255; + } + if (!ptype->rgbchangetime) + ptype->rgbchangetime = ptype->die; + } + else if (!strcmp(var, "rgbdeltatime")) + ptype->rgbchangetime = atof(value); + + else if (!strcmp(var, "redrand")) + ptype->rgbrand[0] = atof(value)/255; + else if (!strcmp(var, "greenrand")) + ptype->rgbrand[1] = atof(value)/255; + else if (!strcmp(var, "bluerand")) + ptype->rgbrand[2] = atof(value)/255; + else if (!strcmp(var, "rgbrand")) + { + ptype->rgbrand[0] = ptype->rgbrand[1] = ptype->rgbrand[2] = atof(value)/255; + if (Cmd_Argc()>3) + { + ptype->rgbrand[1] = atof(Cmd_Argv(2))/255; + ptype->rgbrand[2] = atof(Cmd_Argv(3))/255; + } + } + + else if (!strcmp(var, "rgbrandsync")) + { + ptype->rgbrandsync[0] = ptype->rgbrandsync[1] = ptype->rgbrandsync[2] = atof(value); + if (Cmd_Argc()>3) + { + ptype->rgbrandsync[1] = atof(Cmd_Argv(2)); + ptype->rgbrandsync[2] = atof(Cmd_Argv(3)); + } + } + else if (!strcmp(var, "redrandsync")) + ptype->rgbrandsync[0] = atof(value); + else if (!strcmp(var, "greenrandsync")) + ptype->rgbrandsync[1] = atof(value); + else if (!strcmp(var, "bluerandsync")) + ptype->rgbrandsync[2] = atof(value); + + else if (!strcmp(var, "stains")) + ptype->stains = atoi(value); + else if (!strcmp(var, "blend")) + { + if (!strcmp(value, "add")) + ptype->blendmode = BM_ADD; + else if (!strcmp(value, "subtract")) + ptype->blendmode = BM_SUBTRACT; + else if (!strcmp(value, "blendcolour") || !strcmp(value, "blendcolor")) + ptype->blendmode = BM_BLENDCOLOUR; + else + ptype->blendmode = BM_BLEND; + } + else if (!strcmp(var, "spawnmode")) + { + if (!strcmp(value, "circle")) + ptype->spawnmode = SM_CIRCLE; + else if (!strcmp(value, "ball")) + ptype->spawnmode = SM_BALL; + else if (!strcmp(value, "spiral")) + ptype->spawnmode = SM_SPIRAL; + else if (!strcmp(value, "tracer")) + ptype->spawnmode = SM_TRACER; + else if (!strcmp(value, "telebox")) + ptype->spawnmode = SM_TELEBOX; + else if (!strcmp(value, "lavasplash")) + ptype->spawnmode = SM_LAVASPLASH; + else if (!strcmp(value, "uniformcircle")) + ptype->spawnmode = SM_UNICIRCLE; + else if (!strcmp(value, "syncfield")) + ptype->spawnmode = SM_FIELD; + else if (!strcmp(value, "distball")) + ptype->spawnmode = SM_DISTBALL; + else + ptype->spawnmode = SM_BOX; + + if (Cmd_Argc()>2) + { + if (Cmd_Argc()>3) + ptype->spawnparam2 = atof(Cmd_Argv(3)); + ptype->spawnparam1 = atof(Cmd_Argv(2)); + } + } + else if (!strcmp(var, "type")) + { + if (!strcmp(value, "beam")) + ptype->type = PT_BEAM; + else if (!strcmp(value, "spark")) + ptype->type = PT_SPARK; + else if (!strcmp(value, "sparkfan") || !strcmp(value, "trianglefan")) + ptype->type = PT_SPARKFAN; + else if (!strcmp(value, "texturedspark")) + ptype->type = PT_TEXTUREDSPARK; + else if (!strcmp(value, "decal")) + ptype->type = PT_DECAL; + else + ptype->type = PT_NORMAL; + settype = true; + } + else if (!strcmp(var, "isbeam")) + { + Con_DPrintf("isbeam is deprechiated, use type beam\n"); + ptype->type = PT_BEAM; + } + else if (!strcmp(var, "spawntime")) + ptype->spawntime = atof(value); + else if (!strcmp(var, "spawnchance")) + ptype->spawnchance = atof(value); + else if (!strcmp(var, "cliptype")) + { + assoc = P_ParticleTypeForName(value);//careful - this can realloc all the particle types + ptype = &part_type[pnum]; + ptype->cliptype = assoc; + } + else if (!strcmp(var, "clipcount")) + ptype->clipcount = atof(value); + + else if (!strcmp(var, "emit")) + { + assoc = P_ParticleTypeForName(value);//careful - this can realloc all the particle types + ptype = &part_type[pnum]; + ptype->emit = assoc; + } + else if (!strcmp(var, "emitinterval")) + ptype->emittime = atof(value); + else if (!strcmp(var, "emitintervalrand")) + ptype->emitrand = atof(value); + else if (!strcmp(var, "emitstart")) + ptype->emitstart = atof(value); + + // old names + else if (!strcmp(var, "areaspread")) + { + Con_DPrintf("areaspread is deprechiated, use spawnorg\n"); + ptype->areaspread = atof(value); + } + else if (!strcmp(var, "areaspreadvert")) + { + Con_DPrintf("areaspreadvert is deprechiated, use spawnorg\n"); + ptype->areaspreadvert = atof(value); + } + else if (!strcmp(var, "offsetspread")) + { + Con_DPrintf("offsetspread is deprechiated, use spawnvel\n"); + ptype->offsetspread = atof(value); + } + else if (!strcmp(var, "offsetspreadvert")) + { + Con_DPrintf("offsetspreadvert is deprechiated, use spawnvel\n"); + ptype->offsetspreadvert = atof(value); + } + + // new names + else if (!strcmp(var, "spawnorg")) + { + ptype->areaspreadvert = ptype->areaspread = atof(value); + + if (Cmd_Argc()>2) + ptype->areaspreadvert = atof(Cmd_Argv(2)); + } + else if (!strcmp(var, "spawnvel")) + { + ptype->offsetspreadvert = ptype->offsetspread = atof(value); + + if (Cmd_Argc()>2) + ptype->offsetspreadvert = atof(Cmd_Argv(2)); + } + + // spawn mode param fields + else if (!strcmp(var, "spawnparam1")) + ptype->spawnparam1 = atof(value); + else if (!strcmp(var, "spawnparam2")) + ptype->spawnparam2 = atof(value); +/* else if (!strcmp(var, "spawnparam3")) + ptype->spawnparam3 = atof(value); */ + + else if (!strcmp(var, "up")) + ptype->offsetup = atof(value); + else if (!strcmp(var, "rampmode")) + { + if (!strcmp(value, "none")) + ptype->rampmode = RAMP_NONE; + else if (!strcmp(value, "absolute")) + ptype->rampmode = RAMP_ABSOLUTE; + else //if (!strcmp(value, "delta")) + ptype->rampmode = RAMP_DELTA; + } + else if (!strcmp(var, "rampindexlist")) + { // better not use this with delta ramps... + int cidx, i; + + i = 1; + while (i < Cmd_Argc()) + { + ptype->ramp = BZ_Realloc(ptype->ramp, sizeof(ramp_t)*(ptype->rampindexes+1)); + + cidx = atoi(Cmd_Argv(i)); + ptype->ramp[ptype->rampindexes].alpha = cidx > 255 ? 0.5 : 1; + + cidx = (cidx & 0xff) * 3; + ptype->ramp[ptype->rampindexes].rgb[0] = host_basepal[cidx] * (1/255.0); + ptype->ramp[ptype->rampindexes].rgb[1] = host_basepal[cidx+1] * (1/255.0); + ptype->ramp[ptype->rampindexes].rgb[2] = host_basepal[cidx+2] * (1/255.0); + + ptype->ramp[ptype->rampindexes].scale = ptype->scale; + + ptype->rampindexes++; + i++; + } + } + else if (!strcmp(var, "rampindex")) + { + int cidx; + ptype->ramp = BZ_Realloc(ptype->ramp, sizeof(ramp_t)*(ptype->rampindexes+1)); + + cidx = atoi(value); + ptype->ramp[ptype->rampindexes].alpha = cidx > 255 ? 0.5 : 1; + + if (Cmd_Argc() > 2) // they gave alpha + ptype->ramp[ptype->rampindexes].alpha *= atof(Cmd_Argv(2)); + + cidx = (cidx & 0xff) * 3; + ptype->ramp[ptype->rampindexes].rgb[0] = host_basepal[cidx] * (1/255.0); + ptype->ramp[ptype->rampindexes].rgb[1] = host_basepal[cidx+1] * (1/255.0); + ptype->ramp[ptype->rampindexes].rgb[2] = host_basepal[cidx+2] * (1/255.0); + + if (Cmd_Argc() > 3) // they gave scale + ptype->ramp[ptype->rampindexes].scale = atof(Cmd_Argv(3)); + else + ptype->ramp[ptype->rampindexes].scale = ptype->scale; + + + ptype->rampindexes++; + } + else if (!strcmp(var, "ramp")) + { + ptype->ramp = BZ_Realloc(ptype->ramp, sizeof(ramp_t)*(ptype->rampindexes+1)); + + ptype->ramp[ptype->rampindexes].rgb[0] = atof(value)/255; + if (Cmd_Argc()>3) //seperate rgb + { + ptype->ramp[ptype->rampindexes].rgb[1] = atof(Cmd_Argv(2))/255; + ptype->ramp[ptype->rampindexes].rgb[2] = atof(Cmd_Argv(3))/255; + + if (Cmd_Argc()>4) //have we alpha and scale changes? + { + ptype->ramp[ptype->rampindexes].alpha = atof(Cmd_Argv(4)); + if (Cmd_Argc()>5) //have we scale changes? + ptype->ramp[ptype->rampindexes].scale = atof(Cmd_Argv(5)); + else + ptype->ramp[ptype->rampindexes].scale = ptype->scaledelta; + } + else + { + ptype->ramp[ptype->rampindexes].alpha = ptype->alpha; + ptype->ramp[ptype->rampindexes].scale = ptype->scaledelta; + } + } + else //they only gave one value + { + ptype->ramp[ptype->rampindexes].rgb[1] = ptype->ramp[ptype->rampindexes].rgb[0]; + ptype->ramp[ptype->rampindexes].rgb[2] = ptype->ramp[ptype->rampindexes].rgb[0]; + + ptype->ramp[ptype->rampindexes].alpha = ptype->alpha; + ptype->ramp[ptype->rampindexes].scale = ptype->scaledelta; + } + + ptype->rampindexes++; + } + else if (!strcmp(var, "perframe")) + ptype->flags |= PT_INVFRAMETIME; + else if (!strcmp(var, "averageout")) + ptype->flags |= PT_AVERAGETRAIL; + else if (!strcmp(var, "nostate")) + ptype->flags |= PT_NOSTATE; + else if (!strcmp(var, "nospreadfirst")) + ptype->flags |= PT_NOSPREADFIRST; + else if (!strcmp(var, "nospreadlast")) + ptype->flags |= PT_NOSPREADLAST; + else + Con_DPrintf("%s is not a recognised particle type field (in %s)\n", var, ptype->name); + } + ptype->invscalefactor = 1-ptype->scalefactor; + ptype->loaded = 1; + if (ptype->clipcount < 1) + ptype->clipcount = 1; + + //if there is a chance that it moves + if (ptype->randomvel || ptype->gravity || ptype->veladd || ptype->offsetspread || ptype->offsetspreadvert) + ptype->flags |= PT_VELOCITY; + //if it has friction + if (ptype->friction) + ptype->flags |= PT_FRICTION; + + if (!settype) + { + if (ptype->type == PT_NORMAL && !*ptype->texname) + ptype->type = PT_SPARK; + if (ptype->type == PT_SPARK) + { + if (*ptype->texname) + ptype->type = PT_TEXTUREDSPARK; + if (ptype->scale) + ptype->type = PT_SPARKFAN; + } + } + + if (ptype->type == PT_BEAM && !setbeamlen) + ptype->rotationstartmin = 1/128.0; + + // use old behavior if not using alphadelta + if (!setalphadelta) + ptype->alphachange = (-ptype->alphachange / ptype->die) * ptype->alpha; + + if (ptype->rampmode && !ptype->ramp) + { + ptype->rampmode = RAMP_NONE; + Con_Printf("Particle type %s has a ramp mode but no ramp\n", ptype->name); + } + else if (ptype->ramp && !ptype->rampmode) + { + Con_Printf("Particle type %s has a ramp but no ramp mode\n", ptype->name); + } + + P_LoadTexture(ptype, true); +} + +//assosiate a point effect with a model. +//the effect will be spawned every frame with count*frametime +//has the capability to hide models. +static void P_AssosiateEffect_f (void) +{ + char *modelname = Cmd_Argv(1); + char *effectname = Cmd_Argv(2); + int effectnum; + model_t *model; + + if (!cls.demoplayback && ( + strstr(modelname, "player") || + strstr(modelname, "eyes") || + strstr(modelname, "flag") || + strstr(modelname, "tf_stan") || + strstr(modelname, ".bsp") || + strstr(modelname, "turr"))) + { + Con_Printf("Sorry: Not allowed to attach effects to model \"%s\"\n", modelname); + return; + } + + model = Mod_FindName(modelname); + if (!model) + return; + if (!cls.demoplayback && (model->flags & EF_ROTATE)) + { + Con_Printf("Sorry: You may not assosiate effects with item model \"%s\"\n", modelname); + return; + } + effectnum = P_AllocateParticleType(effectname); + model->particleeffect = effectnum; + if (atoi(Cmd_Argv(3))) + model->engineflags |= MDLF_ENGULPHS; + + P_SetModified(); //make it appear in f_modified. +} + +//assosiate a particle trail with a model. +//the effect will be spawned between two points when an entity with the model moves. +static void P_AssosiateTrail_f (void) +{ + char *modelname = Cmd_Argv(1); + char *effectname = Cmd_Argv(2); + int effectnum; + model_t *model; + + if (!cls.demoplayback && ( + strstr(modelname, "player") || + strstr(modelname, "eyes") || + strstr(modelname, "flag") || + strstr(modelname, "tf_stan"))) + { + Con_Printf("Sorry, you can't assosiate trails with model \"%s\"\n", modelname); + return; + } + + model = Mod_FindName(modelname); + if (!model) + return; + effectnum = P_AllocateParticleType(effectname); + model->particletrail = effectnum; + model->engineflags |= MDLF_NODEFAULTTRAIL; //we could have assigned the trail to a model that wasn't loaded. + + P_SetModified(); //make it appear in f_modified. +} + +#if _DEBUG +// R_BeamInfo_f - debug junk +static void P_BeamInfo_f (void) +{ + beamseg_t *bs; + int i, j, k, l, m; + + i = 0; + + for (bs = free_beams; bs; bs = bs->next) + i++; + + Con_Printf("%i free beams\n", i); + + for (i = 0; i < numparticletypes; i++) + { + m = l = k = j = 0; + for (bs = part_type[i].beams; bs; bs = bs->next) + { + if (!bs->p) + k++; + + if (bs->flags & BS_DEAD) + l++; + + if (bs->flags & BS_LASTSEG) + m++; + + j++; + } + + if (j) + Con_Printf("Type %i = %i NULL p, %i DEAD, %i LASTSEG, %i total\n", i, k, l, m, j); + } +} + +static void P_PartInfo_f (void) +{ + particle_t *p; + + int i, j; + + i = 0; + + for (p = free_particles; p; p = p->next) + i++; + + Con_Printf("%i free particles\n", i); + + for (i = 0; i < numparticletypes; i++) + { + j = 0; + for (p = part_type[i].particles; p; p = p->next) + j++; + + if (j) + Con_Printf("Type %s = %i total\n", part_type[i].name, j); + } +} +#endif + +/* +=============== +R_InitParticles +=============== +*/ +static void PScript_InitParticles (void) +{ + int i; + + if (r_numparticles) //already inited + return; + + i = COM_CheckParm ("-particles"); + + if (i) + { + r_numparticles = (int)(Q_atoi(com_argv[i+1])); + } + else + { + r_numparticles = MAX_PARTICLES; + } + + r_numbeams = MAX_BEAMSEGS; + + r_numdecals = MAX_DECALS; + + r_numtrailstates = MAX_TRAILSTATES; + + particles = (particle_t *) + BZ_Malloc (r_numparticles * sizeof(particle_t)); + + beams = (beamseg_t *) + BZ_Malloc (r_numbeams * sizeof(beamseg_t)); + + decals = (clippeddecal_t *) + BZ_Malloc (r_numdecals * sizeof(clippeddecal_t)); + + trailstates = (trailstate_t *) + BZ_Malloc (r_numtrailstates * sizeof(trailstate_t)); + memset(trailstates, 0, r_numtrailstates * sizeof(trailstate_t)); + ts_cycle = 0; + + Cmd_AddRemCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :) + + Cmd_AddRemCommand("r_part", P_ParticleEffect_f); + Cmd_AddRemCommand("r_effect", P_AssosiateEffect_f); + Cmd_AddRemCommand("r_trail", P_AssosiateTrail_f); + + Cmd_AddRemCommand("r_exportbuiltinparticles", P_ExportBuiltinSet_f); + +#if _DEBUG + Cmd_AddRemCommand("r_partinfo", P_PartInfo_f); + Cmd_AddRemCommand("r_beaminfo", P_BeamInfo_f); +#endif + + CL_RegisterParticles(); + + pt_pointfile = P_AllocateParticleType("PT_POINTFILE"); + pe_default = P_AllocateParticleType("PE_DEFAULT"); + pe_size2 = P_AllocateParticleType("PE_SIZE2"); + pe_size3 = P_AllocateParticleType("PE_SIZE3"); + pe_defaulttrail = P_AllocateParticleType("PE_DEFAULTTRAIL"); + + Cvar_Hook(&r_particlesdesc, R_ParticlesDesc_Callback); + Cvar_ForceCallback(&r_particlesdesc); +} + +static void PScript_Shutdown (void) +{ + Cvar_Unhook(&r_particlesdesc); + + Cmd_RemoveCommand("pointfile"); //load the leak info produced from qbsp into the particle system to show a line. :) + + Cmd_RemoveCommand("r_part"); + Cmd_RemoveCommand("r_effect"); + Cmd_RemoveCommand("r_trail"); + + Cmd_RemoveCommand("r_exportbuiltinparticles"); + +#if _DEBUG + Cmd_RemoveCommand("r_partinfo"); + Cmd_RemoveCommand("r_beaminfo"); +#endif + + BZ_Free (particles); + BZ_Free (beams); + BZ_Free (decals); + BZ_Free (trailstates); + + r_numparticles = 0; +} + + +/* +=============== +P_ClearParticles +=============== +*/ +static void PScript_ClearParticles (void) +{ + int i; + + free_particles = &particles[0]; + for (i=0 ;iramp) + BZ_Free(part_type->ramp); + part_type->ramp = NULL; + } + + for (i=0 , mod=mod_known ; iparticleeffect = P_INVALID; + mod->particletrail = P_INVALID; + mod->engineflags &= ~MDLF_NODEFAULTTRAIL; + + P_DefaultTrail(mod); + } + + f_modified_particles = false; + + first = true; + for (c = COM_ParseStringSet(var->string); com_token[0]; c = COM_ParseStringSet(c)) + { + P_LoadParticleSet(com_token, first); + first = false; + } +} + +static void P_ReadPointFile_f (void) +{ + vfsfile_t *f; + vec3_t org; + //int r; //unreferenced + int c; + char name[MAX_OSPATH]; + char line[1024]; + char *s; + + COM_StripExtension(cl.worldmodel->name, name, sizeof(name)); + strcat(name, ".pts"); + + f = FS_OpenVFS(name, "rb", FS_GAME); + if (!f) + { + Con_Printf ("couldn't open %s\n", name); + return; + } + + P_ClearParticles(); //so overflows arn't as bad. + + Con_Printf ("Reading %s...\n", name); + c = 0; + for ( ;; ) + { + VFS_GETS(f, line, sizeof(line)); + + s = COM_Parse(line); + org[0] = atof(com_token); + + s = COM_Parse(s); + if (!s) + continue; + org[1] = atof(com_token); + + s = COM_Parse(s); + if (!s) + continue; + org[2] = atof(com_token); + if (COM_Parse(s)) + continue; + + c++; + + if (c%8) + continue; + + if (!free_particles) + { + Con_Printf ("Not enough free particles\n"); + break; + } + P_RunParticleEffectType(org, NULL, 1, pt_pointfile); + } + + VFS_CLOSE (f); + Con_Printf ("%i points read\n", c); +} + +static void P_AddRainParticles(void) +{ + float x; + float y; + static float skipped; + static float lastrendered; + int ptype; + + vec3_t org, vdist; + + skytris_t *st; + + if (!r_part_rain.value || !r_part_rain_quantity.value) + { + skipped = true; + return; + } + + if (lastrendered < particletime - 0.5) + skipped = true; //we've gone for half a sec without any new rain. This would cause some strange effects, so reset times. + + if (skipped) + { + for (ptype = 0; ptypenext) + { + st->nexttime = particletime; + } + } + } + skipped = false; + + lastrendered = particletime; +/* +{ + int i; + +glDisable(GL_TEXTURE_2D); +glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +glDisable(GL_DEPTH_TEST); +glBegin(GL_TRIANGLES); + + st = skytris; + for (i = 0; i < r_part_rain_quantity.value; i++) + st = st->next; + glVertex3f(st->org[0], st->org[1], st->org[2]); + glVertex3f(st->org[0]+st->x[0], st->org[1]+st->x[1], st->org[2]+st->x[2]); + glVertex3f(st->org[0]+st->y[0], st->org[1]+st->y[1], st->org[2]+st->y[2]); +glEnd(); +glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +glBegin(GL_POINTS); + for (i = 0; i < 1000; i++) + { + x = frandom()*frandom(); + y = frandom() * (1-x); + VectorMA(st->org, x, st->x, org); + VectorMA(org, y, st->y, org); + + glVertex3f(org[0], org[1], org[2]); + } +glEnd(); +glEnable(GL_DEPTH_TEST); +} +*/ + for (ptype = 0; ptypenext) + { + // if (st->face->visframe != r_framecount) + // continue; + + if (st->face->visframe != r_framecount) + { + st->nexttime = particletime; + continue; + } + + while (st->nexttime < particletime) + { + if (!free_particles) + return; + + st->nexttime += 10000/(st->area*r_part_rain_quantity.value); + + x = frandom()*frandom(); + y = frandom() * (1-x); + VectorMA(st->org, x, st->x, org); + VectorMA(org, y, st->y, org); + + + VectorSubtract(org, r_refdef.vieworg, vdist); + + if (Length(vdist) > (1024+512)*frandom()) + continue; + + if (st->face->flags & SURF_PLANEBACK) + VectorMA(org, -0.5, st->face->plane->normal, org); + else + VectorMA(org, 0.5, st->face->plane->normal, org); + + if (!(cl.worldmodel->funcs.PointContents(cl.worldmodel, org) & FTECONTENTS_SOLID)) + { + if (st->face->flags & SURF_PLANEBACK) + { + vdist[0] = -st->face->plane->normal[0]; + vdist[1] = -st->face->plane->normal[1]; + vdist[2] = -st->face->plane->normal[2]; + P_RunParticleEffectType(org, vdist, 1, ptype); + } + else + P_RunParticleEffectType(org, st->face->plane->normal, 1, ptype); + } + } + } + } +} + + +static void R_Part_SkyTri(float *v1, float *v2, float *v3, msurface_t *surf) +{ + float dot; + float xm; + float ym; + float theta; + vec3_t xd; + vec3_t yd; + + skytris_t *st; + + st = Hunk_Alloc(sizeof(skytris_t)); + st->next = part_type[surf->texinfo->texture->parttype].skytris; + VectorCopy(v1, st->org); + VectorSubtract(v2, st->org, st->x); + VectorSubtract(v3, st->org, st->y); + + VectorCopy(st->x, xd); + VectorCopy(st->y, yd); +/* + xd[2] = 0; //prevent area from being valid on vertical surfaces + yd[2] = 0; +*/ + xm = Length(xd); + ym = Length(yd); + + dot = DotProduct(xd, yd); + theta = acos(dot/(xm*ym)); + st->area = sin(theta)*xm*ym; + st->nexttime = particletime; + st->face = surf; + + if (st->area<=0) + return;//bummer. + + part_type[surf->texinfo->texture->parttype].skytris = st; +} + + + +static void PScript_EmitSkyEffectTris(model_t *mod, msurface_t *fa) +{ + vec3_t verts[64]; + int v1; + int v2; + int v3; + int numverts; + int i, lindex; + float *vec; + + // + // convert edges back to a normal polygon + // + numverts = 0; + for (i=0 ; inumedges ; i++) + { + lindex = mod->surfedges[fa->firstedge + i]; + + if (lindex > 0) + vec = mod->vertexes[mod->edges[lindex].v[0]].position; + else + vec = mod->vertexes[mod->edges[-lindex].v[1]].position; + VectorCopy (vec, verts[numverts]); + numverts++; + + if (numverts>=64) + { + Con_Printf("Too many verts on sky surface\n"); + return; + } + } + + v1 = 0; + v2 = 1; + for (v3 = 2; v3 < numverts; v3++) + { + R_Part_SkyTri(verts[v1], verts[v2], verts[v3], fa); + + v2 = v3; + } +} + +// Trailstate functions +static void P_CleanTrailstate(trailstate_t *ts) +{ + // clear LASTSEG flag from lastbeam so it can be reused + if (ts->lastbeam) + { + ts->lastbeam->flags &= ~BS_LASTSEG; + ts->lastbeam->flags |= BS_NODRAW; + } + + // clean structure + memset(ts, 0, sizeof(trailstate_t)); +} + +static void PScript_DelinkTrailstate(trailstate_t **tsk) +{ + trailstate_t *ts; + trailstate_t *assoc; + + if (*tsk == NULL) + return; // not linked to a trailstate + + ts = *tsk; // store old pointer + *tsk = NULL; // clear pointer + + if (ts->key != tsk) + return; // prevent overwrite + + assoc = ts->assoc; // store assoc + P_CleanTrailstate(ts); // clean directly linked trailstate + + // clean trailstates assoc linked + while (assoc) + { + ts = assoc->assoc; + P_CleanTrailstate(assoc); + assoc = ts; + } +} + +static trailstate_t *P_NewTrailstate(trailstate_t **key) +{ + trailstate_t *ts; + + // bounds check here in case r_numtrailstates changed + if (ts_cycle >= r_numtrailstates) + ts_cycle = 0; + + // get trailstate + ts = trailstates + ts_cycle; + + // clear trailstate + P_CleanTrailstate(ts); + + // set key + ts->key = key; + + // advance index cycle + ts_cycle++; + + // return clean trailstate + return ts; +} + +#define NUMVERTEXNORMALS 162 +static float r_avertexnormals[NUMVERTEXNORMALS][3] = { +#include "anorms.h" +}; +static vec2_t avelocities[NUMVERTEXNORMALS]; +#define BEAMLENGTH 16 +// vec3_t avelocity = {23, 7, 3}; +// float partstep = 0.01; +// float timescale = 0.01; + +int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent, vec3_t tangent2, float size, float **out); +static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk) +{ + part_type_t *ptype = &part_type[typenum]; + int i, j, k, l, spawnspc; + float m, pcount; + particle_t *p; + beamseg_t *b, *bfirst; + vec3_t ofsvec, arsvec; // offsetspread vec, areaspread vec + trailstate_t *ts; + + if (typenum < 0 || typenum >= numparticletypes) + return 1; + + if (!ptype->loaded) + return 1; + + // inwater check, switch only once + if (r_part_contentswitch.value && ptype->inwater >= 0 && cl.worldmodel) + { + int cont; + cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, org); + + if (cont & FTECONTENTS_WATER) + ptype = &part_type[ptype->inwater]; + } + + // eliminate trailstate if flag set + if (ptype->flags & PT_NOSTATE) + tsk = NULL; + + // trailstate allocation/deallocation + if (tsk) + { + // if *tsk = NULL get a new one + if (*tsk == NULL) + { + ts = P_NewTrailstate(tsk); + *tsk = ts; + } + else + { + ts = *tsk; + + if (ts->key != tsk) // trailstate was overwritten + { + ts = P_NewTrailstate(tsk); // so get a new one + *tsk = ts; + } + } + } + else + ts = NULL; + + if (ptype->type == PT_DECAL) + { + clippeddecal_t *d; + int decalcount; + float dist; + vec3_t tangent, t2; + vec3_t vec={0.5, 0.5, 0.5}; + float *decverts; + int i; + trace_t tr; + + vec3_t bestdir; + + if (!free_decals) + return 0; + + if (!dir) + { + bestdir[0] = 0; + bestdir[1] = 0.73; + bestdir[2] = 0.73; + dist = 1; + for (i = 0; i < 6; i++) + { + if (i >= 3) + { + t2[0] = ((i&3)==0)*8; + t2[1] = ((i&3)==1)*8; + t2[2] = ((i&3)==2)*8; + } + else + { + t2[0] = -((i&3)==0)*8; + t2[1] = -((i&3)==1)*8; + t2[2] = -((i&3)==2)*8; + } + VectorSubtract(org, t2, tangent); + VectorAdd(org, t2, t2); + + if (cl.worldmodel->funcs.Trace (cl.worldmodel, 0, 0,tangent, t2, vec3_origin, vec3_origin, &tr)) + { + if (tr.fraction < dist) + { + dist = tr.fraction; + VectorCopy(tr.plane.normal, bestdir); + } + } + } + dir = bestdir; + } + VectorInverse(dir); + + VectorNormalize(vec); + CrossProduct(dir, vec, tangent); + CrossProduct(dir, tangent, t2); + + decalcount = Q1BSP_ClipDecal(org, dir, tangent, t2, ptype->scale, &decverts); + while(decalcount) + { + if (!free_decals) + break; + + d = free_decals; + free_decals = d->next; + d->next = ptype->clippeddecals; + ptype->clippeddecals = d; + + VectorCopy((decverts+0), d->vertex[0]); + VectorCopy((decverts+3), d->vertex[1]); + VectorCopy((decverts+6), d->vertex[2]); + + for (i = 0; i < 3; i++) + { + VectorSubtract(d->vertex[i], org, vec); + d->texcoords[i][0] = (DotProduct(vec, t2)/ptype->scale)+0.5; + d->texcoords[i][1] = (DotProduct(vec, tangent)/ptype->scale)+0.5; + } + + d->die = ptype->randdie*frandom(); + + if (ptype->die) + d->alpha = ptype->alpha+d->die*ptype->alphachange; + else + d->alpha = ptype->alpha; + + if (ptype->colorindex >= 0) + { + int cidx; + cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; + cidx = ptype->colorindex + cidx; + if (cidx > 255) + d->alpha = d->alpha / 2; // Hexen 2 style transparency + cidx = (cidx & 0xff) * 3; + d->rgb[0] = host_basepal[cidx] * (1/255.0); + d->rgb[1] = host_basepal[cidx+1] * (1/255.0); + d->rgb[2] = host_basepal[cidx+2] * (1/255.0); + } + else + VectorCopy(ptype->rgb, d->rgb); + + vec[2] = frandom(); + vec[0] = vec[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); + vec[1] = vec[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); + vec[2] = vec[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); + d->rgb[0] += vec[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*d->die; + d->rgb[1] += vec[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*d->die; + d->rgb[2] += vec[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*d->die; + + d->die = particletime + ptype->die - d->die; + + decverts += 3*3; + decalcount--; + } + + return 0; + } + + // get msvc to shut up + j = k = l = 0; + m = 0; + + while(ptype) + { + // init spawn specific variables + b = bfirst = NULL; + spawnspc = 8; + pcount = count*(ptype->count+ptype->countrand*frandom()); + if (ptype->flags & PT_INVFRAMETIME) + pcount /= host_frametime; + if (ts) + pcount += ts->state2.emittime; + + switch (ptype->spawnmode) + { + case SM_UNICIRCLE: + m = pcount; + if (ptype->type == PT_BEAM) + m--; + + if (m < 1) + m = 0; + else + m = (M_PI*2)/m; + + if (ptype->spawnparam1) /* use for weird shape hacks */ + m *= ptype->spawnparam1; + break; + case SM_TELEBOX: + spawnspc = 4; + l = -ptype->areaspreadvert; + case SM_LAVASPLASH: + j = k = -ptype->areaspread; + if (ptype->spawnparam1) + m = ptype->spawnparam1; + else + m = 0.55752; /* default weird number for tele/lavasplash used in vanilla Q1 */ + + if (ptype->spawnparam2) + spawnspc = (int)ptype->spawnparam2; + break; + case SM_FIELD: + if (!avelocities[0][0]) + { + for (j=0 ; jspawntime && ts) + { + if (ts->state1.statetime > particletime) + return 0; // timelimit still in effect + + ts->state1.statetime = particletime + ptype->spawntime; // record old time + } + + // random chance for point effects + if (ptype->spawnchance < frandom()) + { + i = ceil(pcount); + break; + } + + if (!ptype->die && ptype->count == 1 && ptype->countrand == 0) + { + i = 0; + pcount = 1; + } + + // particle spawning loop + for (i = 0; i < pcount; i++) + { + if (!free_particles) + break; + p = free_particles; + if (ptype->type == PT_BEAM) + { + if (!free_beams) + break; + if (b) + { + b = b->next = free_beams; + free_beams = free_beams->next; + } + else + { + b = bfirst = free_beams; + free_beams = free_beams->next; + } + b->texture_s = i; // TODO: FIX THIS NUMBER + b->flags = 0; + b->p = p; + VectorClear(b->dir); + } + free_particles = p->next; + p->next = ptype->particles; + ptype->particles = p; + + p->die = ptype->randdie*frandom(); + p->scale = ptype->scale+ptype->randscale*frandom(); + if (ptype->die) + p->alpha = ptype->alpha+p->die*ptype->alphachange; + else + p->alpha = ptype->alpha; + // p->color = 0; + if (ptype->emittime < 0) + p->state.trailstate = NULL; + else + p->state.nextemit = particletime + ptype->emitstart - p->die; + + p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand; + p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand; + + if (ptype->colorindex >= 0) + { + int cidx; + cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; + cidx = ptype->colorindex + cidx; + if (cidx > 255) + p->alpha = p->alpha / 2; // Hexen 2 style transparency + cidx = (cidx & 0xff) * 3; + p->rgb[0] = host_basepal[cidx] * (1/255.0); + p->rgb[1] = host_basepal[cidx+1] * (1/255.0); + p->rgb[2] = host_basepal[cidx+2] * (1/255.0); + } + else + VectorCopy(ptype->rgb, p->rgb); + + // use org temporarily for rgbsync + p->org[2] = frandom(); + p->org[0] = p->org[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); + p->org[1] = p->org[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); + p->org[2] = p->org[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); + + p->rgb[0] += p->org[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*p->die; + p->rgb[1] += p->org[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*p->die; + p->rgb[2] += p->org[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*p->die; + + // randomvel + p->vel[0] = crandom()*ptype->randomvel; + p->vel[1] = crandom()*ptype->randomvel; + p->vel[2] = crandom()*ptype->randomvelvert; + + // handle spawn modes (org/vel) + switch (ptype->spawnmode) + { + case SM_BOX: + ofsvec[0] = crandom(); + ofsvec[1] = crandom(); + ofsvec[2] = crandom(); + + arsvec[0] = ofsvec[0]*ptype->areaspread; + arsvec[1] = ofsvec[1]*ptype->areaspread; + arsvec[2] = ofsvec[2]*ptype->areaspreadvert; + break; + case SM_TELEBOX: + ofsvec[0] = k; + ofsvec[1] = j; + ofsvec[2] = l+4; + VectorNormalize(ofsvec); + VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec); + + // org is just like the original + arsvec[0] = j + (rand()%spawnspc); + arsvec[1] = k + (rand()%spawnspc); + arsvec[2] = l + (rand()%spawnspc); + + // advance telebox loop + j += spawnspc; + if (j >= ptype->areaspread) + { + j = -ptype->areaspread; + k += spawnspc; + if (k >= ptype->areaspread) + { + k = -ptype->areaspread; + l += spawnspc; + if (l >= ptype->areaspreadvert) + l = -ptype->areaspreadvert; + } + } + break; + case SM_LAVASPLASH: + // calc directions, org with temp vector + ofsvec[0] = k + (rand()%spawnspc); + ofsvec[1] = j + (rand()%spawnspc); + ofsvec[2] = 256; + + arsvec[0] = ofsvec[0]; + arsvec[1] = ofsvec[1]; + arsvec[2] = frandom()*ptype->areaspreadvert; + + VectorNormalize(ofsvec); + VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec); + + // advance splash loop + j += spawnspc; + if (j >= ptype->areaspread) + { + j = -ptype->areaspread; + k += spawnspc; + if (k >= ptype->areaspread) + k = -ptype->areaspread; + } + break; + case SM_UNICIRCLE: + ofsvec[0] = cos(m*i); + ofsvec[1] = sin(m*i); + ofsvec[2] = 0; + VectorScale(ofsvec, ptype->areaspread, arsvec); + break; + case SM_FIELD: + arsvec[0] = cl.time * (avelocities[i][0] + m); + arsvec[1] = cl.time * (avelocities[i][1] + m); + arsvec[2] = cos(arsvec[1]); + + ofsvec[0] = arsvec[2]*cos(arsvec[0]); + ofsvec[1] = arsvec[2]*sin(arsvec[0]); + ofsvec[2] = -sin(arsvec[1]); + + arsvec[0] = r_avertexnormals[j][0]*ptype->areaspread + ofsvec[0]*BEAMLENGTH; + arsvec[1] = r_avertexnormals[j][1]*ptype->areaspread + ofsvec[1]*BEAMLENGTH; + arsvec[2] = r_avertexnormals[j][2]*ptype->areaspreadvert + ofsvec[2]*BEAMLENGTH; + + VectorNormalize(ofsvec); + + j++; + if (j >= NUMVERTEXNORMALS) + { + j = 0; + m += 0.1762891; // some BS number to try to "randomize" things + } + break; + case SM_DISTBALL: + { + float rdist; + + rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1)); + + // this is a strange spawntype, which is based on the fact that + // crandom()*crandom() provides something similar to an exponential + // probability curve + ofsvec[0] = hrandom(); + ofsvec[1] = hrandom(); + if (ptype->areaspreadvert) + ofsvec[2] = hrandom(); + else + ofsvec[2] = 0; + + VectorNormalize(ofsvec); + VectorScale(ofsvec, rdist, ofsvec); + + arsvec[0] = ofsvec[0]*ptype->areaspread; + arsvec[1] = ofsvec[1]*ptype->areaspread; + arsvec[2] = ofsvec[2]*ptype->areaspreadvert; + } + break; + default: // SM_BALL, SM_CIRCLE + ofsvec[0] = hrandom(); + ofsvec[1] = hrandom(); + if (ptype->areaspreadvert) + ofsvec[2] = hrandom(); + else + ofsvec[2] = 0; + + VectorNormalize(ofsvec); + if (ptype->spawnmode != SM_CIRCLE) + VectorScale(ofsvec, frandom(), ofsvec); + + arsvec[0] = ofsvec[0]*ptype->areaspread; + arsvec[1] = ofsvec[1]*ptype->areaspread; + arsvec[2] = ofsvec[2]*ptype->areaspreadvert; + break; + } + + p->org[0] = org[0] + arsvec[0]; + p->org[1] = org[1] + arsvec[1]; + p->org[2] = org[2] + arsvec[2] + ptype->offsetup; + + // apply arsvec+ofsvec + if (dir) + { + p->vel[0] += dir[0]*ptype->veladd+ofsvec[0]*ptype->offsetspread; + p->vel[1] += dir[1]*ptype->veladd+ofsvec[1]*ptype->offsetspread; + p->vel[2] += dir[2]*ptype->veladd+ofsvec[2]*ptype->offsetspreadvert; + + p->org[0] += dir[0]*ptype->orgadd; + p->org[1] += dir[1]*ptype->orgadd; + p->org[2] += dir[2]*ptype->orgadd; + } + else + { + p->vel[0] += ofsvec[0]*ptype->offsetspread; + p->vel[1] += ofsvec[1]*ptype->offsetspread; + p->vel[2] += ofsvec[2]*ptype->offsetspreadvert - ptype->veladd; + + p->org[2] -= ptype->orgadd; + } + + p->die = particletime + ptype->die - p->die; + } + + // update beam list + if (ptype->type == PT_BEAM) + { + if (b) + { + // update dir for bfirst for certain modes since it will never get updated + switch (ptype->spawnmode) + { + case SM_UNICIRCLE: + // kinda hackish here, assuming ofsvec contains the point at i-1 + arsvec[0] = cos(m*(i-2)); + arsvec[1] = sin(m*(i-2)); + arsvec[2] = 0; + VectorSubtract(ofsvec, arsvec, bfirst->dir); + VectorNormalize(bfirst->dir); + break; + default: + break; + } + + b->flags |= BS_NODRAW; + b->next = ptype->beams; + ptype->beams = bfirst; + } + } + + // save off emit times in trailstate + if (ts) + ts->state2.emittime = pcount - i; + + // maintain run list + if (!(ptype->state & PS_INRUNLIST)) + { + ptype->nexttorun = part_run_list; + part_run_list = ptype; + ptype->state |= PS_INRUNLIST; + } + + // go to next associated effect + if (ptype->assoc < 0) + break; + + // new trailstate + if (ts) + { + tsk = &(ts->assoc); + // if *tsk = NULL get a new one + if (*tsk == NULL) + { + ts = P_NewTrailstate(tsk); + *tsk = ts; + } + else + { + ts = *tsk; + + if (ts->key != tsk) // trailstate was overwritten + { + ts = P_NewTrailstate(tsk); // so get a new one + *tsk = ts; + } + } + } + + ptype = &part_type[ptype->assoc]; + } + + return 0; +} + +static int PScript_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name) +{ + int type = P_FindParticleType(name); + if (type < 0) + return 1; + + return P_RunParticleEffectType(org, dir, count, type); +} + +/* +=============== +P_RunParticleEffect + +=============== +*/ +static void PScript_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) +{ + int ptype; + + ptype = P_FindParticleType(va("pe_%i", color)); + if (P_RunParticleEffectType(org, dir, count, ptype)) + { + color &= ~0x7; + if (count > 130 && part_type[pe_size3].loaded) + { + part_type[pe_size3].colorindex = color; + part_type[pe_size3].colorrand = 8; + P_RunParticleEffectType(org, dir, count, pe_size3); + return; + } + if (count > 20 && part_type[pe_size2].loaded) + { + part_type[pe_size2].colorindex = color; + part_type[pe_size2].colorrand = 8; + P_RunParticleEffectType(org, dir, count, pe_size2); + return; + } + part_type[pe_default].colorindex = color; + part_type[pe_default].colorrand = 8; + P_RunParticleEffectType(org, dir, count, pe_default); + return; + } +} + +//h2 stylie +static void PScript_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count) +{ + int i, j; + float num; + float invcount; + vec3_t nvel; + + int ptype = P_FindParticleType(va("pe2_%i_%i", effect, color)); + if (ptype < 0) + { + ptype = P_FindParticleType(va("pe2_%i", effect)); + if (ptype < 0) + ptype = pe_default; + + part_type[ptype].colorindex = color; + } + + invcount = 1/part_type[ptype].count; // using this to get R_RPET to always spawn 1 + count = count * part_type[ptype].count; + + for (i=0 ; iveladd; + float randvel = ptype->randomvel; + float randvelvert = ptype->randomvelvert; + float step; + float stop; + float tdegree = 2*M_PI/256; /* MSVC whine */ + float sdegree = 0; + float nrfirst, nrlast; + + VectorCopy(startpos, start); + + // eliminate trailstate if flag set + if (ptype->flags & PT_NOSTATE) + tsk = NULL; + + // trailstate allocation/deallocation + if (tsk) + { + // if *tsk = NULL get a new one + if (*tsk == NULL) + { + ts = P_NewTrailstate(tsk); + *tsk = ts; + } + else + { + ts = *tsk; + + if (ts->key != tsk) // trailstate was overwritten + { + ts = P_NewTrailstate(tsk); // so get a new one + *tsk = ts; + } + } + } + else + ts = NULL; + + if (ptype->assoc>=0) + { + if (ts) + P_ParticleTrail(start, end, ptype->assoc, &(ts->assoc)); + else + P_ParticleTrail(start, end, ptype->assoc, NULL); + } + + // time limit for trails + if (ptype->spawntime && ts) + { + if (ts->state1.statetime > particletime) + return; // timelimit still in effect + + ts->state1.statetime = particletime + ptype->spawntime; // record old time + ts = NULL; // clear trailstate so we don't save length/lastseg + } + + // random chance for trails + if (ptype->spawnchance < frandom()) + return; // don't spawn but return success + + if (!ptype->die) + ts = NULL; + + // use ptype step to calc step vector and step size + step = 1/ptype->count; + + if (step < 0.01) + step = 0.01; + + VectorSubtract (end, start, vec); + len = VectorNormalize (vec); + + if (ptype->flags & PT_AVERAGETRAIL) + { + float tavg; + // mangle len/step to get last point to be at end + tavg = len / step; + tavg = tavg / ceil(tavg); + step *= tavg; + len += step; + } + + VectorScale(vec, step, vstep); + + // add offset + start[2] += ptype->offsetup; + + // spawn mode precalculations + if (ptype->spawnmode == SM_SPIRAL) + { + VectorVectors(vec, right, up); + + // precalculate degree of rotation + if (ptype->spawnparam1) + tdegree = 2*M_PI/ptype->spawnparam1; /* distance per rotation inversed */ + sdegree = ptype->spawnparam2*(M_PI/180); + } + else if (ptype->spawnmode == SM_CIRCLE) + { + VectorVectors(vec, right, up); + } + + // store last stop here for lack of a better solution besides vectors + if (ts) + { + ts->state2.laststop = stop = ts->state2.laststop + len; //when to stop + len = ts->state1.lastdist; + } + else + { + stop = len; + len = 0; + } + +// len = ts->lastdist/step; +// len = (len - (int)len)*step; +// VectorMA (start, -len, vec, start); + + if (ptype->flags & PT_NOSPREADFIRST) + nrfirst = len + step*1.5; + else + nrfirst = len; + + if (ptype->flags & PT_NOSPREADLAST) + nrlast = stop; + else + nrlast = stop + step; + + b = bfirst = NULL; + + while (len < stop) + { + len += step; + + if (!free_particles) + { + len = stop; + break; + } + + p = free_particles; + if (ptype->type == PT_BEAM) + { + if (!free_beams) + { + len = stop; + break; + } + if (b) + { + b = b->next = free_beams; + free_beams = free_beams->next; + } + else + { + b = bfirst = free_beams; + free_beams = free_beams->next; + } + b->texture_s = len; // not sure how to calc this + b->flags = 0; + b->p = p; + VectorCopy(vec, b->dir); + } + + free_particles = p->next; + p->next = ptype->particles; + ptype->particles = p; + + p->die = ptype->randdie*frandom(); + p->scale = ptype->scale+ptype->randscale*frandom(); + if (ptype->die) + p->alpha = ptype->alpha+p->die*ptype->alphachange; + else + p->alpha = ptype->alpha; +// p->color = 0; + +// if (ptype->spawnmode == SM_TRACER) + if (ptype->spawnparam1) + tcount = (int)(len * ptype->count / ptype->spawnparam1); + else + tcount = (int)(len * ptype->count); + + if (ptype->colorindex >= 0) + { + int cidx; + cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; + if (ptype->flags & PT_CITRACER) // colorindex behavior as per tracers in std Q1 + cidx += ((tcount & 4) << 1); + + cidx = ptype->colorindex + cidx; + if (cidx > 255) + p->alpha = p->alpha / 2; + cidx = (cidx & 0xff) * 3; + p->rgb[0] = host_basepal[cidx] * (1/255.0); + p->rgb[1] = host_basepal[cidx+1] * (1/255.0); + p->rgb[2] = host_basepal[cidx+2] * (1/255.0); + } + else + VectorCopy(ptype->rgb, p->rgb); + + // use org temporarily for rgbsync + p->org[2] = frandom(); + p->org[0] = p->org[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); + p->org[1] = p->org[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); + p->org[2] = p->org[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); + if (ptype->orgadd) + { + p->org[0] += vec[0]*ptype->orgadd; + p->org[1] += vec[1]*ptype->orgadd; + p->org[2] += vec[2]*ptype->orgadd; + } + + p->rgb[0] += p->org[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*p->die; + p->rgb[1] += p->org[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*p->die; + p->rgb[2] += p->org[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*p->die; + + VectorClear (p->vel); + if (ptype->emittime < 0) + p->state.trailstate = NULL; // init trailstate + else + p->state.nextemit = particletime + ptype->emitstart - p->die; + + p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand; + p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand; + + if (len < nrfirst || len >= nrlast) + { + // no offset or areaspread for these particles... + p->vel[0] = vec[0]*veladd+crandom()*randvel; + p->vel[1] = vec[1]*veladd+crandom()*randvel; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert; + + VectorCopy(start, p->org); + } + else + { + switch(ptype->spawnmode) + { + case SM_TRACER: + if (tcount & 1) + { + p->vel[0] = vec[1]*ptype->offsetspread; + p->vel[1] = -vec[0]*ptype->offsetspread; + p->org[0] = vec[1]*ptype->areaspread; + p->org[1] = -vec[0]*ptype->areaspread; + } + else + { + p->vel[0] = -vec[1]*ptype->offsetspread; + p->vel[1] = vec[0]*ptype->offsetspread; + p->org[0] = -vec[1]*ptype->areaspread; + p->org[1] = vec[0]*ptype->areaspread; + } + + p->vel[0] += vec[0]*veladd+crandom()*randvel; + p->vel[1] += vec[1]*veladd+crandom()*randvel; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert; + + p->org[0] += start[0]; + p->org[1] += start[1]; + p->org[2] = start[2]; + break; + case SM_SPIRAL: + { + float tsin, tcos; + float tright, tup; + + tcos = cos(len*tdegree+sdegree); + tsin = sin(len*tdegree+sdegree); + + tright = tcos*ptype->areaspread; + tup = tsin*ptype->areaspread; + + p->org[0] = start[0] + right[0]*tright + up[0]*tup; + p->org[1] = start[1] + right[1]*tright + up[1]*tup; + p->org[2] = start[2] + right[2]*tright + up[2]*tup; + + tright = tcos*ptype->offsetspread; + tup = tsin*ptype->offsetspread; + + p->vel[0] = vec[0]*veladd+crandom()*randvel + right[0]*tright + up[0]*tup; + p->vel[1] = vec[1]*veladd+crandom()*randvel + right[1]*tright + up[1]*tup; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert + right[2]*tright + up[2]*tup; + } + break; + // TODO: directionalize SM_BALL/SM_CIRCLE/SM_DISTBALL + case SM_BALL: + p->org[0] = crandom(); + p->org[1] = crandom(); + p->org[2] = crandom(); + VectorNormalize(p->org); + VectorScale(p->org, frandom(), p->org); + + p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread; + p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert + p->org[2]*ptype->offsetspreadvert; + + p->org[0] = p->org[0]*ptype->areaspread + start[0]; + p->org[1] = p->org[1]*ptype->areaspread + start[1]; + p->org[2] = p->org[2]*ptype->areaspreadvert + start[2]; + break; + + case SM_CIRCLE: + { + float tsin, tcos; + + tcos = cos(len*tdegree)*ptype->areaspread; + tsin = sin(len*tdegree)*ptype->areaspread; + + p->org[0] = start[0] + right[0]*tcos + up[0]*tsin + vstep[0] * (len*tdegree); + p->org[1] = start[1] + right[1]*tcos + up[1]*tsin + vstep[1] * (len*tdegree); + p->org[2] = start[2] + right[2]*tcos + up[2]*tsin + vstep[2] * (len*tdegree)*50; + + tcos = cos(len*tdegree)*ptype->offsetspread; + tsin = sin(len*tdegree)*ptype->offsetspread; + + p->vel[0] = vec[0]*veladd+crandom()*randvel + right[0]*tcos + up[0]*tsin; + p->vel[1] = vec[1]*veladd+crandom()*randvel + right[1]*tcos + up[1]*tsin; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert + right[2]*tcos + up[2]*tsin; + } + break; + + case SM_DISTBALL: + { + float rdist; + + rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1)); + + // this is a strange spawntype, which is based on the fact that + // crandom()*crandom() provides something similar to an exponential + // probability curve + p->org[0] = crandom(); + p->org[1] = crandom(); + p->org[2] = crandom(); + + VectorNormalize(p->org); + VectorScale(p->org, rdist, p->org); + + p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread; + p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert + p->org[2]*ptype->offsetspreadvert; + + p->org[0] = p->org[0]*ptype->areaspread + start[0]; + p->org[1] = p->org[1]*ptype->areaspread + start[1]; + p->org[2] = p->org[2]*ptype->areaspreadvert + start[2]; + } + break; + default: + p->org[0] = crandom(); + p->org[1] = crandom(); + p->org[2] = crandom(); + + p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread; + p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread; + p->vel[2] = vec[2]*veladd+crandom()*randvelvert + p->org[2]*ptype->offsetspreadvert; + + p->org[0] = p->org[0]*ptype->areaspread + start[0]; + p->org[1] = p->org[1]*ptype->areaspread + start[1]; + p->org[2] = p->org[2]*ptype->areaspreadvert + start[2]; + break; + } + } + + VectorAdd (start, vstep, start); + + if (ptype->countrand) + { + float rstep = frandom() / ptype->countrand; + VectorMA(start, rstep, vec, start); + step += rstep; + } + + p->die = particletime + ptype->die - p->die; + } + + if (ts) + { + ts->state1.lastdist = len; + + // update beamseg list + if (ptype->type == PT_BEAM) + { + if (b) + { + if (ptype->beams) + { + if (ts->lastbeam) + { + b->next = ts->lastbeam->next; + ts->lastbeam->next = bfirst; + ts->lastbeam->flags &= ~BS_LASTSEG; + } + else + { + b->next = ptype->beams; + ptype->beams = bfirst; + } + } + else + { + ptype->beams = bfirst; + b->next = NULL; + } + + b->flags |= BS_LASTSEG; + ts->lastbeam = b; + } + + if ((!free_particles || !free_beams) && ts->lastbeam) + { + ts->lastbeam->flags &= ~BS_LASTSEG; + ts->lastbeam->flags |= BS_NODRAW; + ts->lastbeam = NULL; + } + } + } + else if (ptype->type == PT_BEAM) + { + if (b) + { + b->flags |= BS_NODRAW; + b->next = ptype->beams; + ptype->beams = bfirst; + } + } + + // maintain run list + if (!(ptype->state & PS_INRUNLIST)) + { + ptype->nexttorun = part_run_list; + part_run_list = ptype; + ptype->state |= PS_INRUNLIST; + } + + return; +} + +static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk) +{ + part_type_t *ptype = &part_type[type]; + + if (type < 0 || type >= numparticletypes) + return 1; //bad value + + if (!ptype->loaded) + return 1; + + // inwater check, switch only once + if (r_part_contentswitch.value && ptype->inwater >= 0) + { + int cont; + cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, startpos); + + if (cont & FTECONTENTS_WATER) + ptype = &part_type[ptype->inwater]; + } + + P_ParticleTrailDraw (startpos, end, ptype, tsk); + return 0; +} + +static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk) +{ + part_type[pe_defaulttrail].colorindex = color; + part_type[pe_defaulttrail].colorrand = crnd; + P_ParticleTrail(start, end, pe_defaulttrail, tsk); +} + + +static part_type_t *lastgltype; +vec3_t pright, pup; +static float pframetime; +#ifdef RGLQUAKE +static void GL_DrawTexturedParticle(particle_t *p, part_type_t *type) +{ + float x,y; + float scale; + + if (lastgltype != type) + { + if (!lastgltype || lastgltype->type != type->type || lastgltype->texturenum != type->texturenum || lastgltype->blendmode != type->blendmode) + { + qglEnd(); + qglEnable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_FLAT); + qglBegin(GL_QUADS); + } + lastgltype = type; + } + + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); + if (scale < 20) + scale = 0.25; + else + scale = 0.25 + scale * 0.001; + + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + + if (p->angle) + { + x = sin(p->angle)*scale; + y = cos(p->angle)*scale; + } + else + { + x = 0; + y = scale; + } + qglTexCoord2f(0,0); + qglVertex3f (p->org[0] - x*pright[0] - y*pup[0], p->org[1] - x*pright[1] - y*pup[1], p->org[2] - x*pright[2] - y*pup[2]); + qglTexCoord2f(0,1); + qglVertex3f (p->org[0] - y*pright[0] + x*pup[0], p->org[1] - y*pright[1] + x*pup[1], p->org[2] - y*pright[2] + x*pup[2]); + qglTexCoord2f(1,1); + qglVertex3f (p->org[0] + x*pright[0] + y*pup[0], p->org[1] + x*pright[1] + y*pup[1], p->org[2] + x*pright[2] + y*pup[2]); + qglTexCoord2f(1,0); + qglVertex3f (p->org[0] + y*pright[0] - x*pup[0], p->org[1] + y*pright[1] - x*pup[1], p->org[2] + y*pright[2] - x*pup[2]); +} + + +static void GL_DrawSketchParticle(particle_t *p, part_type_t *type) +{ + float x,y; + float scale; + + int quant; + + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglDisable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); +// if (type->blendmode == BM_ADD) //addative +// glBlendFunc(GL_SRC_ALPHA, GL_ONE); +// else if (type->blendmode == BM_SUBTRACT) //subtractive +// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +// else + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_LINES); + } + + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); + if (scale < 20) + scale = 0.25; + else + scale = 0.25 + scale * 0.001; + + qglColor4f (p->rgb[0]/2, + p->rgb[1]/2, + p->rgb[2]/2, + p->alpha*2); + + quant = scale; + + if (p->angle) + { + x = sin(p->angle)*scale; + y = cos(p->angle)*scale; + } + else + { + x = 0; + y = scale; + } + qglVertex3f (p->org[0] - x*pright[0] - y*pup[0], p->org[1] - x*pright[1] - y*pup[1], p->org[2] - x*pright[2] - y*pup[2]); + qglVertex3f (p->org[0] + x*pright[0] + y*pup[0], p->org[1] + x*pright[1] + y*pup[1], p->org[2] + x*pright[2] + y*pup[2]); + qglVertex3f (p->org[0] + y*pright[0] - x*pup[0], p->org[1] + y*pright[1] - x*pup[1], p->org[2] + y*pright[2] - x*pup[2]); + qglVertex3f (p->org[0] - y*pright[0] + x*pup[0], p->org[1] - y*pright[1] + x*pup[1], p->org[2] - y*pright[2] + x*pup[2]); +} + +static void GL_DrawTrifanParticle(particle_t *p, part_type_t *type) +{ + int i; + vec3_t v; + float scale; + + qglEnd(); + + if (lastgltype != type) + { + lastgltype = type; + qglDisable(GL_TEXTURE_2D); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + } + + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); + if (scale < 20) + scale = 0.05; + else + scale = 0.05 + scale * 0.0001; +/* + if ((p->vel[0]*p->vel[0]+p->vel[1]*p->vel[1]+p->vel[2]*p->vel[2])*2*scale > 30*30) + scale = 1+1/30/Length(p->vel)*2;*/ + + qglBegin (GL_TRIANGLE_FAN); + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + qglVertex3fv (p->org); + qglColor4f (p->rgb[0]/2, + p->rgb[1]/2, + p->rgb[2]/2, + 0); + for (i=7 ; i>=0 ; i--) + { + v[0] = p->org[0] - p->vel[0]*scale + vright[0]*cost[i%7]*p->scale + vup[0]*sint[i%7]*p->scale; + v[1] = p->org[1] - p->vel[1]*scale + vright[1]*cost[i%7]*p->scale + vup[1]*sint[i%7]*p->scale; + v[2] = p->org[2] - p->vel[2]*scale + vright[2]*cost[i%7]*p->scale + vup[2]*sint[i%7]*p->scale; + qglVertex3fv (v); + } + qglEnd (); + qglBegin (GL_TRIANGLES); +} + +static void GL_DrawLineSparkParticle(particle_t *p, part_type_t *type) +{ + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglDisable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_LINES); + } + + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + qglVertex3f (p->org[0], p->org[1], p->org[2]); + + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + 0); + qglVertex3f (p->org[0]-p->vel[0]/10, p->org[1]-p->vel[1]/10, p->org[2]-p->vel[2]/10); +} + +static void GL_DrawTexturedSparkParticle(particle_t *p, part_type_t *type) +{ + vec3_t v, cr, o2, point; + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglEnable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_QUADS); + } + + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + + VectorSubtract(r_refdef.vieworg, p->org, v); + CrossProduct(v, p->vel, cr); + VectorNormalize(cr); + + VectorMA(p->org, -p->scale/2, cr, point); + qglTexCoord2f(0, 0); + qglVertex3fv(point); + VectorMA(p->org, p->scale/2, cr, point); + qglTexCoord2f(0, 1); + qglVertex3fv(point); + + + VectorMA(p->org, 0.1, p->vel, o2); + + VectorSubtract(r_refdef.vieworg, o2, v); + CrossProduct(v, p->vel, cr); + VectorNormalize(cr); + + VectorMA(o2, p->scale/2, cr, point); + qglTexCoord2f(1, 1); + qglVertex3fv(point); + VectorMA(o2, -p->scale/2, cr, point); + qglTexCoord2f(1, 0); + qglVertex3fv(point); +} + +static void GL_DrawSketchSparkParticle(particle_t *p, part_type_t *type) +{ + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglDisable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_LINES); + } + + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + qglVertex3f (p->org[0], p->org[1], p->org[2]); + + qglColor4f (p->rgb[0], + p->rgb[1], + p->rgb[2], + 0); + qglVertex3f (p->org[0]-p->vel[0]/10, p->org[1]-p->vel[1]/10, p->org[2]-p->vel[2]/10); +} + +static void GL_DrawParticleBeam_Textured(beamseg_t *b, part_type_t *type) +{ + vec3_t v, point; + vec3_t cr; + beamseg_t *c; + particle_t *p; + particle_t *q; + float ts; + +// if (!b->next) +// return; + + c = b->next; + + q = c->p; +// if (!q) +// return; + + p = b->p; +// if (!p) +// return; + + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglEnable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_QUADS); + } + qglColor4f(q->rgb[0], + q->rgb[1], + q->rgb[2], + q->alpha); +// qglBegin(GL_LINE_LOOP); + VectorSubtract(r_refdef.vieworg, q->org, v); + VectorNormalize(v); + CrossProduct(c->dir, v, cr); + ts = c->texture_s*type->rotationstartmin + particletime*type->rotationmin; + + VectorMA(q->org, -q->scale, cr, point); + qglTexCoord2f(ts, 0); + qglVertex3fv(point); + VectorMA(q->org, q->scale, cr, point); + qglTexCoord2f(ts, 1); + qglVertex3fv(point); + + qglColor4f(p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + + VectorSubtract(r_refdef.vieworg, p->org, v); + VectorNormalize(v); + CrossProduct(b->dir, v, cr); // replace with old p->dir? + ts = b->texture_s*type->rotationstartmin + particletime*type->rotationmin; + + VectorMA(p->org, p->scale, cr, point); + qglTexCoord2f(ts, 1); + qglVertex3fv(point); + VectorMA(p->org, -p->scale, cr, point); + qglTexCoord2f(ts, 0); + qglVertex3fv(point); +// qglEnd(); +} + +static void GL_DrawParticleBeam_Untextured(beamseg_t *b, part_type_t *type) +{ + vec3_t v; + vec3_t cr; + beamseg_t *c; + particle_t *p; + particle_t *q; + + vec3_t point[4]; + +// if (!b->next) +// return; + + c = b->next; + + q = c->p; +// if (!q) +// return; + + p = b->p; +// if (!p) +// return; + + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglDisable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + qglBegin(GL_QUADS); + } + +// qglBegin(GL_LINE_LOOP); + VectorSubtract(r_refdef.vieworg, q->org, v); + VectorNormalize(v); + CrossProduct(c->dir, v, cr); + + VectorMA(q->org, -q->scale, cr, point[0]); + VectorMA(q->org, q->scale, cr, point[1]); + + + VectorSubtract(r_refdef.vieworg, p->org, v); + VectorNormalize(v); + CrossProduct(b->dir, v, cr); // replace with old p->dir? + + VectorMA(p->org, p->scale, cr, point[2]); + VectorMA(p->org, -p->scale, cr, point[3]); + + + //one half + //back out + //back in + //front in + //front out + qglColor4f(q->rgb[0], + q->rgb[1], + q->rgb[2], + 0); + qglVertex3fv(point[0]); + qglColor4f(q->rgb[0], + q->rgb[1], + q->rgb[2], + q->alpha); + qglVertex3fv(q->org); + + qglColor4f(p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + qglVertex3fv(p->org); + qglColor4f(p->rgb[0], + p->rgb[1], + p->rgb[2], + 0); + qglVertex3fv(point[3]); + + //front out + //front in + //back in + //back out + qglColor4f(p->rgb[0], + p->rgb[1], + p->rgb[2], + 0); + qglVertex3fv(point[2]); + qglColor4f(p->rgb[0], + p->rgb[1], + p->rgb[2], + p->alpha); + qglVertex3fv(p->org); + + qglColor4f(q->rgb[0], + q->rgb[1], + q->rgb[2], + q->alpha); + qglVertex3fv(q->org); + qglColor4f(q->rgb[0], + q->rgb[1], + q->rgb[2], + 0); + qglVertex3fv(point[1]); + +// qglEnd(); +} + +static void GL_DrawClippedDecal(clippeddecal_t *d, part_type_t *type) +{ + if (lastgltype != type) + { + lastgltype = type; + qglEnd(); + qglEnable(GL_TEXTURE_2D); + GL_Bind(type->texturenum); + APPLYBLEND(type->blendmode); + qglShadeModel(GL_SMOOTH); + +// qglDisable(GL_TEXTURE_2D); +// qglBegin(GL_LINE_LOOP); + + qglBegin(GL_TRIANGLES); + } + + qglColor4f(d->rgb[0], + d->rgb[1], + d->rgb[2], + d->alpha); + + qglTexCoord2fv(d->texcoords[0]); + qglVertex3fv(d->vertex[0]); + qglTexCoord2fv(d->texcoords[1]); + qglVertex3fv(d->vertex[1]); + qglTexCoord2fv(d->texcoords[2]); + qglVertex3fv(d->vertex[2]); +} + +#endif +#ifdef SWQUAKE +static void SWD_DrawParticleSpark(particle_t *p, part_type_t *type) +{ + float speed; + vec3_t src, dest; + + int r,g,b; //if you have a cpu with mmx, good for you... + r = p->rgb[0]*255; + if (r < 0) + r = 0; + else if (r > 255) + r = 255; + g = p->rgb[1]*255; + if (g < 0) + g = 0; + else if (g > 255) + g = 255; + b = p->rgb[2]*255; + if (b < 0) + b = 0; + else if (b > 255) + b = 255; + p->color = GetPaletteIndex(r, g, b); + + speed = Length(p->vel); + if ((speed) < 1) + { + VectorCopy(p->org, src); + VectorCopy(p->org, dest); + } + else + { //causes flickers with lower vels (due to bouncing in physics) + if (speed < 50) + speed *= 50/speed; + VectorMA(p->org, 2.5/(speed), p->vel, src); + VectorMA(p->org, -2.5/(speed), p->vel, dest); + } + + D_DrawSparkTrans(p, src, dest, type->blendmode); +} +static void SWD_DrawParticleBlob(particle_t *p, part_type_t *type) +{ + int r,g,b; //This really shouldn't be like this. Pitty the 32 bit renderer... + r = p->rgb[0]*255; + if (r < 0) + r = 0; + else if (r > 255) + r = 255; + g = p->rgb[1]*255; + if (g < 0) + g = 0; + else if (g > 255) + g = 255; + b = p->rgb[2]*255; + if (b < 0) + b = 0; + else if (b > 255) + b = 255; + p->color = GetPaletteIndex(r, g, b); + D_DrawParticleTrans(p->org, p->alpha, p->scale, p->color, type->blendmode); +} +static void SWD_DrawParticleBeam(beamseg_t *beam, part_type_t *type) +{ + int r,g,b; //if you have a cpu with mmx, good for you... + beamseg_t *c; + particle_t *p; + particle_t *q; + +// if (!b->next) +// return; + + c = beam->next; + + q = c->p; +// if (!q) +// return; + + p = beam->p; + + r = p->rgb[0]*255; + if (r < 0) + r = 0; + else if (r > 255) + r = 255; + g = p->rgb[1]*255; + if (g < 0) + g = 0; + else if (g > 255) + g = 255; + b = p->rgb[2]*255; + if (b < 0) + b = 0; + else if (b > 255) + b = 255; + p->color = GetPaletteIndex(r, g, b); + D_DrawSparkTrans(p, p->org, q->org, type->blendmode); +} +#endif + +void PScript_DrawParticleTypes (void (*texturedparticles)(particle_t *,part_type_t*), void (*sparklineparticles)(particle_t*,part_type_t*), void (*sparkfanparticles)(particle_t*,part_type_t*), void (*sparktexturedparticles)(particle_t*,part_type_t*), void (*beamparticlest)(beamseg_t*,part_type_t*), void (*beamparticlesut)(beamseg_t*,part_type_t*), void (*drawdecalparticles)(clippeddecal_t*,part_type_t*)) +{ + RSpeedMark(); + + qboolean (*tr) (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); + void *pdraw, *bdraw; + + vec3_t oldorg; + vec3_t stop, normal; + part_type_t *type, *lastvalidtype; + particle_t *p, *kill; + clippeddecal_t *d; + ramp_t *ramp; + float grav; + vec3_t friction; + float dist; + particle_t *kill_list, *kill_first; //the kill list is to stop particles from being freed and reused whilst still in this loop + //which is bad because beams need to find out when particles died. Reuse can do wierd things. + //remember that they're not drawn instantly either. + beamseg_t *b, *bkill; + + int traces=r_particle_tracelimit.value; + int rampind; + + lastgltype = NULL; + + pframetime = host_frametime; + if (cl.paused || r_secondaryview) + pframetime = 0; + + VectorScale (vup, 1.5, pup); + VectorScale (vright, 1.5, pright); +#ifdef SWQUAKE + VectorScale (vright, xscaleshrink, r_pright); + VectorScale (vup, yscaleshrink, r_pup); + VectorCopy (vpn, r_ppn); +#endif + +#ifdef Q2BSPS + if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3) + tr = Q2TraceLineN; + else +#endif + tr = TraceLineN; + + kill_list = kill_first = NULL; + + // reassign drawing methods by cvars + if (r_part_beams_textured.value < 0) + beamparticlest = NULL; + else if (!r_part_beams_textured.value) + beamparticlest = beamparticlesut; + + if (r_part_beams.value < 0) + beamparticlesut = NULL; + else if (!r_part_beams.value) + { + beamparticlest = NULL; + beamparticlesut = NULL; + } + + if (r_part_sparks_textured.value < 0) + sparktexturedparticles = NULL; + else if (!r_part_sparks_textured.value) + sparktexturedparticles = sparklineparticles; + + if (r_part_sparks_trifan.value < 0) + sparkfanparticles = NULL; + else if (!r_part_sparks_trifan.value) + sparkfanparticles = sparklineparticles; + + if (r_part_sparks.value < 0) + sparklineparticles = NULL; + else if (!r_part_sparks.value) + { + sparktexturedparticles = NULL; + sparkfanparticles = NULL; + sparklineparticles = NULL; + } + + for (type = part_run_list, lastvalidtype = NULL; type != NULL; type = type->nexttorun) + { + if (type->clippeddecals) + { +/* for ( ;; ) + { + dkill = type->clippeddecals; + if (dkill && dkill->die < particletime) + { + type->clippeddecals = dkill->next; + free_decals = + + + dkill->next = (clippeddecal_t *)kill_list; + kill_list = (particle_t*)dkill; + if (!kill_first) + kill_first = kill_list; + continue; + } + break; + } +*/ for (d=type->clippeddecals ; d ; d=d->next) + { + /* for ( ;; ) + { + dkill = d->next; + if (dkill && dkill->die < particletime) + { + d->next = dkill->next; + dkill->next = (clippeddecal_t *)kill_list; + kill_list = (particle_t*)dkill; + if (!kill_first) + kill_first = kill_list; + continue; + } + break; + }*/ + + + + switch (type->rampmode) + { + case RAMP_ABSOLUTE: + rampind = (int)(type->rampindexes * (type->die - (d->die - particletime)) / type->die); + if (rampind >= type->rampindexes) + rampind = type->rampindexes - 1; + ramp = type->ramp + rampind; + VectorCopy(ramp->rgb, d->rgb); + d->alpha = ramp->alpha; + break; + case RAMP_DELTA: //particle ramps + ramp = type->ramp + (int)(type->rampindexes * (type->die - (d->die - particletime)) / type->die); + VectorMA(d->rgb, pframetime, ramp->rgb, d->rgb); + d->alpha -= pframetime*ramp->alpha; + break; + case RAMP_NONE: //particle changes acording to it's preset properties. + if (particletime < (d->die-type->die+type->rgbchangetime)) + { + d->rgb[0] += pframetime*type->rgbchange[0]; + d->rgb[1] += pframetime*type->rgbchange[1]; + d->rgb[2] += pframetime*type->rgbchange[2]; + } + d->alpha += pframetime*type->alphachange; + } + + drawdecalparticles(d, type); + } + } + + bdraw = NULL; + pdraw = NULL; + + // set drawing methods by type and cvars and hope branch + // prediction takes care of the rest + switch(type->type) + { + case PT_BEAM: + if (*type->texname) + bdraw = beamparticlest; + else + bdraw = beamparticlesut; + break; + case PT_DECAL: + break; + case PT_NORMAL: + pdraw = texturedparticles; + break; + case PT_SPARK: + pdraw = sparklineparticles; + break; + case PT_SPARKFAN: + pdraw = sparkfanparticles; + break; + case PT_TEXTUREDSPARK: + pdraw = sparktexturedparticles; + break; + } + + if (!type->die) + { + while ((p=type->particles)) + { + if (pdraw) + RQ_AddDistReorder(pdraw, p, type, p->org); + + // make sure emitter runs at least once + if (type->emit >= 0 && type->emitstart <= 0) + P_RunParticleEffectType(p->org, p->vel, 1, type->emit); + + // make sure stain effect runs + if (type->stains && r_bloodstains.value) + { + if (traces-->0&&tr(oldorg, p->org, stop, normal)) + { + R_AddStain(stop, (p->rgb[1]*-10+p->rgb[2]*-10), + (p->rgb[0]*-10+p->rgb[2]*-10), + (p->rgb[0]*-10+p->rgb[1]*-10), + 30*p->alpha*type->stains); + } + } + + type->particles = p->next; +// p->next = free_particles; +// free_particles = p; + p->next = kill_list; + kill_list = p; + if (!kill_first) // branch here is probably faster than list traversal later + kill_first = p; + } + + if (type->beams) + { + b = type->beams; + } + + while ((b=type->beams) && (b->flags & BS_DEAD)) + { + type->beams = b->next; + b->next = free_beams; + free_beams = b; + } + + while (b) + { + if (!(b->flags & BS_NODRAW)) + { + // no BS_NODRAW implies b->next != NULL + // BS_NODRAW should imply b->next == NULL or b->next->flags & BS_DEAD + VectorCopy(b->next->p->org, stop); + VectorCopy(b->p->org, oldorg); + VectorSubtract(stop, oldorg, b->next->dir); + VectorNormalize(b->next->dir); + if (bdraw) + { + VectorAdd(stop, oldorg, stop); + VectorScale(stop, 0.5, stop); + + RQ_AddDistReorder(bdraw, b, type, stop); + } + } + + // clean up dead entries ahead of current + for ( ;; ) + { + bkill = b->next; + if (bkill && (bkill->flags & BS_DEAD)) + { + b->next = bkill->next; + bkill->next = free_beams; + free_beams = bkill; + continue; + } + break; + } + + b->flags |= BS_DEAD; + b = b->next; + } + + continue; + } + + //kill off early ones. + if (type->emittime < 0) + { + for ( ;; ) + { + kill = type->particles; + if (kill && kill->die < particletime) + { + P_DelinkTrailstate(&kill->state.trailstate); + type->particles = kill->next; + kill->next = kill_list; + kill_list = kill; + if (!kill_first) + kill_first = kill; + continue; + } + break; + } + } + else + { + for ( ;; ) + { + kill = type->particles; + if (kill && kill->die < particletime) + { + type->particles = kill->next; + kill->next = kill_list; + kill_list = kill; + if (!kill_first) + kill_first = kill; + continue; + } + break; + } + } + + grav = type->gravity*pframetime; + VectorScale(type->friction, pframetime, friction); + + for (p=type->particles ; p ; p=p->next) + { + if (type->emittime < 0) + { + for ( ;; ) + { + kill = p->next; + if (kill && kill->die < particletime) + { + P_DelinkTrailstate(&kill->state.trailstate); + p->next = kill->next; + kill->next = kill_list; + kill_list = kill; + if (!kill_first) + kill_first = kill; + continue; + } + break; + } + } + else + { + for ( ;; ) + { + kill = p->next; + if (kill && kill->die < particletime) + { + p->next = kill->next; + kill->next = kill_list; + kill_list = kill; + if (!kill_first) + kill_first = kill; + continue; + } + break; + } + } + + VectorCopy(p->org, oldorg); + if (type->flags & PT_VELOCITY) + { + p->org[0] += p->vel[0]*pframetime; + p->org[1] += p->vel[1]*pframetime; + p->org[2] += p->vel[2]*pframetime; + if (type->flags & PT_FRICTION) + { + p->vel[0] -= friction[0]*p->vel[0]; + p->vel[1] -= friction[1]*p->vel[1]; + p->vel[2] -= friction[2]*p->vel[2]; + } + p->vel[2] -= grav; + } + + p->angle += p->rotationspeed*pframetime; + + switch (type->rampmode) + { + case RAMP_ABSOLUTE: + rampind = (int)(type->rampindexes * (type->die - (p->die - particletime)) / type->die); + if (rampind >= type->rampindexes) + rampind = type->rampindexes - 1; + ramp = type->ramp + rampind; + VectorCopy(ramp->rgb, p->rgb); + p->alpha = ramp->alpha; + p->scale = ramp->scale; + break; + case RAMP_DELTA: //particle ramps + rampind = (int)(type->rampindexes * (type->die - (p->die - particletime)) / type->die); + if (rampind >= type->rampindexes) + rampind = type->rampindexes - 1; + ramp = type->ramp + rampind; + VectorMA(p->rgb, pframetime, ramp->rgb, p->rgb); + p->alpha -= pframetime*ramp->alpha; + p->scale += pframetime*ramp->scale; + break; + case RAMP_NONE: //particle changes acording to it's preset properties. + if (particletime < (p->die-type->die+type->rgbchangetime)) + { + p->rgb[0] += pframetime*type->rgbchange[0]; + p->rgb[1] += pframetime*type->rgbchange[1]; + p->rgb[2] += pframetime*type->rgbchange[2]; + } + p->alpha += pframetime*type->alphachange; + p->scale += pframetime*type->scaledelta; + } + + if (type->emit >= 0) + { + if (type->emittime < 0) + P_ParticleTrail(oldorg, p->org, type->emit, &p->state.trailstate); + else if (p->state.nextemit < particletime) + { + p->state.nextemit = particletime + type->emittime + frandom()*type->emitrand; + P_RunParticleEffectType(p->org, p->vel, 1, type->emit); + } + } + + if (type->cliptype>=0 && r_bouncysparks.value) + { + if (traces-->0&&tr(oldorg, p->org, stop, normal)) + { + if (type->stains && r_bloodstains.value) + R_AddStain(stop, p->rgb[1]*-10+p->rgb[2]*-10, + p->rgb[0]*-10+p->rgb[2]*-10, + p->rgb[0]*-10+p->rgb[1]*-10, + 30*p->alpha); + + if (part_type + type->cliptype == type) + { //bounce + dist = DotProduct(p->vel, normal) * (-1-(rand()/(float)0x7fff)/2); + + VectorMA(p->vel, dist, normal, p->vel); + VectorCopy(stop, p->org); + p->vel[0] *= type->clipbounce; + p->vel[1] *= type->clipbounce; + p->vel[2] *= type->clipbounce; + + if (!*type->texname && Length(p->vel)<1000*pframetime && type->type == PT_NORMAL) + p->die = -1; + } + else + { + p->die = -1; + VectorNormalize(p->vel); + P_RunParticleEffectType(stop, p->vel, type->clipcount/part_type[type->cliptype].count, type->cliptype); + } + + continue; + } + } + else if (type->stains && r_bloodstains.value) + { + if (traces-->0&&tr(oldorg, p->org, stop, normal)) + { + R_AddStain(stop, (p->rgb[1]*-10+p->rgb[2]*-10), + (p->rgb[0]*-10+p->rgb[2]*-10), + (p->rgb[0]*-10+p->rgb[1]*-10), + 30*p->alpha*type->stains); + p->die = -1; + continue; + } + } + + if (pdraw) + RQ_AddDistReorder((void*)pdraw, p, type, p->org); + } + + // beams are dealt with here + + // kill early entries + for ( ;; ) + { + bkill = type->beams; + if (bkill && (bkill->flags & BS_DEAD || bkill->p->die < particletime) && !(bkill->flags & BS_LASTSEG)) + { + type->beams = bkill->next; + bkill->next = free_beams; + free_beams = bkill; + continue; + } + break; + } + + + b = type->beams; + if (b) + { + for ( ;; ) + { + if (b->next) + { + // mark dead entries + if (b->flags & (BS_LASTSEG|BS_DEAD|BS_NODRAW)) + { + // kill some more dead entries + for ( ;; ) + { + bkill = b->next; + if (bkill && (bkill->flags & BS_DEAD) && !(bkill->flags & BS_LASTSEG)) + { + b->next = bkill->next; + bkill->next = free_beams; + free_beams = bkill; + continue; + } + break; + } + + if (!bkill) // have to check so we don't hit NULL->next + continue; + } + else + { + if (!(b->next->flags & BS_DEAD)) + { + VectorCopy(b->next->p->org, stop); + VectorCopy(b->p->org, oldorg); + VectorSubtract(stop, oldorg, b->next->dir); + VectorNormalize(b->next->dir); + if (bdraw) + { + VectorAdd(stop, oldorg, stop); + VectorScale(stop, 0.5, stop); + + RQ_AddDistReorder(bdraw, b, type, stop); + } + } + + // if (b->p->die < particletime) + // b->flags |= BS_DEAD; + } + } + else + { + if (b->p->die < particletime) // end of the list check + b->flags |= BS_DEAD; + + break; + } + + if (b->p->die < particletime) + b->flags |= BS_DEAD; + + b = b->next; + } + } + + // delete from run list if necessary + if (!type->particles && !type->beams && !type->clippeddecals) + { +// if (!lastvalidtype) +// part_run_list = type->nexttorun; +// else +// lastvalidtype->nexttorun = type->nexttorun; +// type->state &= ~PS_INRUNLIST; + } + else + lastvalidtype = type; + } + + RSpeedEnd(RSPEED_PARTICLES); + + // lazy delete for particles is done here + if (kill_list) + { + kill_first->next = free_particles; + free_particles = kill_list; + } + + particletime += pframetime; +} + +static void PScript_FlushRenderer(void) +{ +#ifdef RGLQUAKE + qglDepthMask(0); //primarily to stop close particles from obscuring each other + qglDisable(GL_ALPHA_TEST); + qglEnable (GL_BLEND); + GL_TexEnv(GL_MODULATE); + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + lastgltype = NULL; +#endif +} + +/* +=============== +R_DrawParticles +=============== +*/ +static void PScript_DrawParticles (void) +{ + RSpeedMark(); + + P_AddRainParticles(); +#if defined(RGLQUAKE) + if (qrenderer == QR_OPENGL) + { + extern int gldepthfunc; + extern cvar_t r_drawflat; + + P_FlushRenderer(); + + if (qglPolygonOffset) + qglPolygonOffset(-1, 0); + qglEnable(GL_POLYGON_OFFSET_FILL); + qglEnable(GL_BLEND); + + qglDepthFunc(gldepthfunc); + + qglDisable(GL_ALPHA_TEST); + qglBegin(GL_QUADS); + if (r_drawflat.value == 2) + PScript_DrawParticleTypes(GL_DrawSketchParticle, GL_DrawSketchSparkParticle, GL_DrawSketchSparkParticle, GL_DrawSketchSparkParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured, GL_DrawClippedDecal); + else + PScript_DrawParticleTypes(GL_DrawTexturedParticle, GL_DrawLineSparkParticle, GL_DrawTrifanParticle, GL_DrawTexturedSparkParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured, GL_DrawClippedDecal); + qglEnd(); + qglDisable(GL_POLYGON_OFFSET_FILL); + + + + RSpeedRemark(); + lastgltype = NULL; + qglBegin(GL_QUADS); + RQ_RenderDistAndClear(); + qglEnd(); + RSpeedEnd(RSPEED_PARTICLESDRAW); + + qglEnable(GL_TEXTURE_2D); + + GL_TexEnv(GL_MODULATE); + qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + qglDepthMask(1); + return; + } +#endif +#ifdef SWQUAKE + if (qrenderer == QR_SOFTWARE) + { + lastgltype = NULL; + PScript_DrawParticleTypes(SWD_DrawParticleBlob, SWD_DrawParticleSpark, SWD_DrawParticleSpark, SWD_DrawParticleSpark, SWD_DrawParticleBeam, SWD_DrawParticleBeam, NULL); + + RSpeedRemark(); + D_StartParticles(); + RQ_RenderDistAndClear(); + D_EndParticles(); + RSpeedEnd(RSPEED_PARTICLESDRAW); + return; + } +#endif +#if defined(D3DQUAKE) + if (qrenderer == QR_DIRECT3D) + { + if (!D3D7_DrawParticles(particletime)) + D3D9_DrawParticles(particletime); + } +#endif + + if (qrenderer) + { + RSpeedRemark(); + RQ_RenderDistAndClear(); + RSpeedEnd(RSPEED_PARTICLESDRAW); + } +} + + +particleengine_t pe_script = +{ + "script", + "fte", + + PScript_ParticleTypeForName, + PScript_FindParticleType, + + PScript_RunParticleEffectTypeString, + PScript_ParticleTrail, + PScript_RunParticleEffectState, + PScript_RunParticleWeather, + PScript_RunParticleCube, + PScript_RunParticleEffect, + PScript_RunParticleEffect2, + PScript_RunParticleEffect3, + PScript_RunParticleEffect4, + + PScript_ParticleTrailIndex, + PScript_EmitSkyEffectTris, + PScript_InitParticles, + PScript_Shutdown, + PScript_DelinkTrailstate, + PScript_ClearParticles, + PScript_DrawParticles, + PScript_FlushRenderer +}; + +#endif +#endif \ No newline at end of file diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 8e027c230..f629798dd 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -44,6 +44,7 @@ qboolean csqc_resortfrags; qboolean csqc_drawsbar; qboolean csqc_addcrosshair; static int num_csqc_edicts; +static int csqc_fakereadbyte; #define CSQCPROGSGROUP "CSQC progs control" cvar_t pr_csmaxedicts = SCVAR("pr_csmaxedicts", "3072"); @@ -83,7 +84,10 @@ extern sfx_t *cl_sfx_r_exp3; globalfunction(delta_update, "CSQC_Delta_Update");/*EXT_CSQC_1*/ \ globalfunction(delta_remove, "CSQC_Delta_Remove");/*EXT_CSQC_1*/ \ \ - globalfunction(serversound, "CSQC_ServerSound"); \ + globalfunction(event_sound, "CSQC_Event_Sound"); \ + globalfunction(serversound, "CSQC_ServerSound");/*obsolete, use event_sound*/ \ + globalfunction(loadresource, "CSQC_LoadResource");/*EXT_CSQC_1*/ \ + globalfunction(parse_tempentity, "CSQC_Parse_TempEntity");/*EXT_CSQC_ABSOLUTLY_VILE*/ \ \ /*These are pointers to the csqc's globals.*/ \ globalfloat(time, "time"); /*float Written before entering most qc functions*/ \ @@ -116,6 +120,7 @@ extern sfx_t *cl_sfx_r_exp3; globalfloat(player_localnum, "player_localnum"); /*float the entity number of the local player*/ \ globalfloat(intermission, "intermission"); /*float set when the client receives svc_intermission*/ \ globalvector(view_angles, "view_angles"); /*float set to the view angles at the start of each new frame (EXT_CSQC_1)*/ \ + globalfloat(dpcompat_sbshowscores, "sb_showscores"); /*float ask darkplaces people, its not part of the csqc standard */ \ \ globalvector(pmove_org, "pmove_org"); /*read/written by runplayerphysics*/ \ globalvector(pmove_vel, "pmove_vel"); /*read/written by runplayerphysics*/ \ @@ -132,6 +137,7 @@ extern sfx_t *cl_sfx_r_exp3; globalfloat(input_lightlevel, "input_lightlevel"); /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat(input_weapon, "input_weapon"); /*float filled by getinputstate, read by runplayerphysics*/ \ globalfloat(input_servertime, "input_servertime"); /*float filled by getinputstate, read by runplayerphysics*/ \ + globalfloat(input_clienttime, "input_clienttime"); /*float filled by getinputstate, read by runplayerphysics*/ \ \ globalfloat(movevar_gravity, "movevar_gravity"); /*float obtained from the server*/ \ globalfloat(movevar_stopspeed, "movevar_stopspeed"); /*float obtained from the server*/ \ @@ -222,6 +228,21 @@ static void CSQC_FindGlobals(void) fieldfloat(dimension_hit); \ fieldfloat(dimension_solid); \ \ + fieldfloat(baseframe); /*FTE_CSQC_BASEFRAME*/\ + fieldfloat(baseframe2); /*FTE_CSQC_BASEFRAME*/\ + fieldfloat(baseframe1time); /*FTE_CSQC_BASEFRAME*/\ + fieldfloat(baseframe2time); /*FTE_CSQC_BASEFRAME*/\ + fieldfloat(baselerpfrac); /*FTE_CSQC_BASEFRAME*/\ + fieldfloat(basebone); /*FTE_CSQC_BASEFRAME*/\ + \ + fieldfloat(bonecontrol1); /*FTE_CSQC_HALFLIFE_MODELS*/\ + fieldfloat(bonecontrol2); /*FTE_CSQC_HALFLIFE_MODELS*/\ + fieldfloat(bonecontrol3); /*FTE_CSQC_HALFLIFE_MODELS*/\ + fieldfloat(bonecontrol4); /*FTE_CSQC_HALFLIFE_MODELS*/\ + fieldfloat(bonecontrol5); /*FTE_CSQC_HALFLIFE_MODELS*/\ + fieldfloat(subblendfrac); /*FTE_CSQC_HALFLIFE_MODELS*/\ + fieldfloat(basesubblendfrac); /*FTE_CSQC_HALFLIFE_MODELS*/\ + \ fieldfloat(drawmask); /*So that the qc can specify all rockets at once or all bannanas at once*/ \ fieldfunction(predraw); /*If present, is called just before it's drawn.*/ \ \ @@ -367,7 +388,7 @@ void CS_ClearWorld (void) CS_LinkEdict((csqcedict_t*)EDICT_NUM(csqcprogs, i), false); } -void CS_UnlinkEdict (csqcedict_t *ent) +static void CS_UnlinkEdict (csqcedict_t *ent) { if (!ent->area.prev) return; // not linked in anywhere @@ -443,7 +464,8 @@ typedef struct { vec3_t maxs; csqcedict_t *passedict; } moveclip_t; -void CS_ClipToLinks ( areanode_t *node, moveclip_t *clip ) +#define CSEDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,csqcedict_t,area) +static void CS_ClipToLinks ( areanode_t *node, moveclip_t *clip ) { model_t *model; trace_t tr; @@ -454,7 +476,7 @@ void CS_ClipToLinks ( areanode_t *node, moveclip_t *clip ) for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) { next = l->next; - touch = (csqcedict_t*)EDICT_FROM_AREA(l); + touch = (csqcedict_t*)CSEDICT_FROM_AREA(l); if (touch->v->solid == SOLID_NOT) continue; if (touch == clip->passedict) @@ -552,7 +574,7 @@ static trace_t CS_Move(vec3_t v1, vec3_t mins, vec3_t maxs, vec3_t v2, float nom return clip.trace; } -void CS_CheckVelocity(csqcedict_t *ent) +static void CS_CheckVelocity(csqcedict_t *ent) { } @@ -569,7 +591,7 @@ static void PF_cs_remove (progfuncs_t *prinst, struct globalvars_s *pr_globals) return; } - P_DelinkTrailstate(&ed->trailstate); + pe->DelinkTrailstate(&ed->trailstate); CS_UnlinkEdict(ed); ED_Free (prinst, (void*)ed); } @@ -608,7 +630,7 @@ static void PF_NoCSQC (progfuncs_t *prinst, struct globalvars_s *pr_globals) static void PF_cl_cprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *str = PF_VarString(prinst, 0, pr_globals); - SCR_CenterPrint(0, str); + SCR_CenterPrint(0, str, true); } static void PF_cs_makevectors (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -684,6 +706,7 @@ void EularToQuaternian(vec3_t angles, float *quat) #define CSQCRF_ADDITIVE 8 //add instead of blend #define CSQCRF_USEAXIS 16 //use v_forward/v_right/v_up as an axis/matrix - predraw is needed to use this properly #define CSQCRF_NOSHADOW 32 //don't cast shadows upon other entities (can still be self shadowing, if the engine wishes, and not additive) +#define CSQCRF_FRAMETIMESARESTARTTIMES 64 //EXT_CSQC_1: frame times should be read as (time-frametime). static model_t *CSQC_GetModelForIndex(int index) { @@ -701,42 +724,85 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) { int i; model_t *model; + int rflags; i = in->v->modelindex; model = CSQC_GetModelForIndex(in->v->modelindex); if (!model) return false; //there might be other ent types later as an extension that stop this. - if (!model) - { - Con_Printf("CopyCSQCEdictToEntity: model wasn't precached!\n"); - return false; - } - memset(out, 0, sizeof(*out)); out->model = model; if (in->v->renderflags) { - i = in->v->renderflags; - if (i & CSQCRF_VIEWMODEL) + rflags = in->v->renderflags; + if (rflags & CSQCRF_VIEWMODEL) out->flags |= Q2RF_DEPTHHACK|Q2RF_WEAPONMODEL; - if (i & CSQCRF_EXTERNALMODEL) + if (rflags & CSQCRF_EXTERNALMODEL) out->flags |= Q2RF_EXTERNALMODEL; - if (i & CSQCRF_DEPTHHACK) + if (rflags & CSQCRF_DEPTHHACK) out->flags |= Q2RF_DEPTHHACK; - if (i & CSQCRF_ADDITIVE) + if (rflags & CSQCRF_ADDITIVE) out->flags |= Q2RF_ADDATIVE; //CSQCRF_USEAXIS is below - if (i & CSQCRF_NOSHADOW) + if (rflags & CSQCRF_NOSHADOW) out->flags |= RF_NOSHADOW; + //CSQCRF_FRAMETIMESARESTARTTIMES is below + } + else + rflags = 0; + +//From here. + + //FTE_CSQC_HALFLIFE_MODELS +#ifdef HALFLIFEMODELS + out->bonecontrols[0] = in->v->bonecontrol1; + out->bonecontrols[1] = in->v->bonecontrol2; + out->bonecontrols[2] = in->v->bonecontrol3; + out->bonecontrols[3] = in->v->bonecontrol4; + out->bonecontrols[4] = in->v->bonecontrol5; + out->subblendfrac = in->v->subblendfrac; + out->basesubblendfrac = in->v->basesubblendfrac; +#endif + + //FTE_CSQC_BASEFRAME + out->basebone = in->v->basebone; + if (out->basebone) + { //small optimisation. + out->baseframe1 = in->v->baseframe; + out->baseframe2 = in->v->baseframe2; + if (rflags & CSQCRF_FRAMETIMESARESTARTTIMES) + { + out->baseframe1time = *csqcg.time - in->v->baseframe1time; + out->baseframe2time = *csqcg.time - in->v->baseframe2time; + } + else + { + out->baseframe1time = in->v->baseframe1time; + out->baseframe2time = in->v->baseframe2time; + } + out->baselerpfrac = in->v->baselerpfrac; } - out->frame = in->v->frame; - out->oldframe = in->v->frame2; + //and the normal frames. + out->frame1 = in->v->frame; + out->frame2 = in->v->frame2; out->lerpfrac = in->v->lerpfrac; + if (rflags & CSQCRF_FRAMETIMESARESTARTTIMES) + { + out->frame1time = *csqcg.time - in->v->frame1time; + out->frame2time = *csqcg.time - in->v->frame2time; + } + else + { + out->frame1time = in->v->frame1time; + out->frame2time = in->v->frame2time; + } +//to here... We read only frames and frame times... Yeah... Q1 originally had only a frame field. :D + VectorCopy(in->v->origin, out->origin); - if ((int)in->v->renderflags & CSQCRF_USEAXIS) + if (rflags & CSQCRF_USEAXIS) { VectorCopy(csqcg.forward, out->axis[0]); VectorNegate(csqcg.right, out->axis[1]); @@ -756,9 +822,6 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) out->scale = in->v->scale; } - out->frame1time = in->v->frame1time; - out->frame2time = in->v->frame2time; - if (in->v->colormap > 0 && in->v->colormap <= MAX_CLIENTS) { #ifdef SWQUAKE @@ -817,17 +880,6 @@ static void PF_R_AddEntity(progfuncs_t *prinst, struct globalvars_s *pr_globals) csqcedict_t *in = (void*)G_EDICT(prinst, OFS_PARM0); entity_t ent; - if (in->v->predraw) - { - int oldself = *csqcg.self; - *csqcg.self = EDICT_TO_PROG(prinst, (void*)in); - PR_ExecuteProgram(prinst, in->v->predraw); - *csqcg.self = oldself; - - if (in->isfree) - return; //bummer... - } - if (CopyCSQCEdictToEntity(in, &ent)) V_AddAxisEntity(&ent); @@ -864,8 +916,10 @@ static void PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_s *pr_glob { int mask = G_FLOAT(OFS_PARM0); csqcedict_t *ent; + entity_t rent; int e; + int oldself = *csqcg.self; for (e=1; e < *prinst->parms->sv_num_edicts; e++) { ent = (void*)EDICT_NUM(prinst, e); @@ -874,10 +928,20 @@ static void PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_s *pr_glob if ((int)ent->v->drawmask & mask) { - G_INT(OFS_PARM0) = EDICT_TO_PROG(prinst, (void*)ent); - PF_R_AddEntity(prinst, pr_globals); + if (ent->v->predraw) + { + *csqcg.self = EDICT_TO_PROG(prinst, (void*)ent); + PR_ExecuteProgram(prinst, ent->v->predraw); + + if (ent->isfree) + continue; //bummer... + } + + if (CopyCSQCEdictToEntity(ent, &rent)) + V_AddAxisEntity(&rent); } } + *csqcg.self = oldself; if (cl.worldmodel) { @@ -1514,7 +1578,7 @@ static void PF_cs_tracetoss (progfuncs_t *prinst, struct globalvars_s *pr_global *csqcg.trace_inopen = trace.inopen; VectorCopy (trace.endpos, csqcg.trace_endpos); VectorCopy (trace.plane.normal, csqcg.trace_plane_normal); - pr_global_struct->trace_plane_dist = trace.plane.dist; + *csqcg.trace_plane_dist = trace.plane.dist; if (trace.ent) *csqcg.trace_ent = EDICT_TO_PROG(prinst, trace.ent); else @@ -1662,7 +1726,7 @@ static void PF_cs_PrecacheModel(progfuncs_t *prinst, struct globalvars_s *pr_glo Q_strncpyz(cl.model_csqcname[-freei], modelname, sizeof(cl.model_csqcname[-freei])); //allocate a slot now modelindex = freei; - CL_CheckOrEnqueDownloadFile(modelname, modelname); + CL_CheckOrEnqueDownloadFile(modelname, modelname, 0); cl.model_csqcprecache[-freei] = NULL; } @@ -1686,7 +1750,15 @@ static void PF_cs_ModelnameForIndex(progfuncs_t *prinst, struct globalvars_s *pr static void PF_ReadByte(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - G_FLOAT(OFS_RETURN) = MSG_ReadByte(); + if (csqc_fakereadbyte != -1) + { + G_FLOAT(OFS_RETURN) = csqc_fakereadbyte; + csqc_fakereadbyte = -1; + } + else + { + G_FLOAT(OFS_RETURN) = MSG_ReadByte(); + } } static void PF_ReadChar(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -1744,11 +1816,11 @@ static void PF_ReadAngle(progfuncs_t *prinst, struct globalvars_s *pr_globals) static void PF_objerror (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *s; - edict_t *ed; + struct edict_s *ed; s = PF_VarString(prinst, 0, pr_globals); /* Con_Printf ("======OBJECT ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name),s); -*/ ed = PROG_TO_EDICT(prinst, pr_global_struct->self); +*/ ed = PROG_TO_EDICT(prinst, *csqcg.self); /* ED_Print (ed); */ ED_Print(prinst, ed); @@ -1763,9 +1835,6 @@ static void PF_objerror (progfuncs_t *prinst, struct globalvars_s *pr_globals) prinst->AbortStack(prinst); PR_BIError (prinst, "Program error: %s", s); - - if (sv.time > 10) - Cbuf_AddText("restart\n", RESTRICT_LOCAL); } } @@ -1797,15 +1866,15 @@ static void PF_cs_trailparticles (progfuncs_t *prinst, struct globalvars_s *pr_g float *end = G_VECTOR(OFS_PARM3); if (!ent->entnum) //world trails are non-state-based. - P_ParticleTrail(start, end, efnum, NULL); + pe->ParticleTrail(start, end, efnum, NULL); else - P_ParticleTrail(start, end, efnum, &ent->trailstate); + pe->ParticleTrail(start, end, efnum, &ent->trailstate); } static void PF_cs_particlesloaded (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *effectname = PR_GetStringOfs(prinst, OFS_PARM0); - G_FLOAT(OFS_RETURN) = P_DescriptionIsLoaded(effectname); + G_FLOAT(OFS_RETURN) = pe->FindParticleType(effectname)+1; } static void cs_set_input_state (usercmd_t *cmd) @@ -1814,9 +1883,9 @@ static void cs_set_input_state (usercmd_t *cmd) *csqcg.input_timelength = cmd->msec/1000.0f; if (csqcg.input_angles) { - csqcg.input_angles[0] = SHORT2ANGLE(cmd->angles[0]+0.5); - csqcg.input_angles[1] = SHORT2ANGLE(cmd->angles[1]+0.5); - csqcg.input_angles[2] = SHORT2ANGLE(cmd->angles[2]+0.5); + csqcg.input_angles[0] = SHORT2ANGLE(cmd->angles[0]); + csqcg.input_angles[1] = SHORT2ANGLE(cmd->angles[1]); + csqcg.input_angles[2] = SHORT2ANGLE(cmd->angles[2]); } if (csqcg.input_movevalues) { @@ -1835,6 +1904,8 @@ static void cs_set_input_state (usercmd_t *cmd) *csqcg.input_weapon = cmd->weapon; if (csqcg.input_servertime) *csqcg.input_servertime = cmd->servertime/1000.0f; + if (csqcg.input_clienttime) + *csqcg.input_clienttime = cmd->fclienttime/1000.0f; } static void cs_get_input_state (usercmd_t *cmd) @@ -2000,6 +2071,10 @@ typedef struct { *csqcg.pmove_waterjumptime = pmove.waterjumptime; VectorCopy(pmove.origin, csqcg.pmove_org); VectorCopy(pmove.velocity, csqcg.pmove_vel); + + pmove.origin[0] = ((int)(pmove.origin[0]*8))/8.0f; + pmove.origin[1] = ((int)(pmove.origin[1]*8))/8.0f; + pmove.origin[2] = ((int)(pmove.origin[2]*8))/8.0f; } static void PF_cs_getentitytoken (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2011,7 +2086,11 @@ static void PF_cs_getentitytoken (progfuncs_t *prinst, struct globalvars_s *pr_g } else { - csqcmapentitydata = COM_ParseToken(csqcmapentitydata, "{}()\'\":,"); + com_tokentype = TTP_LINEENDING; + while(com_tokentype == TTP_LINEENDING) + { + csqcmapentitydata = COM_ParseToken(csqcmapentitydata, "{}()\'\":,"); + } RETURN_TSTRING(com_token); } } @@ -2149,17 +2228,29 @@ static void PF_cs_getplayerkey (progfuncs_t *prinst, struct globalvars_s *pr_glo G_INT(OFS_RETURN) = 0; } -#define lh_extension_t void -lh_extension_t *checkfteextensionsv(char *name); -lh_extension_t *checkextension(char *name); - static void PF_checkextension (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *extname = PR_GetStringOfs(prinst, OFS_PARM0); - G_FLOAT(OFS_RETURN) = checkextension(extname) || checkfteextensionsv(extname); + int i; + for (i = 0; i < QSG_Extensions_count; i++) + { + if (!QSG_Extensions[i].name) + continue; + + if (i < 32 && cls.protocol == CP_QUAKEWORLD) + if (!(cls.fteprotocolextensions & (1<entnum, channel, sfx, entity->v->origin, volume, attenuation); }; +void PF_cs_pointsound(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *sample; + float *origin; + float volume; + float attenuation; + + sfx_t *sfx; + + origin = G_VECTOR(OFS_PARM0); + sample = PR_GetStringOfs(prinst, OFS_PARM1); + volume = G_FLOAT(OFS_PARM2); + attenuation = G_FLOAT(OFS_PARM3); + + sfx = S_PrecacheSound(sample); + if (sfx) + S_StartSound(0, 0, sfx, origin, volume, attenuation); +} + static void PF_cs_particle(progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *org = G_VECTOR(OFS_PARM0); @@ -2187,7 +2297,7 @@ static void PF_cs_particle(progfuncs_t *prinst, struct globalvars_s *pr_globals) float colour = G_FLOAT(OFS_PARM2); float count = G_FLOAT(OFS_PARM2); - P_RunParticleEffect(org, dir, colour, count); + pe->RunParticleEffect(org, dir, colour, count); } static void PF_cs_particle2(progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -2203,7 +2313,7 @@ static void PF_cs_particle2(progfuncs_t *prinst, struct globalvars_s *pr_globals effect = G_FLOAT(OFS_PARM4); count = G_FLOAT(OFS_PARM5); - P_RunParticleEffect2 (org, dmin, dmax, colour, effect, count); + pe->RunParticleEffect2 (org, dmin, dmax, colour, effect, count); } static void PF_cs_particle3(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2219,7 +2329,7 @@ static void PF_cs_particle3(progfuncs_t *prinst, struct globalvars_s *pr_globals effect = G_FLOAT(OFS_PARM3); count = G_FLOAT(OFS_PARM4); - P_RunParticleEffect3(org, box, colour, effect, count); + pe->RunParticleEffect3(org, box, colour, effect, count); } static void PF_cs_particle4(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2236,7 +2346,7 @@ static void PF_cs_particle4(progfuncs_t *prinst, struct globalvars_s *pr_globals effect = G_FLOAT(OFS_PARM3); count = G_FLOAT(OFS_PARM4); - P_RunParticleEffect4(org, radius, colour, effect, count); + pe->RunParticleEffect4(org, radius, colour, effect, count); } @@ -2294,7 +2404,7 @@ static void PF_cs_lightstyle (progfuncs_t *prinst, struct globalvars_s *pr_globa cl_lightstyle[stnum].length = Q_strlen(cl_lightstyle[stnum].map); } -void PF_cs_changeyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals) +static void PF_cs_changeyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals) { csqcedict_t *ent; float ideal, current, move, speed; @@ -2330,7 +2440,7 @@ void PF_cs_changeyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals) ent->v->angles[1] = anglemod (current + move); } -void PF_cs_changepitch (progfuncs_t *prinst, struct globalvars_s *pr_globals) +static void PF_cs_changepitch (progfuncs_t *prinst, struct globalvars_s *pr_globals) { csqcedict_t *ent; float ideal, current, move, speed; @@ -2375,18 +2485,18 @@ static void PF_cs_findradius (progfuncs_t *prinst, struct globalvars_s *pr_globa vec3_t eorg; int i, j; - chain = (csqcedict_t *)sv.edicts; + chain = (csqcedict_t *)*prinst->parms->sv_edicts; org = G_VECTOR(OFS_PARM0); rad = G_FLOAT(OFS_PARM1); - for (i=1 ; iparms->sv_num_edicts ; i++) { ent = (void*)EDICT_NUM(prinst, i); if (ent->isfree) continue; - if (ent->v->solid == SOLID_NOT) - continue; +// if (ent->v->solid == SOLID_NOT && !sv_gameplayfix_blowupfallenzombies.value) +// continue; for (j=0 ; j<3 ; j++) eorg[j] = org[j] - (ent->v->origin[j] + (ent->v->mins[j] + ent->v->maxs[j])*0.5); if (Length(eorg) > rad) @@ -2414,8 +2524,9 @@ static void PF_cl_te_bloodqw (progfuncs_t *prinst, struct globalvars_s *pr_globa float scaler = 1; if (*prinst->callargc >= 2) //fte is a quakeworld engine scaler = G_FLOAT(OFS_PARM1); - if (P_RunParticleEffectType(pos, NULL, scaler, pt_blood)) - P_RunParticleEffect (pos, vec3_origin, 73, 20*scaler); + if (P_RunParticleEffectType(pos, NULL, scaler, ptqw_blood)) + if (P_RunParticleEffectType(pos, NULL, scaler, ptdp_blood)) + P_RunParticleEffect (pos, vec3_origin, 73, 20*scaler); } static void PF_cl_te_blooddp (progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -2423,13 +2534,14 @@ static void PF_cl_te_blooddp (progfuncs_t *prinst, struct globalvars_s *pr_globa float *dir = G_VECTOR(OFS_PARM1); float scaler = G_FLOAT(OFS_PARM2); - if (P_RunParticleEffectType(pos, dir, scaler, pt_blood)) - P_RunParticleEffect (pos, dir, 73, 20*scaler); + if (P_RunParticleEffectType(pos, dir, scaler, ptdp_blood)) + if (P_RunParticleEffectType(pos, dir, scaler, ptqw_blood)) + P_RunParticleEffect (pos, dir, 73, 20*scaler); } static void PF_cl_te_lightningblood (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *pos = G_VECTOR(OFS_PARM0); - if (P_RunParticleEffectType(pos, NULL, 1, pt_lightningblood)) + if (P_RunParticleEffectType(pos, NULL, 1, ptqw_lightningblood)) P_RunParticleEffect (pos, vec3_origin, 225, 50); } static void PF_cl_te_spike (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2479,7 +2591,7 @@ static void PF_cl_te_explosion (progfuncs_t *prinst, struct globalvars_s *pr_glo static void PF_cl_te_tarexplosion (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *pos = G_VECTOR(OFS_PARM0); - P_BlobExplosion (pos); + P_RunParticleEffectType(pos, NULL, 1, pt_tarexplosion); S_StartSound (-2, 0, cl_sfx_r_exp3, pos, 1, 1); } @@ -2502,7 +2614,7 @@ static void PF_cl_te_knightspike (progfuncs_t *prinst, struct globalvars_s *pr_g static void PF_cl_te_lavasplash (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *pos = G_VECTOR(OFS_PARM0); - P_LavaSplash (pos); + P_RunParticleEffectType(pos, NULL, 1, pt_lavasplash); } static void PF_cl_te_teleport (progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -2741,7 +2853,121 @@ static void PF_cs_OpenPortal (progfuncs_t *prinst, struct globalvars_s *pr_globa #endif } -void PF_cs_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals) +// #487 float(string name) gecko_create( string name ) +static void PF_cs_gecko_create (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + cin_t *cin; +#ifdef Q3SHADERS + cin = R_ShaderGetCinematic(shader); +#else + cin = NULL; +#endif + + if (!cin) + G_FLOAT(OFS_RETURN) = 0; + else + G_FLOAT(OFS_RETURN) = 1; +} +// #488 void(string name) gecko_destroy( string name ) +static void PF_cs_gecko_destroy (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +} +// #489 void(string name) gecko_navigate( string name, string URI ) +static void PF_cs_gecko_navigate (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + char *command = PR_GetStringOfs(prinst, OFS_PARM1); + cin_t *cin; +#ifdef Q3SHADERS + cin = R_ShaderGetCinematic(shader); +#else + cin = NULL; +#endif + + if (!cin) + return; + + Media_Send_Command(cin, command); +} +// #490 float(string name) gecko_keyevent( string name, float key, float eventtype ) +static void PF_cs_gecko_keyevent (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + int key = G_FLOAT(OFS_PARM1); + int eventtype = G_FLOAT(OFS_PARM2); + cin_t *cin; +#ifdef Q3SHADERS + cin = R_ShaderGetCinematic(shader); +#else + cin = NULL; +#endif + + if (!cin) + return; + Media_Send_KeyEvent(cin, MP_TranslateDPtoFTECodes(key), eventtype); +} +// #491 void gecko_mousemove( string name, float x, float y ) +static void PF_cs_gecko_mousemove (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + float posx = G_FLOAT(OFS_PARM1); + float posy = G_FLOAT(OFS_PARM2); + cin_t *cin; +#ifdef Q3SHADERS + cin = R_ShaderGetCinematic(shader); +#else + cin = NULL; +#endif + + if (!cin) + return; + Media_Send_MouseMove(cin, posx, posy); +} +// #492 void gecko_resize( string name, float w, float h ) +static void PF_cs_gecko_resize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + float sizex = G_FLOAT(OFS_PARM1); + float sizey = G_FLOAT(OFS_PARM2); + cin_t *cin; +#ifdef Q3SHADERS + cin = R_ShaderGetCinematic(shader); +#else + cin = NULL; +#endif + if (!cin) + return; + Media_Send_Resize(cin, sizex, sizey); +} +// #493 vector gecko_get_texture_extent( string name ) +static void PF_cs_gecko_get_texture_extent (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *shader = PR_GetStringOfs(prinst, OFS_PARM0); + float *ret = G_VECTOR(OFS_RETURN); + int sx, sy; + cin_t *cin; +#ifdef Q3SHADERS + cin = R_ShaderGetCinematic(shader); +#else + cin = NULL; +#endif + + if (cin) + { + Media_Send_GetSize(cin, &sx, &sy); + } + else + { + sx = 0; + sy = 0; + } + ret[0] = sx; + ret[1] = sy; + ret[2] = 0; +} + +static void PF_cs_droptofloor (progfuncs_t *prinst, struct globalvars_s *pr_globals) { csqcedict_t *ent; vec3_t end; @@ -2787,7 +3013,11 @@ static void PF_cl_playingdemo (progfuncs_t *prinst, struct globalvars_s *pr_glob static void PF_cl_runningserver (progfuncs_t *prinst, struct globalvars_s *pr_globals) { +#ifdef CLIENTONLY + G_FLOAT(OFS_RETURN) = false; +#else G_FLOAT(OFS_RETURN) = !!sv.active; +#endif } static void PF_cl_getlight (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2804,7 +3034,7 @@ static void PF_Stub (progfuncs_t *prinst, struct globalvars_s *pr_globals) } */ -void PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalvars_s *pr_globals) +static void PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalvars_s *pr_globals) { csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); int tagnum = G_FLOAT(OFS_PARM1); @@ -2866,6 +3096,54 @@ void PF_rotatevectorsbytag (progfuncs_t *prinst, struct globalvars_s *pr_globals VectorCopy(srcorg, retorg); } + +static void EdictToTransform(csqcedict_t *ed, float *trans) +{ + AngleVectors(ed->v->angles, trans+0, trans+4, trans+8); + VectorInverse(trans+4); + + trans[3] = ed->v->origin[0]; + trans[7] = ed->v->origin[1]; + trans[11] = ed->v->origin[2]; +} + +static void PF_cs_gettaginfo (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); + int tagnum = G_FLOAT(OFS_PARM1); + + float *origin = G_VECTOR(OFS_RETURN); + + int modelindex = ent->v->modelindex; + int frame1 = ent->v->frame; + int frame2 = ent->v->frame2; + float lerp = ent->v->lerpfrac; + float frame1time = ent->v->frame1time; + float frame2time = ent->v->frame2time; + + model_t *mod = CSQC_GetModelForIndex(modelindex); + + float transent[12]; + float transforms[12]; + float result[12]; + +#pragma message("PF_cs_gettaginfo: This function doesn't honour attachments (but setattachment isn't implemented yet anyway)") + if (!Mod_GetTag(mod, tagnum, frame1, frame2, lerp, frame1time, frame2time, transforms)) + { + memset(transforms, 0, sizeof(transforms)); + } + + EdictToTransform(ent, transent); + R_ConcatTransforms((void*)transent, (void*)transforms, (void*)result); + + origin[0] = result[3]; + origin[1] = result[7]; + origin[2] = result[11]; + VectorCopy((result+0), csqcg.forward); + VectorCopy((result+4), csqcg.right); + VectorCopy((result+8), csqcg.up); + +} static void PF_cs_gettagindex (progfuncs_t *prinst, struct globalvars_s *pr_globals) { csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM0); @@ -2938,7 +3216,7 @@ static void PF_shaderforname (progfuncs_t *prinst, struct globalvars_s *pr_globa #endif } -qboolean CS_CheckBottom (csqcedict_t *ent) +static qboolean CS_CheckBottom (csqcedict_t *ent) { int savedhull; vec3_t mins, maxs, start, stop; @@ -3023,7 +3301,7 @@ static void PF_cs_break (progfuncs_t *prinst, struct globalvars_s *pr_globals) #endif } -qboolean CS_movestep (csqcedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean set_trace) +static qboolean CS_movestep (csqcedict_t *ent, vec3_t move, qboolean relink, qboolean noenemy, qboolean set_trace) { float dz; vec3_t oldorg, neworg, end; @@ -3183,12 +3461,15 @@ static void PF_cs_walkmove (progfuncs_t *prinst, struct globalvars_s *pr_globals static void CS_ConsoleCommand_f(void) { //FIXME: unregister them. char cmd[2048]; - sprintf(cmd, "%s %s", Cmd_Argv(0), Cmd_Args()); + Q_snprintfz(cmd, sizeof(cmd), "%s %s", Cmd_Argv(0), Cmd_Args()); CSQC_ConsoleCommand(cmd); } static void PF_cs_registercommand (progfuncs_t *prinst, struct globalvars_s *pr_globals) { char *str = PF_VarString(prinst, 0, pr_globals); + if (!strcmp(str, "+showscores") || !strcmp(str, "-showscores") || + !strcmp(str, "+showteamscores") || !strcmp(str, "-showteamscores")) + return; Cmd_AddRemCommand(str, CS_ConsoleCommand_f); } @@ -3221,11 +3502,15 @@ typedef struct oldcsqcpack_s } oldcsqcpack_t; static oldcsqcpack_t loadedcsqcpack[2]; static int loadedcsqcpacknum; +static csqcedict_t *deltaedplayerents[MAX_CLIENTS]; #define RSES_NOLERP 1 -#define RSES_AUTOROTATE 2 +#define RSES_NOROTATE 2 +#define RSES_NOTRAILS 4 +#define RSES_NOLIGHTS 8 + packet_entities_t *CL_ProcessPacketEntities(float *servertime, qboolean nolerp); -static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) +void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *pr_globals) { //read the arguments the csqc gave us unsigned int flags = G_FLOAT(OFS_PARM0); @@ -3241,12 +3526,84 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p oldcsqcpack_t *oldlist, *newlist; int oldidx = 0, newidx = 0; model_t *model; + player_state_t *srcp; //setup servertime += cl.servertime; pack = CL_ProcessPacketEntities(&servertime, (flags & RSES_NOLERP)); if (!pack) - return; //can't do anything, just don't update + return; //we're lagging. can't do anything, just don't update + + for (i = 0; i < MAX_CLIENTS; i++) + { + srcp = &cl.frames[cl.validsequence&UPDATE_MASK].playerstate[i]; + ent = deltaedplayerents[i]; + if (srcp->messagenum == cl.validsequence && (i+1 >= maxcsqcentities || !csqcent[i+1])) + { + if (!ent) + { + ent = (csqcedict_t *)ED_Alloc(prinst); + deltaedplayerents[i] = ent; + G_FLOAT(OFS_PARM0) = true; + } + else + { + G_FLOAT(OFS_PARM0) = false; + } + + ent->v->entnum = i+1; + + if (cl.spectator && !Cam_DrawPlayer(0, i)) + { + ent->v->modelindex = 0; + } + else + ent->v->modelindex = srcp->modelindex; + ent->v->skin = srcp->skinnum; + + ent->v->frame1time = cl.time - cl.lerpplayers[i].framechange; + ent->v->frame2time = cl.time - cl.lerpplayers[i].oldframechange; + + if (ent->v->frame != cl.lerpplayers[i].frame) + { + ent->v->frame2 = ent->v->frame; + ent->v->frame = cl.lerpplayers[i].frame; + } + + ent->v->lerpfrac = 1-(cl.time - cl.lerpplayers[i].framechange)*10; + if (ent->v->lerpfrac > 1) + ent->v->lerpfrac = 1; + else if (ent->v->lerpfrac < 0) + { + ent->v->lerpfrac = 0; + } + VectorCopy(srcp->origin, ent->v->origin); + VectorCopy(srcp->velocity, ent->v->velocity); + VectorCopy(srcp->viewangles, ent->v->angles); + ent->v->angles[0] *= -0.333; + ent->v->colormap = i+1; + ent->v->scale = srcp->scale/16.0f; + //ent->v->fatness = srcp->fatness; + ent->v->alpha = srcp->alpha/255.0f; + +// ent->v->colormod[0] = (srcp->colormod[0]/255.0f)*8; +// ent->v->colormod[1] = (srcp->colormod[1]/255.0f)*8; +// ent->v->colormod[2] = (srcp->colormod[2]/255.0f)*8; +// ent->v->effects = srcp->effects; + + if (csqcg.delta_update) + { + *csqcg.self = EDICT_TO_PROG(prinst, (void*)ent); + PR_ExecuteProgram(prinst, csqcg.delta_update); + } + } + else if (ent) + { + *csqcg.self = EDICT_TO_PROG(prinst, (void*)ent); + PR_ExecuteProgram(prinst, csqcg.delta_remove); + deltaedplayerents[i] = NULL; + } + } oldlist = &loadedcsqcpack[loadedcsqcpacknum]; loadedcsqcpacknum ^= 1; @@ -3288,6 +3645,17 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p } } + if (src->number < maxcsqcentities && csqcent[src->number]) + { + //in the csqc list + if (oldent) + { + *csqcg.self = EDICT_TO_PROG(prinst, (void*)oldent); + PR_ExecuteProgram(prinst, csqcg.delta_remove); + } + continue; + } + //note: we don't delta the state here. we just replace the old. //its already lerped @@ -3315,10 +3683,13 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p } model = cl.model_precache[src->modelindex]; - if (oldent && model->particletrail >= 0) + if (!(flags & RSES_NOTRAILS)) { - if (P_ParticleTrail (ent->v->origin, src->origin, model->particletrail, &(le->trailstate))) - P_ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); + if (oldent && model->particletrail >= 0) + { + if (pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, &(le->trailstate))) + pe->ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); + } } ent->v->entnum = src->number; @@ -3360,7 +3731,7 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p if (model) { - if ((flags & RSES_AUTOROTATE) && (model->flags & EF_ROTATE)) + if (!(flags & RSES_NOROTATE) && (model->flags & EF_ROTATE)) { ent->v->angles[0] = 0; ent->v->angles[1] = 100*servertime; @@ -3407,7 +3778,6 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p //PF_cl_ - works in csqc and menu (if needed...) //these are the builtins that still need to be added. -#define PF_cs_gettaginfo PF_Fixme #define PS_cs_setattachment PF_Fixme #define PF_R_PolygonBegin PF_Fixme // #306 void(string texturename) R_BeginPolygon (EXT_CSQC_???) @@ -3415,455 +3785,472 @@ static void PF_ReadServerEntityState(progfuncs_t *prinst, struct globalvars_s *p #define PF_R_PolygonEnd PF_Fixme // #308 void() R_EndPolygon (EXT_CSQC_???) //warning: functions that depend on globals are bad, mkay? -static builtin_t csqc_builtins[] = { +static struct { + char *name; + builtin_t bifunc; + int ebfsnum; +} BuiltinList[] = { //0 -PF_Fixme, // #0 -PF_cs_makevectors, // #1 void() makevectors (QUAKE) -PF_cs_SetOrigin, // #2 void(entity e, vector org) setorigin (QUAKE) -PF_cs_SetModel, // #3 void(entity e, string modl) setmodel (QUAKE) -PF_cs_SetSize, // #4 void(entity e, vector mins, vector maxs) setsize (QUAKE) -PF_Fixme, // #5 -PF_cs_break, // #6 void() debugbreak (QUAKE) -PF_random, // #7 float() random (QUAKE) -PF_cs_sound, // #8 void(entity e, float chan, string samp, float vol, float atten) sound (QUAKE) -PF_normalize, // #9 vector(vector in) normalize (QUAKE) + {"makevectors", PF_cs_makevectors, 1}, // #1 void() makevectors (QUAKE) + {"setorigin", PF_cs_SetOrigin, 2}, // #2 void(entity e, vector org) setorigin (QUAKE) + {"setmodel", PF_cs_SetModel, 3}, // #3 void(entity e, string modl) setmodel (QUAKE) + {"setsize", PF_cs_SetSize, 4}, // #4 void(entity e, vector mins, vector maxs) setsize (QUAKE) +//5 + {"debugbreak", PF_cs_break, 6}, // #6 void() debugbreak (QUAKE) + {"random", PF_random, 7}, // #7 float() random (QUAKE) + {"sound", PF_cs_sound, 8}, // #8 void(entity e, float chan, string samp, float vol, float atten) sound (QUAKE) + {"normalize", PF_normalize, 9}, // #9 vector(vector in) normalize (QUAKE) //10 -PF_error, // #10 void(string errortext) error (QUAKE) -PF_objerror, // #11 void(string errortext) onjerror (QUAKE) -PF_vlen, // #12 float(vector v) vlen (QUAKE) -PF_vectoyaw, // #13 float(vector v) vectoyaw (QUAKE) -PF_Spawn, // #14 entity() spawn (QUAKE) -PF_cs_remove, // #15 void(entity e) remove (QUAKE) -PF_cs_traceline, // #16 void(vector v1, vector v2, float nomonst, entity forent) traceline (QUAKE) -PF_NoCSQC, // #17 entity() checkclient (QUAKE) (don't support) -PF_FindString, // #18 entity(entity start, .string fld, string match) findstring (QUAKE) -PF_cs_PrecacheSound, // #19 void(string str) precache_sound (QUAKE) + {"error", PF_error, 10}, // #10 void(string errortext) error (QUAKE) + {"objerror", PF_objerror, 11}, // #11 void(string errortext) onjerror (QUAKE) + {"vlen", PF_vlen, 12}, // #12 float(vector v) vlen (QUAKE) + {"vectoyaw", PF_vectoyaw, 13}, // #13 float(vector v) vectoyaw (QUAKE) + {"spawn", PF_Spawn, 14}, // #14 entity() spawn (QUAKE) + {"remove", PF_cs_remove, 15}, // #15 void(entity e) remove (QUAKE) + {"traceline", PF_cs_traceline, 16}, // #16 void(vector v1, vector v2, float nomonst, entity forent) traceline (QUAKE) + {"checkclient", PF_NoCSQC, 17}, // #17 entity() checkclient (QUAKE) (don't support) + {"findstring", PF_FindString, 18}, // #18 entity(entity start, .string fld, string match) findstring (QUAKE) + {"precache_sound", PF_cs_PrecacheSound, 19}, // #19 void(string str) precache_sound (QUAKE) //20 -PF_cs_PrecacheModel, // #20 void(string str) precache_model (QUAKE) -PF_NoCSQC, // #21 void(entity client, string s) stuffcmd (QUAKE) (don't support) -PF_cs_findradius, // #22 entity(vector org, float rad) findradius (QUAKE) -PF_NoCSQC, // #23 void(string s, ...) bprint (QUAKE) (don't support) -PF_NoCSQC, // #24 void(entity e, string s, ...) sprint (QUAKE) (don't support) -PF_dprint, // #25 void(string s, ...) dprint (QUAKE) -PF_ftos, // #26 string(float f) ftos (QUAKE) -PF_vtos, // #27 string(vector f) vtos (QUAKE) -PF_coredump, // #28 void(void) coredump (QUAKE) -PF_traceon, // #29 void() traceon (QUAKE) + {"precache_model", PF_cs_PrecacheModel, 20}, // #20 void(string str) precache_model (QUAKE) + {"stuffcmd", PF_NoCSQC, 21}, // #21 void(entity client, string s) stuffcmd (QUAKE) (don't support) + {"findradius", PF_cs_findradius, 22}, // #22 entity(vector org, float rad) findradius (QUAKE) + {"bprint", PF_NoCSQC, 23}, // #23 void(string s, ...) bprint (QUAKE) (don't support) + {"sprint", PF_NoCSQC, 24}, // #24 void(entity e, string s, ...) sprint (QUAKE) (don't support) + {"dprint", PF_dprint, 25}, // #25 void(string s, ...) dprint (QUAKE) + {"ftos", PF_ftos, 26}, // #26 string(float f) ftos (QUAKE) + {"vtos", PF_vtos, 27}, // #27 string(vector f) vtos (QUAKE) + {"coredump", PF_coredump, 28}, // #28 void(void) coredump (QUAKE) + {"traceon", PF_traceon, 29}, // #29 void() traceon (QUAKE) //30 -PF_traceoff, // #30 void() traceoff (QUAKE) -PF_eprint, // #31 void(entity e) eprint (QUAKE) -PF_cs_walkmove, // #32 float(float yaw, float dist) walkmove (QUAKE) -PF_Fixme, // #33 -PF_cs_droptofloor, // #34 -PF_cs_lightstyle, // #35 void(float lightstyle, string stylestring) lightstyle (QUAKE) -PF_rint, // #36 float(float f) rint (QUAKE) -PF_floor, // #37 float(float f) floor (QUAKE) -PF_ceil, // #38 float(float f) ceil (QUAKE) -PF_Fixme, // #39 + {"traceoff", PF_traceoff, 30}, // #30 void() traceoff (QUAKE) + {"eprint", PF_eprint, 31}, // #31 void(entity e) eprint (QUAKE) + {"walkmove", PF_cs_walkmove, 32}, // #32 float(float yaw, float dist) walkmove (QUAKE) + {"?", PF_Fixme, 33}, // #33 + {"droptofloor", PF_cs_droptofloor, 34}, // #34 + {"lightstyle", PF_cs_lightstyle, 35}, // #35 void(float lightstyle, string stylestring) lightstyle (QUAKE) + {"rint", PF_rint, 36}, // #36 float(float f) rint (QUAKE) + {"floor", PF_floor, 37}, // #37 float(float f) floor (QUAKE) + {"ceil", PF_ceil, 38}, // #38 float(float f) ceil (QUAKE) +// {"?", PF_Fixme, 39}, // #39 //40 -PF_cs_checkbottom, // #40 float(entity e) checkbottom (QUAKE) -PF_cs_pointcontents, // #41 float(vector org) pointcontents (QUAKE) -PF_Fixme, // #42 -PF_fabs, // #43 float(float f) fabs (QUAKE) -PF_NoCSQC, // #44 vector(entity e, float speed) aim (QUAKE) (don't support) -PF_cvar, // #45 float(string cvarname) cvar (QUAKE) -PF_localcmd, // #46 void(string str) localcmd (QUAKE) -PF_nextent, // #47 entity(entity e) nextent (QUAKE) -PF_cs_particle, // #48 void(vector org, vector dir, float colour, float count) particle (QUAKE) -PF_cs_changeyaw, // #49 void() changeyaw (QUAKE) + {"checkbottom", PF_cs_checkbottom, 40}, // #40 float(entity e) checkbottom (QUAKE) + {"pointcontents", PF_cs_pointcontents, 41}, // #41 float(vector org) pointcontents (QUAKE) +// {"?", PF_Fixme, 42}, // #42 + {"fabs", PF_fabs, 43}, // #43 float(float f) fabs (QUAKE) + {"aim", PF_NoCSQC, 44}, // #44 vector(entity e, float speed) aim (QUAKE) (don't support) + {"cvar", PF_cvar, 45}, // #45 float(string cvarname) cvar (QUAKE) + {"localcmd", PF_localcmd, 46}, // #46 void(string str) localcmd (QUAKE) + {"nextent", PF_nextent, 47}, // #47 entity(entity e) nextent (QUAKE) + {"particle", PF_cs_particle, 48}, // #48 void(vector org, vector dir, float colour, float count) particle (QUAKE) + {"changeyaw", PF_cs_changeyaw, 49}, // #49 void() changeyaw (QUAKE) //50 -PF_Fixme, // #50 -PF_vectoangles, // #51 vector(vector v) vectoangles (QUAKE) -PF_Fixme, // #52 void(float to, float f) WriteByte (QUAKE) -PF_Fixme, // #53 void(float to, float f) WriteChar (QUAKE) -PF_Fixme, // #54 void(float to, float f) WriteShort (QUAKE) +// {"?", PF_Fixme, 50}, // #50 + {"vectoangles", PF_vectoangles, 51}, // #51 vector(vector v) vectoangles (QUAKE) +// {"WriteByte", PF_Fixme, 52}, // #52 void(float to, float f) WriteByte (QUAKE) +// {"WriteChar", PF_Fixme, 53}, // #53 void(float to, float f) WriteChar (QUAKE) +// {"WriteShort", PF_Fixme, 54}, // #54 void(float to, float f) WriteShort (QUAKE) -PF_Fixme, // #55 void(float to, float f) WriteLong (QUAKE) -PF_Fixme, // #56 void(float to, float f) WriteCoord (QUAKE) -PF_Fixme, // #57 void(float to, float f) WriteAngle (QUAKE) -PF_Fixme, // #58 void(float to, float f) WriteString (QUAKE) -PF_Fixme, // #59 void(float to, float f) WriteEntity (QUAKE) +// {"WriteLong", PF_Fixme, 55}, // #55 void(float to, float f) WriteLong (QUAKE) +// {"WriteCoord", PF_Fixme, 56}, // #56 void(float to, float f) WriteCoord (QUAKE) +// {"WriteAngle", PF_Fixme, 57}, // #57 void(float to, float f) WriteAngle (QUAKE) +// {"WriteString", PF_Fixme, 58}, // #58 void(float to, float f) WriteString (QUAKE) +// {"WriteEntity", PF_Fixme, 59}, // #59 void(float to, float f) WriteEntity (QUAKE) //60 -PF_Sin, // #60 float(float angle) sin (DP_QC_SINCOSSQRTPOW) -PF_Cos, // #61 float(float angle) cos (DP_QC_SINCOSSQRTPOW) -PF_Sqrt, // #62 float(float value) sqrt (DP_QC_SINCOSSQRTPOW) -PF_cs_changepitch, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) -PF_cs_tracetoss, // #64 void(entity ent, entity ignore) tracetoss (DP_QC_TRACETOSS) + {"sin", PF_Sin, 60}, // #60 float(float angle) sin (DP_QC_SINCOSSQRTPOW) + {"cos", PF_Cos, 61}, // #61 float(float angle) cos (DP_QC_SINCOSSQRTPOW) + {"sqrt", PF_Sqrt, 62}, // #62 float(float value) sqrt (DP_QC_SINCOSSQRTPOW) + {"changepitch", PF_cs_changepitch, 63}, // #63 void(entity ent) changepitch (DP_QC_CHANGEPITCH) + {"tracetoss", PF_cs_tracetoss, 64}, // #64 void(entity ent, entity ignore) tracetoss (DP_QC_TRACETOSS) -PF_etos, // #65 string(entity ent) etos (DP_QC_ETOS) -PF_Fixme, // #66 -PF_Fixme, // #67 void(float step) movetogoal (QUAKE) -PF_NoCSQC, // #68 void(string s) precache_file (QUAKE) (don't support) -PF_cs_makestatic, // #69 void(entity e) makestatic (QUAKE) + {"etos", PF_etos, 65}, // #65 string(entity ent) etos (DP_QC_ETOS) + {"?", PF_Fixme, 66}, // #66 +// {"movetogoal", PF_Fixme, 67}, // #67 void(float step) movetogoal (QUAKE) + {"precache_file", PF_NoCSQC, 68}, // #68 void(string s) precache_file (QUAKE) (don't support) + {"makestatic", PF_cs_makestatic, 69}, // #69 void(entity e) makestatic (QUAKE) //70 -PF_NoCSQC, // #70 void(string mapname) changelevel (QUAKE) (don't support) -PF_Fixme, // #71 -PF_cvar_set, // #72 void(string cvarname, string valuetoset) cvar_set (QUAKE) -PF_NoCSQC, // #73 void(entity ent, string text) centerprint (QUAKE) (don't support - cprint is supported instead) -PF_cl_ambientsound, // #74 void (vector pos, string samp, float vol, float atten) ambientsound (QUAKE) + {"changelevel", PF_NoCSQC, 70}, // #70 void(string mapname) changelevel (QUAKE) (don't support) +// {"?", PF_Fixme, 71}, // #71 + {"cvar_set", PF_cvar_set, 72}, // #72 void(string cvarname, string valuetoset) cvar_set (QUAKE) + {"centerprint", PF_NoCSQC, 73}, // #73 void(entity ent, string text) centerprint (QUAKE) (don't support - cprint is supported instead) + {"ambientsound", PF_cl_ambientsound, 74}, // #74 void (vector pos, string samp, float vol, float atten) ambientsound (QUAKE) -PF_cs_PrecacheModel, // #75 void(string str) precache_model2 (QUAKE) -PF_cs_PrecacheSound, // #76 void(string str) precache_sound2 (QUAKE) -PF_NoCSQC, // #77 void(string str) precache_file2 (QUAKE) -PF_NoCSQC, // #78 void() setspawnparms (QUAKE) (don't support) -PF_NoCSQC, // #79 void(entity killer, entity killee) logfrag (QW_ENGINE) (don't support) + {"precache_model2", PF_cs_PrecacheModel, 80}, // #75 void(string str) precache_model2 (QUAKE) + {"precache_sound2", PF_cs_PrecacheSound, 76}, // #76 void(string str) precache_sound2 (QUAKE) + {"precache_file2", PF_NoCSQC, 77}, // #77 void(string str) precache_file2 (QUAKE) + {"setspawnparms", PF_NoCSQC, 78}, // #78 void() setspawnparms (QUAKE) (don't support) + {"logfrag", PF_NoCSQC, 79}, // #79 void(entity killer, entity killee) logfrag (QW_ENGINE) (don't support) //80 -PF_NoCSQC, // #80 string(entity e, string keyname) infokey (QW_ENGINE) (don't support) -PF_stof, // #81 float(string s) stof (FRIK_FILE or QW_ENGINE) -PF_NoCSQC, // #82 void(vector where, float set) multicast (QW_ENGINE) (don't support) -PF_Fixme, -PF_Fixme, + {"infokey", PF_NoCSQC, 80}, // #80 string(entity e, string keyname) infokey (QW_ENGINE) (don't support) + {"stof", PF_stof, 81}, // #81 float(string s) stof (FRIK_FILE or QW_ENGINE) + {"multicast", PF_NoCSQC, 82}, // #82 void(vector where, float set) multicast (QW_ENGINE) (don't support) -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, //90 -PF_cs_tracebox, -PF_randomvector, // #91 vector() randomvec (DP_QC_RANDOMVEC) -PF_cl_getlight, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) -PF_registercvar, // #93 void(string cvarname, string defaultvalue) registercvar (DP_QC_REGISTERCVAR) -PF_min, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) + {"tracebox", PF_cs_tracebox, 90}, + {"randomvec", PF_randomvector, 91}, // #91 vector() randomvec (DP_QC_RANDOMVEC) + {"getlight", PF_cl_getlight, 92}, // #92 vector(vector org) getlight (DP_QC_GETLIGHT) + {"registercvar", PF_registercvar, 93}, // #93 void(string cvarname, string defaultvalue) registercvar (DP_QC_REGISTERCVAR) + {"min", PF_min, 94}, // #94 float(float a, floats) min (DP_QC_MINMAXBOUND) -PF_max, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) -PF_bound, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) -PF_pow, // #97 float(float value) pow (DP_QC_SINCOSSQRTPOW) -PF_FindFloat, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) -PF_checkextension, // #99 float(string extname) checkextension (EXT_CSQC) - -//100 -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, - -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, + {"max", PF_max, 95}, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) + {"bound", PF_bound, 96}, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) + {"pow", PF_pow, 97}, // #97 float(float value) pow (DP_QC_SINCOSSQRTPOW) + {"findfloat", PF_FindFloat, 98}, // #98 entity(entity start, .float fld, float match) findfloat (DP_QC_FINDFLOAT) + {"checkextension", PF_checkextension, 99}, // #99 float(string extname) checkextension (EXT_CSQC) //110 -PF_fopen, // #110 float(string strname, float accessmode) fopen (FRIK_FILE) -PF_fclose, // #111 void(float fnum) fclose (FRIK_FILE) -PF_fgets, // #112 string(float fnum) fgets (FRIK_FILE) -PF_fputs, // #113 void(float fnum, string str) fputs (FRIK_FILE) -PF_strlen, // #114 float(string str) strlen (FRIK_FILE) + {"fopen", PF_fopen, 110}, // #110 float(string strname, float accessmode) fopen (FRIK_FILE) + {"fclose", PF_fclose, 111}, // #111 void(float fnum) fclose (FRIK_FILE) + {"fgets", PF_fgets, 112}, // #112 string(float fnum) fgets (FRIK_FILE) + {"fputs", PF_fputs, 113}, // #113 void(float fnum, string str) fputs (FRIK_FILE) + {"strlen", PF_strlen, 114}, // #114 float(string str) strlen (FRIK_FILE) -PF_strcat, // #115 string(string str1, string str2, ...) strcat (FRIK_FILE) -PF_substring, // #116 string(string str, float start, float length) substring (FRIK_FILE) -PF_stov, // #117 vector(string str) stov (FRIK_FILE) -PF_dupstring, // #118 string(string str) dupstring (FRIK_FILE) -PF_forgetstring, // #119 void(string str) freestring (FRIK_FILE) - -//120 -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, - -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, -PF_Fixme, - -//130 -PF_FixTen, - -//140 -PF_FixTen, - -//150 -PF_FixTen, - -//160 -PF_FixTen, - -//170 -PF_FixTen, - -//180 -PF_FixTen, - -//190 -PF_FixTen, + {"strcat", PF_strcat, 115}, // #115 string(string str1, string str2, ...) strcat (FRIK_FILE) + {"substring", PF_substring, 116}, // #116 string(string str, float start, float length) substring (FRIK_FILE) + {"stov", PF_stov, 117}, // #117 vector(string str) stov (FRIK_FILE) + {"strzone", PF_dupstring, 118}, // #118 string(string str) dupstring (FRIK_FILE) + {"strunzone", PF_forgetstring, 119}, // #119 void(string str) freestring (FRIK_FILE) //200 -PF_cs_PrecacheModel, -PF_externcall, -PF_cs_addprogs, -PF_externvalue, -PF_externset, + {"precachemodel", PF_cs_PrecacheModel, 200}, + {"eterncall", PF_externcall, 201}, + {"addprogs", PF_cs_addprogs, 202}, + {"externvalue", PF_externvalue, 203}, + {"externset", PF_externset, 204}, -PF_externrefcall, -PF_instr, - PF_cs_OpenPortal, //q2bsps - PF_NoCSQC,//{"RegisterTempEnt", PF_RegisterTEnt, 0, 0, 0, 208}, - PF_NoCSQC,//{"CustomTempEnt", PF_CustomTEnt, 0, 0, 0, 209}, + {"externrefcall", PF_externrefcall, 205}, + {"instr", PF_instr, 206}, + {"openportal", PF_cs_OpenPortal, 207}, //q2bsps + {"registertempent", PF_NoCSQC, 208},//{"RegisterTempEnt", PF_RegisterTEnt, 0, 0, 0, 208}, + {"customtempent", PF_NoCSQC, 209},//{"CustomTempEnt", PF_CustomTEnt, 0, 0, 0, 209}, //210 - PF_Fixme,//{"fork", PF_Fork, 0, 0, 0, 210}, - PF_Abort, //#211 void() abort (FTE_MULTITHREADED) - PF_Fixme,//{"sleep", PF_Sleep, 0, 0, 0, 212}, - PF_NoCSQC,//{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213}, - PF_NoCSQC,//{"chat", PF_chat, 0, 0, 0, 214},// #214 void(string filename, float starttag, entity edict) SV_Chat (FTE_NPCCHAT) +// {"fork", PF_Fixme, 210},//{"fork", PF_Fork, 0, 0, 0, 210}, + {"abort", PF_Abort, 211}, //#211 void() abort (FTE_MULTITHREADED) +// {"sleep", PF_Fixme, 212},//{"sleep", PF_Sleep, 0, 0, 0, 212}, + {"forceinfokey", PF_NoCSQC, 213},//{"forceinfokey", PF_ForceInfoKey, 0, 0, 0, 213}, + {"chat", PF_NoCSQC, 214},//{"chat", PF_chat, 0, 0, 0, 214},// #214 void(string filename, float starttag, entity edict) SV_Chat (FTE_NPCCHAT) - PF_cs_particle2, //215 (FTE_PEXT_HEXEN2) - PF_cs_particle3, //216 (FTE_PEXT_HEXEN2) - PF_cs_particle4, //217 (FTE_PEXT_HEXEN2) + {"particle2", PF_cs_particle2, 215}, //215 (FTE_PEXT_HEXEN2) + {"particle3", PF_cs_particle3, 216}, //216 (FTE_PEXT_HEXEN2) + {"particle4", PF_cs_particle4, 217}, //217 (FTE_PEXT_HEXEN2) //EXT_DIMENSION_PLANES - PF_bitshift, //#218 bitshift (EXT_DIMENSION_PLANES) - PF_cl_te_lightningblood,// #219 te_lightningblood void(vector org) (FTE_TE_STANDARDEFFECTBUILTINS) + {"bitshift", PF_bitshift, 218}, //#218 bitshift (EXT_DIMENSION_PLANES) + {"te_lightningblood", PF_cl_te_lightningblood, 219},// #219 te_lightningblood void(vector org) (FTE_TE_STANDARDEFFECTBUILTINS) //220 - PF_Fixme, //{"map_builtin", PF_builtinsupported,0, 0, 0, 220}, //like #100 - takes 2 args. arg0 is builtinname, 1 is number to map to. -PF_strstrofs, // #221 float(string s1, string sub) strstrofs (FTE_STRINGS) -PF_str2chr, // #222 float(string str, float index) str2chr (FTE_STRINGS) -PF_chr2str, // #223 string(float chr, ...) chr2str (FTE_STRINGS) -PF_strconv, // #224 string(float ccase, float redalpha, float redchars, string str, ...) strconv (FTE_STRINGS) +// {"map_builtin", PF_Fixme, 220}, //like #100 - takes 2 args. arg0 is builtinname, 1 is number to map to. + {"strstrofs", PF_strstrofs, 221}, // #221 float(string s1, string sub) strstrofs (FTE_STRINGS) + {"str2chr", PF_str2chr, 222}, // #222 float(string str, float index) str2chr (FTE_STRINGS) + {"chr2str", PF_chr2str, 223}, // #223 string(float chr, ...) chr2str (FTE_STRINGS) + {"strconv", PF_strconv, 224}, // #224 string(float ccase, float redalpha, float redchars, string str, ...) strconv (FTE_STRINGS) -PF_strpad, // #225 string strpad(float pad, string str1, ...) strpad (FTE_STRINGS) -PF_infoadd, // #226 string(string old, string key, string value) infoadd -PF_infoget, // #227 string(string info, string key) infoget -PF_strncmp, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) -PF_strcasecmp, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS) + {"strpad", PF_strpad, 225}, // #225 string strpad(float pad, string str1, ...) strpad (FTE_STRINGS) + {"infoadd", PF_infoadd, 226}, // #226 string(string old, string key, string value) infoadd + {"infoget", PF_infoget, 227}, // #227 string(string info, string key) infoget + {"strncmp", PF_strncmp, 228}, // #228 float(string s1, string s2, float len) strncmp (FTE_STRINGS) + {"strcasecmp", PF_strcasecmp, 229}, // #229 float(string s1, string s2) strcasecmp (FTE_STRINGS) //230 -PF_strncasecmp, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS) -PF_Fixme, // #231 clientstat -PF_Fixme, // #232 runclientphys -PF_Fixme, // #233 float(entity ent) isbackbuffered -PF_rotatevectorsbytag, // #234 + {"strncasecmp", PF_strncasecmp, 230}, // #230 float(string s1, string s2, float len) strncasecmp (FTE_STRINGS) + {"clientstat", PF_NoCSQC, 231}, // #231 clientstat + {"runclientphys", PF_NoCSQC, 232}, // #232 runclientphys + {"isbackbuffered", PF_NoCSQC, 233}, // #233 float(entity ent) isbackbuffered + {"rotatevectorsbytag", PF_rotatevectorsbytag, 234}, // #234 -PF_rotatevectorsbyangles, // #235 -PF_rotatevectorsbymatrix, // #236 -PF_skinforname, // #237 -PF_shaderforname, // #238 -PF_cl_te_bloodqw, // #239 void te_bloodqw(vector org[, float count]) (FTE_TE_STANDARDEFFECTBUILTINS) + {"rotatevectorsbyangle", PF_rotatevectorsbyangles, 235}, // #235 + {"rotatevectorsbymatrix", PF_rotatevectorsbymatrix, 236}, // #236 + {"skinforname", PF_skinforname, 237}, // #237 + {"shaderforname", PF_shaderforname, 238}, // #238 + {"te_bloodqw", PF_cl_te_bloodqw, 239}, // #239 void te_bloodqw(vector org[, float count]) (FTE_TE_STANDARDEFFECTBUILTINS) -//240 -PF_FixTen, - -//250 -PF_FixTen, - -//260 -PF_FixTen, - -//270 -PF_FixTen, - -//280 -PF_FixTen, - -//290 -PF_FixTen, + {"stoi", PF_stoi, 259}, + {"itos", PF_itos, 260}, + {"stoh", PF_stoh, 261}, + {"htos", PF_htos, 262}, //300 -PF_R_ClearScene, // #300 void() clearscene (EXT_CSQC) -PF_R_AddEntityMask, // #301 void(float mask) addentities (EXT_CSQC) -PF_R_AddEntity, // #302 void(entity ent) addentity (EXT_CSQC) -PF_R_SetViewFlag, // #303 float(float property, ...) setproperty (EXT_CSQC) -PF_R_RenderScene, // #304 void() renderscene (EXT_CSQC) + {"clearscene", PF_R_ClearScene, 300}, // #300 void() clearscene (EXT_CSQC) + {"addentities", PF_R_AddEntityMask, 301}, // #301 void(float mask) addentities (EXT_CSQC) + {"addentity", PF_R_AddEntity, 302}, // #302 void(entity ent) addentity (EXT_CSQC) + {"setproperty", PF_R_SetViewFlag, 303}, // #303 float(float property, ...) setproperty (EXT_CSQC) + {"renderscene", PF_R_RenderScene, 304}, // #304 void() renderscene (EXT_CSQC) -PF_R_AddDynamicLight, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) + {"adddynamiclight", PF_R_AddDynamicLight, 305}, // #305 void(vector org, float radius, vector lightcolours) adddynamiclight (EXT_CSQC) -PF_R_PolygonBegin, // #306 void(string texturename) R_BeginPolygon (EXT_CSQC_???) -PF_R_PolygonVertex, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex (EXT_CSQC_???) -PF_R_PolygonEnd, // #308 void() R_EndPolygon (EXT_CSQC_???) + {"R_BeginPolygon", PF_R_PolygonBegin, 306}, // #306 void(string texturename) R_BeginPolygon (EXT_CSQC_???) + {"R_PolygonVertex", PF_R_PolygonVertex, 307}, // #307 void(vector org, vector texcoords, vector rgb, float alpha) R_PolygonVertex (EXT_CSQC_???) + {"R_EndPolygon", PF_R_PolygonEnd, 308}, // #308 void() R_EndPolygon (EXT_CSQC_???) -PF_R_GetViewFlag, // #309 vector/float(float property) getproperty (EXT_CSQC_1) + {"getproperty", PF_R_GetViewFlag, 309}, // #309 vector/float(float property) getproperty (EXT_CSQC_1) //310 //maths stuff that uses the current view settings. -PF_cs_unproject, // #310 vector (vector v) unproject (EXT_CSQC) -PF_cs_project, // #311 vector (vector v) project (EXT_CSQC) + {"unproject", PF_cs_unproject, 310}, // #310 vector (vector v) unproject (EXT_CSQC) + {"project", PF_cs_project, 311}, // #311 vector (vector v) project (EXT_CSQC) -PF_Fixme, // #312 -PF_Fixme, // #313 -PF_Fixme, // #314 +// {"?", PF_Fixme, 312}, // #312 +// {"?", PF_Fixme, 313}, // #313 +// {"?", PF_Fixme, 314}, // #314 //2d (immediate) operations -PF_CL_drawline, // #315 void(float width, vector pos1, vector pos2) drawline (EXT_CSQC) -PF_CL_is_cached_pic, // #316 float(string name) iscachedpic (EXT_CSQC) -PF_CL_precache_pic, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) -PF_CL_drawgetimagesize, // #318 vector(string picname) draw_getimagesize (EXT_CSQC) -PF_CL_free_pic, // #319 void(string name) freepic (EXT_CSQC) + {"drawline", PF_CL_drawline, 315}, // #315 void(float width, vector pos1, vector pos2) drawline (EXT_CSQC) + {"iscachedpic", PF_CL_is_cached_pic, 316}, // #316 float(string name) iscachedpic (EXT_CSQC) + {"precache_pic", PF_CL_precache_pic, 317}, // #317 string(string name, float trywad) precache_pic (EXT_CSQC) + {"draw_getimagesize", PF_CL_drawgetimagesize, 318}, // #318 vector(string picname) draw_getimagesize (EXT_CSQC) + {"freepic", PF_CL_free_pic, 319}, // #319 void(string name) freepic (EXT_CSQC) //320 -PF_CL_drawcharacter, // #320 float(vector position, float character, vector scale, vector rgb, float alpha [, float flag]) drawcharacter (EXT_CSQC, [EXT_CSQC_???]) -PF_CL_drawstring, // #321 float(vector position, string text, vector scale, vector rgb, float alpha [, float flag]) drawstring (EXT_CSQC, [EXT_CSQC_???]) -PF_CL_drawpic, // #322 float(vector position, string pic, vector size, vector rgb, float alpha [, float flag]) drawpic (EXT_CSQC, [EXT_CSQC_???]) -PF_CL_drawfill, // #323 float(vector position, vector size, vector rgb, float alpha [, float flag]) drawfill (EXT_CSQC, [EXT_CSQC_???]) -PF_CL_drawsetcliparea, // #324 void(float x, float y, float width, float height) drawsetcliparea (EXT_CSQC_???) -PF_CL_drawresetcliparea, // #325 void(void) drawresetcliparea (EXT_CSQC_???) + {"drawcharacter", PF_CL_drawcharacter, 320}, // #320 float(vector position, float character, vector scale, vector rgb, float alpha [, float flag]) drawcharacter (EXT_CSQC, [EXT_CSQC_???]) + {"drawstring", PF_CL_drawstring, 321}, // #321 float(vector position, string text, vector scale, vector rgb, float alpha [, float flag]) drawstring (EXT_CSQC, [EXT_CSQC_???]) + {"drawpic", PF_CL_drawpic, 322}, // #322 float(vector position, string pic, vector size, vector rgb, float alpha [, float flag]) drawpic (EXT_CSQC, [EXT_CSQC_???]) + {"drawfill", PF_CL_drawfill, 323}, // #323 float(vector position, vector size, vector rgb, float alpha [, float flag]) drawfill (EXT_CSQC, [EXT_CSQC_???]) + {"drawsetcliparea", PF_CL_drawsetcliparea, 324}, // #324 void(float x, float y, float width, float height) drawsetcliparea (EXT_CSQC_???) + {"drawresetcliparea", PF_CL_drawresetcliparea, 325}, // #325 void(void) drawresetcliparea (EXT_CSQC_???) -PF_Fixme, // #326 -PF_Fixme, // #327 -PF_Fixme, // #328 -PF_Fixme, // #329 + {"drawcolorcodedstring", PF_CL_drawstring, 326}, // #326 + {"stringwidth", PF_CL_stringwidth, 327}, // #327 EXT_CSQC_'DARKPLACES' + {"drawsubpic", PF_CL_drawsubpic, 328}, // #328 EXT_CSQC_'DARKPLACES' +// {"?", PF_Fixme, 329}, // #329 EXT_CSQC_'DARKPLACES' //330 -PF_cs_getstatf, // #330 float(float stnum) getstatf (EXT_CSQC) -PF_cs_getstati, // #331 float(float stnum) getstati (EXT_CSQC) -PF_cs_getstats, // #332 string(float firststnum) getstats (EXT_CSQC) -PF_cs_SetModelIndex, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) -PF_cs_ModelnameForIndex, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC) + {"getstatf", PF_cs_getstatf, 330}, // #330 float(float stnum) getstatf (EXT_CSQC) + {"getstati", PF_cs_getstati, 331}, // #331 float(float stnum) getstati (EXT_CSQC) + {"getstats", PF_cs_getstats, 332}, // #332 string(float firststnum) getstats (EXT_CSQC) + {"setmodelindex", PF_cs_SetModelIndex, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) + {"modelnameforindex", PF_cs_ModelnameForIndex, 334}, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC) -PF_cs_particlesloaded, // #335 float(string effectname) particleeffectnum (EXT_CSQC) -PF_cs_trailparticles, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC), -PF_cs_pointparticles, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) + {"particleeffectnum", PF_cs_particlesloaded, 335}, // #335 float(string effectname) particleeffectnum (EXT_CSQC) + {"trailparticles", PF_cs_trailparticles, 336}, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC), + {"pointparticles", PF_cs_pointparticles, 337}, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) -PF_cl_cprint, // #338 void(string s) cprint (EXT_CSQC) -PF_print, // #339 void(string s) print (EXT_CSQC) + {"cprint", PF_cl_cprint, 338}, // #338 void(string s) cprint (EXT_CSQC) + {"print", PF_print, 339}, // #339 void(string s) print (EXT_CSQC) //340 -PF_cl_keynumtostring, // #340 string(float keynum) keynumtostring (EXT_CSQC) -PF_cl_stringtokeynum, // #341 float(string keyname) stringtokeynum (EXT_CSQC) -PF_cl_getkeybind, // #342 string(float keynum) getkeybind (EXT_CSQC) + {"keynumtostring", PF_cl_keynumtostring, 340}, // #340 string(float keynum) keynumtostring (EXT_CSQC) + {"stringtokeynum", PF_cl_stringtokeynum, 341}, // #341 float(string keyname) stringtokeynum (EXT_CSQC) + {"getkeybind", PF_cl_getkeybind, 342}, // #342 string(float keynum) getkeybind (EXT_CSQC) -PF_Fixme, // #343 -PF_Fixme, // #344 +// {"?", PF_Fixme, 343}, // #343 +// {"?", PF_Fixme, 344}, // #344 -PF_cs_getinputstate, // #345 float(float framenum) getinputstate (EXT_CSQC) -PF_cs_setsensativityscaler, // #346 void(float sens) setsensitivityscaler (EXT_CSQC) + {"getinputstate", PF_cs_getinputstate, 345}, // #345 float(float framenum) getinputstate (EXT_CSQC) + {"setsensitivityscaler", PF_cs_setsensativityscaler, 346}, // #346 void(float sens) setsensitivityscaler (EXT_CSQC) -PF_cs_runplayerphysics, // #347 void() runstandardplayerphysics (EXT_CSQC) + {"runstandardplayerphysics", PF_cs_runplayerphysics, 347}, // #347 void() runstandardplayerphysics (EXT_CSQC) -PF_cs_getplayerkey, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC) + {"getplayerkeyvalue", PF_cs_getplayerkey, 348}, // #348 string(float playernum, string keyname) getplayerkeyvalue (EXT_CSQC) -PF_cl_playingdemo, // #349 float() isdemo (EXT_CSQC) + {"isdemo", PF_cl_playingdemo, 349}, // #349 float() isdemo (EXT_CSQC) //350 -PF_cl_runningserver, // #350 float() isserver (EXT_CSQC) + {"isserver", PF_cl_runningserver, 350}, // #350 float() isserver (EXT_CSQC) -PF_cs_setlistener, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) -PF_cs_registercommand, // #352 void(string cmdname) registercommand (EXT_CSQC) -PF_WasFreed, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too) + {"SetListener", PF_cs_setlistener, 351}, // #351 void(vector origin, vector forward, vector right, vector up) SetListener (EXT_CSQC) + {"registercommand", PF_cs_registercommand, 352}, // #352 void(string cmdname) registercommand (EXT_CSQC) + {"wasfreed", PF_WasFreed, 353}, // #353 float(entity ent) wasfreed (EXT_CSQC) (should be availabe on server too) -PF_cs_serverkey, // #354 string(string key) serverkey; -PF_cs_getentitytoken, // #355 string() getentitytoken; -PF_Fixme, // #356 -PF_Fixme, // #357 -PF_Fixme, // #358 -PF_Fixme, // #359 + {"serverkey", PF_cs_serverkey, 354}, // #354 string(string key) serverkey; + {"getentitytoken", PF_cs_getentitytoken, 355}, // #355 string() getentitytoken; +// {"?", PF_Fixme, 356}, // #356 +// {"?", PF_Fixme, 357}, // #357 +// {"?", PF_Fixme, 358}, // #358 +// {"?", PF_Fixme, 359}, // #359 //360 //note that 'ReadEntity' is pretty hard to implement reliably. Modders should use a combination of ReadShort, and findfloat, and remember that it might not be known clientside (pvs culled or other reason) -PF_ReadByte, // #360 float() readbyte (EXT_CSQC) -PF_ReadChar, // #361 float() readchar (EXT_CSQC) -PF_ReadShort, // #362 float() readshort (EXT_CSQC) -PF_ReadLong, // #363 float() readlong (EXT_CSQC) -PF_ReadCoord, // #364 float() readcoord (EXT_CSQC) + {"readbyte", PF_ReadByte, 360}, // #360 float() readbyte (EXT_CSQC) + {"readchar", PF_ReadChar, 361}, // #361 float() readchar (EXT_CSQC) + {"readshort", PF_ReadShort, 362}, // #362 float() readshort (EXT_CSQC) + {"readlong", PF_ReadLong, 363}, // #363 float() readlong (EXT_CSQC) + {"readcoord", PF_ReadCoord, 364}, // #364 float() readcoord (EXT_CSQC) -PF_ReadAngle, // #365 float() readangle (EXT_CSQC) -PF_ReadString, // #366 string() readstring (EXT_CSQC) -PF_ReadFloat, // #367 string() readfloat (EXT_CSQC) + {"readangle", PF_ReadAngle, 365}, // #365 float() readangle (EXT_CSQC) + {"readstring", PF_ReadString, 366}, // #366 string() readstring (EXT_CSQC) + {"readfloat", PF_ReadFloat, 367}, // #367 string() readfloat (EXT_CSQC) -PF_ReadEntityNum, // #368 float() readentitynum (EXT_CSQC) -PF_ReadServerEntityState, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1) - -//370 -PF_FixTen, - -//380 -PF_FixTen, - -//390 -PF_FixTen, + {"readentitynum", PF_ReadEntityNum, 368}, // #368 float() readentitynum (EXT_CSQC) + {"readserverentitystate", PF_ReadServerEntityState, 369}, // #369 void(float flags, float simtime) readserverentitystate (EXT_CSQC_1) //400 -PF_cs_copyentity, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) -PF_NoCSQC, // #401 void(entity cl, float colours) setcolors (DP_SV_SETCOLOR) (don't implement) -PF_findchain, // #402 entity(string field, string match) findchain (DP_QC_FINDCHAIN) -PF_findchainfloat, // #403 entity(float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) -PF_cl_effect, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) + {"copyentity", PF_cs_copyentity, 400}, // #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) + {"setcolors", PF_NoCSQC, 401}, // #401 void(entity cl, float colours) setcolors (DP_SV_SETCOLOR) (don't implement) + {"findchain", PF_findchain, 402}, // #402 entity(string field, string match) findchain (DP_QC_FINDCHAIN) + {"findchainfloat", PF_findchainfloat, 403}, // #403 entity(float fld, float match) findchainfloat (DP_QC_FINDCHAINFLOAT) + {"effect", PF_cl_effect, 404}, // #404 void(vector org, string modelname, float startframe, float endframe, float framerate) effect (DP_SV_EFFECT) -PF_cl_te_blooddp, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) -PF_cl_te_bloodshower, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) -PF_cl_te_explosionrgb, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) -PF_cl_te_particlecube, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) -PF_cl_te_particlerain, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) + {"te_blood", PF_cl_te_blooddp, 405}, // #405 void(vector org, vector velocity, float howmany) te_blood (DP_TE_BLOOD) + {"te_bloodshower", PF_cl_te_bloodshower,406}, // #406 void(vector mincorner, vector maxcorner, float explosionspeed, float howmany) te_bloodshower (DP_TE_BLOODSHOWER) + {"te_explosionrgb", PF_cl_te_explosionrgb, 407}, // #407 void(vector org, vector color) te_explosionrgb (DP_TE_EXPLOSIONRGB) + {"te_particlecube", PF_cl_te_particlecube,408}, // #408 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color, float gravityflag, float randomveljitter) te_particlecube (DP_TE_PARTICLECUBE) + {"te_particlerain", PF_cl_te_particlerain, 409}, // #409 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlerain (DP_TE_PARTICLERAIN) -PF_cl_te_particlesnow, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) -PF_cl_te_spark, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) -PF_cl_te_gunshotquad, // #412 void(vector org) te_gunshotquad (DP_TE_QUADEFFECTS1) -PF_cl_te_spikequad, // #413 void(vector org) te_spikequad (DP_TE_QUADEFFECTS1) -PF_cl_te_superspikequad,// #414 void(vector org) te_superspikequad (DP_TE_QUADEFFECTS1) + {"te_particlesnow", PF_cl_te_particlesnow,410}, // #410 void(vector mincorner, vector maxcorner, vector vel, float howmany, float color) te_particlesnow (DP_TE_PARTICLESNOW) + {"te_spark", PF_cl_te_spark, 411}, // #411 void(vector org, vector vel, float howmany) te_spark (DP_TE_SPARK) + {"te_gunshotquad", PF_cl_te_gunshotquad, 412}, // #412 void(vector org) te_gunshotquad (DP_TE_QUADEFFECTS1) + {"te_spikequad", PF_cl_te_spikequad, 413}, // #413 void(vector org) te_spikequad (DP_TE_QUADEFFECTS1) + {"te_superspikequad", PF_cl_te_superspikequad,414}, // #414 void(vector org) te_superspikequad (DP_TE_QUADEFFECTS1) -PF_cl_te_explosionquad, // #415 void(vector org) te_explosionquad (DP_TE_QUADEFFECTS1) -PF_cl_te_smallflash, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) -PF_cl_te_customflash, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) -PF_cl_te_gunshot, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_spike, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) + {"te_explosionquad", PF_cl_te_explosionquad, 415}, // #415 void(vector org) te_explosionquad (DP_TE_QUADEFFECTS1) + {"te_smallflash", PF_cl_te_smallflash, 416}, // #416 void(vector org) te_smallflash (DP_TE_SMALLFLASH) + {"te_customflash", PF_cl_te_customflash, 417}, // #417 void(vector org, float radius, float lifetime, vector color) te_customflash (DP_TE_CUSTOMFLASH) + {"te_gunshot", PF_cl_te_gunshot, 418}, // #418 void(vector org) te_gunshot (DP_TE_STANDARDEFFECTBUILTINS) + {"te_spike", PF_cl_te_spike, 419}, // #419 void(vector org) te_spike (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_superspike, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_explosion, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_tarexplosion, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_wizspike, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_knightspike, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) + {"te_superspike", PF_cl_te_superspike,420}, // #420 void(vector org) te_superspike (DP_TE_STANDARDEFFECTBUILTINS) + {"te_explosion", PF_cl_te_explosion, 421}, // #421 void(vector org) te_explosion (DP_TE_STANDARDEFFECTBUILTINS) + {"te_tarexplosion", PF_cl_te_tarexplosion,422}, // #422 void(vector org) te_tarexplosion (DP_TE_STANDARDEFFECTBUILTINS) + {"te_wizspike", PF_cl_te_wizspike, 423}, // #423 void(vector org) te_wizspike (DP_TE_STANDARDEFFECTBUILTINS) + {"te_knightspike", PF_cl_te_knightspike,424}, // #424 void(vector org) te_knightspike (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_lavasplash, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_teleport, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_explosion2, // #427 void(vector org, float color, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_lightning1, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_lightning2, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) + {"te_lavasplash", PF_cl_te_lavasplash,425}, // #425 void(vector org) te_lavasplash (DP_TE_STANDARDEFFECTBUILTINS) + {"te_teleport", PF_cl_te_teleport, 426}, // #426 void(vector org) te_teleport (DP_TE_STANDARDEFFECTBUILTINS) + {"te_explosion2", PF_cl_te_explosion2,427}, // #427 void(vector org, float color, float colorlength) te_explosion2 (DP_TE_STANDARDEFFECTBUILTINS) + {"te_lightning1", PF_cl_te_lightning1, 428}, // #428 void(entity own, vector start, vector end) te_lightning1 (DP_TE_STANDARDEFFECTBUILTINS) + {"te_lightning2", PF_cl_te_lightning2,429}, // #429 void(entity own, vector start, vector end) te_lightning2 (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_lightning3, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) -PF_cl_te_beam, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) -PF_cs_vectorvectors, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) -PF_cl_te_plasmaburn, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) -PF_Fixme, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) + {"te_lightning3", PF_cl_te_lightning3,430}, // #430 void(entity own, vector start, vector end) te_lightning3 (DP_TE_STANDARDEFFECTBUILTINS) + {"te_beam", PF_cl_te_beam, 431}, // #431 void(entity own, vector start, vector end) te_beam (DP_TE_STANDARDEFFECTBUILTINS) + {"vectorvectors", PF_cs_vectorvectors,432}, // #432 void(vector dir) vectorvectors (DP_QC_VECTORVECTORS) + {"te_plasmaburn", PF_cl_te_plasmaburn,433}, // #433 void(vector org) te_plasmaburn (DP_TE_PLASMABURN) +// {"getsurfacenumpoints", PF_Fixme, 434}, // #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) -PF_Fixme, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) -PF_Fixme, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) -PF_Fixme, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) -PF_Fixme, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) -PF_Fixme, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) +// {"getsurfacepoint", PF_Fixme, 435}, // #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) +// {"getsurfacenormal", PF_Fixme, 436}, // #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) +// {"getsurfacetexture", PF_Fixme, 437}, // #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) +// {"getsurfacenearpoint", PF_Fixme, 438}, // #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) +// {"getsurfaceclippedpoint", PF_Fixme, 439}, // #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) -PF_NoCSQC, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) (don't implement) -PF_Tokenize, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) -PF_ArgV, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) -PS_cs_setattachment, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) -PF_search_begin, // #444 float search_begin(string pattern, float caseinsensitive, float quiet) (DP_QC_FS_SEARCH) + {"clientcommand", PF_NoCSQC, 440}, // #440 void(entity e, string s) clientcommand (KRIMZON_SV_PARSECLIENTCOMMAND) (don't implement) + {"tokenize", PF_Tokenize, 441}, // #441 float(string s) tokenize (KRIMZON_SV_PARSECLIENTCOMMAND) + {"argv", PF_ArgV, 442}, // #442 string(float n) argv (KRIMZON_SV_PARSECLIENTCOMMAND) + {"setattachment", PS_cs_setattachment,443}, // #443 void(entity e, entity tagentity, string tagname) setattachment (DP_GFX_QUAKE3MODELTAGS) + {"search_begin", PF_search_begin, 444}, // #444 float search_begin(string pattern, float caseinsensitive, float quiet) (DP_QC_FS_SEARCH) -PF_search_end, // #445 void search_end(float handle) (DP_QC_FS_SEARCH) -PF_search_getsize, // #446 float search_getsize(float handle) (DP_QC_FS_SEARCH) -PF_search_getfilename, // #447 string search_getfilename(float handle, float num) (DP_QC_FS_SEARCH) -PF_cvar_string, // #448 string(float n) cvar_string (DP_QC_CVAR_STRING) -PF_FindFlags, // #449 entity(entity start, .entity fld, float match) findflags (DP_QC_FINDFLAGS) + {"search_end", PF_search_end, 445}, // #445 void search_end(float handle) (DP_QC_FS_SEARCH) + {"search_getsize", PF_search_getsize, 446}, // #446 float search_getsize(float handle) (DP_QC_FS_SEARCH) + {"search_getfilename", PF_search_getfilename,447}, // #447 string search_getfilename(float handle, float num) (DP_QC_FS_SEARCH) + {"dp_cvar_string", PF_cvar_string, 448}, // #448 string(float n) cvar_string (DP_QC_CVAR_STRING) + {"findflags", PF_FindFlags, 449}, // #449 entity(entity start, .entity fld, float match) findflags (DP_QC_FINDFLAGS) -PF_findchainflags, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) -PF_cs_gettagindex, // #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) -PF_cs_gettaginfo, // #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) -PF_NoCSQC, // #453 void(entity player) dropclient (DP_SV_BOTCLIENT) (don't implement) -PF_NoCSQC, // #454 entity() spawnclient (DP_SV_BOTCLIENT) (don't implement) + {"findchainflags", PF_findchainflags, 450}, // #450 entity(.float fld, float match) findchainflags (DP_QC_FINDCHAINFLAGS) + {"gettagindex", PF_cs_gettagindex, 451}, // #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) + {"gettaginfo", PF_cs_gettaginfo, 452}, // #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) + {"dropclient", PF_NoCSQC, 453}, // #453 void(entity player) dropclient (DP_SV_BOTCLIENT) (don't implement) + {"spawnclient", PF_NoCSQC, 454}, // #454 entity() spawnclient (DP_SV_BOTCLIENT) (don't implement) -PF_NoCSQC, // #455 float(entity client) clienttype (DP_SV_BOTCLIENT) (don't implement) -PF_Fixme, // #456 -PF_Fixme, // #457 -PF_Fixme, // #458 -PF_Fixme, // #459 + {"clienttype", PF_NoCSQC, 455}, // #455 float(entity client) clienttype (DP_SV_BOTCLIENT) (don't implement) -//460 -PF_FixTen, + +// {"WriteUnterminatedString",PF_WriteString2, 456}, //writestring but without the null terminator. makes things a little nicer. -//470 -PF_FixTen, -//480 -PF_FixTen, -//490 -PF_FixTen, -//500 -PF_FixTen, +//DP_TE_FLAMEJET +// {"te_flamejet", PF_te_flamejet, 457}, // #457 void(vector org, vector vel, float howmany) te_flamejet + + //no 458 documented. + +//DP_QC_EDICT_NUM + {"edict_num", PF_edict_for_num, 459}, // #459 entity(float entnum) edict_num + +//DP_QC_STRINGBUFFERS + {"buf_create", PF_buf_create, 460}, // #460 float() buf_create + {"buf_del", PF_buf_del, 461}, // #461 void(float bufhandle) buf_del + {"buf_getsize", PF_buf_getsize, 462}, // #462 float(float bufhandle) buf_getsize + {"buf_copy", PF_buf_copy, 463}, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy + {"buf_sort", PF_buf_sort, 464}, // #464 void(float bufhandle, float sortpower, float backward) buf_sort + {"buf_implode", PF_buf_implode, 465}, // #465 string(float bufhandle, string glue) buf_implode + {"bufstr_get", PF_bufstr_get, 466}, // #466 string(float bufhandle, float string_index) bufstr_get + {"bufstr_set", PF_bufstr_set, 467}, // #467 void(float bufhandle, float string_index, string str) bufstr_set + {"bufstr_add", PF_bufstr_add, 468}, // #468 float(float bufhandle, string str, float order) bufstr_add + {"bufstr_free", PF_bufstr_free, 469}, // #469 void(float bufhandle, float string_index) bufstr_free + + //no 470 documented + +//DP_QC_ASINACOSATANATAN2TAN + {"asin", PF_asin, 471}, // #471 float(float s) asin + {"acos", PF_acos, 472}, // #472 float(float c) acos + {"atan", PF_atan, 473}, // #473 float(float t) atan + {"atan2", PF_atan2, 474}, // #474 float(float c, float s) atan2 + {"tan", PF_tan, 475}, // #475 float(float a) tan + + +////DP_QC_STRINGCOLORFUNCTIONS + {"strlennocol", PF_strlennocol, 476}, // #476 float(string s) strlennocol + {"strdecolorize", PF_strdecolorize, 477}, // #477 string(string s) strdecolorize + +//DP_QC_STRFTIME + {"strftime", PF_strftime, 478}, // #478 string(float uselocaltime, string format, ...) strftime + +//DP_QC_TOKENIZEBYSEPARATOR + {"tokenizebyseparator",PF_tokenizebyseparator, 479}, // #479 float(string s, string separator1, ...) tokenizebyseparator + +//DP_QC_STRING_CASE_FUNCTIONS + {"strtolower", PF_strtolower, 480}, // #476 string(string s) strtolower + {"strtoupper", PF_strtoupper, 481}, // #476 string(string s) strlennocol + +//DP_QC_CVAR_DEFSTRING + {"cvar_defstring", PF_cvar_defstring, 482}, // #482 string(string s) cvar_defstring + +//DP_SV_POINTSOUND + {"pointsound", PF_cs_pointsound, 483}, // #483 void(vector origin, string sample, float volume, float attenuation) pointsound + +//DP_QC_STRREPLACE + {"strreplace", PF_strreplace, 484}, // #484 string(string search, string replace, string subject) strreplace + {"strireplace", PF_strireplace, 485}, // #485 string(string search, string replace, string subject) strireplace + + +//DP_QC_GETSURFACEPOINTATTRIBUTE + {"getsurfacepointattribute",PF_getsurfacepointattribute, 486}, // #486vector(entity e, float s, float n, float a) getsurfacepointattribute + +//DP_GECKO_SUPPORT + {"gecko_create", PF_cs_gecko_create, 487}, // #487 float(string name) gecko_create( string name ) + {"gecko_destroy", PF_cs_gecko_destroy, 488}, // #488 void(string name) gecko_destroy( string name ) + {"gecko_navigate", PF_cs_gecko_navigate, 489}, // #489 void(string name) gecko_navigate( string name, string URI ) + {"gecko_keyevent", PF_cs_gecko_keyevent, 490}, // #490 float(string name) gecko_keyevent( string name, float key, float eventtype ) + {"gecko_mousemove", PF_cs_gecko_mousemove, 491}, // #491 void gecko_mousemove( string name, float x, float y ) + {"gecko_resize", PF_cs_gecko_resize, 492}, // #492 void gecko_resize( string name, float w, float h ) + {"gecko_get_texture_extent",PF_cs_gecko_get_texture_extent, 493}, // #493 vector gecko_get_texture_extent( string name ) + +//DP_QC_CRC16 + {"crc16", PF_crc16, 494}, // #494 float(float caseinsensitive, string s, ...) crc16 + +//DP_QC_CVAR_TYPE + {"cvar_type", PF_cvar_type, 495}, // #495 float(string name) cvar_type + +//DP_QC_ENTITYDATA + {"numentityfields", PF_numentityfields, 496}, // #496 float() numentityfields + {"entityfieldname", PF_entityfieldname, 497}, // #497 string(float fieldnum) entityfieldname + {"entityfieldtype", PF_entityfieldtype, 498}, // #498 float(float fieldnum) entityfieldtype + {"getentityfieldstring",PF_getentityfieldstring, 499}, // #499 string(float fieldnum, entity ent) getentityfieldstring + {"putentityfieldstring",PF_putentityfieldstring, 500}, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring + +//DP_SV_WRITEPICTURE + {"WritePicture", PF_ReadPicture, 501}, // #501 void(float to, string s, float sz) WritePicture + + //no 502 documented + +//DP_QC_WHICHPACK + {"whichpack", PF_whichpack, 503}, // #503 string(string filename) whichpack + +//DP_QC_URI_ESCAPE + {"uri_escape", PF_uri_escape, 510}, // #510 string(string in) uri_escape + {"uri_unescape", PF_uri_unescape, 511}, // #511 string(string in) uri_unescape = #511; + +//DP_QC_NUM_FOR_EDICT + {"num_for_edict", PF_num_for_edict, 512}, // #512 float(entity ent) num_for_edict + +//DP_QC_URI_GET + {"uri_get", PF_uri_get, 513}, // #513 float(string uril, float id) uri_get + + {"keynumtostring", PF_cl_keynumtostring, 520}, // #520 + {"findkeysforcommand", PF_cl_findkeysforcommand, 521}, // #521 + + {NULL} }; -static int csqc_numbuiltins = sizeof(csqc_builtins)/sizeof(csqc_builtins[0]); +static builtin_t pr_builtin[550]; @@ -3872,11 +4259,6 @@ static jmp_buf csqc_abort; static progparms_t csqcprogparms; - -pbool QC_WriteFile(char *name, void *data, int len); -void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves. -void VARGS PR_CB_Free(void *mem); - //Any menu builtin error or anything like that will come here. void VARGS CSQC_Abort (char *format, ...) //an error occured. { @@ -3940,37 +4322,43 @@ qbyte *CSQC_PRLoadFile (char *path, void *buffer, int bufsize) char newname[MAX_QPATH]; snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csqcchecksum); - file = COM_LoadStackFile(newname, buffer, bufsize); - if (file) + if (csqcchecksum) { - if (cls.protocol == CP_NETQUAKE) + file = COM_LoadStackFile(newname, buffer, bufsize); + if (file) { - if (QCRC_Block(file, com_filesize) == csqcchecksum) - return file; - } - else - { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csqcchecksum) //and the user wasn't trying to be cunning. - return file; + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) == csqcchecksum) + return file; + } + else + { + if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csqcchecksum) //and the user wasn't trying to be cunning. + return file; + } } } file = COM_LoadStackFile(path, buffer, bufsize); if (file && !cls.demoplayback) //allow them to use csprogs.dat if playing a demo, and don't care about the checksum { - if (cls.protocol == CP_NETQUAKE) + if (csqcchecksum) { - if (QCRC_Block(file, com_filesize) != csqcchecksum) - return NULL; - } - else - { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csqcchecksum) - return NULL; //not valid - } + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) != csqcchecksum) + return NULL; + } + else + { + if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csqcchecksum) + return NULL; //not valid + } - //back it up - COM_WriteFile(newname, file, com_filesize); + //back it up + COM_WriteFile(newname, file, com_filesize); + } } return file; @@ -3989,33 +4377,39 @@ int CSQC_PRFileSize (char *path) char newname[MAX_QPATH]; snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csqcchecksum); - file = COM_LoadTempFile (newname); - if (file) + if (csqcchecksum) { - if (cls.protocol == CP_NETQUAKE) + file = COM_LoadTempFile (newname); + if (file) { - if (QCRC_Block(file, com_filesize) == csqcchecksum) - return com_filesize+1; - } - else - { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csqcchecksum) //and the user wasn't trying to be cunning. - return com_filesize+1; + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) == csqcchecksum) + return com_filesize+1; + } + else + { + if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csqcchecksum) //and the user wasn't trying to be cunning. + return com_filesize+1; + } } } file = COM_LoadTempFile(path); if (file && !cls.demoplayback) //allow them to use csprogs.dat if playing a demo, and don't care about the checksum { - if (cls.protocol == CP_NETQUAKE) + if (csqcchecksum) { - if (QCRC_Block(file, com_filesize) != csqcchecksum) - return -1; //not valid - } - else - { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csqcchecksum) - return -1; //not valid + if (cls.protocol == CP_NETQUAKE) + { + if (QCRC_Block(file, com_filesize) != csqcchecksum) + return -1; //not valid + } + else + { + if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csqcchecksum) + return -1; //not valid + } } } if (!file) @@ -4034,7 +4428,9 @@ qboolean CSQC_Init (unsigned int checksum) csqcedict_t *worldent; csqcchecksum = checksum; - CSQC_Shutdown(); + //its already running... + if (csqcprogs) + return false; if (!qrenderer) { @@ -4044,6 +4440,14 @@ qboolean CSQC_Init (unsigned int checksum) if (cl_nocsqc.value) return false; + for (i = 0; i < sizeof(pr_builtin)/sizeof(pr_builtin[0]); i++) + pr_builtin[i] = PF_Fixme; + for (i = 0; BuiltinList[i].bifunc; i++) + { + if (BuiltinList[i].ebfsnum) + pr_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc; + } + memset(cl.model_csqcname, 0, sizeof(cl.model_csqcname)); memset(cl.model_csqcprecache, 0, sizeof(cl.model_csqcprecache)); @@ -4071,14 +4475,14 @@ qboolean CSQC_Init (unsigned int checksum) csqcprogparms.memfree = PR_CB_Free;//void (*memfree) (void * mem); - csqcprogparms.globalbuiltins = csqc_builtins;//builtin_t *globalbuiltins; //these are available to all progs - csqcprogparms.numglobalbuiltins = csqc_numbuiltins; + csqcprogparms.globalbuiltins = pr_builtin;//builtin_t *globalbuiltins; //these are available to all progs + csqcprogparms.numglobalbuiltins = sizeof(pr_builtin)/sizeof(pr_builtin[0]); csqcprogparms.autocompile = PR_NOCOMPILE;//enum {PR_NOCOMPILE, PR_COMPILENEXIST, PR_COMPILECHANGED, PR_COMPILEALWAYS} autocompile; csqcprogparms.gametime = &csqctime; - csqcprogparms.sv_edicts = (edict_t **)&csqc_edicts; + csqcprogparms.sv_edicts = (struct edict_s **)&csqc_edicts; csqcprogparms.sv_num_edicts = &num_csqc_edicts; csqcprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); @@ -4110,6 +4514,7 @@ qboolean CSQC_Init (unsigned int checksum) PF_InitTempStrings(csqcprogs); + csqc_fakereadbyte = -1; memset(csqcent, 0, sizeof(*csqcent)*maxcsqcentities); //clear the server->csqc entity translations. csqcentsize = PR_InitEnts(csqcprogs, pr_csmaxedicts.value); @@ -4133,6 +4538,7 @@ qboolean CSQC_Init (unsigned int checksum) loadedcsqcpack[i].entnum = NULL; } + memset(deltaedplayerents, 0, sizeof(deltaedplayerents)); csqcmapentitydata = NULL; csqcmapentitydataloaded = false; @@ -4182,9 +4588,124 @@ void CSQC_CoreDump(void) } +void PR_CSExtensionList_f(void) +{ + int i; + int ebi; + int bi; + lh_extension_t *extlist; + +#define SHOW_ACTIVEEXT 1 +#define SHOW_ACTIVEBI 2 +#define SHOW_NOTSUPPORTEDEXT 4 +#define SHOW_NOTACTIVEEXT 8 +#define SHOW_NOTACTIVEBI 16 + + int showflags = atoi(Cmd_Argv(1)); + if (!showflags) + showflags = SHOW_ACTIVEEXT|SHOW_NOTACTIVEEXT; + + //make sure the info is valid + if (!pr_builtin[0]) + { + for (i = 0; i < sizeof(pr_builtin)/sizeof(pr_builtin[0]); i++) + pr_builtin[i] = PF_Fixme; + for (i = 0; BuiltinList[i].bifunc; i++) + { + if (BuiltinList[i].ebfsnum) + pr_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc; + } + } + + + if (showflags & (SHOW_ACTIVEBI|SHOW_NOTACTIVEBI)) + for (i = 0; BuiltinList[i].name; i++) + { + if (!BuiltinList[i].ebfsnum) + continue; //a reserved builtin. + if (BuiltinList[i].bifunc == PF_Fixme) + Con_Printf("^1%s:%i needs to be added\n", BuiltinList[i].name, BuiltinList[i].ebfsnum); + else if (pr_builtin[BuiltinList[i].ebfsnum] == BuiltinList[i].bifunc) + { + if (showflags & SHOW_ACTIVEBI) + Con_Printf("%s is active on %i\n", BuiltinList[i].name, BuiltinList[i].ebfsnum); + } + else + { + if (showflags & SHOW_NOTACTIVEBI) + Con_Printf("^4%s is NOT active (%i)\n", BuiltinList[i].name, BuiltinList[i].ebfsnum); + } + } + + if (showflags & (SHOW_NOTSUPPORTEDEXT|SHOW_NOTACTIVEEXT|SHOW_ACTIVEEXT)) + { + extlist = QSG_Extensions; + + for (i = 0; i < QSG_Extensions_count; i++) + { + if (!extlist[i].name) + continue; + + if (i < 32) + { + if (!(cls.fteprotocolextensions & (1<lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE); \ - break; \ - case BM_SUBTRACT: \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR); \ - break; \ - case BM_BLENDCOLOUR: \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR); \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR); \ - break; \ - case BM_BLEND: \ - default: \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA); \ - break; \ - } - - -int numparticletypes; -part_type_t *part_type; -part_type_t *part_run_list; - -static part_type_t *P_GetParticleType(char *name) -{ - int i; - part_type_t *ptype; - part_type_t *oldlist = part_type; - for (i = 0; i < numparticletypes; i++) - { - ptype = &part_type[i]; - if (!strcmp(ptype->name, name)) - return ptype; - } - part_type = BZ_Realloc(part_type, sizeof(part_type_t)*(numparticletypes+1)); - ptype = &part_type[numparticletypes++]; - strcpy(ptype->name, name); - ptype->assoc=-1; - ptype->cliptype = -1; - ptype->emit = -1; - - if (oldlist) - { - part_run_list=NULL; - - for (i = 0; i < numparticletypes; i++) - if (part_type[i].nexttorun) - part_type[i].nexttorun = (part_type_t*)((char*)part_type[i].nexttorun - (char*)oldlist + (char*)part_type); - } - - ptype->loaded = 0; - ptype->ramp = NULL; - ptype->particles = NULL; - ptype->beams = NULL; - return ptype; -} - -int P_AllocateParticleType(char *name) //guarentees that the particle type exists, returning it's index. -{ - part_type_t *pt = P_GetParticleType(name); - return pt - part_type; -} - -int P_ParticleTypeForName(char *name) -{ - int to; - - to = P_GetParticleType(name) - part_type; - if (to < 0 || to >= numparticletypes) - { - return -1; - } - - return to; -} - -int P_FindParticleType(char *name) //checks if particle description 'name' exists, returns -1 if not. -{ - int i; - for (i = 0; i < numparticletypes; i++) - { - if (!strcmp(part_type[i].name, name)) - return i; - } - - return -1; -} - -int P_DescriptionIsLoaded(char *name) -{ - int i = P_FindParticleType(name); - part_type_t *ptype; - if (i < 0) - return false; - ptype = &part_type[i]; - if (!ptype->loaded) - return false; - return i+1; -} - -qboolean P_TypeIsLoaded(int effect) -{ - int i = effect; - part_type_t *ptype; - if (i < 0) - return false; - ptype = &part_type[i]; - if (!ptype->loaded) - return false; - return true; -} - -static void P_SetModified(void) //called when the particle system changes (from console). -{ - if (Cmd_FromGamecode()) - return; //server stuffed particle descriptions don't count. - - f_modified_particles = true; - - if (care_f_modified) - { - care_f_modified = false; - Cbuf_AddText("say particles description has changed\n", RESTRICT_LOCAL); - } -} -static int CheckAssosiation(char *name, int from) -{ - int to, orig; - - orig = to = P_AllocateParticleType(name); - - while(to != -1) - { - if (to == from) - { - Con_Printf("Assosiation of %s would cause infinate loop\n", name); - return -1; - } - to = part_type[to].assoc; - } - return orig; -} - -void P_LoadTexture(part_type_t *ptype, qboolean warn) -{ - switch (qrenderer) - { -#ifdef RGLQUAKE - case QR_OPENGL: - if (*ptype->texname && strcmp(ptype->texname, "default")) - { - ptype->texturenum = Mod_LoadHiResTexture(ptype->texname, "particles", true, true, true); - - if (!ptype->texturenum) - { - if (warn) - Con_DPrintf("Couldn't load texture %s for particle effect %s\n", ptype->texname, ptype->name); - - if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball")) - ptype->texturenum = balltexture; - else - ptype->texturenum = explosiontexture; - } - } - else - ptype->texturenum = explosiontexture; - break; -#endif -#ifdef D3DQUAKE - case QR_DIRECT3D: - if (*ptype->texname && strcmp(ptype->texname, "default")) - { - ptype->d3dtexture = NULL;//Mod_LoadHiResTexture(ptype->texname, "particles", true, true, true); - - if (!ptype->d3dtexture) - { - if (warn) - Con_DPrintf("Couldn't load texture %s for particle effect %s\n", ptype->texname, ptype->name); - - if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball")) - ptype->d3dtexture = d3dballtexture; - else - ptype->d3dtexture = d3dexplosiontexture; - } - } - else - ptype->d3dtexture = d3dexplosiontexture; - break; -#endif - default: - break; - } -} - -//Uses FTE's multiline console stuff. -//This is the function that loads the effect descriptions (via console). -void P_ParticleEffect_f(void) -{ - char *var, *value; - char *buf; - particle_t *parts; - beamseg_t *beamsegs; - skytris_t *st; - qboolean settype = false; - qboolean setalphadelta = false; - qboolean setbeamlen = false; - - part_type_t *ptype, *torun; - int pnum, assoc; - - if (Cmd_Argc()!=2) - { - Con_Printf("No name for particle effect\n"); - return; - } - - buf = Cbuf_GetNext(Cmd_ExecLevel); - while (*buf && *buf <= ' ') - buf++; //no whitespace please. - if (*buf != '{') - { - Cbuf_InsertText(buf, Cmd_ExecLevel, true); - Con_Printf("This is a multiline command and should be used within config files\n"); - return; - } - - ptype = P_GetParticleType(Cmd_Argv(1)); - if (!ptype) - { - Con_Printf("Bad name\n"); - return; - } - - P_SetModified(); - - pnum = ptype-part_type; - - st = ptype->skytris; - if (ptype->ramp) - BZ_Free(ptype->ramp); - - while (ptype->particles) // empty particle list - { - parts = ptype->particles->next; - ptype->particles->next = free_particles; - free_particles = ptype->particles; - ptype->particles = parts; - } - - // go with a lazy clear of list.. mark everything as DEAD and let - // the beam rendering handle removing nodes - beamsegs = ptype->beams; - while (beamsegs) - { - beamsegs->flags |= BS_DEAD; - beamsegs = beamsegs->next; - } - - beamsegs = ptype->beams; - - // if we're in the runstate loop through and remove from linked list - if (ptype->state & PS_INRUNLIST) - { - if (part_run_list == ptype) - part_run_list = part_run_list->nexttorun; - else - { - for (torun = part_run_list; torun != NULL; torun = torun->nexttorun) - { - if (torun->nexttorun == ptype) - torun->nexttorun = torun->nexttorun->nexttorun; - } - } - } - - memset(ptype, 0, sizeof(*ptype)); -// ptype->particles = parts; - ptype->beams = beamsegs; - ptype->skytris = st; - strcpy(ptype->name, Cmd_Argv(1)); - ptype->assoc=-1; - ptype->inwater = -1; - ptype->cliptype = -1; - ptype->emit = -1; - ptype->alpha = 1; - ptype->alphachange = 1; - ptype->clipbounce = 0.8; - ptype->colorindex = -1; - ptype->rotationstartmin = -M_PI; //start with a random angle - ptype->rotationstartrand = M_PI-ptype->rotationstartmin; - ptype->spawnchance = 1; - - while(1) - { - buf = Cbuf_GetNext(Cmd_ExecLevel); - if (!*buf) - { - Con_Printf("Unexpected end of buffer with effect %s\n", ptype->name); - return; - } - - while (*buf && *buf <= ' ') - buf++; //no whitespace please. - if (*buf == '}') - break; - - Cmd_TokenizeString(buf, true, true); - var = Cmd_Argv(0); - value = Cmd_Argv(1); - - // TODO: switch this mess to some sort of binary tree to increase - // parse speed - if (!strcmp(var, "texture")) - Q_strncpyz(ptype->texname, value, sizeof(ptype->texname)); - else if (!strcmp(var, "rotationstart")) - { - ptype->rotationstartmin = atof(value)*M_PI/180; - if (Cmd_Argc()>2) - ptype->rotationstartrand = atof(Cmd_Argv(2))*M_PI/180-ptype->rotationstartmin; - else - ptype->rotationstartrand = 0; - } - else if (!strcmp(var, "rotationspeed")) - { - ptype->rotationmin = atof(value)*M_PI/180; - if (Cmd_Argc()>2) - ptype->rotationrand = atof(Cmd_Argv(2))*M_PI/180-ptype->rotationmin; - else - ptype->rotationrand = 0; - } - else if (!strcmp(var, "beamtexstep")) - { - ptype->rotationstartmin = 1/atof(value); - setbeamlen = true; - } - else if (!strcmp(var, "beamtexspeed")) - { - ptype->rotationmin = atof(value); - } - else if (!strcmp(var, "scale")) - { - ptype->scale = atof(value); - if (Cmd_Argc()>2) - ptype->randscale = atof(Cmd_Argv(2)) - ptype->scale; - } - else if (!strcmp(var, "scalerand")) - ptype->randscale = atof(value); - - else if (!strcmp(var, "scalefactor")) - ptype->scalefactor = atof(value); - else if (!strcmp(var, "scaledelta")) - ptype->scaledelta = atof(value); - - - else if (!strcmp(var, "step")) - { - ptype->count = 1/atof(value); - if (Cmd_Argc()>2) - ptype->countrand = 1/atof(Cmd_Argv(2)); - } - else if (!strcmp(var, "count")) - { - ptype->count = atof(value); - if (Cmd_Argc()>2) - ptype->countrand = atof(Cmd_Argv(2)); - } - - else if (!strcmp(var, "alpha")) - ptype->alpha = atof(value); - else if (!strcmp(var, "alphachange")) - { - Con_DPrintf("alphachange is deprechiated, use alphadelta\n"); - ptype->alphachange = atof(value); - } - else if (!strcmp(var, "alphadelta")) - { - ptype->alphachange = atof(value); - setalphadelta = true; - } - else if (!strcmp(var, "die")) - ptype->die = atof(value); - else if (!strcmp(var, "diesubrand")) - ptype->randdie = atof(value); - - else if (!strcmp(var, "randomvel")) - { - ptype->randomvel = atof(value); - if (Cmd_Argc()>2) - ptype->randomvelvert = atof(Cmd_Argv(2)); - else - ptype->randomvelvert = ptype->randomvel; - } - else if (!strcmp(var, "veladd")) - ptype->veladd = atof(value); - else if (!strcmp(var, "orgadd")) - ptype->orgadd = atof(value); - else if (!strcmp(var, "friction")) - { - ptype->friction[2] = ptype->friction[1] = ptype->friction[0] = atof(value); - - if (Cmd_Argc()>3) - { - ptype->friction[2] = atof(Cmd_Argv(3)); - ptype->friction[1] = atof(Cmd_Argv(2)); - } - else if (Cmd_Argc()>2) - { - ptype->friction[2] = atof(Cmd_Argv(2)); - } - } - else if (!strcmp(var, "gravity")) - ptype->gravity = atof(value); - else if (!strcmp(var, "clipbounce")) - ptype->clipbounce = atof(value); - - else if (!strcmp(var, "assoc")) - { - assoc = CheckAssosiation(value, pnum); //careful - this can realloc all the particle types - ptype = &part_type[pnum]; - ptype->assoc = assoc; - } - else if (!strcmp(var, "inwater")) - { - // the underwater effect switch should only occur for - // 1 level so the standard assoc check works - assoc = CheckAssosiation(value, pnum); - ptype = &part_type[pnum]; - ptype->inwater = assoc; - } - else if (!strcmp(var, "colorindex")) - { - if (Cmd_Argc()>2) - ptype->colorrand = atof(Cmd_Argv(2)); - ptype->colorindex = atoi(value); - } - else if (!strcmp(var, "colorrand")) - ptype->colorrand = atoi(value); // now obsolete - else if (!strcmp(var, "citracer")) - ptype->flags |= PT_CITRACER; - - else if (!strcmp(var, "red")) - ptype->rgb[0] = atof(value)/255; - else if (!strcmp(var, "green")) - ptype->rgb[1] = atof(value)/255; - else if (!strcmp(var, "blue")) - ptype->rgb[2] = atof(value)/255; - else if (!strcmp(var, "rgb")) - { - ptype->rgb[0] = ptype->rgb[1] = ptype->rgb[2] = atof(value)/255; - if (Cmd_Argc()>3) - { - ptype->rgb[1] = atof(Cmd_Argv(2))/255; - ptype->rgb[2] = atof(Cmd_Argv(3))/255; - } - } - - else if (!strcmp(var, "reddelta")) - { - ptype->rgbchange[0] = atof(value)/255; - if (!ptype->rgbchangetime) - ptype->rgbchangetime = ptype->die; - } - else if (!strcmp(var, "greendelta")) - { - ptype->rgbchange[1] = atof(value)/255; - if (!ptype->rgbchangetime) - ptype->rgbchangetime = ptype->die; - } - else if (!strcmp(var, "bluedelta")) - { - ptype->rgbchange[2] = atof(value)/255; - if (!ptype->rgbchangetime) - ptype->rgbchangetime = ptype->die; - } - else if (!strcmp(var, "rgbdelta")) - { - ptype->rgbchange[0] = ptype->rgbchange[1] = ptype->rgbchange[2] = atof(value)/255; - if (Cmd_Argc()>3) - { - ptype->rgbchange[1] = atof(Cmd_Argv(2))/255; - ptype->rgbchange[2] = atof(Cmd_Argv(3))/255; - } - if (!ptype->rgbchangetime) - ptype->rgbchangetime = ptype->die; - } - else if (!strcmp(var, "rgbdeltatime")) - ptype->rgbchangetime = atof(value); - - else if (!strcmp(var, "redrand")) - ptype->rgbrand[0] = atof(value)/255; - else if (!strcmp(var, "greenrand")) - ptype->rgbrand[1] = atof(value)/255; - else if (!strcmp(var, "bluerand")) - ptype->rgbrand[2] = atof(value)/255; - else if (!strcmp(var, "rgbrand")) - { - ptype->rgbrand[0] = ptype->rgbrand[1] = ptype->rgbrand[2] = atof(value)/255; - if (Cmd_Argc()>3) - { - ptype->rgbrand[1] = atof(Cmd_Argv(2))/255; - ptype->rgbrand[2] = atof(Cmd_Argv(3))/255; - } - } - - else if (!strcmp(var, "rgbrandsync")) - { - ptype->rgbrandsync[0] = ptype->rgbrandsync[1] = ptype->rgbrandsync[2] = atof(value); - if (Cmd_Argc()>3) - { - ptype->rgbrandsync[1] = atof(Cmd_Argv(2)); - ptype->rgbrandsync[2] = atof(Cmd_Argv(3)); - } - } - else if (!strcmp(var, "redrandsync")) - ptype->rgbrandsync[0] = atof(value); - else if (!strcmp(var, "greenrandsync")) - ptype->rgbrandsync[1] = atof(value); - else if (!strcmp(var, "bluerandsync")) - ptype->rgbrandsync[2] = atof(value); - - else if (!strcmp(var, "stains")) - ptype->stains = atoi(value); - else if (!strcmp(var, "blend")) - { - if (!strcmp(value, "add")) - ptype->blendmode = BM_ADD; - else if (!strcmp(value, "subtract")) - ptype->blendmode = BM_SUBTRACT; - else if (!strcmp(value, "blendcolour") || !strcmp(value, "blendcolor")) - ptype->blendmode = BM_BLENDCOLOUR; - else - ptype->blendmode = BM_BLEND; - } - else if (!strcmp(var, "spawnmode")) - { - if (!strcmp(value, "circle")) - ptype->spawnmode = SM_CIRCLE; - else if (!strcmp(value, "ball")) - ptype->spawnmode = SM_BALL; - else if (!strcmp(value, "spiral")) - ptype->spawnmode = SM_SPIRAL; - else if (!strcmp(value, "tracer")) - ptype->spawnmode = SM_TRACER; - else if (!strcmp(value, "telebox")) - ptype->spawnmode = SM_TELEBOX; - else if (!strcmp(value, "lavasplash")) - ptype->spawnmode = SM_LAVASPLASH; - else if (!strcmp(value, "uniformcircle")) - ptype->spawnmode = SM_UNICIRCLE; - else if (!strcmp(value, "syncfield")) - ptype->spawnmode = SM_FIELD; - else if (!strcmp(value, "distball")) - ptype->spawnmode = SM_DISTBALL; - else - ptype->spawnmode = SM_BOX; - - if (Cmd_Argc()>2) - { - if (Cmd_Argc()>3) - ptype->spawnparam2 = atof(Cmd_Argv(3)); - ptype->spawnparam1 = atof(Cmd_Argv(2)); - } - } - else if (!strcmp(var, "type")) - { - if (!strcmp(value, "beam")) - ptype->type = PT_BEAM; - else if (!strcmp(value, "spark")) - ptype->type = PT_SPARK; - else if (!strcmp(value, "sparkfan") || !strcmp(value, "trianglefan")) - ptype->type = PT_SPARKFAN; - else if (!strcmp(value, "texturedspark")) - ptype->type = PT_TEXTUREDSPARK; - else if (!strcmp(value, "decal")) - ptype->type = PT_DECAL; - else - ptype->type = PT_NORMAL; - settype = true; - } - else if (!strcmp(var, "isbeam")) - { - Con_DPrintf("isbeam is deprechiated, use type beam\n"); - ptype->type = PT_BEAM; - } - else if (!strcmp(var, "spawntime")) - ptype->spawntime = atof(value); - else if (!strcmp(var, "spawnchance")) - ptype->spawnchance = atof(value); - else if (!strcmp(var, "cliptype")) - { - assoc = P_ParticleTypeForName(value);//careful - this can realloc all the particle types - ptype = &part_type[pnum]; - ptype->cliptype = assoc; - } - else if (!strcmp(var, "clipcount")) - ptype->clipcount = atof(value); - - else if (!strcmp(var, "emit")) - { - assoc = P_ParticleTypeForName(value);//careful - this can realloc all the particle types - ptype = &part_type[pnum]; - ptype->emit = assoc; - } - else if (!strcmp(var, "emitinterval")) - ptype->emittime = atof(value); - else if (!strcmp(var, "emitintervalrand")) - ptype->emitrand = atof(value); - else if (!strcmp(var, "emitstart")) - ptype->emitstart = atof(value); - - // old names - else if (!strcmp(var, "areaspread")) - { - Con_DPrintf("areaspread is deprechiated, use spawnorg\n"); - ptype->areaspread = atof(value); - } - else if (!strcmp(var, "areaspreadvert")) - { - Con_DPrintf("areaspreadvert is deprechiated, use spawnorg\n"); - ptype->areaspreadvert = atof(value); - } - else if (!strcmp(var, "offsetspread")) - { - Con_DPrintf("offsetspread is deprechiated, use spawnvel\n"); - ptype->offsetspread = atof(value); - } - else if (!strcmp(var, "offsetspreadvert")) - { - Con_DPrintf("offsetspreadvert is deprechiated, use spawnvel\n"); - ptype->offsetspreadvert = atof(value); - } - - // new names - else if (!strcmp(var, "spawnorg")) - { - ptype->areaspreadvert = ptype->areaspread = atof(value); - - if (Cmd_Argc()>2) - ptype->areaspreadvert = atof(Cmd_Argv(2)); - } - else if (!strcmp(var, "spawnvel")) - { - ptype->offsetspreadvert = ptype->offsetspread = atof(value); - - if (Cmd_Argc()>2) - ptype->offsetspreadvert = atof(Cmd_Argv(2)); - } - - // spawn mode param fields - else if (!strcmp(var, "spawnparam1")) - ptype->spawnparam1 = atof(value); - else if (!strcmp(var, "spawnparam2")) - ptype->spawnparam2 = atof(value); -/* else if (!strcmp(var, "spawnparam3")) - ptype->spawnparam3 = atof(value); */ - - else if (!strcmp(var, "up")) - ptype->offsetup = atof(value); - else if (!strcmp(var, "rampmode")) - { - if (!strcmp(value, "none")) - ptype->rampmode = RAMP_NONE; - else if (!strcmp(value, "absolute")) - ptype->rampmode = RAMP_ABSOLUTE; - else //if (!strcmp(value, "delta")) - ptype->rampmode = RAMP_DELTA; - } - else if (!strcmp(var, "rampindexlist")) - { // better not use this with delta ramps... - int cidx, i; - - i = 1; - while (i < Cmd_Argc()) - { - ptype->ramp = BZ_Realloc(ptype->ramp, sizeof(ramp_t)*(ptype->rampindexes+1)); - - cidx = atoi(Cmd_Argv(i)); - ptype->ramp[ptype->rampindexes].alpha = cidx > 255 ? 0.5 : 1; - - cidx = (cidx & 0xff) * 3; - ptype->ramp[ptype->rampindexes].rgb[0] = host_basepal[cidx] * (1/255.0); - ptype->ramp[ptype->rampindexes].rgb[1] = host_basepal[cidx+1] * (1/255.0); - ptype->ramp[ptype->rampindexes].rgb[2] = host_basepal[cidx+2] * (1/255.0); - - ptype->ramp[ptype->rampindexes].scale = ptype->scale; - - ptype->rampindexes++; - i++; - } - } - else if (!strcmp(var, "rampindex")) - { - int cidx; - ptype->ramp = BZ_Realloc(ptype->ramp, sizeof(ramp_t)*(ptype->rampindexes+1)); - - cidx = atoi(value); - ptype->ramp[ptype->rampindexes].alpha = cidx > 255 ? 0.5 : 1; - - if (Cmd_Argc() > 2) // they gave alpha - ptype->ramp[ptype->rampindexes].alpha *= atof(Cmd_Argv(2)); - - cidx = (cidx & 0xff) * 3; - ptype->ramp[ptype->rampindexes].rgb[0] = host_basepal[cidx] * (1/255.0); - ptype->ramp[ptype->rampindexes].rgb[1] = host_basepal[cidx+1] * (1/255.0); - ptype->ramp[ptype->rampindexes].rgb[2] = host_basepal[cidx+2] * (1/255.0); - - if (Cmd_Argc() > 3) // they gave scale - ptype->ramp[ptype->rampindexes].scale = atof(Cmd_Argv(3)); - else - ptype->ramp[ptype->rampindexes].scale = ptype->scale; - - - ptype->rampindexes++; - } - else if (!strcmp(var, "ramp")) - { - ptype->ramp = BZ_Realloc(ptype->ramp, sizeof(ramp_t)*(ptype->rampindexes+1)); - - ptype->ramp[ptype->rampindexes].rgb[0] = atof(value)/255; - if (Cmd_Argc()>3) //seperate rgb - { - ptype->ramp[ptype->rampindexes].rgb[1] = atof(Cmd_Argv(2))/255; - ptype->ramp[ptype->rampindexes].rgb[2] = atof(Cmd_Argv(3))/255; - - if (Cmd_Argc()>4) //have we alpha and scale changes? - { - ptype->ramp[ptype->rampindexes].alpha = atof(Cmd_Argv(4)); - if (Cmd_Argc()>5) //have we scale changes? - ptype->ramp[ptype->rampindexes].scale = atof(Cmd_Argv(5)); - else - ptype->ramp[ptype->rampindexes].scale = ptype->scaledelta; - } - else - { - ptype->ramp[ptype->rampindexes].alpha = ptype->alpha; - ptype->ramp[ptype->rampindexes].scale = ptype->scaledelta; - } - } - else //they only gave one value - { - ptype->ramp[ptype->rampindexes].rgb[1] = ptype->ramp[ptype->rampindexes].rgb[0]; - ptype->ramp[ptype->rampindexes].rgb[2] = ptype->ramp[ptype->rampindexes].rgb[0]; - - ptype->ramp[ptype->rampindexes].alpha = ptype->alpha; - ptype->ramp[ptype->rampindexes].scale = ptype->scaledelta; - } - - ptype->rampindexes++; - } - else if (!strcmp(var, "perframe")) - ptype->flags |= PT_INVFRAMETIME; - else if (!strcmp(var, "averageout")) - ptype->flags |= PT_AVERAGETRAIL; - else if (!strcmp(var, "nostate")) - ptype->flags |= PT_NOSTATE; - else if (!strcmp(var, "nospreadfirst")) - ptype->flags |= PT_NOSPREADFIRST; - else if (!strcmp(var, "nospreadlast")) - ptype->flags |= PT_NOSPREADLAST; - else - Con_DPrintf("%s is not a recognised particle type field (in %s)\n", var, ptype->name); - } - ptype->invscalefactor = 1-ptype->scalefactor; - ptype->loaded = 1; - if (ptype->clipcount < 1) - ptype->clipcount = 1; - - //if there is a chance that it moves - if (ptype->randomvel || ptype->gravity || ptype->veladd || ptype->offsetspread || ptype->offsetspreadvert) - ptype->flags |= PT_VELOCITY; - //if it has friction - if (ptype->friction) - ptype->flags |= PT_FRICTION; - - if (!settype) - { - if (ptype->type == PT_NORMAL && !*ptype->texname) - ptype->type = PT_SPARK; - if (ptype->type == PT_SPARK) - { - if (*ptype->texname) - ptype->type = PT_TEXTUREDSPARK; - if (ptype->scale) - ptype->type = PT_SPARKFAN; - } - } - - if (ptype->type == PT_BEAM && !setbeamlen) - ptype->rotationstartmin = 1/128.0; - - // use old behavior if not using alphadelta - if (!setalphadelta) - ptype->alphachange = (-ptype->alphachange / ptype->die) * ptype->alpha; - - if (ptype->rampmode && !ptype->ramp) - { - ptype->rampmode = RAMP_NONE; - Con_Printf("Particle type %s has a ramp mode but no ramp\n", ptype->name); - } - else if (ptype->ramp && !ptype->rampmode) - { - Con_Printf("Particle type %s has a ramp but no ramp mode\n", ptype->name); - } - - P_LoadTexture(ptype, true); -} - -//assosiate a point effect with a model. -//the effect will be spawned every frame with count*frametime -//has the capability to hide models. -void P_AssosiateEffect_f (void) -{ - char *modelname = Cmd_Argv(1); - char *effectname = Cmd_Argv(2); - int effectnum; - model_t *model; - - if (!cls.demoplayback && ( - strstr(modelname, "player") || - strstr(modelname, "eyes") || - strstr(modelname, "flag") || - strstr(modelname, "tf_stan") || - strstr(modelname, ".bsp") || - strstr(modelname, "turr"))) - { - Con_Printf("Sorry: Not allowed to attach effects to model \"%s\"\n", modelname); - return; - } - - model = Mod_FindName(modelname); - if (!model) - return; - if (!cls.demoplayback && (model->flags & EF_ROTATE)) - { - Con_Printf("Sorry: You may not assosiate effects with item model \"%s\"\n", modelname); - return; - } - effectnum = P_AllocateParticleType(effectname); - model->particleeffect = effectnum; - if (atoi(Cmd_Argv(3))) - model->engineflags |= MDLF_ENGULPHS; - - P_SetModified(); //make it appear in f_modified. -} - -//assosiate a particle trail with a model. -//the effect will be spawned between two points when an entity with the model moves. -void P_AssosiateTrail_f (void) -{ - char *modelname = Cmd_Argv(1); - char *effectname = Cmd_Argv(2); - int effectnum; - model_t *model; - - if (!cls.demoplayback && ( - strstr(modelname, "player") || - strstr(modelname, "eyes") || - strstr(modelname, "flag") || - strstr(modelname, "tf_stan"))) - { - Con_Printf("Sorry, you can't assosiate trails with model \"%s\"\n", modelname); - return; - } - - model = Mod_FindName(modelname); - if (!model) - return; - effectnum = P_AllocateParticleType(effectname); - model->particletrail = effectnum; - model->engineflags |= MDLF_NODEFAULTTRAIL; //we could have assigned the trail to a model that wasn't loaded. - - P_SetModified(); //make it appear in f_modified. -} - -// P_SelectableTrail: given default/opposite effects, model pointer, and a user selection cvar -// changes model to the appropriate trail effect and default trail index -void P_SelectableTrail(model_t *model, cvar_t *selection, int mdleffect, int mdlcidx, int oppeffect, int oppcidx) -{ - int select = (int)(selection->value); - - switch (select) - { - case 0: // check for string, otherwise no trail - if (selection->string[0] == '0') - { - model->particletrail = -1; - break; - } - else - { - int effect = P_FindParticleType(selection->string); - - if (effect >= 0) - { - model->particletrail = effect; - model->traildefaultindex = mdlcidx; - break; - } - } - // fall through to default (so semicheat will work properly) - case 1: // default model effect - default: - model->particletrail = mdleffect; - model->traildefaultindex = mdlcidx; - break; - case 2: // opposite effect - model->particletrail = oppeffect; - model->traildefaultindex= oppcidx; - break; - case 3: // alt rocket effect - model->particletrail = P_AllocateParticleType("t_altrocket"); - model->traildefaultindex = 107; - break; - case 4: // gib - model->particletrail = rt_gib; - model->traildefaultindex = 70; - break; - case 5: // zombie gib - model->particletrail = P_AllocateParticleType("t_zomgib"); - model->traildefaultindex = 70; - break; - case 6: // Scrag tracer - model->particletrail = P_AllocateParticleType("t_tracer"); - model->traildefaultindex = 60; - break; - case 7: // Knight tracer - model->particletrail = P_AllocateParticleType("t_tracer2"); - model->traildefaultindex = 238; - break; - case 8: // Vore tracer - model->particletrail = P_AllocateParticleType("t_tracer3"); - model->traildefaultindex = 154; - break; - case 9: // rail trail - model->particletrail = rt_railtrail; - model->traildefaultindex = 15; - break; - } -} - -void P_DefaultTrail (model_t *model) -{ - // TODO: EF_BRIGHTFIELD should probably be handled in here somewhere - // TODO: make trail default color into RGB values instead of indexes - if (model->engineflags & MDLF_NODEFAULTTRAIL) - return; - - if (model->flags & EF_ROCKET) - P_SelectableTrail(model, &r_rockettrail, rt_rocket, 109, rt_grenade, 6); - else if (model->flags & EF_GRENADE) - P_SelectableTrail(model, &r_grenadetrail, rt_grenade, 6, rt_rocket, 109); - else if (model->flags & EF_GIB) - { - model->particletrail = rt_gib; - model->traildefaultindex = 70; - } - else if (model->flags & EF_TRACER) - { - model->particletrail = P_AllocateParticleType("t_tracer"); - model->traildefaultindex = 60; - } - else if (model->flags & EF_ZOMGIB) - { - model->particletrail = P_AllocateParticleType("t_zomgib"); - model->traildefaultindex = 70; - } - else if (model->flags & EF_TRACER2) - { - model->particletrail = P_AllocateParticleType("t_tracer2"); - model->traildefaultindex = 238; - } - else if (model->flags & EF_TRACER3) - { - model->particletrail = P_AllocateParticleType("t_tracer3"); - model->traildefaultindex = 154; - } - else if (model->flags & EF_BLOODSHOT) //these are the hexen2 ones. - { - model->particletrail = P_AllocateParticleType("t_bloodshot"); - model->traildefaultindex = 136; - } - else if (model->flags & EF_FIREBALL) - { - model->particletrail = P_AllocateParticleType("t_fireball"); - model->traildefaultindex = 424; - } - else if (model->flags & EF_ACIDBALL) - { - model->particletrail = P_AllocateParticleType("t_acidball"); - model->traildefaultindex = 440; - } - else if (model->flags & EF_ICE) - { - model->particletrail = P_AllocateParticleType("t_ice"); - model->traildefaultindex = 408; - } - else if (model->flags & EF_SPIT) - { - model->particletrail = P_AllocateParticleType("t_spit"); - model->traildefaultindex = 260; - } - else if (model->flags & EF_SPELL) - { - model->particletrail = P_AllocateParticleType("t_spell"); - model->traildefaultindex = 260; - } - else if (model->flags & EF_VORP_MISSILE) - { - model->particletrail = P_AllocateParticleType("t_vorpmissile"); - model->traildefaultindex = 302; - } - else if (model->flags & EF_SET_STAFF) - { - model->particletrail = P_AllocateParticleType("t_setstaff"); - model->traildefaultindex = 424; - } - else if (model->flags & EF_MAGICMISSILE) - { - model->particletrail = P_AllocateParticleType("t_magicmissile"); - model->traildefaultindex = 149; - } - else if (model->flags & EF_BONESHARD) - { - model->particletrail = P_AllocateParticleType("t_boneshard"); - model->traildefaultindex = 384; - } - else if (model->flags & EF_SCARAB) - { - model->particletrail = P_AllocateParticleType("t_scarab"); - model->traildefaultindex = 254; - } - else - model->particletrail = -1; -} void R_Rockettrail_Callback(struct cvar_s *var, char *oldvalue) { @@ -1237,122 +40,78 @@ void R_Grenadetrail_Callback(struct cvar_s *var, char *oldvalue) } } -#if _DEBUG -// R_BeamInfo_f - debug junk -void P_BeamInfo_f (void) +particleengine_t pe_null; +particleengine_t pe_classic; +particleengine_t pe_darkplaces; +particleengine_t pe_script; + +particleengine_t *particlesystem[] = { - beamseg_t *bs; - int i, j, k, l, m; + &pe_script, + &pe_darkplaces, + &pe_classic, + &pe_null, + {NULL}, +}; - i = 0; +void R_ParticleSystem_Callback(struct cvar_s *var, char *oldvalue) +{ + int i; + if (pe) + pe->ShutdownParticles(); - for (bs = free_beams; bs; bs = bs->next) - i++; + pe = NULL; - Con_Printf("%i free beams\n", i); - - for (i = 0; i < numparticletypes; i++) + for (i = 0; particlesystem[i]; i++) { - m = l = k = j = 0; - for (bs = part_type[i].beams; bs; bs = bs->next) + if ( (particlesystem[i]->name1 && !stricmp(var->string, particlesystem[i]->name1)) + || (particlesystem[i]->name2 && !stricmp(var->string, particlesystem[i]->name2))) { - if (!bs->p) - k++; - - if (bs->flags & BS_DEAD) - l++; - - if (bs->flags & BS_LASTSEG) - m++; - - j++; + pe = particlesystem[i]; + break; } - - if (j) - Con_Printf("Type %i = %i NULL p, %i DEAD, %i LASTSEG, %i total\n", i, k, l, m, j); + if (!pe) + if (particlesystem[i]->name1) + pe = particlesystem[i]; } + + if (!pe) + Sys_Error("No particle system available. Please recompile."); + + pe->InitParticles(); + pe->ClearParticles(); + CL_RegisterParticles(); } -void P_PartInfo_f (void) -{ - particle_t *p; +cvar_t r_rockettrail = SCVARFC("r_rockettrail", "1", CVAR_SEMICHEAT, R_Rockettrail_Callback); +cvar_t r_grenadetrail = SCVARFC("r_grenadetrail", "1", CVAR_SEMICHEAT, R_Grenadetrail_Callback); +cvar_t r_particlesystem = SCVARFC("r_particlesystem", "script", CVAR_SEMICHEAT, R_ParticleSystem_Callback); +cvar_t r_particlesdesc = SCVARF("r_particlesdesc", "spikeset tsshaft", CVAR_SEMICHEAT); +extern cvar_t r_bouncysparks; +extern cvar_t r_part_rain; +extern cvar_t r_bloodstains; +extern cvar_t gl_part_flame; +cvar_t r_part_rain_quantity = SCVAR("r_part_rain_quantity", "1"); - int i, j; +cvar_t r_particle_tracelimit = SCVAR("r_particle_tracelimit", "250"); +cvar_t r_part_sparks = SCVAR("r_part_sparks", "1"); +cvar_t r_part_sparks_trifan = SCVAR("r_part_sparks_trifan", "1"); +cvar_t r_part_sparks_textured = SCVAR("r_part_sparks_textured", "1"); +cvar_t r_part_beams = SCVAR("r_part_beams", "1"); +cvar_t r_part_beams_textured = SCVAR("r_part_beams_textured", "1"); +cvar_t r_part_contentswitch = SCVAR("r_part_contentswitch", "1"); - i = 0; - for (p = free_particles; p; p = p->next) - i++; +particleengine_t *pe; - Con_Printf("%i free particles\n", i); - - for (i = 0; i < numparticletypes; i++) - { - j = 0; - for (p = part_type[i].particles; p; p = p->next) - j++; - - if (j) - Con_Printf("Type %s = %i total\n", part_type[i].name, j); - } -} -#endif - -/* -=============== -R_InitParticles -=============== -*/ -void P_InitParticles (void) +void P_InitParticleSystem(void) { char *particlecvargroupname = "Particle effects"; - int i; - if (r_numparticles) //already inited - return; + Cvar_Register(&r_particlesystem, "Particles"); - i = COM_CheckParm ("-particles"); - if (i) - { - r_numparticles = (int)(Q_atoi(com_argv[i+1])); - } - else - { - r_numparticles = MAX_PARTICLES; - } - r_numbeams = MAX_BEAMSEGS; - - r_numdecals = MAX_DECALS; - - r_numtrailstates = MAX_TRAILSTATES; - - particles = (particle_t *) - Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles"); - - beams = (beamseg_t *) - Hunk_AllocName (r_numbeams * sizeof(beamseg_t), "beamsegs"); - - decals = (clippeddecal_t *) - Hunk_AllocName (r_numdecals * sizeof(clippeddecal_t), "decals"); - - trailstates = (trailstate_t *) - Hunk_AllocName (r_numtrailstates * sizeof(trailstate_t), "trailstates"); - ts_cycle = 0; - - Cmd_AddCommand("pointfile", P_ReadPointFile_f); //load the leak info produced from qbsp into the particle system to show a line. :) - - Cmd_AddCommand("r_part", P_ParticleEffect_f); - Cmd_AddCommand("r_effect", P_AssosiateEffect_f); - Cmd_AddCommand("r_trail", P_AssosiateTrail_f); - - Cmd_AddCommand("r_exportbuiltinparticles", P_ExportBuiltinSet_f); - -#if _DEBUG - Cmd_AddCommand("r_partinfo", P_PartInfo_f); - Cmd_AddCommand("r_beaminfo", P_BeamInfo_f); -#endif //particles Cvar_Register(&r_particlesdesc, particlecvargroupname); @@ -1363,9 +122,6 @@ void P_InitParticles (void) Cvar_Register(&r_particle_tracelimit, particlecvargroupname); - Cvar_Register(&r_rockettrail, particlecvargroupname); - Cvar_Register(&r_grenadetrail, particlecvargroupname); - Cvar_Register(&r_part_sparks, particlecvargroupname); Cvar_Register(&r_part_sparks_trifan, particlecvargroupname); Cvar_Register(&r_part_sparks_textured, particlecvargroupname); @@ -1374,1831 +130,6 @@ void P_InitParticles (void) Cvar_Register(&r_part_contentswitch, particlecvargroupname); Cvar_Register (&gl_part_flame, particlecvargroupname); - - pt_explosion = P_AllocateParticleType("te_explosion"); - pt_pointfile = P_AllocateParticleType("pe_pointfile"); - pt_entityparticles = P_AllocateParticleType("ef_entityparticles"); - pt_blob = P_AllocateParticleType("te_tarexplosion"); - - pt_blood = P_AllocateParticleType("te_blood"); - pt_lightningblood = P_AllocateParticleType("te_lightningblood"); - pt_gunshot = P_AllocateParticleType("te_gunshot"); - pt_lavasplash = P_AllocateParticleType("te_lavasplash"); - pt_teleportsplash = P_AllocateParticleType("te_teleportsplash"); - pt_superbullet = P_AllocateParticleType("te_superbullet"); - pt_bullet = P_AllocateParticleType("te_bullet"); - pt_blasterparticles = P_AllocateParticleType("te_blasterparticles"); - pt_wizspike = P_AllocateParticleType("te_wizspike"); - pt_knightspike = P_AllocateParticleType("te_knightspike"); - pt_spike = P_AllocateParticleType("te_spike"); - pt_superspike = P_AllocateParticleType("te_superspike"); - - rt_railtrail = P_AllocateParticleType("te_railtrail"); - rt_bubbletrail = P_AllocateParticleType("te_bubbletrail"); - rt_blastertrail = P_AllocateParticleType("t_blastertrail"); - rt_rocket = P_AllocateParticleType("t_rocket"); - rt_grenade = P_AllocateParticleType("t_grenade"); - rt_gib = P_AllocateParticleType("t_gib"); - - rt_lightning1 = P_AllocateParticleType("te_lightning1"); - rt_lightning2 = P_AllocateParticleType("te_lightning2"); - rt_lightning3 = P_AllocateParticleType("te_lightning3"); - - pt_lightning1_end = P_AllocateParticleType("te_lightning1_end"); - pt_lightning2_end = P_AllocateParticleType("te_lightning2_end"); - pt_lightning3_end = P_AllocateParticleType("te_lightning3_end"); - - pt_spark = P_AllocateParticleType("te_spark"); - pt_plasma = P_AllocateParticleType("te_plasma"); - pt_smoke = P_AllocateParticleType("te_smoke"); - - pe_default = P_AllocateParticleType("pe_default"); - pe_size2 = P_AllocateParticleType("pe_size2"); - pe_size3 = P_AllocateParticleType("pe_size3"); - pe_defaulttrail = P_AllocateParticleType("pe_defaulttrail"); -} - - -/* -=============== -P_ClearParticles -=============== -*/ -void P_ClearParticles (void) -{ - int i; - - free_particles = &particles[0]; - for (i=0 ;iramp) - BZ_Free(part_type->ramp); - part_type->ramp = NULL; - } - - for (i=0 , mod=mod_known ; iparticleeffect = -1; - mod->particletrail = -1; - mod->engineflags &= ~MDLF_NODEFAULTTRAIL; - - P_DefaultTrail(mod); - } - - f_modified_particles = false; - - first = true; - for (c = COM_ParseStringSet(var->string); com_token[0]; c = COM_ParseStringSet(c)) - { - P_LoadParticleSet(com_token, first); - first = false; - } -} - -void P_ReadPointFile_f (void) -{ - vfsfile_t *f; - vec3_t org; - //int r; //unreferenced - int c; - char name[MAX_OSPATH]; - char line[1024]; - char *s; - - COM_StripExtension(cl.worldmodel->name, name, sizeof(name)); - strcat(name, ".pts"); - - f = FS_OpenVFS(name, "rb", FS_GAME); - if (!f) - { - Con_Printf ("couldn't open %s\n", name); - return; - } - - P_ClearParticles(); //so overflows arn't as bad. - - Con_Printf ("Reading %s...\n", name); - c = 0; - for ( ;; ) - { - VFS_GETS(f, line, sizeof(line)); - - s = COM_Parse(line); - org[0] = atof(com_token); - - s = COM_Parse(s); - if (!s) - continue; - org[1] = atof(com_token); - - s = COM_Parse(s); - if (!s) - continue; - org[2] = atof(com_token); - if (COM_Parse(s)) - continue; - - c++; - - if (c%8) - continue; - - if (!free_particles) - { - Con_Printf ("Not enough free particles\n"); - break; - } - P_RunParticleEffectType(org, NULL, 1, pt_pointfile); - } - - VFS_CLOSE (f); - Con_Printf ("%i points read\n", c); -} - -void P_AddRainParticles(void) -{ - float x; - float y; - static float skipped; - static float lastrendered; - int ptype; - - vec3_t org, vdist; - - skytris_t *st; - - if (!r_part_rain.value || !r_part_rain_quantity.value) - { - skipped = true; - return; - } - - if (lastrendered < particletime - 0.5) - skipped = true; //we've gone for half a sec without any new rain. This would cause some strange effects, so reset times. - - if (skipped) - { - for (ptype = 0; ptypenext) - { - st->nexttime = particletime; - } - } - } - skipped = false; - - lastrendered = particletime; -/* -{ - int i; - -glDisable(GL_TEXTURE_2D); -glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); -glDisable(GL_DEPTH_TEST); -glBegin(GL_TRIANGLES); - - st = skytris; - for (i = 0; i < r_part_rain_quantity.value; i++) - st = st->next; - glVertex3f(st->org[0], st->org[1], st->org[2]); - glVertex3f(st->org[0]+st->x[0], st->org[1]+st->x[1], st->org[2]+st->x[2]); - glVertex3f(st->org[0]+st->y[0], st->org[1]+st->y[1], st->org[2]+st->y[2]); -glEnd(); -glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); -glBegin(GL_POINTS); - for (i = 0; i < 1000; i++) - { - x = frandom()*frandom(); - y = frandom() * (1-x); - VectorMA(st->org, x, st->x, org); - VectorMA(org, y, st->y, org); - - glVertex3f(org[0], org[1], org[2]); - } -glEnd(); -glEnable(GL_DEPTH_TEST); -} -*/ - for (ptype = 0; ptypenext) - { - // if (st->face->visframe != r_framecount) - // continue; - - if (st->face->visframe != r_framecount) - { - st->nexttime = particletime; - continue; - } - - while (st->nexttime < particletime) - { - if (!free_particles) - return; - - st->nexttime += 10000/(st->area*r_part_rain_quantity.value); - - x = frandom()*frandom(); - y = frandom() * (1-x); - VectorMA(st->org, x, st->x, org); - VectorMA(org, y, st->y, org); - - - VectorSubtract(org, r_refdef.vieworg, vdist); - - if (Length(vdist) > (1024+512)*frandom()) - continue; - - if (st->face->flags & SURF_PLANEBACK) - VectorMA(org, -0.5, st->face->plane->normal, org); - else - VectorMA(org, 0.5, st->face->plane->normal, org); - - if (!(cl.worldmodel->funcs.PointContents(cl.worldmodel, org) & FTECONTENTS_SOLID)) - { - if (st->face->flags & SURF_PLANEBACK) - { - vdist[0] = -st->face->plane->normal[0]; - vdist[1] = -st->face->plane->normal[1]; - vdist[2] = -st->face->plane->normal[2]; - P_RunParticleEffectType(org, vdist, 1, ptype); - } - else - P_RunParticleEffectType(org, st->face->plane->normal, 1, ptype); - } - } - } - } -} - - -void R_Part_SkyTri(float *v1, float *v2, float *v3, msurface_t *surf) -{ - float dot; - float xm; - float ym; - float theta; - vec3_t xd; - vec3_t yd; - - skytris_t *st; - - st = Hunk_Alloc(sizeof(skytris_t)); - st->next = part_type[surf->texinfo->texture->parttype].skytris; - VectorCopy(v1, st->org); - VectorSubtract(v2, st->org, st->x); - VectorSubtract(v3, st->org, st->y); - - VectorCopy(st->x, xd); - VectorCopy(st->y, yd); -/* - xd[2] = 0; //prevent area from being valid on vertical surfaces - yd[2] = 0; -*/ - xm = Length(xd); - ym = Length(yd); - - dot = DotProduct(xd, yd); - theta = acos(dot/(xm*ym)); - st->area = sin(theta)*xm*ym; - st->nexttime = particletime; - st->face = surf; - - if (st->area<=0) - return;//bummer. - - part_type[surf->texinfo->texture->parttype].skytris = st; -} - - - -void P_EmitSkyEffectTris(model_t *mod, msurface_t *fa) -{ - vec3_t verts[64]; - int v1; - int v2; - int v3; - int numverts; - int i, lindex; - float *vec; - - // - // convert edges back to a normal polygon - // - numverts = 0; - for (i=0 ; inumedges ; i++) - { - lindex = mod->surfedges[fa->firstedge + i]; - - if (lindex > 0) - vec = mod->vertexes[mod->edges[lindex].v[0]].position; - else - vec = mod->vertexes[mod->edges[-lindex].v[1]].position; - VectorCopy (vec, verts[numverts]); - numverts++; - - if (numverts>=64) - { - Con_Printf("Too many verts on sky surface\n"); - return; - } - } - - v1 = 0; - v2 = 1; - for (v3 = 2; v3 < numverts; v3++) - { - R_Part_SkyTri(verts[v1], verts[v2], verts[v3], fa); - - v2 = v3; - } -} - -// Trailstate functions -static void P_CleanTrailstate(trailstate_t *ts) -{ - // clear LASTSEG flag from lastbeam so it can be reused - if (ts->lastbeam) - { - ts->lastbeam->flags &= ~BS_LASTSEG; - ts->lastbeam->flags |= BS_NODRAW; - } - - // clean structure - memset(ts, 0, sizeof(trailstate_t)); -} - -void P_DelinkTrailstate(trailstate_t **tsk) -{ - trailstate_t *ts; - trailstate_t *assoc; - - if (*tsk == NULL) - return; // not linked to a trailstate - - ts = *tsk; // store old pointer - *tsk = NULL; // clear pointer - - if (ts->key != tsk) - return; // prevent overwrite - - assoc = ts->assoc; // store assoc - P_CleanTrailstate(ts); // clean directly linked trailstate - - // clean trailstates assoc linked - while (assoc) - { - ts = assoc->assoc; - P_CleanTrailstate(assoc); - assoc = ts; - } -} - -static trailstate_t *P_NewTrailstate(trailstate_t **key) -{ - trailstate_t *ts; - - // bounds check here in case r_numtrailstates changed - if (ts_cycle >= r_numtrailstates) - ts_cycle = 0; - - // get trailstate - ts = trailstates + ts_cycle; - - // clear trailstate - P_CleanTrailstate(ts); - - // set key - ts->key = key; - - // advance index cycle - ts_cycle++; - - // return clean trailstate - return ts; -} - -#define NUMVERTEXNORMALS 162 -float r_avertexnormals[NUMVERTEXNORMALS][3] = { -#include "anorms.h" -}; -vec2_t avelocities[NUMVERTEXNORMALS]; -#define BEAMLENGTH 16 -// vec3_t avelocity = {23, 7, 3}; -// float partstep = 0.01; -// float timescale = 0.01; - -int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent, vec3_t tangent2, float size, float **out); -int P_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk) -{ - part_type_t *ptype = &part_type[typenum]; - int i, j, k, l, spawnspc; - float m, pcount; - particle_t *p; - beamseg_t *b, *bfirst; - vec3_t ofsvec, arsvec; // offsetspread vec, areaspread vec - trailstate_t *ts; - - if (typenum < 0 || typenum >= numparticletypes) - return 1; - - if (!ptype->loaded) - return 1; - - // inwater check, switch only once - if (r_part_contentswitch.value && ptype->inwater >= 0 && cl.worldmodel) - { - int cont; - cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, org); - - if (cont & FTECONTENTS_WATER) - ptype = &part_type[ptype->inwater]; - } - - // eliminate trailstate if flag set - if (ptype->flags & PT_NOSTATE) - tsk = NULL; - - // trailstate allocation/deallocation - if (tsk) - { - // if *tsk = NULL get a new one - if (*tsk == NULL) - { - ts = P_NewTrailstate(tsk); - *tsk = ts; - } - else - { - ts = *tsk; - - if (ts->key != tsk) // trailstate was overwritten - { - ts = P_NewTrailstate(tsk); // so get a new one - *tsk = ts; - } - } - } - else - ts = NULL; - - if (ptype->type == PT_DECAL) - { - clippeddecal_t *d; - int decalcount; - float dist; - vec3_t tangent, t2; - vec3_t vec={0.5, 0.5, 0.5}; - float *decverts; - int i; - trace_t tr; - - vec3_t bestdir; - - if (!free_decals) - return 0; - - if (!dir) - { - bestdir[0] = 0; - bestdir[1] = 0.73; - bestdir[2] = 0.73; - dist = 1; - for (i = 0; i < 6; i++) - { - if (i >= 3) - { - t2[0] = ((i&3)==0)*8; - t2[1] = ((i&3)==1)*8; - t2[2] = ((i&3)==2)*8; - } - else - { - t2[0] = -((i&3)==0)*8; - t2[1] = -((i&3)==1)*8; - t2[2] = -((i&3)==2)*8; - } - VectorSubtract(org, t2, tangent); - VectorAdd(org, t2, t2); - - if (cl.worldmodel->funcs.Trace (cl.worldmodel, 0, 0,tangent, t2, vec3_origin, vec3_origin, &tr)) - { - if (tr.fraction < dist) - { - dist = tr.fraction; - VectorCopy(tr.plane.normal, bestdir); - } - } - } - dir = bestdir; - } - VectorInverse(dir); - - VectorNormalize(vec); - CrossProduct(dir, vec, tangent); - CrossProduct(dir, tangent, t2); - - decalcount = Q1BSP_ClipDecal(org, dir, tangent, t2, ptype->scale, &decverts); - while(decalcount) - { - if (!free_decals) - break; - - d = free_decals; - free_decals = d->next; - d->next = ptype->clippeddecals; - ptype->clippeddecals = d; - - VectorCopy((decverts+0), d->vertex[0]); - VectorCopy((decverts+3), d->vertex[1]); - VectorCopy((decverts+6), d->vertex[2]); - - for (i = 0; i < 3; i++) - { - VectorSubtract(d->vertex[i], org, vec); - d->texcoords[i][0] = (DotProduct(vec, t2)/ptype->scale)+0.5; - d->texcoords[i][1] = (DotProduct(vec, tangent)/ptype->scale)+0.5; - } - - d->die = ptype->randdie*frandom(); - - if (ptype->die) - d->alpha = ptype->alpha+d->die*ptype->alphachange; - else - d->alpha = ptype->alpha; - - if (ptype->colorindex >= 0) - { - int cidx; - cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; - cidx = ptype->colorindex + cidx; - if (cidx > 255) - d->alpha = d->alpha / 2; // Hexen 2 style transparency - cidx = (cidx & 0xff) * 3; - d->rgb[0] = host_basepal[cidx] * (1/255.0); - d->rgb[1] = host_basepal[cidx+1] * (1/255.0); - d->rgb[2] = host_basepal[cidx+2] * (1/255.0); - } - else - VectorCopy(ptype->rgb, d->rgb); - - vec[2] = frandom(); - vec[0] = vec[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); - vec[1] = vec[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); - vec[2] = vec[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); - d->rgb[0] += vec[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*d->die; - d->rgb[1] += vec[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*d->die; - d->rgb[2] += vec[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*d->die; - - d->die = particletime + ptype->die - d->die; - - decverts += 3*3; - decalcount--; - } - - return 0; - } - - // get msvc to shut up - j = k = l = 0; - m = 0; - - while(ptype) - { - // init spawn specific variables - b = bfirst = NULL; - spawnspc = 8; - pcount = count*(ptype->count+ptype->countrand*frandom()); - if (ptype->flags & PT_INVFRAMETIME) - pcount /= host_frametime; - if (ts) - pcount += ts->state2.emittime; - - switch (ptype->spawnmode) - { - case SM_UNICIRCLE: - m = pcount; - if (ptype->type == PT_BEAM) - m--; - - if (m < 1) - m = 0; - else - m = (M_PI*2)/m; - - if (ptype->spawnparam1) /* use for weird shape hacks */ - m *= ptype->spawnparam1; - break; - case SM_TELEBOX: - spawnspc = 4; - l = -ptype->areaspreadvert; - case SM_LAVASPLASH: - j = k = -ptype->areaspread; - if (ptype->spawnparam1) - m = ptype->spawnparam1; - else - m = 0.55752; /* default weird number for tele/lavasplash used in vanilla Q1 */ - - if (ptype->spawnparam2) - spawnspc = (int)ptype->spawnparam2; - break; - case SM_FIELD: - if (!avelocities[0][0]) - { - for (j=0 ; jspawntime && ts) - { - if (ts->state1.statetime > particletime) - return 0; // timelimit still in effect - - ts->state1.statetime = particletime + ptype->spawntime; // record old time - } - - // random chance for point effects - if (ptype->spawnchance < frandom()) - { - i = ceil(pcount); - break; - } - - // particle spawning loop - for (i = 0; i < pcount; i++) - { - if (!free_particles) - break; - p = free_particles; - if (ptype->type == PT_BEAM) - { - if (!free_beams) - break; - if (b) - { - b = b->next = free_beams; - free_beams = free_beams->next; - } - else - { - b = bfirst = free_beams; - free_beams = free_beams->next; - } - b->texture_s = i; // TODO: FIX THIS NUMBER - b->flags = 0; - b->p = p; - VectorClear(b->dir); - } - free_particles = p->next; - p->next = ptype->particles; - ptype->particles = p; - - p->die = ptype->randdie*frandom(); - p->scale = ptype->scale+ptype->randscale*frandom(); - if (ptype->die) - p->alpha = ptype->alpha+p->die*ptype->alphachange; - else - p->alpha = ptype->alpha; - // p->color = 0; - if (ptype->emittime < 0) - p->state.trailstate = NULL; - else - p->state.nextemit = particletime + ptype->emitstart - p->die; - - p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand; - p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand; - - if (ptype->colorindex >= 0) - { - int cidx; - cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; - cidx = ptype->colorindex + cidx; - if (cidx > 255) - p->alpha = p->alpha / 2; // Hexen 2 style transparency - cidx = (cidx & 0xff) * 3; - p->rgb[0] = host_basepal[cidx] * (1/255.0); - p->rgb[1] = host_basepal[cidx+1] * (1/255.0); - p->rgb[2] = host_basepal[cidx+2] * (1/255.0); - } - else - VectorCopy(ptype->rgb, p->rgb); - - // use org temporarily for rgbsync - p->org[2] = frandom(); - p->org[0] = p->org[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); - p->org[1] = p->org[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); - p->org[2] = p->org[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); - - p->rgb[0] += p->org[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*p->die; - p->rgb[1] += p->org[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*p->die; - p->rgb[2] += p->org[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*p->die; - - // randomvel - p->vel[0] = crandom()*ptype->randomvel; - p->vel[1] = crandom()*ptype->randomvel; - p->vel[2] = crandom()*ptype->randomvelvert; - - // handle spawn modes (org/vel) - switch (ptype->spawnmode) - { - case SM_BOX: - ofsvec[0] = crandom(); - ofsvec[1] = crandom(); - ofsvec[2] = crandom(); - - arsvec[0] = ofsvec[0]*ptype->areaspread; - arsvec[1] = ofsvec[1]*ptype->areaspread; - arsvec[2] = ofsvec[2]*ptype->areaspreadvert; - break; - case SM_TELEBOX: - ofsvec[0] = k; - ofsvec[1] = j; - ofsvec[2] = l+4; - VectorNormalize(ofsvec); - VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec); - - // org is just like the original - arsvec[0] = j + (rand()%spawnspc); - arsvec[1] = k + (rand()%spawnspc); - arsvec[2] = l + (rand()%spawnspc); - - // advance telebox loop - j += spawnspc; - if (j >= ptype->areaspread) - { - j = -ptype->areaspread; - k += spawnspc; - if (k >= ptype->areaspread) - { - k = -ptype->areaspread; - l += spawnspc; - if (l >= ptype->areaspreadvert) - l = -ptype->areaspreadvert; - } - } - break; - case SM_LAVASPLASH: - // calc directions, org with temp vector - ofsvec[0] = k + (rand()%spawnspc); - ofsvec[1] = j + (rand()%spawnspc); - ofsvec[2] = 256; - - arsvec[0] = ofsvec[0]; - arsvec[1] = ofsvec[1]; - arsvec[2] = frandom()*ptype->areaspreadvert; - - VectorNormalize(ofsvec); - VectorScale(ofsvec, 1.0-(frandom())*m, ofsvec); - - // advance splash loop - j += spawnspc; - if (j >= ptype->areaspread) - { - j = -ptype->areaspread; - k += spawnspc; - if (k >= ptype->areaspread) - k = -ptype->areaspread; - } - break; - case SM_UNICIRCLE: - ofsvec[0] = cos(m*i); - ofsvec[1] = sin(m*i); - ofsvec[2] = 0; - VectorScale(ofsvec, ptype->areaspread, arsvec); - break; - case SM_FIELD: - arsvec[0] = cl.time * (avelocities[i][0] + m); - arsvec[1] = cl.time * (avelocities[i][1] + m); - arsvec[2] = cos(arsvec[1]); - - ofsvec[0] = arsvec[2]*cos(arsvec[0]); - ofsvec[1] = arsvec[2]*sin(arsvec[0]); - ofsvec[2] = -sin(arsvec[1]); - - arsvec[0] = r_avertexnormals[j][0]*ptype->areaspread + ofsvec[0]*BEAMLENGTH; - arsvec[1] = r_avertexnormals[j][1]*ptype->areaspread + ofsvec[1]*BEAMLENGTH; - arsvec[2] = r_avertexnormals[j][2]*ptype->areaspreadvert + ofsvec[2]*BEAMLENGTH; - - VectorNormalize(ofsvec); - - j++; - if (j >= NUMVERTEXNORMALS) - { - j = 0; - m += 0.1762891; // some BS number to try to "randomize" things - } - break; - case SM_DISTBALL: - { - float rdist; - - rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1)); - - // this is a strange spawntype, which is based on the fact that - // crandom()*crandom() provides something similar to an exponential - // probability curve - ofsvec[0] = hrandom(); - ofsvec[1] = hrandom(); - if (ptype->areaspreadvert) - ofsvec[2] = hrandom(); - else - ofsvec[2] = 0; - - VectorNormalize(ofsvec); - VectorScale(ofsvec, rdist, ofsvec); - - arsvec[0] = ofsvec[0]*ptype->areaspread; - arsvec[1] = ofsvec[1]*ptype->areaspread; - arsvec[2] = ofsvec[2]*ptype->areaspreadvert; - } - break; - default: // SM_BALL, SM_CIRCLE - ofsvec[0] = hrandom(); - ofsvec[1] = hrandom(); - if (ptype->areaspreadvert) - ofsvec[2] = hrandom(); - else - ofsvec[2] = 0; - - VectorNormalize(ofsvec); - if (ptype->spawnmode != SM_CIRCLE) - VectorScale(ofsvec, frandom(), ofsvec); - - arsvec[0] = ofsvec[0]*ptype->areaspread; - arsvec[1] = ofsvec[1]*ptype->areaspread; - arsvec[2] = ofsvec[2]*ptype->areaspreadvert; - break; - } - - p->org[0] = org[0] + arsvec[0]; - p->org[1] = org[1] + arsvec[1]; - p->org[2] = org[2] + arsvec[2] + ptype->offsetup; - - // apply arsvec+ofsvec - if (dir) - { - p->vel[0] += dir[0]*ptype->veladd+ofsvec[0]*ptype->offsetspread; - p->vel[1] += dir[1]*ptype->veladd+ofsvec[1]*ptype->offsetspread; - p->vel[2] += dir[2]*ptype->veladd+ofsvec[2]*ptype->offsetspreadvert; - - p->org[0] += dir[0]*ptype->orgadd; - p->org[1] += dir[1]*ptype->orgadd; - p->org[2] += dir[2]*ptype->orgadd; - } - else - { - p->vel[0] += ofsvec[0]*ptype->offsetspread; - p->vel[1] += ofsvec[1]*ptype->offsetspread; - p->vel[2] += ofsvec[2]*ptype->offsetspreadvert - ptype->veladd; - - p->org[2] -= ptype->orgadd; - } - - p->die = particletime + ptype->die - p->die; - } - - // update beam list - if (ptype->type == PT_BEAM) - { - if (b) - { - // update dir for bfirst for certain modes since it will never get updated - switch (ptype->spawnmode) - { - case SM_UNICIRCLE: - // kinda hackish here, assuming ofsvec contains the point at i-1 - arsvec[0] = cos(m*(i-2)); - arsvec[1] = sin(m*(i-2)); - arsvec[2] = 0; - VectorSubtract(ofsvec, arsvec, bfirst->dir); - VectorNormalize(bfirst->dir); - break; - default: - break; - } - - b->flags |= BS_NODRAW; - b->next = ptype->beams; - ptype->beams = bfirst; - } - } - - // save off emit times in trailstate - if (ts) - ts->state2.emittime = pcount - i; - - // maintain run list - if (!(ptype->state & PS_INRUNLIST)) - { - ptype->nexttorun = part_run_list; - part_run_list = ptype; - ptype->state |= PS_INRUNLIST; - } - - // go to next associated effect - if (ptype->assoc < 0) - break; - - // new trailstate - if (ts) - { - tsk = &(ts->assoc); - // if *tsk = NULL get a new one - if (*tsk == NULL) - { - ts = P_NewTrailstate(tsk); - *tsk = ts; - } - else - { - ts = *tsk; - - if (ts->key != tsk) // trailstate was overwritten - { - ts = P_NewTrailstate(tsk); // so get a new one - *tsk = ts; - } - } - } - - ptype = &part_type[ptype->assoc]; - } - - return 0; -} - -void P_BlobExplosion (vec3_t org) -{ - P_RunParticleEffectType(org, NULL, 1, pt_blob); -} - -int P_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name) -{ - int type = P_FindParticleType(name); - if (type < 0) - return 1; - - return P_RunParticleEffectType(org, dir, count, type); -} - -void P_EmitEffect (vec3_t pos, int type, trailstate_t **tsk) -{ -#ifdef SIDEVIEWS -// is this even needed? -// if (r_secondaryview==1) -// return; -#endif - if (cl.paused) - return; - - P_RunParticleEffectState(pos, NULL, host_frametime, type, tsk); -} - -/* -=============== -P_RunParticleEffect - -=============== -*/ -void P_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count) -{ - int ptype; - - ptype = P_FindParticleType(va("pe_%i", color)); - if (P_RunParticleEffectType(org, dir, count, ptype)) - { - color &= ~0x7; - if (count > 130 && part_type[pe_size3].loaded) - { - part_type[pe_size3].colorindex = color; - part_type[pe_size3].colorrand = 8; - P_RunParticleEffectType(org, dir, count, pe_size3); - return; - } - if (count > 20 && part_type[pe_size2].loaded) - { - part_type[pe_size2].colorindex = color; - part_type[pe_size2].colorrand = 8; - P_RunParticleEffectType(org, dir, count, pe_size2); - return; - } - part_type[pe_default].colorindex = color; - part_type[pe_default].colorrand = 8; - P_RunParticleEffectType(org, dir, count, pe_default); - return; - } -} - -//h2 stylie -void P_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count) -{ - int i, j; - float num; - float invcount; - vec3_t nvel; - - int ptype = P_FindParticleType(va("pe2_%i_%i", effect, color)); - if (ptype < 0) - { - ptype = P_FindParticleType(va("pe2_%i", effect)); - if (ptype < 0) - ptype = pe_default; - - part_type[ptype].colorindex = color; - } - - invcount = 1/part_type[ptype].count; // using this to get R_RPET to always spawn 1 - count = count * part_type[ptype].count; - - for (i=0 ; iveladd; - float randvel = ptype->randomvel; - float randvelvert = ptype->randomvelvert; - float step; - float stop; - float tdegree = 2*M_PI/256; /* MSVC whine */ - float sdegree = 0; - float nrfirst, nrlast; - - VectorCopy(startpos, start); - - // eliminate trailstate if flag set - if (ptype->flags & PT_NOSTATE) - tsk = NULL; - - // trailstate allocation/deallocation - if (tsk) - { - // if *tsk = NULL get a new one - if (*tsk == NULL) - { - ts = P_NewTrailstate(tsk); - *tsk = ts; - } - else - { - ts = *tsk; - - if (ts->key != tsk) // trailstate was overwritten - { - ts = P_NewTrailstate(tsk); // so get a new one - *tsk = ts; - } - } - } - else - ts = NULL; - - if (ptype->assoc>=0) - { - if (ts) - P_ParticleTrail(start, end, ptype->assoc, &(ts->assoc)); - else - P_ParticleTrail(start, end, ptype->assoc, NULL); - } - - // time limit for trails - if (ptype->spawntime && ts) - { - if (ts->state1.statetime > particletime) - return; // timelimit still in effect - - ts->state1.statetime = particletime + ptype->spawntime; // record old time - ts = NULL; // clear trailstate so we don't save length/lastseg - } - - // random chance for trails - if (ptype->spawnchance < frandom()) - return; // don't spawn but return success - - if (!ptype->die) - ts = NULL; - - // use ptype step to calc step vector and step size - step = 1/ptype->count; - - if (step < 0.01) - step = 0.01; - - VectorSubtract (end, start, vec); - len = VectorNormalize (vec); - - if (ptype->flags & PT_AVERAGETRAIL) - { - float tavg; - // mangle len/step to get last point to be at end - tavg = len / step; - tavg = tavg / ceil(tavg); - step *= tavg; - len += step; - } - - VectorScale(vec, step, vstep); - - // add offset - start[2] += ptype->offsetup; - - // spawn mode precalculations - if (ptype->spawnmode == SM_SPIRAL) - { - VectorVectors(vec, right, up); - - // precalculate degree of rotation - if (ptype->spawnparam1) - tdegree = 2*M_PI/ptype->spawnparam1; /* distance per rotation inversed */ - sdegree = ptype->spawnparam2*(M_PI/180); - } - else if (ptype->spawnmode == SM_CIRCLE) - { - VectorVectors(vec, right, up); - } - - // store last stop here for lack of a better solution besides vectors - if (ts) - { - ts->state2.laststop = stop = ts->state2.laststop + len; //when to stop - len = ts->state1.lastdist; - } - else - { - stop = len; - len = 0; - } - -// len = ts->lastdist/step; -// len = (len - (int)len)*step; -// VectorMA (start, -len, vec, start); - - if (ptype->flags & PT_NOSPREADFIRST) - nrfirst = len + step*1.5; - else - nrfirst = len; - - if (ptype->flags & PT_NOSPREADLAST) - nrlast = stop; - else - nrlast = stop + step; - - b = bfirst = NULL; - - while (len < stop) - { - len += step; - - if (!free_particles) - { - len = stop; - break; - } - - p = free_particles; - if (ptype->type == PT_BEAM) - { - if (!free_beams) - { - len = stop; - break; - } - if (b) - { - b = b->next = free_beams; - free_beams = free_beams->next; - } - else - { - b = bfirst = free_beams; - free_beams = free_beams->next; - } - b->texture_s = len; // not sure how to calc this - b->flags = 0; - b->p = p; - VectorCopy(vec, b->dir); - } - - free_particles = p->next; - p->next = ptype->particles; - ptype->particles = p; - - p->die = ptype->randdie*frandom(); - p->scale = ptype->scale+ptype->randscale*frandom(); - if (ptype->die) - p->alpha = ptype->alpha+p->die*ptype->alphachange; - else - p->alpha = ptype->alpha; -// p->color = 0; - -// if (ptype->spawnmode == SM_TRACER) - if (ptype->spawnparam1) - tcount = (int)(len * ptype->count / ptype->spawnparam1); - else - tcount = (int)(len * ptype->count); - - if (ptype->colorindex >= 0) - { - int cidx; - cidx = ptype->colorrand > 0 ? rand() % ptype->colorrand : 0; - if (ptype->flags & PT_CITRACER) // colorindex behavior as per tracers in std Q1 - cidx += ((tcount & 4) << 1); - - cidx = ptype->colorindex + cidx; - if (cidx > 255) - p->alpha = p->alpha / 2; - cidx = (cidx & 0xff) * 3; - p->rgb[0] = host_basepal[cidx] * (1/255.0); - p->rgb[1] = host_basepal[cidx+1] * (1/255.0); - p->rgb[2] = host_basepal[cidx+2] * (1/255.0); - } - else - VectorCopy(ptype->rgb, p->rgb); - - // use org temporarily for rgbsync - p->org[2] = frandom(); - p->org[0] = p->org[2]*ptype->rgbrandsync[0] + frandom()*(1-ptype->rgbrandsync[0]); - p->org[1] = p->org[2]*ptype->rgbrandsync[1] + frandom()*(1-ptype->rgbrandsync[1]); - p->org[2] = p->org[2]*ptype->rgbrandsync[2] + frandom()*(1-ptype->rgbrandsync[2]); - if (ptype->orgadd) - { - p->org[0] += vec[0]*ptype->orgadd; - p->org[1] += vec[1]*ptype->orgadd; - p->org[2] += vec[2]*ptype->orgadd; - } - - p->rgb[0] += p->org[0]*ptype->rgbrand[0] + ptype->rgbchange[0]*p->die; - p->rgb[1] += p->org[1]*ptype->rgbrand[1] + ptype->rgbchange[1]*p->die; - p->rgb[2] += p->org[2]*ptype->rgbrand[2] + ptype->rgbchange[2]*p->die; - - VectorClear (p->vel); - if (ptype->emittime < 0) - p->state.trailstate = NULL; // init trailstate - else - p->state.nextemit = particletime + ptype->emitstart - p->die; - - p->rotationspeed = ptype->rotationmin + frandom()*ptype->rotationrand; - p->angle = ptype->rotationstartmin + frandom()*ptype->rotationstartrand; - - if (len < nrfirst || len >= nrlast) - { - // no offset or areaspread for these particles... - p->vel[0] = vec[0]*veladd+crandom()*randvel; - p->vel[1] = vec[1]*veladd+crandom()*randvel; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert; - - VectorCopy(start, p->org); - } - else - { - switch(ptype->spawnmode) - { - case SM_TRACER: - if (tcount & 1) - { - p->vel[0] = vec[1]*ptype->offsetspread; - p->vel[1] = -vec[0]*ptype->offsetspread; - p->org[0] = vec[1]*ptype->areaspread; - p->org[1] = -vec[0]*ptype->areaspread; - } - else - { - p->vel[0] = -vec[1]*ptype->offsetspread; - p->vel[1] = vec[0]*ptype->offsetspread; - p->org[0] = -vec[1]*ptype->areaspread; - p->org[1] = vec[0]*ptype->areaspread; - } - - p->vel[0] += vec[0]*veladd+crandom()*randvel; - p->vel[1] += vec[1]*veladd+crandom()*randvel; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert; - - p->org[0] += start[0]; - p->org[1] += start[1]; - p->org[2] = start[2]; - break; - case SM_SPIRAL: - { - float tsin, tcos; - float tright, tup; - - tcos = cos(len*tdegree+sdegree); - tsin = sin(len*tdegree+sdegree); - - tright = tcos*ptype->areaspread; - tup = tsin*ptype->areaspread; - - p->org[0] = start[0] + right[0]*tright + up[0]*tup; - p->org[1] = start[1] + right[1]*tright + up[1]*tup; - p->org[2] = start[2] + right[2]*tright + up[2]*tup; - - tright = tcos*ptype->offsetspread; - tup = tsin*ptype->offsetspread; - - p->vel[0] = vec[0]*veladd+crandom()*randvel + right[0]*tright + up[0]*tup; - p->vel[1] = vec[1]*veladd+crandom()*randvel + right[1]*tright + up[1]*tup; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert + right[2]*tright + up[2]*tup; - } - break; - // TODO: directionalize SM_BALL/SM_CIRCLE/SM_DISTBALL - case SM_BALL: - p->org[0] = crandom(); - p->org[1] = crandom(); - p->org[2] = crandom(); - VectorNormalize(p->org); - VectorScale(p->org, frandom(), p->org); - - p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread; - p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert + p->org[2]*ptype->offsetspreadvert; - - p->org[0] = p->org[0]*ptype->areaspread + start[0]; - p->org[1] = p->org[1]*ptype->areaspread + start[1]; - p->org[2] = p->org[2]*ptype->areaspreadvert + start[2]; - break; - - case SM_CIRCLE: - { - float tsin, tcos; - - tcos = cos(len*tdegree)*ptype->areaspread; - tsin = sin(len*tdegree)*ptype->areaspread; - - p->org[0] = start[0] + right[0]*tcos + up[0]*tsin + vstep[0] * (len*tdegree); - p->org[1] = start[1] + right[1]*tcos + up[1]*tsin + vstep[1] * (len*tdegree); - p->org[2] = start[2] + right[2]*tcos + up[2]*tsin + vstep[2] * (len*tdegree)*50; - - tcos = cos(len*tdegree)*ptype->offsetspread; - tsin = sin(len*tdegree)*ptype->offsetspread; - - p->vel[0] = vec[0]*veladd+crandom()*randvel + right[0]*tcos + up[0]*tsin; - p->vel[1] = vec[1]*veladd+crandom()*randvel + right[1]*tcos + up[1]*tsin; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert + right[2]*tcos + up[2]*tsin; - } - break; - - case SM_DISTBALL: - { - float rdist; - - rdist = ptype->spawnparam2 - crandom()*(1-(crandom() * ptype->spawnparam1)); - - // this is a strange spawntype, which is based on the fact that - // crandom()*crandom() provides something similar to an exponential - // probability curve - p->org[0] = crandom(); - p->org[1] = crandom(); - p->org[2] = crandom(); - - VectorNormalize(p->org); - VectorScale(p->org, rdist, p->org); - - p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread; - p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert + p->org[2]*ptype->offsetspreadvert; - - p->org[0] = p->org[0]*ptype->areaspread + start[0]; - p->org[1] = p->org[1]*ptype->areaspread + start[1]; - p->org[2] = p->org[2]*ptype->areaspreadvert + start[2]; - } - break; - default: - p->org[0] = crandom(); - p->org[1] = crandom(); - p->org[2] = crandom(); - - p->vel[0] = vec[0]*veladd+crandom()*randvel + p->org[0]*ptype->offsetspread; - p->vel[1] = vec[1]*veladd+crandom()*randvel + p->org[1]*ptype->offsetspread; - p->vel[2] = vec[2]*veladd+crandom()*randvelvert + p->org[2]*ptype->offsetspreadvert; - - p->org[0] = p->org[0]*ptype->areaspread + start[0]; - p->org[1] = p->org[1]*ptype->areaspread + start[1]; - p->org[2] = p->org[2]*ptype->areaspreadvert + start[2]; - break; - } - } - - VectorAdd (start, vstep, start); - - if (ptype->countrand) - { - float rstep = frandom() / ptype->countrand; - VectorMA(start, rstep, vec, start); - step += rstep; - } - - p->die = particletime + ptype->die - p->die; - } - - if (ts) - { - ts->state1.lastdist = len; - - // update beamseg list - if (ptype->type == PT_BEAM) - { - if (b) - { - if (ptype->beams) - { - if (ts->lastbeam) - { - b->next = ts->lastbeam->next; - ts->lastbeam->next = bfirst; - ts->lastbeam->flags &= ~BS_LASTSEG; - } - else - { - b->next = ptype->beams; - ptype->beams = bfirst; - } - } - else - { - ptype->beams = bfirst; - b->next = NULL; - } - - b->flags |= BS_LASTSEG; - ts->lastbeam = b; - } - - if ((!free_particles || !free_beams) && ts->lastbeam) - { - ts->lastbeam->flags &= ~BS_LASTSEG; - ts->lastbeam->flags |= BS_NODRAW; - ts->lastbeam = NULL; - } - } - } - else if (ptype->type == PT_BEAM) - { - if (b) - { - b->flags |= BS_NODRAW; - b->next = ptype->beams; - ptype->beams = bfirst; - } - } - - // maintain run list - if (!(ptype->state & PS_INRUNLIST)) - { - ptype->nexttorun = part_run_list; - part_run_list = ptype; - ptype->state |= PS_INRUNLIST; - } - - return; -} - -int P_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk) -{ - part_type_t *ptype = &part_type[type]; - - if (type < 0 || type >= numparticletypes) - return 1; //bad value - - if (!ptype->loaded) - return 1; - - // inwater check, switch only once - if (r_part_contentswitch.value && ptype->inwater >= 0) - { - int cont; - cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, startpos); - - if (cont & FTECONTENTS_WATER) - ptype = &part_type[ptype->inwater]; - } - - P_ParticleTrailDraw (startpos, end, ptype, tsk); - return 0; -} - -void P_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk) -{ - part_type[pe_defaulttrail].colorindex = color; - part_type[pe_defaulttrail].colorrand = crnd; - P_ParticleTrail(start, end, pe_defaulttrail, tsk); } #ifdef Q2BSPS @@ -3217,12 +148,6 @@ qboolean Q2TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) } #endif -qboolean DoomTraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) -{ - return false; -} - -#if 1 //extra code to make em bounce of doors. qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) { trace_t trace; @@ -3230,7 +155,6 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) int i; vec3_t delta, ts, te; physent_t *pe; - hull_t *hull; qboolean clipped=false; memset (&trace, 0, sizeof(trace)); @@ -3245,7 +169,6 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) pe = &pmove.physents[i]; if (pe->model) { - hull = &pe->model->hulls[0]; VectorSubtract(start, pe->origin, ts); VectorSubtract(end, pe->origin, te); pe->model->funcs.Trace(pe->model, 0, 0, ts, te, vec3_origin, vec3_origin, &trace); @@ -3285,1667 +208,185 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) } } -#else //basic (faster) -qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) +//handy utility... +void P_EmitEffect (vec3_t pos, int type, trailstate_t **tsk) { - pmtrace_t trace; - - memset (&trace, 0, sizeof(trace)); - trace.fraction = 1; - if (cl.worldmodel->hulls->funcs.RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace)) - return false; - - if (trace.startsolid) - return true; - - VectorCopy (trace.endpos, impact); - VectorCopy (trace.plane.normal, normal); - - return true; -} -#endif - - -part_type_t *lastgltype; -static vec3_t pright, pup; -float pframetime; -#ifdef RGLQUAKE -void GL_DrawTexturedParticle(particle_t *p, part_type_t *type) -{ - float x,y; - float scale; - - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglEnable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_FLAT); - qglBegin(GL_QUADS); - } - - scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); - if (scale < 20) - scale = 0.25; - else - scale = 0.25 + scale * 0.001; - - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - - if (p->angle) - { - x = sin(p->angle)*scale; - y = cos(p->angle)*scale; - } - else - { - x = 0; - y = scale; - } - qglTexCoord2f(0,0); - qglVertex3f (p->org[0] - x*pright[0] - y*pup[0], p->org[1] - x*pright[1] - y*pup[1], p->org[2] - x*pright[2] - y*pup[2]); - qglTexCoord2f(0,1); - qglVertex3f (p->org[0] - y*pright[0] + x*pup[0], p->org[1] - y*pright[1] + x*pup[1], p->org[2] - y*pright[2] + x*pup[2]); - qglTexCoord2f(1,1); - qglVertex3f (p->org[0] + x*pright[0] + y*pup[0], p->org[1] + x*pright[1] + y*pup[1], p->org[2] + x*pright[2] + y*pup[2]); - qglTexCoord2f(1,0); - qglVertex3f (p->org[0] + y*pright[0] - x*pup[0], p->org[1] + y*pright[1] - x*pup[1], p->org[2] + y*pright[2] - x*pup[2]); -} - - -void GL_DrawSketchParticle(particle_t *p, part_type_t *type) -{ - float x,y; - float scale; - - int quant; - - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglDisable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); -// if (type->blendmode == BM_ADD) //addative -// glBlendFunc(GL_SRC_ALPHA, GL_ONE); -// else if (type->blendmode == BM_SUBTRACT) //subtractive -// glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); -// else - qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - qglShadeModel(GL_SMOOTH); - qglBegin(GL_LINES); - } - - scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); - if (scale < 20) - scale = 0.25; - else - scale = 0.25 + scale * 0.001; - - qglColor4f (p->rgb[0]/2, - p->rgb[1]/2, - p->rgb[2]/2, - p->alpha*2); - - quant = scale; - - if (p->angle) - { - x = sin(p->angle)*scale; - y = cos(p->angle)*scale; - } - else - { - x = 0; - y = scale; - } - qglVertex3f (p->org[0] - x*pright[0] - y*pup[0], p->org[1] - x*pright[1] - y*pup[1], p->org[2] - x*pright[2] - y*pup[2]); - qglVertex3f (p->org[0] + x*pright[0] + y*pup[0], p->org[1] + x*pright[1] + y*pup[1], p->org[2] + x*pright[2] + y*pup[2]); - qglVertex3f (p->org[0] + y*pright[0] - x*pup[0], p->org[1] + y*pright[1] - x*pup[1], p->org[2] + y*pright[2] - x*pup[2]); - qglVertex3f (p->org[0] - y*pright[0] + x*pup[0], p->org[1] - y*pright[1] + x*pup[1], p->org[2] - y*pright[2] + x*pup[2]); -} - -void GL_DrawTrifanParticle(particle_t *p, part_type_t *type) -{ - int i; - vec3_t v; - float scale; - - qglEnd(); - - if (lastgltype != type) - { - lastgltype = type; - qglDisable(GL_TEXTURE_2D); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - } - - scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); - if (scale < 20) - scale = 0.05; - else - scale = 0.05 + scale * 0.0001; -/* - if ((p->vel[0]*p->vel[0]+p->vel[1]*p->vel[1]+p->vel[2]*p->vel[2])*2*scale > 30*30) - scale = 1+1/30/Length(p->vel)*2;*/ - - qglBegin (GL_TRIANGLE_FAN); - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - qglVertex3fv (p->org); - qglColor4f (p->rgb[0]/2, - p->rgb[1]/2, - p->rgb[2]/2, - 0); - for (i=7 ; i>=0 ; i--) - { - v[0] = p->org[0] - p->vel[0]*scale + vright[0]*cost[i%7]*p->scale + vup[0]*sint[i%7]*p->scale; - v[1] = p->org[1] - p->vel[1]*scale + vright[1]*cost[i%7]*p->scale + vup[1]*sint[i%7]*p->scale; - v[2] = p->org[2] - p->vel[2]*scale + vright[2]*cost[i%7]*p->scale + vup[2]*sint[i%7]*p->scale; - qglVertex3fv (v); - } - qglEnd (); - qglBegin (GL_TRIANGLES); -} - -void GL_DrawLineSparkParticle(particle_t *p, part_type_t *type) -{ - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglDisable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - qglBegin(GL_LINES); - } - - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - qglVertex3f (p->org[0], p->org[1], p->org[2]); - - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - 0); - qglVertex3f (p->org[0]-p->vel[0]/10, p->org[1]-p->vel[1]/10, p->org[2]-p->vel[2]/10); -} - -void GL_DrawTexturedSparkParticle(particle_t *p, part_type_t *type) -{ - vec3_t v, cr, o2, point; - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglEnable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - qglBegin(GL_QUADS); - } - - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - - VectorSubtract(r_refdef.vieworg, p->org, v); - CrossProduct(v, p->vel, cr); - VectorNormalize(cr); - - VectorMA(p->org, -p->scale/2, cr, point); - qglTexCoord2f(0, 0); - qglVertex3fv(point); - VectorMA(p->org, p->scale/2, cr, point); - qglTexCoord2f(0, 1); - qglVertex3fv(point); - - - VectorMA(p->org, 0.1, p->vel, o2); - - VectorSubtract(r_refdef.vieworg, o2, v); - CrossProduct(v, p->vel, cr); - VectorNormalize(cr); - - VectorMA(o2, p->scale/2, cr, point); - qglTexCoord2f(1, 1); - qglVertex3fv(point); - VectorMA(o2, -p->scale/2, cr, point); - qglTexCoord2f(1, 0); - qglVertex3fv(point); -} - -void GL_DrawSketchSparkParticle(particle_t *p, part_type_t *type) -{ - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglDisable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - qglBegin(GL_LINES); - } - - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - qglVertex3f (p->org[0], p->org[1], p->org[2]); - - qglColor4f (p->rgb[0], - p->rgb[1], - p->rgb[2], - 0); - qglVertex3f (p->org[0]-p->vel[0]/10, p->org[1]-p->vel[1]/10, p->org[2]-p->vel[2]/10); -} - -void GL_DrawParticleBeam_Textured(beamseg_t *b, part_type_t *type) -{ - vec3_t v, point; - vec3_t cr; - beamseg_t *c; - particle_t *p; - particle_t *q; - float ts; - -// if (!b->next) -// return; - - c = b->next; - - q = c->p; -// if (!q) -// return; - - p = b->p; -// if (!p) -// return; - - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglEnable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - qglBegin(GL_QUADS); - } - qglColor4f(q->rgb[0], - q->rgb[1], - q->rgb[2], - q->alpha); -// qglBegin(GL_LINE_LOOP); - VectorSubtract(r_refdef.vieworg, q->org, v); - VectorNormalize(v); - CrossProduct(c->dir, v, cr); - ts = c->texture_s*type->rotationstartmin + particletime*type->rotationmin; - - VectorMA(q->org, -q->scale, cr, point); - qglTexCoord2f(ts, 0); - qglVertex3fv(point); - VectorMA(q->org, q->scale, cr, point); - qglTexCoord2f(ts, 1); - qglVertex3fv(point); - - qglColor4f(p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - - VectorSubtract(r_refdef.vieworg, p->org, v); - VectorNormalize(v); - CrossProduct(b->dir, v, cr); // replace with old p->dir? - ts = b->texture_s*type->rotationstartmin + particletime*type->rotationmin; - - VectorMA(p->org, p->scale, cr, point); - qglTexCoord2f(ts, 1); - qglVertex3fv(point); - VectorMA(p->org, -p->scale, cr, point); - qglTexCoord2f(ts, 0); - qglVertex3fv(point); -// qglEnd(); -} - -void GL_DrawParticleBeam_Untextured(beamseg_t *b, part_type_t *type) -{ - vec3_t v; - vec3_t cr; - beamseg_t *c; - particle_t *p; - particle_t *q; - - vec3_t point[4]; - -// if (!b->next) -// return; - - c = b->next; - - q = c->p; -// if (!q) -// return; - - p = b->p; -// if (!p) -// return; - - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglDisable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - qglBegin(GL_QUADS); - } - -// qglBegin(GL_LINE_LOOP); - VectorSubtract(r_refdef.vieworg, q->org, v); - VectorNormalize(v); - CrossProduct(c->dir, v, cr); - - VectorMA(q->org, -q->scale, cr, point[0]); - VectorMA(q->org, q->scale, cr, point[1]); - - - VectorSubtract(r_refdef.vieworg, p->org, v); - VectorNormalize(v); - CrossProduct(b->dir, v, cr); // replace with old p->dir? - - VectorMA(p->org, p->scale, cr, point[2]); - VectorMA(p->org, -p->scale, cr, point[3]); - - - //one half - //back out - //back in - //front in - //front out - qglColor4f(q->rgb[0], - q->rgb[1], - q->rgb[2], - 0); - qglVertex3fv(point[0]); - qglColor4f(q->rgb[0], - q->rgb[1], - q->rgb[2], - q->alpha); - qglVertex3fv(q->org); - - qglColor4f(p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - qglVertex3fv(p->org); - qglColor4f(p->rgb[0], - p->rgb[1], - p->rgb[2], - 0); - qglVertex3fv(point[3]); - - //front out - //front in - //back in - //back out - qglColor4f(p->rgb[0], - p->rgb[1], - p->rgb[2], - 0); - qglVertex3fv(point[2]); - qglColor4f(p->rgb[0], - p->rgb[1], - p->rgb[2], - p->alpha); - qglVertex3fv(p->org); - - qglColor4f(q->rgb[0], - q->rgb[1], - q->rgb[2], - q->alpha); - qglVertex3fv(q->org); - qglColor4f(q->rgb[0], - q->rgb[1], - q->rgb[2], - 0); - qglVertex3fv(point[1]); - -// qglEnd(); -} - -void GL_DrawClippedDecal(clippeddecal_t *d, part_type_t *type) -{ - if (lastgltype != type) - { - lastgltype = type; - qglEnd(); - qglEnable(GL_TEXTURE_2D); - GL_Bind(type->texturenum); - APPLYBLEND(type->blendmode); - qglShadeModel(GL_SMOOTH); - -// qglDisable(GL_TEXTURE_2D); -// qglBegin(GL_LINE_LOOP); - - qglBegin(GL_TRIANGLES); - } - - qglColor4f(d->rgb[0], - d->rgb[1], - d->rgb[2], - d->alpha); - - qglTexCoord2fv(d->texcoords[0]); - qglVertex3fv(d->vertex[0]); - qglTexCoord2fv(d->texcoords[1]); - qglVertex3fv(d->vertex[1]); - qglTexCoord2fv(d->texcoords[2]); - qglVertex3fv(d->vertex[2]); -} - -#endif -#ifdef SWQUAKE -void SWD_DrawParticleSpark(particle_t *p, part_type_t *type) -{ - float speed; - vec3_t src, dest; - - int r,g,b; //if you have a cpu with mmx, good for you... - r = p->rgb[0]*255; - if (r < 0) - r = 0; - else if (r > 255) - r = 255; - g = p->rgb[1]*255; - if (g < 0) - g = 0; - else if (g > 255) - g = 255; - b = p->rgb[2]*255; - if (b < 0) - b = 0; - else if (b > 255) - b = 255; - p->color = GetPaletteIndex(r, g, b); - - speed = Length(p->vel); - if ((speed) < 1) - { - VectorCopy(p->org, src); - VectorCopy(p->org, dest); - } - else - { //causes flickers with lower vels (due to bouncing in physics) - if (speed < 50) - speed *= 50/speed; - VectorMA(p->org, 2.5/(speed), p->vel, src); - VectorMA(p->org, -2.5/(speed), p->vel, dest); - } - - D_DrawSparkTrans(p, src, dest, type->blendmode); -} -void SWD_DrawParticleBlob(particle_t *p, part_type_t *type) -{ - int r,g,b; //This really shouldn't be like this. Pitty the 32 bit renderer... - r = p->rgb[0]*255; - if (r < 0) - r = 0; - else if (r > 255) - r = 255; - g = p->rgb[1]*255; - if (g < 0) - g = 0; - else if (g > 255) - g = 255; - b = p->rgb[2]*255; - if (b < 0) - b = 0; - else if (b > 255) - b = 255; - p->color = GetPaletteIndex(r, g, b); - D_DrawParticleTrans(p, type->blendmode); -} -void SWD_DrawParticleBeam(beamseg_t *beam, part_type_t *type) -{ - int r,g,b; //if you have a cpu with mmx, good for you... - beamseg_t *c; - particle_t *p; - particle_t *q; - -// if (!b->next) -// return; - - c = beam->next; - - q = c->p; -// if (!q) -// return; - - p = beam->p; - - r = p->rgb[0]*255; - if (r < 0) - r = 0; - else if (r > 255) - r = 255; - g = p->rgb[1]*255; - if (g < 0) - g = 0; - else if (g > 255) - g = 255; - b = p->rgb[2]*255; - if (b < 0) - b = 0; - else if (b > 255) - b = 255; - p->color = GetPaletteIndex(r, g, b); - D_DrawSparkTrans(p, p->org, q->org, type->blendmode); -} -#endif -#ifdef D3DQUAKE -typedef struct d3dparticlevert_s { - float org[3]; - unsigned int colour; - float s, t; //these could actually be preinitialised -} d3dparticlevert_t; -d3dparticlevert_t d3dparticlevert[4]; - -typedef struct d3dparticlevertut_s { - float org[3]; - unsigned int colour; -} d3dparticlevertut_t; -d3dparticlevertut_t d3dparticlevertut[4]; - -unsigned short d3dparticlevertindexes[] = -{ - 0, 1, 2, - 0, 2, 3 -}; - -void D3D_DrawParticleBlob(particle_t *p, part_type_t *type) -{ - float scale; - float x; - float y; - unsigned int colour; - int cb, cg, cr, ca; - if (lastgltype != type) - { - lastgltype = type; - pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); - -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - - APPLYD3DBLEND(type->blendmode); - } - - scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] - + (p->org[2] - r_origin[2])*vpn[2]; - scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); - if (scale < 20) - scale = 0.25; - else - scale = 0.25 + scale * 0.001; - - cr = p->rgb[0]*255; - if (cr < 0) cr = 0; - if (cr > 255) cr = 255; - - cg = p->rgb[1]*255; - if (cg < 0) cg = 0; - if (cg > 255) cg = 255; - - cb = p->rgb[2]*255; - if (cb < 0) cb = 0; - if (cb > 255) cb = 255; - - ca = p->alpha*255; - if (ca < 0) ca = 0; - if (ca > 255) ca = 255; - - colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); - - if (p->angle) - { - x = sin(p->angle)*scale; - y = cos(p->angle)*scale; - } - else - { - x = 0; - y = scale; - } - d3dparticlevert[0].s = 0; - d3dparticlevert[0].t = 0; - d3dparticlevert[0].colour = colour; - d3dparticlevert[0].org[0] = p->org[0] - x*pright[0] - y*pup[0]; - d3dparticlevert[0].org[1] = p->org[1] - x*pright[1] - y*pup[1]; - d3dparticlevert[0].org[2] = p->org[2] - x*pright[2] - y*pup[2]; - - d3dparticlevert[1].s = 0; - d3dparticlevert[1].t = 1; - d3dparticlevert[1].colour = colour; - d3dparticlevert[1].org[0] = p->org[0] - y*pright[0] + x*pup[0]; - d3dparticlevert[1].org[1] = p->org[1] - y*pright[1] + x*pup[1]; - d3dparticlevert[1].org[2] = p->org[2] - y*pright[2] + x*pup[2]; - - d3dparticlevert[2].s = 1; - d3dparticlevert[2].t = 1; - d3dparticlevert[2].colour = colour; - d3dparticlevert[2].org[0] = p->org[0] + x*pright[0] + y*pup[0]; - d3dparticlevert[2].org[1] = p->org[1] + x*pright[1] + y*pup[1]; - d3dparticlevert[2].org[2] = p->org[2] + x*pright[2] + y*pup[2]; - - d3dparticlevert[3].s = 1; - d3dparticlevert[3].t = 0; - d3dparticlevert[3].colour = colour; - d3dparticlevert[3].org[0] = p->org[0] + y*pright[0] - x*pup[0]; - d3dparticlevert[3].org[1] = p->org[1] + y*pright[1] - x*pup[1]; - d3dparticlevert[3].org[2] = p->org[2] + y*pright[2] - x*pup[2]; - - pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); -} -void D3D_DrawParticleSpark(particle_t *p, part_type_t *type) -{ - vec3_t v, crv, o2; - - unsigned int colour; - int cb, cg, cr, ca; - - if (lastgltype != type) - { - lastgltype = type; - pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); - -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - - APPLYD3DBLEND(type->blendmode); - } - - - cr = p->rgb[0]*255; - if (cr < 0) cr = 0; - if (cr > 255) cr = 255; - - cg = p->rgb[1]*255; - if (cg < 0) cg = 0; - if (cg > 255) cg = 255; - - cb = p->rgb[2]*255; - if (cb < 0) cb = 0; - if (cb > 255) cb = 255; - - ca = p->alpha*255; - if (ca < 0) ca = 0; - if (ca > 255) ca = 255; - - colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); - - - - - VectorSubtract(r_refdef.vieworg, p->org, v); - CrossProduct(v, p->vel, crv); - VectorNormalize(crv); - - VectorMA(p->org, -p->scale/2, crv, d3dparticlevert[0].org); - d3dparticlevert[0].s = 0; - d3dparticlevert[0].t = 0; - d3dparticlevert[0].colour = colour; - - VectorMA(p->org, p->scale/2, crv, d3dparticlevert[1].org); - d3dparticlevert[1].s = 0; - d3dparticlevert[1].t = 1; - d3dparticlevert[1].colour = colour; - - - VectorMA(p->org, 0.1, p->vel, o2); - - VectorSubtract(r_refdef.vieworg, o2, v); - CrossProduct(v, p->vel, crv); - VectorNormalize(crv); - - VectorMA(o2, p->scale/2, crv, d3dparticlevert[2].org); - d3dparticlevert[2].s = 1; - d3dparticlevert[2].t = 1; - d3dparticlevert[2].colour = colour; - - VectorMA(o2, -p->scale/2, crv, d3dparticlevert[3].org); - d3dparticlevert[3].s = 1; - d3dparticlevert[3].t = 0; - d3dparticlevert[3].colour = colour; - - - pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); -} -void D3D_DrawParticleBeam(beamseg_t *b, part_type_t *type) -{ - vec3_t v; - vec3_t crv; - beamseg_t *c; - particle_t *p; - particle_t *q; - float ts; - - - unsigned int colour; - int cb, cg, cr, ca; - - if (lastgltype != type) - { - lastgltype = type; - pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); - -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); -pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - - APPLYD3DBLEND(type->blendmode); - } - - - - - c = b->next; - q = c->p; - p = b->p; - - - cr = q->rgb[0]*255; - if (cr < 0) cr = 0; - if (cr > 255) cr = 255; - - cg = q->rgb[1]*255; - if (cg < 0) cg = 0; - if (cg > 255) cg = 255; - - cb = q->rgb[2]*255; - if (cb < 0) cb = 0; - if (cb > 255) cb = 255; - - ca = q->alpha*255; - if (ca < 0) ca = 0; - if (ca > 255) ca = 255; - - colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); - - - - - - c = b->next; - - q = c->p; - - p = b->p; - - VectorSubtract(r_refdef.vieworg, q->org, v); - VectorNormalize(v); - CrossProduct(c->dir, v, crv); - ts = c->texture_s*type->rotationstartmin + particletime*type->rotationmin; - - VectorMA(q->org, -q->scale, crv, d3dparticlevert[0].org); - d3dparticlevert[0].s = ts; - d3dparticlevert[0].t = 0; - d3dparticlevert[0].colour = colour; - - VectorMA(q->org, q->scale, crv, d3dparticlevert[1].org); - d3dparticlevert[1].s = ts; - d3dparticlevert[1].t = 1; - d3dparticlevert[1].colour = colour; - - - cr = p->rgb[0]*255; - if (cr < 0) cr = 0; - if (cr > 255) cr = 255; - - cg = p->rgb[1]*255; - if (cg < 0) cg = 0; - if (cg > 255) cg = 255; - - cb = p->rgb[2]*255; - if (cb < 0) cb = 0; - if (cb > 255) cb = 255; - - ca = p->alpha*255; - if (ca < 0) ca = 0; - if (ca > 255) ca = 255; - - colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); - - - VectorSubtract(r_refdef.vieworg, p->org, v); - VectorNormalize(v); - CrossProduct(b->dir, v, crv); // replace with old p->dir? - ts = b->texture_s*type->rotationstartmin + particletime*type->rotationmin; - - VectorMA(p->org, p->scale, crv, d3dparticlevert[2].org); - d3dparticlevert[2].s = ts; - d3dparticlevert[2].t = 1; - d3dparticlevert[2].colour = colour; - - VectorMA(p->org, -p->scale, crv, d3dparticlevert[3].org); - d3dparticlevert[3].s = ts; - d3dparticlevert[3].t = 0; - d3dparticlevert[3].colour = colour; - - - pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); -} - -void D3D_DrawParticleBeamUT(beamseg_t *b, part_type_t *type) -{ - vec3_t v; - vec3_t crv; - beamseg_t *c; - particle_t *p; - particle_t *q; - float ts; - - - unsigned int colour; - int cb, cg, cr, ca; - -// D3D_DrawParticleBeam(b, type); -// return; - - if (lastgltype != type) - { - lastgltype = type; - pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, NULL); - pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); - pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2); - - pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); - pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); - - - APPLYD3DBLEND(type->blendmode); - } - - - - - c = b->next; - q = c->p; - p = b->p; - - - cr = q->rgb[0]*255; - if (cr < 0) cr = 0; - if (cr > 255) cr = 255; - - cg = q->rgb[1]*255; - if (cg < 0) cg = 0; - if (cg > 255) cg = 255; - - cb = q->rgb[2]*255; - if (cb < 0) cb = 0; - if (cb > 255) cb = 255; - - ca = q->alpha*255; - if (ca < 0) ca = 0; - if (ca > 255) ca = 255; - - colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); - - - - - - c = b->next; - - q = c->p; - - p = b->p; - - VectorSubtract(r_refdef.vieworg, q->org, v); - VectorNormalize(v); - CrossProduct(c->dir, v, crv); - ts = c->texture_s*type->rotationstartmin + particletime*type->rotationmin; - - VectorMA(q->org, -q->scale, crv, d3dparticlevertut[0].org); - d3dparticlevertut[0].colour = colour; - - VectorMA(q->org, q->scale, crv, d3dparticlevertut[1].org); - d3dparticlevertut[1].colour = colour; - - - cr = p->rgb[0]*255; - if (cr < 0) cr = 0; - if (cr > 255) cr = 255; - - cg = p->rgb[1]*255; - if (cg < 0) cg = 0; - if (cg > 255) cg = 255; - - cb = p->rgb[2]*255; - if (cb < 0) cb = 0; - if (cb > 255) cb = 255; - - ca = p->alpha*255; - if (ca < 0) ca = 0; - if (ca > 255) ca = 255; - - colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); - - - VectorSubtract(r_refdef.vieworg, p->org, v); - VectorNormalize(v); - CrossProduct(b->dir, v, crv); // replace with old p->dir? - ts = b->texture_s*type->rotationstartmin + particletime*type->rotationmin; - - VectorMA(p->org, p->scale, crv, d3dparticlevertut[2].org); - d3dparticlevertut[2].colour = colour; - - VectorMA(p->org, -p->scale, crv, d3dparticlevertut[3].org); - d3dparticlevertut[3].colour = colour; - - - pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE, d3dparticlevertut, 4, d3dparticlevertindexes, 6, 0); -} -#endif - -void DrawParticleTypes (void (*texturedparticles)(particle_t *,part_type_t*), void (*sparklineparticles)(particle_t*,part_type_t*), void (*sparkfanparticles)(particle_t*,part_type_t*), void (*sparktexturedparticles)(particle_t*,part_type_t*), void (*beamparticlest)(beamseg_t*,part_type_t*), void (*beamparticlesut)(beamseg_t*,part_type_t*), void (*drawdecalparticles)(clippeddecal_t*,part_type_t*)) -{ - RSpeedMark(); - - qboolean (*tr) (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); - void *pdraw, *bdraw; - - vec3_t oldorg; - vec3_t stop, normal; - part_type_t *type, *lastvalidtype; - particle_t *p, *kill; - clippeddecal_t *d; - ramp_t *ramp; - float grav; - vec3_t friction; - float dist; - particle_t *kill_list, *kill_first; //the kill list is to stop particles from being freed and reused whilst still in this loop - //which is bad because beams need to find out when particles died. Reuse can do wierd things. - //remember that they're not drawn instantly either. - beamseg_t *b, *bkill; - - int traces=r_particle_tracelimit.value; - int rampind; - - lastgltype = NULL; - - pframetime = host_frametime; - if (cl.paused || r_secondaryview) - pframetime = 0; - - VectorScale (vup, 1.5, pup); - VectorScale (vright, 1.5, pright); -#ifdef SWQUAKE - VectorScale (vright, xscaleshrink, r_pright); - VectorScale (vup, yscaleshrink, r_pup); - VectorCopy (vpn, r_ppn); -#endif - -#ifdef Q2BSPS - if (cl.worldmodel->fromgame == fg_quake2 || cl.worldmodel->fromgame == fg_quake3) - tr = Q2TraceLineN; - else -#endif - tr = TraceLineN; - - kill_list = kill_first = NULL; - - // reassign drawing methods by cvars - if (r_part_beams_textured.value < 0) - beamparticlest = NULL; - else if (!r_part_beams_textured.value) - beamparticlest = beamparticlesut; - - if (r_part_beams.value < 0) - beamparticlesut = NULL; - else if (!r_part_beams.value) - { - beamparticlest = NULL; - beamparticlesut = NULL; - } - - if (r_part_sparks_textured.value < 0) - sparktexturedparticles = NULL; - else if (!r_part_sparks_textured.value) - sparktexturedparticles = sparklineparticles; - - if (r_part_sparks_trifan.value < 0) - sparkfanparticles = NULL; - else if (!r_part_sparks_trifan.value) - sparkfanparticles = sparklineparticles; - - if (r_part_sparks.value < 0) - sparklineparticles = NULL; - else if (!r_part_sparks.value) - { - sparktexturedparticles = NULL; - sparkfanparticles = NULL; - sparklineparticles = NULL; - } - - for (type = part_run_list, lastvalidtype = NULL; type != NULL; type = type->nexttorun) - { - if (type->clippeddecals) - { -/* for ( ;; ) - { - dkill = type->clippeddecals; - if (dkill && dkill->die < particletime) - { - type->clippeddecals = dkill->next; - free_decals = - - - dkill->next = (clippeddecal_t *)kill_list; - kill_list = (particle_t*)dkill; - if (!kill_first) - kill_first = kill_list; - continue; - } - break; - } -*/ for (d=type->clippeddecals ; d ; d=d->next) - { - /* for ( ;; ) - { - dkill = d->next; - if (dkill && dkill->die < particletime) - { - d->next = dkill->next; - dkill->next = (clippeddecal_t *)kill_list; - kill_list = (particle_t*)dkill; - if (!kill_first) - kill_first = kill_list; - continue; - } - break; - }*/ - - - - switch (type->rampmode) - { - case RAMP_ABSOLUTE: - rampind = (int)(type->rampindexes * (type->die - (d->die - particletime)) / type->die); - if (rampind >= type->rampindexes) - rampind = type->rampindexes - 1; - ramp = type->ramp + rampind; - VectorCopy(ramp->rgb, d->rgb); - d->alpha = ramp->alpha; - break; - case RAMP_DELTA: //particle ramps - ramp = type->ramp + (int)(type->rampindexes * (type->die - (d->die - particletime)) / type->die); - VectorMA(d->rgb, pframetime, ramp->rgb, d->rgb); - d->alpha -= pframetime*ramp->alpha; - break; - case RAMP_NONE: //particle changes acording to it's preset properties. - if (particletime < (d->die-type->die+type->rgbchangetime)) - { - d->rgb[0] += pframetime*type->rgbchange[0]; - d->rgb[1] += pframetime*type->rgbchange[1]; - d->rgb[2] += pframetime*type->rgbchange[2]; - } - d->alpha += pframetime*type->alphachange; - } - - drawdecalparticles(d, type); - } - } - - bdraw = NULL; - pdraw = NULL; - - // set drawing methods by type and cvars and hope branch - // prediction takes care of the rest - switch(type->type) - { - case PT_BEAM: - if (*type->texname) - bdraw = beamparticlest; - else - bdraw = beamparticlesut; - break; - case PT_DECAL: - break; - case PT_NORMAL: - pdraw = texturedparticles; - break; - case PT_SPARK: - pdraw = sparklineparticles; - break; - case PT_SPARKFAN: - pdraw = sparkfanparticles; - break; - case PT_TEXTUREDSPARK: - pdraw = sparktexturedparticles; - break; - } - - if (!type->die) - { - while ((p=type->particles)) - { - if (pdraw) - RQ_AddDistReorder(pdraw, p, type, p->org); - - // make sure emitter runs at least once - if (type->emit >= 0 && type->emitstart <= 0) - P_RunParticleEffectType(p->org, p->vel, 1, type->emit); - - // make sure stain effect runs - if (type->stains && r_bloodstains.value) - { - if (traces-->0&&tr(oldorg, p->org, stop, normal)) - { - R_AddStain(stop, (p->rgb[1]*-10+p->rgb[2]*-10), - (p->rgb[0]*-10+p->rgb[2]*-10), - (p->rgb[0]*-10+p->rgb[1]*-10), - 30*p->alpha*type->stains); - } - } - - type->particles = p->next; -// p->next = free_particles; -// free_particles = p; - p->next = kill_list; - kill_list = p; - if (!kill_first) // branch here is probably faster than list traversal later - kill_first = p; - } - - if (type->beams) - { - b = type->beams; - } - - while ((b=type->beams) && (b->flags & BS_DEAD)) - { - type->beams = b->next; - b->next = free_beams; - free_beams = b; - } - - while (b) - { - if (!(b->flags & BS_NODRAW)) - { - // no BS_NODRAW implies b->next != NULL - // BS_NODRAW should imply b->next == NULL or b->next->flags & BS_DEAD - VectorCopy(b->next->p->org, stop); - VectorCopy(b->p->org, oldorg); - VectorSubtract(stop, oldorg, b->next->dir); - VectorNormalize(b->next->dir); - if (bdraw) - { - VectorAdd(stop, oldorg, stop); - VectorScale(stop, 0.5, stop); - - RQ_AddDistReorder(bdraw, b, type, stop); - } - } - - // clean up dead entries ahead of current - for ( ;; ) - { - bkill = b->next; - if (bkill && (bkill->flags & BS_DEAD)) - { - b->next = bkill->next; - bkill->next = free_beams; - free_beams = bkill; - continue; - } - break; - } - - b->flags |= BS_DEAD; - b = b->next; - } - - continue; - } - - //kill off early ones. - if (type->emittime < 0) - { - for ( ;; ) - { - kill = type->particles; - if (kill && kill->die < particletime) - { - P_DelinkTrailstate(&kill->state.trailstate); - type->particles = kill->next; - kill->next = kill_list; - kill_list = kill; - if (!kill_first) - kill_first = kill; - continue; - } - break; - } - } - else - { - for ( ;; ) - { - kill = type->particles; - if (kill && kill->die < particletime) - { - type->particles = kill->next; - kill->next = kill_list; - kill_list = kill; - if (!kill_first) - kill_first = kill; - continue; - } - break; - } - } - - grav = type->gravity*pframetime; - VectorScale(type->friction, pframetime, friction); - - for (p=type->particles ; p ; p=p->next) - { - if (type->emittime < 0) - { - for ( ;; ) - { - kill = p->next; - if (kill && kill->die < particletime) - { - P_DelinkTrailstate(&kill->state.trailstate); - p->next = kill->next; - kill->next = kill_list; - kill_list = kill; - if (!kill_first) - kill_first = kill; - continue; - } - break; - } - } - else - { - for ( ;; ) - { - kill = p->next; - if (kill && kill->die < particletime) - { - p->next = kill->next; - kill->next = kill_list; - kill_list = kill; - if (!kill_first) - kill_first = kill; - continue; - } - break; - } - } - - VectorCopy(p->org, oldorg); - if (type->flags & PT_VELOCITY) - { - p->org[0] += p->vel[0]*pframetime; - p->org[1] += p->vel[1]*pframetime; - p->org[2] += p->vel[2]*pframetime; - if (type->flags & PT_FRICTION) - { - p->vel[0] -= friction[0]*p->vel[0]; - p->vel[1] -= friction[1]*p->vel[1]; - p->vel[2] -= friction[2]*p->vel[2]; - } - p->vel[2] -= grav; - } - - p->angle += p->rotationspeed*pframetime; - - switch (type->rampmode) - { - case RAMP_ABSOLUTE: - rampind = (int)(type->rampindexes * (type->die - (p->die - particletime)) / type->die); - if (rampind >= type->rampindexes) - rampind = type->rampindexes - 1; - ramp = type->ramp + rampind; - VectorCopy(ramp->rgb, p->rgb); - p->alpha = ramp->alpha; - p->scale = ramp->scale; - break; - case RAMP_DELTA: //particle ramps - rampind = (int)(type->rampindexes * (type->die - (p->die - particletime)) / type->die); - if (rampind >= type->rampindexes) - rampind = type->rampindexes - 1; - ramp = type->ramp + rampind; - VectorMA(p->rgb, pframetime, ramp->rgb, p->rgb); - p->alpha -= pframetime*ramp->alpha; - p->scale += pframetime*ramp->scale; - break; - case RAMP_NONE: //particle changes acording to it's preset properties. - if (particletime < (p->die-type->die+type->rgbchangetime)) - { - p->rgb[0] += pframetime*type->rgbchange[0]; - p->rgb[1] += pframetime*type->rgbchange[1]; - p->rgb[2] += pframetime*type->rgbchange[2]; - } - p->alpha += pframetime*type->alphachange; - p->scale += pframetime*type->scaledelta; - } - - if (type->emit >= 0) - { - if (type->emittime < 0) - P_ParticleTrail(oldorg, p->org, type->emit, &p->state.trailstate); - else if (p->state.nextemit < particletime) - { - p->state.nextemit = particletime + type->emittime + frandom()*type->emitrand; - P_RunParticleEffectType(p->org, p->vel, 1, type->emit); - } - } - - if (type->cliptype>=0 && r_bouncysparks.value) - { - if (traces-->0&&tr(oldorg, p->org, stop, normal)) - { - if (type->stains && r_bloodstains.value) - R_AddStain(stop, p->rgb[1]*-10+p->rgb[2]*-10, - p->rgb[0]*-10+p->rgb[2]*-10, - p->rgb[0]*-10+p->rgb[1]*-10, - 30*p->alpha); - - if (part_type + type->cliptype == type) - { //bounce - dist = DotProduct(p->vel, normal) * (-1-(rand()/(float)0x7fff)/2); - - VectorMA(p->vel, dist, normal, p->vel); - VectorCopy(stop, p->org); - p->vel[0] *= type->clipbounce; - p->vel[1] *= type->clipbounce; - p->vel[2] *= type->clipbounce; - - if (!*type->texname && Length(p->vel)<1000*pframetime && type->type == PT_NORMAL) - p->die = -1; - } - else - { - p->die = -1; - VectorNormalize(p->vel); - P_RunParticleEffectType(stop, p->vel, type->clipcount/part_type[type->cliptype].count, type->cliptype); - } - - continue; - } - } - else if (type->stains && r_bloodstains.value) - { - if (traces-->0&&tr(oldorg, p->org, stop, normal)) - { - R_AddStain(stop, (p->rgb[1]*-10+p->rgb[2]*-10), - (p->rgb[0]*-10+p->rgb[2]*-10), - (p->rgb[0]*-10+p->rgb[1]*-10), - 30*p->alpha*type->stains); - p->die = -1; - continue; - } - } - - if (pdraw) - RQ_AddDistReorder((void*)pdraw, p, type, p->org); - } - - // beams are dealt with here - - // kill early entries - for ( ;; ) - { - bkill = type->beams; - if (bkill && (bkill->flags & BS_DEAD || bkill->p->die < particletime) && !(bkill->flags & BS_LASTSEG)) - { - type->beams = bkill->next; - bkill->next = free_beams; - free_beams = bkill; - continue; - } - break; - } - - - b = type->beams; - if (b) - { - for ( ;; ) - { - if (b->next) - { - // mark dead entries - if (b->flags & (BS_LASTSEG|BS_DEAD|BS_NODRAW)) - { - // kill some more dead entries - for ( ;; ) - { - bkill = b->next; - if (bkill && (bkill->flags & BS_DEAD) && !(bkill->flags & BS_LASTSEG)) - { - b->next = bkill->next; - bkill->next = free_beams; - free_beams = bkill; - continue; - } - break; - } - - if (!bkill) // have to check so we don't hit NULL->next - continue; - } - else - { - if (!(b->next->flags & BS_DEAD)) - { - VectorCopy(b->next->p->org, stop); - VectorCopy(b->p->org, oldorg); - VectorSubtract(stop, oldorg, b->next->dir); - VectorNormalize(b->next->dir); - if (bdraw) - { - VectorAdd(stop, oldorg, stop); - VectorScale(stop, 0.5, stop); - - RQ_AddDistReorder(bdraw, b, type, stop); - } - } - - // if (b->p->die < particletime) - // b->flags |= BS_DEAD; - } - } - else - { - if (b->p->die < particletime) // end of the list check - b->flags |= BS_DEAD; - - break; - } - - if (b->p->die < particletime) - b->flags |= BS_DEAD; - - b = b->next; - } - } - - // delete from run list if necessary - if (!type->particles && !type->beams && !type->clippeddecals) - { -// if (!lastvalidtype) -// part_run_list = type->nexttorun; -// else -// lastvalidtype->nexttorun = type->nexttorun; -// type->state &= ~PS_INRUNLIST; - } - else - lastvalidtype = type; - } - - RSpeedEnd(RSPEED_PARTICLES); - - // lazy delete for particles is done here - if (kill_list) - { - kill_first->next = free_particles; - free_particles = kill_list; - } - - particletime += pframetime; -} - -#ifdef RGLQUAKE -void P_FlushRenderer(void) -{ - qglDepthMask(0); //primarily to stop close particles from obscuring each other - qglDisable(GL_ALPHA_TEST); - qglEnable (GL_BLEND); - GL_TexEnv(GL_MODULATE); - qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - lastgltype = NULL; -} -#endif - -/* -=============== -R_DrawParticles -=============== -*/ -void P_DrawParticles (void) -{ - RSpeedMark(); - - P_AddRainParticles(); -#if defined(RGLQUAKE) - if (qrenderer == QR_OPENGL) - { - extern int gldepthfunc; - extern cvar_t r_drawflat; - - P_FlushRenderer(); - - if (qglPolygonOffset) - qglPolygonOffset(-1, 0); - qglEnable(GL_POLYGON_OFFSET_FILL); - qglEnable(GL_BLEND); - - qglDepthFunc(gldepthfunc); - - qglDisable(GL_ALPHA_TEST); - qglBegin(GL_QUADS); - if (r_drawflat.value == 2) - DrawParticleTypes(GL_DrawSketchParticle, GL_DrawSketchSparkParticle, GL_DrawSketchSparkParticle, GL_DrawSketchSparkParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured, GL_DrawClippedDecal); - else - DrawParticleTypes(GL_DrawTexturedParticle, GL_DrawLineSparkParticle, GL_DrawTrifanParticle, GL_DrawTexturedSparkParticle, GL_DrawParticleBeam_Textured, GL_DrawParticleBeam_Untextured, GL_DrawClippedDecal); - qglEnd(); - qglDisable(GL_POLYGON_OFFSET_FILL); - - - - RSpeedRemark(); - qglBegin(GL_QUADS); - RQ_RenderDistAndClear(); - qglEnd(); - RSpeedEnd(RSPEED_PARTICLESDRAW); - - qglEnable(GL_TEXTURE_2D); - - GL_TexEnv(GL_MODULATE); - qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - qglDepthMask(1); + if (cl.paused) return; - } -#endif -#ifdef SWQUAKE - if (qrenderer == QR_SOFTWARE) - { - lastgltype = NULL; - DrawParticleTypes(SWD_DrawParticleBlob, SWD_DrawParticleSpark, SWD_DrawParticleSpark, SWD_DrawParticleSpark, SWD_DrawParticleBeam, SWD_DrawParticleBeam, NULL); - RSpeedRemark(); - D_StartParticles(); - RQ_RenderDistAndClear(); - D_EndParticles(); - RSpeedEnd(RSPEED_PARTICLESDRAW); - return; - } -#endif -#if defined(D3DQUAKE) - if (qrenderer == QR_DIRECT3D) + pe->RunParticleEffectState(pos, NULL, host_frametime, type, tsk); +} + + + + + + + + + + + +// P_SelectableTrail: given default/opposite effects, model pointer, and a user selection cvar +// changes model to the appropriate trail effect and default trail index +void P_SelectableTrail(model_t *model, cvar_t *selection, int mdleffect, int mdlcidx, int oppeffect, int oppcidx) +{ + int select = (int)(selection->value); + + switch (select) { - if (pD3DDev) + case 0: // check for string, otherwise no trail + if (selection->string[0] == '0') { - lastgltype = NULL; - DrawParticleTypes(D3D_DrawParticleBlob, D3D_DrawParticleSpark, D3D_DrawParticleSpark, D3D_DrawParticleSpark, D3D_DrawParticleBeam, D3D_DrawParticleBeamUT, NULL); - - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZWRITEENABLE, FALSE ); - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE ); - - RSpeedRemark(); - RQ_RenderDistAndClear(); - RSpeedEnd(RSPEED_PARTICLESDRAW); - - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZWRITEENABLE, TRUE ); - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); - pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE ); - - pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); - - return; + model->particletrail = P_INVALID; + break; } else - D3D9_DrawParticles(particletime); - } -#endif + { + int effect = P_FindParticleType(selection->string); - if (qrenderer) - { - RSpeedRemark(); - RQ_RenderDistAndClear(); - RSpeedEnd(RSPEED_PARTICLESDRAW); + if (effect >= 0) + { + model->particletrail = effect; + model->traildefaultindex = mdlcidx; + break; + } + } + // fall through to default (so semicheat will work properly) + case 1: // default model effect + default: + model->particletrail = mdleffect; + model->traildefaultindex = mdlcidx; + break; + case 2: // opposite effect + model->particletrail = oppeffect; + model->traildefaultindex= oppcidx; + break; + case 3: // alt rocket effect + model->particletrail = P_ParticleTypeForName("TR_ALTROCKET"); + model->traildefaultindex = 107; + break; + case 4: // gib + model->particletrail = P_ParticleTypeForName("TR_BLOOD"); + model->traildefaultindex = 70; + break; + case 5: // zombie gib + model->particletrail = P_ParticleTypeForName("TR_SLIGHTBLOOD"); + model->traildefaultindex = 70; + break; + case 6: // Scrag tracer + model->particletrail = P_ParticleTypeForName("TR_WIZSPIKE"); + model->traildefaultindex = 60; + break; + case 7: // Knight tracer + model->particletrail = P_ParticleTypeForName("TR_KNIGHTSPIKE"); + model->traildefaultindex = 238; + break; + case 8: // Vore tracer + model->particletrail = P_ParticleTypeForName("TR_VORESPIKE"); + model->traildefaultindex = 154; + break; + case 9: // rail trail + model->particletrail = P_ParticleTypeForName("TR_RAILTRAIL"); + model->traildefaultindex = 15; + break; } } + +//figure out which particle trail to use for the given model, filling in its values as required. +void P_DefaultTrail (model_t *model) +{ + // TODO: EF_BRIGHTFIELD should probably be handled in here somewhere + // TODO: make trail default color into RGB values instead of indexes + if (model->engineflags & MDLF_NODEFAULTTRAIL) + return; + + if (model->flags & EF_ROCKET) + P_SelectableTrail(model, &r_rockettrail, P_ParticleTypeForName("TR_ROCKET"), 109, P_ParticleTypeForName("TR_GRENADE"), 6); + else if (model->flags & EF_GRENADE) + P_SelectableTrail(model, &r_grenadetrail, P_ParticleTypeForName("TR_GRENADE"), 6, P_ParticleTypeForName("TR_ROCKET"), 109); + else if (model->flags & EF_GIB) + { + model->particletrail = P_ParticleTypeForName("TR_BLOOD"); + model->traildefaultindex = 70; + } + else if (model->flags & EF_TRACER) + { + model->particletrail = P_ParticleTypeForName("TR_WIZSPIKE"); + model->traildefaultindex = 60; + } + else if (model->flags & EF_ZOMGIB) + { + model->particletrail = P_ParticleTypeForName("TR_SLIGHTBLOOD"); + model->traildefaultindex = 70; + } + else if (model->flags & EF_TRACER2) + { + model->particletrail = P_ParticleTypeForName("TR_KNIGHTSPIKE"); + model->traildefaultindex = 238; + } + else if (model->flags & EF_TRACER3) + { + model->particletrail = P_ParticleTypeForName("TR_VORESPIKE"); + model->traildefaultindex = 154; + } + else if (model->flags & EFH2_BLOODSHOT) //these are the hexen2 ones. + { + model->particletrail = P_ParticleTypeForName("t_bloodshot"); + model->traildefaultindex = 136; + } + else if (model->flags & EFH2_FIREBALL) + { + model->particletrail = P_ParticleTypeForName("t_fireball"); + model->traildefaultindex = 424; + } + else if (model->flags & EFH2_ACIDBALL) + { + model->particletrail = P_ParticleTypeForName("t_acidball"); + model->traildefaultindex = 440; + } + else if (model->flags & EFH2_ICE) + { + model->particletrail = P_ParticleTypeForName("t_ice"); + model->traildefaultindex = 408; + } + else if (model->flags & EFH2_SPIT) + { + model->particletrail = P_ParticleTypeForName("t_spit"); + model->traildefaultindex = 260; + } + else if (model->flags & EFH2_SPELL) + { + model->particletrail = P_ParticleTypeForName("t_spell"); + model->traildefaultindex = 260; + } + else if (model->flags & EFH2_VORP_MISSILE) + { + model->particletrail = P_ParticleTypeForName("t_vorpmissile"); + model->traildefaultindex = 302; + } + else if (model->flags & EFH2_SET_STAFF) + { + model->particletrail = P_ParticleTypeForName("t_setstaff"); + model->traildefaultindex = 424; + } + else if (model->flags & EFH2_MAGICMISSILE) + { + model->particletrail = P_ParticleTypeForName("t_magicmissile"); + model->traildefaultindex = 149; + } + else if (model->flags & EFH2_BONESHARD) + { + model->particletrail = P_ParticleTypeForName("t_boneshard"); + model->traildefaultindex = 384; + } + else if (model->flags & EFH2_SCARAB) + { + model->particletrail = P_ParticleTypeForName("t_scarab"); + model->traildefaultindex = 254; + } + else + model->particletrail = P_INVALID; +} diff --git a/engine/client/render.h b/engine/client/render.h index 824cfe65c..7e52ed37a 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -54,6 +54,7 @@ typedef enum { RT_MAX_REF_ENTITY_TYPE } refEntityType_t; +#define MAX_BONE_CONTROLLERS 5 typedef struct entity_s { int keynum; // for matching entities in different frames @@ -68,14 +69,10 @@ typedef struct entity_s vec3_t oldangles; struct model_s *model; // NULL = no model - int frame; int skinnum; // for Alias models struct player_info_s *scoreboard; // identify player - float frame1time; - float frame2time; - struct efrag_s *efrag; // linked list of efrags (FIXME) int visframe; // last frame this entity was // found in an active leaf @@ -90,7 +87,24 @@ typedef struct entity_s // that splits bmodel, or NULL if // not split - float bonecontrols[4]; + int frame1; + int frame2; + float frame1time; + float frame2time; + float lerpfrac; + +#ifdef HALFLIFEMODELS + float subblendfrac; //hl models are weird + float bonecontrols[MAX_BONE_CONTROLLERS]; //hl special bone controllers + float basesubblendfrac;//hl models are weird +#endif + + int baseframe1; //used to control legs animations + int baseframe2; + float baseframe1time; + float baseframe2time; + float baselerpfrac;// + int basebone; //the base frame fills bones up to this one (thus if 0, base sequence is not used). int flags; @@ -114,8 +128,6 @@ typedef struct entity_s #ifdef SWQUAKE struct palremap_s *palremap; #endif - float lerpfrac; - int oldframe; } entity_t; // !!! if this is changed, it must be changed in asm_draw.h too !!! diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 14594c69c..d5baa24e9 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -705,7 +705,7 @@ void Renderer_Init(void) Cmd_AddCommand("bul_make", R_BulletenForce_f); - P_InitParticles(); + P_InitParticleSystem(); R_InitTextures(); RQ_Init(); } @@ -2216,7 +2216,7 @@ mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) float *pintervals, fullinterval, targettime, time; psprite = currententity->model->cache.data; - frame = currententity->frame; + frame = currententity->frame1; if ((frame >= psprite->numframes) || (frame < 0)) { @@ -2368,7 +2368,7 @@ texture_t *R_TextureAnimation (texture_t *base) int reletive; int count; - if (currententity->frame) + if (currententity->frame1) { if (base->alternate_anims) base = base->alternate_anims; diff --git a/engine/client/renderque.h b/engine/client/renderque.h index d9de937f8..f1174d77c 100644 --- a/engine/client/renderque.h +++ b/engine/client/renderque.h @@ -1,3 +1,6 @@ +#ifndef RENDERQUE_H +#define RENDERQUE_H + void RQ_AddDistReorder(void (*render) (void *, void *), void *data1, void *data2, float *pos); void RQ_RenderDistAndClear(void); @@ -9,3 +12,5 @@ typedef struct renderque_s void *data1; void *data2; } renderque_t; + +#endif diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 02a63e002..2551201a9 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -29,6 +29,7 @@ cvar_t scr_scoreboard_newstyle = SCVAR("scr_scoreboard_newstyle", "1"); // New s cvar_t scr_scoreboard_showfrags = SCVAR("scr_scoreboard_showfrags", "0"); cvar_t scr_scoreboard_teamscores = SCVAR("scr_scoreboard_teamscores", "1"); cvar_t scr_scoreboard_titleseperator = SCVAR("scr_scoreboard_titleseperator", "1"); +cvar_t sbar_teamstatus = SCVAR("sbar_teamstatus", "1"); //=========================================== //rogue changed and added defines @@ -74,6 +75,8 @@ int sb_hexen2_cur_item;//hexen2 hud qboolean sb_hexen2_extra_info;//show the extra stuff float sb_hexen2_item_time; +qboolean sbar_parsingteamstatuses; //so we don't eat it if its not displayed + #define STAT_MINUS 10 // num frame for '-' stats digit mpic_t *sb_nums[2][11]; mpic_t *sb_colon, *sb_slash; @@ -236,6 +239,17 @@ void Draw_FunString(int x, int y, unsigned char *str) x += 8; continue; } + if (*str == '&' && str[1] == 'c') + { + // ezQuake color codes + if (ishexcode(str[2]) && ishexcode(str[3]) && ishexcode(str[4])) + { + // Just strip it for now + // TODO: Colorize the console properly + str += 5; + continue; + } + } messedup: Draw_ColouredCharacter (x, y, (*str++) | ext); x += 8; @@ -1040,6 +1054,8 @@ void Sbar_Init (void) Cvar_Register(&scr_scoreboard_teamscores, "Scoreboard settings"); Cvar_Register(&scr_scoreboard_titleseperator, "Scoreboard settings"); + Cvar_Register(&sbar_teamstatus, "Status bar settings"); + Cmd_AddCommand ("+showscores", Sbar_ShowScores); Cmd_AddCommand ("-showscores", Sbar_DontShowScores); @@ -1962,10 +1978,11 @@ void Sbar_Hexen2DrawExtra (int pnum) float val; char *pclassname[] = { "Unknown", - "Barbarian", - "Crusader", "Paladin", - "Assasin" + "Crusader", + "Necromancer", + "Assasin", + "Demoness" }; if (!sb_hexen2_extra_info) @@ -2045,7 +2062,7 @@ void Sbar_Hexen2DrawExtra (int pnum) } } - Sbar_DrawPic(134, 50, Draw_CachePic(va("gfx/cport%d.lmp", pclass))); + Sbar_DrawPic(134, 50, Draw_SafeCachePic(va("gfx/cport%d.lmp", pclass))); } void Sbar_Hexen2DrawBasic(int pnum) @@ -2104,6 +2121,121 @@ void Sbar_Hexen2DrawBasic(int pnum) Sbar_Hexen2DrawItem(pnum, 144, 3, sb_hexen2_cur_item); } + + +void Sbar_DrawTeamStatus(void) +{ + int p; + int y; + int track; + + if (!sbar_teamstatus.value) + return; + y = -32; + + track = Cam_TrackNum(0); + if (track == -1 || !cl.spectator) + track = cl.playernum[0]; + + for (p = 0; p < MAX_CLIENTS; p++) + { + if (cl.playernum[0] == p) //self is not shown + continue; + if (track == p) //nor is the person you are tracking + continue; + + if (!*cl.players[p].teamstatus) //only show them if they have something. no blank lines thanks + continue; + if (strcmp(cl.players[p].team, cl.players[track].team)) + continue; + + if (*cl.players[p].name) + { + Sbar_DrawFunString (0, y, cl.players[p].teamstatus); + y-=8; + } + } + sbar_parsingteamstatuses = true; +} + +qboolean Sbar_UpdateTeamStatus(player_info_t *player, char *status) +{ + qboolean aswhite = false; + char *outb; + int outlen; + char *msgstart; + char *ledstatus; + + if (*status != '\r')// && !(strchr(status, 0x86) || strchr(status, 0x87) || strchr(status, 0x88) || strchr(status, 0x89))) + { + if (*status != 'x' || status[1] != '\r') + return false; + status++; + } + + if (*status == '\r') + { + while (*status == ' ' || *status == '\r') + status++; + ledstatus = status; + if (*(unsigned char*)ledstatus >= 0x86 && *(unsigned char*)ledstatus <= 0x89) + { + msgstart = strchr(status, ':'); + if (!status) + return false; + if (msgstart) + status = msgstart+1; + else + ledstatus = NULL; + } + else + ledstatus = NULL; + } + else + ledstatus = NULL; + + while (*status == ' ' || *status == '\r') + status++; + + //fixme: handle { and } stuff (assume red?) + outb = player->teamstatus; + outlen = sizeof(player->teamstatus)-1; + if (ledstatus) + { + *outb++ = *ledstatus; + outlen--; + } + + while(outlen>0 && *status) + { + if (*status == '{') + { + aswhite=true; + status++; + continue; + } + if (aswhite) + { + if (*status == '}') + { + aswhite = false; + status++; + continue; + } + *outb++ = *status++; + } + else + *outb++ = *status++|128; + outlen--; + } + + *outb = '\0'; + + if (sbar_teamstatus.value == 2) + return sbar_parsingteamstatuses; + return false; +} + /* =============== Sbar_Draw @@ -2121,6 +2253,8 @@ void Sbar_Draw (void) if ((sb_updates >= vid.numpages) && !headsup) return; + sbar_parsingteamstatuses = false; + #ifdef Q2CLIENT if (cls.protocol == CP_QUAKE2) @@ -2263,6 +2397,8 @@ void Sbar_Draw (void) #endif + if (sb_lines > 0) + Sbar_DrawTeamStatus(); if (sb_lines > 0 && cl.deathmatch) Sbar_MiniDeathmatchOverlay (); diff --git a/engine/client/sbar.h b/engine/client/sbar.h index 1def9e543..af1e76ac8 100644 --- a/engine/client/sbar.h +++ b/engine/client/sbar.h @@ -26,6 +26,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. extern int sb_lines; // scan lines to draw void Sbar_Init (void); +struct player_info_s; +qboolean Sbar_UpdateTeamStatus(struct player_info_s *player, char *status); #ifdef RGLQUAKE void Sbar_ReInit (void); #endif diff --git a/engine/client/skin.c b/engine/client/skin.c index 4f25ebab4..e955b65ff 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -160,8 +160,8 @@ void Skin_Find (player_info_t *sc) model = Mod_ForName(va("players/%s/tris.mdl", name), false); else #endif - model = Mod_ForName(va("models/players/%s.mdl", name), false); - if (model->type == mod_dummy) + model = NULL;//Mod_ForName(va("models/players/%s.mdl", name), false); + if (model && model->type == mod_dummy) model = NULL; *s = '/'; } @@ -533,7 +533,7 @@ void Skin_NextDownload (void) if (strchr(sc->skin->name, ' ')) //skip over skins using a space continue; - CL_CheckOrEnqueDownloadFile(va("skins/%s.pcx", sc->skin->name), NULL); + CL_CheckOrEnqueDownloadFile(va("skins/%s.pcx", sc->skin->name), NULL, 0); } // now load them in for real diff --git a/engine/client/snd_ov.c b/engine/client/snd_ov.c index 29a149c4a..327103e60 100644 --- a/engine/client/snd_ov.c +++ b/engine/client/snd_ov.c @@ -190,6 +190,16 @@ int OV_DecodeSome(sfx_t *s, int minlength) bytesread = p_ov_read(&dec->vf, dec->mediatemprecode, decodesize, bigendianp, 2, 1, ¤t_section); + if (bytesread <= 0) + { + if (bytesread != 0) //0==eof + { + Con_Printf("ogg decoding failed\n"); + return 1; + } + return 0; + } + SND_ResampleStream(dec->mediatemprecode, dec->srcspeed, 2, diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 8e064a7d4..58d98ca28 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -385,7 +385,7 @@ void *Sys_GetGameAPI(void *parms) else snprintf(name, sizeof(name), "%s/%s/%s", curpath, searchpath, gamename); - game_library = dlopen (name, RTLD_LAZY ); + game_library = dlopen (name, RTLD_LAZY); if (game_library) { GetGameAPI = (void *)dlsym (game_library, "GetGameAPI"); @@ -402,6 +402,34 @@ void *Sys_GetGameAPI(void *parms) return 0; } +void Sys_CloseLibrary(dllhandle_t *lib) +{ + dlclose((void*)lib) +} +dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs) +{ + int i; + HMODULE lib; + + lib = dlopen (name, RTLD_LAZY); + if (!lib) + return NULL; + + for (i = 0; funcs[i].name; i++) + { + *funcs[i].funcptr = dlsym(lib, funcs[i].name); + if (!*funcs[i].funcptr) + break; + } + if (funcs[i].name) + { + Sys_CloseLibrary((dllhandle_t*)lib); + lib = NULL; + } + + return (dllhandle_t*)lib; +} + // ======================================================================= // Sleeps for microseconds // ======================================================================= diff --git a/engine/client/sys_morphos.c b/engine/client/sys_morphos.c index 63a75fbe8..929a82e46 100755 --- a/engine/client/sys_morphos.c +++ b/engine/client/sys_morphos.c @@ -348,6 +348,34 @@ void Sys_UnloadGame(void) } } +void Sys_CloseLibrary(dllhandle_t *lib) +{ + dlclose((void*)lib) +} +dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs) +{ + int i; + HMODULE lib; + + lib = dlopen (name, RTLD_LAZY); + if (!lib) + return NULL; + + for (i = 0; funcs[i].name; i++) + { + *funcs[i].funcptr = dlsym(lib, funcs[i].name); + if (!*funcs[i].funcptr) + break; + } + if (funcs[i].name) + { + Sys_CloseLibrary((dllhandle_t*)lib); + lib = NULL; + } + + return (dllhandle_t*)lib; +} + int main(int argc, char **argv) { double oldtime, newtime; diff --git a/engine/client/sys_sdl.c b/engine/client/sys_sdl.c index 541f05efb..269580763 100644 --- a/engine/client/sys_sdl.c +++ b/engine/client/sys_sdl.c @@ -5,6 +5,8 @@ #include #endif +#include + #ifndef WIN32 #include @@ -149,6 +151,33 @@ void *Sys_GetGameAPI (void *parms) } +void Sys_CloseLibrary(dllhandle_t *lib) +{ + SDL_UnloadObject((void*)lib) +} +dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs) +{ + int i; + void *lib; + + lib = SDL_LoadObject(name); + if (!lib) + return NULL; + + for (i = 0; funcs[i].name; i++) + { + *funcs[i].funcptr = SDL_LoadFunction(lib, funcs[i].name); + if (!*funcs[i].funcptr) + break; + } + if (funcs[i].name) + { + Sys_CloseLibrary((dllhandle_t*)lib); + lib = NULL; + } + + return (dllhandle_t*)lib; +} //used to see if a file exists or not. diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index c40354ae5..bd817a66f 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -38,6 +38,34 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif +void Sys_CloseLibrary(dllhandle_t *lib) +{ + FreeLibrary((HMODULE)lib); +} +dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs) +{ + int i; + HMODULE lib; + + lib = LoadLibrary(name); + if (!lib) + return NULL; + + for (i = 0; funcs[i].name; i++) + { + *funcs[i].funcptr = GetProcAddress(lib, funcs[i].name); + if (!*funcs[i].funcptr) + break; + } + if (funcs[i].name) + { + Sys_CloseLibrary((dllhandle_t*)lib); + lib = NULL; + } + + return (dllhandle_t*)lib; +} + static HINSTANCE game_library; @@ -457,7 +485,7 @@ void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length) DWORD flOldProtect; //@@@ copy on write or just read-write? - if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect)) + if (!VirtualProtect((LPVOID)startaddr, length, PAGE_EXECUTE_READWRITE, &flOldProtect)) { char str[1024]; diff --git a/engine/client/valid.c b/engine/client/valid.c index 2c73f267b..c7e5c5bce 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -65,8 +65,8 @@ static void Validation_Version(void) { char sr[256]; char *s = sr; - char *auth = ""; char authbuf[256]; + char *auth = authbuf; extern cvar_t r_shadow_realtime_world, r_drawflat; diff --git a/engine/client/view.c b/engine/client/view.c index 0c9fe4fbc..6b07fa4f5 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -1198,7 +1198,7 @@ void V_CalcRefdef (int pnum) view->model = NULL; else view->model = cl.model_precache[cl.stats[pnum][STAT_WEAPON]]; - view->frame = view_message?view_message->weaponframe:0; + view->frame1 = view_message?view_message->weaponframe:0; #ifdef SWQUAKE view->palremap = D_IdentityRemap(); #endif diff --git a/engine/client/wad.c b/engine/client/wad.c index da49aed18..1d5c0cae9 100644 --- a/engine/client/wad.c +++ b/engine/client/wad.c @@ -584,7 +584,7 @@ qboolean Wad_NextDownload (void) if (wadname[9]) { if (COM_FCheckExists(wadname+9)) //wad is in root dir, so we don't need to try textures. - CL_CheckOrEnqueDownloadFile(wadname, wadname); + CL_CheckOrEnqueDownloadFile(wadname, wadname, DLLF_REQUIRED); //don't skip this one, or the world is white. } wads[i] = k; diff --git a/engine/client/zqtp.c b/engine/client/zqtp.c index 72c8baf3d..297816cbf 100644 --- a/engine/client/zqtp.c +++ b/engine/client/zqtp.c @@ -76,6 +76,7 @@ void TP_SkinCvar_Callback(struct cvar_s *var, char *oldvalue); TP_CVAR(cl_parseSay, "1"); \ TP_CVAR(cl_parseFunChars, "1"); \ TP_CVAR(cl_triggers, "1"); \ + TP_CVAR(tp_autostatus, "$name $location"); /* things which will not always change, but are useful */ \ TP_CVAR(tp_forceTriggers, "0"); \ TP_CVAR(tp_loadlocs, "1"); \ TP_CVARC(cl_teamskin, "", TP_SkinCvar_Callback); \ @@ -170,6 +171,7 @@ TP_CVARS; extern cvar_t host_mapname; +void TP_UpdateAutoStatus(void); static void TP_FindModelNumbers (void); static void TP_FindPoint (void); char *TP_LocationName (vec3_t location); @@ -179,6 +181,9 @@ char *TP_LocationName (vec3_t location); // this structure is cleared after entering a new map typedef struct tvars_s { + char autoteamstatus[256]; + float autoteamstatus_time; + int health; int items; int olditems; @@ -1084,7 +1089,7 @@ char *Macro_CombinedHealth(void) //work out the max useful armour //this will under-exagurate, due to usage of ceil based on damage m = h/(1-t); - if (a > m) + if (a > m && m > 0) a = m; h = h + a; @@ -2006,6 +2011,7 @@ void TP_NewMap (void) strlcpy (last_map, "", sizeof(last_map)); } + TP_UpdateAutoStatus(); TP_ExecTrigger ("f_newmap"); } @@ -2061,14 +2067,28 @@ int TP_CategorizeMessage (char *s, int *offset, player_info_t **plr) *plr = player; } // check messagemode2 - else if (s[0] == '(' && len+4 <= msglen && !cl.spectator && + else if (s[0] == '(' && len+4 <= msglen && !strncmp(s+len+1, "): ", 3) && !strncmp(name, s+1, len)) { // no team messages in teamplay 0, except for our own - if (i == cl.playernum[SP] || ( cl.teamplay && - !strcmp(cl.players[cl.playernum[SP]].team, player->team)) ) - flags |= TPM_TEAM; + if (cl.spectator) + { + unsigned int track = Cam_TrackNum(0); + if (i == track || ( cl.teamplay && + !strcmp(cl.players[track].team, player->team)) ) + { + flags |= TPM_OBSERVEDTEAM; + } + } + else + { + if (i == cl.playernum[SP] || ( cl.teamplay && + !strcmp(cl.players[cl.playernum[SP]].team, player->team)) ) + { + flags |= TPM_TEAM; + } + } *offset = len + 4; *plr = player; @@ -2997,6 +3017,43 @@ nothing: } +void TP_UpdateAutoStatus(void) +{ + char newstatusbuf[sizeof(vars.autoteamstatus)]; + char *newstatus; + + if (vars.autoteamstatus_time < realtime) + return; + + newstatus = Cmd_ExpandString(tp_autostatus.string, newstatusbuf, sizeof(newstatusbuf), tp_autostatus.restriction, true, true); + newstatus = TP_ParseMacroString(newstatus); + + if (!strcmp(newstatus, vars.autoteamstatus)) + return; + if (!*vars.autoteamstatus && !vars.health) + { + if (cls.state != ca_active) + strcpy(vars.autoteamstatus, newstatus); + return; //don't start it with a death (stops spamming of locations when we originally connect, before spawning) + } + strcpy(vars.autoteamstatus, newstatus); + + if (strchr(tp_autostatus.string, ';')) + return; //don't take risks + + if (tp_autostatus.latched_string) + return; + + if (cl.spectator) //don't spam as spectators, that's just silly + return; + if (!cl.teamplay) //don't spam in deathmatch, that's just pointless + return; + + //the tp code will reexpand it as part of the say team + Cbuf_AddText(va("say_team $\\%s\n", tp_autostatus.string), RESTRICT_LOCAL); + vars.autoteamstatus_time = realtime + 3; +} + void TP_StatChanged (int stat, int value) { int i; @@ -3013,10 +3070,8 @@ void TP_StatChanged (int stat, int value) if (!cl.spectator && CountTeammates()) TP_ExecTrigger ("f_respawn"); } - vars.health = value; - return; } - if (vars.health > 0) + else if (vars.health > 0) { // We have just died vars.droppedweapon = cl.stats[SP][STAT_ACTIVEWEAPON]; @@ -3068,6 +3123,8 @@ void TP_StatChanged (int stat, int value) } vars.stat_framecounts[stat] = cls.framecount; + + TP_UpdateAutoStatus(); } @@ -3430,6 +3487,7 @@ void CL_SayMe_f (void) void CL_SayTeam_f (void) { + vars.autoteamstatus_time = realtime + 3; CL_Say (true, NULL); } #endif diff --git a/engine/common/bothdefs.h b/engine/common/bothdefs.h index a0b58a61d..4aedd3e9f 100644 --- a/engine/common/bothdefs.h +++ b/engine/common/bothdefs.h @@ -94,6 +94,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define MD3MODELS //we DO want to use quake3 alias models. This might be a minimal build, but we still want this. #define PLUGINS + #define PSET_CLASSIC + +#pragma message("temp") +#define CSQC_DAT +#define MENU_DAT + #ifndef SERVERONLY //don't be stupid, stupid. #define CLIENTONLY #endif @@ -135,14 +141,23 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define VM_Q1 //q1 qvm gamecode interface #define TCPCONNECT //a tcpconnect command, that allows the player to connect to tcp-encapsulated qw protocols. + #define IRCCONNECT //an ircconnect command, that allows the player to connect to irc-encapsulated qw protocols... yeah, really. #define PLUGINS +#ifdef _DEBUG +// #define OFFSCREENGECKO +#endif + #define CSQC_DAT //support for csqc #define MENU_DAT //support for menu.dat #define Q3SHADERS + #define PSET_SCRIPT + #define PSET_CLASSIC + //#define PSET_DARKPLACES + // #define VOICECHAT //not added yet. //these things were moved to plugins. @@ -180,6 +195,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #undef RUNTIMELIGHTING #undef Q3SHADERS #undef TERRAIN //not supported + + #undef PSET_SCRIPT + #undef PSET_CLASSIC + #undef PSET_DARKPLACES #endif #ifdef CLIENTONLY //remove optional server components that make no sence on a client only build. #undef Q2SERVER @@ -217,7 +236,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #endif -#if !defined(GLQUAKE) +#if !defined(GLQUAKE) && !defined(SERVERONLY) #undef Q3BSPS #endif #if !defined(Q3BSPS) diff --git a/engine/common/cmd.c b/engine/common/cmd.c index 2e3233178..b4dc3a739 100644 --- a/engine/common/cmd.c +++ b/engine/common/cmd.c @@ -1372,7 +1372,52 @@ void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize) cmd_argc++; } } +} +void Cmd_TokenizePunctation (char *text, char *punctuation) +{ + int i; + +// clear the args from the last string + for (i=0 ; i= text) + { + if (*end == ' ') + end--; + else + break; + } + end++; + *(char*)end = 0; + + } + } forceflags = 0; } diff --git a/engine/common/cmd.h b/engine/common/cmd.h index 87e1b61a1..8e344b45e 100644 --- a/engine/common/cmd.h +++ b/engine/common/cmd.h @@ -107,6 +107,7 @@ void Alias_WipeStuffedAliaes(void); void Cmd_AddMacro(char *s, char *(*f)(void), int disputableintentions); +void Cmd_TokenizePunctation (char *text, char *punctuation); void Cmd_TokenizeString (char *text, qboolean expandmacros, qboolean qctokenize); // Takes a null terminated string. Does not need to be /n terminated. // breaks the string up into arg tokens. diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index d070387dc..58b4ce5ad 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1,4306 +1,4311 @@ -#include "quakedef.h" -#if defined(D3DQUAKE) || defined(RGLQUAKE) || defined(SERVERONLY) - -#ifdef D3DQUAKE -#include "d3dquake.h" -#endif -#ifdef RGLQUAKE -#include "glquake.h" -#endif - -#include "com_mesh.h" - -#ifdef _WIN32 -#include -#else -#include -#endif - -extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models; +#include "quakedef.h" +#if defined(D3DQUAKE) || defined(RGLQUAKE) || defined(SERVERONLY) + +#ifdef D3DQUAKE +#include "d3dquake.h" +#endif +#ifdef RGLQUAKE +#include "glquake.h" +#endif + +#include "com_mesh.h" + +#ifdef _WIN32 +#include +#else +#include +#endif + +extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models; extern cvar_t r_noaliasshadows; -extern cvar_t r_skin_overlays; -extern cvar_t mod_md3flags; - - -extern model_t *loadmodel; -extern char loadname[]; - - - -typedef struct -{ - char *name; - float furthestallowedextremety; //this field is the combined max-min square, added together - //note that while this allows you to move models about a little, you cannot resize the visible part -} clampedmodel_t; - -//these should be rounded up slightly. -//really this is only to catch spiked models. This doesn't prevent more visible models, just bigger ones. -clampedmodel_t clampedmodel[] = { - {"maps/b_bh100.bsp", 3440}, - {"progs/player.mdl", 22497}, - {"progs/eyes.mdl", 755}, - {"progs/gib1.mdl", 374}, - {"progs/gib2.mdl", 1779}, - {"progs/gib3.mdl", 2066}, - {"progs/bolt2.mdl", 1160}, - {"progs/end1.mdl", 764}, - {"progs/end2.mdl", 981}, - {"progs/end3.mdl", 851}, - {"progs/end4.mdl", 903}, - {"progs/g_shot.mdl", 3444}, - {"progs/g_nail.mdl", 2234}, - {"progs/g_nail2.mdl", 3660}, - {"progs/g_rock.mdl", 3441}, - {"progs/g_rock2.mdl", 3660}, - {"progs/g_light.mdl", 2698}, - {"progs/invisibl.mdl", 196}, - {"progs/quaddama.mdl", 2353}, - {"progs/invulner.mdl", 2746}, - {"progs/suit.mdl", 3057}, - {"progs/missile.mdl", 416}, - {"progs/grenade.mdl", 473}, - {"progs/spike.mdl", 112}, - {"progs/s_spike.mdl", 112}, - {"progs/backpack.mdl", 1117}, - {"progs/armor.mdl", 2919}, - {"progs/s_bubble.spr", 100}, - {"progs/s_explod.spr", 1000}, - - //and now TF models -#ifndef _MSC_VER -#warning FIXME: these are placeholders -#endif - {"progs/disp.mdl", 3000}, - {"progs/tf_flag.mdl", 3000}, - {"progs/tf_stan.mdl", 3000}, - {"progs/turrbase.mdl", 3000}, - {"progs/turrgun.mdl", 3000} -}; - -#ifdef SKELETALMODELS - -static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, float bonepose[MAX_BONES][12]) -{ - int i, k, b; - float *matrix, m[12]; - - if (poses == 1) - { - // vertex weighted skeletal - // interpolate matrices and concatenate them to their parents - for (i = 0;i < bonecount;i++) - { - matrix = pose[0] + i*12; - - if (bones[i].parent >= 0) - R_ConcatTransforms((void*)bonepose[bones[i].parent], (void*)matrix, (void*)bonepose[i]); - else - for (k = 0;k < 12;k++) //parentless - bonepose[i][k] = matrix[k]; - } - } - else - { - // vertex weighted skeletal - // interpolate matrices and concatenate them to their parents - for (i = 0;i < bonecount;i++) - { - for (k = 0;k < 12;k++) - m[k] = 0; - for (b = 0;b < poses;b++) - { - matrix = pose[b] + i*12; - - for (k = 0;k < 12;k++) - m[k] += matrix[k] * plerp[b]; - } - if (bones[i].parent >= 0) - R_ConcatTransforms((void*)bonepose[bones[i].parent], (void*)m, (void*)bonepose[i]); - else - for (k = 0;k < 12;k++) //parentless - bonepose[i][k] = m[k]; - } - } -} -static void R_TransformVerticies(float bonepose[MAX_BONES][12], galisskeletaltransforms_t *weights, int numweights, float *xyzout) -{ - int i; - float *out, *matrix; - - galisskeletaltransforms_t *v = weights; - for (i = 0;i < numweights;i++, v++) - { - out = xyzout + v->vertexindex * 3; - matrix = bonepose[v->boneindex]; - // FIXME: this can very easily be optimized with SSE or 3DNow - out[0] += v->org[0] * matrix[0] + v->org[1] * matrix[1] + v->org[2] * matrix[ 2] + v->org[3] * matrix[ 3]; - out[1] += v->org[0] * matrix[4] + v->org[1] * matrix[5] + v->org[2] * matrix[ 6] + v->org[3] * matrix[ 7]; - out[2] += v->org[0] * matrix[8] + v->org[1] * matrix[9] + v->org[2] * matrix[10] + v->org[3] * matrix[11]; - } -} -#ifndef SERVERONLY -static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, galisskeletaltransforms_t *weights, int numweights, qboolean usehierarchy) -{ - float bonepose[MAX_BONES][12]; - - int i, k, l; - - if (usehierarchy) - R_LerpBones(plerp, pose, poses, bones, bonecount, bonepose); - else - { - if (poses == 1) - memcpy(bonepose, pose[0], sizeof(float)*12*bonecount); - else if (poses == 2) - { - for (i = 0; i < bonecount*12; i++) - { - ((float*)bonepose)[i] = pose[0][i]*plerp[0] + pose[1][i]*plerp[1]; - } - } - else - { - for (i = 0; i < bonecount; i++) - { - for (l = 0; l < 12; l++) - bonepose[i][l] = 0; - for (k = 0; k < poses; k++) - { - for (l = 0; l < 12; l++) - bonepose[i][l] += pose[k][i*12+l] * plerp[k]; - } - } - } - } - - // blend the vertex bone weights -// memset(outhead, 0, mesh->numvertexes * sizeof(mesh->xyz_array[0])); - - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->normals_array[i][0] = 0; - mesh->normals_array[i][1] = 0; - mesh->normals_array[i][2] = 1; -/* - mesh->colors_array[i][0] = ambientlight[0]; - mesh->colors_array[i][1] = ambientlight[1]; - mesh->colors_array[i][2] = ambientlight[2]; - mesh->colors_array[i][3] = 255;//alpha; -*/ -/* - mesh->xyz_array[i][0] = 0; - mesh->xyz_array[i][1] = 0; - mesh->xyz_array[i][2] = 0; - mesh->xyz_array[i][3] = 1; - */ - } - mesh->colors_array = NULL; - - memset(mesh->xyz_array, 0, mesh->numvertexes*sizeof(vec3_t)); - R_TransformVerticies(bonepose, weights, numweights, (float*)mesh->xyz_array); - - - - -#if 0 //draws the bones - qglColor3f(1, 0, 0); - { - int i; - int p; - vec3_t org, dest; - - qglBegin(GL_LINES); - for (i = 0; i < bonecount; i++) - { - p = bones[i].parent; - if (p < 0) - p = 0; - qglVertex3f(bonepose[i][3], bonepose[i][7], bonepose[i][11]); - qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); - } - qglEnd(); - qglBegin(GL_LINES); - for (i = 0; i < bonecount; i++) - { - p = bones[i].parent; - if (p < 0) - p = 0; - org[0] = bonepose[i][3]; org[1] = bonepose[i][7]; org[2] = bonepose[i][11]; - qglVertex3fv(org); - qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); - dest[0] = org[0]+bonepose[i][0];dest[1] = org[1]+bonepose[i][1];dest[2] = org[2]+bonepose[i][2]; - qglVertex3fv(org); - qglVertex3fv(dest); - qglVertex3fv(dest); - qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); - dest[0] = org[0]+bonepose[i][4];dest[1] = org[1]+bonepose[i][5];dest[2] = org[2]+bonepose[i][6]; - qglVertex3fv(org); - qglVertex3fv(dest); - qglVertex3fv(dest); - qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); - dest[0] = org[0]+bonepose[i][8];dest[1] = org[1]+bonepose[i][9];dest[2] = org[2]+bonepose[i][10]; - qglVertex3fv(org); - qglVertex3fv(dest); - qglVertex3fv(dest); - qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); - } - qglEnd(); - -// mesh->numindexes = 0; //don't draw this mesh, as that would obscure the bones. :( - } -#endif -} -#endif -#endif - - - - - -#if defined(D3DQUAKE) || defined(RGLQUAKE) - -extern entity_t *currententity; -int numTempColours; -byte_vec4_t *tempColours; - -int numTempVertexCoords; -vec3_t *tempVertexCoords; - -int numTempNormals; -vec3_t *tempNormals; - -vec3_t shadevector; -vec3_t ambientlight; -vec3_t shadelight; - -static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float lerp, qbyte alpha, float expand, qboolean nolightdir) -{ - extern cvar_t r_nolerp, r_nolightdir; - float blerp = 1-lerp; - int i; - float l; - int temp; - vec3_t *p1v, *p2v; - vec3_t *p1n, *p2n; - p1v = (vec3_t *)((char *)p1 + p1->ofsverts); - p2v = (vec3_t *)((char *)p2 + p2->ofsverts); - - p1n = (vec3_t *)((char *)p1 + p1->ofsnormals); - p2n = (vec3_t *)((char *)p2 + p2->ofsnormals); - - if (p1v == p2v || r_nolerp.value) - { - mesh->normals_array = p1n; - mesh->xyz_array = p1v; - if (r_nolightdir.value || nolightdir) - { - mesh->colors_array = NULL; - } - else - { - for (i = 0; i < mesh->numvertexes; i++) - { - l = DotProduct(mesh->normals_array[i], shadevector); - - temp = l*ambientlight[0]+shadelight[0]; - if (temp < 0) temp = 0; - else if (temp > 255) temp = 255; - mesh->colors_array[i][0] = temp; - - temp = l*ambientlight[1]+shadelight[1]; - if (temp < 0) temp = 0; - else if (temp > 255) temp = 255; - mesh->colors_array[i][1] = temp; - - temp = l*ambientlight[2]+shadelight[2]; - if (temp < 0) temp = 0; - else if (temp > 255) temp = 255; - mesh->colors_array[i][2] = temp; - - mesh->colors_array[i][3] = alpha; - } - } - } - else - { - if (r_nolightdir.value || nolightdir) - { - mesh->colors_array = NULL; - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; - mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; - mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; - - mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; - mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; - mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; - } - } - else - { - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; - mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; - mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; - - mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; - mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; - mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; - - l = DotProduct(mesh->normals_array[i], shadevector); - temp = l*ambientlight[0]+shadelight[0]; - if (temp < 0) temp = 0; - else if (temp > 255) temp = 255; - mesh->colors_array[i][0] = temp; - - temp = l*ambientlight[1]+shadelight[1]; - if (temp < 0) temp = 0; - else if (temp > 255) temp = 255; - mesh->colors_array[i][1] = temp; - - temp = l*ambientlight[2]+shadelight[2]; - if (temp < 0) temp = 0; - else if (temp > 255) temp = 255; - mesh->colors_array[i][2] = temp; - - mesh->colors_array[i][3] = alpha; - } - } - } - if (expand) - { - if (mesh->xyz_array == p1v) - { - mesh->xyz_array = tempVertexCoords; - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->xyz_array[i][0] = p1v[i][0] + mesh->normals_array[i][0]*expand; - mesh->xyz_array[i][1] = p1v[i][1] + mesh->normals_array[i][1]*expand; - mesh->xyz_array[i][2] = p1v[i][2] + mesh->normals_array[i][2]*expand; - } - - } - else - { - for (i = 0; i < mesh->numvertexes; i++) - { - mesh->xyz_array[i][0] += mesh->normals_array[i][0]*expand; - mesh->xyz_array[i][1] += mesh->normals_array[i][1]*expand; - mesh->xyz_array[i][2] += mesh->normals_array[i][2]*expand; - } - } - } -} - -qboolean R_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int frame1, int frame2, float lerp, float alpha, float fg1time, float fg2time, qboolean nolightdir) -{ - galiasgroup_t *g1, *g2; - - if (!inf->groups) - { - Con_DPrintf("Model with no frames (%s)\n", currententity->model->name); - return false; - } - if (frame1 < 0) - { - Con_DPrintf("Negative frame (%s)\n", currententity->model->name); - frame1 = 0; - } - if (frame2 < 0) - { - Con_DPrintf("Negative frame (%s)\n", currententity->model->name); - frame2 = frame1; - } - if (frame1 >= inf->groups) - { - Con_DPrintf("Too high frame %i (%s)\n", frame1, currententity->model->name); - frame1 %= inf->groups; - } - if (frame2 >= inf->groups) - { - Con_DPrintf("Too high frame %i (%s)\n", frame2, currententity->model->name); - frame2 = frame1; - } - - if (lerp <= 0) - frame2 = frame1; - else if (lerp >= 1) - frame1 = frame2; - - if (numTempColours < inf->numverts) - { - if (tempColours) - BZ_Free(tempColours); - tempColours = BZ_Malloc(sizeof(*tempColours)*inf->numverts); - numTempColours = inf->numverts; - } - if (numTempNormals < inf->numverts) - { - if (tempNormals) - BZ_Free(tempNormals); - tempNormals = BZ_Malloc(sizeof(*tempNormals)*inf->numverts); - numTempNormals = inf->numverts; - } - if (numTempVertexCoords < inf->numverts) - { - if (tempVertexCoords) - BZ_Free(tempVertexCoords); - tempVertexCoords = BZ_Malloc(sizeof(*tempVertexCoords)*inf->numverts); - numTempVertexCoords = inf->numverts; - } - - mesh->numvertexes = inf->numverts; - mesh->indexes = (index_t*)((char *)inf + inf->ofs_indexes); - mesh->numindexes = inf->numindexes; - - if (inf->sharesverts) - return false; //don't generate the new vertex positions. We still have them all. - -#ifndef SERVERONLY - mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); - mesh->lmst_array = NULL; - mesh->colors_array = tempColours; - mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); - mesh->normals_array = tempNormals; -#endif - mesh->xyz_array = tempVertexCoords; - - g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); - g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); - -//we don't support meshes with one pose skeletal and annother not. -//we don't support meshes with one group skeletal and annother not. - -#ifdef SKELETALMODELS - if (inf->numbones) - { - int l=0; - float plerp[4]; - float *pose[4]; - float mlerp; //minor lerp, poses within a group. - qboolean hirachy; - - if (g1->isheirachical != g2->isheirachical || lerp < 0) - lerp = 0; - hirachy = g1->isheirachical; - - mlerp = (fg1time)*g1->rate; - frame1=mlerp; - frame2=frame1+1; - mlerp-=frame1; - if (g1->loop) - { - frame1=frame1%g1->numposes; - frame2=frame2%g1->numposes; - } - else - { - frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; - frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; - } - - plerp[l] = (1-mlerp)*(1-lerp); - if (plerp[l]>0) - pose[l++] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); - plerp[l] = (mlerp)*(1-lerp); - if (plerp[l]>0) - pose[l++] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); - - if (lerp) - { - mlerp = (fg2time)*g2->rate; - frame1=mlerp; - frame2=frame1+1; - mlerp-=frame1; - if (g2->loop) - { - frame1=frame1%g2->numposes; - frame2=frame2%g2->numposes; - } - else - { - frame1=(frame1>g2->numposes-1)?g2->numposes-1:frame1; - frame2=(frame2>g2->numposes-1)?g2->numposes-1:frame2; - } - - plerp[l] = (1-mlerp)*(lerp); - if (plerp[l]>0) - pose[l++] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); - plerp[l] = (mlerp)*(lerp); - if (plerp[l]>0) - pose[l++] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); - } -/* - pose[0] = (float *)((char *)g1 + g1->poseofs); - plerp[0] = 1; - plerp[1] = 0; - plerp[3] = 0; - plerp[4] = 0; - l = 1; -*/ - R_BuildSkeletalMesh(mesh, plerp, pose, l, (galiasbone_t *)((char*)inf+inf->ofsbones), inf->numbones, (galisskeletaltransforms_t *)((char*)inf+inf->ofstransforms), inf->numtransforms, hirachy); - return false; - } -#endif - - if (g1 == g2) //lerping within group is only done if not changing group - { - lerp = fg1time*g1->rate; - if (lerp < 0) lerp = 0; //hrm - frame1=lerp; - frame2=frame1+1; - lerp-=frame1; - if (g1->loop) - { - frame1=frame1%g1->numposes; - frame2=frame2%g1->numposes; - } - else - { - frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; - frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; - } - } - else //don't bother with a four way lerp. Yeah, this will produce jerkyness with models with just framegroups. - { - frame1=0; - frame2=0; - } - - R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), - (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), - 1-lerp, (qbyte)(alpha*255), currententity->fatness, nolightdir); - - return true; //to allow the mesh to be dlighted. -} - -#endif - - - - - - - - - - - -//The whole reason why model loading is supported in the server. -qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) -{ - galiasinfo_t *mod = Mod_Extradata(model); - galiasgroup_t *group; - galiaspose_t *pose; - int i; - - float *p1, *p2, *p3; - vec3_t edge1, edge2, edge3; - vec3_t normal; - vec3_t edgenormal; - - float planedist; - float diststart, distend; - - float frac; -// float temp; - - vec3_t impactpoint; - - float *posedata; - int *indexes; - - while(mod) - { - indexes = (int*)((char*)mod + mod->ofs_indexes); - group = (galiasgroup_t*)((char*)mod + mod->groupofs); - pose = (galiaspose_t*)((char*)&group[0] + group[0].poseofs); - posedata = (float*)((char*)pose + pose->ofsverts); -#ifdef SKELETALMODELS - if (mod->numbones && !mod->sharesverts) - { - float bonepose[MAX_BONES][12]; - posedata = alloca(mod->numverts*sizeof(vec3_t)); - frac = 1; - if (group->isheirachical) - { - if (!mod->sharesbones) - R_LerpBones(&frac, (float**)posedata, 1, (galiasbone_t*)((char*)mod + mod->ofsbones), mod->numbones, bonepose); - R_TransformVerticies(bonepose, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata); - } - else - R_TransformVerticies((void*)posedata, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata); - } -#endif - - for (i = 0; i < mod->numindexes; i+=3) - { - p1 = posedata + 3*indexes[i+0]; - p2 = posedata + 3*indexes[i+1]; - p3 = posedata + 3*indexes[i+2]; - - VectorSubtract(p1, p2, edge1); - VectorSubtract(p3, p2, edge2); - CrossProduct(edge1, edge2, normal); - - planedist = DotProduct(p1, normal); - diststart = DotProduct(start, normal); - if (diststart <= planedist) - continue; //start on back side. - distend = DotProduct(end, normal); - if (distend >= planedist) - continue; //end on front side (as must start - doesn't cross). - - frac = (diststart - planedist) / (diststart-distend); - - if (frac >= trace->fraction) //already found one closer. - continue; - - impactpoint[0] = start[0] + frac*(end[0] - start[0]); - impactpoint[1] = start[1] + frac*(end[1] - start[1]); - impactpoint[2] = start[2] + frac*(end[2] - start[2]); - -// temp = DotProduct(impactpoint, normal)-planedist; - - CrossProduct(edge1, normal, edgenormal); -// temp = DotProduct(impactpoint, edgenormal)-DotProduct(p2, edgenormal); - if (DotProduct(impactpoint, edgenormal) > DotProduct(p2, edgenormal)) - continue; - - CrossProduct(normal, edge2, edgenormal); - if (DotProduct(impactpoint, edgenormal) > DotProduct(p3, edgenormal)) - continue; - - VectorSubtract(p1, p3, edge3); - CrossProduct(normal, edge3, edgenormal); - if (DotProduct(impactpoint, edgenormal) > DotProduct(p1, edgenormal)) - continue; - - trace->fraction = frac; - VectorCopy(impactpoint, trace->endpos); - VectorCopy(normal, trace->plane.normal); - } - - if (mod->nextsurf) - mod = (galiasinfo_t*)((char*)mod + mod->nextsurf); - else - mod = NULL; - } - - trace->allsolid = false; - - return trace->fraction != 1; -} - - - - -//Common loader function. -static void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) -{ -#ifndef SERVERONLY - //we've got to have this bit - if (loadmodel->engineflags & MDLF_DOCRC) - { - unsigned short crc; - qbyte *p; - int len; - char st[40]; - - QCRC_Init(&crc); - for (len = buffersize, p = buffer; len; len--, p++) - QCRC_ProcessByte(&crc, *p); - - sprintf(st, "%d", (int) crc); - Info_SetValueForKey (cls.userinfo, - (loadmodel->engineflags & MDLF_PLAYER) ? pmodel_name : emodel_name, - st, MAX_INFO_STRING); - - if (cls.state >= ca_connected) - { - CL_SendClientCommand(true, "setinfo %s %d", - (loadmodel->engineflags & MDLF_PLAYER) ? pmodel_name : emodel_name, - (int)crc); - } - - if (!(loadmodel->engineflags & MDLF_PLAYER)) - { //eyes - loadmodel->tainted = (crc != 6967); - } - } -#endif -} - - -static void Mod_ClampModelSize(model_t *mod) -{ -#ifndef SERVERONLY - int i; - - float rad=0, axis; - axis = (mod->maxs[0] - mod->mins[0]); - rad += axis*axis; - axis = (mod->maxs[1] - mod->mins[1]); - rad += axis*axis; - axis = (mod->maxs[2] - mod->mins[2]); - rad += axis*axis; - - if (loadmodel->engineflags & MDLF_DOCRC) - { - if (!strcmp(mod->name, "progs/eyes.mdl")) - { //this is checked elsewhere to make sure the crc matches (this is to make sure the crc check was actually called) - if (mod->type != mod_alias || mod->fromgame != fg_quake) - mod->tainted = true; - } - } - - mod->clampscale = 1; - for (i = 0; i < sizeof(clampedmodel)/sizeof(clampedmodel[0]); i++) - { - if (!strcmp(mod->name, clampedmodel[i].name)) - { - if (rad > clampedmodel[i].furthestallowedextremety) - { - axis = clampedmodel[i].furthestallowedextremety; - mod->clampscale = axis/rad; - Con_DPrintf("\"%s\" will be clamped.\n", mod->name); - } - return; - } - } - - Con_DPrintf("Don't know what size to clamp \"%s\" to (size:%f).\n", mod->name, rad); -#endif -} - -#ifdef RGLQUAKE -static int R_FindTriangleWithEdge ( int *indexes, int numtris, int start, int end, int ignore) -{ - int i; - int match, count; - - count = 0; - match = -1; - - for (i = 0; i < numtris; i++, indexes += 3) - { - if ( (indexes[0] == start && indexes[1] == end) - || (indexes[1] == start && indexes[2] == end) - || (indexes[2] == start && indexes[0] == end) ) { - if (i != ignore) - match = i; - count++; - } else if ( (indexes[1] == start && indexes[0] == end) - || (indexes[2] == start && indexes[1] == end) - || (indexes[0] == start && indexes[2] == end) ) { - count++; - } - } - - // detect edges shared by three triangles and make them seams - if (count > 2) - match = -1; - - return match; -} -static void Mod_BuildTriangleNeighbours ( int *neighbours, int *indexes, int numtris ) -{ - int i, *n; - int *index; - - for (i = 0, index = indexes, n = neighbours; i < numtris; i++, index += 3, n += 3) - { - n[0] = R_FindTriangleWithEdge (indexes, numtris, index[1], index[0], i); - n[1] = R_FindTriangleWithEdge (indexes, numtris, index[2], index[1], i); - n[2] = R_FindTriangleWithEdge (indexes, numtris, index[0], index[2], i); - } -} -#endif -void Mod_CompileTriangleNeighbours(galiasinfo_t *galias) -{ -#ifdef RGLQUAKE - if (qrenderer != QR_OPENGL) - return; - if (r_shadows.value) - { - int *neighbours; - neighbours = Hunk_Alloc(sizeof(int)*galias->numindexes/3*3); - galias->ofs_trineighbours = (qbyte *)neighbours - (qbyte *)galias; - Mod_BuildTriangleNeighbours(neighbours, (int*)((char*)galias + galias->ofs_indexes), galias->numindexes/3); - } -#endif -} - -#if defined(D3DQUAKE) || defined(RGLQUAKE) -/* -================= -Mod_FloodFillSkin - -Fill background pixels so mipmapping doesn't have haloes - Ed -================= -*/ - -typedef struct -{ - short x, y; -} floodfill_t; - -// must be a power of 2 -#define FLOODFILL_FIFO_SIZE 0x1000 -#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1) - -#define FLOODFILL_STEP( off, dx, dy ) \ -{ \ - if (pos[off] == fillcolor) \ - { \ - pos[off] = 255; \ - fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \ - inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \ - } \ - else if (pos[off] != 255) fdc = pos[off]; \ -} - -void Mod_FloodFillSkin( qbyte *skin, int skinwidth, int skinheight ) -{ - qbyte fillcolor = *skin; // assume this is the pixel to fill - floodfill_t fifo[FLOODFILL_FIFO_SIZE]; - int inpt = 0, outpt = 0; - int filledcolor = -1; - int i; - - if (filledcolor == -1) - { - filledcolor = 0; - // attempt to find opaque black - for (i = 0; i < 256; ++i) - if (d_8to24rgbtable[i] == (255 << 0)) // alpha 1.0 - { - filledcolor = i; - break; - } - } - - // can't fill to filled color or to transparent color (used as visited marker) - if ((fillcolor == filledcolor) || (fillcolor == 255)) - { - //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor ); - return; - } - - fifo[inpt].x = 0, fifo[inpt].y = 0; - inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; - - while (outpt != inpt) - { - int x = fifo[outpt].x, y = fifo[outpt].y; - int fdc = filledcolor; - qbyte *pos = &skin[x + skinwidth * y]; - - outpt = (outpt + 1) & FLOODFILL_FIFO_MASK; - - if (x > 0) FLOODFILL_STEP( -1, -1, 0 ); - if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 ); - if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 ); - if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 ); - skin[x + skinwidth * y] = fdc; - } -} -#endif - -//additional skin loading -char **skinfilelist; -int skinfilecount; - -static qboolean VARGS Mod_TryAddSkin(char *skinname, ...) -{ - va_list argptr; - char string[MAX_QPATH]; - - //make sure we don't add it twice - int i; - - - va_start (argptr, skinname); - vsnprintf (string,sizeof(string)-1, skinname,argptr); - va_end (argptr); - string[MAX_QPATH-1] = '\0'; - - for (i = 0; i < skinfilecount; i++) - { - if (!strcmp(skinfilelist[i], string)) - return true; //already added - } - - if (!COM_FCheckExists(string)) - return false; - - skinfilelist = BZ_Realloc(skinfilelist, sizeof(*skinfilelist)*(skinfilecount+1)); - skinfilelist[skinfilecount] = Z_Malloc(strlen(string)+1); - strcpy(skinfilelist[skinfilecount], string); - skinfilecount++; - return true; -} - -int Mod_EnumerateSkins(char *name, int size, void *param) -{ - Mod_TryAddSkin(name); - return true; -} - -int Mod_BuildSkinFileList(char *modelname) -{ - int i; - char skinfilename[MAX_QPATH]; - - //flush the old list - for (i = 0; i < skinfilecount; i++) - { - Z_Free(skinfilelist[i]); - skinfilelist[i] = NULL; - } - skinfilecount=0; - - COM_StripExtension(modelname, skinfilename, sizeof(skinfilename)); - - //try and add numbered skins, and then try fixed names. - for (i = 0; ; i++) - { - if (!Mod_TryAddSkin("%s_%i.skin", modelname, i)) - { - if (i == 0) - { - if (!Mod_TryAddSkin("%s_default.skin", skinfilename, i)) - break; - } - else if (i == 1) - { - if (!Mod_TryAddSkin("%s_blue.skin", skinfilename, i)) - break; - } - else if (i == 2) - { - if (!Mod_TryAddSkin("%s_red.skin", skinfilename, i)) - break; - } - else if (i == 3) - { - if (!Mod_TryAddSkin("%s_green.skin", skinfilename, i)) - break; - } - else if (i == 4) - { - if (!Mod_TryAddSkin("%s_yellow.skin", skinfilename, i)) - break; - } - else - break; - } - } - -// if (strstr(modelname, "lower") || strstr(modelname, "upper") || strstr(modelname, "head")) -// { - COM_EnumerateFiles(va("%s_*.skin", modelname), Mod_EnumerateSkins, NULL); - COM_EnumerateFiles(va("%s_*.skin", skinfilename), Mod_EnumerateSkins, NULL); -// } -// else -// COM_EnumerateFiles("*.skin", Mod_EnumerateSkins, NULL); - - return skinfilecount; -} - - -//This is a hack. It uses an assuption about q3 player models. -void Mod_ParseQ3SkinFile(char *out, char *surfname, char *modelname, int skinnum, char *skinfilename) -{ - const char *f = NULL, *p; - int len; - - if (skinnum >= skinfilecount) - return; - - if (skinfilename) - strcpy(skinfilename, skinfilelist[skinnum]); - - f = COM_LoadTempFile2(skinfilelist[skinnum]); - - while(f) - { - f = COM_ParseToken(f,NULL); - if (!f) - return; - if (!strcmp(com_token, "replace")) - { - f = COM_ParseToken(f, NULL); - - len = strlen(com_token); - - //copy surfname -> out, until we meet the part we need to replace - while(*surfname) - { - if (!strncmp(com_token, surfname, len)) - //found it - { - surfname+=len; - f = COM_ParseToken(f, NULL); - p = com_token; - while(*p) //copy the replacement - *out++ = *p++; - - while(*surfname) //copy the remaining - *out++ = *surfname++; - *out++ = '\0'; //we didn't find it. - return; - } - *out++ = *surfname++; - } - *out++ = '\0'; //we didn't find it. - return; - } - else - { - while(*f == ' ' || *f == '\t') - f++; - if (*f == ',') - { - if (!strcmp(com_token, surfname)) - { - f++; - COM_ParseToken(f, NULL); - strcpy(out, com_token); - return; - } - } - } - - p = strchr(f, '\n'); - if (!p) - f = f+strlen(f); - else - f = p+1; - if (!*f) - break; - } -} - -#if defined(D3DQUAKE) || defined(RGLQUAKE) -void Mod_LoadSkinFile(galiastexnum_t *texnum, char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette) -{ - char shadername[MAX_QPATH]; - Q_strncpyz(shadername, surfacename, sizeof(shadername)); - - Mod_ParseQ3SkinFile(shadername, surfacename, loadmodel->name, skinnumber, NULL); - -#ifdef Q3SHADERS - texnum->shader = R_RegisterSkin(shadername); -#endif - +extern cvar_t r_skin_overlays; +extern cvar_t mod_md3flags; + + +extern model_t *loadmodel; +extern char loadname[]; + + + +typedef struct +{ + char *name; + float furthestallowedextremety; //this field is the combined max-min square, added together + //note that while this allows you to move models about a little, you cannot resize the visible part +} clampedmodel_t; + +//these should be rounded up slightly. +//really this is only to catch spiked models. This doesn't prevent more visible models, just bigger ones. +clampedmodel_t clampedmodel[] = { + {"maps/b_bh100.bsp", 3440}, + {"progs/player.mdl", 22497}, + {"progs/eyes.mdl", 755}, + {"progs/gib1.mdl", 374}, + {"progs/gib2.mdl", 1779}, + {"progs/gib3.mdl", 2066}, + {"progs/bolt2.mdl", 1160}, + {"progs/end1.mdl", 764}, + {"progs/end2.mdl", 981}, + {"progs/end3.mdl", 851}, + {"progs/end4.mdl", 903}, + {"progs/g_shot.mdl", 3444}, + {"progs/g_nail.mdl", 2234}, + {"progs/g_nail2.mdl", 3660}, + {"progs/g_rock.mdl", 3441}, + {"progs/g_rock2.mdl", 3660}, + {"progs/g_light.mdl", 2698}, + {"progs/invisibl.mdl", 196}, + {"progs/quaddama.mdl", 2353}, + {"progs/invulner.mdl", 2746}, + {"progs/suit.mdl", 3057}, + {"progs/missile.mdl", 416}, + {"progs/grenade.mdl", 473}, + {"progs/spike.mdl", 112}, + {"progs/s_spike.mdl", 112}, + {"progs/backpack.mdl", 1117}, + {"progs/armor.mdl", 2919}, + {"progs/s_bubble.spr", 100}, + {"progs/s_explod.spr", 1000}, + + //and now TF models +#ifndef _MSC_VER +#warning FIXME: these are placeholders +#endif + {"progs/disp.mdl", 3000}, + {"progs/tf_flag.mdl", 3000}, + {"progs/tf_stan.mdl", 3000}, + {"progs/turrbase.mdl", 3000}, + {"progs/turrgun.mdl", 3000} +}; + +#ifdef SKELETALMODELS + +static void R_LerpBones(float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, float bonepose[MAX_BONES][12]) +{ + int i, k, b; + float *matrix, m[12]; + + if (poses == 1) + { + // vertex weighted skeletal + // interpolate matrices and concatenate them to their parents + for (i = 0;i < bonecount;i++) + { + matrix = pose[0] + i*12; + + if (bones[i].parent >= 0) + R_ConcatTransforms((void*)bonepose[bones[i].parent], (void*)matrix, (void*)bonepose[i]); + else + for (k = 0;k < 12;k++) //parentless + bonepose[i][k] = matrix[k]; + } + } + else + { + // vertex weighted skeletal + // interpolate matrices and concatenate them to their parents + for (i = 0;i < bonecount;i++) + { + for (k = 0;k < 12;k++) + m[k] = 0; + for (b = 0;b < poses;b++) + { + matrix = pose[b] + i*12; + + for (k = 0;k < 12;k++) + m[k] += matrix[k] * plerp[b]; + } + if (bones[i].parent >= 0) + R_ConcatTransforms((void*)bonepose[bones[i].parent], (void*)m, (void*)bonepose[i]); + else + for (k = 0;k < 12;k++) //parentless + bonepose[i][k] = m[k]; + } + } +} +static void R_TransformVerticies(float bonepose[MAX_BONES][12], galisskeletaltransforms_t *weights, int numweights, float *xyzout) +{ + int i; + float *out, *matrix; + + galisskeletaltransforms_t *v = weights; + for (i = 0;i < numweights;i++, v++) + { + out = xyzout + v->vertexindex * 3; + matrix = bonepose[v->boneindex]; + // FIXME: this can very easily be optimized with SSE or 3DNow + out[0] += v->org[0] * matrix[0] + v->org[1] * matrix[1] + v->org[2] * matrix[ 2] + v->org[3] * matrix[ 3]; + out[1] += v->org[0] * matrix[4] + v->org[1] * matrix[5] + v->org[2] * matrix[ 6] + v->org[3] * matrix[ 7]; + out[2] += v->org[0] * matrix[8] + v->org[1] * matrix[9] + v->org[2] * matrix[10] + v->org[3] * matrix[11]; + } +} +#ifndef SERVERONLY +static void R_BuildSkeletalMesh(mesh_t *mesh, float *plerp, float **pose, int poses, galiasbone_t *bones, int bonecount, galisskeletaltransforms_t *weights, int numweights, qboolean usehierarchy) +{ + float bonepose[MAX_BONES][12]; + + int i, k, l; + + if (usehierarchy) + R_LerpBones(plerp, pose, poses, bones, bonecount, bonepose); + else + { + if (poses == 1) + memcpy(bonepose, pose[0], sizeof(float)*12*bonecount); + else if (poses == 2) + { + for (i = 0; i < bonecount*12; i++) + { + ((float*)bonepose)[i] = pose[0][i]*plerp[0] + pose[1][i]*plerp[1]; + } + } + else + { + for (i = 0; i < bonecount; i++) + { + for (l = 0; l < 12; l++) + bonepose[i][l] = 0; + for (k = 0; k < poses; k++) + { + for (l = 0; l < 12; l++) + bonepose[i][l] += pose[k][i*12+l] * plerp[k]; + } + } + } + } + + // blend the vertex bone weights +// memset(outhead, 0, mesh->numvertexes * sizeof(mesh->xyz_array[0])); + + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->normals_array[i][0] = 0; + mesh->normals_array[i][1] = 0; + mesh->normals_array[i][2] = 1; +/* + mesh->colors_array[i][0] = ambientlight[0]; + mesh->colors_array[i][1] = ambientlight[1]; + mesh->colors_array[i][2] = ambientlight[2]; + mesh->colors_array[i][3] = 255;//alpha; +*/ +/* + mesh->xyz_array[i][0] = 0; + mesh->xyz_array[i][1] = 0; + mesh->xyz_array[i][2] = 0; + mesh->xyz_array[i][3] = 1; + */ + } + mesh->colors_array = NULL; + + memset(mesh->xyz_array, 0, mesh->numvertexes*sizeof(vec3_t)); + R_TransformVerticies(bonepose, weights, numweights, (float*)mesh->xyz_array); + + + + +#if 0 //draws the bones + qglColor3f(1, 0, 0); + { + int i; + int p; + vec3_t org, dest; + + qglBegin(GL_LINES); + for (i = 0; i < bonecount; i++) + { + p = bones[i].parent; + if (p < 0) + p = 0; + qglVertex3f(bonepose[i][3], bonepose[i][7], bonepose[i][11]); + qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); + } + qglEnd(); + qglBegin(GL_LINES); + for (i = 0; i < bonecount; i++) + { + p = bones[i].parent; + if (p < 0) + p = 0; + org[0] = bonepose[i][3]; org[1] = bonepose[i][7]; org[2] = bonepose[i][11]; + qglVertex3fv(org); + qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); + dest[0] = org[0]+bonepose[i][0];dest[1] = org[1]+bonepose[i][1];dest[2] = org[2]+bonepose[i][2]; + qglVertex3fv(org); + qglVertex3fv(dest); + qglVertex3fv(dest); + qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); + dest[0] = org[0]+bonepose[i][4];dest[1] = org[1]+bonepose[i][5];dest[2] = org[2]+bonepose[i][6]; + qglVertex3fv(org); + qglVertex3fv(dest); + qglVertex3fv(dest); + qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); + dest[0] = org[0]+bonepose[i][8];dest[1] = org[1]+bonepose[i][9];dest[2] = org[2]+bonepose[i][10]; + qglVertex3fv(org); + qglVertex3fv(dest); + qglVertex3fv(dest); + qglVertex3f(bonepose[p][3], bonepose[p][7], bonepose[p][11]); + } + qglEnd(); + +// mesh->numindexes = 0; //don't draw this mesh, as that would obscure the bones. :( + } +#endif +} +#endif +#endif + + + + + +#if defined(D3DQUAKE) || defined(RGLQUAKE) + +extern entity_t *currententity; +int numTempColours; +byte_vec4_t *tempColours; + +int numTempVertexCoords; +vec3_t *tempVertexCoords; + +int numTempNormals; +vec3_t *tempNormals; + +vec3_t shadevector; +vec3_t ambientlight; +vec3_t shadelight; + +static void R_LerpFrames(mesh_t *mesh, galiaspose_t *p1, galiaspose_t *p2, float lerp, qbyte alpha, float expand, qboolean nolightdir) +{ + extern cvar_t r_nolerp, r_nolightdir; + float blerp = 1-lerp; + int i; + float l; + int temp; + vec3_t *p1v, *p2v; + vec3_t *p1n, *p2n; + p1v = (vec3_t *)((char *)p1 + p1->ofsverts); + p2v = (vec3_t *)((char *)p2 + p2->ofsverts); + + p1n = (vec3_t *)((char *)p1 + p1->ofsnormals); + p2n = (vec3_t *)((char *)p2 + p2->ofsnormals); + + if (p1v == p2v || r_nolerp.value) + { + mesh->normals_array = p1n; + mesh->xyz_array = p1v; + if (r_nolightdir.value || nolightdir) + { + mesh->colors_array = NULL; + } + else + { + for (i = 0; i < mesh->numvertexes; i++) + { + l = DotProduct(mesh->normals_array[i], shadevector); + + temp = l*ambientlight[0]+shadelight[0]; + if (temp < 0) temp = 0; + else if (temp > 255) temp = 255; + mesh->colors_array[i][0] = temp; + + temp = l*ambientlight[1]+shadelight[1]; + if (temp < 0) temp = 0; + else if (temp > 255) temp = 255; + mesh->colors_array[i][1] = temp; + + temp = l*ambientlight[2]+shadelight[2]; + if (temp < 0) temp = 0; + else if (temp > 255) temp = 255; + mesh->colors_array[i][2] = temp; + + mesh->colors_array[i][3] = alpha; + } + } + } + else + { + if (r_nolightdir.value || nolightdir) + { + mesh->colors_array = NULL; + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; + mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; + mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; + + mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; + mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; + mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; + } + } + else + { + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->normals_array[i][0] = p1n[i][0]*lerp + p2n[i][0]*blerp; + mesh->normals_array[i][1] = p1n[i][1]*lerp + p2n[i][1]*blerp; + mesh->normals_array[i][2] = p1n[i][2]*lerp + p2n[i][2]*blerp; + + mesh->xyz_array[i][0] = p1v[i][0]*lerp + p2v[i][0]*blerp; + mesh->xyz_array[i][1] = p1v[i][1]*lerp + p2v[i][1]*blerp; + mesh->xyz_array[i][2] = p1v[i][2]*lerp + p2v[i][2]*blerp; + + l = DotProduct(mesh->normals_array[i], shadevector); + temp = l*ambientlight[0]+shadelight[0]; + if (temp < 0) temp = 0; + else if (temp > 255) temp = 255; + mesh->colors_array[i][0] = temp; + + temp = l*ambientlight[1]+shadelight[1]; + if (temp < 0) temp = 0; + else if (temp > 255) temp = 255; + mesh->colors_array[i][1] = temp; + + temp = l*ambientlight[2]+shadelight[2]; + if (temp < 0) temp = 0; + else if (temp > 255) temp = 255; + mesh->colors_array[i][2] = temp; + + mesh->colors_array[i][3] = alpha; + } + } + } + if (expand) + { + if (mesh->xyz_array == p1v) + { + mesh->xyz_array = tempVertexCoords; + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->xyz_array[i][0] = p1v[i][0] + mesh->normals_array[i][0]*expand; + mesh->xyz_array[i][1] = p1v[i][1] + mesh->normals_array[i][1]*expand; + mesh->xyz_array[i][2] = p1v[i][2] + mesh->normals_array[i][2]*expand; + } + + } + else + { + for (i = 0; i < mesh->numvertexes; i++) + { + mesh->xyz_array[i][0] += mesh->normals_array[i][0]*expand; + mesh->xyz_array[i][1] += mesh->normals_array[i][1]*expand; + mesh->xyz_array[i][2] += mesh->normals_array[i][2]*expand; + } + } + } +} + +qboolean R_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int frame1, int frame2, float lerp, float alpha, float fg1time, float fg2time, qboolean nolightdir) +{ + galiasgroup_t *g1, *g2; + + if (!inf->groups) + { + Con_DPrintf("Model with no frames (%s)\n", currententity->model->name); + return false; + } + if (frame1 < 0) + { + Con_DPrintf("Negative frame (%s)\n", currententity->model->name); + frame1 = 0; + } + if (frame2 < 0) + { + Con_DPrintf("Negative frame (%s)\n", currententity->model->name); + frame2 = frame1; + } + if (frame1 >= inf->groups) + { + Con_DPrintf("Too high frame %i (%s)\n", frame1, currententity->model->name); + frame1 %= inf->groups; + } + if (frame2 >= inf->groups) + { + Con_DPrintf("Too high frame %i (%s)\n", frame2, currententity->model->name); + frame2 = frame1; + } + + if (lerp <= 0) + frame2 = frame1; + else if (lerp >= 1) + frame1 = frame2; + + if (numTempColours < inf->numverts) + { + if (tempColours) + BZ_Free(tempColours); + tempColours = BZ_Malloc(sizeof(*tempColours)*inf->numverts); + numTempColours = inf->numverts; + } + if (numTempNormals < inf->numverts) + { + if (tempNormals) + BZ_Free(tempNormals); + tempNormals = BZ_Malloc(sizeof(*tempNormals)*inf->numverts); + numTempNormals = inf->numverts; + } + if (numTempVertexCoords < inf->numverts) + { + if (tempVertexCoords) + BZ_Free(tempVertexCoords); + tempVertexCoords = BZ_Malloc(sizeof(*tempVertexCoords)*inf->numverts); + numTempVertexCoords = inf->numverts; + } + + mesh->numvertexes = inf->numverts; + mesh->indexes = (index_t*)((char *)inf + inf->ofs_indexes); + mesh->numindexes = inf->numindexes; + + if (inf->sharesverts) + return false; //don't generate the new vertex positions. We still have them all. + +#ifndef SERVERONLY + mesh->st_array = (vec2_t*)((char *)inf + inf->ofs_st_array); + mesh->lmst_array = NULL; + mesh->colors_array = tempColours; + mesh->trneighbors = (int *)((char *)inf + inf->ofs_trineighbours); + mesh->normals_array = tempNormals; +#endif + mesh->xyz_array = tempVertexCoords; + + g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); + g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); + +//we don't support meshes with one pose skeletal and annother not. +//we don't support meshes with one group skeletal and annother not. + +#ifdef SKELETALMODELS + if (inf->numbones) + { + int l=0; + float plerp[4]; + float *pose[4]; + float mlerp; //minor lerp, poses within a group. + qboolean hirachy; + + if (g1->isheirachical != g2->isheirachical || lerp < 0) + lerp = 0; + hirachy = g1->isheirachical; + + mlerp = (fg1time)*g1->rate; + frame1=mlerp; + frame2=frame1+1; + mlerp-=frame1; + if (g1->loop) + { + frame1=frame1%g1->numposes; + frame2=frame2%g1->numposes; + } + else + { + frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; + frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; + } + + plerp[l] = (1-mlerp)*(1-lerp); + if (plerp[l]>0) + pose[l++] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[l] = (mlerp)*(1-lerp); + if (plerp[l]>0) + pose[l++] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); + + if (lerp) + { + mlerp = (fg2time)*g2->rate; + frame1=mlerp; + frame2=frame1+1; + mlerp-=frame1; + if (g2->loop) + { + frame1=frame1%g2->numposes; + frame2=frame2%g2->numposes; + } + else + { + frame1=(frame1>g2->numposes-1)?g2->numposes-1:frame1; + frame2=(frame2>g2->numposes-1)?g2->numposes-1:frame2; + } + + plerp[l] = (1-mlerp)*(lerp); + if (plerp[l]>0) + pose[l++] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[l] = (mlerp)*(lerp); + if (plerp[l]>0) + pose[l++] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); + } +/* + pose[0] = (float *)((char *)g1 + g1->poseofs); + plerp[0] = 1; + plerp[1] = 0; + plerp[3] = 0; + plerp[4] = 0; + l = 1; +*/ + R_BuildSkeletalMesh(mesh, plerp, pose, l, (galiasbone_t *)((char*)inf+inf->ofsbones), inf->numbones, (galisskeletaltransforms_t *)((char*)inf+inf->ofstransforms), inf->numtransforms, hirachy); + return false; + } +#endif + + if (g1 == g2) //lerping within group is only done if not changing group + { + lerp = fg1time*g1->rate; + if (lerp < 0) lerp = 0; //hrm + frame1=lerp; + frame2=frame1+1; + lerp-=frame1; + if (g1->loop) + { + frame1=frame1%g1->numposes; + frame2=frame2%g1->numposes; + } + else + { + frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; + frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; + } + } + else //don't bother with a four way lerp. Yeah, this will produce jerkyness with models with just framegroups. + { + frame1=0; + frame2=0; + } + + R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), + (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), + 1-lerp, (qbyte)(alpha*255), currententity->fatness, nolightdir); + + return true; //to allow the mesh to be dlighted. +} + +#endif + + + + + + + + + + + +//The whole reason why model loading is supported in the server. +qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +{ + galiasinfo_t *mod = Mod_Extradata(model); + galiasgroup_t *group; + galiaspose_t *pose; + int i; + + float *p1, *p2, *p3; + vec3_t edge1, edge2, edge3; + vec3_t normal; + vec3_t edgenormal; + + float planedist; + float diststart, distend; + + float frac; +// float temp; + + vec3_t impactpoint; + + float *posedata; + int *indexes; + + while(mod) + { + indexes = (int*)((char*)mod + mod->ofs_indexes); + group = (galiasgroup_t*)((char*)mod + mod->groupofs); + pose = (galiaspose_t*)((char*)&group[0] + group[0].poseofs); + posedata = (float*)((char*)pose + pose->ofsverts); +#ifdef SKELETALMODELS + if (mod->numbones && !mod->sharesverts) + { + float bonepose[MAX_BONES][12]; + posedata = alloca(mod->numverts*sizeof(vec3_t)); + frac = 1; + if (group->isheirachical) + { + if (!mod->sharesbones) + R_LerpBones(&frac, (float**)posedata, 1, (galiasbone_t*)((char*)mod + mod->ofsbones), mod->numbones, bonepose); + R_TransformVerticies(bonepose, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata); + } + else + R_TransformVerticies((void*)posedata, (galisskeletaltransforms_t*)((char*)mod + mod->ofstransforms), mod->numtransforms, posedata); + } +#endif + + for (i = 0; i < mod->numindexes; i+=3) + { + p1 = posedata + 3*indexes[i+0]; + p2 = posedata + 3*indexes[i+1]; + p3 = posedata + 3*indexes[i+2]; + + VectorSubtract(p1, p2, edge1); + VectorSubtract(p3, p2, edge2); + CrossProduct(edge1, edge2, normal); + + planedist = DotProduct(p1, normal); + diststart = DotProduct(start, normal); + if (diststart <= planedist) + continue; //start on back side. + distend = DotProduct(end, normal); + if (distend >= planedist) + continue; //end on front side (as must start - doesn't cross). + + frac = (diststart - planedist) / (diststart-distend); + + if (frac >= trace->fraction) //already found one closer. + continue; + + impactpoint[0] = start[0] + frac*(end[0] - start[0]); + impactpoint[1] = start[1] + frac*(end[1] - start[1]); + impactpoint[2] = start[2] + frac*(end[2] - start[2]); + +// temp = DotProduct(impactpoint, normal)-planedist; + + CrossProduct(edge1, normal, edgenormal); +// temp = DotProduct(impactpoint, edgenormal)-DotProduct(p2, edgenormal); + if (DotProduct(impactpoint, edgenormal) > DotProduct(p2, edgenormal)) + continue; + + CrossProduct(normal, edge2, edgenormal); + if (DotProduct(impactpoint, edgenormal) > DotProduct(p3, edgenormal)) + continue; + + VectorSubtract(p1, p3, edge3); + CrossProduct(normal, edge3, edgenormal); + if (DotProduct(impactpoint, edgenormal) > DotProduct(p1, edgenormal)) + continue; + + trace->fraction = frac; + VectorCopy(impactpoint, trace->endpos); + VectorCopy(normal, trace->plane.normal); + } + + if (mod->nextsurf) + mod = (galiasinfo_t*)((char*)mod + mod->nextsurf); + else + mod = NULL; + } + + trace->allsolid = false; + + return trace->fraction != 1; +} + + + + +//Common loader function. +static void Mod_DoCRC(model_t *mod, char *buffer, int buffersize) +{ +#ifndef SERVERONLY + //we've got to have this bit + if (loadmodel->engineflags & MDLF_DOCRC) + { + unsigned short crc; + qbyte *p; + int len; + char st[40]; + + QCRC_Init(&crc); + for (len = buffersize, p = buffer; len; len--, p++) + QCRC_ProcessByte(&crc, *p); + + sprintf(st, "%d", (int) crc); + Info_SetValueForKey (cls.userinfo, + (loadmodel->engineflags & MDLF_PLAYER) ? pmodel_name : emodel_name, + st, MAX_INFO_STRING); + + if (cls.state >= ca_connected) + { + CL_SendClientCommand(true, "setinfo %s %d", + (loadmodel->engineflags & MDLF_PLAYER) ? pmodel_name : emodel_name, + (int)crc); + } + + if (!(loadmodel->engineflags & MDLF_PLAYER)) + { //eyes + loadmodel->tainted = (crc != 6967); + } + } +#endif +} + + +static void Mod_ClampModelSize(model_t *mod) +{ +#ifndef SERVERONLY + int i; + + float rad=0, axis; + axis = (mod->maxs[0] - mod->mins[0]); + rad += axis*axis; + axis = (mod->maxs[1] - mod->mins[1]); + rad += axis*axis; + axis = (mod->maxs[2] - mod->mins[2]); + rad += axis*axis; + + if (loadmodel->engineflags & MDLF_DOCRC) + { + if (!strcmp(mod->name, "progs/eyes.mdl")) + { //this is checked elsewhere to make sure the crc matches (this is to make sure the crc check was actually called) + if (mod->type != mod_alias || mod->fromgame != fg_quake) + mod->tainted = true; + } + } + + mod->clampscale = 1; + for (i = 0; i < sizeof(clampedmodel)/sizeof(clampedmodel[0]); i++) + { + if (!strcmp(mod->name, clampedmodel[i].name)) + { + if (rad > clampedmodel[i].furthestallowedextremety) + { + axis = clampedmodel[i].furthestallowedextremety; + mod->clampscale = axis/rad; + Con_DPrintf("\"%s\" will be clamped.\n", mod->name); + } + return; + } + } + + Con_DPrintf("Don't know what size to clamp \"%s\" to (size:%f).\n", mod->name, rad); +#endif +} + +#ifdef RGLQUAKE +static int R_FindTriangleWithEdge ( int *indexes, int numtris, int start, int end, int ignore) +{ + int i; + int match, count; + + count = 0; + match = -1; + + for (i = 0; i < numtris; i++, indexes += 3) + { + if ( (indexes[0] == start && indexes[1] == end) + || (indexes[1] == start && indexes[2] == end) + || (indexes[2] == start && indexes[0] == end) ) { + if (i != ignore) + match = i; + count++; + } else if ( (indexes[1] == start && indexes[0] == end) + || (indexes[2] == start && indexes[1] == end) + || (indexes[0] == start && indexes[2] == end) ) { + count++; + } + } + + // detect edges shared by three triangles and make them seams + if (count > 2) + match = -1; + + return match; +} +static void Mod_BuildTriangleNeighbours ( int *neighbours, int *indexes, int numtris ) +{ + int i, *n; + int *index; + + for (i = 0, index = indexes, n = neighbours; i < numtris; i++, index += 3, n += 3) + { + n[0] = R_FindTriangleWithEdge (indexes, numtris, index[1], index[0], i); + n[1] = R_FindTriangleWithEdge (indexes, numtris, index[2], index[1], i); + n[2] = R_FindTriangleWithEdge (indexes, numtris, index[0], index[2], i); + } +} +#endif +void Mod_CompileTriangleNeighbours(galiasinfo_t *galias) +{ +#ifdef RGLQUAKE + if (qrenderer != QR_OPENGL) + return; + if (r_shadows.value) + { + int *neighbours; + neighbours = Hunk_Alloc(sizeof(int)*galias->numindexes/3*3); + galias->ofs_trineighbours = (qbyte *)neighbours - (qbyte *)galias; + Mod_BuildTriangleNeighbours(neighbours, (int*)((char*)galias + galias->ofs_indexes), galias->numindexes/3); + } +#endif +} + +#if defined(D3DQUAKE) || defined(RGLQUAKE) +/* +================= +Mod_FloodFillSkin + +Fill background pixels so mipmapping doesn't have haloes - Ed +================= +*/ + +typedef struct +{ + short x, y; +} floodfill_t; + +// must be a power of 2 +#define FLOODFILL_FIFO_SIZE 0x1000 +#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1) + +#define FLOODFILL_STEP( off, dx, dy ) \ +{ \ + if (pos[off] == fillcolor) \ + { \ + pos[off] = 255; \ + fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \ + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \ + } \ + else if (pos[off] != 255) fdc = pos[off]; \ +} + +void Mod_FloodFillSkin( qbyte *skin, int skinwidth, int skinheight ) +{ + qbyte fillcolor = *skin; // assume this is the pixel to fill + floodfill_t fifo[FLOODFILL_FIFO_SIZE]; + int inpt = 0, outpt = 0; + int filledcolor = -1; + int i; + + if (filledcolor == -1) + { + filledcolor = 0; + // attempt to find opaque black + for (i = 0; i < 256; ++i) + if (d_8to24rgbtable[i] == (255 << 0)) // alpha 1.0 + { + filledcolor = i; + break; + } + } + + // can't fill to filled color or to transparent color (used as visited marker) + if ((fillcolor == filledcolor) || (fillcolor == 255)) + { + //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor ); + return; + } + + fifo[inpt].x = 0, fifo[inpt].y = 0; + inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; + + while (outpt != inpt) + { + int x = fifo[outpt].x, y = fifo[outpt].y; + int fdc = filledcolor; + qbyte *pos = &skin[x + skinwidth * y]; + + outpt = (outpt + 1) & FLOODFILL_FIFO_MASK; + + if (x > 0) FLOODFILL_STEP( -1, -1, 0 ); + if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 ); + if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 ); + if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 ); + skin[x + skinwidth * y] = fdc; + } +} +#endif + +//additional skin loading +char **skinfilelist; +int skinfilecount; + +static qboolean VARGS Mod_TryAddSkin(char *skinname, ...) +{ + va_list argptr; + char string[MAX_QPATH]; + + //make sure we don't add it twice + int i; + + + va_start (argptr, skinname); + vsnprintf (string,sizeof(string)-1, skinname,argptr); + va_end (argptr); + string[MAX_QPATH-1] = '\0'; + + for (i = 0; i < skinfilecount; i++) + { + if (!strcmp(skinfilelist[i], string)) + return true; //already added + } + + if (!COM_FCheckExists(string)) + return false; + + skinfilelist = BZ_Realloc(skinfilelist, sizeof(*skinfilelist)*(skinfilecount+1)); + skinfilelist[skinfilecount] = Z_Malloc(strlen(string)+1); + strcpy(skinfilelist[skinfilecount], string); + skinfilecount++; + return true; +} + +int Mod_EnumerateSkins(char *name, int size, void *param) +{ + Mod_TryAddSkin(name); + return true; +} + +int Mod_BuildSkinFileList(char *modelname) +{ + int i; + char skinfilename[MAX_QPATH]; + + //flush the old list + for (i = 0; i < skinfilecount; i++) + { + Z_Free(skinfilelist[i]); + skinfilelist[i] = NULL; + } + skinfilecount=0; + + COM_StripExtension(modelname, skinfilename, sizeof(skinfilename)); + + //try and add numbered skins, and then try fixed names. + for (i = 0; ; i++) + { + if (!Mod_TryAddSkin("%s_%i.skin", modelname, i)) + { + if (i == 0) + { + if (!Mod_TryAddSkin("%s_default.skin", skinfilename, i)) + break; + } + else if (i == 1) + { + if (!Mod_TryAddSkin("%s_blue.skin", skinfilename, i)) + break; + } + else if (i == 2) + { + if (!Mod_TryAddSkin("%s_red.skin", skinfilename, i)) + break; + } + else if (i == 3) + { + if (!Mod_TryAddSkin("%s_green.skin", skinfilename, i)) + break; + } + else if (i == 4) + { + if (!Mod_TryAddSkin("%s_yellow.skin", skinfilename, i)) + break; + } + else + break; + } + } + +// if (strstr(modelname, "lower") || strstr(modelname, "upper") || strstr(modelname, "head")) +// { + COM_EnumerateFiles(va("%s_*.skin", modelname), Mod_EnumerateSkins, NULL); + COM_EnumerateFiles(va("%s_*.skin", skinfilename), Mod_EnumerateSkins, NULL); +// } +// else +// COM_EnumerateFiles("*.skin", Mod_EnumerateSkins, NULL); + + return skinfilecount; +} + + +//This is a hack. It uses an assuption about q3 player models. +void Mod_ParseQ3SkinFile(char *out, char *surfname, char *modelname, int skinnum, char *skinfilename) +{ + const char *f = NULL, *p; + int len; + + if (skinnum >= skinfilecount) + return; + + if (skinfilename) + strcpy(skinfilename, skinfilelist[skinnum]); + + f = COM_LoadTempFile2(skinfilelist[skinnum]); + + while(f) + { + f = COM_ParseToken(f,NULL); + if (!f) + return; + if (!strcmp(com_token, "replace")) + { + f = COM_ParseToken(f, NULL); + + len = strlen(com_token); + + //copy surfname -> out, until we meet the part we need to replace + while(*surfname) + { + if (!strncmp(com_token, surfname, len)) + //found it + { + surfname+=len; + f = COM_ParseToken(f, NULL); + p = com_token; + while(*p) //copy the replacement + *out++ = *p++; + + while(*surfname) //copy the remaining + *out++ = *surfname++; + *out++ = '\0'; //we didn't find it. + return; + } + *out++ = *surfname++; + } + *out++ = '\0'; //we didn't find it. + return; + } + else + { + while(*f == ' ' || *f == '\t') + f++; + if (*f == ',') + { + if (!strcmp(com_token, surfname)) + { + f++; + COM_ParseToken(f, NULL); + strcpy(out, com_token); + return; + } + } + } + + p = strchr(f, '\n'); + if (!p) + f = f+strlen(f); + else + f = p+1; + if (!*f) + break; + } +} + +#if defined(D3DQUAKE) || defined(RGLQUAKE) +void Mod_LoadSkinFile(galiastexnum_t *texnum, char *surfacename, int skinnumber, unsigned char *rawdata, int width, int height, unsigned char *palette) +{ + char shadername[MAX_QPATH]; + Q_strncpyz(shadername, surfacename, sizeof(shadername)); + + Mod_ParseQ3SkinFile(shadername, surfacename, loadmodel->name, skinnumber, NULL); + +#ifdef Q3SHADERS + texnum->shader = R_RegisterSkin(shadername); +#endif + texnum->base = Mod_LoadHiResTexture(shadername, "models", true, true, true); //13/4/08 IMPLEMENTME texnum->loweroverlay = 0; - texnum->upperoverlay = 0; -} -#endif - - - - - - - - - - - - -//Q1 model loading -#if 1 -static galiasinfo_t *galias; -static dmdl_t *pq1inmodel; -#define NUMVERTEXNORMALS 162 -extern float r_avertexnormals[NUMVERTEXNORMALS][3]; -static void *QTest_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) -{ - galiaspose_t *pose; - galiasgroup_t *frame; - dtrivertx_t *pinframe; - qtestaliasframe_t *frameinfo; - int i, j; - - vec3_t *normals; - vec3_t *verts; - - frame = (galiasgroup_t*)((char *)galias + galias->groupofs); - - for (i = 0; i < pq1inmodel->numframes; i++) - { - switch(LittleLong(pframetype->type)) - { - case ALIAS_SINGLE: - frameinfo = (qtestaliasframe_t*)((char *)(pframetype+1)); - pinframe = (dtrivertx_t*)((char*)frameinfo+sizeof(qtestaliasframe_t)); - pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*2*galias->numverts); - frame->poseofs = (char *)pose - (char *)frame; - frame->numposes = 1; - galias->groups++; - - frame->name[0] = '\0'; - - verts = (vec3_t *)(pose+1); - normals = &verts[galias->numverts]; - pose->ofsverts = (char *)verts - (char *)pose; -#ifndef SERVERONLY - pose->ofsnormals = (char *)normals - (char *)pose; -#endif - - for (j = 0; j < pq1inmodel->numverts; j++) - { - verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); -#endif - if (seamremaps[j] != j) - { - VectorCopy(verts[j], verts[seamremaps[j]]); - VectorCopy(normals[j], normals[seamremaps[j]]); - } - } - -// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); - - pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; - break; - default: - Con_Printf(CON_ERROR "Bad frame type for QTest model in %s\n", loadmodel->name); - return NULL; - } - frame++; - } - return pframetype; -} - -static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) -{ - galiaspose_t *pose; - galiasgroup_t *frame; - dtrivertx_t *pinframe; - daliasframe_t *frameinfo; - int i, j, k; - daliasgroup_t *ingroup; - daliasinterval_t *intervals; - float sinter; - - vec3_t *normals; - vec3_t *verts; - - frame = (galiasgroup_t*)((char *)galias + galias->groupofs); - - for (i = 0; i < pq1inmodel->numframes; i++) - { - switch(LittleLong(pframetype->type)) - { - case ALIAS_SINGLE: - frameinfo = (daliasframe_t*)((char *)(pframetype+1)); - pinframe = (dtrivertx_t*)((char*)frameinfo+sizeof(daliasframe_t)); - pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*2*galias->numverts); - frame->poseofs = (char *)pose - (char *)frame; - frame->numposes = 1; - galias->groups++; - - Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); - - verts = (vec3_t *)(pose+1); - normals = &verts[galias->numverts]; - pose->ofsverts = (char *)verts - (char *)pose; -#ifndef SERVERONLY - pose->ofsnormals = (char *)normals - (char *)pose; -#endif - - for (j = 0; j < pq1inmodel->numverts; j++) - { - verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); -#endif - if (seamremaps[j] != j) - { - VectorCopy(verts[j], verts[seamremaps[j]]); - VectorCopy(normals[j], normals[seamremaps[j]]); - } - } - -// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); - - pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; - break; - - case ALIAS_GROUP: - case ALIAS_GROUP_SWAPPED: // prerelease - ingroup = (daliasgroup_t *)(pframetype+1); - - pose = (galiaspose_t *)Hunk_Alloc(LittleLong(ingroup->numframes)*(sizeof(galiaspose_t) + sizeof(vec3_t)*2*galias->numverts)); - frame->poseofs = (char *)pose - (char *)frame; - frame->numposes = LittleLong(ingroup->numframes); - frame->loop = true; - galias->groups++; - - verts = (vec3_t *)(pose+frame->numposes); - normals = &verts[galias->numverts]; - - intervals = (daliasinterval_t *)(ingroup+1); - sinter = LittleFloat(intervals->interval); - if (sinter <= 0) - sinter = 0.1; - frame->rate = 1/sinter; - - pinframe = (dtrivertx_t *)(intervals+frame->numposes); - for (k = 0; k < frame->numposes; k++) - { - pose->ofsverts = (char *)verts - (char *)pose; -#ifndef SERVERONLY - pose->ofsnormals = (char *)normals - (char *)pose; -#endif - - frameinfo = (daliasframe_t*)pinframe; - pinframe = (dtrivertx_t *)((char *)frameinfo + sizeof(daliasframe_t)); - - if (k == 0) - Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); - - for (j = 0; j < pq1inmodel->numverts; j++) - { - verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; - verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; - verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; -#ifndef SERVERONLY - VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); -#endif - if (seamremaps[j] != j) - { - VectorCopy(verts[j], verts[seamremaps[j]]); - VectorCopy(normals[j], normals[seamremaps[j]]); - } - } - verts = &normals[galias->numverts]; - normals = &verts[galias->numverts]; - pose++; - - pinframe += pq1inmodel->numverts; - } - -// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); - - pframetype = (daliasframetype_t *)pinframe; - break; - default: - Con_Printf(CON_ERROR "Bad frame type in %s\n", loadmodel->name); - return NULL; - } - frame++; - } - return pframetype; -} - -//greatly reduced version of Q1_LoadSkins -//just skips over the data -static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha) -{ - int i; - int s; - int *count; - float *intervals; - qbyte *data; - - s = pq1inmodel->skinwidth*pq1inmodel->skinheight; - for (i = 0; i < pq1inmodel->numskins; i++) - { - switch(LittleLong(pskintype->type)) - { - case ALIAS_SKIN_SINGLE: - pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s); - break; - - default: - count = (int *)(pskintype+1); - intervals = (float *)(count+1); - data = (qbyte *)(intervals + LittleLong(*count)); - data += s*LittleLong(*count); - pskintype = (daliasskintype_t *)data; - break; - } - } - galias->numskins=pq1inmodel->numskins; - return pskintype; -} - -#if defined(RGLQUAKE) || defined(D3DQUAKE) -static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, qboolean alpha) -{ - extern cvar_t gl_bump; - galiastexnum_t *texnums; - char skinname[MAX_QPATH]; - int i; - int s, t; - float sinter; - daliasskingroup_t *count; - daliasskininterval_t *intervals; - qbyte *data, *saved; - galiasskin_t *outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); - - int texture; - int fbtexture; - int bumptexture; - - s = pq1inmodel->skinwidth*pq1inmodel->skinheight; - for (i = 0; i < pq1inmodel->numskins; i++) - { - switch(LittleLong(pskintype->type)) - { - case ALIAS_SKIN_SINGLE: - outskin->skinwidth = pq1inmodel->skinwidth; - outskin->skinheight = pq1inmodel->skinheight; - - //LH's naming scheme ("models" is likly to be ignored) - fbtexture = 0; - bumptexture = 0; - snprintf(skinname, sizeof(skinname), "%s_%i.", loadmodel->name, i); - texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); - if (texture) - { - snprintf(skinname, sizeof(skinname), "%s_%i_luma.", loadmodel->name, i); - fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); - if (gl_bump.value) - { - snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadmodel->name, i); - bumptexture = Mod_LoadBumpmapTexture(skinname, "models"); - } - } - else - { - snprintf(skinname, sizeof(skinname), "%s_%i", loadname, i); - texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); - if (texture && r_fb_models.value) - { - snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadname, i); - fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); - } - if (texture && gl_bump.value) - { - snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadname, i); - bumptexture = Mod_LoadBumpmapTexture(skinname, "models"); - } - } - -//but only preload it if we have no replacement. - if (!texture || (loadmodel->engineflags & MDLF_NOTREPLACEMENTS)) - { - //we're not using 24bits - texnums = Hunk_Alloc(sizeof(*texnums)+s); - saved = (qbyte*)(texnums+1); - outskin->ofstexels = (qbyte *)(saved) - (qbyte *)outskin; - memcpy(saved, pskintype+1, s); - Mod_FloodFillSkin(saved, outskin->skinwidth, outskin->skinheight); - + texnum->upperoverlay = 0; +} +#endif + + + + + + + + + + + + +//Q1 model loading +#if 1 +static galiasinfo_t *galias; +static dmdl_t *pq1inmodel; +#define NUMVERTEXNORMALS 162 +extern float r_avertexnormals[NUMVERTEXNORMALS][3]; +static void *QTest_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) +{ + galiaspose_t *pose; + galiasgroup_t *frame; + dtrivertx_t *pinframe; + qtestaliasframe_t *frameinfo; + int i, j; + + vec3_t *normals; + vec3_t *verts; + + frame = (galiasgroup_t*)((char *)galias + galias->groupofs); + + for (i = 0; i < pq1inmodel->numframes; i++) + { + switch(LittleLong(pframetype->type)) + { + case ALIAS_SINGLE: + frameinfo = (qtestaliasframe_t*)((char *)(pframetype+1)); + pinframe = (dtrivertx_t*)((char*)frameinfo+sizeof(qtestaliasframe_t)); + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*2*galias->numverts); + frame->poseofs = (char *)pose - (char *)frame; + frame->numposes = 1; + galias->groups++; + + frame->name[0] = '\0'; + + verts = (vec3_t *)(pose+1); + normals = &verts[galias->numverts]; + pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + pose->ofsnormals = (char *)normals - (char *)pose; +#endif + + for (j = 0; j < pq1inmodel->numverts; j++) + { + verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); +#endif + if (seamremaps[j] != j) + { + VectorCopy(verts[j], verts[seamremaps[j]]); + VectorCopy(normals[j], normals[seamremaps[j]]); + } + } + +// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); + + pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; + break; + default: + Con_Printf(CON_ERROR "Bad frame type for QTest model in %s\n", loadmodel->name); + return NULL; + } + frame++; + } + return pframetype; +} + +static void *Q1_LoadFrameGroup (daliasframetype_t *pframetype, int *seamremaps) +{ + galiaspose_t *pose; + galiasgroup_t *frame; + dtrivertx_t *pinframe; + daliasframe_t *frameinfo; + int i, j, k; + daliasgroup_t *ingroup; + daliasinterval_t *intervals; + float sinter; + + vec3_t *normals; + vec3_t *verts; + + frame = (galiasgroup_t*)((char *)galias + galias->groupofs); + + for (i = 0; i < pq1inmodel->numframes; i++) + { + switch(LittleLong(pframetype->type)) + { + case ALIAS_SINGLE: + frameinfo = (daliasframe_t*)((char *)(pframetype+1)); + pinframe = (dtrivertx_t*)((char*)frameinfo+sizeof(daliasframe_t)); + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*2*galias->numverts); + frame->poseofs = (char *)pose - (char *)frame; + frame->numposes = 1; + galias->groups++; + + Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); + + verts = (vec3_t *)(pose+1); + normals = &verts[galias->numverts]; + pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + pose->ofsnormals = (char *)normals - (char *)pose; +#endif + + for (j = 0; j < pq1inmodel->numverts; j++) + { + verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); +#endif + if (seamremaps[j] != j) + { + VectorCopy(verts[j], verts[seamremaps[j]]); + VectorCopy(normals[j], normals[seamremaps[j]]); + } + } + +// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); + + pframetype = (daliasframetype_t *)&pinframe[pq1inmodel->numverts]; + break; + + case ALIAS_GROUP: + case ALIAS_GROUP_SWAPPED: // prerelease + ingroup = (daliasgroup_t *)(pframetype+1); + + pose = (galiaspose_t *)Hunk_Alloc(LittleLong(ingroup->numframes)*(sizeof(galiaspose_t) + sizeof(vec3_t)*2*galias->numverts)); + frame->poseofs = (char *)pose - (char *)frame; + frame->numposes = LittleLong(ingroup->numframes); + frame->loop = true; + galias->groups++; + + verts = (vec3_t *)(pose+frame->numposes); + normals = &verts[galias->numverts]; + + intervals = (daliasinterval_t *)(ingroup+1); + sinter = LittleFloat(intervals->interval); + if (sinter <= 0) + sinter = 0.1; + frame->rate = 1/sinter; + + pinframe = (dtrivertx_t *)(intervals+frame->numposes); + for (k = 0; k < frame->numposes; k++) + { + pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + pose->ofsnormals = (char *)normals - (char *)pose; +#endif + + frameinfo = (daliasframe_t*)pinframe; + pinframe = (dtrivertx_t *)((char *)frameinfo + sizeof(daliasframe_t)); + + if (k == 0) + Q_strncpyz(frame->name, frameinfo->name, sizeof(frame->name)); + + for (j = 0; j < pq1inmodel->numverts; j++) + { + verts[j][0] = pinframe[j].v[0]*pq1inmodel->scale[0]+pq1inmodel->scale_origin[0]; + verts[j][1] = pinframe[j].v[1]*pq1inmodel->scale[1]+pq1inmodel->scale_origin[1]; + verts[j][2] = pinframe[j].v[2]*pq1inmodel->scale[2]+pq1inmodel->scale_origin[2]; +#ifndef SERVERONLY + VectorCopy(r_avertexnormals[pinframe[j].lightnormalindex], normals[j]); +#endif + if (seamremaps[j] != j) + { + VectorCopy(verts[j], verts[seamremaps[j]]); + VectorCopy(normals[j], normals[seamremaps[j]]); + } + } + verts = &normals[galias->numverts]; + normals = &verts[galias->numverts]; + pose++; + + pinframe += pq1inmodel->numverts; + } + +// GL_GenerateNormals((float*)verts, (float*)normals, (int *)((char *)galias + galias->ofs_indexes), galias->numindexes/3, galias->numverts); + + pframetype = (daliasframetype_t *)pinframe; + break; + default: + Con_Printf(CON_ERROR "Bad frame type in %s\n", loadmodel->name); + return NULL; + } + frame++; + } + return pframetype; +} + +//greatly reduced version of Q1_LoadSkins +//just skips over the data +static void *Q1_LoadSkins_SV (daliasskintype_t *pskintype, qboolean alpha) +{ + int i; + int s; + int *count; + float *intervals; + qbyte *data; + + s = pq1inmodel->skinwidth*pq1inmodel->skinheight; + for (i = 0; i < pq1inmodel->numskins; i++) + { + switch(LittleLong(pskintype->type)) + { + case ALIAS_SKIN_SINGLE: + pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s); + break; + + default: + count = (int *)(pskintype+1); + intervals = (float *)(count+1); + data = (qbyte *)(intervals + LittleLong(*count)); + data += s*LittleLong(*count); + pskintype = (daliasskintype_t *)data; + break; + } + } + galias->numskins=pq1inmodel->numskins; + return pskintype; +} + +#if defined(RGLQUAKE) || defined(D3DQUAKE) +static void *Q1_LoadSkins_GL (daliasskintype_t *pskintype, qboolean alpha) +{ + extern cvar_t gl_bump; + galiastexnum_t *texnums; + char skinname[MAX_QPATH]; + int i; + int s, t; + float sinter; + daliasskingroup_t *count; + daliasskininterval_t *intervals; + qbyte *data, *saved; + galiasskin_t *outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); + + int texture; + int fbtexture; + int bumptexture; + + s = pq1inmodel->skinwidth*pq1inmodel->skinheight; + for (i = 0; i < pq1inmodel->numskins; i++) + { + switch(LittleLong(pskintype->type)) + { + case ALIAS_SKIN_SINGLE: + outskin->skinwidth = pq1inmodel->skinwidth; + outskin->skinheight = pq1inmodel->skinheight; + + //LH's naming scheme ("models" is likly to be ignored) + fbtexture = 0; + bumptexture = 0; + snprintf(skinname, sizeof(skinname), "%s_%i.", loadmodel->name, i); + texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); + if (texture) + { + snprintf(skinname, sizeof(skinname), "%s_%i_luma.", loadmodel->name, i); + fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); + if (gl_bump.value) + { + snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadmodel->name, i); + bumptexture = Mod_LoadBumpmapTexture(skinname, "models"); + } + } + else + { + snprintf(skinname, sizeof(skinname), "%s_%i", loadname, i); + texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); + if (texture && r_fb_models.value) + { + snprintf(skinname, sizeof(skinname), "%s_%i_luma", loadname, i); + fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); + } + if (texture && gl_bump.value) + { + snprintf(skinname, sizeof(skinname), "%s_%i_bump", loadname, i); + bumptexture = Mod_LoadBumpmapTexture(skinname, "models"); + } + } + +//but only preload it if we have no replacement. + if (!texture || (loadmodel->engineflags & MDLF_NOTREPLACEMENTS)) + { + //we're not using 24bits + texnums = Hunk_Alloc(sizeof(*texnums)+s); + saved = (qbyte*)(texnums+1); + outskin->ofstexels = (qbyte *)(saved) - (qbyte *)outskin; + memcpy(saved, pskintype+1, s); + Mod_FloodFillSkin(saved, outskin->skinwidth, outskin->skinheight); + //the extra underscore is to stop if (!texture) - { - snprintf(skinname, sizeof(skinname), "%s__%i", loadname, i); - texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, true, alpha); - if (r_fb_models.value) - { - snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i); - fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, true, true); - } - if (gl_bump.value) - { - snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i); - bumptexture = R_LoadTexture8Bump(skinname, outskin->skinwidth, outskin->skinheight, saved, true, true); + { + snprintf(skinname, sizeof(skinname), "%s__%i", loadname, i); + texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, true, alpha); + if (r_fb_models.value) + { + snprintf(skinname, sizeof(skinname), "%s__%i_luma", loadname, i); + fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, true, true); } - } - } - else - texnums = Hunk_Alloc(sizeof(*texnums)); - outskin->texnums=1; - - outskin->ofstexnums = (char *)texnums - (char *)outskin; - -#ifdef Q3SHADERS - if (cls.allow_shaders) - { - sprintf(skinname, "%s_%i", loadname, i); - texnums->shader = R_RegisterCustom (skinname, NULL); - } -#endif - - - texnums->base = texture; - texnums->fullbright = fbtexture; + if (gl_bump.value) + { + snprintf(skinname, sizeof(skinname), "%s__%i_bump", loadname, i); + bumptexture = R_LoadTexture8Bump(skinname, outskin->skinwidth, outskin->skinheight, saved, true, true); + } + } + } + else + texnums = Hunk_Alloc(sizeof(*texnums)); + outskin->texnums=1; + + outskin->ofstexnums = (char *)texnums - (char *)outskin; + +#ifdef Q3SHADERS + if (cls.allow_shaders) + { + sprintf(skinname, "%s_%i", loadname, i); + texnums->shader = R_RegisterCustom (skinname, NULL); + } +#endif + + texnums->loweroverlay = 0; + texnums->upperoverlay = 0; + + texnums->base = texture; + texnums->fullbright = fbtexture; texnums->bump = bumptexture; //13/4/08 IMPLEMENTME if (r_skin_overlays.value) { - snprintf(skinname, sizeof(skinname), "%s_%i", loadname, i); - texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, true, alpha); + snprintf(skinname, sizeof(skinname), "%s_%i_pants", loadname, i); + texnums->loweroverlay = Mod_LoadReplacementTexture(skinname, "models", true, true, true); + + snprintf(skinname, sizeof(skinname), "%s_%i_shirt", loadname, i); + texnums->upperoverlay = Mod_LoadReplacementTexture(skinname, "models", true, true, true); } - else + + pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s); + break; + + default: + outskin->skinwidth = pq1inmodel->skinwidth; + outskin->skinheight = pq1inmodel->skinheight; + count = (daliasskingroup_t*)(pskintype+1); + intervals = (daliasskininterval_t *)(count+1); + outskin->texnums = LittleLong(count->numskins); + data = (qbyte *)(intervals + outskin->texnums); + texnums = Hunk_Alloc(sizeof(*texnums)*outskin->texnums); + outskin->ofstexnums = (char *)texnums - (char *)outskin; + outskin->ofstexels = 0; + sinter = LittleFloat(intervals[0].interval); + if (sinter <= 0) + sinter = 0.1; + outskin->skinspeed = 1/sinter; + + for (t = 0; t < outskin->texnums; t++,data+=s, texnums++) { - texnums->loweroverlay = 0; - texnums->upperoverlay = 0; - } - - pskintype = (daliasskintype_t *)((char *)(pskintype+1)+s); - break; - - default: - outskin->skinwidth = pq1inmodel->skinwidth; - outskin->skinheight = pq1inmodel->skinheight; - count = (daliasskingroup_t*)(pskintype+1); - intervals = (daliasskininterval_t *)(count+1); - outskin->texnums = LittleLong(count->numskins); - data = (qbyte *)(intervals + outskin->texnums); - texnums = Hunk_Alloc(sizeof(*texnums)*outskin->texnums); - outskin->ofstexnums = (char *)texnums - (char *)outskin; - outskin->ofstexels = 0; - sinter = LittleFloat(intervals[0].interval); - if (sinter <= 0) - sinter = 0.1; - outskin->skinspeed = 1/sinter; - - for (t = 0; t < outskin->texnums; t++,data+=s, texnums++) - { - texture = 0; - fbtexture = 0; - - //LH naming scheme - if (!texture) - { - sprintf(skinname, "%s_%i_%i.", loadmodel->name, i, t); - texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); - } - if (!fbtexture && r_fb_models.value) - { - sprintf(skinname, "%s_%i_%i_luma.", loadmodel->name, i, t); - fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); - } - - //Fuhquake naming scheme - if (!texture) - { - sprintf(skinname, "%s_%i_%i", loadname, i, t); - texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); - } - if (!fbtexture && r_fb_models.value) - { - sprintf(skinname, "%s_%i_%i_luma", loadname, i, t); - fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); - } - - if (!texture || (!fbtexture && r_fb_models.value)) - { - if (t == 0) - { - saved = Hunk_Alloc(s); - outskin->ofstexels = (qbyte *)(saved) - (qbyte *)outskin; - } - else - saved = BZ_Malloc(s); - memcpy(saved, data, s); - Mod_FloodFillSkin(saved, outskin->skinwidth, outskin->skinheight); - if (!texture) - { - sprintf(skinname, "%s_%i_%i", loadname, i, t); - texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, true, alpha); - } - - - if (!fbtexture && r_fb_models.value) - { - sprintf(skinname, "%s_%i_%i_luma", loadname, i, t); - fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, true, true); - } - - if (t != 0) //only keep the first. - BZ_Free(saved); - } - -#ifdef Q3SHADERS - if (cls.allow_shaders) - { - sprintf(skinname, "%s_%i_%i", loadname, i, t); - texnums->shader = R_RegisterCustom (skinname, NULL); - } -#endif - - texnums->base = texture; + texture = 0; + fbtexture = 0; + + //LH naming scheme + if (!texture) + { + sprintf(skinname, "%s_%i_%i.", loadmodel->name, i, t); + texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); + } + if (!fbtexture && r_fb_models.value) + { + sprintf(skinname, "%s_%i_%i_luma.", loadmodel->name, i, t); + fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); + } + + //Fuhquake naming scheme + if (!texture) + { + sprintf(skinname, "%s_%i_%i", loadname, i, t); + texture = Mod_LoadReplacementTexture(skinname, "models", true, false, true); + } + if (!fbtexture && r_fb_models.value) + { + sprintf(skinname, "%s_%i_%i_luma", loadname, i, t); + fbtexture = Mod_LoadReplacementTexture(skinname, "models", true, true, true); + } + + if (!texture || (!fbtexture && r_fb_models.value)) + { + if (t == 0) + { + saved = Hunk_Alloc(s); + outskin->ofstexels = (qbyte *)(saved) - (qbyte *)outskin; + } + else + saved = BZ_Malloc(s); + memcpy(saved, data, s); + Mod_FloodFillSkin(saved, outskin->skinwidth, outskin->skinheight); + if (!texture) + { + sprintf(skinname, "%s_%i_%i", loadname, i, t); + texture = R_LoadTexture8(skinname, outskin->skinwidth, outskin->skinheight, saved, true, alpha); + } + + + if (!fbtexture && r_fb_models.value) + { + sprintf(skinname, "%s_%i_%i_luma", loadname, i, t); + fbtexture = R_LoadTextureFB(skinname, outskin->skinwidth, outskin->skinheight, saved, true, true); + } + + if (t != 0) //only keep the first. + BZ_Free(saved); + } + +#ifdef Q3SHADERS + if (cls.allow_shaders) + { + sprintf(skinname, "%s_%i_%i", loadname, i, t); + texnums->shader = R_RegisterCustom (skinname, NULL); + } +#endif + + texnums->base = texture; texnums->fullbright = fbtexture; //13/4/08 IMPLEMENTME texnums->loweroverlay = 0; - texnums->upperoverlay = 0; - } - pskintype = (daliasskintype_t *)data; - break; - } - outskin++; - } - galias->numskins=pq1inmodel->numskins; - return pskintype; -} -#endif - -qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) -{ -#ifndef SERVERONLY - vec2_t *st_array; - int j; -#endif - int hunkstart, hunkend, hunktotal; - int version; - int i, onseams; - dstvert_t *pinstverts; - dtriangle_t *pintriangles; - int *seamremap; - index_t *indexes; - qboolean qtest = false; - daliasskintype_t *skinstart; - int skintranstype; - - int size; - - loadmodel=mod; - - Mod_DoCRC(loadmodel, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - pq1inmodel = (dmdl_t *)buffer; - - loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; - - version = LittleLong(pq1inmodel->version); - if (version == QTESTALIAS_VERSION) - qtest = true; - else if (version != ALIAS_VERSION) - { - Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n", - mod->name, version, ALIAS_VERSION); - return false; - } - - seamremap = (int*)pq1inmodel; //I like overloading locals. - - if (qtest) - i = sizeof(dmdl_t)/4 - sizeof(int)*2 - 1; - else - i = sizeof(dmdl_t)/4 - 1; - - for (; i >= 0; i--) - seamremap[i] = LittleLong(seamremap[i]); - - if (pq1inmodel->numframes < 1 || - pq1inmodel->numskins < 1 || - pq1inmodel->numtris < 1 || - pq1inmodel->numverts < 3 || - pq1inmodel->skinheight < 1 || - pq1inmodel->skinwidth < 1) - { - Con_Printf(CON_ERROR "Model %s has an invalid quantity\n", mod->name); - return false; - } - - if (qtest) - mod->flags = 0; // Qtest has no flags in header - else - mod->flags = pq1inmodel->flags; - - size = sizeof(galiasinfo_t) -#ifndef SERVERONLY - + pq1inmodel->numskins*sizeof(galiasskin_t) -#endif - + pq1inmodel->numframes*sizeof(galiasgroup_t); - - galias = Hunk_Alloc(size); - galias->groupofs = sizeof(*galias); -#ifndef SERVERONLY - galias->ofsskins = sizeof(*galias)+pq1inmodel->numframes*sizeof(galiasgroup_t); -#endif - galias->nextsurf = 0; - -//skins - if (qtest) - skinstart = (daliasskintype_t *)((char *)buffer + sizeof(dmdl_t) - sizeof(int)*2); - else - skinstart = (daliasskintype_t *)(pq1inmodel+1); - if( mod->flags & EF_HOLEY ) - skintranstype = 3; //hexen2 - else if( mod->flags & EF_TRANSPARENT ) - skintranstype = 2; //hexen2 - else if( mod->flags & EF_SPECIAL_TRANS ) - skintranstype = 4; //hexen2 - else - skintranstype = 0; - - switch(qrenderer) - { -#if defined(RGLQUAKE) || defined(D3DQUAKE) - case QR_DIRECT3D: - case QR_OPENGL: - pinstverts = (dstvert_t *)Q1_LoadSkins_GL(skinstart, skintranstype); - break; -#endif - default: - pinstverts = (dstvert_t *)Q1_LoadSkins_SV(skinstart, skintranstype); - break; - } - - - - //count number of verts that are onseam. - for (onseams=0,i = 0; i < pq1inmodel->numverts; i++) - { - if (pinstverts[i].onseam) - onseams++; - } - seamremap = BZ_Malloc(sizeof(int)*pq1inmodel->numverts); - - galias->numverts = pq1inmodel->numverts+onseams; - - //st -#ifndef SERVERONLY - st_array = Hunk_Alloc(sizeof(*st_array)*(pq1inmodel->numverts+onseams)); - galias->ofs_st_array = (char *)st_array - (char *)galias; - for (j=pq1inmodel->numverts,i = 0; i < pq1inmodel->numverts; i++) - { - st_array[i][0] = (LittleLong(pinstverts[i].s)+0.5)/(float)pq1inmodel->skinwidth; - st_array[i][1] = (LittleLong(pinstverts[i].t)+0.5)/(float)pq1inmodel->skinheight; - - if (pinstverts[i].onseam) - { - st_array[j][0] = st_array[i][0]+0.5; - st_array[j][1] = st_array[i][1]; - seamremap[i] = j; - j++; - } - else - seamremap[i] = i; - } -#endif - - //trianglelists; - pintriangles = (dtriangle_t *)&pinstverts[pq1inmodel->numverts]; - - galias->numindexes = pq1inmodel->numtris*3; - indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); - galias->ofs_indexes = (char *)indexes - (char *)galias; - for (i=0 ; inumtris ; i++) - { - if (!pintriangles[i].facesfront) - { - indexes[i*3+0] = seamremap[LittleLong(pintriangles[i].vertindex[0])]; - indexes[i*3+1] = seamremap[LittleLong(pintriangles[i].vertindex[1])]; - indexes[i*3+2] = seamremap[LittleLong(pintriangles[i].vertindex[2])]; - } - else - { - indexes[i*3+0] = LittleLong(pintriangles[i].vertindex[0]); - indexes[i*3+1] = LittleLong(pintriangles[i].vertindex[1]); - indexes[i*3+2] = LittleLong(pintriangles[i].vertindex[2]); - } - } - - //frames - if (qtest) - { - if (QTest_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap) == NULL) - { - BZ_Free(seamremap); - Hunk_FreeToLowMark (hunkstart); - return false; - } - } - else - { - if (Q1_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap) == NULL) - { - BZ_Free(seamremap); - Hunk_FreeToLowMark (hunkstart); - return false; - } - } - BZ_Free(seamremap); - - - Mod_CompileTriangleNeighbours(galias); - - VectorCopy (pq1inmodel->scale_origin, mod->mins); - VectorMA (mod->mins, 255, pq1inmodel->scale, mod->maxs); - - Mod_ClampModelSize(mod); -// -// move the complete, relocatable alias model to the cache -// - hunkend = Hunk_LowMark (); - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, galias, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - mod->funcs.Trace = Mod_Trace; - - return true; -} -#endif - - -int Mod_ReadFlagsFromMD1(char *name, int md3version) -{ - dmdl_t *pinmodel; - char fname[MAX_QPATH]; - COM_StripExtension(name, fname, sizeof(fname)); - COM_DefaultExtension(fname, ".mdl", sizeof(fname)); - - if (strcmp(name, fname)) //md3 renamed as mdl - { - COM_StripExtension(name, fname, sizeof(fname)); //seeing as the md3 is named over the mdl, - COM_DefaultExtension(fname, ".md1", sizeof(fname));//read from a file with md1 (one, not an ell) - return 0; - } - - pinmodel = (dmdl_t *)COM_LoadTempFile(fname); - - if (!pinmodel) //not found - return 0; - - if (LittleLong(pinmodel->ident) != IDPOLYHEADER) - return 0; - if (LittleLong(pinmodel->version) != ALIAS_VERSION) - return 0; - return LittleLong(pinmodel->flags); -} - -#ifdef MD2MODELS - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//Q2 model loading - -typedef struct -{ - float scale[3]; // multiply qbyte verts by this - float translate[3]; // then add this - char name[16]; // frame name from grabbing - dtrivertx_t verts[1]; // variable sized -} dmd2aliasframe_t; - -//static galiasinfo_t *galias; -//static md2_t *pq2inmodel; -#define Q2NUMVERTEXNORMALS 162 -extern vec3_t bytedirs[Q2NUMVERTEXNORMALS]; - -static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins) -{ -#ifndef SERVERONLY - int i; - galiastexnum_t *texnums; - galiasskin_t *outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); - - for (i = 0; i < LittleLong(pq2inmodel->num_skins); i++, outskin++) - { - texnums = Hunk_Alloc(sizeof(*texnums)); - outskin->ofstexnums = (char *)texnums - (char *)outskin; - outskin->texnums=1; - - COM_CleanUpPath(skins); //blooming tanks. - texnums->base = Mod_LoadReplacementTexture(skins, "models", true, false, true); -#ifdef Q3SHADERS - texnums->shader = R_RegisterCustom(skins, NULL); - if (!texnums->base && !texnums->shader) - Con_Printf("Couldn't load %s\n", skins); -#endif - outskin->skinwidth = 0; - outskin->skinheight = 0; - outskin->skinspeed = 0; - - skins += MD2MAX_SKINNAME; - } -#endif - galias->numskins = LittleLong(pq2inmodel->num_skins); - -#ifndef SERVERONLY - outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); - outskin += galias->numskins - 1; - if (galias->numskins) - { - texnums = (galiastexnum_t*)((char *)outskin +outskin->ofstexnums); - if (texnums->base) - return; -#ifdef Q3SHADERS - if (texnums->shader) - return; -#endif - - galias->numskins--; - } -#endif -} - -#define MD2_MAX_TRIANGLES 4096 -qboolean Mod_LoadQ2Model (model_t *mod, void *buffer) -{ -#ifndef SERVERONLY - dmd2stvert_t *pinstverts; - vec2_t *st_array; - vec3_t *normals; -#endif - md2_t *pq2inmodel; - - int hunkstart, hunkend, hunktotal; - int version; - int i, j; - dmd2triangle_t *pintri; - index_t *indexes; - int numindexes; - - vec3_t min; - vec3_t max; - - galiaspose_t *pose; - galiasgroup_t *poutframe; - dmd2aliasframe_t *pinframe; - int framesize; - vec3_t *verts; - - int indremap[MD2_MAX_TRIANGLES*3]; - unsigned short ptempindex[MD2_MAX_TRIANGLES*3], ptempstindex[MD2_MAX_TRIANGLES*3]; - - int numverts; - - int size; - - - loadmodel=mod; - - loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; - - Mod_DoCRC(mod, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - pq2inmodel = (md2_t *)buffer; - - version = LittleLong (pq2inmodel->version); - if (version != MD2ALIAS_VERSION) - { - Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n", - mod->name, version, MD2ALIAS_VERSION); - return false; - } - - if (LittleLong(pq2inmodel->num_frames) < 1 || - LittleLong(pq2inmodel->num_skins) < 0 || - LittleLong(pq2inmodel->num_tris) < 1 || - LittleLong(pq2inmodel->num_xyz) < 3 || - LittleLong(pq2inmodel->num_st) < 3 || - LittleLong(pq2inmodel->skinheight) < 1 || - LittleLong(pq2inmodel->skinwidth) < 1) - { - Con_Printf(CON_ERROR "Model %s has an invalid quantity\n", mod->name); - return false; - } - - mod->flags = 0; - - loadmodel->numframes = LittleLong(pq2inmodel->num_frames); - - size = sizeof(galiasinfo_t) -#ifndef SERVERONLY - + LittleLong(pq2inmodel->num_skins)*sizeof(galiasskin_t) -#endif - + LittleLong(pq2inmodel->num_frames)*sizeof(galiasgroup_t); - - galias = Hunk_Alloc(size); - galias->groupofs = sizeof(*galias); -#ifndef SERVERONLY - galias->ofsskins = sizeof(*galias)+LittleLong(pq2inmodel->num_frames)*sizeof(galiasgroup_t); -#endif - galias->nextsurf = 0; - -//skins - Q2_LoadSkins(pq2inmodel, ((char *)pq2inmodel+LittleLong(pq2inmodel->ofs_skins))); - - //trianglelists; - pintri = (dmd2triangle_t *)((char *)pq2inmodel + LittleLong(pq2inmodel->ofs_tris)); - - - for (i=0 ; inum_tris) ; i++, pintri++) - { - for (j=0 ; j<3 ; j++) - { - ptempindex[i*3+j] = ( unsigned short )LittleShort ( pintri->xyz_index[j] ); - ptempstindex[i*3+j] = ( unsigned short )LittleShort ( pintri->st_index[j] ); - } - } - - numindexes = galias->numindexes = LittleLong(pq2inmodel->num_tris)*3; - indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); - galias->ofs_indexes = (char *)indexes - (char *)galias; - memset ( indremap, -1, sizeof(indremap) ); - numverts=0; - - for ( i = 0; i < numindexes; i++ ) - { - if ( indremap[i] != -1 ) { - continue; - } - - for ( j = 0; j < numindexes; j++ ) - { - if ( j == i ) { - continue; - } - - if ( (ptempindex[i] == ptempindex[j]) && (ptempstindex[i] == ptempstindex[j]) ) { - indremap[j] = i; - } - } - } - - // count unique vertexes - for ( i = 0; i < numindexes; i++ ) - { - if ( indremap[i] != -1 ) { - continue; - } - - indexes[i] = numverts++; - indremap[i] = i; - } - - Con_DPrintf ( "%s: remapped %i verts to %i\n", mod->name, LittleLong(pq2inmodel->num_xyz), numverts ); - - galias->numverts = numverts; - - // remap remaining indexes - for ( i = 0; i < numindexes; i++ ) - { - if ( indremap[i] != i ) { - indexes[i] = indexes[indremap[i]]; - } - } - -// s and t vertices -#ifndef SERVERONLY - pinstverts = ( dmd2stvert_t * ) ( ( qbyte * )pq2inmodel + LittleLong (pq2inmodel->ofs_st) ); - st_array = Hunk_Alloc(sizeof(*st_array)*(numverts)); - galias->ofs_st_array = (char *)st_array - (char *)galias; - - for (j=0 ; jskinwidth)); - st_array[indexes[j]][1] = (float)(((double)LittleShort (pinstverts[ptempstindex[indremap[j]]].t) + 0.5f) /LittleLong(pq2inmodel->skinheight)); - } -#endif - - //frames - ClearBounds ( mod->mins, mod->maxs ); - - poutframe = (galiasgroup_t*)((char *)galias + galias->groupofs); - framesize = LittleLong (pq2inmodel->framesize); - for (i=0 ; inum_frames) ; i++) - { - pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*numverts -#ifndef SERVERONLY - + sizeof(vec3_t)*numverts -#endif - ); - poutframe->poseofs = (char *)pose - (char *)poutframe; - poutframe->numposes = 1; - galias->groups++; - - verts = (vec3_t *)(pose+1); - pose->ofsverts = (char *)verts - (char *)pose; -#ifndef SERVERONLY - normals = &verts[galias->numverts]; - pose->ofsnormals = (char *)normals - (char *)pose; -#endif - - - pinframe = ( dmd2aliasframe_t * )( ( qbyte * )pq2inmodel + LittleLong (pq2inmodel->ofs_frames) + i * framesize ); - Q_strncpyz(poutframe->name, pinframe->name, sizeof(poutframe->name)); - - for (j=0 ; j<3 ; j++) - { - pose->scale[j] = LittleFloat (pinframe->scale[j]); - pose->scale_origin[j] = LittleFloat (pinframe->translate[j]); - } - - for (j=0 ; jscale_origin[0]+pose->scale[0]*pinframe->verts[ptempindex[indremap[j]]].v[0]; - verts[indexes[j]][1] = pose->scale_origin[1]+pose->scale[1]*pinframe->verts[ptempindex[indremap[j]]].v[1]; - verts[indexes[j]][2] = pose->scale_origin[2]+pose->scale[2]*pinframe->verts[ptempindex[indremap[j]]].v[2]; -#ifndef SERVERONLY - VectorCopy(bytedirs[pinframe->verts[ptempindex[indremap[j]]].lightnormalindex], normals[indexes[j]]); -#endif - } - -// Mod_AliasCalculateVertexNormals ( numindexes, poutindex, numverts, poutvertex, qfalse ); - - VectorCopy ( pose->scale_origin, min ); - VectorMA ( pose->scale_origin, 255, pose->scale, max ); - -// poutframe->radius = RadiusFromBounds ( min, max ); - -// mod->radius = max ( mod->radius, poutframe->radius ); - AddPointToBounds ( min, mod->mins, mod->maxs ); - AddPointToBounds ( max, mod->mins, mod->maxs ); - -// GL_GenerateNormals((float*)verts, (float*)normals, indexes, numindexes/3, numverts); - - poutframe++; - } - - - - Mod_CompileTriangleNeighbours(galias); - /* - VectorCopy (pq2inmodel->scale_origin, mod->mins); - VectorMA (mod->mins, 255, pq2inmodel->scale, mod->maxs); - */ - - Mod_ClampModelSize(mod); -// -// move the complete, relocatable alias model to the cache -// - hunkend = Hunk_LowMark (); - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, galias, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - mod->funcs.Trace = Mod_Trace; - - return true; -} - -#endif - - - - - - - - - - - - - - - - -typedef struct { - char name[MAX_QPATH]; - vec3_t org; - float ang[3][3]; -} md3tag_t; - - - -qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) -{ - galiasinfo_t *inf; - - - if (!model || model->type != mod_alias) - return false; - - inf = Mod_Extradata(model); -#ifdef SKELETALMODELS - if (inf->numbones) - { - galiasbone_t *bone; - galiasgroup_t *g1, *g2; - - float tempmatrix[12]; //flipped between this and bonematrix - float *matrix; //the matrix for a single bone in a single pose. - float m[12]; //combined interpolated version of 'matrix'. - int b, k; //counters - - float *pose[4]; //the per-bone matricies (one for each pose) - float plerp[4]; //the ammount of that pose to use (must combine to 1) - int numposes = 0; - - if (tagnum <= 0 || tagnum > inf->numbones) - return false; - tagnum--; //tagnum 0 is 'use my angles/org' - - if (frame1 < 0 || frame1 >= inf->groups) - return false; - if (frame2 < 0 || frame2 >= inf->groups) - { - f2ness = 0; - frame2 = frame1; - } - - bone = (galiasbone_t*)((char*)inf + inf->ofsbones); -//the higher level merges old/new anims, but we still need to blend between automated frame-groups. - g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); - g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); - - f1time *= g1->rate; - frame1 = (int)f1time%g1->numposes; - frame2 = ((int)f1time+1)%g1->numposes; - f1time = f1time - (int)f1time; - pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); - plerp[numposes] = (1-f1time) * (1-f2ness); - numposes++; - if (frame1 != frame2) - { - pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); - plerp[numposes] = f1time * (1-f2ness); - numposes++; - } - if (f2ness) - { - f2time *= g2->rate; - frame1 = (int)f2time%g2->numposes; - frame2 = ((int)f2time+1)%g2->numposes; - f2time = f2time - (int)f2time; - pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); - plerp[numposes] = (1-f2time) * f2ness; - numposes++; - if (frame1 != frame2) - { - pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); - plerp[numposes] = f2time * f2ness; - numposes++; - } - } - - //set up the identity matrix - for (k = 0;k < 12;k++) - result[k] = 0; - result[0] = 1; - result[5] = 1; - result[10] = 1; - while(tagnum >= 0) - { - //set up the per-bone transform matrix - for (k = 0;k < 12;k++) - m[k] = 0; - for (b = 0;b < numposes;b++) - { - matrix = pose[b] + tagnum*12; - - for (k = 0;k < 12;k++) - m[k] += matrix[k] * plerp[b]; - } - - memcpy(tempmatrix, result, sizeof(tempmatrix)); - R_ConcatTransforms((void*)m, (void*)tempmatrix, (void*)result); - - tagnum = bone[tagnum].parent; - } - - return true; - } -#endif - if (inf->numtags) - { - md3tag_t *t1, *t2; - - if (tagnum <= 0 || tagnum > inf->numtags) - return false; - if (frame1 < 0) - return false; - if (frame1 >= inf->numtagframes) - frame1 = inf->numtagframes - 1; - if (frame2 < 0 || frame2 >= inf->numtagframes) - frame2 = frame1; - tagnum--; //tagnum 0 is 'use my angles/org' - - t1 = (md3tag_t*)((char*)inf + inf->ofstags); - t1 += tagnum; - t1 += inf->numtags*frame1; - - t2 = (md3tag_t*)((char*)inf + inf->ofstags); - t2 += tagnum; - t2 += inf->numtags*frame2; - - if (t1 == t2) - { - result[0] = t1->ang[0][0]; - result[1] = t1->ang[0][1]; - result[2] = t1->ang[0][2]; - result[3] = t1->org[0]; - result[4] = t1->ang[1][0]; - result[5] = t1->ang[1][1]; - result[6] = t1->ang[1][2]; - result[7] = t1->org[1]; - result[8] = t1->ang[2][0]; - result[9] = t1->ang[2][1]; - result[10] = t1->ang[2][2]; - result[11] = t1->org[2]; - } - else - { - float f1ness = 1-f2ness; - result[0] = t1->ang[0][0]*f1ness + t2->ang[0][0]*f2ness; - result[1] = t1->ang[0][1]*f1ness + t2->ang[0][1]*f2ness; - result[2] = t1->ang[0][2]*f1ness + t2->ang[0][2]*f2ness; - result[3] = t1->org[0]*f1ness + t2->org[0]*f2ness; - result[4] = t1->ang[1][0]*f1ness + t2->ang[1][0]*f2ness; - result[5] = t1->ang[1][1]*f1ness + t2->ang[1][1]*f2ness; - result[6] = t1->ang[1][2]*f1ness + t2->ang[1][2]*f2ness; - result[7] = t1->org[1]*f1ness + t2->org[1]*f2ness; - result[8] = t1->ang[2][0]*f1ness + t2->ang[2][0]*f2ness; - result[9] = t1->ang[2][1]*f1ness + t2->ang[2][1]*f2ness; - result[10] = t1->ang[2][2]*f1ness + t2->ang[2][2]*f2ness; - result[11] = t1->org[2]*f1ness + t2->org[2]*f2ness; - } - return true; - } - return false; -} - -int Mod_TagNumForName(model_t *model, char *name) -{ - int i; - galiasinfo_t *inf; - md3tag_t *t; - - if (!model || model->type != mod_alias) - return 0; - inf = Mod_Extradata(model); - -#ifdef SKELETALMODELS - if (inf->numbones) - { - galiasbone_t *b; - b = (galiasbone_t*)((char*)inf + inf->ofsbones); - for (i = 0; i < inf->numbones; i++) - { - if (!strcmp(b[i].name, name)) - return i+1; - } - } -#endif - t = (md3tag_t*)((char*)inf + inf->ofstags); - for (i = 0; i < inf->numtags; i++) - { - if (!strcmp(t[i].name, name)) - return i+1; - } - - return 0; -} -#ifndef SERVERONLY -int Mod_SkinNumForName(model_t *model, char *name) -{ - int i; - galiasinfo_t *inf; - galiasskin_t *skin; - - if (!model || model->type != mod_alias) - return -1; - inf = Mod_Extradata(model); - - skin = (galiasskin_t*)((char*)inf+inf->ofsskins); - for (i = 0; i < inf->numskins; i++, skin++) - { - if (!strcmp(skin->name, name)) - return i; - } - - return -1; -} -#endif - - -#ifdef MD3MODELS - -//structures from Tenebrae -typedef struct { - int ident; - int version; - - char name[MAX_QPATH]; - - int flags; //Does anyone know what these are? - - int numFrames; - int numTags; - int numSurfaces; - - int numSkins; - - int ofsFrames; - int ofsTags; - int ofsSurfaces; - int ofsEnd; -} md3Header_t; - -//then has header->numFrames of these at header->ofs_Frames -typedef struct md3Frame_s { - vec3_t bounds[2]; - vec3_t localOrigin; - float radius; - char name[16]; -} md3Frame_t; - -//there are header->numSurfaces of these at header->ofsSurfaces, following from ofsEnd -typedef struct { - int ident; // - - char name[MAX_QPATH]; // polyset name - - int flags; - int numFrames; // all surfaces in a model should have the same - - int numShaders; // all surfaces in a model should have the same - int numVerts; - - int numTriangles; - int ofsTriangles; - - int ofsShaders; // offset from start of md3Surface_t - int ofsSt; // texture coords are common for all frames - int ofsXyzNormals; // numVerts * numFrames - - int ofsEnd; // next surface follows -} md3Surface_t; - -//at surf+surf->ofsXyzNormals -typedef struct { - short xyz[3]; - qbyte latlong[2]; -} md3XyzNormal_t; - -//surf->numTriangles at surf+surf->ofsTriangles -typedef struct { - int indexes[3]; -} md3Triangle_t; - -//surf->numVerts at surf+surf->ofsSt -typedef struct { - float s; - float t; -} md3St_t; - -typedef struct { - char name[MAX_QPATH]; - int shaderIndex; -} md3Shader_t; -//End of Tenebrae 'assistance' - -qboolean Mod_LoadQ3Model(model_t *mod, void *buffer) -{ -#ifndef SERVERONLY - galiasskin_t *skin; - galiastexnum_t *texnum; - float lat, lng; - md3St_t *inst; - vec3_t *normals; - vec2_t *st_array; - md3Shader_t *inshader; -#endif - int hunkstart, hunkend, hunktotal; -// int version; - int s, i, j, d; - - index_t *indexes; - - vec3_t min; - vec3_t max; - - galiaspose_t *pose; - galiasinfo_t *parent, *root; - galiasgroup_t *group; - - vec3_t *verts; - - md3Triangle_t *intris; - md3XyzNormal_t *invert; - - - int size; - int externalskins; - - md3Header_t *header; - md3Surface_t *surf; - - - loadmodel=mod; - - Mod_DoCRC(mod, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - header = buffer; - -// if (header->version != sdfs) -// Sys_Error("GL_LoadQ3Model: Bad version\n"); - - parent = NULL; - root = NULL; - -#ifndef SERVERONLY - externalskins = Mod_BuildSkinFileList(mod->name); -#else - externalskins = 0; -#endif - - min[0] = min[1] = min[2] = 0; - max[0] = max[1] = max[2] = 0; - - surf = (md3Surface_t *)((qbyte *)header + LittleLong(header->ofsSurfaces)); - for (s = 0; s < LittleLong(header->numSurfaces); s++) - { - if (LittleLong(surf->ident) != MD3_IDENT) - Con_Printf(CON_WARNING "Warning: md3 sub-surface doesn't match ident\n"); - size = sizeof(galiasinfo_t) + sizeof(galiasgroup_t)*LittleLong(header->numFrames); - galias = Hunk_Alloc(size); - galias->groupofs = sizeof(*galias); //frame groups - galias->groups = LittleLong(header->numFrames); - galias->numverts = LittleLong(surf->numVerts); - galias->numindexes = LittleLong(surf->numTriangles)*3; - if (parent) - parent->nextsurf = (qbyte *)galias - (qbyte *)parent; - else - root = galias; - parent = galias; - -#ifndef SERVERONLY - st_array = Hunk_Alloc(sizeof(vec2_t)*galias->numindexes); - galias->ofs_st_array = (qbyte*)st_array - (qbyte*)galias; - inst = (md3St_t*)((qbyte*)surf + LittleLong(surf->ofsSt)); - for (i = 0; i < galias->numverts; i++) - { - st_array[i][0] = LittleFloat(inst[i].s); - st_array[i][1] = LittleFloat(inst[i].t); - } -#endif - - indexes = Hunk_Alloc(sizeof(*indexes)*galias->numindexes); - galias->ofs_indexes = (qbyte*)indexes - (qbyte*)galias; - intris = (md3Triangle_t *)((qbyte*)surf + LittleLong(surf->ofsTriangles)); - for (i = 0; i < LittleLong(surf->numTriangles); i++) - { - indexes[i*3+0] = LittleLong(intris[i].indexes[0]); - indexes[i*3+1] = LittleLong(intris[i].indexes[1]); - indexes[i*3+2] = LittleLong(intris[i].indexes[2]); - } - - group = (galiasgroup_t *)(galias+1); - invert = (md3XyzNormal_t *)((qbyte*)surf + LittleLong(surf->ofsXyzNormals)); - for (i = 0; i < LittleLong(surf->numFrames); i++) - { - pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*LittleLong(surf->numVerts) -#ifndef SERVERONLY - + sizeof(vec3_t)*LittleLong(surf->numVerts) -#endif - ); - - verts = (vec3_t*)(pose+1); - pose->ofsverts = (qbyte*)verts - (qbyte*)pose; -#ifndef SERVERONLY - normals = verts + LittleLong(surf->numVerts); - pose->ofsnormals = (qbyte*)normals - (qbyte*)pose; -#endif - - for (j = 0; j < LittleLong(surf->numVerts); j++) - { -#ifndef SERVERONLY - lat = (float)invert[j].latlong[0] * (2 * M_PI)*(1.0 / 255.0); - lng = (float)invert[j].latlong[1] * (2 * M_PI)*(1.0 / 255.0); - normals[j][0] = cos ( lng ) * sin ( lat ); - normals[j][1] = sin ( lng ) * sin ( lat ); - normals[j][2] = cos ( lat ); -#endif - for (d = 0; d < 3; d++) - { - verts[j][d] = LittleShort(invert[j].xyz[d])/64.0f; - if (verts[j][d]max[d]) - max[d] = verts[j][d]; - } - } - - pose->scale[0] = 1; - pose->scale[1] = 1; - pose->scale[2] = 1; - - pose->scale_origin[0] = 0; - pose->scale_origin[1] = 0; - pose->scale_origin[2] = 0; - - snprintf(group->name, sizeof(group->name)-1, "frame%i", i); - - group->numposes = 1; - group->rate = 1; - group->poseofs = (qbyte*)pose - (qbyte*)group; - - group++; - invert += LittleLong(surf->numVerts); - } - -#ifndef SERVERONLY - if (externalskinsnumShaders)) - externalskins = LittleLong(surf->numShaders); - if (externalskins) - { -#ifndef Q3SHADERS - char name[1024]; - extern int gl_bumpmappingpossible; -#endif - char shadname[1024]; - - skin = Hunk_Alloc((LittleLong(surf->numShaders)+externalskins)*((sizeof(galiasskin_t)+sizeof(galiastexnum_t)))); - galias->ofsskins = (qbyte *)skin - (qbyte *)galias; - texnum = (galiastexnum_t *)(skin + LittleLong(surf->numShaders)+externalskins); - inshader = (md3Shader_t *)((qbyte *)surf + LittleLong(surf->ofsShaders)); - for (i = 0; i < externalskins; i++) - { - skin->texnums = 1; - skin->ofstexnums = (qbyte *)texnum - (qbyte *)skin; - skin->ofstexels = 0; - skin->skinwidth = 0; - skin->skinheight = 0; - skin->skinspeed = 0; - - shadname[0] = '\0'; - - Mod_ParseQ3SkinFile(shadname, surf->name, loadmodel->name, i, skin->name); - - if (!*shadname) - { - if (i >= LittleLong(surf->numShaders)) - strcpy(shadname, "missingskin"); //this shouldn't be possible - else - strcpy(shadname, inshader->name); - - Q_strncpyz(skin->name, shadname, sizeof(skin->name)); - } - -#ifdef Q3SHADERS - if (qrenderer) - { - texnum->shader = R_RegisterSkin(shadname); - - if (r_shadows.value) //real-time shadows requires a texture to lighten the model with, even if it has a shader. - //fixme: this should be read from the shader. - texnum->base = Mod_LoadHiResTexture(shadname, "models", true, true, true); - } -#else - - texnum->base = Mod_LoadHiResTexture(shadname, "models", true, true, true); - if (!texnum->base) - { - strcpy(name, loadmodel->name); - strcpy(COM_SkipPath(name), COM_SkipPath(shadname)); //eviile eh? - texnum->base = Mod_LoadHiResTexture(name, "models", true, true, true); - } - - texnum->bump = 0; - if (gl_bumpmappingpossible) - { - COM_StripExtension(shadname, name, sizeof(name)); //go for the normalmap - strcat(name, "_norm"); - texnum->bump = Mod_LoadHiResTexture(name, "models", true, true, false); - if (!texnum->bump) - { - strcpy(name, loadmodel->name); - COM_StripExtension(COM_SkipPath(shadname), COM_SkipPath(name), sizeof(name)); - strcat(name, "_norm"); - texnum->bump = Mod_LoadHiResTexture(name, "models", true, true, false); - if (!texnum->bump) - { - COM_StripExtension(shadname, name, sizeof(name)); //bother, go for heightmap and convert - strcat(name, "_bump"); - texnum->bump = Mod_LoadBumpmapTexture(name, "models"); - if (!texnum->bump) - { - strcpy(name, loadmodel->name); - strcpy(COM_SkipPath(name), COM_SkipPath(shadname)); //eviile eh? - COM_StripExtension(name, name, sizeof(name)); - strcat(name, "_bump"); - texnum->bump = Mod_LoadBumpmapTexture(name, "models"); - } - } - } - } - if (r_fb_models.value) - { - COM_StripExtension(shadname, name, sizeof(name)); //go for the normalmap - strcat(name, "_luma"); - texnum->fullbright = Mod_LoadHiResTexture(name, "models", true, true, true); - if (!texnum->base) - { - strcpy(name, loadmodel->name); - strcpy(COM_SkipPath(name), COM_SkipPath(shadname)); //eviile eh? - COM_StripExtension(name, name, sizeof(name)); - strcat(name, "_luma"); - texnum->fullbright = Mod_LoadBumpmapTexture(name, "models"); - } - } + texnums->upperoverlay = 0; + } + pskintype = (daliasskintype_t *)data; + break; + } + outskin++; + } + galias->numskins=pq1inmodel->numskins; + return pskintype; +} +#endif + +qboolean Mod_LoadQ1Model (model_t *mod, void *buffer) +{ +#ifndef SERVERONLY + vec2_t *st_array; + int j; +#endif + int hunkstart, hunkend, hunktotal; + int version; + int i, onseams; + dstvert_t *pinstverts; + dtriangle_t *pintriangles; + int *seamremap; + index_t *indexes; + qboolean qtest = false; + daliasskintype_t *skinstart; + int skintranstype; + + int size; + + loadmodel=mod; + + Mod_DoCRC(loadmodel, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + pq1inmodel = (dmdl_t *)buffer; + + loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; + + version = LittleLong(pq1inmodel->version); + if (version == QTESTALIAS_VERSION) + qtest = true; + else if (version != ALIAS_VERSION) + { + Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n", + mod->name, version, ALIAS_VERSION); + return false; + } + + seamremap = (int*)pq1inmodel; //I like overloading locals. + + if (qtest) + i = sizeof(dmdl_t)/4 - sizeof(int)*2 - 1; + else + i = sizeof(dmdl_t)/4 - 1; + + for (; i >= 0; i--) + seamremap[i] = LittleLong(seamremap[i]); + + if (pq1inmodel->numframes < 1 || + pq1inmodel->numskins < 1 || + pq1inmodel->numtris < 1 || + pq1inmodel->numverts < 3 || + pq1inmodel->skinheight < 1 || + pq1inmodel->skinwidth < 1) + { + Con_Printf(CON_ERROR "Model %s has an invalid quantity\n", mod->name); + return false; + } + + if (qtest) + mod->flags = 0; // Qtest has no flags in header + else + mod->flags = pq1inmodel->flags; + + size = sizeof(galiasinfo_t) +#ifndef SERVERONLY + + pq1inmodel->numskins*sizeof(galiasskin_t) +#endif + + pq1inmodel->numframes*sizeof(galiasgroup_t); + + galias = Hunk_Alloc(size); + galias->groupofs = sizeof(*galias); +#ifndef SERVERONLY + galias->ofsskins = sizeof(*galias)+pq1inmodel->numframes*sizeof(galiasgroup_t); +#endif + galias->nextsurf = 0; + +//skins + if (qtest) + skinstart = (daliasskintype_t *)((char *)buffer + sizeof(dmdl_t) - sizeof(int)*2); + else + skinstart = (daliasskintype_t *)(pq1inmodel+1); + if( mod->flags & EFH2_HOLEY ) + skintranstype = 3; //hexen2 + else if( mod->flags & EFH2_TRANSPARENT ) + skintranstype = 2; //hexen2 + else if( mod->flags & EFH2_SPECIAL_TRANS ) + skintranstype = 4; //hexen2 + else + skintranstype = 0; + + switch(qrenderer) + { +#if defined(RGLQUAKE) || defined(D3DQUAKE) + case QR_DIRECT3D: + case QR_OPENGL: + pinstverts = (dstvert_t *)Q1_LoadSkins_GL(skinstart, skintranstype); + break; +#endif + default: + pinstverts = (dstvert_t *)Q1_LoadSkins_SV(skinstart, skintranstype); + break; + } + + + + //count number of verts that are onseam. + for (onseams=0,i = 0; i < pq1inmodel->numverts; i++) + { + if (pinstverts[i].onseam) + onseams++; + } + seamremap = BZ_Malloc(sizeof(int)*pq1inmodel->numverts); + + galias->numverts = pq1inmodel->numverts+onseams; + + //st +#ifndef SERVERONLY + st_array = Hunk_Alloc(sizeof(*st_array)*(pq1inmodel->numverts+onseams)); + galias->ofs_st_array = (char *)st_array - (char *)galias; + for (j=pq1inmodel->numverts,i = 0; i < pq1inmodel->numverts; i++) + { + st_array[i][0] = (LittleLong(pinstverts[i].s)+0.5)/(float)pq1inmodel->skinwidth; + st_array[i][1] = (LittleLong(pinstverts[i].t)+0.5)/(float)pq1inmodel->skinheight; + + if (pinstverts[i].onseam) + { + st_array[j][0] = st_array[i][0]+0.5; + st_array[j][1] = st_array[i][1]; + seamremap[i] = j; + j++; + } + else + seamremap[i] = i; + } +#endif + + //trianglelists; + pintriangles = (dtriangle_t *)&pinstverts[pq1inmodel->numverts]; + + galias->numindexes = pq1inmodel->numtris*3; + indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); + galias->ofs_indexes = (char *)indexes - (char *)galias; + for (i=0 ; inumtris ; i++) + { + if (!pintriangles[i].facesfront) + { + indexes[i*3+0] = seamremap[LittleLong(pintriangles[i].vertindex[0])]; + indexes[i*3+1] = seamremap[LittleLong(pintriangles[i].vertindex[1])]; + indexes[i*3+2] = seamremap[LittleLong(pintriangles[i].vertindex[2])]; + } + else + { + indexes[i*3+0] = LittleLong(pintriangles[i].vertindex[0]); + indexes[i*3+1] = LittleLong(pintriangles[i].vertindex[1]); + indexes[i*3+2] = LittleLong(pintriangles[i].vertindex[2]); + } + } + + //frames + if (qtest) + { + if (QTest_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap) == NULL) + { + BZ_Free(seamremap); + Hunk_FreeToLowMark (hunkstart); + return false; + } + } + else + { + if (Q1_LoadFrameGroup((daliasframetype_t *)&pintriangles[pq1inmodel->numtris], seamremap) == NULL) + { + BZ_Free(seamremap); + Hunk_FreeToLowMark (hunkstart); + return false; + } + } + BZ_Free(seamremap); + + + Mod_CompileTriangleNeighbours(galias); + + VectorCopy (pq1inmodel->scale_origin, mod->mins); + VectorMA (mod->mins, 255, pq1inmodel->scale, mod->maxs); + + Mod_ClampModelSize(mod); +// +// move the complete, relocatable alias model to the cache +// + hunkend = Hunk_LowMark (); + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, galias, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + mod->funcs.Trace = Mod_Trace; + + return true; +} +#endif + + +int Mod_ReadFlagsFromMD1(char *name, int md3version) +{ + dmdl_t *pinmodel; + char fname[MAX_QPATH]; + COM_StripExtension(name, fname, sizeof(fname)); + COM_DefaultExtension(fname, ".mdl", sizeof(fname)); + + if (strcmp(name, fname)) //md3 renamed as mdl + { + COM_StripExtension(name, fname, sizeof(fname)); //seeing as the md3 is named over the mdl, + COM_DefaultExtension(fname, ".md1", sizeof(fname));//read from a file with md1 (one, not an ell) + return 0; + } + + pinmodel = (dmdl_t *)COM_LoadTempFile(fname); + + if (!pinmodel) //not found + return 0; + + if (LittleLong(pinmodel->ident) != IDPOLYHEADER) + return 0; + if (LittleLong(pinmodel->version) != ALIAS_VERSION) + return 0; + return LittleLong(pinmodel->flags); +} + +#ifdef MD2MODELS + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Q2 model loading + +typedef struct +{ + float scale[3]; // multiply qbyte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + dtrivertx_t verts[1]; // variable sized +} dmd2aliasframe_t; + +//static galiasinfo_t *galias; +//static md2_t *pq2inmodel; +#define Q2NUMVERTEXNORMALS 162 +extern vec3_t bytedirs[Q2NUMVERTEXNORMALS]; + +static void Q2_LoadSkins(md2_t *pq2inmodel, char *skins) +{ +#ifndef SERVERONLY + int i; + galiastexnum_t *texnums; + galiasskin_t *outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); + + for (i = 0; i < LittleLong(pq2inmodel->num_skins); i++, outskin++) + { + texnums = Hunk_Alloc(sizeof(*texnums)); + outskin->ofstexnums = (char *)texnums - (char *)outskin; + outskin->texnums=1; + + COM_CleanUpPath(skins); //blooming tanks. + texnums->base = Mod_LoadReplacementTexture(skins, "models", true, false, true); +#ifdef Q3SHADERS + texnums->shader = R_RegisterCustom(skins, NULL); + if (!texnums->base && !texnums->shader) + Con_Printf("Couldn't load %s\n", skins); +#endif + outskin->skinwidth = 0; + outskin->skinheight = 0; + outskin->skinspeed = 0; + + skins += MD2MAX_SKINNAME; + } +#endif + galias->numskins = LittleLong(pq2inmodel->num_skins); + +#ifndef SERVERONLY + outskin = (galiasskin_t *)((char *)galias + galias->ofsskins); + outskin += galias->numskins - 1; + if (galias->numskins) + { + texnums = (galiastexnum_t*)((char *)outskin +outskin->ofstexnums); + if (texnums->base) + return; +#ifdef Q3SHADERS + if (texnums->shader) + return; +#endif + + galias->numskins--; + } +#endif +} + +#define MD2_MAX_TRIANGLES 4096 +qboolean Mod_LoadQ2Model (model_t *mod, void *buffer) +{ +#ifndef SERVERONLY + dmd2stvert_t *pinstverts; + vec2_t *st_array; + vec3_t *normals; +#endif + md2_t *pq2inmodel; + + int hunkstart, hunkend, hunktotal; + int version; + int i, j; + dmd2triangle_t *pintri; + index_t *indexes; + int numindexes; + + vec3_t min; + vec3_t max; + + galiaspose_t *pose; + galiasgroup_t *poutframe; + dmd2aliasframe_t *pinframe; + int framesize; + vec3_t *verts; + + int indremap[MD2_MAX_TRIANGLES*3]; + unsigned short ptempindex[MD2_MAX_TRIANGLES*3], ptempstindex[MD2_MAX_TRIANGLES*3]; + + int numverts; + + int size; + + + loadmodel=mod; + + loadmodel->engineflags |= MDLF_NEEDOVERBRIGHT; + + Mod_DoCRC(mod, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + pq2inmodel = (md2_t *)buffer; + + version = LittleLong (pq2inmodel->version); + if (version != MD2ALIAS_VERSION) + { + Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n", + mod->name, version, MD2ALIAS_VERSION); + return false; + } + + if (LittleLong(pq2inmodel->num_frames) < 1 || + LittleLong(pq2inmodel->num_skins) < 0 || + LittleLong(pq2inmodel->num_tris) < 1 || + LittleLong(pq2inmodel->num_xyz) < 3 || + LittleLong(pq2inmodel->num_st) < 3 || + LittleLong(pq2inmodel->skinheight) < 1 || + LittleLong(pq2inmodel->skinwidth) < 1) + { + Con_Printf(CON_ERROR "Model %s has an invalid quantity\n", mod->name); + return false; + } + + mod->flags = 0; + + loadmodel->numframes = LittleLong(pq2inmodel->num_frames); + + size = sizeof(galiasinfo_t) +#ifndef SERVERONLY + + LittleLong(pq2inmodel->num_skins)*sizeof(galiasskin_t) +#endif + + LittleLong(pq2inmodel->num_frames)*sizeof(galiasgroup_t); + + galias = Hunk_Alloc(size); + galias->groupofs = sizeof(*galias); +#ifndef SERVERONLY + galias->ofsskins = sizeof(*galias)+LittleLong(pq2inmodel->num_frames)*sizeof(galiasgroup_t); +#endif + galias->nextsurf = 0; + +//skins + Q2_LoadSkins(pq2inmodel, ((char *)pq2inmodel+LittleLong(pq2inmodel->ofs_skins))); + + //trianglelists; + pintri = (dmd2triangle_t *)((char *)pq2inmodel + LittleLong(pq2inmodel->ofs_tris)); + + + for (i=0 ; inum_tris) ; i++, pintri++) + { + for (j=0 ; j<3 ; j++) + { + ptempindex[i*3+j] = ( unsigned short )LittleShort ( pintri->xyz_index[j] ); + ptempstindex[i*3+j] = ( unsigned short )LittleShort ( pintri->st_index[j] ); + } + } + + numindexes = galias->numindexes = LittleLong(pq2inmodel->num_tris)*3; + indexes = Hunk_Alloc(galias->numindexes*sizeof(*indexes)); + galias->ofs_indexes = (char *)indexes - (char *)galias; + memset ( indremap, -1, sizeof(indremap) ); + numverts=0; + + for ( i = 0; i < numindexes; i++ ) + { + if ( indremap[i] != -1 ) { + continue; + } + + for ( j = 0; j < numindexes; j++ ) + { + if ( j == i ) { + continue; + } + + if ( (ptempindex[i] == ptempindex[j]) && (ptempstindex[i] == ptempstindex[j]) ) { + indremap[j] = i; + } + } + } + + // count unique vertexes + for ( i = 0; i < numindexes; i++ ) + { + if ( indremap[i] != -1 ) { + continue; + } + + indexes[i] = numverts++; + indremap[i] = i; + } + + Con_DPrintf ( "%s: remapped %i verts to %i\n", mod->name, LittleLong(pq2inmodel->num_xyz), numverts ); + + galias->numverts = numverts; + + // remap remaining indexes + for ( i = 0; i < numindexes; i++ ) + { + if ( indremap[i] != i ) { + indexes[i] = indexes[indremap[i]]; + } + } + +// s and t vertices +#ifndef SERVERONLY + pinstverts = ( dmd2stvert_t * ) ( ( qbyte * )pq2inmodel + LittleLong (pq2inmodel->ofs_st) ); + st_array = Hunk_Alloc(sizeof(*st_array)*(numverts)); + galias->ofs_st_array = (char *)st_array - (char *)galias; + + for (j=0 ; jskinwidth)); + st_array[indexes[j]][1] = (float)(((double)LittleShort (pinstverts[ptempstindex[indremap[j]]].t) + 0.5f) /LittleLong(pq2inmodel->skinheight)); + } +#endif + + //frames + ClearBounds ( mod->mins, mod->maxs ); + + poutframe = (galiasgroup_t*)((char *)galias + galias->groupofs); + framesize = LittleLong (pq2inmodel->framesize); + for (i=0 ; inum_frames) ; i++) + { + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*numverts +#ifndef SERVERONLY + + sizeof(vec3_t)*numverts +#endif + ); + poutframe->poseofs = (char *)pose - (char *)poutframe; + poutframe->numposes = 1; + galias->groups++; + + verts = (vec3_t *)(pose+1); + pose->ofsverts = (char *)verts - (char *)pose; +#ifndef SERVERONLY + normals = &verts[galias->numverts]; + pose->ofsnormals = (char *)normals - (char *)pose; +#endif + + + pinframe = ( dmd2aliasframe_t * )( ( qbyte * )pq2inmodel + LittleLong (pq2inmodel->ofs_frames) + i * framesize ); + Q_strncpyz(poutframe->name, pinframe->name, sizeof(poutframe->name)); + + for (j=0 ; j<3 ; j++) + { + pose->scale[j] = LittleFloat (pinframe->scale[j]); + pose->scale_origin[j] = LittleFloat (pinframe->translate[j]); + } + + for (j=0 ; jscale_origin[0]+pose->scale[0]*pinframe->verts[ptempindex[indremap[j]]].v[0]; + verts[indexes[j]][1] = pose->scale_origin[1]+pose->scale[1]*pinframe->verts[ptempindex[indremap[j]]].v[1]; + verts[indexes[j]][2] = pose->scale_origin[2]+pose->scale[2]*pinframe->verts[ptempindex[indremap[j]]].v[2]; +#ifndef SERVERONLY + VectorCopy(bytedirs[pinframe->verts[ptempindex[indremap[j]]].lightnormalindex], normals[indexes[j]]); +#endif + } + +// Mod_AliasCalculateVertexNormals ( numindexes, poutindex, numverts, poutvertex, qfalse ); + + VectorCopy ( pose->scale_origin, min ); + VectorMA ( pose->scale_origin, 255, pose->scale, max ); + +// poutframe->radius = RadiusFromBounds ( min, max ); + +// mod->radius = max ( mod->radius, poutframe->radius ); + AddPointToBounds ( min, mod->mins, mod->maxs ); + AddPointToBounds ( max, mod->mins, mod->maxs ); + +// GL_GenerateNormals((float*)verts, (float*)normals, indexes, numindexes/3, numverts); + + poutframe++; + } + + + + Mod_CompileTriangleNeighbours(galias); + /* + VectorCopy (pq2inmodel->scale_origin, mod->mins); + VectorMA (mod->mins, 255, pq2inmodel->scale, mod->maxs); + */ + + Mod_ClampModelSize(mod); +// +// move the complete, relocatable alias model to the cache +// + hunkend = Hunk_LowMark (); + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, galias, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + mod->funcs.Trace = Mod_Trace; + + return true; +} + +#endif + + + + + + + + + + + + + + + + +typedef struct { + char name[MAX_QPATH]; + vec3_t org; + float ang[3][3]; +} md3tag_t; + + + +qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) +{ + galiasinfo_t *inf; + + + if (!model || model->type != mod_alias) + return false; + + inf = Mod_Extradata(model); +#ifdef SKELETALMODELS + if (inf->numbones) + { + galiasbone_t *bone; + galiasgroup_t *g1, *g2; + + float tempmatrix[12]; //flipped between this and bonematrix + float *matrix; //the matrix for a single bone in a single pose. + float m[12]; //combined interpolated version of 'matrix'. + int b, k; //counters + + float *pose[4]; //the per-bone matricies (one for each pose) + float plerp[4]; //the ammount of that pose to use (must combine to 1) + int numposes = 0; + + if (tagnum <= 0 || tagnum > inf->numbones) + return false; + tagnum--; //tagnum 0 is 'use my angles/org' + + if (frame1 < 0 || frame1 >= inf->groups) + return false; + if (frame2 < 0 || frame2 >= inf->groups) + { + f2ness = 0; + frame2 = frame1; + } + + bone = (galiasbone_t*)((char*)inf + inf->ofsbones); +//the higher level merges old/new anims, but we still need to blend between automated frame-groups. + g1 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame1); + g2 = (galiasgroup_t*)((char *)inf + inf->groupofs + sizeof(galiasgroup_t)*frame2); + + f1time *= g1->rate; + frame1 = (int)f1time%g1->numposes; + frame2 = ((int)f1time+1)%g1->numposes; + f1time = f1time - (int)f1time; + pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[numposes] = (1-f1time) * (1-f2ness); + numposes++; + if (frame1 != frame2) + { + pose[numposes] = (float *)((char *)g1 + g1->poseofs + sizeof(float)*inf->numbones*12*frame2); + plerp[numposes] = f1time * (1-f2ness); + numposes++; + } + if (f2ness) + { + f2time *= g2->rate; + frame1 = (int)f2time%g2->numposes; + frame2 = ((int)f2time+1)%g2->numposes; + f2time = f2time - (int)f2time; + pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame1); + plerp[numposes] = (1-f2time) * f2ness; + numposes++; + if (frame1 != frame2) + { + pose[numposes] = (float *)((char *)g2 + g2->poseofs + sizeof(float)*inf->numbones*12*frame2); + plerp[numposes] = f2time * f2ness; + numposes++; + } + } + + //set up the identity matrix + for (k = 0;k < 12;k++) + result[k] = 0; + result[0] = 1; + result[5] = 1; + result[10] = 1; + while(tagnum >= 0) + { + //set up the per-bone transform matrix + for (k = 0;k < 12;k++) + m[k] = 0; + for (b = 0;b < numposes;b++) + { + matrix = pose[b] + tagnum*12; + + for (k = 0;k < 12;k++) + m[k] += matrix[k] * plerp[b]; + } + + memcpy(tempmatrix, result, sizeof(tempmatrix)); + R_ConcatTransforms((void*)m, (void*)tempmatrix, (void*)result); + + tagnum = bone[tagnum].parent; + } + + return true; + } +#endif + if (inf->numtags) + { + md3tag_t *t1, *t2; + + if (tagnum <= 0 || tagnum > inf->numtags) + return false; + if (frame1 < 0) + return false; + if (frame1 >= inf->numtagframes) + frame1 = inf->numtagframes - 1; + if (frame2 < 0 || frame2 >= inf->numtagframes) + frame2 = frame1; + tagnum--; //tagnum 0 is 'use my angles/org' + + t1 = (md3tag_t*)((char*)inf + inf->ofstags); + t1 += tagnum; + t1 += inf->numtags*frame1; + + t2 = (md3tag_t*)((char*)inf + inf->ofstags); + t2 += tagnum; + t2 += inf->numtags*frame2; + + if (t1 == t2) + { + result[0] = t1->ang[0][0]; + result[1] = t1->ang[0][1]; + result[2] = t1->ang[0][2]; + result[3] = t1->org[0]; + result[4] = t1->ang[1][0]; + result[5] = t1->ang[1][1]; + result[6] = t1->ang[1][2]; + result[7] = t1->org[1]; + result[8] = t1->ang[2][0]; + result[9] = t1->ang[2][1]; + result[10] = t1->ang[2][2]; + result[11] = t1->org[2]; + } + else + { + float f1ness = 1-f2ness; + result[0] = t1->ang[0][0]*f1ness + t2->ang[0][0]*f2ness; + result[1] = t1->ang[0][1]*f1ness + t2->ang[0][1]*f2ness; + result[2] = t1->ang[0][2]*f1ness + t2->ang[0][2]*f2ness; + result[3] = t1->org[0]*f1ness + t2->org[0]*f2ness; + result[4] = t1->ang[1][0]*f1ness + t2->ang[1][0]*f2ness; + result[5] = t1->ang[1][1]*f1ness + t2->ang[1][1]*f2ness; + result[6] = t1->ang[1][2]*f1ness + t2->ang[1][2]*f2ness; + result[7] = t1->org[1]*f1ness + t2->org[1]*f2ness; + result[8] = t1->ang[2][0]*f1ness + t2->ang[2][0]*f2ness; + result[9] = t1->ang[2][1]*f1ness + t2->ang[2][1]*f2ness; + result[10] = t1->ang[2][2]*f1ness + t2->ang[2][2]*f2ness; + result[11] = t1->org[2]*f1ness + t2->org[2]*f2ness; + } + + VectorNormalize(result); + VectorNormalize(result+4); + VectorNormalize(result+8); + + return true; + } + return false; +} + +int Mod_TagNumForName(model_t *model, char *name) +{ + int i; + galiasinfo_t *inf; + md3tag_t *t; + + if (!model || model->type != mod_alias) + return 0; + inf = Mod_Extradata(model); + +#ifdef SKELETALMODELS + if (inf->numbones) + { + galiasbone_t *b; + b = (galiasbone_t*)((char*)inf + inf->ofsbones); + for (i = 0; i < inf->numbones; i++) + { + if (!strcmp(b[i].name, name)) + return i+1; + } + } +#endif + t = (md3tag_t*)((char*)inf + inf->ofstags); + for (i = 0; i < inf->numtags; i++) + { + if (!strcmp(t[i].name, name)) + return i+1; + } + + return 0; +} +#ifndef SERVERONLY +int Mod_SkinNumForName(model_t *model, char *name) +{ + int i; + galiasinfo_t *inf; + galiasskin_t *skin; + + if (!model || model->type != mod_alias) + return -1; + inf = Mod_Extradata(model); + + skin = (galiasskin_t*)((char*)inf+inf->ofsskins); + for (i = 0; i < inf->numskins; i++, skin++) + { + if (!strcmp(skin->name, name)) + return i; + } + + return -1; +} +#endif + + +#ifdef MD3MODELS + +//structures from Tenebrae +typedef struct { + int ident; + int version; + + char name[MAX_QPATH]; + + int flags; //Does anyone know what these are? + + int numFrames; + int numTags; + int numSurfaces; + + int numSkins; + + int ofsFrames; + int ofsTags; + int ofsSurfaces; + int ofsEnd; +} md3Header_t; + +//then has header->numFrames of these at header->ofs_Frames +typedef struct md3Frame_s { + vec3_t bounds[2]; + vec3_t localOrigin; + float radius; + char name[16]; +} md3Frame_t; + +//there are header->numSurfaces of these at header->ofsSurfaces, following from ofsEnd +typedef struct { + int ident; // + + char name[MAX_QPATH]; // polyset name + + int flags; + int numFrames; // all surfaces in a model should have the same + + int numShaders; // all surfaces in a model should have the same + int numVerts; + + int numTriangles; + int ofsTriangles; + + int ofsShaders; // offset from start of md3Surface_t + int ofsSt; // texture coords are common for all frames + int ofsXyzNormals; // numVerts * numFrames + + int ofsEnd; // next surface follows +} md3Surface_t; + +//at surf+surf->ofsXyzNormals +typedef struct { + short xyz[3]; + qbyte latlong[2]; +} md3XyzNormal_t; + +//surf->numTriangles at surf+surf->ofsTriangles +typedef struct { + int indexes[3]; +} md3Triangle_t; + +//surf->numVerts at surf+surf->ofsSt +typedef struct { + float s; + float t; +} md3St_t; + +typedef struct { + char name[MAX_QPATH]; + int shaderIndex; +} md3Shader_t; +//End of Tenebrae 'assistance' + +qboolean Mod_LoadQ3Model(model_t *mod, void *buffer) +{ +#ifndef SERVERONLY + galiasskin_t *skin; + galiastexnum_t *texnum; + float lat, lng; + md3St_t *inst; + vec3_t *normals; + vec2_t *st_array; + md3Shader_t *inshader; +#endif + int hunkstart, hunkend, hunktotal; +// int version; + int s, i, j, d; + + index_t *indexes; + + vec3_t min; + vec3_t max; + + galiaspose_t *pose; + galiasinfo_t *parent, *root; + galiasgroup_t *group; + + vec3_t *verts; + + md3Triangle_t *intris; + md3XyzNormal_t *invert; + + + int size; + int externalskins; + + md3Header_t *header; + md3Surface_t *surf; + + + loadmodel=mod; + + Mod_DoCRC(mod, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + header = buffer; + +// if (header->version != sdfs) +// Sys_Error("GL_LoadQ3Model: Bad version\n"); + + parent = NULL; + root = NULL; + +#ifndef SERVERONLY + externalskins = Mod_BuildSkinFileList(mod->name); +#else + externalskins = 0; +#endif + + min[0] = min[1] = min[2] = 0; + max[0] = max[1] = max[2] = 0; + + surf = (md3Surface_t *)((qbyte *)header + LittleLong(header->ofsSurfaces)); + for (s = 0; s < LittleLong(header->numSurfaces); s++) + { + if (LittleLong(surf->ident) != MD3_IDENT) + Con_Printf(CON_WARNING "Warning: md3 sub-surface doesn't match ident\n"); + size = sizeof(galiasinfo_t) + sizeof(galiasgroup_t)*LittleLong(header->numFrames); + galias = Hunk_Alloc(size); + galias->groupofs = sizeof(*galias); //frame groups + galias->groups = LittleLong(header->numFrames); + galias->numverts = LittleLong(surf->numVerts); + galias->numindexes = LittleLong(surf->numTriangles)*3; + if (parent) + parent->nextsurf = (qbyte *)galias - (qbyte *)parent; + else + root = galias; + parent = galias; + +#ifndef SERVERONLY + st_array = Hunk_Alloc(sizeof(vec2_t)*galias->numindexes); + galias->ofs_st_array = (qbyte*)st_array - (qbyte*)galias; + inst = (md3St_t*)((qbyte*)surf + LittleLong(surf->ofsSt)); + for (i = 0; i < galias->numverts; i++) + { + st_array[i][0] = LittleFloat(inst[i].s); + st_array[i][1] = LittleFloat(inst[i].t); + } +#endif + + indexes = Hunk_Alloc(sizeof(*indexes)*galias->numindexes); + galias->ofs_indexes = (qbyte*)indexes - (qbyte*)galias; + intris = (md3Triangle_t *)((qbyte*)surf + LittleLong(surf->ofsTriangles)); + for (i = 0; i < LittleLong(surf->numTriangles); i++) + { + indexes[i*3+0] = LittleLong(intris[i].indexes[0]); + indexes[i*3+1] = LittleLong(intris[i].indexes[1]); + indexes[i*3+2] = LittleLong(intris[i].indexes[2]); + } + + group = (galiasgroup_t *)(galias+1); + invert = (md3XyzNormal_t *)((qbyte*)surf + LittleLong(surf->ofsXyzNormals)); + for (i = 0; i < LittleLong(surf->numFrames); i++) + { + pose = (galiaspose_t *)Hunk_Alloc(sizeof(galiaspose_t) + sizeof(vec3_t)*LittleLong(surf->numVerts) +#ifndef SERVERONLY + + sizeof(vec3_t)*LittleLong(surf->numVerts) +#endif + ); + + verts = (vec3_t*)(pose+1); + pose->ofsverts = (qbyte*)verts - (qbyte*)pose; +#ifndef SERVERONLY + normals = verts + LittleLong(surf->numVerts); + pose->ofsnormals = (qbyte*)normals - (qbyte*)pose; +#endif + + for (j = 0; j < LittleLong(surf->numVerts); j++) + { +#ifndef SERVERONLY + lat = (float)invert[j].latlong[0] * (2 * M_PI)*(1.0 / 255.0); + lng = (float)invert[j].latlong[1] * (2 * M_PI)*(1.0 / 255.0); + normals[j][0] = cos ( lng ) * sin ( lat ); + normals[j][1] = sin ( lng ) * sin ( lat ); + normals[j][2] = cos ( lat ); +#endif + for (d = 0; d < 3; d++) + { + verts[j][d] = LittleShort(invert[j].xyz[d])/64.0f; + if (verts[j][d]max[d]) + max[d] = verts[j][d]; + } + } + + pose->scale[0] = 1; + pose->scale[1] = 1; + pose->scale[2] = 1; + + pose->scale_origin[0] = 0; + pose->scale_origin[1] = 0; + pose->scale_origin[2] = 0; + + snprintf(group->name, sizeof(group->name)-1, "frame%i", i); + + group->numposes = 1; + group->rate = 1; + group->poseofs = (qbyte*)pose - (qbyte*)group; + + group++; + invert += LittleLong(surf->numVerts); + } + +#ifndef SERVERONLY + if (externalskinsnumShaders)) + externalskins = LittleLong(surf->numShaders); + if (externalskins) + { +#ifndef Q3SHADERS + char name[1024]; + extern int gl_bumpmappingpossible; +#endif + char shadname[1024]; + + skin = Hunk_Alloc((LittleLong(surf->numShaders)+externalskins)*((sizeof(galiasskin_t)+sizeof(galiastexnum_t)))); + galias->ofsskins = (qbyte *)skin - (qbyte *)galias; + texnum = (galiastexnum_t *)(skin + LittleLong(surf->numShaders)+externalskins); + inshader = (md3Shader_t *)((qbyte *)surf + LittleLong(surf->ofsShaders)); + for (i = 0; i < externalskins; i++) + { + skin->texnums = 1; + skin->ofstexnums = (qbyte *)texnum - (qbyte *)skin; + skin->ofstexels = 0; + skin->skinwidth = 0; + skin->skinheight = 0; + skin->skinspeed = 0; + + shadname[0] = '\0'; + + Mod_ParseQ3SkinFile(shadname, surf->name, loadmodel->name, i, skin->name); + + if (!*shadname) + { + if (i >= LittleLong(surf->numShaders)) + strcpy(shadname, "missingskin"); //this shouldn't be possible + else + strcpy(shadname, inshader->name); + + Q_strncpyz(skin->name, shadname, sizeof(skin->name)); + } + +#ifdef Q3SHADERS + if (qrenderer) + { + texnum->shader = R_RegisterSkin(shadname); + + if (r_shadows.value) //real-time shadows requires a texture to lighten the model with, even if it has a shader. + //fixme: this should be read from the shader. + texnum->base = Mod_LoadHiResTexture(shadname, "models", true, true, true); + } +#else + + texnum->base = Mod_LoadHiResTexture(shadname, "models", true, true, true); + if (!texnum->base) + { + strcpy(name, loadmodel->name); + strcpy(COM_SkipPath(name), COM_SkipPath(shadname)); //eviile eh? + texnum->base = Mod_LoadHiResTexture(name, "models", true, true, true); + } + + texnum->bump = 0; + if (gl_bumpmappingpossible) + { + COM_StripExtension(shadname, name, sizeof(name)); //go for the normalmap + strcat(name, "_norm"); + texnum->bump = Mod_LoadHiResTexture(name, "models", true, true, false); + if (!texnum->bump) + { + strcpy(name, loadmodel->name); + COM_StripExtension(COM_SkipPath(shadname), COM_SkipPath(name), sizeof(name)); + strcat(name, "_norm"); + texnum->bump = Mod_LoadHiResTexture(name, "models", true, true, false); + if (!texnum->bump) + { + COM_StripExtension(shadname, name, sizeof(name)); //bother, go for heightmap and convert + strcat(name, "_bump"); + texnum->bump = Mod_LoadBumpmapTexture(name, "models"); + if (!texnum->bump) + { + strcpy(name, loadmodel->name); + strcpy(COM_SkipPath(name), COM_SkipPath(shadname)); //eviile eh? + COM_StripExtension(name, name, sizeof(name)); + strcat(name, "_bump"); + texnum->bump = Mod_LoadBumpmapTexture(name, "models"); + } + } + } + } + if (r_fb_models.value) + { + COM_StripExtension(shadname, name, sizeof(name)); //go for the normalmap + strcat(name, "_luma"); + texnum->fullbright = Mod_LoadHiResTexture(name, "models", true, true, true); + if (!texnum->base) + { + strcpy(name, loadmodel->name); + strcpy(COM_SkipPath(name), COM_SkipPath(shadname)); //eviile eh? + COM_StripExtension(name, name, sizeof(name)); + strcat(name, "_luma"); + texnum->fullbright = Mod_LoadBumpmapTexture(name, "models"); + } + } #endif //13/4/08 IMPLEMENTME texnum->loweroverlay = 0; - texnum->upperoverlay = 0; - - inshader++; - skin++; - texnum++; - } - galias->numskins = i; - } -#endif - - VectorCopy(min, loadmodel->mins); - VectorCopy(max, loadmodel->maxs); - - - Mod_CompileTriangleNeighbours (galias); - - surf = (md3Surface_t *)((qbyte *)surf + LittleLong(surf->ofsEnd)); - } - - if (!root) - root = Hunk_Alloc(sizeof(galiasinfo_t)); - - root->numtagframes = LittleLong(header->numFrames); - root->numtags = LittleLong(header->numTags); - root->ofstags = (char*)Hunk_Alloc(LittleLong(header->numTags)*sizeof(md3tag_t)*LittleLong(header->numFrames)) - (char*)root; - - { - md3tag_t *src; - md3tag_t *dst; - - src = (md3tag_t *)((char*)header+LittleLong(header->ofsTags)); - dst = (md3tag_t *)((char*)root+root->ofstags); - for(i=0;inumTags)*LittleLong(header->numFrames);i++) - { - memcpy(dst->name, src->name, sizeof(dst->name)); - for(j=0;j<3;j++) - { - dst->org[j] = LittleFloat(src->org[j]); - } - - for(j=0;j<3;j++) - { - for(s=0;s<3;s++) - { - dst->ang[j][s] = LittleFloat(src->ang[j][s]); - } - } - - src++; - dst++; - } - } - -// -// move the complete, relocatable alias model to the cache -// - - hunkend = Hunk_LowMark (); -#ifndef SERVERONLY - if (mod_md3flags.value) - mod->flags = LittleLong(header->flags); - else -#endif - mod->flags = 0; - if (!mod->flags) - mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); - - Mod_ClampModelSize(mod); - - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, root, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - mod->funcs.Trace = Mod_Trace; - - return true; -} -#endif - - - -#ifdef ZYMOTICMODELS - - -typedef struct zymlump_s -{ - int start; - int length; -} zymlump_t; - -typedef struct zymtype1header_s -{ - char id[12]; // "ZYMOTICMODEL", length 12, no termination - int type; // 0 (vertex morph) 1 (skeletal pose) or 2 (skeletal scripted) - int filesize; // size of entire model file - float mins[3], maxs[3], radius; // for clipping uses - int numverts; - int numtris; - int numsurfaces; - int numbones; // this may be zero in the vertex morph format (undecided) - int numscenes; // 0 in skeletal scripted models - -// skeletal pose header - // lump offsets are relative to the file - zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct) - zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data - zymlump_t lump_bones; // zymbone_t bone[numbones]; - zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better) - zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct - zymlump_t lump_texcoords; // float texcoords[numvertices][2]; - zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices) - zymlump_t lump_surfnames; // char shadername[numsurfaces][32]; // shaders used on this model - zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation -} zymtype1header_t; - -typedef struct zymbone_s -{ - char name[32]; - int flags; - int parent; // parent bone number -} zymbone_t; - -typedef struct zymscene_s -{ - char name[32]; - float mins[3], maxs[3], radius; // for clipping - float framerate; // the scene will animate at this framerate (in frames per second) - int flags; - int start, length; // range of poses -} zymscene_t; -#define ZYMSCENEFLAG_NOLOOP 1 - -typedef struct zymvertex_s -{ - int bonenum; - float origin[3]; -} zymvertex_t; - -//this can generate multiple meshes (one for each shader). -//but only one set of transforms are ever generated. -qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer) -{ -#ifndef SERVERONLY - galiasskin_t *skin; - galiastexnum_t *texnum; - int skinfiles; - int j; -#endif - - int i; - int hunkstart, hunkend, hunktotal; - - zymtype1header_t *header; - galiasinfo_t *root; - - galisskeletaltransforms_t *transforms; - zymvertex_t *intrans; - - galiasbone_t *bone; - zymbone_t *inbone; - int v; - float multiplier; - float *matrix, *inmatrix; - - vec2_t *stcoords; - vec2_t *inst; - - int *vertbonecounts; - - galiasgroup_t *grp; - zymscene_t *inscene; - - int *renderlist, count; - index_t *indexes; - - char *surfname; - - - loadmodel=mod; - - Mod_DoCRC(mod, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - header = buffer; - - if (memcmp(header->id, "ZYMOTICMODEL", 12)) - { - Con_Printf("Mod_LoadZymoticModel: %s, doesn't appear to BE a zymotic!\n", mod->name); - return false; - } - - if (BigLong(header->type) != 1) - { - Con_Printf("Mod_LoadZymoticModel: %s, only type 1 is supported\n", mod->name); - return false; - } - - for (i = 0; i < sizeof(zymtype1header_t)/4; i++) - ((int*)header)[i] = BigLong(((int*)header)[i]); - - if (!header->numverts) - { - Con_Printf("Mod_LoadZymoticModel: %s, no vertexes\n", mod->name); - return false; - } - - if (!header->numsurfaces) - { - Con_Printf("Mod_LoadZymoticModel: %s, no surfaces\n", mod->name); - return false; - } - - VectorCopy(header->mins, mod->mins); - VectorCopy(header->maxs, mod->maxs); - - root = Hunk_AllocName(sizeof(galiasinfo_t)*header->numsurfaces, loadname); - - root->numtransforms = header->lump_verts.length/sizeof(zymvertex_t); - transforms = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); - root->ofstransforms = (char*)transforms - (char*)root; - - vertbonecounts = (int *)((char*)header + header->lump_vertbonecounts.start); - intrans = (zymvertex_t *)((char*)header + header->lump_verts.start); - - vertbonecounts[0] = BigLong(vertbonecounts[0]); - multiplier = 1.0f / vertbonecounts[0]; - for (i = 0, v=0; i < root->numtransforms; i++) - { - while(!vertbonecounts[v]) - { - v++; - if (v == header->numverts) - { - Con_Printf("Mod_LoadZymoticModel: %s, too many transformations\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - vertbonecounts[v] = BigLong(vertbonecounts[v]); - multiplier = 1.0f / vertbonecounts[v]; - } - transforms[i].vertexindex = v; - transforms[i].boneindex = BigLong(intrans[i].bonenum); - transforms[i].org[0] = multiplier*BigFloat(intrans[i].origin[0]); - transforms[i].org[1] = multiplier*BigFloat(intrans[i].origin[1]); - transforms[i].org[2] = multiplier*BigFloat(intrans[i].origin[2]); - transforms[i].org[3] = multiplier*1; - vertbonecounts[v]--; - } - if (intrans != (zymvertex_t *)((char*)header + header->lump_verts.start)) - { - Con_Printf(CON_ERROR "%s, Vertex transforms list appears corrupt.\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - if (vertbonecounts != (int *)((char*)header + header->lump_vertbonecounts.start)) - { - Con_Printf(CON_ERROR "%s, Vertex bone counts list appears corrupt.\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - - root->numverts = v+1; - - root->numbones = header->numbones; - bone = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); - inbone = (zymbone_t*)((char*)header + header->lump_bones.start); - for (i = 0; i < root->numbones; i++) - { - Q_strncpyz(bone[i].name, inbone[i].name, sizeof(bone[i].name)); - bone[i].parent = BigLong(inbone[i].parent); - } - root->ofsbones = (char *)bone - (char *)root; - - renderlist = (int*)((char*)header + header->lump_render.start); - for (i = 0;i < header->numsurfaces; i++) - { - count = BigLong(*renderlist++); - count *= 3; - indexes = Hunk_Alloc(count*sizeof(*indexes)); - root[i].ofs_indexes = (char *)indexes - (char*)&root[i]; - root[i].numindexes = count; - while(count) - { //invert - indexes[count-1] = BigLong(renderlist[count-3]); - indexes[count-2] = BigLong(renderlist[count-2]); - indexes[count-3] = BigLong(renderlist[count-1]); - count-=3; - } - renderlist += root[i].numindexes; - } - if (renderlist != (int*)((char*)header + header->lump_render.start + header->lump_render.length)) - { - Con_Printf(CON_ERROR "%s, render list appears corrupt.\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - - grp = Hunk_Alloc(sizeof(*grp)*header->numscenes*header->numsurfaces); - matrix = Hunk_Alloc(header->lump_poses.length); - inmatrix = (float*)((char*)header + header->lump_poses.start); - for (i = 0; i < header->lump_poses.length/4; i++) - matrix[i] = BigFloat(inmatrix[i]); - inscene = (zymscene_t*)((char*)header + header->lump_scenes.start); - surfname = ((char*)header + header->lump_surfnames.start); - - stcoords = Hunk_Alloc(root[0].numverts*sizeof(vec2_t)); - inst = (vec2_t *)((char *)header + header->lump_texcoords.start); - for (i = 0; i < header->lump_texcoords.length/8; i++) - { - stcoords[i][0] = BigFloat(inst[i][0]); - stcoords[i][1] = 1-BigFloat(inst[i][1]); //hmm. upside down skin coords? - } - -#ifndef SERVERONLY - skinfiles = Mod_BuildSkinFileList(loadmodel->name); - if (skinfiles < 1) - skinfiles = 1; -#endif - - for (i = 0; i < header->numsurfaces; i++, surfname+=32) - { - root[i].groups = header->numscenes; - root[i].groupofs = (char*)grp - (char*)&root[i]; - -#ifdef SERVERONLY - root[i].numskins = 1; -#else - root[i].ofs_st_array = (char*)stcoords - (char*)&root[i]; - root[i].numskins = skinfiles; - - skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(galiastexnum_t))*skinfiles); - texnum = (galiastexnum_t*)(skin+skinfiles); - for (j = 0; j < skinfiles; j++, texnum++) - { - skin[j].texnums = 1; //non-sequenced skins. - skin[j].ofstexnums = (char *)texnum - (char *)&skin[j]; - - Mod_LoadSkinFile(texnum, surfname, j, NULL, 0, 0, NULL); - } - - root[i].ofsskins = (char *)skin - (char *)&root[i]; -#endif - } - - - for (i = 0; i < header->numscenes; i++, grp++, inscene++) - { - Q_strncpyz(grp->name, inscene->name, sizeof(grp->name)); - - grp->isheirachical = 1; - grp->rate = BigFloat(inscene->framerate); - grp->loop = !(BigLong(inscene->flags) & ZYMSCENEFLAG_NOLOOP); - grp->numposes = BigLong(inscene->length); - grp->poseofs = (char*)matrix - (char*)grp; - grp->poseofs += BigLong(inscene->start)*12*sizeof(float)*root->numbones; - } - - if (inscene != (zymscene_t*)((char*)header + header->lump_scenes.start+header->lump_scenes.length)) - { - Con_Printf(CON_ERROR "%s, scene list appears corrupt.\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - - for (i = 0; i < header->numsurfaces-1; i++) - root[i].nextsurf = sizeof(galiasinfo_t); - for (i = 1; i < header->numsurfaces; i++) - { - root[i].sharesverts = true; - root[i].numbones = root[0].numbones; - root[i].numverts = root[0].numverts; - - root[i].ofsbones = root[0].ofsbones; - - root[i-1].nextsurf = sizeof(*root); - } - -// -// move the complete, relocatable alias model to the cache -// - - hunkend = Hunk_LowMark (); - - mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. - - Mod_ClampModelSize(mod); - - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, root, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - - mod->funcs.Trace = Mod_Trace; - - return true; -} - - - - - - - - - -////////////////////////////////////////////////////////////// -//dpm - - -// header for the entire file -typedef struct dpmheader_s -{ - char id[16]; // "DARKPLACESMODEL\0", length 16 - unsigned int type; // 2 (hierarchical skeletal pose) - unsigned int filesize; // size of entire model file - float mins[3], maxs[3], yawradius, allradius; // for clipping uses - - // these offsets are relative to the file - unsigned int num_bones; - unsigned int num_meshs; - unsigned int num_frames; - unsigned int ofs_bones; // dpmbone_t bone[num_bones]; - unsigned int ofs_meshs; // dpmmesh_t mesh[num_meshs]; - unsigned int ofs_frames; // dpmframe_t frame[num_frames]; -} dpmheader_t; - -// there may be more than one of these -typedef struct dpmmesh_s -{ - // these offsets are relative to the file - char shadername[32]; // name of the shader to use - unsigned int num_verts; - unsigned int num_tris; - unsigned int ofs_verts; // dpmvertex_t vert[numvertices]; // see vertex struct - unsigned int ofs_texcoords; // float texcoords[numvertices][2]; - unsigned int ofs_indices; // unsigned int indices[numtris*3]; // designed for glDrawElements (each triangle is 3 unsigned int indices) - unsigned int ofs_groupids; // unsigned int groupids[numtris]; // the meaning of these values is entirely up to the gamecode and modeler -} dpmmesh_t; - -// if set on a bone, it must be protected from removal -#define DPMBONEFLAG_ATTACHMENT 1 - -// one per bone -typedef struct dpmbone_s -{ - // name examples: upperleftarm leftfinger1 leftfinger2 hand, etc - char name[32]; - // parent bone number - signed int parent; - // flags for the bone - unsigned int flags; -} dpmbone_t; - -// a bonepose matrix is intended to be used like this: -// (n = output vertex, v = input vertex, m = matrix, f = influence) -// n[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2] + f * m[0][3]; -// n[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2] + f * m[1][3]; -// n[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2] + f * m[2][3]; -typedef struct dpmbonepose_s -{ - float matrix[3][4]; -} dpmbonepose_t; - -// immediately followed by bone positions for the frame -typedef struct dpmframe_s -{ - // name examples: idle_1 idle_2 idle_3 shoot_1 shoot_2 shoot_3, etc - char name[32]; - float mins[3], maxs[3], yawradius, allradius; - int ofs_bonepositions; // dpmbonepose_t bonepositions[bones]; -} dpmframe_t; - -// one or more of these per vertex -typedef struct dpmbonevert_s -{ - float origin[3]; // vertex location (these blend) - float influence; // influence fraction (these must add up to 1) - float normal[3]; // surface normal (these blend) - unsigned int bonenum; // number of the bone -} dpmbonevert_t; - -// variable size, parsed sequentially -typedef struct dpmvertex_s -{ - unsigned int numbones; - // immediately followed by 1 or more dpmbonevert_t structures -} dpmvertex_t; - -qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) -{ -#ifndef SERVERONLY - galiasskin_t *skin; - galiastexnum_t *texnum; - int skinfiles; - float *inst; - float *outst; -#endif - - int i, j, k; - int hunkstart, hunkend, hunktotal; - - dpmheader_t *header; - galiasinfo_t *root, *m; - dpmmesh_t *mesh; - dpmvertex_t *vert; - dpmbonevert_t *bonevert; - - galisskeletaltransforms_t *transforms; - - galiasbone_t *outbone; - dpmbone_t *inbone; - - float *outposedata; - galiasgroup_t *outgroups; - float *inposedata; - dpmframe_t *inframes; - - unsigned int *index; index_t *outdex; // groan... - - int numtransforms; - int numverts; - - - loadmodel=mod; - - Mod_DoCRC(mod, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - header = buffer; - - if (memcmp(header->id, "DARKPLACESMODEL\0", 16)) - { - Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, doesn't appear to be a darkplaces model!\n", mod->name); - return false; - } - - if (BigLong(header->type) != 2) - { - Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, only type 2 is supported\n", mod->name); - return false; - } - - for (i = 0; i < sizeof(dpmheader_t)/4; i++) - ((int*)header)[i] = BigLong(((int*)header)[i]); - - if (!header->num_bones) - { - Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, no bones\n", mod->name); - return false; - } - if (!header->num_frames) - { - Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, no frames\n", mod->name); - return false; - } - if (!header->num_meshs) - { - Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, no surfaces\n", mod->name); - return false; - } - - - VectorCopy(header->mins, mod->mins); - VectorCopy(header->maxs, mod->maxs); - - root = Hunk_AllocName(sizeof(galiasinfo_t)*header->num_meshs, loadname); - - mesh = (dpmmesh_t*)((char*)buffer + header->ofs_meshs); - for (i = 0; i < header->num_meshs; i++, mesh++) - { - //work out how much memory we need to allocate - - mesh->num_verts = BigLong(mesh->num_verts); - mesh->num_tris = BigLong(mesh->num_tris); - mesh->ofs_verts = BigLong(mesh->ofs_verts); - mesh->ofs_texcoords = BigLong(mesh->ofs_texcoords); - mesh->ofs_indices = BigLong(mesh->ofs_indices); - mesh->ofs_groupids = BigLong(mesh->ofs_groupids); - - - numverts = mesh->num_verts; - numtransforms = 0; - //count and byteswap the transformations - vert = (dpmvertex_t*)((char *)buffer+mesh->ofs_verts); - for (j = 0; j < mesh->num_verts; j++) - { - vert->numbones = BigLong(vert->numbones); - numtransforms += vert->numbones; - bonevert = (dpmbonevert_t*)(vert+1); - vert = (dpmvertex_t*)(bonevert+vert->numbones); - } - - m = &root[i]; -#ifdef SERVERONLY - transforms = Hunk_AllocName(numtransforms*sizeof(galisskeletaltransforms_t) + mesh->num_tris*3*sizeof(index_t), loadname); -#else - outst = Hunk_AllocName(numverts*sizeof(vec2_t) + numtransforms*sizeof(galisskeletaltransforms_t) + mesh->num_tris*3*sizeof(index_t), loadname); - m->ofs_st_array = (char*)outst - (char*)m; - m->numverts = mesh->num_verts; - inst = (float*)((char*)buffer + mesh->ofs_texcoords); - for (j = 0; j < numverts; j++, outst+=2, inst+=2) - { - outst[0] = BigFloat(inst[0]); - outst[1] = BigFloat(inst[1]); - } - - transforms = (galisskeletaltransforms_t*)outst; -#endif - - //build the transform list. - m->ofstransforms = (char*)transforms - (char*)m; - m->numtransforms = numtransforms; - vert = (dpmvertex_t*)((char *)buffer+mesh->ofs_verts); - for (j = 0; j < mesh->num_verts; j++) - { - bonevert = (dpmbonevert_t*)(vert+1); - for (k = 0; k < vert->numbones; k++, bonevert++, transforms++) - { - transforms->boneindex = BigLong(bonevert->bonenum); - transforms->vertexindex = j; - transforms->org[0] = BigFloat(bonevert->origin[0]); - transforms->org[1] = BigFloat(bonevert->origin[1]); - transforms->org[2] = BigFloat(bonevert->origin[2]); - transforms->org[3] = BigFloat(bonevert->influence); - //do nothing with the normals. :( - } - vert = (dpmvertex_t*)bonevert; - } - - index = (unsigned int*)((char*)buffer + mesh->ofs_indices); - outdex = (index_t *)transforms; - m->ofs_indexes = (char*)outdex - (char*)m; - m->numindexes = mesh->num_tris*3; - for (j = 0; j < m->numindexes; j++) - { - *outdex++ = BigLong(*index++); - } - } - - outbone = Hunk_Alloc(sizeof(galiasbone_t)*header->num_bones); - inbone = (dpmbone_t*)((char*)buffer + header->ofs_bones); - for (i = 0; i < header->num_bones; i++) - { - outbone[i].parent = BigLong(inbone[i].parent); - if (outbone[i].parent >= i || outbone[i].parent < -1) - { - Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: bad bone index in %s\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - - Q_strncpyz(outbone[i].name, inbone[i].name, sizeof(outbone[i].name)); - //throw away the flags. - } - - outgroups = Hunk_Alloc(sizeof(galiasgroup_t)*header->num_frames + sizeof(float)*header->num_frames*header->num_bones*12); - outposedata = (float*)(outgroups+header->num_frames); - - inframes = (dpmframe_t*)((char*)buffer + header->ofs_frames); - for (i = 0; i < header->num_frames; i++) - { - inframes[i].ofs_bonepositions = BigLong(inframes[i].ofs_bonepositions); - inframes[i].allradius = BigLong(inframes[i].allradius); - inframes[i].yawradius = BigLong(inframes[i].yawradius); - inframes[i].mins[0] = BigLong(inframes[i].mins[0]); - inframes[i].mins[1] = BigLong(inframes[i].mins[1]); - inframes[i].mins[2] = BigLong(inframes[i].mins[2]); - inframes[i].maxs[0] = BigLong(inframes[i].maxs[0]); - inframes[i].maxs[1] = BigLong(inframes[i].maxs[1]); - inframes[i].maxs[2] = BigLong(inframes[i].maxs[2]); - - Q_strncpyz(outgroups[i].name, inframes[i].name, sizeof(outgroups[i].name)); - - outgroups[i].rate = 10; - outgroups[i].numposes = 1; - outgroups[i].isheirachical = true; - outgroups[i].poseofs = (char*)outposedata - (char*)&outgroups[i]; - - inposedata = (float*)((char*)buffer + inframes[i].ofs_bonepositions); - for (j = 0; j < header->num_bones*12; j++) - *outposedata++ = BigFloat(*inposedata++); - } - -#ifndef SERVERONLY - skinfiles = Mod_BuildSkinFileList(loadmodel->name); - if (skinfiles < 1) - skinfiles = 1; -#endif - - mesh = (dpmmesh_t*)((char*)buffer + header->ofs_meshs); - for (i = 0; i < header->num_meshs; i++, mesh++) - { - m = &root[i]; - if (i < header->num_meshs-1) - m->nextsurf = sizeof(galiasinfo_t); - m->sharesbones = true; - - m->ofsbones = (char*)outbone-(char*)m; - m->numbones = header->num_bones; - - m->groups = header->num_frames; - m->groupofs = (char*)outgroups - (char*)m; - - - -#ifdef SERVERONLY - m->numskins = 1; -#else - m->numskins = skinfiles; - - skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(galiastexnum_t))*skinfiles); - texnum = (galiastexnum_t*)(skin+skinfiles); - for (j = 0; j < skinfiles; j++, texnum++) - { - skin[j].texnums = 1; //non-sequenced skins. - skin[j].ofstexnums = (char *)texnum - (char *)&skin[j]; - - Mod_LoadSkinFile(texnum, mesh->shadername, j, NULL, 0, 0, NULL); - } - - m->ofsskins = (char *)skin - (char *)m; -#endif - } - root[0].sharesbones = false; - - - - -// -// move the complete, relocatable alias model to the cache -// - hunkend = Hunk_LowMark (); - - mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. - - Mod_ClampModelSize(mod); - - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, root, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - - mod->funcs.Trace = Mod_Trace; - - return true; -} - - - - - - - -#endif //ZYMOTICMODELS - -#ifdef MD5MODELS - -static void GenMatrix(float x, float y, float z, float qx, float qy, float qz, float result[12]) -{ - float qw; - { //figure out qw - float term = 1 - (qx*qx) - (qy*qy) - (qz*qz); - if (term < 0) - qw = 0; - else - qw = - (float) sqrt(term); - } - - { //generate the matrix - /* - float xx = qx * qx; - float xy = qx * qy; - float xz = qx * qz; - float xw = qx * qw; - float yy = qy * qy; - float yz = qy * qz; - float yw = qy * qw; - float zz = qz * qz; - float zw = qz * qw; - result[0*4+0] = 1 - 2 * ( yy + zz ); - result[0*4+1] = 2 * ( xy - zw ); - result[0*4+2] = 2 * ( xz + yw ); - result[0*4+3] = x; - result[1*4+0] = 2 * ( xy + zw ); - result[1*4+1] = 1 - 2 * ( xx + zz ); - result[1*4+2] = 2 * ( yz - xw ); - result[1*4+3] = y; - result[2*4+0] = 2 * ( xz - yw ); - result[2*4+1] = 2 * ( yz + xw ); - result[2*4+2] = 1 - 2 * ( xx + yy ); - result[2*4+3] = z; - */ - - float xx, xy, xz, xw, yy, yz, yw, zz, zw; - float x2, y2, z2; - x2 = qx + qx; - y2 = qy + qy; - z2 = qz + qz; - - xx = qx * x2; xy = qx * y2; xz = qx * z2; - yy = qy * y2; yz = qy * z2; zz = qz * z2; - xw = qw * x2; yw = qw * y2; zw = qw * z2; - - result[0*4+0] = 1.0f - (yy + zz); - result[1*4+0] = xy + zw; - result[2*4+0] = xz - yw; - - result[0*4+1] = xy - zw; - result[1*4+1] = 1.0f - (xx + zz); - result[2*4+1] = yz + xw; - - result[0*4+2] = xz + yw; - result[1*4+2] = yz - xw; - result[2*4+2] = 1.0f - (xx + yy); - - result[0*4+3] = x; - result[1*4+3] = y; - result[2*4+3] = z; - } -} - -galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) -{ -#define MD5ERROR0PARAM(x) { Con_Printf(CON_ERROR x "\n"); return NULL; } -#define MD5ERROR1PARAM(x, y) { Con_Printf(CON_ERROR x "\n", y); return NULL; } -#define EXPECT(x) buffer = COM_Parse(buffer); if (strcmp(com_token, x)) Sys_Error("MD5MESH: expected %s", x); - int numjoints = 0; - int nummeshes = 0; - qboolean foundjoints = false; - int i; - - galiasbone_t *bones = NULL; - galiasgroup_t *pose = NULL; - galiasinfo_t *inf, *root, *lastsurf; - float *posedata; -#ifndef SERVERONLY - galiasskin_t *skin; - galiastexnum_t *texnum; -#endif - - float x, y, z, qx, qy, qz; - - - - buffer = COM_Parse(buffer); - if (strcmp(com_token, "MD5Version")) - MD5ERROR0PARAM("MD5 model without MD5Version identifier first"); - - buffer = COM_Parse(buffer); - if (atoi(com_token) != 10) - MD5ERROR0PARAM("MD5 model with unsupported MD5Version"); - - - root = Hunk_Alloc(sizeof(galiasinfo_t)); - lastsurf = NULL; - - for(;;) - { - buffer = COM_Parse(buffer); - if (!buffer) - break; - - if (!strcmp(com_token, "commandline")) - { //we don't need this - buffer = strchr(buffer, '\"'); - buffer = strchr((char*)buffer+1, '\"')+1; -// buffer = COM_Parse(buffer); - } - else if (!strcmp(com_token, "numJoints")) - { - if (numjoints) - MD5ERROR0PARAM("MD5MESH: numMeshes was already declared"); - buffer = COM_Parse(buffer); - numjoints = atoi(com_token); - if (numjoints <= 0) - MD5ERROR0PARAM("MD5MESH: Needs some joints"); - } - else if (!strcmp(com_token, "numMeshes")) - { - if (nummeshes) - MD5ERROR0PARAM("MD5MESH: numMeshes was already declared"); - buffer = COM_Parse(buffer); - nummeshes = atoi(com_token); - if (nummeshes <= 0) - MD5ERROR0PARAM("MD5MESH: Needs some meshes"); - } - else if (!strcmp(com_token, "joints")) - { - if (foundjoints) - MD5ERROR0PARAM("MD5MESH: Duplicate joints section"); - foundjoints=true; - if (!numjoints) - MD5ERROR0PARAM("MD5MESH: joints section before (or without) numjoints"); - - bones = Hunk_Alloc(sizeof(*bones) * numjoints); - pose = Hunk_Alloc(sizeof(galiasgroup_t)); - posedata = Hunk_Alloc(sizeof(float)*12 * numjoints); - pose->isheirachical = false; - pose->rate = 1; - pose->numposes = 1; - pose->poseofs = (char*)posedata - (char*)pose; - - Q_strncpyz(pose->name, "base", sizeof(pose->name)); - - EXPECT("{"); - //"name" parent (x y z) (s t u) - //stu are a normalized quaternion, which we will convert to a 3*4 matrix for no apparent reason - - for (i = 0; i < numjoints; i++) - { - buffer = COM_Parse(buffer); - Q_strncpyz(bones[i].name, com_token, sizeof(bones[i].name)); - buffer = COM_Parse(buffer); - bones[i].parent = atoi(com_token); - if (bones[i].parent >= i) - MD5ERROR0PARAM("MD5MESH: joints parent's must be lower"); - if ((bones[i].parent < 0 && i) || (!i && bones[i].parent!=-1)) - MD5ERROR0PARAM("MD5MESH: Only the root joint may have a negative parent"); - - EXPECT("("); - buffer = COM_Parse(buffer); - x = atof(com_token); - buffer = COM_Parse(buffer); - y = atof(com_token); - buffer = COM_Parse(buffer); - z = atof(com_token); - EXPECT(")"); - EXPECT("("); - buffer = COM_Parse(buffer); - qx = atof(com_token); - buffer = COM_Parse(buffer); - qy = atof(com_token); - buffer = COM_Parse(buffer); - qz = atof(com_token); - EXPECT(")"); - GenMatrix(x, y, z, qx, qy, qz, posedata+i*12); - } - EXPECT("}"); - } - else if (!strcmp(com_token, "mesh")) - { - int numverts = 0; - int numweights = 0; - int numtris = 0; - - int num; - int vnum; - - int numusableweights = 0; - int *firstweightlist = NULL; - int *numweightslist = NULL; - - galisskeletaltransforms_t *trans; -#ifndef SERVERONLY - float *stcoord = NULL; -#endif - int *indexes = NULL; - float w; - - vec4_t *rawweight = NULL; - int *rawweightbone = NULL; - - - if (!nummeshes) - MD5ERROR0PARAM("MD5MESH: mesh section before (or without) nummeshes"); - if (!foundjoints || !bones || !pose) - MD5ERROR0PARAM("MD5MESH: mesh must come after joints"); - - if (!lastsurf) - { - lastsurf = root; - inf = root; - } - else - { - inf = Hunk_Alloc(sizeof(*inf)); - lastsurf->nextsurf = (char*)inf - (char*)lastsurf; - lastsurf = inf; - } - - inf->ofsbones = (char*)bones - (char*)inf; - inf->numbones = numjoints; - inf->groups = 1; - inf->groupofs = (char*)pose - (char*)inf; - -#ifndef SERVERONLY - skin = Hunk_Alloc(sizeof(*skin)); - texnum = Hunk_Alloc(sizeof(*texnum)); - inf->numskins = 1; - inf->ofsskins = (char*)skin - (char*)inf; - skin->texnums = 1; - skin->skinspeed = 1; - skin->ofstexnums = (char*)texnum - (char*)skin; -#endif - EXPECT("{"); - for(;;) - { - buffer = COM_Parse(buffer); - if (!buffer) - MD5ERROR0PARAM("MD5MESH: unexpected eof"); - - if (!strcmp(com_token, "shader")) - { - buffer = COM_Parse(buffer); -#ifndef SERVERONLY - // texnum->shader = R_RegisterSkin(com_token); - texnum->base = Mod_LoadHiResTexture(com_token, "models", true, true, true); -#endif - } - else if (!strcmp(com_token, "numverts")) - { - if (numverts) - MD5ERROR0PARAM("MD5MESH: numverts was already specified"); - buffer = COM_Parse(buffer); - numverts = atoi(com_token); - if (numverts < 0) - MD5ERROR0PARAM("MD5MESH: numverts cannot be negative"); - - firstweightlist = Z_Malloc(sizeof(*firstweightlist) * numverts); - numweightslist = Z_Malloc(sizeof(*numweightslist) * numverts); -#ifndef SERVERONLY - stcoord = Hunk_Alloc(sizeof(float)*2*numverts); - inf->ofs_st_array = (char*)stcoord - (char*)inf; - inf->numverts = numverts; -#endif - } - else if (!strcmp(com_token, "vert")) - { //vert num ( s t ) firstweight numweights - - buffer = COM_Parse(buffer); - num = atoi(com_token); - if (num < 0 || num >= numverts || !indexes) - MD5ERROR0PARAM("MD5MESH: vertex out of range"); - - EXPECT("("); - buffer = COM_Parse(buffer); -#ifndef SERVERONLY - if (!stcoord) - MD5ERROR0PARAM("MD5MESH: vertex out of range"); - stcoord[num*2+0] = atof(com_token); -#endif - buffer = COM_Parse(buffer); -#ifndef SERVERONLY - stcoord[num*2+1] = atof(com_token); -#endif - EXPECT(")"); - buffer = COM_Parse(buffer); - firstweightlist[num] = atoi(com_token); - buffer = COM_Parse(buffer); - numweightslist[num] = atoi(com_token); - - numusableweights += numweightslist[num]; - } - else if (!strcmp(com_token, "numtris")) - { - if (numtris) - MD5ERROR0PARAM("MD5MESH: numtris was already specified"); - buffer = COM_Parse(buffer); - numtris = atoi(com_token); - if (numtris < 0) - MD5ERROR0PARAM("MD5MESH: numverts cannot be negative"); - - indexes = Hunk_Alloc(sizeof(int)*3*numtris); - inf->ofs_indexes = (char*)indexes - (char*)inf; - inf->numindexes = numtris*3; - } - else if (!strcmp(com_token, "tri")) - { - buffer = COM_Parse(buffer); - num = atoi(com_token); - if (num < 0 || num >= numtris) - MD5ERROR0PARAM("MD5MESH: vertex out of range"); - - buffer = COM_Parse(buffer); - indexes[num*3+0] = atoi(com_token); - buffer = COM_Parse(buffer); - indexes[num*3+1] = atoi(com_token); - buffer = COM_Parse(buffer); - indexes[num*3+2] = atoi(com_token); - } - else if (!strcmp(com_token, "numweights")) - { - if (numweights) - MD5ERROR0PARAM("MD5MESH: numweights was already specified"); - buffer = COM_Parse(buffer); - numweights = atoi(com_token); - - rawweight = Z_Malloc(sizeof(*rawweight)*numweights); - rawweightbone = Z_Malloc(sizeof(*rawweightbone)*numweights); - } - else if (!strcmp(com_token, "weight")) - { - //weight num bone scale ( x y z ) - buffer = COM_Parse(buffer); - num = atoi(com_token); - if (num < 0 || num >= numweights) - MD5ERROR0PARAM("MD5MESH: weight out of range"); - - buffer = COM_Parse(buffer); - rawweightbone[num] = atoi(com_token); - if (rawweightbone[num] < 0 || rawweightbone[num] >= numjoints) - MD5ERROR0PARAM("MD5MESH: weight specifies bad bone"); - buffer = COM_Parse(buffer); - w = atof(com_token); - - EXPECT("("); - buffer = COM_Parse(buffer); - rawweight[num][0] = w*atof(com_token); - buffer = COM_Parse(buffer); - rawweight[num][1] = w*atof(com_token); - buffer = COM_Parse(buffer); - rawweight[num][2] = w*atof(com_token); - EXPECT(")"); - rawweight[num][3] = w; - } - else if (!strcmp(com_token, "}")) - break; - else - MD5ERROR1PARAM("MD5MESH: Unrecognised token inside mesh (%s)", com_token); - - } - - trans = Hunk_Alloc(sizeof(*trans)*numusableweights); - inf->ofstransforms = (char*)trans - (char*)inf; - - for (num = 0, vnum = 0; num < numverts; num++) - { - if (numweightslist[num] <= 0) - MD5ERROR0PARAM("MD5MESH: weights not set on vertex"); - while(numweightslist[num]) - { - trans[vnum].vertexindex = num; - trans[vnum].boneindex = rawweightbone[firstweightlist[num]]; - trans[vnum].org[0] = rawweight[firstweightlist[num]][0]; - trans[vnum].org[1] = rawweight[firstweightlist[num]][1]; - trans[vnum].org[2] = rawweight[firstweightlist[num]][2]; - trans[vnum].org[3] = rawweight[firstweightlist[num]][3]; - vnum++; - firstweightlist[num]++; - numweightslist[num]--; - } - } - inf->numtransforms = vnum; - - if (firstweightlist) - Z_Free(firstweightlist); - if (numweightslist) - Z_Free(numweightslist); - if (rawweight) - Z_Free(rawweight); - if (rawweightbone) - Z_Free(rawweightbone); - } - else - MD5ERROR1PARAM("Unrecognised token in MD5 model (%s)", com_token); - } - - if (!lastsurf) - MD5ERROR0PARAM("MD5MESH: No meshes"); - - return root; -#undef MD5ERROR0PARAM -#undef MD5ERROR1PARAM -#undef EXPECT -} - -qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer) -{ - galiasinfo_t *root; - int hunkstart, hunkend, hunktotal; - - - loadmodel=mod; - - Mod_DoCRC(mod, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - - root = Mod_ParseMD5MeshModel(buffer); - if (root == NULL) - { - Hunk_FreeToLowMark(hunkstart); - return false; - } - - - hunkend = Hunk_LowMark (); - - mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. - - Mod_ClampModelSize(mod); - - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, root, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - - mod->funcs.Trace = Mod_Trace; - return true; -} - -qboolean Mod_ParseMD5Anim(char *buffer, galiasinfo_t *prototype, void**poseofs, galiasgroup_t *gat) -{ -#define MD5ERROR0PARAM(x) { Con_Printf(CON_ERROR x "\n"); return false; } -#define MD5ERROR1PARAM(x, y) { Con_Printf(CON_ERROR x "\n", y); return false; } -#define EXPECT(x) buffer = COM_Parse(buffer); if (strcmp(com_token, x)) MD5ERROR1PARAM("MD5ANIM: expected %s", x); - unsigned int i, j; - - galiasgroup_t grp; - - unsigned int parent; - unsigned int numframes; - unsigned int numjoints; - float framespersecond; - unsigned int numanimatedparts; - galiasbone_t *bonelist; - - unsigned char *boneflags; - unsigned int *firstanimatedcomponents; - - float *animatedcomponents; - float *baseframe; //6 components. - float *posedata; - float tx, ty, tz, qx, qy, qz; - int fac, flags; - float f; - - EXPECT("MD5Version"); - EXPECT("10"); - - EXPECT("commandline"); - buffer = COM_Parse(buffer); - - EXPECT("numFrames"); - buffer = COM_Parse(buffer); - numframes = atoi(com_token); - - EXPECT("numJoints"); - buffer = COM_Parse(buffer); - numjoints = atoi(com_token); - - EXPECT("frameRate"); - buffer = COM_Parse(buffer); - framespersecond = atof(com_token); - - EXPECT("numAnimatedComponents"); - buffer = COM_Parse(buffer); - numanimatedparts = atoi(com_token); - - firstanimatedcomponents = BZ_Malloc(sizeof(int)*numjoints); - animatedcomponents = BZ_Malloc(sizeof(float)*numanimatedparts); - boneflags = BZ_Malloc(sizeof(unsigned char)*numjoints); - baseframe = BZ_Malloc(sizeof(float)*12*numjoints); - - *poseofs = posedata = Hunk_Alloc(sizeof(float)*12*numjoints*numframes); - - if (prototype) - { - if (prototype->numbones != numjoints) - MD5ERROR0PARAM("MD5ANIM: number of bones doesn't match"); - bonelist = (galiasbone_t *)((char*)prototype + prototype->ofsbones); - } - else - { - bonelist = Hunk_Alloc(sizeof(galiasbone_t)*numjoints); - prototype->ofsbones = (char*)bonelist - (char*)prototype; - prototype->numbones = numjoints; - } - - EXPECT("hierarchy"); - EXPECT("{"); - for (i = 0; i < numjoints; i++, bonelist++) - { - buffer = COM_Parse(buffer); - if (prototype) - { - if (strcmp(bonelist->name, com_token)) - MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", com_token); - } - else - Q_strncpyz(bonelist->name, com_token, sizeof(bonelist->name)); - buffer = COM_Parse(buffer); - parent = atoi(com_token); - if (prototype) - { - if (bonelist->parent != parent) - MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", com_token); - } - else - bonelist->parent = parent; - - buffer = COM_Parse(buffer); - boneflags[i] = atoi(com_token); - buffer = COM_Parse(buffer); - firstanimatedcomponents[i] = atoi(com_token); - } - EXPECT("}"); - - EXPECT("bounds"); - EXPECT("{"); - for (i = 0; i < numframes; i++) - { - EXPECT("("); - buffer = COM_Parse(buffer);f=atoi(com_token); - if (f < loadmodel->mins[0]) loadmodel->mins[0] = f; - buffer = COM_Parse(buffer);f=atoi(com_token); - if (f < loadmodel->mins[1]) loadmodel->mins[1] = f; - buffer = COM_Parse(buffer);f=atoi(com_token); - if (f < loadmodel->mins[2]) loadmodel->mins[2] = f; - EXPECT(")"); - EXPECT("("); - buffer = COM_Parse(buffer);f=atoi(com_token); - if (f > loadmodel->maxs[0]) loadmodel->maxs[0] = f; - buffer = COM_Parse(buffer);f=atoi(com_token); - if (f > loadmodel->maxs[1]) loadmodel->maxs[1] = f; - buffer = COM_Parse(buffer);f=atoi(com_token); - if (f > loadmodel->maxs[2]) loadmodel->maxs[2] = f; - EXPECT(")"); - } - EXPECT("}"); - - EXPECT("baseframe"); - EXPECT("{"); - for (i = 0; i < numjoints; i++) - { - EXPECT("("); - buffer = COM_Parse(buffer); - baseframe[i*6+0] = atof(com_token); - buffer = COM_Parse(buffer); - baseframe[i*6+1] = atof(com_token); - buffer = COM_Parse(buffer); - baseframe[i*6+2] = atof(com_token); - EXPECT(")"); - EXPECT("("); - buffer = COM_Parse(buffer); - baseframe[i*6+3] = atof(com_token); - buffer = COM_Parse(buffer); - baseframe[i*6+4] = atof(com_token); - buffer = COM_Parse(buffer); - baseframe[i*6+5] = atof(com_token); - EXPECT(")"); - } - EXPECT("}"); - - for (i = 0; i < numframes; i++) - { - EXPECT("frame"); - EXPECT(va("%i", i)); - EXPECT("{"); - for (j = 0; j < numanimatedparts; j++) - { - buffer = COM_Parse(buffer); - animatedcomponents[j] = atof(com_token); - } - EXPECT("}"); - - for (j = 0; j < numjoints; j++) - { - fac = firstanimatedcomponents[j]; - flags = boneflags[j]; - - if (flags&1) - tx = animatedcomponents[fac++]; - else - tx = baseframe[j*6+0]; - if (flags&2) - ty = animatedcomponents[fac++]; - else - ty = baseframe[j*6+1]; - if (flags&4) - tz = animatedcomponents[fac++]; - else - tz = baseframe[j*6+2]; - if (flags&8) - qx = animatedcomponents[fac++]; - else - qx = baseframe[j*6+3]; - if (flags&16) - qy = animatedcomponents[fac++]; - else - qy = baseframe[j*6+4]; - if (flags&32) - qz = animatedcomponents[fac++]; - else - qz = baseframe[j*6+5]; - - GenMatrix(tx, ty, tz, qx, qy, qz, posedata+12*(j+numjoints*i)); - } - } - - BZ_Free(firstanimatedcomponents); - BZ_Free(animatedcomponents); - BZ_Free(boneflags); - BZ_Free(baseframe); - - Q_strncpyz(grp.name, "", sizeof(grp.name)); - grp.isheirachical = true; - grp.numposes = numframes; - grp.rate = framespersecond; - grp.loop = true; - - *gat = grp; - return true; -#undef MD5ERROR0PARAM -#undef MD5ERROR1PARAM -#undef EXPECT -} - -/* -EXTERNALANIM - -//File what specifies md5 model/anim stuff. - -model test/imp.md5mesh - -group test/idle1.md5anim -clampgroup test/idle1.md5anim -frames test/idle1.md5anim - -*/ -qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer) -{ - int i; - - char *file; - galiasinfo_t *root = NULL; - int numgroups = 0; - galiasgroup_t *grouplist = NULL; - galiasgroup_t *newgroup = NULL; - void **poseofs; - int hunkstart, hunkend, hunktotal; - - - loadmodel=mod; - - Mod_DoCRC(mod, buffer, com_filesize); - - hunkstart = Hunk_LowMark (); - - - - - buffer = COM_Parse(buffer); - if (strcmp(com_token, "EXTERNALANIM")) - { - Con_Printf (CON_ERROR "EXTERNALANIM: header is not compleate (%s)\n", mod->name); - return false; - } - - buffer = COM_Parse(buffer); - if (!strcmp(com_token, "model")) - { - buffer = COM_Parse(buffer); - file = COM_LoadTempFile2(com_token); - - if (!file) //FIXME: make non fatal somehow.. - { - Con_Printf(CON_ERROR "Couldn't open %s (from %s)\n", com_token, mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - - root = Mod_ParseMD5MeshModel(file); - if (root == NULL) - { - Hunk_FreeToLowMark(hunkstart); - return false; - } - newgroup = (galiasgroup_t*)((char*)root + root->groupofs); - - grouplist = BZ_Malloc(sizeof(galiasgroup_t)*(numgroups+root->groups)); - memcpy(grouplist, newgroup, sizeof(galiasgroup_t)*(numgroups+root->groups)); - poseofs = BZ_Malloc(sizeof(galiasgroup_t)*(numgroups+root->groups)); - for (i = 0; i < root->groups; i++) - { - grouplist[numgroups] = newgroup[i]; - poseofs[numgroups] = (char*)&newgroup[i] + newgroup[i].poseofs; - numgroups++; - } - } - else - { - Con_Printf (CON_ERROR "EXTERNALANIM: model must be defined immediatly after the header\n"); - return false; - } - - for (;;) - { - buffer = COM_Parse(buffer); - if (!buffer) - break; - - if (!strcmp(com_token, "group")) - { - grouplist = BZ_Realloc(grouplist, sizeof(galiasgroup_t)*(numgroups+1)); - poseofs = BZ_Realloc(poseofs, sizeof(*poseofs)*(numgroups+1)); - buffer = COM_Parse(buffer); - file = COM_LoadTempFile2(com_token); - if (file) //FIXME: make non fatal somehow.. - { - char namebkup[MAX_QPATH]; - Q_strncpyz(namebkup, com_token, sizeof(namebkup)); - if (!Mod_ParseMD5Anim(file, root, &poseofs[numgroups], &grouplist[numgroups])) - { - Hunk_FreeToLowMark(hunkstart); - return false; - } - Q_strncpyz(grouplist[numgroups].name, namebkup, sizeof(grouplist[numgroups].name)); - numgroups++; - } - } - else if (!strcmp(com_token, "clampgroup")) - { - Con_Printf(CON_ERROR "EXTERNALANIM: clampgroup not yet supported (%s)\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - else if (!strcmp(com_token, "frames")) - { - Con_Printf (CON_ERROR "EXTERNALANIM: frames not yet supported (%s)\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - else - { - Con_Printf(CON_ERROR "EXTERNALANIM: unrecognised token (%s)\n", mod->name); - Hunk_FreeToLowMark(hunkstart); - return false; - } - } - - newgroup = grouplist; - grouplist = Hunk_Alloc(sizeof(galiasgroup_t)*numgroups); - for(;;) - { - root->groupofs = (char*)grouplist - (char*)root; - root->groups = numgroups; - if (!root->nextsurf) - break; - root = (galiasinfo_t*)((char*)root + root->nextsurf); - } - for (i = 0; i < numgroups; i++) - { - grouplist[i] = newgroup[i]; - grouplist[i].poseofs = (char*)poseofs[i] - (char*)&grouplist[i]; - } - - - hunkend = Hunk_LowMark (); - - mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. - - Mod_ClampModelSize(mod); - - Hunk_Alloc(0); - hunktotal = hunkend - hunkstart; - - Cache_Alloc (&mod->cache, hunktotal, loadname); - mod->type = mod_alias; - if (!mod->cache.data) - { - Hunk_FreeToLowMark (hunkstart); - return false; - } - memcpy (mod->cache.data, root, hunktotal); - - Hunk_FreeToLowMark (hunkstart); - - - mod->funcs.Trace = Mod_Trace; - return true; -} - -#endif //MD5MODELS - -#else -int Mod_TagNumForName(model_t *model, char *name) -{ - return 0; -} -qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) -{ - return false; -} -#endif //#if defined(D3DQUAKE) || defined(RGLQUAKE) + texnum->upperoverlay = 0; + + inshader++; + skin++; + texnum++; + } + galias->numskins = i; + } +#endif + + VectorCopy(min, loadmodel->mins); + VectorCopy(max, loadmodel->maxs); + + + Mod_CompileTriangleNeighbours (galias); + + surf = (md3Surface_t *)((qbyte *)surf + LittleLong(surf->ofsEnd)); + } + + if (!root) + root = Hunk_Alloc(sizeof(galiasinfo_t)); + + root->numtagframes = LittleLong(header->numFrames); + root->numtags = LittleLong(header->numTags); + root->ofstags = (char*)Hunk_Alloc(LittleLong(header->numTags)*sizeof(md3tag_t)*LittleLong(header->numFrames)) - (char*)root; + + { + md3tag_t *src; + md3tag_t *dst; + + src = (md3tag_t *)((char*)header+LittleLong(header->ofsTags)); + dst = (md3tag_t *)((char*)root+root->ofstags); + for(i=0;inumTags)*LittleLong(header->numFrames);i++) + { + memcpy(dst->name, src->name, sizeof(dst->name)); + for(j=0;j<3;j++) + { + dst->org[j] = LittleFloat(src->org[j]); + } + + for(j=0;j<3;j++) + { + for(s=0;s<3;s++) + { + dst->ang[j][s] = LittleFloat(src->ang[j][s]); + } + } + + src++; + dst++; + } + } + +// +// move the complete, relocatable alias model to the cache +// + + hunkend = Hunk_LowMark (); +#ifndef SERVERONLY + if (mod_md3flags.value) + mod->flags = LittleLong(header->flags); + else +#endif + mod->flags = 0; + if (!mod->flags) + mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); + + Mod_ClampModelSize(mod); + + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, root, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + mod->funcs.Trace = Mod_Trace; + + return true; +} +#endif + + + +#ifdef ZYMOTICMODELS + + +typedef struct zymlump_s +{ + int start; + int length; +} zymlump_t; + +typedef struct zymtype1header_s +{ + char id[12]; // "ZYMOTICMODEL", length 12, no termination + int type; // 0 (vertex morph) 1 (skeletal pose) or 2 (skeletal scripted) + int filesize; // size of entire model file + float mins[3], maxs[3], radius; // for clipping uses + int numverts; + int numtris; + int numsurfaces; + int numbones; // this may be zero in the vertex morph format (undecided) + int numscenes; // 0 in skeletal scripted models + +// skeletal pose header + // lump offsets are relative to the file + zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct) + zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data + zymlump_t lump_bones; // zymbone_t bone[numbones]; + zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better) + zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct + zymlump_t lump_texcoords; // float texcoords[numvertices][2]; + zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices) + zymlump_t lump_surfnames; // char shadername[numsurfaces][32]; // shaders used on this model + zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation +} zymtype1header_t; + +typedef struct zymbone_s +{ + char name[32]; + int flags; + int parent; // parent bone number +} zymbone_t; + +typedef struct zymscene_s +{ + char name[32]; + float mins[3], maxs[3], radius; // for clipping + float framerate; // the scene will animate at this framerate (in frames per second) + int flags; + int start, length; // range of poses +} zymscene_t; +#define ZYMSCENEFLAG_NOLOOP 1 + +typedef struct zymvertex_s +{ + int bonenum; + float origin[3]; +} zymvertex_t; + +//this can generate multiple meshes (one for each shader). +//but only one set of transforms are ever generated. +qboolean Mod_LoadZymoticModel(model_t *mod, void *buffer) +{ +#ifndef SERVERONLY + galiasskin_t *skin; + galiastexnum_t *texnum; + int skinfiles; + int j; +#endif + + int i; + int hunkstart, hunkend, hunktotal; + + zymtype1header_t *header; + galiasinfo_t *root; + + galisskeletaltransforms_t *transforms; + zymvertex_t *intrans; + + galiasbone_t *bone; + zymbone_t *inbone; + int v; + float multiplier; + float *matrix, *inmatrix; + + vec2_t *stcoords; + vec2_t *inst; + + int *vertbonecounts; + + galiasgroup_t *grp; + zymscene_t *inscene; + + int *renderlist, count; + index_t *indexes; + + char *surfname; + + + loadmodel=mod; + + Mod_DoCRC(mod, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + header = buffer; + + if (memcmp(header->id, "ZYMOTICMODEL", 12)) + { + Con_Printf("Mod_LoadZymoticModel: %s, doesn't appear to BE a zymotic!\n", mod->name); + return false; + } + + if (BigLong(header->type) != 1) + { + Con_Printf("Mod_LoadZymoticModel: %s, only type 1 is supported\n", mod->name); + return false; + } + + for (i = 0; i < sizeof(zymtype1header_t)/4; i++) + ((int*)header)[i] = BigLong(((int*)header)[i]); + + if (!header->numverts) + { + Con_Printf("Mod_LoadZymoticModel: %s, no vertexes\n", mod->name); + return false; + } + + if (!header->numsurfaces) + { + Con_Printf("Mod_LoadZymoticModel: %s, no surfaces\n", mod->name); + return false; + } + + VectorCopy(header->mins, mod->mins); + VectorCopy(header->maxs, mod->maxs); + + root = Hunk_AllocName(sizeof(galiasinfo_t)*header->numsurfaces, loadname); + + root->numtransforms = header->lump_verts.length/sizeof(zymvertex_t); + transforms = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); + root->ofstransforms = (char*)transforms - (char*)root; + + vertbonecounts = (int *)((char*)header + header->lump_vertbonecounts.start); + intrans = (zymvertex_t *)((char*)header + header->lump_verts.start); + + vertbonecounts[0] = BigLong(vertbonecounts[0]); + multiplier = 1.0f / vertbonecounts[0]; + for (i = 0, v=0; i < root->numtransforms; i++) + { + while(!vertbonecounts[v]) + { + v++; + if (v == header->numverts) + { + Con_Printf("Mod_LoadZymoticModel: %s, too many transformations\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + vertbonecounts[v] = BigLong(vertbonecounts[v]); + multiplier = 1.0f / vertbonecounts[v]; + } + transforms[i].vertexindex = v; + transforms[i].boneindex = BigLong(intrans[i].bonenum); + transforms[i].org[0] = multiplier*BigFloat(intrans[i].origin[0]); + transforms[i].org[1] = multiplier*BigFloat(intrans[i].origin[1]); + transforms[i].org[2] = multiplier*BigFloat(intrans[i].origin[2]); + transforms[i].org[3] = multiplier*1; + vertbonecounts[v]--; + } + if (intrans != (zymvertex_t *)((char*)header + header->lump_verts.start)) + { + Con_Printf(CON_ERROR "%s, Vertex transforms list appears corrupt.\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + if (vertbonecounts != (int *)((char*)header + header->lump_vertbonecounts.start)) + { + Con_Printf(CON_ERROR "%s, Vertex bone counts list appears corrupt.\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + + root->numverts = v+1; + + root->numbones = header->numbones; + bone = Hunk_Alloc(root->numtransforms*sizeof(*transforms)); + inbone = (zymbone_t*)((char*)header + header->lump_bones.start); + for (i = 0; i < root->numbones; i++) + { + Q_strncpyz(bone[i].name, inbone[i].name, sizeof(bone[i].name)); + bone[i].parent = BigLong(inbone[i].parent); + } + root->ofsbones = (char *)bone - (char *)root; + + renderlist = (int*)((char*)header + header->lump_render.start); + for (i = 0;i < header->numsurfaces; i++) + { + count = BigLong(*renderlist++); + count *= 3; + indexes = Hunk_Alloc(count*sizeof(*indexes)); + root[i].ofs_indexes = (char *)indexes - (char*)&root[i]; + root[i].numindexes = count; + while(count) + { //invert + indexes[count-1] = BigLong(renderlist[count-3]); + indexes[count-2] = BigLong(renderlist[count-2]); + indexes[count-3] = BigLong(renderlist[count-1]); + count-=3; + } + renderlist += root[i].numindexes; + } + if (renderlist != (int*)((char*)header + header->lump_render.start + header->lump_render.length)) + { + Con_Printf(CON_ERROR "%s, render list appears corrupt.\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + + grp = Hunk_Alloc(sizeof(*grp)*header->numscenes*header->numsurfaces); + matrix = Hunk_Alloc(header->lump_poses.length); + inmatrix = (float*)((char*)header + header->lump_poses.start); + for (i = 0; i < header->lump_poses.length/4; i++) + matrix[i] = BigFloat(inmatrix[i]); + inscene = (zymscene_t*)((char*)header + header->lump_scenes.start); + surfname = ((char*)header + header->lump_surfnames.start); + + stcoords = Hunk_Alloc(root[0].numverts*sizeof(vec2_t)); + inst = (vec2_t *)((char *)header + header->lump_texcoords.start); + for (i = 0; i < header->lump_texcoords.length/8; i++) + { + stcoords[i][0] = BigFloat(inst[i][0]); + stcoords[i][1] = 1-BigFloat(inst[i][1]); //hmm. upside down skin coords? + } + +#ifndef SERVERONLY + skinfiles = Mod_BuildSkinFileList(loadmodel->name); + if (skinfiles < 1) + skinfiles = 1; +#endif + + for (i = 0; i < header->numsurfaces; i++, surfname+=32) + { + root[i].groups = header->numscenes; + root[i].groupofs = (char*)grp - (char*)&root[i]; + +#ifdef SERVERONLY + root[i].numskins = 1; +#else + root[i].ofs_st_array = (char*)stcoords - (char*)&root[i]; + root[i].numskins = skinfiles; + + skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(galiastexnum_t))*skinfiles); + texnum = (galiastexnum_t*)(skin+skinfiles); + for (j = 0; j < skinfiles; j++, texnum++) + { + skin[j].texnums = 1; //non-sequenced skins. + skin[j].ofstexnums = (char *)texnum - (char *)&skin[j]; + + Mod_LoadSkinFile(texnum, surfname, j, NULL, 0, 0, NULL); + } + + root[i].ofsskins = (char *)skin - (char *)&root[i]; +#endif + } + + + for (i = 0; i < header->numscenes; i++, grp++, inscene++) + { + Q_strncpyz(grp->name, inscene->name, sizeof(grp->name)); + + grp->isheirachical = 1; + grp->rate = BigFloat(inscene->framerate); + grp->loop = !(BigLong(inscene->flags) & ZYMSCENEFLAG_NOLOOP); + grp->numposes = BigLong(inscene->length); + grp->poseofs = (char*)matrix - (char*)grp; + grp->poseofs += BigLong(inscene->start)*12*sizeof(float)*root->numbones; + } + + if (inscene != (zymscene_t*)((char*)header + header->lump_scenes.start+header->lump_scenes.length)) + { + Con_Printf(CON_ERROR "%s, scene list appears corrupt.\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + + for (i = 0; i < header->numsurfaces-1; i++) + root[i].nextsurf = sizeof(galiasinfo_t); + for (i = 1; i < header->numsurfaces; i++) + { + root[i].sharesverts = true; + root[i].numbones = root[0].numbones; + root[i].numverts = root[0].numverts; + + root[i].ofsbones = root[0].ofsbones; + + root[i-1].nextsurf = sizeof(*root); + } + +// +// move the complete, relocatable alias model to the cache +// + + hunkend = Hunk_LowMark (); + + mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. + + Mod_ClampModelSize(mod); + + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, root, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + + mod->funcs.Trace = Mod_Trace; + + return true; +} + + + + + + + + + +////////////////////////////////////////////////////////////// +//dpm + + +// header for the entire file +typedef struct dpmheader_s +{ + char id[16]; // "DARKPLACESMODEL\0", length 16 + unsigned int type; // 2 (hierarchical skeletal pose) + unsigned int filesize; // size of entire model file + float mins[3], maxs[3], yawradius, allradius; // for clipping uses + + // these offsets are relative to the file + unsigned int num_bones; + unsigned int num_meshs; + unsigned int num_frames; + unsigned int ofs_bones; // dpmbone_t bone[num_bones]; + unsigned int ofs_meshs; // dpmmesh_t mesh[num_meshs]; + unsigned int ofs_frames; // dpmframe_t frame[num_frames]; +} dpmheader_t; + +// there may be more than one of these +typedef struct dpmmesh_s +{ + // these offsets are relative to the file + char shadername[32]; // name of the shader to use + unsigned int num_verts; + unsigned int num_tris; + unsigned int ofs_verts; // dpmvertex_t vert[numvertices]; // see vertex struct + unsigned int ofs_texcoords; // float texcoords[numvertices][2]; + unsigned int ofs_indices; // unsigned int indices[numtris*3]; // designed for glDrawElements (each triangle is 3 unsigned int indices) + unsigned int ofs_groupids; // unsigned int groupids[numtris]; // the meaning of these values is entirely up to the gamecode and modeler +} dpmmesh_t; + +// if set on a bone, it must be protected from removal +#define DPMBONEFLAG_ATTACHMENT 1 + +// one per bone +typedef struct dpmbone_s +{ + // name examples: upperleftarm leftfinger1 leftfinger2 hand, etc + char name[32]; + // parent bone number + signed int parent; + // flags for the bone + unsigned int flags; +} dpmbone_t; + +// a bonepose matrix is intended to be used like this: +// (n = output vertex, v = input vertex, m = matrix, f = influence) +// n[0] = v[0] * m[0][0] + v[1] * m[0][1] + v[2] * m[0][2] + f * m[0][3]; +// n[1] = v[0] * m[1][0] + v[1] * m[1][1] + v[2] * m[1][2] + f * m[1][3]; +// n[2] = v[0] * m[2][0] + v[1] * m[2][1] + v[2] * m[2][2] + f * m[2][3]; +typedef struct dpmbonepose_s +{ + float matrix[3][4]; +} dpmbonepose_t; + +// immediately followed by bone positions for the frame +typedef struct dpmframe_s +{ + // name examples: idle_1 idle_2 idle_3 shoot_1 shoot_2 shoot_3, etc + char name[32]; + float mins[3], maxs[3], yawradius, allradius; + int ofs_bonepositions; // dpmbonepose_t bonepositions[bones]; +} dpmframe_t; + +// one or more of these per vertex +typedef struct dpmbonevert_s +{ + float origin[3]; // vertex location (these blend) + float influence; // influence fraction (these must add up to 1) + float normal[3]; // surface normal (these blend) + unsigned int bonenum; // number of the bone +} dpmbonevert_t; + +// variable size, parsed sequentially +typedef struct dpmvertex_s +{ + unsigned int numbones; + // immediately followed by 1 or more dpmbonevert_t structures +} dpmvertex_t; + +qboolean Mod_LoadDarkPlacesModel(model_t *mod, void *buffer) +{ +#ifndef SERVERONLY + galiasskin_t *skin; + galiastexnum_t *texnum; + int skinfiles; + float *inst; + float *outst; +#endif + + int i, j, k; + int hunkstart, hunkend, hunktotal; + + dpmheader_t *header; + galiasinfo_t *root, *m; + dpmmesh_t *mesh; + dpmvertex_t *vert; + dpmbonevert_t *bonevert; + + galisskeletaltransforms_t *transforms; + + galiasbone_t *outbone; + dpmbone_t *inbone; + + float *outposedata; + galiasgroup_t *outgroups; + float *inposedata; + dpmframe_t *inframes; + + unsigned int *index; index_t *outdex; // groan... + + int numtransforms; + int numverts; + + + loadmodel=mod; + + Mod_DoCRC(mod, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + header = buffer; + + if (memcmp(header->id, "DARKPLACESMODEL\0", 16)) + { + Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, doesn't appear to be a darkplaces model!\n", mod->name); + return false; + } + + if (BigLong(header->type) != 2) + { + Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, only type 2 is supported\n", mod->name); + return false; + } + + for (i = 0; i < sizeof(dpmheader_t)/4; i++) + ((int*)header)[i] = BigLong(((int*)header)[i]); + + if (!header->num_bones) + { + Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, no bones\n", mod->name); + return false; + } + if (!header->num_frames) + { + Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, no frames\n", mod->name); + return false; + } + if (!header->num_meshs) + { + Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: %s, no surfaces\n", mod->name); + return false; + } + + + VectorCopy(header->mins, mod->mins); + VectorCopy(header->maxs, mod->maxs); + + root = Hunk_AllocName(sizeof(galiasinfo_t)*header->num_meshs, loadname); + + mesh = (dpmmesh_t*)((char*)buffer + header->ofs_meshs); + for (i = 0; i < header->num_meshs; i++, mesh++) + { + //work out how much memory we need to allocate + + mesh->num_verts = BigLong(mesh->num_verts); + mesh->num_tris = BigLong(mesh->num_tris); + mesh->ofs_verts = BigLong(mesh->ofs_verts); + mesh->ofs_texcoords = BigLong(mesh->ofs_texcoords); + mesh->ofs_indices = BigLong(mesh->ofs_indices); + mesh->ofs_groupids = BigLong(mesh->ofs_groupids); + + + numverts = mesh->num_verts; + numtransforms = 0; + //count and byteswap the transformations + vert = (dpmvertex_t*)((char *)buffer+mesh->ofs_verts); + for (j = 0; j < mesh->num_verts; j++) + { + vert->numbones = BigLong(vert->numbones); + numtransforms += vert->numbones; + bonevert = (dpmbonevert_t*)(vert+1); + vert = (dpmvertex_t*)(bonevert+vert->numbones); + } + + m = &root[i]; +#ifdef SERVERONLY + transforms = Hunk_AllocName(numtransforms*sizeof(galisskeletaltransforms_t) + mesh->num_tris*3*sizeof(index_t), loadname); +#else + outst = Hunk_AllocName(numverts*sizeof(vec2_t) + numtransforms*sizeof(galisskeletaltransforms_t) + mesh->num_tris*3*sizeof(index_t), loadname); + m->ofs_st_array = (char*)outst - (char*)m; + m->numverts = mesh->num_verts; + inst = (float*)((char*)buffer + mesh->ofs_texcoords); + for (j = 0; j < numverts; j++, outst+=2, inst+=2) + { + outst[0] = BigFloat(inst[0]); + outst[1] = BigFloat(inst[1]); + } + + transforms = (galisskeletaltransforms_t*)outst; +#endif + + //build the transform list. + m->ofstransforms = (char*)transforms - (char*)m; + m->numtransforms = numtransforms; + vert = (dpmvertex_t*)((char *)buffer+mesh->ofs_verts); + for (j = 0; j < mesh->num_verts; j++) + { + bonevert = (dpmbonevert_t*)(vert+1); + for (k = 0; k < vert->numbones; k++, bonevert++, transforms++) + { + transforms->boneindex = BigLong(bonevert->bonenum); + transforms->vertexindex = j; + transforms->org[0] = BigFloat(bonevert->origin[0]); + transforms->org[1] = BigFloat(bonevert->origin[1]); + transforms->org[2] = BigFloat(bonevert->origin[2]); + transforms->org[3] = BigFloat(bonevert->influence); + //do nothing with the normals. :( + } + vert = (dpmvertex_t*)bonevert; + } + + index = (unsigned int*)((char*)buffer + mesh->ofs_indices); + outdex = (index_t *)transforms; + m->ofs_indexes = (char*)outdex - (char*)m; + m->numindexes = mesh->num_tris*3; + for (j = 0; j < m->numindexes; j++) + { + *outdex++ = BigLong(*index++); + } + } + + outbone = Hunk_Alloc(sizeof(galiasbone_t)*header->num_bones); + inbone = (dpmbone_t*)((char*)buffer + header->ofs_bones); + for (i = 0; i < header->num_bones; i++) + { + outbone[i].parent = BigLong(inbone[i].parent); + if (outbone[i].parent >= i || outbone[i].parent < -1) + { + Con_Printf(CON_ERROR "Mod_LoadDarkPlacesModel: bad bone index in %s\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + + Q_strncpyz(outbone[i].name, inbone[i].name, sizeof(outbone[i].name)); + //throw away the flags. + } + + outgroups = Hunk_Alloc(sizeof(galiasgroup_t)*header->num_frames + sizeof(float)*header->num_frames*header->num_bones*12); + outposedata = (float*)(outgroups+header->num_frames); + + inframes = (dpmframe_t*)((char*)buffer + header->ofs_frames); + for (i = 0; i < header->num_frames; i++) + { + inframes[i].ofs_bonepositions = BigLong(inframes[i].ofs_bonepositions); + inframes[i].allradius = BigLong(inframes[i].allradius); + inframes[i].yawradius = BigLong(inframes[i].yawradius); + inframes[i].mins[0] = BigLong(inframes[i].mins[0]); + inframes[i].mins[1] = BigLong(inframes[i].mins[1]); + inframes[i].mins[2] = BigLong(inframes[i].mins[2]); + inframes[i].maxs[0] = BigLong(inframes[i].maxs[0]); + inframes[i].maxs[1] = BigLong(inframes[i].maxs[1]); + inframes[i].maxs[2] = BigLong(inframes[i].maxs[2]); + + Q_strncpyz(outgroups[i].name, inframes[i].name, sizeof(outgroups[i].name)); + + outgroups[i].rate = 10; + outgroups[i].numposes = 1; + outgroups[i].isheirachical = true; + outgroups[i].poseofs = (char*)outposedata - (char*)&outgroups[i]; + + inposedata = (float*)((char*)buffer + inframes[i].ofs_bonepositions); + for (j = 0; j < header->num_bones*12; j++) + *outposedata++ = BigFloat(*inposedata++); + } + +#ifndef SERVERONLY + skinfiles = Mod_BuildSkinFileList(loadmodel->name); + if (skinfiles < 1) + skinfiles = 1; +#endif + + mesh = (dpmmesh_t*)((char*)buffer + header->ofs_meshs); + for (i = 0; i < header->num_meshs; i++, mesh++) + { + m = &root[i]; + if (i < header->num_meshs-1) + m->nextsurf = sizeof(galiasinfo_t); + m->sharesbones = true; + + m->ofsbones = (char*)outbone-(char*)m; + m->numbones = header->num_bones; + + m->groups = header->num_frames; + m->groupofs = (char*)outgroups - (char*)m; + + + +#ifdef SERVERONLY + m->numskins = 1; +#else + m->numskins = skinfiles; + + skin = Hunk_Alloc((sizeof(galiasskin_t)+sizeof(galiastexnum_t))*skinfiles); + texnum = (galiastexnum_t*)(skin+skinfiles); + for (j = 0; j < skinfiles; j++, texnum++) + { + skin[j].texnums = 1; //non-sequenced skins. + skin[j].ofstexnums = (char *)texnum - (char *)&skin[j]; + + Mod_LoadSkinFile(texnum, mesh->shadername, j, NULL, 0, 0, NULL); + } + + m->ofsskins = (char *)skin - (char *)m; +#endif + } + root[0].sharesbones = false; + + + + +// +// move the complete, relocatable alias model to the cache +// + hunkend = Hunk_LowMark (); + + mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. + + Mod_ClampModelSize(mod); + + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, root, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + + mod->funcs.Trace = Mod_Trace; + + return true; +} + + + + + + + +#endif //ZYMOTICMODELS + +#ifdef MD5MODELS + +static void GenMatrix(float x, float y, float z, float qx, float qy, float qz, float result[12]) +{ + float qw; + { //figure out qw + float term = 1 - (qx*qx) - (qy*qy) - (qz*qz); + if (term < 0) + qw = 0; + else + qw = - (float) sqrt(term); + } + + { //generate the matrix + /* + float xx = qx * qx; + float xy = qx * qy; + float xz = qx * qz; + float xw = qx * qw; + float yy = qy * qy; + float yz = qy * qz; + float yw = qy * qw; + float zz = qz * qz; + float zw = qz * qw; + result[0*4+0] = 1 - 2 * ( yy + zz ); + result[0*4+1] = 2 * ( xy - zw ); + result[0*4+2] = 2 * ( xz + yw ); + result[0*4+3] = x; + result[1*4+0] = 2 * ( xy + zw ); + result[1*4+1] = 1 - 2 * ( xx + zz ); + result[1*4+2] = 2 * ( yz - xw ); + result[1*4+3] = y; + result[2*4+0] = 2 * ( xz - yw ); + result[2*4+1] = 2 * ( yz + xw ); + result[2*4+2] = 1 - 2 * ( xx + yy ); + result[2*4+3] = z; + */ + + float xx, xy, xz, xw, yy, yz, yw, zz, zw; + float x2, y2, z2; + x2 = qx + qx; + y2 = qy + qy; + z2 = qz + qz; + + xx = qx * x2; xy = qx * y2; xz = qx * z2; + yy = qy * y2; yz = qy * z2; zz = qz * z2; + xw = qw * x2; yw = qw * y2; zw = qw * z2; + + result[0*4+0] = 1.0f - (yy + zz); + result[1*4+0] = xy + zw; + result[2*4+0] = xz - yw; + + result[0*4+1] = xy - zw; + result[1*4+1] = 1.0f - (xx + zz); + result[2*4+1] = yz + xw; + + result[0*4+2] = xz + yw; + result[1*4+2] = yz - xw; + result[2*4+2] = 1.0f - (xx + yy); + + result[0*4+3] = x; + result[1*4+3] = y; + result[2*4+3] = z; + } +} + +galiasinfo_t *Mod_ParseMD5MeshModel(char *buffer) +{ +#define MD5ERROR0PARAM(x) { Con_Printf(CON_ERROR x "\n"); return NULL; } +#define MD5ERROR1PARAM(x, y) { Con_Printf(CON_ERROR x "\n", y); return NULL; } +#define EXPECT(x) buffer = COM_Parse(buffer); if (strcmp(com_token, x)) Sys_Error("MD5MESH: expected %s", x); + int numjoints = 0; + int nummeshes = 0; + qboolean foundjoints = false; + int i; + + galiasbone_t *bones = NULL; + galiasgroup_t *pose = NULL; + galiasinfo_t *inf, *root, *lastsurf; + float *posedata; +#ifndef SERVERONLY + galiasskin_t *skin; + galiastexnum_t *texnum; +#endif + + float x, y, z, qx, qy, qz; + + + + buffer = COM_Parse(buffer); + if (strcmp(com_token, "MD5Version")) + MD5ERROR0PARAM("MD5 model without MD5Version identifier first"); + + buffer = COM_Parse(buffer); + if (atoi(com_token) != 10) + MD5ERROR0PARAM("MD5 model with unsupported MD5Version"); + + + root = Hunk_Alloc(sizeof(galiasinfo_t)); + lastsurf = NULL; + + for(;;) + { + buffer = COM_Parse(buffer); + if (!buffer) + break; + + if (!strcmp(com_token, "commandline")) + { //we don't need this + buffer = strchr(buffer, '\"'); + buffer = strchr((char*)buffer+1, '\"')+1; +// buffer = COM_Parse(buffer); + } + else if (!strcmp(com_token, "numJoints")) + { + if (numjoints) + MD5ERROR0PARAM("MD5MESH: numMeshes was already declared"); + buffer = COM_Parse(buffer); + numjoints = atoi(com_token); + if (numjoints <= 0) + MD5ERROR0PARAM("MD5MESH: Needs some joints"); + } + else if (!strcmp(com_token, "numMeshes")) + { + if (nummeshes) + MD5ERROR0PARAM("MD5MESH: numMeshes was already declared"); + buffer = COM_Parse(buffer); + nummeshes = atoi(com_token); + if (nummeshes <= 0) + MD5ERROR0PARAM("MD5MESH: Needs some meshes"); + } + else if (!strcmp(com_token, "joints")) + { + if (foundjoints) + MD5ERROR0PARAM("MD5MESH: Duplicate joints section"); + foundjoints=true; + if (!numjoints) + MD5ERROR0PARAM("MD5MESH: joints section before (or without) numjoints"); + + bones = Hunk_Alloc(sizeof(*bones) * numjoints); + pose = Hunk_Alloc(sizeof(galiasgroup_t)); + posedata = Hunk_Alloc(sizeof(float)*12 * numjoints); + pose->isheirachical = false; + pose->rate = 1; + pose->numposes = 1; + pose->poseofs = (char*)posedata - (char*)pose; + + Q_strncpyz(pose->name, "base", sizeof(pose->name)); + + EXPECT("{"); + //"name" parent (x y z) (s t u) + //stu are a normalized quaternion, which we will convert to a 3*4 matrix for no apparent reason + + for (i = 0; i < numjoints; i++) + { + buffer = COM_Parse(buffer); + Q_strncpyz(bones[i].name, com_token, sizeof(bones[i].name)); + buffer = COM_Parse(buffer); + bones[i].parent = atoi(com_token); + if (bones[i].parent >= i) + MD5ERROR0PARAM("MD5MESH: joints parent's must be lower"); + if ((bones[i].parent < 0 && i) || (!i && bones[i].parent!=-1)) + MD5ERROR0PARAM("MD5MESH: Only the root joint may have a negative parent"); + + EXPECT("("); + buffer = COM_Parse(buffer); + x = atof(com_token); + buffer = COM_Parse(buffer); + y = atof(com_token); + buffer = COM_Parse(buffer); + z = atof(com_token); + EXPECT(")"); + EXPECT("("); + buffer = COM_Parse(buffer); + qx = atof(com_token); + buffer = COM_Parse(buffer); + qy = atof(com_token); + buffer = COM_Parse(buffer); + qz = atof(com_token); + EXPECT(")"); + GenMatrix(x, y, z, qx, qy, qz, posedata+i*12); + } + EXPECT("}"); + } + else if (!strcmp(com_token, "mesh")) + { + int numverts = 0; + int numweights = 0; + int numtris = 0; + + int num; + int vnum; + + int numusableweights = 0; + int *firstweightlist = NULL; + int *numweightslist = NULL; + + galisskeletaltransforms_t *trans; +#ifndef SERVERONLY + float *stcoord = NULL; +#endif + int *indexes = NULL; + float w; + + vec4_t *rawweight = NULL; + int *rawweightbone = NULL; + + + if (!nummeshes) + MD5ERROR0PARAM("MD5MESH: mesh section before (or without) nummeshes"); + if (!foundjoints || !bones || !pose) + MD5ERROR0PARAM("MD5MESH: mesh must come after joints"); + + if (!lastsurf) + { + lastsurf = root; + inf = root; + } + else + { + inf = Hunk_Alloc(sizeof(*inf)); + lastsurf->nextsurf = (char*)inf - (char*)lastsurf; + lastsurf = inf; + } + + inf->ofsbones = (char*)bones - (char*)inf; + inf->numbones = numjoints; + inf->groups = 1; + inf->groupofs = (char*)pose - (char*)inf; + +#ifndef SERVERONLY + skin = Hunk_Alloc(sizeof(*skin)); + texnum = Hunk_Alloc(sizeof(*texnum)); + inf->numskins = 1; + inf->ofsskins = (char*)skin - (char*)inf; + skin->texnums = 1; + skin->skinspeed = 1; + skin->ofstexnums = (char*)texnum - (char*)skin; +#endif + EXPECT("{"); + for(;;) + { + buffer = COM_Parse(buffer); + if (!buffer) + MD5ERROR0PARAM("MD5MESH: unexpected eof"); + + if (!strcmp(com_token, "shader")) + { + buffer = COM_Parse(buffer); +#ifndef SERVERONLY + // texnum->shader = R_RegisterSkin(com_token); + texnum->base = Mod_LoadHiResTexture(com_token, "models", true, true, true); +#endif + } + else if (!strcmp(com_token, "numverts")) + { + if (numverts) + MD5ERROR0PARAM("MD5MESH: numverts was already specified"); + buffer = COM_Parse(buffer); + numverts = atoi(com_token); + if (numverts < 0) + MD5ERROR0PARAM("MD5MESH: numverts cannot be negative"); + + firstweightlist = Z_Malloc(sizeof(*firstweightlist) * numverts); + numweightslist = Z_Malloc(sizeof(*numweightslist) * numverts); +#ifndef SERVERONLY + stcoord = Hunk_Alloc(sizeof(float)*2*numverts); + inf->ofs_st_array = (char*)stcoord - (char*)inf; + inf->numverts = numverts; +#endif + } + else if (!strcmp(com_token, "vert")) + { //vert num ( s t ) firstweight numweights + + buffer = COM_Parse(buffer); + num = atoi(com_token); + if (num < 0 || num >= numverts || !indexes) + MD5ERROR0PARAM("MD5MESH: vertex out of range"); + + EXPECT("("); + buffer = COM_Parse(buffer); +#ifndef SERVERONLY + if (!stcoord) + MD5ERROR0PARAM("MD5MESH: vertex out of range"); + stcoord[num*2+0] = atof(com_token); +#endif + buffer = COM_Parse(buffer); +#ifndef SERVERONLY + stcoord[num*2+1] = atof(com_token); +#endif + EXPECT(")"); + buffer = COM_Parse(buffer); + firstweightlist[num] = atoi(com_token); + buffer = COM_Parse(buffer); + numweightslist[num] = atoi(com_token); + + numusableweights += numweightslist[num]; + } + else if (!strcmp(com_token, "numtris")) + { + if (numtris) + MD5ERROR0PARAM("MD5MESH: numtris was already specified"); + buffer = COM_Parse(buffer); + numtris = atoi(com_token); + if (numtris < 0) + MD5ERROR0PARAM("MD5MESH: numverts cannot be negative"); + + indexes = Hunk_Alloc(sizeof(int)*3*numtris); + inf->ofs_indexes = (char*)indexes - (char*)inf; + inf->numindexes = numtris*3; + } + else if (!strcmp(com_token, "tri")) + { + buffer = COM_Parse(buffer); + num = atoi(com_token); + if (num < 0 || num >= numtris) + MD5ERROR0PARAM("MD5MESH: vertex out of range"); + + buffer = COM_Parse(buffer); + indexes[num*3+0] = atoi(com_token); + buffer = COM_Parse(buffer); + indexes[num*3+1] = atoi(com_token); + buffer = COM_Parse(buffer); + indexes[num*3+2] = atoi(com_token); + } + else if (!strcmp(com_token, "numweights")) + { + if (numweights) + MD5ERROR0PARAM("MD5MESH: numweights was already specified"); + buffer = COM_Parse(buffer); + numweights = atoi(com_token); + + rawweight = Z_Malloc(sizeof(*rawweight)*numweights); + rawweightbone = Z_Malloc(sizeof(*rawweightbone)*numweights); + } + else if (!strcmp(com_token, "weight")) + { + //weight num bone scale ( x y z ) + buffer = COM_Parse(buffer); + num = atoi(com_token); + if (num < 0 || num >= numweights) + MD5ERROR0PARAM("MD5MESH: weight out of range"); + + buffer = COM_Parse(buffer); + rawweightbone[num] = atoi(com_token); + if (rawweightbone[num] < 0 || rawweightbone[num] >= numjoints) + MD5ERROR0PARAM("MD5MESH: weight specifies bad bone"); + buffer = COM_Parse(buffer); + w = atof(com_token); + + EXPECT("("); + buffer = COM_Parse(buffer); + rawweight[num][0] = w*atof(com_token); + buffer = COM_Parse(buffer); + rawweight[num][1] = w*atof(com_token); + buffer = COM_Parse(buffer); + rawweight[num][2] = w*atof(com_token); + EXPECT(")"); + rawweight[num][3] = w; + } + else if (!strcmp(com_token, "}")) + break; + else + MD5ERROR1PARAM("MD5MESH: Unrecognised token inside mesh (%s)", com_token); + + } + + trans = Hunk_Alloc(sizeof(*trans)*numusableweights); + inf->ofstransforms = (char*)trans - (char*)inf; + + for (num = 0, vnum = 0; num < numverts; num++) + { + if (numweightslist[num] <= 0) + MD5ERROR0PARAM("MD5MESH: weights not set on vertex"); + while(numweightslist[num]) + { + trans[vnum].vertexindex = num; + trans[vnum].boneindex = rawweightbone[firstweightlist[num]]; + trans[vnum].org[0] = rawweight[firstweightlist[num]][0]; + trans[vnum].org[1] = rawweight[firstweightlist[num]][1]; + trans[vnum].org[2] = rawweight[firstweightlist[num]][2]; + trans[vnum].org[3] = rawweight[firstweightlist[num]][3]; + vnum++; + firstweightlist[num]++; + numweightslist[num]--; + } + } + inf->numtransforms = vnum; + + if (firstweightlist) + Z_Free(firstweightlist); + if (numweightslist) + Z_Free(numweightslist); + if (rawweight) + Z_Free(rawweight); + if (rawweightbone) + Z_Free(rawweightbone); + } + else + MD5ERROR1PARAM("Unrecognised token in MD5 model (%s)", com_token); + } + + if (!lastsurf) + MD5ERROR0PARAM("MD5MESH: No meshes"); + + return root; +#undef MD5ERROR0PARAM +#undef MD5ERROR1PARAM +#undef EXPECT +} + +qboolean Mod_LoadMD5MeshModel(model_t *mod, void *buffer) +{ + galiasinfo_t *root; + int hunkstart, hunkend, hunktotal; + + + loadmodel=mod; + + Mod_DoCRC(mod, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + + root = Mod_ParseMD5MeshModel(buffer); + if (root == NULL) + { + Hunk_FreeToLowMark(hunkstart); + return false; + } + + + hunkend = Hunk_LowMark (); + + mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. + + Mod_ClampModelSize(mod); + + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, root, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + + mod->funcs.Trace = Mod_Trace; + return true; +} + +qboolean Mod_ParseMD5Anim(char *buffer, galiasinfo_t *prototype, void**poseofs, galiasgroup_t *gat) +{ +#define MD5ERROR0PARAM(x) { Con_Printf(CON_ERROR x "\n"); return false; } +#define MD5ERROR1PARAM(x, y) { Con_Printf(CON_ERROR x "\n", y); return false; } +#define EXPECT(x) buffer = COM_Parse(buffer); if (strcmp(com_token, x)) MD5ERROR1PARAM("MD5ANIM: expected %s", x); + unsigned int i, j; + + galiasgroup_t grp; + + unsigned int parent; + unsigned int numframes; + unsigned int numjoints; + float framespersecond; + unsigned int numanimatedparts; + galiasbone_t *bonelist; + + unsigned char *boneflags; + unsigned int *firstanimatedcomponents; + + float *animatedcomponents; + float *baseframe; //6 components. + float *posedata; + float tx, ty, tz, qx, qy, qz; + int fac, flags; + float f; + + EXPECT("MD5Version"); + EXPECT("10"); + + EXPECT("commandline"); + buffer = COM_Parse(buffer); + + EXPECT("numFrames"); + buffer = COM_Parse(buffer); + numframes = atoi(com_token); + + EXPECT("numJoints"); + buffer = COM_Parse(buffer); + numjoints = atoi(com_token); + + EXPECT("frameRate"); + buffer = COM_Parse(buffer); + framespersecond = atof(com_token); + + EXPECT("numAnimatedComponents"); + buffer = COM_Parse(buffer); + numanimatedparts = atoi(com_token); + + firstanimatedcomponents = BZ_Malloc(sizeof(int)*numjoints); + animatedcomponents = BZ_Malloc(sizeof(float)*numanimatedparts); + boneflags = BZ_Malloc(sizeof(unsigned char)*numjoints); + baseframe = BZ_Malloc(sizeof(float)*12*numjoints); + + *poseofs = posedata = Hunk_Alloc(sizeof(float)*12*numjoints*numframes); + + if (prototype) + { + if (prototype->numbones != numjoints) + MD5ERROR0PARAM("MD5ANIM: number of bones doesn't match"); + bonelist = (galiasbone_t *)((char*)prototype + prototype->ofsbones); + } + else + { + bonelist = Hunk_Alloc(sizeof(galiasbone_t)*numjoints); + prototype->ofsbones = (char*)bonelist - (char*)prototype; + prototype->numbones = numjoints; + } + + EXPECT("hierarchy"); + EXPECT("{"); + for (i = 0; i < numjoints; i++, bonelist++) + { + buffer = COM_Parse(buffer); + if (prototype) + { + if (strcmp(bonelist->name, com_token)) + MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", com_token); + } + else + Q_strncpyz(bonelist->name, com_token, sizeof(bonelist->name)); + buffer = COM_Parse(buffer); + parent = atoi(com_token); + if (prototype) + { + if (bonelist->parent != parent) + MD5ERROR1PARAM("MD5ANIM: bone name doesn't match (%s)", com_token); + } + else + bonelist->parent = parent; + + buffer = COM_Parse(buffer); + boneflags[i] = atoi(com_token); + buffer = COM_Parse(buffer); + firstanimatedcomponents[i] = atoi(com_token); + } + EXPECT("}"); + + EXPECT("bounds"); + EXPECT("{"); + for (i = 0; i < numframes; i++) + { + EXPECT("("); + buffer = COM_Parse(buffer);f=atoi(com_token); + if (f < loadmodel->mins[0]) loadmodel->mins[0] = f; + buffer = COM_Parse(buffer);f=atoi(com_token); + if (f < loadmodel->mins[1]) loadmodel->mins[1] = f; + buffer = COM_Parse(buffer);f=atoi(com_token); + if (f < loadmodel->mins[2]) loadmodel->mins[2] = f; + EXPECT(")"); + EXPECT("("); + buffer = COM_Parse(buffer);f=atoi(com_token); + if (f > loadmodel->maxs[0]) loadmodel->maxs[0] = f; + buffer = COM_Parse(buffer);f=atoi(com_token); + if (f > loadmodel->maxs[1]) loadmodel->maxs[1] = f; + buffer = COM_Parse(buffer);f=atoi(com_token); + if (f > loadmodel->maxs[2]) loadmodel->maxs[2] = f; + EXPECT(")"); + } + EXPECT("}"); + + EXPECT("baseframe"); + EXPECT("{"); + for (i = 0; i < numjoints; i++) + { + EXPECT("("); + buffer = COM_Parse(buffer); + baseframe[i*6+0] = atof(com_token); + buffer = COM_Parse(buffer); + baseframe[i*6+1] = atof(com_token); + buffer = COM_Parse(buffer); + baseframe[i*6+2] = atof(com_token); + EXPECT(")"); + EXPECT("("); + buffer = COM_Parse(buffer); + baseframe[i*6+3] = atof(com_token); + buffer = COM_Parse(buffer); + baseframe[i*6+4] = atof(com_token); + buffer = COM_Parse(buffer); + baseframe[i*6+5] = atof(com_token); + EXPECT(")"); + } + EXPECT("}"); + + for (i = 0; i < numframes; i++) + { + EXPECT("frame"); + EXPECT(va("%i", i)); + EXPECT("{"); + for (j = 0; j < numanimatedparts; j++) + { + buffer = COM_Parse(buffer); + animatedcomponents[j] = atof(com_token); + } + EXPECT("}"); + + for (j = 0; j < numjoints; j++) + { + fac = firstanimatedcomponents[j]; + flags = boneflags[j]; + + if (flags&1) + tx = animatedcomponents[fac++]; + else + tx = baseframe[j*6+0]; + if (flags&2) + ty = animatedcomponents[fac++]; + else + ty = baseframe[j*6+1]; + if (flags&4) + tz = animatedcomponents[fac++]; + else + tz = baseframe[j*6+2]; + if (flags&8) + qx = animatedcomponents[fac++]; + else + qx = baseframe[j*6+3]; + if (flags&16) + qy = animatedcomponents[fac++]; + else + qy = baseframe[j*6+4]; + if (flags&32) + qz = animatedcomponents[fac++]; + else + qz = baseframe[j*6+5]; + + GenMatrix(tx, ty, tz, qx, qy, qz, posedata+12*(j+numjoints*i)); + } + } + + BZ_Free(firstanimatedcomponents); + BZ_Free(animatedcomponents); + BZ_Free(boneflags); + BZ_Free(baseframe); + + Q_strncpyz(grp.name, "", sizeof(grp.name)); + grp.isheirachical = true; + grp.numposes = numframes; + grp.rate = framespersecond; + grp.loop = true; + + *gat = grp; + return true; +#undef MD5ERROR0PARAM +#undef MD5ERROR1PARAM +#undef EXPECT +} + +/* +EXTERNALANIM + +//File what specifies md5 model/anim stuff. + +model test/imp.md5mesh + +group test/idle1.md5anim +clampgroup test/idle1.md5anim +frames test/idle1.md5anim + +*/ +qboolean Mod_LoadCompositeAnim(model_t *mod, void *buffer) +{ + int i; + + char *file; + galiasinfo_t *root = NULL; + int numgroups = 0; + galiasgroup_t *grouplist = NULL; + galiasgroup_t *newgroup = NULL; + void **poseofs; + int hunkstart, hunkend, hunktotal; + + + loadmodel=mod; + + Mod_DoCRC(mod, buffer, com_filesize); + + hunkstart = Hunk_LowMark (); + + + + + buffer = COM_Parse(buffer); + if (strcmp(com_token, "EXTERNALANIM")) + { + Con_Printf (CON_ERROR "EXTERNALANIM: header is not compleate (%s)\n", mod->name); + return false; + } + + buffer = COM_Parse(buffer); + if (!strcmp(com_token, "model")) + { + buffer = COM_Parse(buffer); + file = COM_LoadTempFile2(com_token); + + if (!file) //FIXME: make non fatal somehow.. + { + Con_Printf(CON_ERROR "Couldn't open %s (from %s)\n", com_token, mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + + root = Mod_ParseMD5MeshModel(file); + if (root == NULL) + { + Hunk_FreeToLowMark(hunkstart); + return false; + } + newgroup = (galiasgroup_t*)((char*)root + root->groupofs); + + grouplist = BZ_Malloc(sizeof(galiasgroup_t)*(numgroups+root->groups)); + memcpy(grouplist, newgroup, sizeof(galiasgroup_t)*(numgroups+root->groups)); + poseofs = BZ_Malloc(sizeof(galiasgroup_t)*(numgroups+root->groups)); + for (i = 0; i < root->groups; i++) + { + grouplist[numgroups] = newgroup[i]; + poseofs[numgroups] = (char*)&newgroup[i] + newgroup[i].poseofs; + numgroups++; + } + } + else + { + Con_Printf (CON_ERROR "EXTERNALANIM: model must be defined immediatly after the header\n"); + return false; + } + + for (;;) + { + buffer = COM_Parse(buffer); + if (!buffer) + break; + + if (!strcmp(com_token, "group")) + { + grouplist = BZ_Realloc(grouplist, sizeof(galiasgroup_t)*(numgroups+1)); + poseofs = BZ_Realloc(poseofs, sizeof(*poseofs)*(numgroups+1)); + buffer = COM_Parse(buffer); + file = COM_LoadTempFile2(com_token); + if (file) //FIXME: make non fatal somehow.. + { + char namebkup[MAX_QPATH]; + Q_strncpyz(namebkup, com_token, sizeof(namebkup)); + if (!Mod_ParseMD5Anim(file, root, &poseofs[numgroups], &grouplist[numgroups])) + { + Hunk_FreeToLowMark(hunkstart); + return false; + } + Q_strncpyz(grouplist[numgroups].name, namebkup, sizeof(grouplist[numgroups].name)); + numgroups++; + } + } + else if (!strcmp(com_token, "clampgroup")) + { + Con_Printf(CON_ERROR "EXTERNALANIM: clampgroup not yet supported (%s)\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + else if (!strcmp(com_token, "frames")) + { + Con_Printf (CON_ERROR "EXTERNALANIM: frames not yet supported (%s)\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + else + { + Con_Printf(CON_ERROR "EXTERNALANIM: unrecognised token (%s)\n", mod->name); + Hunk_FreeToLowMark(hunkstart); + return false; + } + } + + newgroup = grouplist; + grouplist = Hunk_Alloc(sizeof(galiasgroup_t)*numgroups); + for(;;) + { + root->groupofs = (char*)grouplist - (char*)root; + root->groups = numgroups; + if (!root->nextsurf) + break; + root = (galiasinfo_t*)((char*)root + root->nextsurf); + } + for (i = 0; i < numgroups; i++) + { + grouplist[i] = newgroup[i]; + grouplist[i].poseofs = (char*)poseofs[i] - (char*)&grouplist[i]; + } + + + hunkend = Hunk_LowMark (); + + mod->flags = Mod_ReadFlagsFromMD1(mod->name, 0); //file replacement - inherit flags from any defunc mdl files. + + Mod_ClampModelSize(mod); + + Hunk_Alloc(0); + hunktotal = hunkend - hunkstart; + + Cache_Alloc (&mod->cache, hunktotal, loadname); + mod->type = mod_alias; + if (!mod->cache.data) + { + Hunk_FreeToLowMark (hunkstart); + return false; + } + memcpy (mod->cache.data, root, hunktotal); + + Hunk_FreeToLowMark (hunkstart); + + + mod->funcs.Trace = Mod_Trace; + return true; +} + +#endif //MD5MODELS + +#else +int Mod_TagNumForName(model_t *model, char *name) +{ + return 0; +} +qboolean Mod_GetTag(model_t *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) +{ + return false; +} +#endif //#if defined(D3DQUAKE) || defined(RGLQUAKE) diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index 209224fb5..7da48f6bc 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -1,123 +1,123 @@ - -#include "hash.h" -#include "shader.h" - -#if defined(ZYMOTICMODELS) || defined(MD5MODELS) -#define SKELETALMODELS -#include -#endif - -#define MAX_BONES 256 - - -typedef struct { - int ofs_indexes; - int numindexes; - - int ofs_trineighbours; - - int numskins; -#ifndef SERVERONLY - int ofsskins; -#endif - - qboolean sharesverts; //used with models with two shaders using the same vertex - use last mesh's verts - qboolean sharesbones; //use last mesh's bones (please, never set this on the first mesh!) - - int numverts; - -#ifndef SERVERONLY - int ofs_st_array; -#endif - - int groups; - int groupofs; - - int nextsurf; - -#ifdef SKELETALMODELS - int numbones; - int ofsbones; - int numtransforms; - int ofstransforms; -#endif - -//these exist only in the root mesh. - int numtagframes; - int numtags; - int ofstags; -} galiasinfo_t; - -//frame is an index into this -typedef struct { -#ifdef SKELETALMODELS - qboolean isheirachical; //for models with transforms, states that bones need to be transformed from their parent. - //this is actually bad, and can result in bones shortening as they interpolate. -#endif - qboolean loop; - int numposes; - float rate; - int poseofs; - char name[64]; -} galiasgroup_t; - -typedef struct { - int ofsverts; -#ifndef SERVERONLY - int ofsnormals; -#endif - - vec3_t scale; - vec3_t scale_origin; -} galiaspose_t; - -#ifdef SKELETALMODELS -typedef struct { - char name[32]; - int parent; -} galiasbone_t; - -typedef struct { - //skeletal poses refer to this. - int vertexindex; - int boneindex; - vec4_t org; -} galisskeletaltransforms_t; -#endif - -//we can't be bothered with animating skins. -//We'll load up to four of them but after that you're on your own -#ifndef SERVERONLY -typedef struct { - int skinwidth; - int skinheight; - int ofstexels; //this is 8bit for frame 0 only. only valid in q1 models without replacement textures, used for colourising player skins. - float skinspeed; - int texnums; - int ofstexnums; - char name [MAX_QPATH]; -} galiasskin_t; - -typedef struct { - int base; - int bump; + +#include "hash.h" +#include "shader.h" + +#if defined(ZYMOTICMODELS) || defined(MD5MODELS) +#define SKELETALMODELS +#include +#endif + +#define MAX_BONES 256 + + +typedef struct { + int ofs_indexes; + int numindexes; + + int ofs_trineighbours; + + int numskins; +#ifndef SERVERONLY + int ofsskins; +#endif + + qboolean sharesverts; //used with models with two shaders using the same vertex - use last mesh's verts + qboolean sharesbones; //use last mesh's bones (please, never set this on the first mesh!) + + int numverts; + +#ifndef SERVERONLY + int ofs_st_array; +#endif + + int groups; + int groupofs; + + int nextsurf; + +#ifdef SKELETALMODELS + int numbones; + int ofsbones; + int numtransforms; + int ofstransforms; +#endif + +//these exist only in the root mesh. + int numtagframes; + int numtags; + int ofstags; +} galiasinfo_t; + +//frame is an index into this +typedef struct { +#ifdef SKELETALMODELS + qboolean isheirachical; //for models with transforms, states that bones need to be transformed from their parent. + //this is actually bad, and can result in bones shortening as they interpolate. +#endif + qboolean loop; + int numposes; + float rate; + int poseofs; + char name[64]; +} galiasgroup_t; + +typedef struct { + int ofsverts; +#ifndef SERVERONLY + int ofsnormals; +#endif + + vec3_t scale; + vec3_t scale_origin; +} galiaspose_t; + +#ifdef SKELETALMODELS +typedef struct { + char name[32]; + int parent; +} galiasbone_t; + +typedef struct { + //skeletal poses refer to this. + int vertexindex; + int boneindex; + vec4_t org; +} galisskeletaltransforms_t; +#endif + +//we can't be bothered with animating skins. +//We'll load up to four of them but after that you're on your own +#ifndef SERVERONLY +typedef struct { + int skinwidth; + int skinheight; + int ofstexels; //this is 8bit for frame 0 only. only valid in q1 models without replacement textures, used for colourising player skins. + float skinspeed; + int texnums; + int ofstexnums; + char name [MAX_QPATH]; +} galiasskin_t; + +typedef struct { + int base; + int bump; int fullbright; int upperoverlay; - int loweroverlay; - -#ifdef Q3SHADERS - shader_t *shader; -#endif -} galiastexnum_t; - -typedef struct { - char name[MAX_QPATH]; - galiastexnum_t texnum; + int loweroverlay; + +#ifdef Q3SHADERS + shader_t *shader; +#endif +} galiastexnum_t; + +typedef struct { + char name[MAX_QPATH]; + galiastexnum_t texnum; unsigned int tcolour; - unsigned int bcolour; - int skinnum; - bucket_t bucket; -} galiascolourmapped_t; -#endif - - + unsigned int bcolour; + int skinnum; + bucket_t bucket; +} galiascolourmapped_t; +#endif + + diff --git a/engine/common/common.c b/engine/common/common.c index 46c3a0566..fbeec24b7 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -45,6 +45,7 @@ static char *safeargvs[NUM_SAFE_ARGVS] = {"-stdvid", "-nolan", "-nosound", "-nocdaudio", "-nojoy", "-nomouse"}; cvar_t registered = SCVAR("registered","0"); +cvar_t gameversion = SCVAR("gameversion","0"); cvar_t com_gamename = SCVAR("com_gamename", ""); qboolean com_modified; // set true if using non-id files @@ -2247,7 +2248,7 @@ char *COM_ParseToken (const char *data, const char *punctuation) // skip whitespace skipwhite: - while ( (c = *(unsigned char*)data) <= ' ') + while ( (c = *(unsigned char*)data) <= ' ' && c != '\r' && c != '\n') { if (c == 0) { @@ -2257,6 +2258,19 @@ skipwhite: data++; } + //if windows, ignore the \r. + if (c == '\r' && data[1] == '\n') + c = *(unsigned char*)data++; + + if (c == '\r' || c == '\n') + { + com_tokentype = TTP_LINEENDING; + com_token[0] = '\n'; + com_token[1] = '\0'; + data++; + return (char*)data; + } + // skip // comments if (c=='/') { @@ -2271,12 +2285,14 @@ skipwhite: data+=2; while (*data && (*data != '*' || data[1] != '/')) data++; - data+=2; + if (*data) + data++; + if (*data) + data++; goto skipwhite; } } - // handle quoted strings specially if (c == '\"') { @@ -2667,6 +2683,7 @@ void COM_Init (void) registered.string = "0"; Cvar_Register (®istered, "Copy protection"); + Cvar_Register (&gameversion, "Gamecode"); @@ -2718,8 +2735,92 @@ int memsearch (qbyte *start, int count, int search) return -1; } +struct effectinfo_s +{ + struct effectinfo_s *next; + int index; + char name[1]; +}; +struct effectinfo_s *effectinfo; +void COM_Effectinfo_Reset(void) +{ + int fidx = 0; + char *f; + struct effectinfo_s *n; + + while(effectinfo) + { + n = effectinfo->next; + Z_Free(effectinfo); + effectinfo = n; + } + + f = COM_LoadMallocFile("effectinfo.txt"); + if (!f) + return; + while (*f) + { + f = COM_ParseToken(f, NULL); + if (strcmp(com_token, "\n")) + { + if (!strcmp(com_token, "effect")) + { + f = COM_ParseToken(f, NULL); + //don't count duplicates + for (n = effectinfo; n; n = n->next) + { + if (!strcmp(com_token, n->name)) + break; + } + if (!n) + { + n = Z_Malloc(sizeof(*n) + strlen(com_token)); + n->next = effectinfo; + n->index = ++fidx; + effectinfo = n; + strcpy(n->name, com_token); + } + } + + do + { + f = COM_ParseToken(f, NULL); + } while(*f && strcmp(com_token, "\n")); + } + } +} + +unsigned int COM_Effectinfo_ForName(char *efname) +{ + struct effectinfo_s *e; + + if (!effectinfo) + COM_Effectinfo_Reset(); + + for (e = effectinfo; e; e = e->next) + { + if (!strcmp(efname, e->name)) + return e->index; + } + return 0; +} + +char *COM_Effectinfo_ForNumber(unsigned int efnum) +{ + struct effectinfo_s *e; + + if (!effectinfo) + COM_Effectinfo_Reset(); + + for (e = effectinfo; e; e = e->next) + { + if (e->index == efnum) + return e->name; + } + return ""; +} /* diff --git a/engine/common/common.h b/engine/common/common.h index 0f6c1c1db..3e4445d8f 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -229,7 +229,7 @@ float Q_atof (char *str); extern char com_token[1024]; -typedef enum {TTP_UNKNOWN, TTP_STRING} com_tokentype_t; +typedef enum {TTP_UNKNOWN, TTP_STRING, TTP_LINEENDING} com_tokentype_t; extern com_tokentype_t com_tokentype; extern qboolean com_eof; @@ -289,11 +289,15 @@ typedef struct { int offset; int len; } flocation_t; +struct vfsfile_s; typedef enum {FSLFRT_IFFOUND, FSLFRT_LENGTH, FSLFRT_DEPTH_OSONLY, FSLFRT_DEPTH_ANYPATH} FSLF_ReturnType_e; //if loc is valid, loc->search is always filled in, the others are filled on success. //returns -1 if couldn't find. int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *loc); +struct vfsfile_s *FS_OpenReadLocation(flocation_t *location); +char *FS_WhichPackForLocation(flocation_t *loc); + char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly); char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly); @@ -374,6 +378,10 @@ void COM_EnumerateFiles (char *match, int (*func)(char *, int, void *), void *pa extern struct cvar_s registered; extern qboolean standard_quake; //fixme: remove +void COM_Effectinfo_Reset(void); +unsigned int COM_Effectinfo_ForName(char *efname); +char *COM_Effectinfo_ForNumber(unsigned int efnum); + #define MAX_INFO_KEY 64 char *Info_ValueForKey (char *s, const char *key); void Info_RemoveKey (char *s, const char *key); diff --git a/engine/common/crc.c b/engine/common/crc.c index 57d841291..b35958e26 100644 --- a/engine/common/crc.c +++ b/engine/common/crc.c @@ -91,6 +91,17 @@ unsigned short QCRC_Block (qbyte *start, int count) return crc; } +unsigned short QCRC_Block_AsLower (qbyte *start, int count) +{ + unsigned short crc; + + QCRC_Init (&crc); + while (count--) + crc = (crc << 8) ^ crctable[(crc >> 8) ^ tolower(*start++)]; + + return crc; +} + void QCRC_AddBlock (unsigned short *crcvalue, qbyte *start, int count) { while (count--) diff --git a/engine/common/crc.h b/engine/common/crc.h index a2b7bfaf9..b73203db2 100644 --- a/engine/common/crc.h +++ b/engine/common/crc.h @@ -24,3 +24,4 @@ void QCRC_AddBlock (unsigned short *crcvalue, qbyte *start, int count); void QCRC_ProcessByte(unsigned short *crcvalue, qbyte data); unsigned short QCRC_Value(unsigned short crcvalue); unsigned short QCRC_Block (qbyte *start, int count); +unsigned short QCRC_Block_AsLower (qbyte *start, int count); diff --git a/engine/common/cvar.c b/engine/common/cvar.c index 772767319..0eac2b3d6 100644 --- a/engine/common/cvar.c +++ b/engine/common/cvar.c @@ -1180,8 +1180,9 @@ void Cvar_Unhook(cvar_t *cvar) void Cvar_ForceCallback(cvar_t *var) { - if (var->callback) - var->callback(var, var->string); + if (var) + if (var->callback) + var->callback(var, var->string); } void Cvar_ApplyCallbacks(int callbackflag) diff --git a/engine/common/cvar.h b/engine/common/cvar.h index 2c7628c4c..f584909c7 100644 --- a/engine/common/cvar.h +++ b/engine/common/cvar.h @@ -79,6 +79,7 @@ typedef struct cvar_s #define SCVARF(ConsoleName,Value, Flags) FCVAR(ConsoleName, NULL, Value, Flags) #define SCVARC(ConsoleName,Value,Callback) FCVARC(ConsoleName, NULL, Value, 0, Callback) #define SCVAR(ConsoleName,Value) FCVAR(ConsoleName, NULL, Value, 0) +#define CVARDP4(Flags,ConsoleName,Value,Description) FCVAR(ConsoleName, NULL, Value, Flags) typedef struct cvar_group_s { @@ -113,6 +114,9 @@ typedef struct cvar_group_s #define CVAR_LATCHMASK (CVAR_LATCH|CVAR_RENDERERLATCH|CVAR_SERVEROVERRIDE|CVAR_CHEAT|CVAR_SEMICHEAT) //you're only allowed one of these. #define CVAR_NEEDDEFAULT CVAR_CHEAT +//an alias +#define CVAR_SAVE CVAR_ARCHIVE + cvar_t *Cvar_Get (const char *var_name, const char *value, int flags, const char *groupname); void Cvar_LockFromServer(cvar_t *var, const char *str); diff --git a/engine/common/fs.c b/engine/common/fs.c index 1ee106d74..b79aa751c 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1324,6 +1324,7 @@ typedef struct searchpath_s qboolean istemporary; void *handle; + char purepath[256]; //server tracks the path used to load them so it can tell the client int crc_check; //client sorts packs according to this checksum int crc_reply; //client sends a different crc back to the server, for the paks it's actually loaded. @@ -1335,9 +1336,9 @@ searchpath_t *com_searchpaths; searchpath_t *com_purepaths; searchpath_t *com_base_searchpaths; // without gamedirs -static void COM_AddDataFiles(char *pathto, searchpath_t *search, char *extension, searchpathfuncs_t *funcs); +static void COM_AddDataFiles(char *purepath, char *pathto, searchpath_t *search, char *extension, searchpathfuncs_t *funcs); -searchpath_t *COM_AddPathHandle(char *probablepath, searchpathfuncs_t *funcs, void *handle, qboolean copyprotect, qboolean istemporary, unsigned int loadstuff) +searchpath_t *COM_AddPathHandle(char *purepath, char *probablepath, searchpathfuncs_t *funcs, void *handle, qboolean copyprotect, qboolean istemporary, unsigned int loadstuff) { searchpath_t *search; @@ -1346,6 +1347,7 @@ searchpath_t *COM_AddPathHandle(char *probablepath, searchpathfuncs_t *funcs, vo search->istemporary = istemporary; search->handle = handle; search->funcs = funcs; + Q_strncpyz(search->purepath, purepath, sizeof(search->purepath)); search->next = com_searchpaths; com_searchpaths = search; @@ -1355,19 +1357,19 @@ searchpath_t *COM_AddPathHandle(char *probablepath, searchpathfuncs_t *funcs, vo //add any data files too if (loadstuff & 2) - COM_AddDataFiles(probablepath, search, "pak", &packfilefuncs);//q1/hl/h2/q2 + COM_AddDataFiles(purepath, probablepath, search, "pak", &packfilefuncs);//q1/hl/h2/q2 //pk2s never existed. #ifdef AVAIL_ZLIB if (loadstuff & 4) - COM_AddDataFiles(probablepath, search, "pk3", &zipfilefuncs); //q3 + offspring + COM_AddDataFiles(purepath, probablepath, search, "pk3", &zipfilefuncs); //q3 + offspring if (loadstuff & 8) - COM_AddDataFiles(probablepath, search, "pk4", &zipfilefuncs); //q4 + COM_AddDataFiles(purepath, probablepath, search, "pk4", &zipfilefuncs); //q4 //we could easily add zip, but it's friendlier not to #endif #ifdef DOOMWADS if (loadstuff & 16) - COM_AddDataFiles(probablepath, search, "wad", &doomwadfilefuncs); //q4 + COM_AddDataFiles(purepath, probablepath, search, "wad", &doomwadfilefuncs); //q4 #endif return search; @@ -1703,6 +1705,7 @@ int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *lo } else len = 0; + com_file_copyprotected = search->copyprotected; goto out; } depth += (search->funcs != &osfilefuncs || returntype == FSLFRT_DEPTH_ANYPATH); @@ -1723,6 +1726,7 @@ int FS_FLocateFile(char *filename, FSLF_ReturnType_e returntype, flocation_t *lo } else len = 1; + com_file_copyprotected = search->copyprotected; goto out; } depth += (search->funcs != &osfilefuncs || returntype == FSLFRT_DEPTH_ANYPATH); @@ -1752,6 +1756,21 @@ out: return depth; } +char *FS_WhichPackForLocation(flocation_t *loc) +{ + char *ret; + if (!loc->search) + return NULL; //huh? not a valid location. + + ret = strchr(loc->search->purepath, '/'); + if (!ret) + return NULL; + ret++; + if (strchr(ret, '/')) + return NULL; + return ret; +} + char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly) { @@ -1783,7 +1802,31 @@ char *FS_GetPackHashes(char *buffer, int buffersize, qboolean referencedonly) } char *FS_GetPackNames(char *buffer, int buffersize, qboolean referencedonly) { - return ""; + searchpath_t *search; + buffersize--; + *buffer = 0; + + if (com_purepaths) + { + for (search = com_purepaths ; search ; search = search->nextpure) + { + Q_strncatz(buffer, va("%s ", search->purepath), buffersize); + } + return buffer; + } + else + { + for (search = com_searchpaths ; search ; search = search->next) + { + if (!search->crc_check && search->funcs->GeneratePureCRC) + search->crc_check = search->funcs->GeneratePureCRC(search->handle, 0, 0); + if (search->crc_check) + { + Q_strncatz(buffer, va("%s ", search->purepath), buffersize); + } + } + return buffer; + } } @@ -2067,6 +2110,7 @@ vfsfile_t *FS_OpenVFS(char *filename, char *mode, int relativeto) if (strcmp(mode, "ab")) return NULL; //urm, unable to write/append + //if there can only be one file (eg: write access) find out where it is. switch (relativeto) { case FS_GAMEONLY: //OS access only, no paks @@ -2130,6 +2174,16 @@ vfsfile_t *FS_OpenVFS(char *filename, char *mode, int relativeto) return NULL; } +vfsfile_t *FS_OpenReadLocation(flocation_t *location) +{ + if (location->search) + { + com_file_copyprotected = location->search->copyprotected; + return VFS_Filter(NULL, location->search->funcs->OpenVFS(location->search->handle, location, "rb")); + } + return NULL; +} + int FS_Rename2(char *oldf, char *newf, int oldrelativeto, int newrelativeto) { char oldfullname[MAX_OSPATH]; @@ -2534,6 +2588,7 @@ typedef struct { searchpathfuncs_t *funcs; searchpath_t *parentpath; char *parentdesc; + char *puredesc; } wildpaks_t; static int COM_AddWildDataFiles (char *descriptor, int size, void *vparam) @@ -2544,6 +2599,7 @@ static int COM_AddWildDataFiles (char *descriptor, int size, void *vparam) searchpath_t *search; pack_t *pak; char pakfile[MAX_OSPATH]; + char purefile[MAX_OSPATH]; flocation_t loc; sprintf (pakfile, "%s%s", param->parentdesc, descriptor); @@ -2566,22 +2622,28 @@ static int COM_AddWildDataFiles (char *descriptor, int size, void *vparam) return true; sprintf (pakfile, "%s%s/", param->parentdesc, descriptor); - COM_AddPathHandle(pakfile, funcs, pak, true, false, (unsigned int)-1); + if (*param->puredesc) + snprintf (purefile, sizeof(purefile), "%s/%s", param->puredesc, descriptor); + else + Q_strncpyz(purefile, descriptor, sizeof(purefile)); + COM_AddPathHandle(purefile, pakfile, funcs, pak, true, false, (unsigned int)-1); return true; } -static void COM_AddDataFiles(char *pathto, searchpath_t *search, char *extension, searchpathfuncs_t *funcs) +static void COM_AddDataFiles(char *purepath, char *pathto, searchpath_t *search, char *extension, searchpathfuncs_t *funcs) { //search is the parent int i; void *handle; char pakfile[MAX_OSPATH]; + char purefile[MAX_OSPATH]; vfsfile_t *vfs; flocation_t loc; wildpaks_t wp; + //first load all the numbered pak files for (i=0 ; ; i++) { snprintf (pakfile, sizeof(pakfile), "pak%i.%s", i, extension); @@ -2596,13 +2658,16 @@ static void COM_AddDataFiles(char *pathto, searchpath_t *search, char *extension if (!handle) break; snprintf (pakfile, sizeof(pakfile), "%spak%i.%s/", pathto, i, extension); - COM_AddPathHandle(pakfile, funcs, handle, true, false, (unsigned int)-1); + snprintf (purefile, sizeof(pakfile), "%spak%i.%s", purepath, i, extension); + COM_AddPathHandle(purefile, pakfile, funcs, handle, true, false, (unsigned int)-1); } + //now load the random ones sprintf (pakfile, "*.%s", extension); wp.funcs = funcs; wp.parentdesc = pathto; wp.parentpath = search; + wp.puredesc = purepath; search->funcs->EnumerateFiles(search->handle, pakfile, COM_AddWildDataFiles, &wp); } @@ -2624,7 +2689,7 @@ Sets com_gamedir, adds the directory to the head of the path, then loads and adds pak1.pak pak2.pak ... ================ */ -void COM_AddGameDirectory (char *dir, unsigned int loadstuff) +void COM_AddGameDirectory (char *puredir, char *dir, unsigned int loadstuff) { searchpath_t *search; @@ -2650,7 +2715,7 @@ void COM_AddGameDirectory (char *dir, unsigned int loadstuff) p = Z_Malloc(strlen(dir)+1); strcpy(p, dir); - COM_AddPathHandle(va("%s/", dir), &osfilefuncs, p, false, false, loadstuff); + COM_AddPathHandle((*dir?puredir:""), va("%s/", dir), &osfilefuncs, p, false, false, loadstuff); } char *COM_NextPath (char *prevpath) @@ -2684,7 +2749,7 @@ char *COM_GetPathInfo (int i, int *crc) searchpath_t *s; static char name[MAX_OSPATH]; - char adr[MAX_ADR_SIZE]; +// char adr[MAX_ADR_SIZE]; char *protocol; for (s=com_searchpaths ; s ; s=s->next) @@ -2696,11 +2761,13 @@ char *COM_GetPathInfo (int i, int *crc) if (i) //too high. return NULL; +/* #ifdef WEBSERVER if (httpserver.value) protocol = va("http://%s/", NET_AdrToString(adr, sizeof(adr), net_local_sv_ipadr)); else #endif + */ protocol = "qw://"; *crc = 0;//s->crc; @@ -2767,12 +2834,13 @@ void COM_Gamedir (char *dir) // Cache_Flush (); - COM_AddGameDirectory(va("%s%s", com_quakedir, dir), (unsigned int)-1); + COM_AddGameDirectory(dir, va("%s%s", com_quakedir, dir), (unsigned int)-1); if (*com_homedir) - COM_AddGameDirectory(va("%s%s", com_homedir, dir), (unsigned int)-1); + COM_AddGameDirectory(dir, va("%s%s", com_homedir, dir), (unsigned int)-1); #ifndef SERVERONLY + if (!isDedicated) { char fn[MAX_OSPATH]; FILE *f; @@ -2799,6 +2867,8 @@ void COM_Gamedir (char *dir) } #endif + COM_Effectinfo_Reset(); + Validation_FlushFileList(); //prevent previous hacks from making a difference. //FIXME: load new palette, if different cause a vid_restart. @@ -2983,7 +3053,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) //a lame way to fix pure paks #ifndef SERVERONLY - if (cls.state) + if (cls.state && com_purepaths) { CL_Disconnect_f(); CL_Reconnect_f(); @@ -3018,7 +3088,7 @@ void FS_ReloadPackFilesFlags(unsigned int reloadflags) com_base_searchpaths = com_searchpaths; if (oldpaths->funcs == &osfilefuncs) - COM_AddGameDirectory(oldpaths->handle, reloadflags); + COM_AddGameDirectory(oldpaths->purepath, oldpaths->handle, reloadflags); oldpaths->funcs->ClosePath(oldpaths->handle); Z_Free(oldpaths); @@ -3233,7 +3303,7 @@ void COM_InitFilesystem (void) { do //use multiple -basegames { - COM_AddGameDirectory (va("%s%s", com_quakedir, com_argv[i+1]), (unsigned int)-1); + COM_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), (unsigned int)-1); i = COM_CheckNextParm ("-basegame", i); } @@ -3242,17 +3312,17 @@ void COM_InitFilesystem (void) else { if (gamemode_info[gamenum].dir1) - COM_AddGameDirectory (va("%s%s", com_quakedir, gamemode_info[gamenum].dir1), (unsigned int)-1); + COM_AddGameDirectory (gamemode_info[gamenum].dir1, va("%s%s", com_quakedir, gamemode_info[gamenum].dir1), (unsigned int)-1); if (gamemode_info[gamenum].dir2) - COM_AddGameDirectory (va("%s%s", com_quakedir, gamemode_info[gamenum].dir2), (unsigned int)-1); + COM_AddGameDirectory (gamemode_info[gamenum].dir2, va("%s%s", com_quakedir, gamemode_info[gamenum].dir2), (unsigned int)-1); if (gamemode_info[gamenum].dir3) - COM_AddGameDirectory (va("%s%s", com_quakedir, gamemode_info[gamenum].dir3), (unsigned int)-1); + COM_AddGameDirectory (gamemode_info[gamenum].dir3, va("%s%s", com_quakedir, gamemode_info[gamenum].dir3), (unsigned int)-1); if (gamemode_info[gamenum].dir4) - COM_AddGameDirectory (va("%s%s", com_quakedir, gamemode_info[gamenum].dir4), (unsigned int)-1); + COM_AddGameDirectory (gamemode_info[gamenum].dir4, va("%s%s", com_quakedir, gamemode_info[gamenum].dir4), (unsigned int)-1); } if (*com_homedir) - COM_AddGameDirectory (va("%sfte", com_homedir), (unsigned int)-1); + COM_AddGameDirectory ("fte", va("%sfte", com_homedir), (unsigned int)-1); // any set gamedirs will be freed up to here com_base_searchpaths = com_searchpaths; @@ -3260,7 +3330,7 @@ void COM_InitFilesystem (void) i = COM_CheckParm ("-game"); //effectivly replace with +gamedir x (But overridable) if (i && i < com_argc-1) { - COM_AddGameDirectory (va("%s%s", com_quakedir, com_argv[i+1]), (unsigned int)-1); + COM_AddGameDirectory (com_argv[i+1], va("%s%s", com_quakedir, com_argv[i+1]), (unsigned int)-1); #ifndef CLIENTONLY Info_SetValueForStarKey (svs.info, "*gamedir", com_argv[i+1], MAX_SERVERINFO_STRING); diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 9ce15a38d..93d633651 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -1046,12 +1046,13 @@ void *Mod_LoadWall(char *name) COM_FileBase(name, ln, sizeof(ln)); - if (!CL_CheckOrEnqueDownloadFile(name, NULL)) - return NULL; - wal = (void *)COM_LoadMallocFile (name); if (!wal) + { + //they will download eventually... + CL_CheckOrEnqueDownloadFile(name, NULL, 0); return NULL; + } wal->width = LittleLong(wal->width); wal->height = LittleLong(wal->height); diff --git a/engine/common/huff.c b/engine/common/huff.c index 9207b800b..1c3082550 100644 --- a/engine/common/huff.c +++ b/engine/common/huff.c @@ -103,14 +103,15 @@ static int huffBitPos; Huff_PrepareTree ============ */ -static ID_INLINE void Huff_PrepareTree( tree_t tree ) { +static ID_INLINE void Huff_PrepareTree(tree_t tree) +{ void **node; - memset( tree, 0, sizeof( tree_t ) ); + memset(tree, 0, sizeof(tree_t)); // create first node node = &tree[263]; - tree[0] = (void*)(VALUE( tree[0] )+1); + tree[0] = (void*)(VALUE(tree[0])+1); node[7] = NODE_NONE; tree[2] = node; @@ -126,13 +127,15 @@ static ID_INLINE void Huff_PrepareTree( tree_t tree ) { Huff_GetNode ============ */ -static ID_INLINE void **Huff_GetNode( void **tree ) { +static ID_INLINE void **Huff_GetNode(void **tree) +{ void **node; int value; node = (void**)tree[262]; - if( !node ) { - value = VALUE( tree[1] )++; + if (!node) + { + value = VALUE(tree[1])++; node = &tree[value + 6407]; return node; } @@ -146,24 +149,27 @@ static ID_INLINE void **Huff_GetNode( void **tree ) { Huff_Swap ============ */ -static ID_INLINE void Huff_Swap( void **tree1, void **tree2, void **tree3 ) { +static ID_INLINE void Huff_Swap(void **tree1, void **tree2, void **tree3) +{ void **a, **b; a = (void**)tree2[2]; - if( a ) { - if( a[0] == tree2 ) { + if (a) + { + if (a[0] == tree2) a[0] = tree3; - } else { + else a[1] = tree3; - } - } else { - tree1[2] = tree3; } + else + tree1[2] = tree3; b = (void**)tree3[2]; - if( b ) { - if( b[0] == tree3 ) { + if (b) + { + if (b[0] == tree3) + { b[0] = tree2; tree2[2] = b; tree3[2] = a; @@ -186,7 +192,8 @@ static ID_INLINE void Huff_Swap( void **tree1, void **tree2, void **tree3 ) { Huff_SwapTrees ============ */ -static ID_INLINE void Huff_SwapTrees( void **tree1, void **tree2 ) { +static ID_INLINE void Huff_SwapTrees(void **tree1, void **tree2) +{ void **temp; temp = (void**)tree1[3]; @@ -197,33 +204,27 @@ static ID_INLINE void Huff_SwapTrees( void **tree1, void **tree2 ) { tree1[4] = tree2[4]; tree2[4] = temp; - if( tree1[3] == tree1 ) { + if (tree1[3] == tree1) tree1[3] = tree2; - } - if( tree2[3] == tree2 ) { + if (tree2[3] == tree2) tree2[3] = tree1; - } temp = (void**)tree1[3]; - if( temp ) { + if (temp) temp[4] = tree1; - } temp = (void**)tree2[3]; - if( temp ) { + if (temp) temp[4] = tree2; - } temp = (void**)tree1[4]; - if( temp ) { + if (temp) temp[3] = tree1; - } temp = (void**)tree2[4]; - if( temp ) { + if (temp) temp[3] = tree2; - } } @@ -232,7 +233,8 @@ static ID_INLINE void Huff_SwapTrees( void **tree1, void **tree2 ) { Huff_DeleteNode ============ */ -static ID_INLINE void Huff_DeleteNode( void **tree1, void **tree2 ) { +static ID_INLINE void Huff_DeleteNode(void **tree1, void **tree2) +{ tree2[0] = tree1[262]; tree1[262] = tree2; } @@ -242,54 +244,68 @@ static ID_INLINE void Huff_DeleteNode( void **tree1, void **tree2 ) { Huff_IncrementFreq_r ============ */ -static void Huff_IncrementFreq_r( void **tree1, void **tree2 ) { +static void Huff_IncrementFreq_r(void **tree1, void **tree2) +{ void **a, **b; - if( !tree2 ) { + if (!tree2) + { return; } a = (void**)tree2[3]; - if( a ) { + if (a) + { a = (void**)a[6]; - if( a == tree2[6] ) { + if (a == tree2[6]) + { b = (void**)tree2[5]; - if( b[0] != tree2[2] ) { - Huff_Swap( tree1, (void**)b[0], tree2 ); + if (b[0] != tree2[2]) + { + Huff_Swap(tree1, (void**)b[0], tree2); } - Huff_SwapTrees( (void**)b[0], tree2 ); + Huff_SwapTrees((void**)b[0], tree2); } } a = (void**)tree2[4]; - if( a && a[6] == tree2[6] ) { + if (a && a[6] == tree2[6]) + { b = (void**)tree2[5]; b[0] = a; - } else { + } + else + { a = (void**)tree2[5]; a[0] = 0; - Huff_DeleteNode( tree1, (void**)tree2[5] ); + Huff_DeleteNode(tree1, (void**)tree2[5]); } - VALUE( tree2[6] )++; + VALUE(tree2[6])++; a = (void**)tree2[3]; - if( a && a[6] == tree2[6] ) { + if (a && a[6] == tree2[6]) + { tree2[5] = a[5]; - } else { - a = Huff_GetNode( tree1 ); + } + else + { + a = Huff_GetNode(tree1); tree2[5] = a; a[0] = tree2; } - if( tree2[2] ) { - Huff_IncrementFreq_r( tree1, (void**)tree2[2] ); + if (tree2[2]) + { + Huff_IncrementFreq_r(tree1, (void**)tree2[2]); - if( tree2[4] == tree2[2] ) { - Huff_SwapTrees( tree2, (void**)tree2[2] ); + if (tree2[4] == tree2[2]) + { + Huff_SwapTrees(tree2, (void**)tree2[2]); a = (void**)tree2[5]; - if( a[0] == tree2 ) { + if (a[0] == tree2) + { a[0] = (void**)tree2[2]; } } @@ -303,39 +319,47 @@ Huff_AddReference Insert 'ch' into the tree or increment it's frequency ============ */ -static void Huff_AddReference( void **tree, int ch ) { +static void Huff_AddReference(void **tree, int ch) +{ void **a, **b, **c, **d; int value; ch &= 255; - if( tree[ch + 5] ) { - Huff_IncrementFreq_r( tree, (void**)tree[ch + 5] ); + if (tree[ch + 5]) + { + Huff_IncrementFreq_r(tree, (void**)tree[ch + 5]); return; // already added } - value = VALUE( tree[0] )++; + value = VALUE(tree[0])++; b = &tree[value * 8 + 263]; - value = VALUE( tree[0] )++; + value = VALUE(tree[0])++; a = &tree[value * 8 + 263]; a[7] = NODE_NEXT; a[6] = NODE_START; d = (void**)tree[3]; a[3] = d[3]; - if( a[3] ) { + if (a[3]) + { d = (void**)a[3]; d[4] = a; d = (void**)a[3]; - if( d[6] == NODE_START ) { + if (d[6] == NODE_START) + { a[5] = d[5]; - } else { - d = Huff_GetNode( tree ); + } + else + { + d = Huff_GetNode(tree); a[5] = d; d[0] = a; } - } else { - d = Huff_GetNode( tree ); + } + else + { + d = Huff_GetNode(tree); a[5] = d; d[0] = a; @@ -344,22 +368,28 @@ static void Huff_AddReference( void **tree, int ch ) { d = (void**)tree[3]; d[3] = a; a[4] = (void**)tree[3]; - b[7] = NODE( ch ); + b[7] = NODE(ch); b[6] = NODE_START; d = (void**)tree[3]; b[3] = d[3]; - if( b[3] ) { + if (b[3]) + { d = (void**)b[3]; d[4] = b; - if( d[6] == NODE_START ) { + if (d[6] == NODE_START) + { b[5] = d[5]; - } else { - d = Huff_GetNode( tree ); + } + else + { + d = Huff_GetNode(tree); b[5] = d; d[0] = a; } - } else { - d = Huff_GetNode( tree ); + } + else + { + d = Huff_GetNode(tree); b[5] = d; d[0] = b; } @@ -371,13 +401,19 @@ static void Huff_AddReference( void **tree, int ch ) { b[0] = NULL; d = (void**)tree[3]; c = (void**)d[2]; - if( c ) { - if( c[0] == tree[3] ) { + if (c) + { + if (c[0] == tree[3]) + { c[0] = a; - } else { + } + else + { c[1] = a; } - } else { + } + else + { tree[2] = a; } @@ -390,7 +426,7 @@ static void Huff_AddReference( void **tree, int ch ) { d[2] = a; tree[ch + 5] = b; - Huff_IncrementFreq_r( tree, (void**)a[2] ); + Huff_IncrementFreq_r(tree, (void**)a[2]); } /* @@ -408,8 +444,10 @@ Huff_EmitBit Put one bit into buffer ============ */ -static ID_INLINE void Huff_EmitBit( int bit, qbyte *buffer ) { - if( !(huffBitPos & 7) ) { +static ID_INLINE void Huff_EmitBit(int bit, qbyte *buffer) +{ + if (!(huffBitPos & 7)) + { buffer[huffBitPos >> 3] = 0; } @@ -424,7 +462,8 @@ Huff_GetBit Read one bit from buffer ============ */ -static ID_INLINE int Huff_GetBit( qbyte *buffer ) { +static ID_INLINE int Huff_GetBit(qbyte *buffer) +{ int bit; bit = buffer[huffBitPos >> 3] >> (huffBitPos & 7); @@ -438,22 +477,28 @@ static ID_INLINE int Huff_GetBit( qbyte *buffer ) { Huff_EmitPathToByte ============ */ -static ID_INLINE void Huff_EmitPathToByte( void **tree, void **subtree, qbyte *buffer ) { - if( tree[2] ) { - Huff_EmitPathToByte( (void**)tree[2], tree, buffer ); +static ID_INLINE void Huff_EmitPathToByte(void **tree, void **subtree, qbyte *buffer) +{ + if (tree[2]) + { + Huff_EmitPathToByte((void**)tree[2], tree, buffer); } - if( !subtree ) { + if (!subtree) + { return; } // // emit tree walking control bits // - if( tree[1] == subtree ) { - Huff_EmitBit( 1, buffer ); - } else { - Huff_EmitBit( 0, buffer ); + if (tree[1] == subtree) + { + Huff_EmitBit(1, buffer); + } + else + { + Huff_EmitBit(0, buffer); } } @@ -464,27 +509,34 @@ Huff_GetByteFromTree Get one qbyte using dynamic or static tree ============ */ -static ID_INLINE int Huff_GetByteFromTree( void **tree, qbyte *buffer ) { - if( !tree ) { +static ID_INLINE int Huff_GetByteFromTree(void **tree, qbyte *buffer) +{ + if (!tree) + { return 0; } // // walk through the tree until we get a value // - while( tree[7] == NODE_NEXT ) { - if( !Huff_GetBit( buffer ) ) { + while (tree[7] == NODE_NEXT) + { + if (!Huff_GetBit(buffer)) + { tree = (void**)tree[0]; - } else { + } + else + { tree = (void**)tree[1]; } - if( !tree ) { + if (!tree) + { return 0; } } - return VALUE( tree[7] ); + return VALUE(tree[7]); } /* @@ -494,7 +546,8 @@ Huff_EmitByteDynamic Emit one qbyte using dynamic tree ============ */ -static void Huff_EmitByteDynamic( void **tree, int value, qbyte *buffer ) { +static void Huff_EmitByteDynamic(void **tree, int value, qbyte *buffer) +{ void **subtree; int i; @@ -502,9 +555,11 @@ static void Huff_EmitByteDynamic( void **tree, int value, qbyte *buffer ) { // if qbyte was already referenced, emit path to it // subtree = (void**)tree[value + 5]; - if( subtree ) { - if( subtree[2] ) { - Huff_EmitPathToByte( (void**)subtree[2], subtree, buffer ); + if (subtree) + { + if (subtree[2]) + { + Huff_EmitPathToByte((void**)subtree[2], subtree, buffer); } return; } @@ -512,10 +567,11 @@ static void Huff_EmitByteDynamic( void **tree, int value, qbyte *buffer ) { // // qbyte was not referenced, just emit 8 bits // - Huff_EmitByteDynamic( tree, NOT_REFERENCED, buffer ); + Huff_EmitByteDynamic(tree, NOT_REFERENCED, buffer); - for( i=7 ; i>=0 ; i-- ) { - Huff_EmitBit( (value >> i) & 1, buffer ); + for (i = 7; i >= 0; i--) + { + Huff_EmitBit((value >> i) & 1, buffer); } } @@ -536,7 +592,8 @@ Compress message using dynamic Huffman tree, beginning from specified offset ============ */ -void Huff_EncryptPacket( sizebuf_t *msg, int offset ) { +void Huff_EncryptPacket(sizebuf_t *msg, int offset) +{ tree_t tree; qbyte buffer[MAX_NQMSGLEN]; qbyte *data; @@ -545,26 +602,28 @@ void Huff_EncryptPacket( sizebuf_t *msg, int offset ) { int i; data = msg->data + offset; - inLen = msg->cursize - offset; - if( inLen <= 0 || inLen >= MAX_NQMSGLEN ) { + inLen = msg->cursize - offset; + if (inLen <= 0 || inLen >= MAX_NQMSGLEN) + { return; } - Huff_PrepareTree( tree ); + Huff_PrepareTree(tree); buffer[0] = inLen >> 8; buffer[1] = inLen & 0xFF; huffBitPos = 16; - for( i=0 ; i> 3) + 1; msg->cursize = offset + outLen; - memcpy( data, buffer, outLen ); + memcpy(data, buffer, outLen); } @@ -576,7 +635,8 @@ Decompress message using dynamic Huffman tree, beginning from specified offset ============ */ -void Huff_DecryptPacket( sizebuf_t *msg, int offset ) { +void Huff_DecryptPacket(sizebuf_t *msg, int offset) +{ tree_t tree; qbyte buffer[MAX_NQMSGLEN]; qbyte *data; @@ -587,42 +647,48 @@ void Huff_DecryptPacket( sizebuf_t *msg, int offset ) { data = msg->data + offset; inLen = msg->cursize - offset; - if( inLen <= 0 ) { + if (inLen <= 0) + { return; } - Huff_PrepareTree( tree ); + Huff_PrepareTree(tree); outLen = (data[0] << 8) + data[1]; huffBitPos = 16; - if( outLen > msg->maxsize - offset ) { + if (outLen > msg->maxsize - offset) + { outLen = msg->maxsize - offset; } - for( i=0 ; i> 3) > inLen ) { + for (i = 0; i < outLen; i++) + { + if ((huffBitPos >> 3) > inLen) + { buffer[i] = 0; break; } - ch = Huff_GetByteFromTree( (void**)tree[2], data ); + ch = Huff_GetByteFromTree((void**)tree[2], data); - if( ch == NOT_REFERENCED ) { + if (ch == NOT_REFERENCED) + { ch = 0; // just read 8 bits - for( j=0 ; j<8 ; j++ ) { + for (j = 0 ; j < 8 ; j++) + { ch <<= 1; - ch |= Huff_GetBit( data ); + ch |= Huff_GetBit(data); } } buffer[i] = ch; - Huff_AddReference( tree, ch ); + Huff_AddReference(tree, ch); } msg->cursize = offset + outLen; - memcpy( data, buffer, outLen ); + memcpy(data, buffer, outLen); } /* @@ -630,9 +696,10 @@ void Huff_DecryptPacket( sizebuf_t *msg, int offset ) { Huff_EmitByte ============ */ -void Huff_EmitByte( int ch, qbyte *buffer, int *count ) { +void Huff_EmitByte(int ch, qbyte *buffer, int *count) +{ huffBitPos = *count; - Huff_EmitPathToByte( (void**)huffTree[ch + 5], NULL, buffer ); + Huff_EmitPathToByte((void**)huffTree[ch + 5], NULL, buffer); *count = huffBitPos; } @@ -641,11 +708,12 @@ void Huff_EmitByte( int ch, qbyte *buffer, int *count ) { Huff_GetByte ============ */ -int Huff_GetByte( qbyte *buffer, int *count ) { +int Huff_GetByte(qbyte *buffer, int *count) +{ int ch; huffBitPos = *count; - ch = Huff_GetByteFromTree( (void**)huffTree[2], buffer ); + ch = Huff_GetByteFromTree((void**)huffTree[2], buffer); *count = huffBitPos; return ch; @@ -657,19 +725,22 @@ static int madetable; Huff_Init ============ */ -void Huff_Init( int *huffCounts ) { +void Huff_Init(int *huffCounts) +{ int i, j; if (!huffCounts) huffCounts = q3huffCounts; // build empty tree - Huff_PrepareTree( huffTree ); + Huff_PrepareTree(huffTree); // add all pre-defined qbyte references - for( i=0 ; i<256 ; i++ ) { - for( j=0 ; jdata + offset; inLen = msg->cursize - offset; - if( inLen <= 0 || inLen >= MAX_NQMSGLEN ) { + if (inLen <= 0 || inLen >= MAX_NQMSGLEN) + { return; } outLen = 0; - for( i=0 ; i inLen) { - memmove( data+1, data, inLen ); + memmove(data+1, data, inLen); data[0] = 0x80; //this would have grown the packet. msg->cursize+=1; return; //cap it at only 1 qbyte growth. @@ -756,7 +828,7 @@ void Huff_CompressPacket( sizebuf_t *msg, int offset ) } if (msg->cursize > msg->maxsize) Sys_Error("Compression became too large\n"); - memcpy( data, buffer, outLen ); + memcpy(data, buffer, outLen); } /* @@ -767,7 +839,7 @@ Decompress message using loaded Huffman tree, beginning from specified offset ============ */ -void Huff_DecompressPacket( sizebuf_t *msg, int offset ) +void Huff_DecompressPacket(sizebuf_t *msg, int offset) { qbyte buffer[MAX_NQMSGLEN]; qbyte *data; @@ -780,7 +852,8 @@ void Huff_DecompressPacket( sizebuf_t *msg, int offset ) data = msg->data + offset; inLen = msg->cursize - offset; - if( inLen <= 0 || inLen >= MAX_NQMSGLEN ) { + if (inLen <= 0 || inLen >= MAX_NQMSGLEN) + { return; } @@ -797,7 +870,7 @@ void Huff_DecompressPacket( sizebuf_t *msg, int offset ) } outLen = 0; - for( i=0 ; outLencursize = offset + i; if (msg->cursize > msg->maxsize) Sys_Error("Decompression became too large\n"); - memcpy( msg->data + offset, buffer, i ); + memcpy(msg->data + offset, buffer, i); } #endif + diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 455db7ee9..9198797d1 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -355,7 +355,7 @@ int VectorCompare (vec3_t v1, vec3_t v2) return 1; } -void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc) +void VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc) { vecc[0] = veca[0] + scale*vecb[0]; vecc[1] = veca[1] + scale*vecb[1]; @@ -409,6 +409,23 @@ vec_t Length(vec3_t v) return length; } +float Q_rsqrt(float number) +{ + int i; + float x2, y; + const float threehalfs = 1.5F; + + x2 = number * 0.5F; + y = number; + i = * (int *) &y; // evil floating point bit level hacking + i = 0x5f3759df - (i >> 1); // what the fuck? + y = * (float *) &i; + y = y * (threehalfs - (x2 * y * y)); // 1st iteration +// y = y * (threehalfs - (x2 * y * y)); // 2nd iteration, this can be removed + + return y; +} + float VectorNormalize (vec3_t v) { float length, ilength; @@ -425,7 +442,17 @@ float VectorNormalize (vec3_t v) } return length; +} +void VectorNormalizeFast(vec3_t v) +{ + float ilength; + + ilength = Q_rsqrt(DotProduct(v, v)); + + v[0] *= ilength; + v[1] *= ilength; + v[2] *= ilength; } void VectorInverse (vec3_t v) @@ -861,6 +888,12 @@ void Matrix4_ModelViewMatrix(float *modelview, vec3_t viewangles, vec3_t vieworg Matrix4_Multiply(tempmat, Matrix4_NewTranslation(-vieworg[0], -vieworg[1], -vieworg[2]), modelview); // put Z going up } + +void Matrix4x4_CreateTranslate (matrix4x4_t *out, float x, float y, float z) +{ + memcpy(out, Matrix4_NewTranslation(x, y, z), sizeof(*out)); +} + void Matrix4_ModelViewMatrixFromAxis(float *modelview, vec3_t pn, vec3_t right, vec3_t up, vec3_t vieworg) { float tempmat[16]; diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index 473df1b38..7ef52b9cf 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -97,11 +97,13 @@ int GreatestCommonDivisor (int i1, int i2); fixed16_t Invert24To16 (fixed16_t val); vec_t Length (vec3_t v); void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up); +float Q_rsqrt(float number); //used for crosshair stuff. void Matrix3_Multiply (vec3_t *in1, vec3_t *in2, vec3_t *out); void Matrix4_Identity(float *outm); void Matrix4_Invert_Simple (matrix4x4_t *out, const matrix4x4_t *in1); +void Matrix4x4_CreateTranslate (matrix4x4_t *out, float x, float y, float z); void Matrix4_ModelMatrixFromAxis (float *modelview, vec3_t pn, vec3_t right, vec3_t up, vec3_t vieworg); void Matrix4_ModelViewMatrix (float *modelview, vec3_t viewangles, vec3_t vieworg); void Matrix4_ModelViewMatrixFromAxis (float *modelview, vec3_t pn, vec3_t right, vec3_t up, vec3_t vieworg); @@ -121,9 +123,10 @@ void R_ConcatTransforms (matrix3x4 in1, matrix3x4 in2, matrix3x4 out); void RotatePointAroundVector (vec3_t dst, const vec3_t dir, const vec3_t point, float degrees); int VectorCompare (vec3_t v1, vec3_t v2); void VectorInverse (vec3_t v); -void VectorMA (vec3_t veca, float scale, vec3_t vecb, vec3_t vecc); +void VectorMA (const vec3_t veca, const float scale, const vec3_t vecb, vec3_t vecc); float VectorNormalize (vec3_t v); // returns vector length vec_t VectorNormalize2 (vec3_t v, vec3_t out); +void VectorNormalizeFast(vec3_t v); void VectorScale (vec3_t in, vec_t scale, vec3_t out); void VectorTransform (const vec3_t in1, matrix3x4 in2, vec3_t out); void VectorVectors (vec3_t forward, vec3_t right, vec3_t up); diff --git a/engine/common/net.h b/engine/common/net.h index 52d9e369c..f46af3d0c 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define PORT_ANY -1 -typedef enum {NA_INVALID, NA_LOOPBACK, NA_IP, NA_IPV6, NA_IPX, NA_BROADCAST_IP, NA_BROADCAST_IP6, NA_BROADCAST_IPX} netadrtype_t; +typedef enum {NA_INVALID, NA_LOOPBACK, NA_IP, NA_IPV6, NA_IPX, NA_BROADCAST_IP, NA_BROADCAST_IP6, NA_BROADCAST_IPX, NA_TCP, NA_TCPV6, NA_IRC} netadrtype_t; typedef enum {NS_CLIENT, NS_SERVER} netsrc_t; @@ -35,9 +35,16 @@ typedef struct qbyte ip[4]; qbyte ip6[16]; qbyte ipx[10]; +#ifdef IRCCONNECT + struct { + char user[32]; + char channel[12]; + } irc; +#endif } address; unsigned short port; + unsigned short connum; } netadr_t; struct sockaddr_qstorage @@ -53,10 +60,6 @@ struct sockaddr_qstorage }; -extern netadr_t net_local_sv_ipadr; -extern netadr_t net_local_sv_ip6adr; -extern netadr_t net_local_sv_ipxadr; -extern netadr_t net_local_sv_tcpipadr; extern netadr_t net_local_cl_ipadr; extern netadr_t net_from; // address of who sent the packet extern sizebuf_t net_message; @@ -68,6 +71,7 @@ extern cvar_t hostname; int TCP_OpenStream (netadr_t remoteaddr); //makes things easier +struct ftenet_connections_s; void NET_Init (void); void NET_InitClient (void); void NET_InitServer (void); @@ -76,6 +80,10 @@ void UDP_CloseSocket (int socket); void NET_Shutdown (void); qboolean NET_GetPacket (netsrc_t socket); void NET_SendPacket (netsrc_t socket, int length, void *data, netadr_t to); +int NET_LocalAddressForRemote(struct ftenet_connections_s *collection, netadr_t *remote, netadr_t *local, int idx); +void NET_PrintAddresses(struct ftenet_connections_s *collection); +qboolean NET_AddressSmellsFunny(netadr_t a); +void NET_EnsureRoute(struct ftenet_connections_s *collection, char *routename, char *host); qboolean NET_CompareAdr (netadr_t a, netadr_t b); qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b); diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index aede5426b..b5c632675 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -210,6 +210,14 @@ qboolean Netchan_CanPacket (netchan_t *chan, int rate) return false; } +void Netchan_Block (netchan_t *chan, int bytes, int rate) +{ + if (chan->cleartime < realtime-0.25) //0.25 allows it to be a little bursty. + chan->cleartime = realtime + bytes/(float)rate; + else + chan->cleartime += bytes/(float)rate; +} + /* =============== @@ -389,10 +397,8 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) *(int*)send_buf = BigLong(NETFLAG_DATA | send.cursize); NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); - if (chan->cleartime < realtime) - chan->cleartime = realtime + send.cursize/(float)rate; - else - chan->cleartime += send.cursize/(float)rate; + Netchan_Block(chan, send.cursize, rate); + send.cursize = 0; } //send out the unreliable (if still unsent) @@ -407,11 +413,7 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) *(int*)send_buf = BigLong(NETFLAG_UNRELIABLE | send.cursize); NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); - if (chan->cleartime < realtime) - chan->cleartime = realtime + send.cursize/(float)rate; - else - chan->cleartime += send.cursize/(float)rate; - + Netchan_Block(chan, send.cursize, rate); send.cursize = 0; } return; @@ -447,6 +449,8 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) // write the packet header send.data = send_buf; send.maxsize = MAX_QWMSGLEN + PACKET_HEADER; //dmw: wasn't quite true. + if (chan->sock == NS_CLIENT) + send.maxsize += 2; send.cursize = 0; w1 = chan->outgoing_sequence | (send_reliable<<31); @@ -497,10 +501,7 @@ void Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate) NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address); } - if (chan->cleartime < realtime) - chan->cleartime = realtime + send.cursize/(float)rate; - else - chan->cleartime += send.cursize/(float)rate; + Netchan_Block(chan, send.cursize, rate); #ifdef SERVERONLY if (ServerPaused()) chan->cleartime = realtime; diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index b01f576c3..cc8569584 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -23,13 +23,8 @@ struct sockaddr; #include "quakedef.h" #include "netinc.h" -netadr_t net_local_cl_ipadr; -netadr_t net_local_cl_ip6adr; -netadr_t net_local_cl_ipxadr; -netadr_t net_local_sv_ipadr; -netadr_t net_local_sv_ip6adr; -netadr_t net_local_sv_ipxadr; -netadr_t net_local_sv_tcpipadr; +#pragma message("these two are never set. A NET_ReplySource function that returns the address a reply would originate from would be sufficient. Note that INADDR_ANY can be multiple however, so these are just a hint.") +netadr_t net_local_cl_ipadr; //still used to match local ui requests, and to generate ip reports for q3 servers. netadr_t net_from; sizebuf_t net_message; @@ -78,9 +73,10 @@ extern cvar_t sv_port_ipx; #endif #ifdef TCPCONNECT extern cvar_t sv_port_tcp; +extern cvar_t sv_port_tcp6; #endif -extern cvar_t sv_public, sv_listen_qw, sv_listen_nq, sv_listen_dp; +extern cvar_t sv_public, sv_listen_qw, sv_listen_nq, sv_listen_dp, sv_listen_q3; static qboolean allowconnects = false; @@ -162,6 +158,8 @@ int NetadrToSockadr (netadr_t *a, struct sockaddr_qstorage *s) void SockadrToNetadr (struct sockaddr_qstorage *s, netadr_t *a) { + a->connum = 0; + switch (((struct sockaddr*)s)->sa_family) { case AF_INET: @@ -225,6 +223,15 @@ qboolean NET_CompareAdr (netadr_t a, netadr_t b) return false; } +#ifdef IRCCONNECT + if (a.type == NA_IRC) + { + if (!strcmp(a.address.irc.user, b.address.irc.user)) + return true; + return false; + } +#endif + Sys_Error("NET_CompareAdr: Bad address type"); return false; } @@ -264,6 +271,14 @@ qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b) return true; return false; } +#ifdef IRCCONNECT + if (a.type == NA_IRC) + { + if (!strcmp(a.address.irc.user, b.address.irc.user)) + return true; + return false; + } +#endif Sys_Error("NET_CompareBaseAdr: Bad address type"); return false; @@ -325,6 +340,15 @@ char *NET_AdrToString (char *s, int len, netadr_t a) switch(a.type) { +#ifdef TCPCONNECT + case NA_TCP: + if (len < 7) + return "?"; + snprintf (s, len, "tcp://"); + s += 6; + len -= 6; + //fallthrough +#endif case NA_BROADCAST_IP: case NA_IP: snprintf (s, len, "%i.%i.%i.%i:%i", @@ -334,6 +358,15 @@ char *NET_AdrToString (char *s, int len, netadr_t a) a.address.ip[3], ntohs(a.port)); break; +#ifdef TCPCONNECT + case NA_TCPV6: + if (len < 7) + return "?"; + snprintf (s, len, "tcp://"); + s += 6; + len -= 6; + //fallthrough +#endif #ifdef IPPROTO_IPV6 case NA_BROADCAST_IP6: case NA_IPV6: @@ -402,6 +435,16 @@ char *NET_AdrToString (char *s, int len, netadr_t a) case NA_LOOPBACK: snprintf (s, len, "LocalHost"); break; + +#ifdef IRCCONNECT + case NA_IRC: + if (*a.address.irc.channel) + snprintf (s, len, "irc://%s@", a.address.irc.user, a.address.irc.channel); + else + snprintf (s, len, "irc://%s", a.address.irc.user); + break; +#endif + default: snprintf (s, len, "invalid netadr_t type"); // Sys_Error("NET_AdrToString: Bad netadr_t type"); @@ -486,6 +529,12 @@ char *NET_BaseAdrToString (char *s, int len, netadr_t a) case NA_LOOPBACK: snprintf (s, len, "LocalHost"); break; + +#ifdef IRCCONNECT + case NA_IRC: + snprintf (s, len, "irc://%s", a.address.irc.user); + break; +#endif default: Sys_Error("NET_BaseAdrToString: Bad netadr_t type"); } @@ -566,21 +615,15 @@ qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr) error = EAI_NONAME; else { + *port = 0; error = pgetaddrinfo(s+1, port+2, &udp6hint, &addrinfo); + *port = ']'; } } else { - port = s + strlen(s); - while(port >= s) - { - if (*port == ':') - break; - port--; - } + port = strrchr(s, ':'); - if (port == s) - port = NULL; if (port) { len = port - s; @@ -609,7 +652,7 @@ qboolean NET_StringToSockaddr (char *s, struct sockaddr_qstorage *sadr) break; //first one should be best... //fallthrough case AF_INET: - memcpy(sadr, addrinfo->ai_addr, addrinfo->ai_addrlen); + memcpy(sadr, pos->ai_addr, pos->ai_addrlen); if (pos->ai_family == AF_INET) goto dblbreak; //don't try finding any more, this is quake, they probably prefer ip4... break; @@ -658,10 +701,62 @@ dblbreak: #undef DO +/* +accepts anything that NET_StringToSockaddr accepts plus certain url schemes +including: tcp, irc +*/ qboolean NET_StringToAdr (char *s, netadr_t *a) { struct sockaddr_qstorage sadr; +#ifdef TCPCONNECT + if (!strncmp (s, "tcp://", 6)) + { + //make sure that the rest of the address is a valid ip address (4 or 6) + + if (!NET_StringToSockaddr (s+6, &sadr)) + return false; + + SockadrToNetadr (&sadr, a); + + if (a->type == NA_IP) + { + a->type = NA_TCP; + return true; + } + if (a->type == NA_IPV6) + { + a->type = NA_TCPV6; + return true; + } + return false; + } +#endif +#ifdef IRCCONNECT + if (!strncmp (s, "irc://", 6)) + { + char *at; + memset (a, 0, sizeof(*a)); + a->type = NA_IRC; + + s+=6; + at = strchr(s, '@'); + if (at) + { + if (at-s+1 >= sizeof(a->address.irc.user)) + return false; + Q_strncpyz(a->address.irc.user, s, at-s+1); + Q_strncpyz(a->address.irc.channel, at+1, sizeof(a->address.irc.channel)); + } + else + { + //just a user. + Q_strncpyz(a->address.irc.user, s, sizeof(a->address.irc.user)); + } + return true; + } +#endif + if (!strcmp (s, "internalserver")) { memset (a, 0, sizeof(*a)); @@ -964,6 +1059,14 @@ qboolean NET_CompareAdrMasked(netadr_t a, netadr_t b, netadr_t mask) } break; #endif + +#ifdef IRCCONNECT + case NA_IRC: + //masks are not supported, match explicitly + if (strcmp(a.address.irc.user, b.address.irc.user)) + return false; + break; +#endif default: return false; // invalid protocol } @@ -1183,511 +1286,283 @@ void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to) } //============================================================================= -#ifndef CLIENTONLY -void SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue) -{ -#ifdef TCPCONNECT - if (!allowconnects) - return; +#define FTENET_ADDRTYPES 2 +typedef struct ftenet_generic_connection_s { + char *name; - if (var->value) - { - if (svs.sockettcp == INVALID_SOCKET) - { - svs.sockettcp = TCP_OpenListenSocket(var->value); - if (svs.sockettcp != INVALID_SOCKET) - NET_GetLocalAddress (svs.sockettcp, &net_local_sv_tcpipadr); - else - Con_Printf("Failed to open TCP port %i\n", (int)var->value); - } - } - else - { - if (svs.sockettcp != INVALID_SOCKET) - { - closesocket(svs.sockettcp); - svs.sockettcp = INVALID_SOCKET; - } - } -#endif + int (*GetLocalAddress)(struct ftenet_generic_connection_s *con, netadr_t *local, int adridx); + qboolean (*ChangeLocalAddress)(struct ftenet_generic_connection_s *con, char *newaddress); + qboolean (*GetPacket)(struct ftenet_generic_connection_s *con); + qboolean (*SendPacket)(struct ftenet_generic_connection_s *con, int length, void *data, netadr_t to); + void (*Close)(struct ftenet_generic_connection_s *con); + + netadrtype_t addrtype[FTENET_ADDRTYPES]; + qboolean islisten; + int thesocket; +} ftenet_generic_connection_t; + +#define MAX_CONNECTIONS 8 +typedef struct ftenet_connections_s { + qboolean islisten; + ftenet_generic_connection_t *conn[MAX_CONNECTIONS]; +} ftenet_connections_t; + +ftenet_connections_t *FTENET_CreateCollection(qboolean listen) +{ + ftenet_connections_t *col; + col = Z_Malloc(sizeof(*col)); + col->islisten = listen; + return col; } -void SV_Port_Callback(struct cvar_s *var, char *oldvalue) +qboolean FTENET_AddToCollection(ftenet_connections_t *col, char *name, char *address, ftenet_generic_connection_t *(*establish)(qboolean isserver, char *address)) { - if (!allowconnects) - return; - - if (var->value) - { - if (svs.socketip == INVALID_SOCKET) - { - svs.socketip = UDP_OpenSocket (var->value, false); - if (svs.socketip != INVALID_SOCKET) - NET_GetLocalAddress (svs.socketip, &net_local_sv_ipadr); - } - } - else - { - if (svs.socketip != INVALID_SOCKET) - { - UDP_CloseSocket(svs.socketip); - svs.socketip = INVALID_SOCKET; - } - } -} - -void SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue) -{ -#ifdef IPPROTO_IPV6 - if (!allowconnects) - return; - - if (var->value) - { - if (svs.socketip6 == INVALID_SOCKET) - { - svs.socketip6 = UDP6_OpenSocket (var->value, false); - if (svs.socketip6 != INVALID_SOCKET) - NET_GetLocalAddress (svs.socketip6, &net_local_sv_ip6adr); - } - } - else - { - if (svs.socketip6 != INVALID_SOCKET) - { - UDP_CloseSocket(svs.socketip6); - svs.socketip6 = INVALID_SOCKET; - } - } -#endif -} - -void SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue) -{ -#ifdef USEIPX - if (!allowconnects) - return; - - if (var->value) - { - if (svs.socketipx == INVALID_SOCKET) - { - svs.socketipx = IPX_OpenSocket (var->value, false); - if (svs.socketipx != INVALID_SOCKET) - NET_GetLocalAddress (svs.socketipx, &net_local_sv_ipxadr); - } - } - else - { - if (svs.socketipx != INVALID_SOCKET) - { - IPX_CloseSocket(svs.socketipx); - svs.socketipx = INVALID_SOCKET; - } - } -#endif -} -#endif - -qboolean NET_GetPacket (netsrc_t netsrc) -{ - int ret; - struct sockaddr_qstorage from; - int fromlen; int i; - int socket; - int err; - char adr[MAX_ADR_SIZE]; + if (!col) + return false; - if (NET_GetLoopPacket(netsrc, &net_from, &net_message)) + if (name) + { + for (i = 0; i < MAX_CONNECTIONS; i++) + { + if (col->conn[i]) + if (col->conn[i]->name && !strcmp(col->conn[i]->name, name)) + { + if (address && *address) + if (col->conn[i]->ChangeLocalAddress) + { + if (col->conn[i]->ChangeLocalAddress(col->conn[i], address)) + return true; + } + + col->conn[i]->Close(col->conn[i]); + col->conn[i] = NULL; + break; + } + } + } + + if (!address || !*address) + { + return true; //must have at least a port. + } + + for (i = 0; i < MAX_CONNECTIONS; i++) + { + if (!col->conn[i]) + { + col->conn[i] = establish(col->islisten, address); + if (!col->conn[i]) + return false; + col->conn[i]->name = name; + return true; + } + } + return false; +} + +void FTENET_CloseCollection(ftenet_connections_t *col) +{ + Z_Free(col); +} + +void FTENET_Generic_Close(ftenet_generic_connection_t *con) +{ + if (con->thesocket != INVALID_SOCKET) + closesocket(con->thesocket); + Z_Free(con); +} + +#if !defined(CLIENTONLY) && !defined(SERVERONLY) + +int FTENET_Loop_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *out, int adrnum) +{ + if (adrnum==0) + { + out->type = NA_LOOPBACK; + out->port = con->islisten+1; + } + return 1; +} + +qboolean FTENET_Loop_GetPacket(ftenet_generic_connection_t *con) +{ + return NET_GetLoopPacket(con->islisten, &net_from, &net_message); +} + +qboolean FTENET_Loop_SendPacket(ftenet_generic_connection_t *con, int length, void *data, netadr_t to) +{ + if (to.type == NA_LOOPBACK) + { + NET_SendLoopPacket(con->islisten, length, data, to); return true; - - for (i = 0; i < 3; i++) - { - if (netsrc == NS_SERVER) - { -#ifdef CLIENTONLY - Sys_Error("NET_GetPacket: Bad netsrc"); - socket = 0; -#else - if (i == 0) - socket = svs.socketip; - else if (i == 1) - socket = svs.socketip6; - else - socket = svs.socketipx; -#endif - } - else - { -#ifdef SERVERONLY - Sys_Error("NET_GetPacket: Bad netsrc"); - socket = 0; -#else - if (i == 0) - socket = cls.socketip; - else if (i == 1) - socket = cls.socketip6; - else - socket = cls.socketipx; -#endif - } - if (socket == INVALID_SOCKET) - continue; - - fromlen = sizeof(from); - ret = recvfrom (socket, (char *)net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr*)&from, &fromlen); - - if (ret == -1) - { - err = qerrno; - - if (err == EWOULDBLOCK) - continue; - if (err == EMSGSIZE) - { - SockadrToNetadr (&from, &net_from); - Con_TPrintf (TL_OVERSIZEPACKETFROM, - NET_AdrToString (adr, sizeof(adr), net_from)); - continue; - } - if (err == ECONNABORTED || err == ECONNRESET) - { - Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. -#ifndef SERVERONLY - if (cls.state != ca_disconnected && netsrc == NS_CLIENT) - { - if (cls.lastarbiatarypackettime+5 < Sys_DoubleTime()) //too many mvdsv - Cbuf_AddText("disconnect\nreconnect\n", RESTRICT_LOCAL); //retry connecting. - else - Con_Printf("Packet was not delivered - server might be badly configured\n"); - break; - } -#endif - continue; - } - - - Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err)); - continue; - } - SockadrToNetadr (&from, &net_from); - - net_message.packing = SZ_RAWBYTES; - net_message.currentbit = 0; - net_message.cursize = ret; - if (net_message.cursize == sizeof(net_message_buffer) ) - { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); - continue; - } - - return ret; } -#ifdef TCPCONNECT -#ifndef SERVERONLY - if (netsrc == NS_CLIENT) - { - if (cls.sockettcp != INVALID_SOCKET) - {//client receiving only via tcp - - ret = recv(cls.sockettcp, cls.tcpinbuffer+cls.tcpinlen, sizeof(cls.tcpinbuffer)-cls.tcpinlen, 0); - if (ret == -1) - { - err = qerrno; - - if (err == EWOULDBLOCK) - ret = 0; - else - { - if (err == ECONNABORTED || err == ECONNRESET) - { - closesocket(cls.sockettcp); - cls.sockettcp = INVALID_SOCKET; - Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. - - if (cls.state != ca_disconnected) - { - if (cls.lastarbiatarypackettime+5 < Sys_DoubleTime()) //too many mvdsv - Cbuf_AddText("disconnect\nreconnect\n", RESTRICT_LOCAL); //retry connecting. - else - Con_Printf("Packet was not delivered - server might be badly configured\n"); - return false; - } - return false; - } - - - closesocket(cls.sockettcp); - cls.sockettcp = INVALID_SOCKET; - Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err)); - return false; - } - } - cls.tcpinlen += ret; - - if (cls.tcpinlen < 2) - return false; - - net_message.cursize = BigShort(*(short*)cls.tcpinbuffer); - if (net_message.cursize >= sizeof(net_message_buffer) ) - { - closesocket(cls.sockettcp); - cls.sockettcp = INVALID_SOCKET; - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); - return false; - } - if (net_message.cursize+2 > cls.tcpinlen) - { //not enough buffered to read a packet out of it. - return false; - } - - memcpy(net_message_buffer, cls.tcpinbuffer+2, net_message.cursize); - memmove(cls.tcpinbuffer, cls.tcpinbuffer+net_message.cursize+2, cls.tcpinlen - (net_message.cursize+2)); - cls.tcpinlen -= net_message.cursize+2; - - net_message.packing = SZ_RAWBYTES; - net_message.currentbit = 0; - net_from = cls.sockettcpdest; - - return true; - } - } -#endif -#ifndef CLIENTONLY - if (netsrc == NS_SERVER) - { - float timeval = Sys_DoubleTime(); - svtcpstream_t *st; - st = svs.tcpstreams; - - while (svs.tcpstreams && svs.tcpstreams->socketnum == INVALID_SOCKET) - { - st = svs.tcpstreams; - svs.tcpstreams = svs.tcpstreams->next; - BZ_Free(st); - } - - for (st = svs.tcpstreams; st; st = st->next) - {//client receiving only via tcp - - while (st->next && st->next->socketnum == INVALID_SOCKET) - { - svtcpstream_t *temp; - temp = st->next; - st->next = st->next->next; - BZ_Free(temp); - } - -//due to the above checks about invalid sockets, the socket is always open for st below. - - if (st->timeouttime < timeval) - goto closesvstream; - - ret = recv(st->socketnum, st->inbuffer+st->inlen, sizeof(st->inbuffer)-st->inlen, 0); - if (ret == 0) - goto closesvstream; - else if (ret == -1) - { - err = qerrno; - - if (err == EWOULDBLOCK) - ret = 0; - else - { - if (err == ECONNABORTED || err == ECONNRESET) - { - Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. - } - else - Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err)); - - closesvstream: - closesocket(st->socketnum); - st->socketnum = INVALID_SOCKET; - continue; - } - } - st->inlen += ret; - - if (st->waitingforprotocolconfirmation) - { - if (st->inlen < 6) - continue; - - if (strncmp(st->inbuffer, "qizmo\n", 6)) - { - Con_Printf ("Unknown TCP client\n"); - goto closesvstream; - } - - memmove(st->inbuffer, st->inbuffer+6, st->inlen - (6)); - st->inlen -= 6; - st->waitingforprotocolconfirmation = false; - } - - if (st->inlen < 2) - continue; - - net_message.cursize = BigShort(*(short*)st->inbuffer); - if (net_message.cursize >= sizeof(net_message_buffer) ) - { - Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); - goto closesvstream; - } - if (net_message.cursize+2 > st->inlen) - { //not enough buffered to read a packet out of it. - continue; - } - - memcpy(net_message_buffer, st->inbuffer+2, net_message.cursize); - memmove(st->inbuffer, st->inbuffer+net_message.cursize+2, st->inlen - (net_message.cursize+2)); - st->inlen -= net_message.cursize+2; - - net_message.packing = SZ_RAWBYTES; - net_message.currentbit = 0; - net_from = st->remoteaddr; - - return true; - } - - if (svs.sockettcp != INVALID_SOCKET) - { - int newsock; - newsock = accept(svs.sockettcp, (struct sockaddr*)&from, &fromlen); - if (newsock != INVALID_SOCKET) - { - int _true = true; - ioctlsocket(newsock, FIONBIO, &_true); - setsockopt(newsock, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); - - - - - st = Z_Malloc(sizeof(svtcpstream_t)); - st->waitingforprotocolconfirmation = true; - st->next = svs.tcpstreams; - svs.tcpstreams = st; - st->socketnum = newsock; - st->inlen = 0; - SockadrToNetadr(&from, &st->remoteaddr); - send(newsock, "qizmo\n", 6, 0); - - st->timeouttime = timeval + 30; - } - } - } -#endif -#endif - - return false; } -//============================================================================= - -void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) +ftenet_generic_connection_t *FTENET_Loop_EstablishConnection(qboolean isserver, char *address) { - int ret; - struct sockaddr_qstorage addr; - int socket; - int size; - - if (to.type == NA_LOOPBACK) + ftenet_generic_connection_t *newcon; + newcon = Z_Malloc(sizeof(*newcon)); + if (newcon) { -// if (Cvar_Get("drop", "0", 0, "network debugging")->value) -// if ((rand()&15)==15) //simulate PL -// return; - NET_SendLoopPacket(netsrc, length, data, to); - return; + newcon->name = "Loopback"; + newcon->GetLocalAddress = FTENET_Loop_GetLocalAddress; + newcon->GetPacket = FTENET_Loop_GetPacket; + newcon->SendPacket = FTENET_Loop_SendPacket; + newcon->Close = FTENET_Generic_Close; + + newcon->islisten = isserver; + newcon->addrtype[0] = NA_LOOPBACK; + newcon->addrtype[1] = NA_INVALID; + + newcon->thesocket = INVALID_SOCKET; } + return newcon; +} +#endif - if (netsrc == NS_SERVER) +int FTENET_Generic_GetLocalAddress(ftenet_generic_connection_t *con, netadr_t *out, int count) +{ + struct sockaddr_qstorage from; + int fromsize = sizeof(from); + netadr_t adr; + char adrs[MAX_ADR_SIZE]; + int b; + struct hostent *h; + int idx = 0; + + if (getsockname (con->thesocket, (struct sockaddr*)&from, &fromsize) != -1) { -#ifdef CLIENTONLY - Sys_Error("NET_SendPacket: bad netsrc"); - socket = 0; -#else + memset(&adr, 0, sizeof(adr)); + SockadrToNetadr(&from, &adr); -#ifdef TCPCONNECT - svtcpstream_t *st; - for (st = svs.tcpstreams; st; st = st->next) + for (b = 0; b < sizeof(adr.address); b++) + if (((unsigned char*)&adr.address)[b] != 0) + break; + if (b == sizeof(adr.address)) { - if (st->socketnum == INVALID_SOCKET) - continue; - - if (NET_CompareAdr(to, st->remoteaddr)) + gethostname(adrs, sizeof(adrs)); + h = gethostbyname(adrs); + b = 0; + if(h && h->h_addrtype == AF_INET) { - unsigned short slen = BigShort((unsigned short)length); - send(st->socketnum, (char*)&slen, sizeof(slen), 0); - send(st->socketnum, data, length, 0); + for (b = 0; h->h_addr_list[b]; b++) + { + memcpy(&((struct sockaddr_in*)&from)->sin_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in*)&from)->sin_addr)); + SockadrToNetadr(&from, &adr); + if (idx++ == count) + *out = adr; + } + } + else if(h && h->h_addrtype == AF_INET6) + { + for (b = 0; h->h_addr_list[b]; b++) + { + memcpy(&((struct sockaddr_in6*)&from)->sin6_addr, h->h_addr_list[b], sizeof(((struct sockaddr_in6*)&from)->sin6_addr)); + SockadrToNetadr(&from, &adr); + if (idx++ == count) + *out = adr; + } + } - st->timeouttime = Sys_DoubleTime() + 20; - - return; + if (b == 0) + { + if (idx++ == count) + *out = adr; } } -#endif - - -#ifdef USEIPX - if (to.type == NA_BROADCAST_IPX || to.type == NA_IPX) - socket = svs.socketipx; else -#endif -#ifdef IPPROTO_IPV6 - if (to.type == NA_IPV6) - socket = svs.socketip6; - else -#endif - socket = svs.socketip; -#endif - } - else - { -#ifdef SERVERONLY - Sys_Error("NET_SendPacket: bad netsrc"); - socket = 0; -#else - -#ifdef TCPCONNECT - if (cls.sockettcp != -1) { - if (NET_CompareAdr(to, cls.sockettcpdest)) - { //this goes to the server - //so send it via tcp - unsigned short slen = BigShort((unsigned short)length); - send(cls.sockettcp, (char*)&slen, sizeof(slen), 0); - send(cls.sockettcp, data, length, 0); - - return; - } + if (idx++ == count) + *out = adr; } -#endif - - - -#ifdef USEIPX - if (to.type == NA_BROADCAST_IPX || to.type == NA_IPX) - socket = cls.socketipx; - else -#endif -#ifdef IPPROTO_IPV6 - if (to.type == NA_BROADCAST_IP6 || to.type == NA_IPV6) - socket = cls.socketip6; - else -#endif - socket = cls.socketip; -#endif } + return idx; +} + +qboolean FTENET_Generic_GetPacket(ftenet_generic_connection_t *con) +{ + struct sockaddr_qstorage from; + int fromlen; + int ret; + int err; + char adr[MAX_ADR_SIZE]; + + if (con->thesocket == INVALID_SOCKET) + return false; + + fromlen = sizeof(from); + ret = recvfrom (con->thesocket, (char *)net_message_buffer, sizeof(net_message_buffer), 0, (struct sockaddr*)&from, &fromlen); + + if (ret == -1) + { + err = qerrno; + + if (err == EWOULDBLOCK) + return false; + if (err == EMSGSIZE) + { + SockadrToNetadr (&from, &net_from); + Con_TPrintf (TL_OVERSIZEPACKETFROM, + NET_AdrToString (adr, sizeof(adr), net_from)); + return false; + } + if (err == ECONNABORTED || err == ECONNRESET) + { + Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. +#ifndef SERVERONLY + if (cls.state != ca_disconnected && !con->islisten) + { + if (cls.lastarbiatarypackettime+5 < Sys_DoubleTime()) //too many mvdsv + Cbuf_AddText("disconnect\nreconnect\n", RESTRICT_LOCAL); //retry connecting. + else + Con_Printf("Packet was not delivered - server might be badly configured\n"); + return false; + } +#endif + return false; + } + + + Con_Printf ("NET_GetPacket: Error (%i): %s\n", err, strerror(err)); + return false; + } + SockadrToNetadr (&from, &net_from); + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + net_message.cursize = ret; + if (net_message.cursize == sizeof(net_message_buffer) ) + { + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + return false; + } + + return true; +} + +qboolean FTENET_Generic_SendPacket(ftenet_generic_connection_t *con, int length, void *data, netadr_t to) +{ + struct sockaddr_qstorage addr; + int size; + int ret; + + for (size = 0; size < FTENET_ADDRTYPES; size++) + if (to.type == con->addrtype[size]) + break; + if (size == FTENET_ADDRTYPES) + return false; + + NetadrToSockadr (&to, &addr); switch(to.type) { default: - size = 0; //should cause an error. :) + Con_Printf("Bad address type\n"); break; #ifdef USEIPX //who uses ipx nowadays anyway? case NA_BROADCAST_IPX: @@ -1707,15 +1582,15 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) #endif } - ret = sendto (socket, data, length, 0, (struct sockaddr*)&addr, size ); + ret = sendto (con->thesocket, data, length, 0, (struct sockaddr*)&addr, size ); if (ret == -1) { // wouldblock is silent if (qerrno == EWOULDBLOCK) - return; + return true; if (qerrno == ECONNREFUSED) - return; + return true; #ifndef SERVERONLY if (qerrno == EADDRNOTAVAIL) @@ -1724,6 +1599,1164 @@ void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) #endif Con_TPrintf (TL_NETSENDERROR, qerrno); } + return true; +} + +qboolean NET_PortToAdr (int adrfamily, char *s, netadr_t *a) +{ + char *e; + int port; + port = strtoul(s, &e, 10); + if (*e) + return NET_StringToAdr(s, a); + else if (port) + { + memset(a, 0, sizeof(*a)); + a->port = htons((unsigned short)port); + if (adrfamily == AF_INET) + a->type = NA_IP; + else if (adrfamily == AF_INET6) + a->type = NA_IPV6; + else if (adrfamily == AF_IPX) + a->type = NA_IPX; + else + { + a->type = NA_INVALID; + return false; + } + return true; + } + return false; +} + +ftenet_generic_connection_t *FTENET_Generic_EstablishConnection(int adrfamily, int protocol, qboolean isserver, char *address) +{ + //this is written to support either ipv4 or ipv6, depending on the remote addr. + ftenet_generic_connection_t *newcon; + + unsigned long _true = true; + int newsocket; + int temp; + netadr_t adr; + struct sockaddr_qstorage qs; + int family; + int port; + int bindtries; + + + if (!NET_PortToAdr(adrfamily, address, &adr)) + { + Con_Printf("unable to resolve local address %s\n", address); + return NULL; //couldn't resolve the name + } + temp = NetadrToSockadr(&adr, &qs); + family = ((struct sockaddr_in*)&qs)->sin_family; + + if ((newsocket = socket (family, SOCK_DGRAM, protocol)) == INVALID_SOCKET) + { + return NULL; + } + + //try and find an unused port. + port = ntohs(((struct sockaddr_in*)&qs)->sin_port); + for (bindtries = 100; bindtries > 0; bindtries--) + { + ((struct sockaddr_in*)&qs)->sin_port = htons((unsigned short)(port+100-bindtries)); + if ((bind(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET)) + { + continue; + } + break; + } + if (!bindtries) + { + SockadrToNetadr(&qs, &adr); + //mneh, reuse qs. + NET_AdrToString((char*)&qs, sizeof(qs), adr); + Con_Printf("Unable to listen at %s\n", (char*)&qs); + closesocket(newsocket); + return NULL; + } + + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); + + newcon = Z_Malloc(sizeof(*newcon)); + if (newcon) + { + newcon->name = "Generic"; + newcon->GetLocalAddress = FTENET_Generic_GetLocalAddress; + newcon->GetPacket = FTENET_Generic_GetPacket; + newcon->SendPacket = FTENET_Generic_SendPacket; + newcon->Close = FTENET_Generic_Close; + + newcon->islisten = isserver; + newcon->addrtype[0] = adr.type; + newcon->addrtype[1] = NA_INVALID; + + newcon->thesocket = newsocket; + + return newcon; + } + else + { + closesocket(newsocket); + return NULL; + } +} + +ftenet_generic_connection_t *FTENET_UDP6_EstablishConnection(qboolean isserver, char *address) +{ + return FTENET_Generic_EstablishConnection(AF_INET6, IPPROTO_UDP, isserver, address); +} +ftenet_generic_connection_t *FTENET_UDP4_EstablishConnection(qboolean isserver, char *address) +{ + return FTENET_Generic_EstablishConnection(AF_INET, IPPROTO_UDP, isserver, address); +} +ftenet_generic_connection_t *FTENET_IPX_EstablishConnection(qboolean isserver, char *address) +{ + return FTENET_Generic_EstablishConnection(AF_IPX, NSPROTO_IPX, isserver, address); +} + +#ifdef TCPCONNECT +typedef struct ftenet_tcpconnect_stream_s { + int socketnum; + int inlen; + qboolean waitingforprotocolconfirmation; + char inbuffer[1500]; + float timeouttime; + netadr_t remoteaddr; + struct ftenet_tcpconnect_stream_s *next; +} ftenet_tcpconnect_stream_t; + +typedef struct { + ftenet_generic_connection_t generic; + + int active; + ftenet_tcpconnect_stream_t *tcpstreams; +} ftenet_tcpconnect_connection_t; + +qboolean FTENET_TCPConnect_GetPacket(ftenet_generic_connection_t *gcon) +{ + ftenet_tcpconnect_connection_t *con = (ftenet_tcpconnect_connection_t*)gcon; + int ret; + int err; + char adr[MAX_ADR_SIZE]; + struct sockaddr_qstorage from; + int fromlen; + + float timeval = Sys_DoubleTime(); + ftenet_tcpconnect_stream_t *st; + st = con->tcpstreams; + + //remove any stale ones + while (con->tcpstreams && con->tcpstreams->socketnum == INVALID_SOCKET) + { + st = con->tcpstreams; + con->tcpstreams = con->tcpstreams->next; + BZ_Free(st); + } + + for (st = con->tcpstreams; st; st = st->next) + {//client receiving only via tcp + + while (st->next && st->next->socketnum == INVALID_SOCKET) + { + ftenet_tcpconnect_stream_t *temp; + temp = st->next; + st->next = st->next->next; + BZ_Free(temp); + con->active--; + } + +//due to the above checks about invalid sockets, the socket is always open for st below. + + if (st->timeouttime < timeval) + goto closesvstream; + + ret = recv(st->socketnum, st->inbuffer+st->inlen, sizeof(st->inbuffer)-st->inlen, 0); + if (ret == 0) + goto closesvstream; + else if (ret == -1) + { + err = qerrno; + + if (err == EWOULDBLOCK) + ret = 0; + else + { + if (err == ECONNABORTED || err == ECONNRESET) + { + Con_TPrintf (TL_CONNECTIONLOSTORABORTED); //server died/connection lost. + } + else + Con_Printf ("TCPConnect_GetPacket: Error (%i): %s\n", err, strerror(err)); + +closesvstream: + closesocket(st->socketnum); + st->socketnum = INVALID_SOCKET; + continue; + } + } + st->inlen += ret; + + if (st->waitingforprotocolconfirmation) + { + if (st->inlen < 6) + continue; + + if (strncmp(st->inbuffer, "qizmo\n", 6)) + { + Con_Printf ("Unknown TCP client\n"); + goto closesvstream; + } + + memmove(st->inbuffer, st->inbuffer+6, st->inlen - (6)); + st->inlen -= 6; + st->waitingforprotocolconfirmation = false; + } + + if (st->inlen < 2) + continue; + + net_message.cursize = BigShort(*(short*)st->inbuffer); + if (net_message.cursize >= sizeof(net_message_buffer) ) + { + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + goto closesvstream; + } + if (net_message.cursize+2 > st->inlen) + { //not enough buffered to read a packet out of it. + continue; + } + + memcpy(net_message_buffer, st->inbuffer+2, net_message.cursize); + memmove(st->inbuffer, st->inbuffer+net_message.cursize+2, st->inlen - (net_message.cursize+2)); + st->inlen -= net_message.cursize+2; + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + net_from = st->remoteaddr; + + return true; + } + + if (con->generic.thesocket != INVALID_SOCKET && con->active < 256) + { + int newsock; + newsock = accept(con->generic.thesocket, (struct sockaddr*)&from, &fromlen); + if (newsock != INVALID_SOCKET) + { + int _true = true; + ioctlsocket(newsock, FIONBIO, &_true); + setsockopt(newsock, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); + + con->active++; + st = Z_Malloc(sizeof(*con->tcpstreams)); + st->waitingforprotocolconfirmation = true; + st->next = con->tcpstreams; + con->tcpstreams = st; + st->socketnum = newsock; + st->inlen = 0; + SockadrToNetadr(&from, &st->remoteaddr); + + //send the qizmo greeting. + send(newsock, "qizmo\n", 6, 0); + + st->timeouttime = timeval + 30; + } + } + return false; +} + +qboolean FTENET_TCPConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t to) +{ + ftenet_tcpconnect_connection_t *con = (ftenet_tcpconnect_connection_t*)gcon; + ftenet_tcpconnect_stream_t *st; + + for (st = con->tcpstreams; st; st = st->next) + { + if (st->socketnum == INVALID_SOCKET) + continue; + + if (NET_CompareAdr(to, st->remoteaddr)) + { + unsigned short slen = BigShort((unsigned short)length); + send(st->socketnum, (char*)&slen, sizeof(slen), 0); + send(st->socketnum, data, length, 0); + + st->timeouttime = Sys_DoubleTime() + 20; + + return true; + } + } + return false; +} + +void FTENET_TCPConnect_Close(ftenet_generic_connection_t *gcon) +{ + ftenet_tcpconnect_connection_t *con = (ftenet_tcpconnect_connection_t*)gcon; + ftenet_tcpconnect_stream_t *st; + + st = con->tcpstreams; + while (con->tcpstreams) + { + st = con->tcpstreams; + con->tcpstreams = st->next; + + if (st->socketnum != INVALID_SOCKET) + closesocket(st->socketnum); + + BZ_Free(st); + } + + FTENET_Generic_Close(gcon); +} + +ftenet_generic_connection_t *FTENET_TCPConnect_EstablishConnection(int affamily, qboolean isserver, char *address) +{ + //this is written to support either ipv4 or ipv6, depending on the remote addr. + ftenet_tcpconnect_connection_t *newcon; + + unsigned long _true = true; + int newsocket; + int temp; + netadr_t adr; + struct sockaddr_qstorage qs; + int family; + + if (isserver) + { + if (!NET_PortToAdr(affamily, address, &adr)) + return NULL; //couldn't resolve the name + temp = NetadrToSockadr(&adr, &qs); + family = ((struct sockaddr_in*)&qs)->sin_family; + + if ((newsocket = socket (family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) + { + Con_Printf("operating system doesn't support that\n"); + return NULL; + } + + if ((bind(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET) || + (listen(newsocket, 2) == INVALID_SOCKET)) + { + SockadrToNetadr(&qs, &adr); + //mneh, reuse qs. + NET_AdrToString((char*)&qs, sizeof(qs), adr); + Con_Printf("Unable to listen at %s\n", (char*)&qs); + closesocket(newsocket); + return NULL; + } + } + else + { + if (!NET_StringToAdr(address, &adr)) + return NULL; //couldn't resolve the name + + temp = NetadrToSockadr(&adr, &qs); + family = ((struct sockaddr_in*)&qs)->sin_family; + + if ((newsocket = socket (family, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) + return NULL; + + if (connect(newsocket, (struct sockaddr *)&qs, temp) == INVALID_SOCKET) + { + closesocket(newsocket); + return NULL; + } + } + + if (ioctlsocket (newsocket, FIONBIO, &_true) == -1) + Sys_Error ("UDP_OpenSocket: ioctl FIONBIO: %s", strerror(qerrno)); + + //this isn't fatal + setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (char *)&_true, sizeof(_true)); + + newcon = Z_Malloc(sizeof(*newcon)); + if (newcon) + { + newcon->generic.name = "TCPConnect"; + if (isserver) + newcon->generic.GetLocalAddress = FTENET_Generic_GetLocalAddress; + newcon->generic.GetPacket = FTENET_TCPConnect_GetPacket; + newcon->generic.SendPacket = FTENET_TCPConnect_SendPacket; + newcon->generic.Close = FTENET_TCPConnect_Close; + + newcon->generic.islisten = true; + newcon->generic.addrtype[0] = adr.type; + newcon->generic.addrtype[1] = NA_INVALID; + + newcon->active = 0; + + if (!isserver) + { + newcon->generic.thesocket = INVALID_SOCKET; + + newcon->active++; + newcon->tcpstreams = Z_Malloc(sizeof(*newcon->tcpstreams)); + newcon->tcpstreams->waitingforprotocolconfirmation = true; + newcon->tcpstreams->next = NULL; + newcon->tcpstreams->socketnum = newsocket; + newcon->tcpstreams->inlen = 0; + SockadrToNetadr(&qs, &newcon->tcpstreams->remoteaddr); + + //send the qizmo greeting. + send(newsocket, "qizmo\n", 6, 0); + + newcon->tcpstreams->timeouttime = Sys_DoubleTime() + 30; + } + else + { + newcon->tcpstreams = NULL; + newcon->generic.thesocket = newsocket; + } + + return &newcon->generic; + } + else + { + closesocket(newsocket); + return NULL; + } +} + +ftenet_generic_connection_t *FTENET_TCP6Connect_EstablishConnection(qboolean isserver, char *address) +{ + return FTENET_TCPConnect_EstablishConnection(AF_INET6, isserver, address); +} + +ftenet_generic_connection_t *FTENET_TCP4Connect_EstablishConnection(qboolean isserver, char *address) +{ + return FTENET_TCPConnect_EstablishConnection(AF_INET, isserver, address); +} + +#endif + + + + +#ifdef IRCCONNECT + +typedef struct ftenet_ircconnect_stream_s { + char theiruser[16]; + + int inlen; + char inbuffer[1500]; + float timeouttime; + netadr_t remoteaddr; + struct ftenet_ircconnect_stream_s *next; +} ftenet_ircconnect_stream_t; + +typedef struct { + ftenet_generic_connection_t generic; + + netadr_t ircserver; + + char incoming[512+1]; + int income; + + char ourusername[16]; + char usechannel[16]; + + char outbuf[8192]; + unsigned int outbufcount; + + ftenet_ircconnect_stream_t *streams; +} ftenet_ircconnect_connection_t; + +qboolean FTENET_IRCConnect_GetPacket(ftenet_generic_connection_t *gcon) +{ + unsigned char *s, *start, *end, *endl; + int read; + unsigned char *from; + int fromlen; + int code; + char adr[128]; + + ftenet_ircconnect_connection_t *con = (ftenet_ircconnect_connection_t*)gcon; + + if (con->generic.thesocket == INVALID_SOCKET) + { + if (con->income == 0) + { + cvar_t *ircuser = Cvar_Get("ircuser", "none", 0, "IRC Connect"); + cvar_t *irchost = Cvar_Get("irchost", "none", 0, "IRC Connect"); + cvar_t *ircnick = Cvar_Get("ircnick", "ftesv", 0, "IRC Connect"); + cvar_t *ircchannel = Cvar_Get("ircchannel", "#ftetest", 0, "IRC Connect"); + cvar_t *ircsomething = Cvar_Get("ircsomething", "moo", 0, "IRC Connect"); + cvar_t *ircclientaddr = Cvar_Get("ircclientaddr", "127.0.0.1", 0, "IRC Connect"); + + con->generic.thesocket = TCP_OpenStream(con->ircserver); + + Q_strncpyz(con->ourusername, ircnick->string, sizeof(con->ourusername)); + + send(con->generic.thesocket, "USER ", 5, 0); + send(con->generic.thesocket, ircuser->string, strlen(ircuser->string), 0); + send(con->generic.thesocket, " ", 1, 0); + send(con->generic.thesocket, irchost->string, strlen(irchost->string), 0); + send(con->generic.thesocket, " ", 1, 0); + send(con->generic.thesocket, ircclientaddr->string, strlen(ircclientaddr->string), 0); + send(con->generic.thesocket, " :", 2, 0); + send(con->generic.thesocket, ircsomething->string, strlen(ircsomething->string), 0); + send(con->generic.thesocket, "\r\n", 2, 0); + send(con->generic.thesocket, "NICK ", 5, 0); + send(con->generic.thesocket, con->ourusername, strlen(con->ourusername), 0); + send(con->generic.thesocket, "\r\n", 2, 0); + } + } + else + { + read = recv(con->generic.thesocket, con->incoming+con->income, sizeof(con->incoming)-1 - con->income, 0); + if (read < 0) + { + read = qerrno; + switch(read) + { + case ECONNABORTED: + case ECONNRESET: + closesocket(con->generic.thesocket); + con->generic.thesocket = INVALID_SOCKET; + break; + default: + break; + } + + read = 0;//return false; + } + else if (read == 0) //they disconnected. + { + closesocket(con->generic.thesocket); + con->generic.thesocket = INVALID_SOCKET; + } + + con->income += read; + con->incoming[con->income] = 0; + } + + start = con->incoming; + end = start+con->income; + + while (start < end) + { + endl = NULL; + for (s = start; s < end; s++) + { + if (*s == '\n') + { + endl = s; + break; + } + } + if (endl == NULL) + //not got a complete command. + break; + + s = start; + while(*s == ' ') + s++; + if (*s == ':') + { + s++; + from = s; + while(s sizeof(net_from.address.irc.user)-1) + fromlen = sizeof(net_from.address.irc.user)-1; + for (code = 0; code < fromlen; code++) + if (from[code] == '!') + { + fromlen = code; + break; + } + + net_from.type = NA_IRC; + memcpy(net_from.address.irc.user, from, fromlen); + net_from.address.irc.user[fromlen] = 0; + + dest = s; + //discard the destination name + while(s= sizeof(net_from.address.irc.channel)) + { //no space, just pretend it was direct. + net_from.address.irc.channel[0] = 0; + } + else + { + memcpy(net_from.address.irc.channel, dest, s-dest); + net_from.address.irc.channel[s-dest] = 0; + + if (!strcmp(net_from.address.irc.channel, con->ourusername)) + { //this was aimed at us. clear the channel. + net_from.address.irc.channel[0] = 0; + } + } + + while(*s == ' ') + s++; + + if (*s == ':') + { + s++; + + if (*s == '!') + { + s++; + + /*interpret as a connectionless packet*/ + net_message.cursize = 4 + endl - s; + if (net_message.cursize >= sizeof(net_message_buffer) ) + { + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + break; + } + + *(unsigned int*)net_message_buffer = ~0; + memcpy(net_message_buffer+4, s, net_message.cursize); + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + + //clean up the incoming data + memmove(con->incoming, start, end - (endl+1)); + con->income = end - (endl+1); + con->incoming[con->income] = 0; + + return true; + } + if (*s == '$') + { + char *nstart = s; + while (*s != '\r' && *s != '\n' && *s != '#' && *s != ' ' && *s != ':') + s++; + if (*s == '#') + { + if (strncmp(nstart, con->ourusername, strlen(con->ourusername)) || strlen(con->ourusername) != s - nstart) + while(*s == '#') + s++; + } + } + if (*s == '#') + { + ftenet_ircconnect_stream_t *st; + int psize; + + for (st = con->streams; st; st = st->next) + { + if (!strncmp(st->remoteaddr.address.irc.user, from, fromlen) && st->remoteaddr.address.irc.user[fromlen] == 0) + break; + } + if (!st) + { + st = Z_Malloc(sizeof(*st)); + + st->remoteaddr = net_from; + st->next = con->streams; + con->streams = st; + } + + //skip over the hash + s++; + + psize = 0; + if (*s >= 'a' && *s <= 'f') + psize += *s - 'a' + 10; + else if (*s >= '0' && *s <= '9') + psize += *s - '0'; + s++; + + psize*=16; + if (*s >= 'a' && *s <= 'f') + psize += *s - 'a' + 10; + else if (*s >= '0' && *s <= '9') + psize += *s - '0'; + s++; + + psize*=16; + if (*s >= 'a' && *s <= 'f') + psize += *s - 'a' + 10; + else if (*s >= '0' && *s <= '9') + psize += *s - '0'; + s++; + + while (s < endl && st->inlen < sizeof(st->inbuffer)) + { + switch (*s) + { + //handle markup + case '\\': + s++; + if (s < endl) + { + switch(*s) + { + case '\\': + st->inbuffer[st->inlen++] = *s; + break; + case 'n': + st->inbuffer[st->inlen++] = '\n'; + break; + case 'r': + st->inbuffer[st->inlen++] = '\r'; + break; + case '0': + st->inbuffer[st->inlen++] = 0; + break; + default: + st->inbuffer[st->inlen++] = '?'; + break; + } + } + break; + + //ignore these + case '\n': + case '\r': + case '\0': //this one doesn't have to be ignored. + break; + + //handle normal char + default: + st->inbuffer[st->inlen++] = *s; + break; + } + s++; + } + + if (st->inlen > psize || psize >= sizeof(net_message_buffer) ) + { + st->inlen = 0; + Con_Printf ("Corrupt packet from %s\n", NET_AdrToString (adr, sizeof(adr), net_from)); + } + else if (st->inlen == psize) + { + /*interpret as a connectionless packet*/ + net_message.cursize = st->inlen; + if (net_message.cursize >= sizeof(net_message_buffer) ) + { + Con_TPrintf (TL_OVERSIZEPACKETFROM, NET_AdrToString (adr, sizeof(adr), net_from)); + break; + } + + memcpy(net_message_buffer, st->inbuffer, net_message.cursize); + + net_message.packing = SZ_RAWBYTES; + net_message.currentbit = 0; + + st->inlen = 0; + + //clean up the incoming data + memmove(con->incoming, start, end - (endl+1)); + con->income = end - (endl+1); + con->incoming[con->income] = 0; + + return true; + } + } + } + } + else if (!strncmp(s, "PING ", 5)) + { + send(con->generic.thesocket, "PONG ", 5, 0); + send(con->generic.thesocket, s+5, endl - s - 5, 0); + send(con->generic.thesocket, "\r\n", 2, 0); + } + else + { + code = strtoul(s, &s, 10); + switch (code) + { + case 001: + { + cvar_t *ircchannel = Cvar_Get("ircchannel", "", 0, "IRC Connect"); + if (*ircchannel->string) + { + send(con->generic.thesocket, "JOIN ", 5, 0); + send(con->generic.thesocket, ircchannel->string, strlen(ircchannel->string), 0); + send(con->generic.thesocket, "\r\n", 2, 0); + } + } + break; + case 433: + //nick already in use + send(con->generic.thesocket, "NICK ", 5, 0); + { + cvar_t *ircnick2 = Cvar_Get("ircnick2", "YIBBLE", 0, "IRC Connect"); + Q_strncpyz(con->ourusername, ircnick2->string, sizeof(con->ourusername)); + send(con->generic.thesocket, con->ourusername, strlen(con->ourusername), 0); + } + send(con->generic.thesocket, "\r\n", 2, 0); + break; + case 0: + //non-numerical event. + break; + } + } + + while(*s == ' ') + s++; + + start = s = endl+1; + } + + memmove(con->incoming, start, end - start); + con->income = end - start; + con->incoming[con->income] = 0; + + if (con->generic.thesocket == INVALID_SOCKET) + con->income = 0; + + return false; +} +qboolean FTENET_IRCConnect_SendPacket(ftenet_generic_connection_t *gcon, int length, void *data, netadr_t to) +{ + ftenet_ircconnect_connection_t *con = (ftenet_ircconnect_connection_t*)gcon; + + unsigned char *buffer; + unsigned char *lenofs; + int packed; + int fulllen = length; + int newoutcount; + + for (packed = 0; packed < FTENET_ADDRTYPES; packed++) + if (to.type == con->generic.addrtype[packed]) + break; + if (packed == FTENET_ADDRTYPES) + return false; + + packed = 0; + + if (con->generic.thesocket == INVALID_SOCKET) + return true; +/* + if (*(unsigned int *)data == ~0 && !strchr(data, '\n') && !strchr(data, '\r') && strlen(data) == length) + { + if (send(con->generic.thesocket, va("PRIVMSG %s :!", to.address.irc.user), 15, 0) != 15) + Con_Printf("bad send\n"); + else if (send(con->generic.thesocket, (char*)data+4, length - 4, 0) != length-4) + Con_Printf("bad send\n"); + else if (send(con->generic.thesocket, "\r\n", 2, 0) != 2) + Con_Printf("bad send\n"); + return true; + } +*/ + newoutcount = con->outbufcount; + if (!con->outbufcount) + while(length) + { + buffer = con->outbuf + newoutcount; + + if (*to.address.irc.channel) + { + int unamelen; + int chanlen; + unamelen = strlen(to.address.irc.user); + chanlen = strlen(to.address.irc.channel); + packed = 8+chanlen+3+unamelen+1 + 3; + + if (packed+1 + newoutcount > sizeof(con->outbuf)) + break; + + memcpy(buffer, "PRIVMSG ", 8); + memcpy(buffer+8, to.address.irc.channel, chanlen); + memcpy(buffer+8+chanlen, " :$", 3); + memcpy(buffer+8+chanlen+3, to.address.irc.user, unamelen); + memcpy(buffer+8+chanlen+3+unamelen, "#", 1); + lenofs = buffer+8+chanlen+3+unamelen+1; + sprintf(lenofs, "%03x", fulllen); + + } + else + { + int unamelen; + unamelen = strlen(to.address.irc.user); + packed = 8 + unamelen + 3 + 3; + + if (packed+1 + newoutcount > sizeof(con->outbuf)) + break; + + memcpy(buffer, "PRIVMSG ", 8); + memcpy(buffer+8, to.address.irc.user, unamelen); + memcpy(buffer+8+unamelen, " :#", 3); + lenofs = buffer+8+unamelen+3; + sprintf(lenofs, "%03x", fulllen); + } + + + while(length && packed < 400 && packed+newoutcount < sizeof(con->outbuf)-2) //make sure there's always space + { + switch(*(unsigned char*)data) + { + case '\\': + buffer[packed++] = '\\'; + buffer[packed++] = '\\'; + break; + case '\n': + buffer[packed++] = '\\'; + buffer[packed++] = 'n'; + break; + case '\r': + buffer[packed++] = '\\'; + buffer[packed++] = 'r'; + break; + case '\0': + buffer[packed++] = '\\'; + buffer[packed++] = '0'; + break; + default: + buffer[packed++] = *(unsigned char*)data; + break; + } + length--; + data = (char*)data + 1; + } + + buffer[packed++] = '\r'; + buffer[packed++] = '\n'; + + newoutcount += packed; + packed = 0; + } + if (!length) + { + //only if we flushed all + con->outbufcount = newoutcount; + } + + //try and flush it + length = send(con->generic.thesocket, con->outbuf, con->outbufcount, 0); + if (length > 0) + { + memmove(con->outbuf, con->outbuf+length, con->outbufcount-length); + con->outbufcount -= length; + } + return true; +} +void FTENET_IRCConnect_Close(ftenet_generic_connection_t *gcon) +{ + ftenet_ircconnect_connection_t *con = (ftenet_ircconnect_connection_t *)gcon; + ftenet_ircconnect_stream_t *st; + + while(con->streams) + { + st = con->streams; + con->streams = st->next; + Z_Free(st); + } + + FTENET_Generic_Close(gcon); +} + +ftenet_generic_connection_t *FTENET_IRCConnect_EstablishConnection(qboolean isserver, char *address) +{ + //this is written to support either ipv4 or ipv6, depending on the remote addr. + ftenet_ircconnect_connection_t *newcon; + netadr_t adr; + + if (!NET_StringToAdr(address, &adr)) + return NULL; //couldn't resolve the name + + + + newcon = Z_Malloc(sizeof(*newcon)); + if (newcon) + { + newcon->generic.name = "IRCConnect"; + newcon->generic.GetPacket = FTENET_IRCConnect_GetPacket; + newcon->generic.SendPacket = FTENET_IRCConnect_SendPacket; + newcon->generic.Close = FTENET_IRCConnect_Close; + + newcon->generic.islisten = true; + newcon->generic.addrtype[0] = NA_IRC; + newcon->generic.addrtype[1] = NA_INVALID; + + newcon->generic.thesocket = INVALID_SOCKET; + + newcon->ircserver = adr; + + + return &newcon->generic; + } + else + { + return NULL; + } +} + + +#endif + +qboolean NET_GetPacket (netsrc_t netsrc) +{ + int i; + ftenet_connections_t *collection; + if (netsrc == NS_SERVER) + { +#ifdef CLIENTONLY + Sys_Error("NET_GetPacket: Bad netsrc"); + collection = NULL; +#else + collection = svs.sockets; +#endif + } + else + { +#ifdef SERVERONLY + Sys_Error("NET_GetPacket: Bad netsrc"); + collection = NULL; +#else + collection = cls.sockets; +#endif + } + + if (!collection) + return false; + + for (i = 0; i < MAX_CONNECTIONS; i++) + { + if (!collection->conn[i]) + break; + if (collection->conn[i]->GetPacket(collection->conn[i])) + { + net_from.connum = i+1; + return true; + } + } + + return false; +} + +int NET_LocalAddressForRemote(ftenet_connections_t *collection, netadr_t *remote, netadr_t *local, int idx) +{ + if (!remote->connum) + return 0; + + if (!collection->conn[remote->connum-1]) + return 0; + + if (!collection->conn[remote->connum-1]->GetLocalAddress) + return 0; + + return collection->conn[remote->connum-1]->GetLocalAddress(collection->conn[remote->connum-1], local, idx); +} + +void NET_SendPacket (netsrc_t netsrc, int length, void *data, netadr_t to) +{ + ftenet_connections_t *collection; + int i; + + if (netsrc == NS_SERVER) + { +#ifdef CLIENTONLY + Sys_Error("NET_GetPacket: Bad netsrc"); +#else + collection = svs.sockets; +#endif + } + else + { +#ifdef SERVERONLY + Sys_Error("NET_GetPacket: Bad netsrc"); +#else + collection = cls.sockets; +#endif + } + + if (!collection) + return; + + if (to.connum) + { + if (collection->conn[to.connum-1]) + if (collection->conn[to.connum-1]->SendPacket(collection->conn[to.connum-1], length, data, to)) + return; + } + + for (i = 0; i < MAX_CONNECTIONS; i++) + { + if (!collection->conn[i]) + continue; + if (collection->conn[i]->SendPacket(collection->conn[i], length, data, to)) + return; + } + + Con_Printf("No route - open some ports\n"); +} + +void NET_EnsureRoute(ftenet_connections_t *collection, char *routename, char *host) +{ + netadr_t adr; + NET_StringToAdr(host, &adr); + + switch(adr.type) + { +#ifdef TCPCONNECT + case NA_TCP: + FTENET_AddToCollection(collection, routename, host, FTENET_TCP4Connect_EstablishConnection); + break; + case NA_TCPV6: + FTENET_AddToCollection(collection, routename, host, FTENET_TCP6Connect_EstablishConnection); + break; +#endif +#ifdef IRCCONNECT + case NA_IRC: + FTENET_AddToCollection(collection, routename, host, FTENET_IRCConnect_EstablishConnection); + break; +#endif + default: + //not recognised, or not needed + break; + } +} + +void NET_PrintAddresses(ftenet_connections_t *collection) +{ + int i; + int adrno, adrcount=1; + netadr_t adr; + char adrbuf[MAX_ADR_SIZE]; + + if (!collection) + return; + + for (i = 0; i < MAX_CONNECTIONS; i++) + { + if (!collection->conn[i]) + continue; + if (collection->conn[i]->GetLocalAddress) + { + for (adrno = 0, adrcount=1; adrcount = collection->conn[i]->GetLocalAddress(collection->conn[i], &adr, adrno) && adrno < adrcount; adrno++) + { + Con_Printf("net address: %s\n", NET_AdrToString(adrbuf, sizeof(adrbuf), adr)); + } + } + else + Con_Printf("%s\n", collection->conn[i]->name); + } } //============================================================================= @@ -2017,39 +3050,32 @@ qboolean NET_Sleep(int msec, qboolean stdinissocket) { struct timeval timeout; fd_set fdset; - int i; + int maxfd; + int con, sock; FD_ZERO(&fdset); if (stdinissocket) FD_SET(0, &fdset); //stdin tends to be socket 0 - i = 0; - if (svs.socketip!=INVALID_SOCKET) + maxfd = 0; + if (svs.sockets) + for (con = 0; con < MAX_CONNECTIONS; con++) { - FD_SET(svs.socketip, &fdset); // network socket - i = svs.socketip; + if (!svs.sockets->conn[con]) + continue; + sock = svs.sockets->conn[con]->thesocket; + if (sock != INVALID_SOCKET) + { + FD_SET(sock, &fdset); // network socket + if (sock > maxfd) + maxfd = sock; + } } -#ifdef IPPROTO_IPV6 - if (svs.socketip6!=INVALID_SOCKET) - { - FD_SET(svs.socketip6, &fdset); // network socket - if (svs.socketip6 > i) - i = svs.socketip6; - i = svs.socketip6; - } -#endif -#ifdef USEIPX - if (svs.socketipx!=INVALID_SOCKET) - { - FD_SET(svs.socketipx, &fdset); // network socket - if (svs.socketipx > i) - i = svs.socketipx; - } -#endif + timeout.tv_sec = msec/1000; timeout.tv_usec = (msec%1000)*1000; - select(i+1, &fdset, NULL, NULL, &timeout); + select(maxfd+1, &fdset, NULL, NULL, &timeout); if (stdinissocket) return FD_ISSET(0, &fdset); @@ -2095,6 +3121,55 @@ void NET_GetLocalAddress (int socket, netadr_t *out) Con_TPrintf(TL_IPADDRESSIS, NET_AdrToString (adrbuf, sizeof(adrbuf), *out) ); } +#ifndef CLIENTONLY +void SVNET_AddPort(void) +{ + netadr_t adr; + char *s = Cmd_Argv(1); + + //just in case + if (!svs.sockets) + { + svs.sockets = FTENET_CreateCollection(true); +#ifndef SERVERONLY + FTENET_AddToCollection(svs.sockets, "SVLoopback", "27500", FTENET_Loop_EstablishConnection); +#endif + } + + NET_PortToAdr(AF_INET, s, &adr); + + switch(adr.type) + { + case NA_IP: + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_UDP4_EstablishConnection); + break; +#ifdef IPPROTO_IPV6 + case NA_IPV6: + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_UDP6_EstablishConnection); + break; +#endif +#ifdef USEIPX + case NA_IPX: + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_IPX_EstablishConnection); + break; +#endif +#ifdef IRCCONNECT + case NA_IRC: + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_IRCConnect_EstablishConnection); + break; +#endif +#ifdef IRCCONNECT + case NA_TCP: + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_TCP4Connect_EstablishConnection); + break; + case NA_TCPV6: + FTENET_AddToCollection(svs.sockets, NULL, s, FTENET_TCP6Connect_EstablishConnection); + break; +#endif + } +} +#endif + /* ==================== NET_Init @@ -2132,53 +3207,36 @@ void NET_Init (void) #endif Con_TPrintf(TL_UDPINITED); - -#ifndef SERVERONLY - cls.socketip = INVALID_SOCKET; - cls.socketip6 = INVALID_SOCKET; - cls.socketipx = INVALID_SOCKET; -#ifdef TCPCONNECT - cls.sockettcp = INVALID_SOCKET; -#endif -#endif - -#ifndef CLIENTONLY - svs.socketip = INVALID_SOCKET; - svs.socketip6 = INVALID_SOCKET; - svs.socketipx = INVALID_SOCKET; -#ifdef TCPCONNECT - svs.sockettcp = INVALID_SOCKET; -#endif -#endif } +#define STRINGIFY2(s) #s +#define STRINGIFY(s) STRINGIFY2(##s) #ifndef SERVERONLY void NET_InitClient(void) { - int port; + char *port; int p; - port = PORT_CLIENT; + port = STRINGIFY(PORT_CLIENT); p = COM_CheckParm ("-port"); if (p && p < com_argc) { - port = atoi(com_argv[p+1]); + port = com_argv[p+1]; } p = COM_CheckParm ("-clport"); if (p && p < com_argc) { - port = atoi(com_argv[p+1]); + port = com_argv[p+1]; } - // - // open the single socket to be used for all communications - // - cls.socketip = UDP_OpenSocket (port, false); -#ifdef IPPROTO_IPV6 - cls.socketip6 = UDP6_OpenSocket (port, false); -#endif -#ifdef USEIPX - cls.socketipx = IPX_OpenSocket (port, false); + cls.sockets = FTENET_CreateCollection(false); +#ifndef CLIENTONLY + FTENET_AddToCollection(cls.sockets, "CLLoopback", port, FTENET_Loop_EstablishConnection); #endif +// FTENET_AddToCollection(cls.sockets, "CLTCP6", port, FTENET_TCP6Connect_EstablishConnection); +// FTENET_AddToCollection(cls.sockets, "CLTCP4", port, FTENET_TCP4Connect_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLUDP4", port, FTENET_UDP4_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLUDP6", port, FTENET_UDP6_EstablishConnection); + FTENET_AddToCollection(cls.sockets, "CLIPX", port, FTENET_IPX_EstablishConnection); // // init the message buffer @@ -2189,67 +3247,80 @@ void NET_InitClient(void) // // determine my name & address // - NET_GetLocalAddress (cls.socketip, &net_local_cl_ipadr); +// NET_GetLocalAddress (cls.socketip, &net_local_cl_ipadr); Con_TPrintf(TL_CLIENTPORTINITED); } #endif #ifndef CLIENTONLY + + +#ifndef CLIENTONLY +void SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue) +{ + FTENET_AddToCollection(svs.sockets, "SVTCP4", var->string, FTENET_TCP4Connect_EstablishConnection); +} +void SV_Tcpport6_Callback(struct cvar_s *var, char *oldvalue) +{ + FTENET_AddToCollection(svs.sockets, "SVTCP6", var->string, FTENET_TCP6Connect_EstablishConnection); +} + +void SV_Port_Callback(struct cvar_s *var, char *oldvalue) +{ + FTENET_AddToCollection(svs.sockets, "SVUDP4", var->string, FTENET_UDP4_EstablishConnection); +} +#ifdef IPPROTO_IPV6 +void SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue) +{ + FTENET_AddToCollection(svs.sockets, "SVUDP6", var->string, FTENET_UDP6_EstablishConnection); +} +#endif +#ifdef USEIPX +void SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue) +{ + FTENET_AddToCollection(svs.sockets, "SVIPX", var->string, FTENET_IPX_EstablishConnection); +} +#endif +#endif + void NET_CloseServer(void) { allowconnects = false; - if (svs.socketip != INVALID_SOCKET) - { - UDP_CloseSocket(svs.socketip); - svs.socketip = INVALID_SOCKET; - } -#ifdef IPPROTO_IPV6 - if (svs.socketip6 != INVALID_SOCKET) - { - UDP_CloseSocket(svs.socketip6); - svs.socketip6 = INVALID_SOCKET; - } -#endif -#ifdef USEIPX - if (svs.socketipx != INVALID_SOCKET) - { - IPX_CloseSocket(svs.socketipx); - svs.socketipx = INVALID_SOCKET; - } -#endif -#ifdef TCPCONNECT - if (svs.sockettcp != INVALID_SOCKET) - { - closesocket(svs.sockettcp); - svs.sockettcp = INVALID_SOCKET; - } -#endif - - net_local_sv_ipadr.type = NA_LOOPBACK; - net_local_sv_ip6adr.type = NA_LOOPBACK; - net_local_sv_ipxadr.type = NA_LOOPBACK; + FTENET_CloseCollection(svs.sockets); + svs.sockets = NULL; } void NET_InitServer(void) { - int port; - port = PORT_SERVER; + char *port; + port = STRINGIFY(PORT_SERVER); - if (sv_listen_nq.value || sv_listen_dp.value || sv_listen_qw.value) + if (!svs.sockets) + { + svs.sockets = FTENET_CreateCollection(true); +#ifndef SERVERONLY + FTENET_AddToCollection(svs.sockets, "SVLoopback", port, FTENET_Loop_EstablishConnection); +#endif + } + + if (sv_listen_nq.value || sv_listen_dp.value || sv_listen_qw.value || sv_listen_q3.value) { allowconnects = true; Cvar_ForceCallback(&sv_port); -#ifdef TCPCONNECT - Cvar_ForceCallback(&sv_port_tcp); -#endif #ifdef IPPROTO_IPV6 Cvar_ForceCallback(&sv_port_ipv6); #endif #ifdef USEIPX Cvar_ForceCallback(&sv_port_ipx); +#endif +#ifdef TCPCONNECT + Cvar_ForceCallback(&sv_port_tcp); +#ifdef IPPROTO_IPV6 + Cvar_ForceCallback(&sv_port_tcp6); +#endif #endif } else @@ -2274,14 +3345,11 @@ void NET_Shutdown (void) NET_CloseServer(); #endif #ifndef SERVERONLY - UDP_CloseSocket (cls.socketip); -#ifdef IPPROTO_IPV6 - UDP_CloseSocket (cls.socketip6); -#endif -#ifdef USEIPX - IPX_CloseSocket (cls.socketipx); -#endif + FTENET_CloseCollection(cls.sockets); + cls.sockets = NULL; #endif + + #ifdef _WIN32 #ifdef SERVERTONLY if (!serverthreadID) //running as subsystem of client. Don't close all of it's sockets too. diff --git a/engine/common/particles.h b/engine/common/particles.h index 3aa84bf7d..75e3a9aaa 100644 --- a/engine/common/particles.h +++ b/engine/common/particles.h @@ -1,63 +1,63 @@ #ifndef _PARTICLES_H_ #define _PARTICLES_H_ -extern int pt_explosion, - pt_pointfile, - pt_entityparticles, - pt_blob, - pt_blood, - pt_lightningblood, +extern int pt_gunshot, + ptdp_gunshotquad, + pt_spike, + ptdp_spikequad, + pt_superspike, + ptdp_superspikequad, pt_wizspike, pt_knightspike, - pt_spike, - pt_superspike, - pt_lavasplash, + pt_explosion, + ptdp_explosionquad, + pt_tarexplosion, pt_teleportsplash, - pt_blasterparticles, - pt_torch, - pt_flame, - pt_bullet, - pt_superbullet, - pe_default, - pe_defaulttrail; - -extern int rt_blastertrail, - rt_railtrail, - rt_bubbletrail, + pt_lavasplash, + ptdp_smallflash, + ptdp_flamejet, + ptdp_flame, + ptdp_blood, + ptdp_spark, + ptdp_plasmaburn, + ptdp_tei_g3, + ptdp_tei_smoke, + ptdp_tei_bigexplosion, + ptdp_tei_plasmahit, + ptdp_stardust, rt_rocket, rt_grenade, - rt_gib, - rt_lightning1, - rt_lightning2, - rt_lightning3, - pt_lightning1_end, - pt_lightning2_end, - pt_lightning3_end; - -/* -extern int rt_rocket_trail, - rt_smoke, rt_blood, - rt_tracer, - rt_slight_blood, - rt_tracer2, - rt_voor_trail, - rt_fireball, - rt_ice, - rt_spit, - rt_spell, - rt_vorpal, - rt_setstaff, - rt_magicmissile, - rt_boneshard, - rt_scarab, - rt_acidball, - rt_bloodshot, - rt_blastertrail, - rt_railtrail, - rt_bubbletrail; -*/ + rt_wizspike, + rt_slightblood, + rt_knightspike, + rt_vorespike, + rtdp_neharasmoke, + rtdp_nexuizplasma, + rtdp_glowtrail, + + ptqw_blood, + ptqw_lightningblood, + + ptq2_blood, + rtq2_railtrail, + rtq2_blastertrail, + ptq2_blasterparticles, + rtq2_bubbletrail, + rtq2_gib, + rtq2_rocket, + rtq2_grenade, + + rtqw_railtrail, //common to zquake/fuhquake/fte + rtfte_lightning1, + ptfte_lightning1_end, + rtfte_lightning2, + ptfte_lightning2_end, + rtfte_lightning3, + ptfte_lightning3_end, + ptfte_bullet, + ptfte_superbullet; struct beamseg_s; @@ -75,233 +75,75 @@ typedef struct trailstate_s { } state2; } trailstate_t; -// !!! if this is changed, it must be changed in d_ifacea.h too !!! -typedef struct particle_s -{ - struct particle_s *next; - float die; - -// driver-usable fields - vec3_t org; - float color; //used by sw renderer. To be removed. - vec3_t rgb; - float alpha; - float scale; - - vec3_t vel; //renderer uses for sparks - float angle; - union { - float nextemit; - trailstate_t *trailstate; - } state; -// drivers never touch the following fields - float rotationspeed; -} particle_t; - -typedef struct clippeddecal_s -{ - struct clippeddecal_s *next; - float die; - - vec3_t center; - vec3_t vertex[3]; - vec2_t texcoords[3]; - - vec3_t rgb; - float alpha; -} clippeddecal_t; - -#define BS_LASTSEG 0x1 // no draw to next, no delete -#define BS_DEAD 0x2 // segment is dead -#define BS_NODRAW 0x4 // only used for lerp switching - -typedef struct beamseg_s -{ - struct beamseg_s *next; // next in beamseg list - - particle_t *p; - int flags; // flags for beamseg - vec3_t dir; - - float texture_s; -} beamseg_t; - - - -typedef struct skytris_s { - struct skytris_s *next; - vec3_t org; - vec3_t x; - vec3_t y; - float area; - float nexttime; - struct msurface_s *face; -} skytris_t; - -//these could be deltas or absolutes depending on ramping mode. -typedef struct { - vec3_t rgb; - float alpha; - float scale; - float rotation; -} ramp_t; -typedef enum { BM_BLEND, BM_BLENDCOLOUR, BM_ADD, BM_SUBTRACT } blendmode_t; -// TODO: merge in alpha with rgb to gain benefit of vector opts -typedef struct part_type_s { - char name[MAX_QPATH]; - char texname[MAX_QPATH]; - vec3_t rgb; - vec3_t rgbchange; - vec3_t rgbrand; - int colorindex; - int colorrand; - float rgbchangetime; - vec3_t rgbrandsync; - float scale, alpha; - float alphachange; - float die, randdie; - float randomvel, veladd; - float orgadd; - float offsetspread; - float offsetspreadvert; - float randomvelvert; - float randscale; - - float spawntime; - float spawnchance; - - enum {PT_NORMAL, PT_SPARK, PT_SPARKFAN, PT_TEXTUREDSPARK, PT_BEAM, PT_DECAL} type; - blendmode_t blendmode; - - float rotationstartmin, rotationstartrand; - float rotationmin, rotationrand; - - float scaledelta; - float count; - float countrand; - int texturenum; -#ifdef D3DQUAKE - void *d3dtexture; -#endif - int assoc; - int cliptype; - int inwater; - float clipcount; - int emit; - float emittime; - float emitrand; - float emitstart; - - float areaspread; - float areaspreadvert; - float scalefactor; - float invscalefactor; - - float spawnparam1; - float spawnparam2; -/* float spawnparam3; */ - - float offsetup; // make this into a vec3_t later with dir, possibly for mdls - - enum { - SM_BOX, //box = even spread within the area - SM_CIRCLE, //circle = around edge of a circle - SM_BALL, //ball = filled sphere - SM_SPIRAL, //spiral = spiral trail - SM_TRACER, //tracer = tracer trail - SM_TELEBOX, //telebox = q1-style telebox - SM_LAVASPLASH, //lavasplash = q1-style lavasplash - SM_UNICIRCLE, //unicircle = uniform circle - SM_FIELD, //field = synced field (brightfield, etc) - SM_DISTBALL // uneven distributed ball - } spawnmode; - - float gravity; - vec3_t friction; - float clipbounce; - int stains; - - enum {RAMP_NONE, RAMP_DELTA, RAMP_ABSOLUTE} rampmode; - int rampindexes; - ramp_t *ramp; - - int loaded; - particle_t *particles; - clippeddecal_t *clippeddecals; - beamseg_t *beams; - skytris_t *skytris; - struct part_type_s *nexttorun; - - unsigned int flags; -#define PT_VELOCITY 0x001 -#define PT_FRICTION 0x002 -#define PT_CHANGESCOLOUR 0x004 -#define PT_CITRACER 0x008 // Q1-style tracer behavior for colorindex -#define PT_INVFRAMETIME 0x010 // apply inverse frametime to count (causes emits to be per frame) -#define PT_AVERAGETRAIL 0x020 // average trail points from start to end, useful with t_lightning, etc -#define PT_NOSTATE 0x040 // don't use trailstate for this emitter (careful with assoc...) -#define PT_NOSPREADFIRST 0x080 // don't randomize org/vel for first generated particle -#define PT_NOSPREADLAST 0x100 // don't randomize org/vel for last generated particle - unsigned int state; -#define PS_INRUNLIST 0x1 // particle type is currently in execution list -} part_type_t; - - - #define PARTICLE_Z_CLIP 8.0 +typedef enum { BM_BLEND, BM_BLENDCOLOUR, BM_ADD, BM_SUBTRACT } blendmode_t; + #define frandom() (rand()*(1.0f/RAND_MAX)) #define crandom() (rand()*(2.0f/RAND_MAX)-1.0f) #define hrandom() (rand()*(1.0f/RAND_MAX)-0.5f) -//main functions -void P_DrawParticles (void); -void P_InitParticles (void); -void P_ClearParticles (void); +#define P_INVALID -1 -//allocate a new effect -int P_ParticleTypeForName(char *name); -int P_AllocateParticleType(char *name); //find one if it exists, or create if it doesn't. -int P_FindParticleType(char *name); //checks if particle description 'name' exists, returns -1 if not. - -int P_DescriptionIsLoaded(char *name); //returns true if it's usable. -qboolean P_TypeIsLoaded(int effect); - -void P_SkyTri(float *v1, float *v2, float *v3, struct msurface_s *surf); - -// default particle effect -void P_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count); //aka: the particle builtin. - -//wierd effects -void P_RunParticleEffect2 (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count); //these three are needed for hexen2. -void P_RunParticleEffect3 (vec3_t org, vec3_t box, int color, int effect, int count); -void P_RunParticleEffect4 (vec3_t org, float radius, int color, int effect, int count); - -void P_EmitEffect (vec3_t pos, int type, trailstate_t **tsk); //particles centered around a model, called every frame for those models. - -//functions that spawn point effects (basically just pass throughs) -void P_BlobExplosion (vec3_t org); //tarbaby explosion or TF emp. -void P_LavaSplash (vec3_t org); //cthon dying, or a gas grenade. -void P_RunParticleCube(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter); -void P_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname); - -//the core spawn function for trails. (trailstate can be null) -int P_ParticleTrail (vec3_t start, vec3_t end, int type, trailstate_t **trailstate); -void P_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int rndcolor, trailstate_t **trailstate); - -void P_DefaultTrail (struct model_s *model); //fills in the default particle properties for a loaded model. Should already have the model flags set. - -//the core spawn function for point effects -int P_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk); //1 if failed -int P_RunParticleEffectTypeString (vec3_t org, vec3_t dir, float count, char *name); //1 if failed. #define P_RunParticleEffectType(a,b,c,d) P_RunParticleEffectState(a,b,c,d,NULL) -void P_EmitSkyEffectTris(struct model_s *mod, struct msurface_s *fa); - -// trailstate functions -void P_DelinkTrailstate(trailstate_t **tsk); - // used for callback extern cvar_t r_particlesdesc; +struct model_s; +struct msurface_s; + +void P_DefaultTrail (struct model_s *model); +void P_EmitEffect (vec3_t pos, int type, trailstate_t **tsk);//this is just a wrapper + +#define P_ParticleTypeForName pe->ParticleTypeForName +#define P_FindParticleType pe->FindParticleType + +#define P_RunParticleEffectTypeString pe->RunParticleEffectTypeString +#define P_ParticleTrail pe->ParticleTrail +#define P_RunParticleEffectState pe->RunParticleEffectState +#define P_RunParticleWeather pe->RunParticleWeather +#define P_RunParticleCube pe->RunParticleCube +#define P_RunParticleEffect pe->RunParticleEffect +#define P_RunParticleEffect2 pe->RunParticleEffect2 +#define P_RunParticleEffect3 pe->RunParticleEffect3 +#define P_RunParticleEffect4 pe->RunParticleEffect4 + +#define P_ParticleTrailIndex pe->ParticleTrailIndex +#define P_EmitSkyEffectTris pe->EmitSkyEffectTris +#define P_InitParticles pe->InitParticles +#define P_DelinkTrailstate pe->DelinkTrailstate +#define P_ClearParticles pe->ClearParticles +#define P_DrawParticles pe->DrawParticles +#define P_FlushRenderer pe->FlushRenderer + +typedef struct { + char *name1; + char *name2; + + + int (*ParticleTypeForName) (char *name); + int (*FindParticleType) (char *name); + + int (*RunParticleEffectTypeString) (vec3_t org, vec3_t dir, float count, char *name); + int (*ParticleTrail) (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk); + int (*RunParticleEffectState) (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk); + void (*RunParticleWeather) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, char *efname); + void (*RunParticleCube) (vec3_t minb, vec3_t maxb, vec3_t dir, float count, int colour, qboolean gravity, float jitter); + void (*RunParticleEffect) (vec3_t org, vec3_t dir, int color, int count); + void (*RunParticleEffect2) (vec3_t org, vec3_t dmin, vec3_t dmax, int color, int effect, int count); + void (*RunParticleEffect3) (vec3_t org, vec3_t box, int color, int effect, int count); + void (*RunParticleEffect4) (vec3_t org, float radius, int color, int effect, int count); + + void (*ParticleTrailIndex) (vec3_t start, vec3_t end, int color, int crnd, trailstate_t **tsk); + void (*EmitSkyEffectTris) (struct model_s *mod, struct msurface_s *fa); + void (*InitParticles) (void); + void (*ShutdownParticles) (void); + void (*DelinkTrailstate) (trailstate_t **tsk); + void (*ClearParticles) (void); + void (*DrawParticles) (void); + void (*FlushRenderer) (void); +} particleengine_t; +extern particleengine_t *pe; + #endif diff --git a/engine/common/pr_bgcmd.c b/engine/common/pr_bgcmd.c new file mode 100644 index 000000000..692940dec --- /dev/null +++ b/engine/common/pr_bgcmd.c @@ -0,0 +1,2516 @@ +#include "quakedef.h" + +#if !defined(CLIENTONLY) || defined(CSQC_DAT) || defined(MENU_DAT) + +#include "pr_common.h" + +//fixme +#define Z_QC_TAG 2 +#define PRSTR 0xa6ffb3d7 + +static char *cvargroup_progs = "Progs variables"; + +cvar_t pr_brokenfloatconvert = SCVAR("pr_brokenfloatconvert", "0"); +cvar_t pr_tempstringcount = SCVAR("pr_tempstringcount", "");//"16"); +cvar_t pr_tempstringsize = SCVAR("pr_tempstringsize", "4096"); + +void PF_Common_RegisterCvars(void) +{ + static qboolean alreadydone; + if (alreadydone) + return; + alreadydone = true; + + Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs); + Cvar_Register (&pr_tempstringcount, cvargroup_progs); + Cvar_Register (&pr_tempstringsize, cvargroup_progs); +} + +char *Translate(char *message); +char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals) +{ +#define VARSTRINGLEN 16384+8 + int i; + static char buffer[2][VARSTRINGLEN]; + static int bufnum; + char *s, *out; + + out = buffer[(bufnum++)&1]; + + out[0] = 0; + for (i=first ; i<*prinst->callargc ; i++) + { +// if (G_INT(OFS_PARM0+i*3) < 0 || G_INT(OFS_PARM0+i*3) >= 1024*1024); +// break; + + s = PR_GetStringOfs(prinst, OFS_PARM0+i*3); + if (s) + { + s = Translate(s); + if (strlen(out)+strlen(s)+1 >= VARSTRINGLEN) + Con_DPrintf("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", VARSTRINGLEN); + + Q_strncatz (out, s, VARSTRINGLEN); + } + } + return out; +} + +#define MAX_TEMPSTRS ((int)pr_tempstringcount.value) +#define MAXTEMPBUFFERLEN ((int)pr_tempstringsize.value) +string_t PR_TempString(progfuncs_t *prinst, char *str) +{ + char *tmp; + if (!prinst->tempstringbase) + return prinst->TempString(prinst, str); + + if (!str || !*str) + return 0; + + if (prinst->tempstringnum == MAX_TEMPSTRS) + prinst->tempstringnum = 0; + tmp = prinst->tempstringbase + (prinst->tempstringnum++)*MAXTEMPBUFFERLEN; + + Q_strncpyz(tmp, str, MAXTEMPBUFFERLEN); + return tmp - prinst->stringtable; +} + +void PF_InitTempStrings(progfuncs_t *prinst) +{ + if (pr_tempstringcount.value > 0 && pr_tempstringcount.value < 2) + pr_tempstringcount.value = 2; + if (pr_tempstringsize.value < 256) + pr_tempstringsize.value = 256; + pr_tempstringcount.flags |= CVAR_NOSET; + pr_tempstringsize.flags |= CVAR_NOSET; + + if (pr_tempstringcount.value >= 2) + prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS); + else + prinst->tempstringbase = 0; + prinst->tempstringnum = 0; +} + +//#define RETURN_EDICT(pf, e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(pf, e)) +#define RETURN_SSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //static - exe will not change it. +#define RETURN_TSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_TempString(prinst, s)) //temp (static but cycle buffers) +#define RETURN_CSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_SetString(prinst, s)) //semi-permanant. (hash tables?) +#define RETURN_PSTRING(s) (((int *)pr_globals)[OFS_RETURN] = PR_NewString(prinst, s, 0)) //permanant + + + +void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...) +{ + va_list argptr; + static char string[2048]; + + va_start (argptr, format); + vsnprintf (string,sizeof(string)-1, format,argptr); + va_end (argptr); + + if (developer.value) + { + struct globalvars_s *pr_globals = PR_globals(progfuncs, PR_CURRENT); + Con_Printf("%s\n", string); + *progfuncs->pr_trace = 1; + G_INT(OFS_RETURN)=0; //just in case it was a float and should be an ent... + G_INT(OFS_RETURN+1)=0; + G_INT(OFS_RETURN+2)=0; + } + else + { + PR_StackTrace(progfuncs); + PR_AbortStack(progfuncs); + progfuncs->parms->Abort ("%s", string); + } +} + + +pbool QC_WriteFile(char *name, void *data, int len) +{ + char buffer[256]; + sprintf(buffer, "%s", name); + COM_WriteFile(buffer, data, len); + return true; +} + + +//////////////////////////////////////////////////// +//Finding + +/* +//entity(string field, float match) findchainflags = #450 +//chained search for float, int, and entity reference fields +void PF_findchainflags (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i, f; + int s; + edict_t *ent, *chain; + + chain = (edict_t *) *prinst->parms->sv_edicts; + + f = G_INT(OFS_PARM0)+prinst->fieldadjust; + s = G_FLOAT(OFS_PARM1); + + for (i = 1; i < *prinst->parms->sv_num_edicts; i++) + { + ent = EDICT_NUM(prinst, i); + if (ent->isfree) + continue; + if (!((int)((float *)ent->v)[f] & s)) + continue; + + ent->v->chain = EDICT_TO_PROG(prinst, chain); + chain = ent; + } + + RETURN_EDICT(prinst, chain); +} +*/ + +//EXTENSION: DP_QC_FINDFLAGS +//entity(entity start, float fld, float match) findflags = #449 +void PF_FindFlags (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int e, f; + int s; + edict_t *ed; + + e = G_EDICTNUM(prinst, OFS_PARM0); + f = G_INT(OFS_PARM1)+prinst->fieldadjust; + s = G_FLOAT(OFS_PARM2); + + for (e++; e < *prinst->parms->sv_num_edicts; e++) + { + ed = EDICT_NUM(prinst, e); + if (ed->isfree) + continue; + if ((int)((float *)ed->v)[f] & s) + { + RETURN_EDICT(prinst, ed); + return; + } + } + + RETURN_EDICT(prinst, *prinst->parms->sv_edicts); +} + +/* +//entity(string field, float match) findchainfloat = #403 +void PF_findchainfloat (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i, f; + float s; + edict_t *ent, *chain; + + chain = (edict_t *) *prinst->parms->sv_edicts; + + f = G_INT(OFS_PARM0)+prinst->fieldadjust; + s = G_FLOAT(OFS_PARM1); + + for (i = 1; i < *prinst->parms->sv_num_edicts; i++) + { + ent = EDICT_NUM(prinst, i); + if (ent->isfree) + continue; + if (((float *)ent->v)[f] != s) + continue; + + ent->v->chain = EDICT_TO_PROG(prinst, chain); + chain = ent; + } + + RETURN_EDICT(prinst, chain); +} +*/ + +/* +//entity(string field, string match) findchain = #402 +//chained search for strings in entity fields +void PF_findchain (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i, f; + char *s; + string_t t; + edict_t *ent, *chain; + + chain = (edict_t *) *prinst->parms->sv_edicts; + + f = G_INT(OFS_PARM0)+prinst->fieldadjust; + s = PR_GetStringOfs(prinst, OFS_PARM1); + + for (i = 1; i < *prinst->parms->sv_num_edicts; i++) + { + ent = EDICT_NUM(prinst, i); + if (ent->isfree) + continue; + t = *(string_t *)&((float*)ent->v)[f]; + if (!t) + continue; + if (strcmp(PR_GetString(prinst, t), s)) + continue; + + ent->v->chain = EDICT_TO_PROG(prinst, chain); + chain = ent; + } + + RETURN_EDICT(prinst, chain); +} +*/ + +//entity(entity start, float fld, float match) findfloat = #98 +void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int e, f; + int s; + edict_t *ed; + + if (*prinst->callargc != 3) //I can hate mvdsv if I want to. + { + PR_BIError(prinst, "PF_FindFloat (#98): callargc != 3\nDid you mean to set pr_imitatemvdsv to 1?"); + return; + } + + e = G_EDICTNUM(prinst, OFS_PARM0); + f = G_INT(OFS_PARM1)+prinst->fieldadjust; + s = G_INT(OFS_PARM2); + + for (e++; e < *prinst->parms->sv_num_edicts; e++) + { + ed = EDICT_NUM(prinst, e); + if (ed->isfree) + continue; + if (((int *)ed->v)[f] == s) + { + RETURN_EDICT(prinst, ed); + return; + } + } + + RETURN_EDICT(prinst, *prinst->parms->sv_edicts); +} + +// entity (entity start, .string field, string match) find = #5; +void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int e; + int f; + char *s; + string_t t; + edict_t *ed; + + e = G_EDICTNUM(prinst, OFS_PARM0); + f = G_INT(OFS_PARM1)+prinst->fieldadjust; + s = PR_GetStringOfs(prinst, OFS_PARM2); + if (!s) + { + PR_BIError (prinst, "PF_FindString: bad search string"); + return; + } + + for (e++ ; e < *prinst->parms->sv_num_edicts ; e++) + { + ed = EDICT_NUM(prinst, e); + if (ed->isfree) + continue; + t = ((string_t *)ed->v)[f]; + if (!t) + continue; + if (!strcmp(PR_GetString(prinst, t),s)) + { + RETURN_EDICT(prinst, ed); + return; + } + } + + RETURN_EDICT(prinst, *prinst->parms->sv_edicts); +} + +//Finding +//////////////////////////////////////////////////// +//Cvars + +//string(string cvarname) cvar_string +void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str = PR_GetStringOfs(prinst, OFS_PARM0); + cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); + RETURN_CSTRING(cv->string); +} + +//string(string cvarname) cvar_defstring +void PF_cvar_defstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str = PR_GetStringOfs(prinst, OFS_PARM0); + cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); + RETURN_CSTRING(cv->defaultstr); +} + +//float(string name) cvar_type +void PF_cvar_type (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str = PR_GetStringOfs(prinst, OFS_PARM0); + int ret = 0; + cvar_t *v; + + v = Cvar_FindVar(str); + if (v) + { + ret |= 1; // CVAR_EXISTS + if(v->flags & CVAR_ARCHIVE) + ret |= 2; // CVAR_TYPE_SAVED + if(v->flags & CVAR_NOTFROMSERVER) + ret |= 4; // CVAR_TYPE_PRIVATE + if(!(v->flags & CVAR_USERCREATED)) + ret |= 8; // CVAR_TYPE_ENGINE + + //fte cvars don't support this + // ret |= 16; // CVAR_TYPE_HASDESCRIPTION + } + G_FLOAT(OFS_RETURN) = ret; +} + +//void(string cvarname, string newvalue) cvar +void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *var_name, *val; + cvar_t *var; + + var_name = PR_GetStringOfs(prinst, OFS_PARM0); + val = PR_GetStringOfs(prinst, OFS_PARM1); + + var = Cvar_Get(var_name, val, 0, "QC variables"); + if (!var) + return; + Cvar_Set (var, val); +} + +void PF_cvar_setf (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *var_name; + float val; + cvar_t *var; + + var_name = PR_GetStringOfs(prinst, OFS_PARM0); + val = G_FLOAT(OFS_PARM1); + + var = Cvar_FindVar(var_name); + if (!var) + Con_Printf("PF_cvar_set: variable %s not found\n", var_name); + else + Cvar_SetValue (var, val); +} + +//float(string name, string value) registercvar +void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name, *value; + value = PR_GetStringOfs(prinst, OFS_PARM0); + + if (Cvar_FindVar(value)) + G_FLOAT(OFS_RETURN) = 0; + else + { + name = BZ_Malloc(strlen(value)+1); + strcpy(name, value); + if (*prinst->callargc > 1) + value = PR_GetStringOfs(prinst, OFS_PARM1); + else + value = ""; + + // archive? + if (Cvar_Get(name, value, CVAR_USERCREATED, "QC created vars")) + G_FLOAT(OFS_RETURN) = 1; + else + G_FLOAT(OFS_RETURN) = 0; + } +} + +//Cvars +//////////////////////////////////////////////////// +//File access + +#define MAX_QC_FILES 8 + +#define FIRST_QC_FILE_INDEX 1000 + +typedef struct { + char name[256]; + char *data; + int bufferlen; + int len; + int ofs; + int accessmode; + progfuncs_t *prinst; +} pf_fopen_files_t; +pf_fopen_files_t pf_fopen_files[MAX_QC_FILES]; + +void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name = PR_GetStringOfs(prinst, OFS_PARM0); + int fmode = G_FLOAT(OFS_PARM1); + int i; + + for (i = 0; i < MAX_QC_FILES; i++) + if (!pf_fopen_files[i].data) + break; + + if (i == MAX_QC_FILES) //too many already open + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + if (name[1] == ':' || //dos filename absolute path specified - reject. + strchr(name, '\\') || *name == '/' || //absolute path was given - reject + strstr(name, "..")) //someone tried to be cleaver. + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + Q_strncpyz(pf_fopen_files[i].name, va("data/%s", name), sizeof(pf_fopen_files[i].name)); + + pf_fopen_files[i].accessmode = fmode; + switch (fmode) + { + case 0: //read + pf_fopen_files[i].data = COM_LoadMallocFile(pf_fopen_files[i].name); + if (!pf_fopen_files[i].data) + { + Q_strncpyz(pf_fopen_files[i].name, name, sizeof(pf_fopen_files[i].name)); + pf_fopen_files[i].data = COM_LoadMallocFile(pf_fopen_files[i].name); + } + + if (pf_fopen_files[i].data) + { + G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; + pf_fopen_files[i].prinst = prinst; + } + else + G_FLOAT(OFS_RETURN) = -1; + + pf_fopen_files[i].bufferlen = pf_fopen_files[i].len = com_filesize; + pf_fopen_files[i].ofs = 0; + break; + case 1: //append + pf_fopen_files[i].data = COM_LoadMallocFile(pf_fopen_files[i].name); + pf_fopen_files[i].ofs = pf_fopen_files[i].bufferlen = pf_fopen_files[i].len = com_filesize; + if (pf_fopen_files[i].data) + { + G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; + pf_fopen_files[i].prinst = prinst; + break; + } + //file didn't exist - fall through + case 2: //write + pf_fopen_files[i].bufferlen = 8192; + pf_fopen_files[i].data = BZ_Malloc(pf_fopen_files[i].bufferlen); + pf_fopen_files[i].len = 0; + pf_fopen_files[i].ofs = 0; + G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; + pf_fopen_files[i].prinst = prinst; + break; + default: //bad + G_FLOAT(OFS_RETURN) = -1; + break; + } +} + +void PF_fclose_i (int fnum) +{ + if (fnum < 0 || fnum >= MAX_QC_FILES) + { + Con_Printf("PF_fclose: File out of range\n"); + return; //out of range + } + + if (!pf_fopen_files[fnum].data) + { + Con_Printf("PF_fclose: File is not open\n"); + return; //not open + } + + switch(pf_fopen_files[fnum].accessmode) + { + case 0: + BZ_Free(pf_fopen_files[fnum].data); + break; + case 1: + case 2: + COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); + BZ_Free(pf_fopen_files[fnum].data); + break; + } + pf_fopen_files[fnum].data = NULL; + pf_fopen_files[fnum].prinst = NULL; +} + +void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int fnum = G_FLOAT(OFS_PARM0)-FIRST_QC_FILE_INDEX; + + if (fnum < 0 || fnum >= MAX_QC_FILES) + { + Con_Printf("PF_fclose: File out of range\n"); + return; //out of range + } + + if (pf_fopen_files[fnum].prinst != prinst) + { + Con_Printf("PF_fclose: File is from wrong instance\n"); + return; //this just isn't ours. + } + + PF_fclose_i(fnum); +} + +void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char c, *s, *o, *max; + int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; + char pr_string_temp[4096]; + + *pr_string_temp = '\0'; + G_INT(OFS_RETURN) = 0; //EOF + if (fnum < 0 || fnum >= MAX_QC_FILES) + { + PR_BIError(prinst, "PF_fgets: File out of range\n"); + return; //out of range + } + + if (!pf_fopen_files[fnum].data) + { + PR_BIError(prinst, "PF_fgets: File is not open\n"); + return; //not open + } + + if (pf_fopen_files[fnum].prinst != prinst) + { + PR_BIError(prinst, "PF_fgets: File is from wrong instance\n"); + return; //this just isn't ours. + } + + //read up to the next \n, ignoring any \rs. + o = pr_string_temp; + max = o + MAXTEMPBUFFERLEN-1; + s = pf_fopen_files[fnum].data+pf_fopen_files[fnum].ofs; + while(*s) + { + c = *s++; + if (c == '\n') + break; + if (c == '\r') + continue; + + if (o == max) + break; + *o++ = c; + } + *o = '\0'; + + pf_fopen_files[fnum].ofs = s - pf_fopen_files[fnum].data; + + if (!pr_string_temp[0] && !*s) + G_INT(OFS_RETURN) = 0; //EOF + else + RETURN_TSTRING(pr_string_temp); +} + +void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; + char *msg = PF_VarString(prinst, 1, pr_globals); + int len = strlen(msg); + if (fnum < 0 || fnum >= MAX_QC_FILES) + { + Con_Printf("PF_fgets: File out of range\n"); + return; //out of range + } + + if (!pf_fopen_files[fnum].data) + { + Con_Printf("PF_fgets: File is not open\n"); + return; //not open + } + + if (pf_fopen_files[fnum].prinst != prinst) + { + Con_Printf("PF_fgets: File is from wrong instance\n"); + return; //this just isn't ours. + } + + if (pf_fopen_files[fnum].bufferlen < pf_fopen_files[fnum].ofs + len) + { + char *newbuf; + pf_fopen_files[fnum].bufferlen = pf_fopen_files[fnum].bufferlen*2 + len; + newbuf = BZF_Malloc(pf_fopen_files[fnum].bufferlen); + memcpy(newbuf, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); + BZ_Free(pf_fopen_files[fnum].data); + pf_fopen_files[fnum].data = newbuf; + } + + memcpy(pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, msg, len); + if (pf_fopen_files[fnum].len < pf_fopen_files[fnum].ofs + len) + pf_fopen_files[fnum].len = pf_fopen_files[fnum].ofs + len; + pf_fopen_files[fnum].ofs+=len; +} + +void PF_fcloseall (progfuncs_t *prinst) +{ + int i; + for (i = 0; i < MAX_QC_FILES; i++) + { + if (pf_fopen_files[i].prinst != prinst) + continue; + PF_fclose_i(i); + } +} + + +//DP_QC_WHICHPACK +void PF_whichpack (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *srcname = PR_GetStringOfs(prinst, OFS_PARM0); + flocation_t loc; + + if (FS_FLocateFile(srcname, FSLFRT_IFFOUND, &loc)) + { + RETURN_TSTRING(FS_WhichPackForLocation(&loc)); + } + else + { + G_INT(OFS_RETURN) = 0; //null/empty + } + +} + + +typedef struct prvmsearch_s { + int handle; + progfuncs_t *fromprogs; //share across menu/server + int entries; + char **names; + int *sizes; + + struct prvmsearch_s *next; +} prvmsearch_t; +prvmsearch_t *prvmsearches; +int prvm_nextsearchhandle; + +void search_close (progfuncs_t *prinst, int handle) +{ + int i; + prvmsearch_t *prev, *s; + + prev = NULL; + for (s = prvmsearches; s; ) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Handle wasn't valid with that progs\n"); + return; + } + if (prev) + prev->next = s->next; + else + prvmsearches = s->next; + + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s->names); + BZ_Free(s->sizes); + BZ_Free(s); + + return; + } + + prev = s; + s = s->next; + } +} +//a progs was closed... hunt down it's searches, and warn about any searches left open. +void search_close_progs(progfuncs_t *prinst, qboolean complain) +{ + int i; + prvmsearch_t *prev, *s; + + prev = NULL; + for (s = prvmsearches; s; ) + { + if (s->fromprogs == prinst) + { //close it down. + + if (complain) + Con_Printf("Warning: Progs search was still active\n"); + if (prev) + prev->next = s->next; + else + prvmsearches = s->next; + + for (i = 0; i < s->entries; i++) + { + BZ_Free(s->names[i]); + } + BZ_Free(s->names); + BZ_Free(s->sizes); + BZ_Free(s); + + if (prev) + s = prev->next; + else + s = prvmsearches; + continue; + } + + prev = s; + s = s->next; + } + + if (!prvmsearches) + prvm_nextsearchhandle = 0; //might as well. +} + +int search_enumerate(char *name, int fsize, void *parm) +{ + prvmsearch_t *s = parm; + + s->names = BZ_Realloc(s->names, ((s->entries+64)&~63) * sizeof(char*)); + s->sizes = BZ_Realloc(s->sizes, ((s->entries+64)&~63) * sizeof(int)); + s->names[s->entries] = BZ_Malloc(strlen(name)+1); + strcpy(s->names[s->entries], name); + s->sizes[s->entries] = fsize; + + s->entries++; + return true; +} + +//float search_begin(string pattern, float caseinsensitive, float quiet) = #74; +void PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ //< 0 for error, > 0 for handle. + char *pattern = PR_GetStringOfs(prinst, OFS_PARM0); +// qboolean caseinsensative = G_FLOAT(OFS_PARM1); +// qboolean quiet = G_FLOAT(OFS_PARM2); + prvmsearch_t *s; + + s = Z_Malloc(sizeof(*s)); + s->fromprogs = prinst; + s->handle = prvm_nextsearchhandle++; + + COM_EnumerateFiles(pattern, search_enumerate, s); + + if (s->entries==0) + { + BZ_Free(s); + G_FLOAT(OFS_RETURN) = -1; + return; + } + s->next = prvmsearches; + prvmsearches = s; + G_FLOAT(OFS_RETURN) = s->handle; +} +//void search_end(float handle) = #75; +void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + search_close(prinst, handle); +} +//float search_getsize(float handle) = #76; +void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + prvmsearch_t *s; + G_FLOAT(OFS_RETURN) = -1; + for (s = prvmsearches; s; s = s->next) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Handle wasn't valid with that progs\n"); + return; + } + + G_FLOAT(OFS_RETURN) = s->entries; + return; + } + } +} +//string search_getfilename(float handle, float num) = #77; +void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int handle = G_FLOAT(OFS_PARM0); + int num = G_FLOAT(OFS_PARM1); + prvmsearch_t *s; + G_INT(OFS_RETURN) = 0; + + for (s = prvmsearches; s; s = s->next) + { + if (s->handle == handle) + { //close it down. + if (s->fromprogs != prinst) + { + Con_Printf("Search handle wasn't valid with that progs\n"); + return; + } + + if (num < 0 || num >= s->entries) + return; + RETURN_TSTRING(s->names[num]); + return; + } + } + + Con_Printf("Search handle wasn't valid\n"); +} + +//closes filesystem type stuff for when a progs has stopped needing it. +void PR_fclose_progs (progfuncs_t *prinst) +{ + PF_fcloseall(prinst); + search_close_progs(prinst, true); +} + +//File access +//////////////////////////////////////////////////// +//Entities + +void PF_WasFreed (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + edict_t *ent; + ent = (edict_t*)G_EDICT(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = ent->isfree; +} + +void PF_num_for_edict (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + edict_t *ent; + ent = (edict_t*)G_EDICT(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = ent->entnum; +} + +void PF_edict_for_num(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + edict_t *ent; + ent = (edict_t*)EDICT_NUM(prinst, G_FLOAT(OFS_PARM0)); + + RETURN_EDICT(prinst, ent); +} + +//entity nextent(entity) +void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + edict_t *ent; + + i = G_EDICTNUM(prinst, OFS_PARM0); + while (1) + { + i++; + if (i == *prinst->parms->sv_num_edicts) + { + RETURN_EDICT(prinst, *prinst->parms->sv_edicts); + return; + } + ent = EDICT_NUM(prinst, i); + if (!ent->isfree) + { + RETURN_EDICT(prinst, ent); + return; + } + } +} + +//entity() spawn +void PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + struct edict_s *ed; + ed = ED_Alloc(prinst); + RETURN_EDICT(prinst, ed); +} + +//Entities +//////////////////////////////////////////////////// +//String functions + +//PF_dprint +void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + Con_DPrintf ("%s",PF_VarString(prinst, 0, pr_globals)); +} + +//PF_print +void PF_print (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + Con_Printf ("%s",PF_VarString(prinst, 0, pr_globals)); +} + +//FTE_STRINGS +//C style strncasecmp (compare first n characters - case insensative) +void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *a = PR_GetStringOfs(prinst, OFS_PARM0); + char *b = PR_GetStringOfs(prinst, OFS_PARM1); + float len = G_FLOAT(OFS_PARM2); + + G_FLOAT(OFS_RETURN) = strnicmp(a, b, len); +} + +//FTE_STRINGS +//C style strcasecmp (case insensative string compare) +void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *a = PR_GetStringOfs(prinst, OFS_PARM0); + char *b = PR_GetStringOfs(prinst, OFS_PARM1); + + G_FLOAT(OFS_RETURN) = stricmp(a, b); +} + +//FTE_STRINGS +//C style strncmp (compare first n characters - case sensative. Note that there is no strcmp provided) +void PF_strncmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *a = PR_GetStringOfs(prinst, OFS_PARM0); + char *b = PR_GetStringOfs(prinst, OFS_PARM1); + float len = G_FLOAT(OFS_PARM2); + + G_FLOAT(OFS_RETURN) = strncmp(a, b, len); +} + +//uses qw style \key\value strings +void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *info = PR_GetStringOfs(prinst, OFS_PARM0); + char *key = PR_GetStringOfs(prinst, OFS_PARM1); + + key = Info_ValueForKey(info, key); + + RETURN_TSTRING(key); +} + +//uses qw style \key\value strings +void PF_infoadd (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *info = PR_GetStringOfs(prinst, OFS_PARM0); + char *key = PR_GetStringOfs(prinst, OFS_PARM1); + char *value = PF_VarString(prinst, 2, pr_globals); + char temp[8192]; + + Q_strncpyz(temp, info, MAXTEMPBUFFERLEN); + + Info_SetValueForStarKey(temp, key, value, MAXTEMPBUFFERLEN); + + RETURN_TSTRING(temp); +} + +//string(float pad, string str1, ...) strpad +void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char destbuf[4096]; + char *dest = destbuf; + int pad = G_FLOAT(OFS_PARM0); + char *src = PF_VarString(prinst, 1, pr_globals); + + if (pad < 0) + { //pad left + pad = -pad - strlen(src); + if (pad>=MAXTEMPBUFFERLEN) + pad = MAXTEMPBUFFERLEN-1; + if (pad < 0) + pad = 0; + + Q_strncpyz(dest+pad, src, MAXTEMPBUFFERLEN-pad); + while(pad--) + { + pad--; + dest[pad] = ' '; + } + } + else + { //pad right + if (pad>=MAXTEMPBUFFERLEN) + pad = MAXTEMPBUFFERLEN-1; + pad -= strlen(src); + if (pad < 0) + pad = 0; + + Q_strncpyz(dest, src, MAXTEMPBUFFERLEN); + dest+=strlen(dest); + + while(pad-->0) + *dest++ = ' '; + *dest = '\0'; + } + + RETURN_TSTRING(destbuf); +} + +//part of PF_strconv +static int chrconv_number(int i, int base, int conv) +{ + i -= base; + switch (conv) + { + default: + case 5: + case 6: + case 0: + break; + case 1: + base = '0'; + break; + case 2: + base = '0'+128; + break; + case 3: + base = '0'-30; + break; + case 4: + base = '0'+128-30; + break; + } + return i + base; +} +//part of PF_strconv +static int chrconv_punct(int i, int base, int conv) +{ + i -= base; + switch (conv) + { + default: + case 0: + break; + case 1: + base = 0; + break; + case 2: + base = 128; + break; + } + return i + base; +} +//part of PF_strconv +static int chrchar_alpha(int i, int basec, int baset, int convc, int convt, int charnum) +{ + //convert case and colour seperatly... + + i -= baset + basec; + switch (convt) + { + default: + case 0: + break; + case 1: + baset = 0; + break; + case 2: + baset = 128; + break; + + case 5: + case 6: + baset = 128*((charnum&1) == (convt-5)); + break; + } + + switch (convc) + { + default: + case 0: + break; + case 1: + basec = 'a'; + break; + case 2: + basec = 'A'; + break; + } + return i + basec + baset; +} +//FTE_STRINGS +//bulk convert a string. change case or colouring. +void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int ccase = G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper + int redalpha = G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate + int rednum = G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate + unsigned char *string = PF_VarString(prinst, 3, pr_globals); + int len = strlen(string); + int i; + unsigned char resbuf[8192]; + unsigned char *result = resbuf; + + if (len >= MAXTEMPBUFFERLEN) + len = MAXTEMPBUFFERLEN-1; + + for (i = 0; i < len; i++, string++, result++) //should this be done backwards? + { + if (*string >= '0' && *string <= '9') //normal numbers... + *result = chrconv_number(*string, '0', rednum); + else if (*string >= '0'+128 && *string <= '9'+128) + *result = chrconv_number(*string, '0'+128, rednum); + else if (*string >= '0'+128-30 && *string <= '9'+128-30) + *result = chrconv_number(*string, '0'+128-30, rednum); + else if (*string >= '0'-30 && *string <= '9'-30) + *result = chrconv_number(*string, '0'-30, rednum); + + else if (*string >= 'a' && *string <= 'z') //normal numbers... + *result = chrchar_alpha(*string, 'a', 0, ccase, redalpha, i); + else if (*string >= 'A' && *string <= 'Z') //normal numbers... + *result = chrchar_alpha(*string, 'A', 0, ccase, redalpha, i); + else if (*string >= 'a'+128 && *string <= 'z'+128) //normal numbers... + *result = chrchar_alpha(*string, 'a', 128, ccase, redalpha, i); + else if (*string >= 'A'+128 && *string <= 'Z'+128) //normal numbers... + *result = chrchar_alpha(*string, 'A', 128, ccase, redalpha, i); + + else if ((*string & 127) < 16 || !redalpha) //special chars.. + *result = *string; + else if (*string < 128) + *result = chrconv_punct(*string, 0, redalpha); + else + *result = chrconv_punct(*string, 128, redalpha); + } + *result = '\0'; + + RETURN_TSTRING(((char*)resbuf)); +} + +//FTE_STRINGS +//returns a string containing one character per parameter (up to the qc max params of 8). +void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + + char string[16]; + for (i = 0; i < *prinst->callargc; i++) + string[i] = G_FLOAT(OFS_PARM0 + i*3); + string[i] = '\0'; + RETURN_TSTRING(string); +} + +//FTE_STRINGS +//returns character at position X +void PF_str2chr (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *instr = PR_GetStringOfs(prinst, OFS_PARM0); + int ofs = (*prinst->callargc>1)?G_FLOAT(OFS_PARM1):0; + + if (ofs < 0) + ofs = strlen(instr)+ofs; + + if (ofs && (ofs < 0 || ofs > strlen(instr))) + G_FLOAT(OFS_RETURN) = '\0'; + else + G_FLOAT(OFS_RETURN) = instr[ofs]; +} + +//FTE_STRINGS +//strstr, without generating a new string. Use in conjunction with FRIK_FILE's substring for more similar strstr. +void PF_strstrofs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *instr = PR_GetStringOfs(prinst, OFS_PARM0); + char *match = PR_GetStringOfs(prinst, OFS_PARM1); + + int firstofs = (*prinst->callargc>2)?G_FLOAT(OFS_PARM2):0; + + if (firstofs && (firstofs < 0 || firstofs > strlen(instr))) + { + G_FLOAT(OFS_RETURN) = -1; + return; + } + + match = strstr(instr+firstofs, match); + if (!match) + G_FLOAT(OFS_RETURN) = -1; + else + G_FLOAT(OFS_RETURN) = match - instr; +} + +//float(string input) stof +void PF_stof (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s; + + s = PR_GetStringOfs(prinst, OFS_PARM0); + + G_FLOAT(OFS_RETURN) = atof(s); +} + +//tstring(float input) ftos +void PF_ftos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float v; + char pr_string_temp[64]; + v = G_FLOAT(OFS_PARM0); + + if (v == (int)v) + sprintf (pr_string_temp, "%d",(int)v); + else if (pr_brokenfloatconvert.value) + sprintf (pr_string_temp, "%5.1f",v); + else + Q_ftoa (pr_string_temp, v); + RETURN_TSTRING(pr_string_temp); +} + +//tstring(integer input) itos +void PF_itos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int v; + char pr_string_temp[64]; + v = G_INT(OFS_PARM0); + + sprintf (pr_string_temp, "%d",v); + RETURN_TSTRING(pr_string_temp); +} + +//int(string input) stoi +void PF_stoi (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *input = PR_GetStringOfs(prinst, OFS_PARM0); + + G_INT(OFS_RETURN) = atoi(input); +} + +//tstring(integer input) htos +void PF_htos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + unsigned int v; + char pr_string_temp[64]; + v = G_INT(OFS_PARM0); + + sprintf (pr_string_temp, "%08x",v); + RETURN_TSTRING(pr_string_temp); +} + +//int(string input) stoh +void PF_stoh (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *input = PR_GetStringOfs(prinst, OFS_PARM0); + + G_INT(OFS_RETURN) = strtoul(input, NULL, 16); +} + +//vector(string s) stov = #117 +//returns vector value from a string +void PF_stov (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + char *s; + float *out; + + s = PF_VarString(prinst, 0, pr_globals); + out = G_VECTOR(OFS_RETURN); + out[0] = out[1] = out[2] = 0; + + if (*s == '\'') + s++; + + for (i = 0; i < 3; i++) + { + while (*s == ' ' || *s == '\t') + s++; + out[i] = atof (s); + if (!out[i] && *s != '-' && *s != '+' && (*s < '0' || *s > '9')) + break; // not a number + while (*s && *s != ' ' && *s !='\t' && *s != '\'') + s++; + if (*s == '\'') + break; + } +} + +//tstring(vector input) vtos +void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char pr_string_temp[64]; + //sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); + sprintf (pr_string_temp, "'%f %f %f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); + PR_TempString(prinst, pr_string_temp); + RETURN_TSTRING(pr_string_temp); +} + +#pragma message("this should use something more... less hacky") +void PF_forgetstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s=PR_GetStringOfs(prinst, OFS_PARM0); + s-=8; + if (((int *)s)[0] != PRSTR) + { + Con_Printf("QC tried to free a non allocated string: "); + Con_Printf("%s\n", s+8); //two prints, so that logged prints ensure the first is written. + (*prinst->pr_trace) = 1; + PR_StackTrace(prinst); + return; + } + ((int *)s)[0] = 0xabcd1234; + Z_TagFree(s); +} + +void PF_dupstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) //frik_file +{ + char *s, *in; + int len; + in = PF_VarString(prinst, 0, pr_globals); + len = strlen(in)+1; + s = Z_TagMalloc(len+8, Z_QC_TAG); + ((int *)s)[0] = PRSTR; + ((int *)s)[1] = len; + strcpy(s+8, in); + RETURN_SSTRING(s+8); +} + +//returns a section of a string as a tempstring +void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i, start, length; + char *s; + char string[4096]; + + s = PR_GetStringOfs(prinst, OFS_PARM0); + start = G_FLOAT(OFS_PARM1); + length = G_FLOAT(OFS_PARM2); + + if (start < 0) + start = strlen(s)-start; + if (length < 0) + length = strlen(s)-start+(length+1); + + if (start >= strlen(s) || length<=0 || !*s) + { + RETURN_TSTRING(""); + return; + } + + if (length >= MAXTEMPBUFFERLEN) + length = MAXTEMPBUFFERLEN-1; + + for (i = 0; i < start && *s; i++, s++) + ; + + for (i = 0; *s && i < length; i++, s++) + string[i] = *s; + string[i] = 0; + + RETURN_TSTRING(string); +} + +//string(string str1, string str2) strcat +void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char dest[4096]; + char *src = PF_VarString(prinst, 0, pr_globals); + Q_strncpyz(dest, src, MAXTEMPBUFFERLEN); + RETURN_TSTRING(dest); +} + +void PF_strlen(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = strlen(PR_GetStringOfs(prinst, OFS_PARM0)); +} + +//float(string input, string token) instr +void PF_instr (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *sub; + char *s1; + char *s2; + + s1 = PR_GetStringOfs(prinst, OFS_PARM0); + s2 = PF_VarString(prinst, 1, pr_globals); + + if (!s1 || !s2) + { + PR_BIError(prinst, "Null string in \"instr\"\n"); + return; + } + + sub = strstr(s1, s2); + + if (sub == NULL) + G_INT(OFS_RETURN) = 0; + else + RETURN_SSTRING(sub); //last as long as the original string +} + +//string(entity ent) etos = #65 +void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char s[64]; + snprintf (s, sizeof(s), "entity %i", G_EDICTNUM(prinst, OFS_PARM0)); + RETURN_TSTRING(s); +} + +//DP_QC_STRINGCOLORFUNCTIONS +// #476 float(string s) strlennocol - returns how many characters are in a string, minus color codes +void PF_strlennocol (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PR_GetStringOfs(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = COM_FunStringLength(in); +} + +//DP_QC_STRINGCOLORFUNCTIONS +// string (string s) strdecolorize - returns the passed in string with color codes stripped +void PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PR_GetStringOfs(prinst, OFS_PARM0); + char result[8192]; + unsigned long flagged[8192]; + COM_ParseFunString(in, flagged, sizeof(flagged)/sizeof(flagged[0])); + COM_DeFunString(flagged, result, sizeof(result), true); + + RETURN_TSTRING(result); +} + +//DP_QC_STRING_CASE_FUNCTIONS +void PF_strtolower (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PR_GetStringOfs(prinst, OFS_PARM0); + char result[8192]; + + Q_strncpyz(result, in, sizeof(result)); + strlwr(result); + + RETURN_TSTRING(result); +} + +//DP_QC_STRING_CASE_FUNCTIONS +void PF_strtoupper (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PR_GetStringOfs(prinst, OFS_PARM0); + char result[8192]; + + Q_strncpyz(result, in, sizeof(result)); + strupr(result); + + RETURN_TSTRING(result); +} + +//DP_QC_STRFTIME +void PF_strftime (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *in = PF_VarString(prinst, 1, pr_globals); + char result[8192]; + + time_t ctime; + struct tm *tm; + + ctime = time(NULL); + + if (G_FLOAT(OFS_PARM0)) + tm = localtime(&ctime); + else + tm = gmtime(&ctime); + strftime(result, sizeof(result), in, tm); + Q_strncpyz(result, in, sizeof(result)); + strupr(result); + + RETURN_TSTRING(result); +} + +//String functions +//////////////////////////////////////////////////// +//515's String functions + +struct strbuf { + progfuncs_t *prinst; + char **strings; + int used; + int allocated; +}; + +#define NUMSTRINGBUFS 16 +struct strbuf strbuflist[NUMSTRINGBUFS]; + +// #440 float() buf_create (DP_QC_STRINGBUFFERS) +void PF_buf_create (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + + int i; + + for (i = 0; i < NUMSTRINGBUFS; i++) + { + if (!strbuflist[i].prinst) + { + strbuflist[i].prinst = prinst; + strbuflist[i].used = 0; + strbuflist[i].allocated = 0; + strbuflist[i].strings = NULL; + G_FLOAT(OFS_RETURN) = i+1; + return; + } + } + G_FLOAT(OFS_RETURN) = 0; +} +// #441 void(float bufhandle) buf_del (DP_QC_STRINGBUFFERS) +void PF_buf_del (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + int bufno = G_FLOAT(OFS_PARM0)-1; + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + for (i = 0; i < strbuflist[bufno].used; i++) + Z_Free(strbuflist[bufno].strings[i]); + Z_Free(strbuflist[bufno].strings); + + strbuflist[bufno].strings = NULL; + strbuflist[bufno].used = 0; + strbuflist[bufno].allocated = 0; + + strbuflist[bufno].prinst = NULL; +} +// #442 float(float bufhandle) buf_getsize (DP_QC_STRINGBUFFERS) +void PF_buf_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + G_FLOAT(OFS_RETURN) = strbuflist[bufno].used; +} +// #443 void(float bufhandle_from, float bufhandle_to) buf_copy (DP_QC_STRINGBUFFERS) +void PF_buf_copy (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int buffrom = G_FLOAT(OFS_PARM0)-1; + int bufto = G_FLOAT(OFS_PARM1)-1; + + if ((unsigned int)buffrom >= NUMSTRINGBUFS) + return; + if (strbuflist[buffrom].prinst != prinst) + return; + + if ((unsigned int)bufto >= NUMSTRINGBUFS) + return; + if (strbuflist[bufto].prinst != prinst) + return; + + //codeme +} +// #444 void(float bufhandle, float sortpower, float backward) buf_sort (DP_QC_STRINGBUFFERS) +void PF_buf_sort (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + int sortpower = G_FLOAT(OFS_PARM1); + int backwards = G_FLOAT(OFS_PARM2); + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + //codeme +} +// #445 string(float bufhandle, string glue) buf_implode (DP_QC_STRINGBUFFERS) +void PF_buf_implode (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + char *glue = PR_GetStringOfs(prinst, OFS_PARM1); + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + //codeme + + RETURN_TSTRING(""); +} +// #446 string(float bufhandle, float string_index) bufstr_get (DP_QC_STRINGBUFFERS) +void PF_bufstr_get (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + int index = G_FLOAT(OFS_PARM1); + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + { + RETURN_CSTRING(""); + return; + } + if (strbuflist[bufno].prinst != prinst) + { + RETURN_CSTRING(""); + return; + } + + if (index >= strbuflist[bufno].used) + { + RETURN_CSTRING(""); + return; + } + + RETURN_TSTRING(strbuflist[bufno].strings[index]); +} +// #447 void(float bufhandle, float string_index, string str) bufstr_set (DP_QC_STRINGBUFFERS) +void PF_bufstr_set (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + int index = G_FLOAT(OFS_PARM1); + char *string = PR_GetStringOfs(prinst, OFS_PARM2); + int oldcount; + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + if (index >= strbuflist[bufno].allocated) + { + oldcount = strbuflist[bufno].allocated; + strbuflist[bufno].allocated = (index + 256); + strbuflist[bufno].strings = BZ_Realloc(strbuflist[bufno].strings, strbuflist[bufno].allocated*sizeof(char*)); + memset(strbuflist[bufno].strings+oldcount, 0, (strbuflist[bufno].allocated - oldcount) * sizeof(char*)); + } + strbuflist[bufno].strings[index] = Z_Malloc(strlen(string)+1); + strcpy(strbuflist[bufno].strings[index], string); + + if (index >= strbuflist[bufno].used) + strbuflist[bufno].used = index+1; +} +// #448 float(float bufhandle, string str, float order) bufstr_add (DP_QC_STRINGBUFFERS) +void PF_bufstr_add (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + char *string = PR_GetStringOfs(prinst, OFS_PARM1); + int order = G_FLOAT(OFS_PARM2); + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + //codeme + + G_FLOAT(OFS_RETURN) = 0; +} +// #449 void(float bufhandle, float string_index) bufstr_free (DP_QC_STRINGBUFFERS) +void PF_bufstr_free (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bufno = G_FLOAT(OFS_PARM0)-1; + int index = G_FLOAT(OFS_PARM1); + + if ((unsigned int)bufno >= NUMSTRINGBUFS) + return; + if (strbuflist[bufno].prinst != prinst) + return; + + //codeme +} + +//515's String functions +//////////////////////////////////////////////////// + +//float(float caseinsensitive, string s, ...) crc16 = #494 (DP_QC_CRC16) +void PF_crc16 (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int insens = G_FLOAT(OFS_PARM0); + char *str = PF_VarString(prinst, 1, pr_globals); + int len = strlen(str); + + if (insens) + G_FLOAT(OFS_RETURN) = QCRC_Block_AsLower(str, len); + else + G_FLOAT(OFS_RETURN) = QCRC_Block(str, len); +} + +// #510 string(string in) uri_escape = #510; +void PF_uri_escape (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s = PR_GetStringOfs(prinst, OFS_PARM0); + RETURN_TSTRING(s); +} + +// #511 string(string in) uri_unescape = #511; +void PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s = PR_GetStringOfs(prinst, OFS_PARM0); + RETURN_TSTRING(s); +} + +//////////////////////////////////////////////////// +//Console functions + +void PF_ArgC (progfuncs_t *prinst, struct globalvars_s *pr_globals) //85 //float() argc; +{ + G_FLOAT(OFS_RETURN) = Cmd_Argc(); +} + +//KRIMZON_SV_PARSECLIENTCOMMAND added these two. +void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 //void(string str) tokanize; +{ + Cmd_TokenizeString(PR_GetStringOfs(prinst, OFS_PARM0), false, true); + G_FLOAT(OFS_RETURN) = Cmd_Argc(); +} + +void PF_tokenizebyseparator (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + Cmd_TokenizePunctation(PR_GetStringOfs(prinst, OFS_PARM0), PR_GetStringOfs(prinst, OFS_PARM1)); + G_FLOAT(OFS_RETURN) = Cmd_Argc(); +} + +void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 //string(float num) argv; +{ + int i = G_FLOAT(OFS_PARM0); + if (i < 0) + { + PR_BIError(prinst, "pr_argv with i < 0"); + G_INT(OFS_RETURN) = 0; + return; + } + RETURN_TSTRING(Cmd_Argv(i)); +} + +//Console functions +//////////////////////////////////////////////////// +//Maths functions + +void PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float num; + + num = (rand ()&0x7fff) / ((float)0x7fff); + + G_FLOAT(OFS_RETURN) = num; +} + +//float(float number, float quantity) bitshift = #218; +void PF_bitshift(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int bitmask; + int shift; + + bitmask = G_FLOAT(OFS_PARM0); + shift = G_FLOAT(OFS_PARM1); + + if (shift < 0) + bitmask >>= shift; + else + bitmask <<= shift; + + G_FLOAT(OFS_RETURN) = bitmask; +} + +//float(float a, floats) min = #94 +void PF_min (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + float f; + + if (*prinst->callargc == 2) + { + G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + } + else if (*prinst->callargc >= 3) + { + f = G_FLOAT(OFS_PARM0); + for (i = 1; i < *prinst->callargc; i++) + { + if (G_FLOAT((OFS_PARM0 + i * 3)) < f) + f = G_FLOAT((OFS_PARM0 + i * 3)); + } + G_FLOAT(OFS_RETURN) = f; + } + else + PR_BIError(prinst, "PF_min: must supply at least 2 floats\n"); +} + +//float(float a, floats) max = #95 +void PF_max (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int i; + float f; + + if (*prinst->callargc == 2) + { + G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); + } + else if (*prinst->callargc >= 3) + { + f = G_FLOAT(OFS_PARM0); + for (i = 1; i < *prinst->callargc; i++) { + if (G_FLOAT((OFS_PARM0 + i * 3)) > f) + f = G_FLOAT((OFS_PARM0 + i * 3)); + } + G_FLOAT(OFS_RETURN) = f; + } + else + { + PR_BIError(prinst, "PF_min: must supply at least 2 floats\n"); + } +} + +//float(float minimum, float val, float maximum) bound = #96 +void PF_bound (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + if (G_FLOAT(OFS_PARM1) > G_FLOAT(OFS_PARM2)) + G_FLOAT(OFS_RETURN) = G_FLOAT(OFS_PARM2); + else if (G_FLOAT(OFS_PARM1) < G_FLOAT(OFS_PARM0)) + G_FLOAT(OFS_RETURN) = G_FLOAT(OFS_PARM0); + else + G_FLOAT(OFS_RETURN) = G_FLOAT(OFS_PARM1); +} + +void PF_Sin (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0)); +} +void PF_Cos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0)); +} +void PF_Sqrt (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0)); +} +void PF_pow (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); +} +void PF_asin (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = asin(G_FLOAT(OFS_PARM0)); +} +void PF_acos (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = acos(G_FLOAT(OFS_PARM0)); +} +void PF_atan (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = atan(G_FLOAT(OFS_PARM0)); +} +void PF_atan2 (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = atan2(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); +} +void PF_tan (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = tan(G_FLOAT(OFS_PARM0)); +} + +void PF_fabs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float v; + v = G_FLOAT(OFS_PARM0); + G_FLOAT(OFS_RETURN) = fabs(v); +} + +void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float f; + f = G_FLOAT(OFS_PARM0); + if (f > 0) + G_FLOAT(OFS_RETURN) = (int)(f + 0.5); + else + G_FLOAT(OFS_RETURN) = (int)(f - 0.5); +} + +void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); +} + +void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); +} + +//Maths functions +//////////////////////////////////////////////////// +//Vector functions + +//vector() randomvec = #91 +void PF_randomvector (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + vec3_t temp; + do + { + temp[0] = (rand() & 32767) * (2.0 / 32767.0) - 1.0; + temp[1] = (rand() & 32767) * (2.0 / 32767.0) - 1.0; + temp[2] = (rand() & 32767) * (2.0 / 32767.0) - 1.0; + } while (DotProduct(temp, temp) >= 1); + VectorCopy (temp, G_VECTOR(OFS_RETURN)); +} + +//float vectoyaw(vector) +void PF_vectoyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *value1; + float yaw; + + value1 = G_VECTOR(OFS_PARM0); + + if (value1[1] == 0 && value1[0] == 0) + yaw = 0; + else + { + yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); + if (yaw < 0) + yaw += 360; + } + + G_FLOAT(OFS_RETURN) = yaw; +} + +//float(vector) vlen +void PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *value1; + float newv; + + value1 = G_VECTOR(OFS_PARM0); + + newv = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; + newv = sqrt(newv); + + G_FLOAT(OFS_RETURN) = newv; +} + +//vector vectoangles(vector) +void PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *value1, *up; + float yaw, pitch, roll; + + value1 = G_VECTOR(OFS_PARM0); + if (*prinst->callargc >= 2) + up = G_VECTOR(OFS_PARM1); + else + up = NULL; + + + + if (value1[1] == 0 && value1[0] == 0) + { + yaw = 0; + if (value1[2] > 0) + { + pitch = 90; + yaw = up ? atan2(-up[1], -up[0]) : 0; + } + else + { + pitch = 270; + yaw = up ? atan2(up[1], up[0]) : 0; + } + roll = 0; + } + else + { + yaw = atan2(value1[1], value1[0]); + pitch = atan2(value1[2], sqrt (value1[0]*value1[0] + value1[1]*value1[1])); + + if (up) + { + vec_t cp = cos(pitch), sp = sin(pitch); + vec_t cy = cos(yaw), sy = sin(yaw); + vec3_t tleft, tup; + tleft[0] = -sy; + tleft[1] = cy; + tleft[2] = 0; + tup[0] = sp*cy; + tup[1] = sp*sy; + tup[2] = cp; + roll = -atan2(DotProduct(up, tleft), DotProduct(up, tup)); + } + else + roll = 0; + } + + pitch *= 180 / M_PI; + yaw *= 180 / M_PI; + roll *= 180 / M_PI; + if (pitch < 0) + pitch += 360; + if (yaw < 0) + yaw += 360; + if (roll < 0) + roll += 360; + G_FLOAT(OFS_RETURN+0) = pitch; + G_FLOAT(OFS_RETURN+1) = yaw; + G_FLOAT(OFS_RETURN+2) = roll; +} + +//vector normalize(vector) +void PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + float *value1; + vec3_t newvalue; + float newf; + + value1 = G_VECTOR(OFS_PARM0); + + newf = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; + newf = sqrt(newf); + + if (newf == 0) + newvalue[0] = newvalue[1] = newvalue[2] = 0; + else + { + newf = 1/newf; + newvalue[0] = value1[0] * newf; + newvalue[1] = value1[1] * newf; + newvalue[2] = value1[2] * newf; + } + + VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); +} + +//Vector functions +//////////////////////////////////////////////////// +//Progs internals + +void PF_Abort(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + prinst->AbortStack(prinst); +} + +//this func calls a function in annother progs +//it works in the same way as the above func, except that it calls by reference to a function, as opposed to by it's name +//used for entity function variables - not actually needed anymore +void PF_externrefcall (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int progsnum; + func_t f; + progsnum = G_PROG(OFS_PARM0); + f = G_INT(OFS_PARM1); + + (*prinst->pr_trace)++; //continue debugging. + PR_ExecuteProgram(prinst, f); +} + +void PF_externset (progfuncs_t *prinst, struct globalvars_s *pr_globals) //set a value in annother progs +{ + int n = G_PROG(OFS_PARM0); + int v = G_INT(OFS_PARM1); + char *varname = PF_VarString(prinst, 2, pr_globals); + eval_t *var; + + var = prinst->FindGlobal(prinst, varname, n); + + if (var) + var->_int = v; +} + +void PF_externvalue (progfuncs_t *prinst, struct globalvars_s *pr_globals) //return a value in annother progs +{ + int n = G_PROG(OFS_PARM0); + char *varname = PF_VarString(prinst, 1, pr_globals); + eval_t *var; + + var = prinst->FindGlobal(prinst, varname, n); + + if (var) + { + G_INT(OFS_RETURN+0) = ((int*)&var->_int)[0]; + G_INT(OFS_RETURN+1) = ((int*)&var->_int)[1]; + G_INT(OFS_RETURN+2) = ((int*)&var->_int)[2]; + } + else + G_INT(OFS_RETURN) = 0; +} + +void PF_externcall (progfuncs_t *prinst, struct globalvars_s *pr_globals) //this func calls a function in annother progs (by name) +{ + int progsnum; + char *funcname; + int i; + string_t failedst = G_INT(OFS_PARM1); + func_t f; + + progsnum = G_PROG(OFS_PARM0); + funcname = PR_GetStringOfs(prinst, OFS_PARM1); + + f = PR_FindFunction(prinst, funcname, progsnum); + if (f) + { + for (i = OFS_PARM0; i < OFS_PARM5; i+=3) + VectorCopy(G_VECTOR(i+(2*3)), G_VECTOR(i)); + + (*prinst->pr_trace)++; //continue debugging + PR_ExecuteProgram(prinst, f); + } + else if (!f) + { + f = PR_FindFunction(prinst, "MissingFunc", progsnum); + if (!f) + { + PR_BIError(prinst, "Couldn't find function %s", funcname); + return; + } + + for (i = OFS_PARM0; i < OFS_PARM6; i+=3) + VectorCopy(G_VECTOR(i+(1*3)), G_VECTOR(i)); + G_INT(OFS_PARM0) = failedst; + + (*prinst->pr_trace)++; //continue debugging + PR_ExecuteProgram(prinst, f); + } +} + +/* +pr_csqc.obj : error LNK2001: unresolved external symbol _ PR_BIError +*/ +void PF_traceon (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + (*prinst->pr_trace) = true; +} + +void PF_traceoff (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + (*prinst->pr_trace) = false; +} +void PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int size = 1024*1024*8; + char *buffer = BZ_Malloc(size); + prinst->save_ents(prinst, buffer, &size, 3); + COM_WriteFile("core.txt", buffer, size); + BZ_Free(buffer); +} +void PF_eprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int size = 1024*1024; + char *buffer = BZ_Malloc(size); + char *buf; + buf = prinst->saveent(prinst, buffer, &size, G_EDICT(prinst, OFS_PARM0)); + Con_Printf("Entity %i:\n%s\n", G_EDICTNUM(prinst, OFS_PARM0), buf); + BZ_Free(buffer); +} + +void PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +#ifdef SERVERONLY //new break code + char *s; + + //I would like some sort of network activity here, + //but I don't want to mess up the sequence and stuff + //It should be possible, but would mean that I would + //need to alter the client, or rewrite a bit of the server.. + + if (pr_globals) + Con_TPrintf(STL_BREAKSTATEMENT); + else if (developer.value!=2) + return; //non developers cann't step. + for(;;) + { + s=Sys_ConsoleInput(); + if (s) + { + if (!*s) + break; + else + Con_Printf("%s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, s)); + } + } +#elif defined(TEXTEDITOR) + (*prinst->pr_trace)++; +#else //old break code +Con_Printf ("break statement\n"); +*(int *)-4 = 0; // dump to debugger +// PR_RunError ("break statement"); +#endif +} + +void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *s; + + s = PF_VarString(prinst, 0, pr_globals); +/* Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s); + ed = PROG_TO_EDICT(pr_global_struct->self); + ED_Print (ed); +*/ + + PR_StackTrace(prinst); + + Con_Printf("%s\n", s); + + if (developer.value) + { +// SV_Error ("Program error: %s", s); + PF_break(prinst, pr_globals); + (*prinst->pr_trace) = 2; + } + else + { + PR_AbortStack(prinst); + PR_BIError (prinst, "Program error: %s", s); + } +} + +//Progs internals +//////////////////////////////////////////////////// +//System + +//Sends text over to the client's execution buffer +void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *str; + + str = PF_VarString(prinst, 0, pr_globals); + if (!strcmp(str, "host_framerate 0\n")) + Cbuf_AddText ("sv_mintic 0\n", RESTRICT_INSECURE); //hmm... do this better... + else + Cbuf_AddText (str, RESTRICT_INSECURE); +} + + + +/* +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_findchainflags +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_findchainfloat +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_findchain +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_cl_getkeybind +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_cl_stringtokeynum +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_cl_keynumtostring +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawresetcliparea +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawsetcliparea +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawfill +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawpic +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawstring +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawcharacter +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_free_pic +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawgetimagesize +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_precache_pic +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_is_cached_pic +pr_csqc.obj : error LNK2001: unresolved external symbol _PF_CL_drawline +pr_csqc.obj : error LNK2001: unresolved external symbol _checkfteextensionsv +pr_csqc.obj : error LNK2001: unresolved external symbol _checkextension +pr_csqc.obj : error LNK2001: unresolved external symbol _QCEditor +pr_csqc.obj : error LNK2001: unresolved external symbol _PR_CB_Free +pr_csqc.obj : error LNK2001: unresolved external symbol _PR_CB_Malloc +pr_csqc.obj : error LNK2001: unresolved external symbol _QC_WriteFile +pr_csqc.obj : error LNK2001: unresolved external symbol _MP_TranslateFTEtoDPCodes +*/ + + + + + +lh_extension_t QSG_Extensions[] = { + +//as a special hack, the first 32 entries are PEXT features. +//some of these are overkill yes, but they are all derived from the fteextensions flags and document the underlaying protocol available. +//(which is why there are two lists of extensions here) +//note: not all of these are actually supported. This list mearly reflects the values of the PEXT_ constants. +//Check protocol.h to make sure that the related PEXT is enabled. The engine will only accept if they are actually supported. + {"FTE_PEXT_SETVIEW"}, //nq setview works. + {"DP_ENT_SCALE"}, //entities may be rescaled + {"FTE_PEXT_LIGHTSTYLECOL"}, //lightstyles may have colours. + {"DP_ENT_ALPHA"}, //transparent entites + {"FTE_PEXT_VIEW2"}, //secondary view. + {"FTE_PEXT_BULLETENS"}, //bulleten boards (scrolling text on walls) + {"FTE_PEXT_ZLIBDL"}, //supposed download optimisation (unimportant to qc) + {"FTE_PEXT_LIGHTUPDATES"}, //zap.mdl is sent as a nail packet. + {"FTE_PEXT_FATNESS"}, //entities may be expanded along their vertex normals + {"DP_HALFLIFE_MAP"}, //entitiy can visit a hl bsp + {"FTE_PEXT_TE_BULLET"}, //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE + {"FTE_PEXT_HULLSIZE"}, //means we can tell a client to go to crouching hull + {"FTE_PEXT_MODELDBL"}, //max of 512 models + {"FTE_PEXT_ENTITYDBL"}, //max of 1024 ents + {"FTE_PEXT_ENTITYDBL2"}, //max of 2048 ents + {"FTE_PEXT_ORIGINDBL"}, //-8k to +8k map size. + {"FTE_PEXT_VWEAP"}, + {"FTE_PEXT_Q2BSP"}, //supports q2 maps. No bugs are apparent. + {"FTE_PEXT_Q3BSP"}, //quake3 bsp support. dp probably has an equivelent, but this is queryable per client. + {"DP_ENT_COLORMOD"}, + {NULL}, //splitscreen - not queryable. + {"FTE_HEXEN2"}, //client can use hexen2 maps. server can use hexen2 progs + {"FTE_PEXT_SPAWNSTATIC"}, //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatible - previous system failed with -1 skins) + {"FTE_PEXT_CUSTOMTENTS", 2, NULL, {"RegisterTempEnt", "CustomTempEnt"}}, + {"FTE_PEXT_256PACKETENTITIES"}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity). + {"FTE_PEXT_64PLAYERS"}, + {"TEI_SHOWLMP2", 6, NULL, {"showpic", "hidepic", "movepic", "changepic", "showpicent", "hidepicent"}}, //telejano doesn't actually export the moveent/changeent (we don't want to either cos it would stop frik_file stuff being autoregistered) + {"DP_GFX_QUAKE3MODELTAGS", 1, NULL, {"setattachment"}}, + {"FTE_PK3DOWNLOADS"}, + {"PEXT_CHUNKEDDOWNLOADS"}, + + {"EXT_CSQC_SHARED"}, //this is a separate extension because it requires protocol modifications. note: this is also the extension that extends the allowed stats. + + {NULL}, + + //{"EXT_CSQC"}, //this is the base csqc extension. I'm not sure what needs to be separate and what does not. + //{"EXT_CSQC_DELTAS"},//this is a separate extension because a: its slower thus optional. b: the feature may be banned in a league due to cheat protection. + +//the rest are generic extensions + {"??TOMAZ_STRINGS", 6, NULL, {"tq_zone", "tq_unzone", "tq_strcat", "tq_substring", "tq_stof", "tq_stov"}}, + {"??TOMAZ_FILE", 4, NULL, {"tq_fopen", "tq_fclose", "tq_fgets", "tq_fputs"}}, + {"??MVDSV_BUILTINS", 21, NULL, {"executecommand", "mvdtokenize", "mvdargc", "mvdargv", + "teamfield", "substr", "mvdstrcat", "mvdstrlen", "str2byte", + "str2short", "mvdnewstr", "mvdfreestr", "conprint", "readcmd", + "mvdstrcpy", "strstr", "mvdstrncpy", "log", "redirectcmd", + "mvdcalltimeofday", "forcedemoframe"}}, +//end of mvdsv +// Tomaz - QuakeC File System End + + {"BX_COLOREDTEXT"}, + {"DP_CON_SET"}, +#ifndef SERVERONLY + {"DP_CON_SETA"}, //because the server doesn't write configs. +#endif + {"DP_EF_BLUE"}, //hah!! This is QuakeWorld!!! + {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. + {"DP_EF_NODRAW"}, //implemented by sending it with no modelindex + {"DP_EF_RED"}, + {"DP_ENT_COLORMOD"}, + {"DP_ENT_EXTERIORMODELTOCLIENT"}, + //only in dp6 currently {"DP_ENT_GLOW"}, + {"DP_ENT_VIEWMODEL"}, + {"DP_GECKO_SUPPORT", 7, NULL, {"gecko_create", "gecko_destroy", "gecko_navigate", "gecko_keyevent", "gecko_mousemove", "gecko_resize", "gecko_get_texture_extent"}}, + {"DP_GFX_QUAKE3MODELTAGS"}, + {"DP_GFX_SKINFILES"}, + {"DP_GFX_SKYBOX"}, //according to the spec. :) + {"DP_HALFLIFE_MAP_CVAR"}, + //to an extend {"DP_HALFLIFE_SPRITE"}, + {"DP_INPUTBUTTONS"}, + {"DP_LITSUPPORT"}, + {"DP_MONSTERWALK"}, + {"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support. + {"DP_MOVETYPEFOLLOW"}, + {"DP_QC_ASINACOSATANATAN2TAN", 5, NULL, {"asin", "acos", "atan", "atan2", "tan"}}, + {"DP_QC_CHANGEPITCH", 1, NULL, {"changepitch"}}, + {"DP_QC_COPYENTITY", 1, NULL, {"copyentity"}}, + {"DP_QC_CRC16", 1, NULL, {"crc16"}}, + {"DP_QC_CVAR_DEFSTRING", 1, NULL, {"cvar_defstring"}}, + {"DP_QC_CVAR_STRING", 1, NULL, {"dp_cvar_string"}}, //448 builtin. + {"DP_QC_CVAR_TYPE", 1, NULL, {"cvar_type"}}, + {"DP_QC_EDICT_NUM", 1, NULL, {"edict_num"}}, + {"DP_QC_ENTITYDATA", 5, NULL, {"numentityfields", "entityfieldname", "entityfieldtype", "getentityfieldstring", "putentityfieldstring"}}, + {"DP_QC_ETOS", 1, NULL, {"etos"}}, + {"DP_QC_FINDCHAIN", 1, NULL, {"findchain"}}, + {"DP_QC_FINDCHAINFLOAT", 1, NULL, {"findchainfloat"}}, + {"DP_QC_FINDFLAGS", 1, NULL, {"findflags"}}, + {"DP_QC_FINDCHAINFLAGS", 1, NULL, {"findchainflags"}}, + {"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}}, + {"DP_QC_FS_SEARCH", 4, NULL, {"search_begin", "search_end", "search_getsize", "search_getfilename"}}, + {"DP_QC_GETSURFACEPOINTATTRIBUTE", 1, NULL, {"getsurfacepointattribute"}}, + {"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}}, + {"DP_QC_MULTIPLETEMPSTRINGS"}, + {"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, + {"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, + {"DP_QC_STRFTIME", 1, NULL, {"strftime"}}, + {"DP_QC_STRING_CASE_FUNCTIONS", 2, NULL, {"strtolower", "strtoupper"}}, + {"DP_QC_STRINGBUFFERS", 10, NULL, {"buf_create", "buf_del", "buf_getsize", "buf_copy", "buf_sort", "buf_implode", "bufstr_get", "bufstr_set", "bufstr_add", "bufstr_free"}}, + {"DP_QC_STRINGCOLORFUNCTIONS", 2, NULL, {"strlennocol", "strdecolorize"}}, + {"DP_QC_STRREPLACE", 2, NULL, {"strreplace", "strireplace"}}, + {"DP_QC_TOKENIZEBYSEPARATOR", 1, NULL, {"tokenizebyseparator"}}, + {"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}}, + {"DP_QC_TRACETOSS"}, + {"DP_QC_TRACE_MOVETYPE_HITMODEL"}, + {"DP_QC_TRACE_MOVETYPE_WORLDONLY"}, + {"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension... + {"DP_QC_UNLIMITEDTEMPSTRINGS"}, + {"DP_QC_URI_ESCAPE", 2, NULL, {"uri_escape", "uri_unescape"}}, + {"DP_QC_URI_GET", 1, NULL, {"uri_get"}}, + {"DP_QC_VECTOANGLES_WITH_ROLL"}, + {"DP_QC_VECTORVECTORS", 1, NULL, {"vectorvectors"}}, + {"DP_QC_WHICHPACK", 1, NULL, {"whichpack"}}, + {"DP_QUAKE2_MODEL"}, + {"DP_QUAKE2_SPRITE"}, + {"DP_QUAKE3_MODEL"}, + {"DP_REGISTERCVAR", 1, NULL, {"registercvar"}}, + {"DP_SND_STEREOWAV"}, + {"DP_SND_OGGVORBIS"}, + {"DP_SOLIDCORPSE"}, + {"DP_SPRITE32"}, //hmm... is it legal to advertise this one? + {"DP_SV_BOTCLIENT", 2, NULL, {"spawnclient", "clienttype"}}, + {"DP_SV_CLIENTCOLORS"}, + {"DP_SV_CLIENTNAME"}, + {"DP_SV_DRAWONLYTOCLIENT"}, + {"DP_SV_DROPCLIENT", 1, NULL, {"dropclient"}}, + {"DP_SV_EFFECT", 1, NULL, {"effect"}}, + {"DP_SV_EXTERIORMODELFORCLIENT"}, + {"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point. + {"DP_SV_PLAYERPHYSICS"}, + {"DP_SV_POINTSOUND", 1, NULL, {"pointsound"}}, + {"DP_SV_PRECACHEANYTIME"}, + {"DP_SV_SETCOLOR"}, + {"DP_SV_SPAWNFUNC_PREFIX"}, + {"DP_SV_WRITEPICTURE", 1, NULL, {"WritePicture"}}, + {"DP_SV_WRITEUNTERMINATEDSTRING", 1, NULL, {"WriteUnterminatedString"}}, + {"DP_TE_BLOOD", 1, NULL, {"te_blood"}}, + {"DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}}, + {"DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}}, + {"DP_TE_EXPLOSIONRGB"}, + {"DP_TE_FLAMEJET", 1, NULL, {"te_flamejet"}}, + {"DP_TE_PARTICLECUBE", 1, NULL, {"te_particlecube"}}, + //particlerain + //particlesnow + {"DP_TE_PLASMABURN", 1, NULL, {"te_plasmaburn"}}, + {"DP_TE_QUADEFFECTS1"}, + {"DP_TE_SMALLFLASH", 1, NULL, {"te_smallflash"}}, + {"DP_TE_SPARK", 1, NULL, {"te_spark"}}, + {"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", "te_teleport", "te_explosion2", "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}}, + {"DP_VIEWZOOM"}, + {"EXT_BITSHIFT", 1, NULL, {"bitshift"}}, + {"EXT_DIMENSION_VISIBILITY"}, + {"EXT_DIMENSION_PHYSICS"}, + {"EXT_DIMENSION_GHOST"}, + {"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, + {"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}}, + {"FTE_CSQC_HALFLIFE_MODELS"}, //hl-specific skeletal model control +//implementme {"FTE_CSQC_BASEFRAME"}, //control for all skeletal models + {"FTE_ENT_UNIQUESPAWNID"}, + {"FTE_EXTENDEDTEXTCODES"}, + {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, + {"FTE_GFX_QUAKE3SHADERS"}, + {"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}}, +#ifndef NOMEDIA + {"FTE_MEDIA_AVI"}, //playfilm supports avi files. + {"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files. + {"FTE_MEDIA_ROQ"}, //playfilm command supports q3 roq files +#endif + {"FTE_MULTIPROGS"}, //multiprogs functions are available. + {"FTE_MULTITHREADED", 3, NULL, {"sleep", "fork", "abort"}}, + {"FTE_MVD_PLAYBACK"}, +#ifdef SVCHAT + {"FTE_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested. +#endif + {"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}}, + {"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}}, + {"FTE_QC_PAUSED"}, + {"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}}, + {"FTE_QC_TRACETRIGGER"}, + {"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20) + +#ifdef SQL + // serverside SQL functions for managing an SQL database connection + {"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion", + "sqlreadfloat"}}, +#endif + //eperimental advanced strings functions. + //reuses the FRIK_FILE builtins (with substring extension) + {"FTE_STRINGS", 16, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone", + "strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp"}}, + {"FTE_SV_REENTER"}, + {"FTE_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", + "te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}}, + + {"KRIMZON_SV_PARSECLIENTCOMMAND", 3, NULL, {"clientcommand", "tokenize", "argv"}}, //very very similar to the mvdsv system. + {"NEH_CMD_PLAY2"}, + {"NEH_RESTOREGAME"}, + //{"PRYDON_CLIENTCURSOR"}, + {"QSG_CVARSTRING", 1, NULL, {"qsg_cvar_string"}}, + {"QW_ENGINE", 3, NULL, {"infokey", "stof", "logfrag"}}, //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ. + {"QWE_MVD_RECORD"}, //Quakeworld extended get the credit for this one. (mvdsv) + {"TEI_MD3_MODEL"}, +// {"TQ_RAILTRAIL"}, //treat this as the ZQ style railtrails which the client already supports, okay so the preparse stuff needs strengthening. + {"ZQ_MOVETYPE_FLY"}, + {"ZQ_MOVETYPE_NOCLIP"}, + {"ZQ_MOVETYPE_NONE"}, +// {"ZQ_QC_PARTICLE"}, //particle builtin works in QW ( we don't mimic ZQ fully though) + + + {"ZQ_QC_STRINGS", 7, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone"}} //a trimmed down FRIK_FILE. +}; +unsigned int QSG_Extensions_count = sizeof(QSG_Extensions)/sizeof(QSG_Extensions[0]); +#endif diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index ec4c0515b..e2fb3225b 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -1,3 +1,66 @@ +#include "progtype.h" +#include "progslib.h" + +#ifdef CLIENTONLY +typedef struct edict_s { + pbool isfree; + + float freetime; // realtime when the object was freed + unsigned int entnum; + pbool readonly; //causes error when QC tries writing to it. (quake's world entity) + void *v; +} edict_t; +#endif + +#define PF_cin_open PF_Fixme +#define PF_cin_close PF_Fixme +#define PF_cin_setstate PF_Fixme +#define PF_cin_getstate PF_Fixme +#define PF_cin_restart PF_Fixme +#define PF_drawline PF_Fixme +#define PF_drawcolorcodedstring PF_Fixme +#define PF_uri_get PF_Fixme +#define PF_strreplace PF_Fixme +#define PF_strireplace PF_Fixme +#define PF_gecko_create PF_Fixme +#define PF_gecko_destroy PF_Fixme +#define PF_gecko_navigate PF_Fixme +#define PF_gecko_keyevent PF_Fixme +#define PF_gecko_movemouse PF_Fixme +#define PF_gecko_resize PF_Fixme +#define PF_gecko_get_texture_extent PF_Fixme +#define PF_uri_get PF_Fixme + +#define PF_pointsound PF_Fixme +#define PF_getsurfacepointattribute PF_Fixme +#define PF_gecko_mousemove PF_Fixme +#define PF_numentityfields PF_Fixme +#define PF_entityfieldname PF_Fixme +#define PF_entityfieldtype PF_Fixme +#define PF_getentityfieldstring PF_Fixme +#define PF_putentityfieldstring PF_Fixme +#define PF_WritePicture PF_Fixme +#define PF_ReadPicture PF_Fixme + +#define G_PROG G_FLOAT + +//the lh extension system asks for a name for the extension. +//the ebfs version is a function that returns a builtin number. +//thus lh's system requires various builtins to exist at specific numbers. +typedef struct lh_extension_s { + char *name; + int numbuiltins; + qboolean *enabled; + char *builtinnames[21]; //extend freely +} lh_extension_t; + +extern lh_extension_t QSG_Extensions[]; +extern unsigned int QSG_Extensions_count; + +pbool QC_WriteFile(char *name, void *data, int len); +void *VARGS PR_CB_Malloc(int size); //these functions should be tracked by the library reliably, so there should be no need to track them ourselves. +void VARGS PR_CB_Free(void *mem); + void PF_InitTempStrings(progfuncs_t *prinst); string_t PR_TempString(progfuncs_t *prinst, char *str); //returns a tempstring containing str @@ -19,6 +82,7 @@ void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_tokenizebyseparator (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -45,6 +109,11 @@ void PF_min (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_max (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_pow (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_asin (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_acos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_atan (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_atan2 (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_tan (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -68,7 +137,15 @@ void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_WasFreed (progfuncs_t *prinst, struct globalvars_s *pr_globals); - +void PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_crc16 (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cvar_type (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_uri_escape (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_uri_unescape (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_itos (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_stoi (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_stoh (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_htos (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PR_fclose_progs (progfuncs_t *prinst); char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals); @@ -83,6 +160,7 @@ char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_glob void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...); void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cvar_setf (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_print (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -91,6 +169,7 @@ void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_ArgC (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -140,11 +219,17 @@ void PF_bitshift(progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_Abort(progfuncs_t *prinst, struct globalvars_s *pr_globals); -void PF_externcall (progfuncs_t *prinst, globalvars_t *pr_globals); -void PF_externrefcall (progfuncs_t *prinst, globalvars_t *pr_globals); -void PF_externvalue (progfuncs_t *prinst, globalvars_t *pr_globals); -void PF_externset (progfuncs_t *prinst, globalvars_t *pr_globals); -void PF_instr (progfuncs_t *prinst, globalvars_t *pr_globals); +void PF_externcall (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_externrefcall (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_externvalue (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_externset (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_instr (progfuncs_t *prinst, struct globalvars_s *pr_globals); + +void PF_strlennocol (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strtolower (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strtoupper (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_strftime (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_strstrofs (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_str2chr (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -157,6 +242,10 @@ void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_edict_for_num (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_num_for_edict (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cvar_defstring (progfuncs_t *prinst, struct globalvars_s *pr_globals); + //these functions are from pr_menu.dat void PF_CL_is_cached_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_precache_pic (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -169,8 +258,11 @@ void PF_CL_drawfill (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawsetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawresetcliparea (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_CL_drawgetimagesize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_CL_stringwidth (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_CL_drawsubpic (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_cl_keynumtostring (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_cl_findkeysforcommand (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_cl_stringtokeynum(progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_cl_getkeybind (progfuncs_t *prinst, struct globalvars_s *pr_globals); @@ -180,8 +272,62 @@ void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_create (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_del (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_copy (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_sort (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_buf_implode (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_bufstr_get (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_bufstr_set (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_bufstr_add (progfuncs_t *prinst, struct globalvars_s *pr_globals); +void PF_bufstr_free (progfuncs_t *prinst, struct globalvars_s *pr_globals); + +void PF_whichpack (progfuncs_t *prinst, struct globalvars_s *pr_globals); void PF_fclose_progs (progfuncs_t *prinst); char *PF_VarString (progfuncs_t *prinst, int first, struct globalvars_s *pr_globals); int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **parms); +void PF_Common_RegisterCvars(void); + + + + +// edict->solid values +#define SOLID_NOT 0 // no interaction with other objects +#define SOLID_TRIGGER 1 // touch on edge, but not blocking +#define SOLID_BBOX 2 // touch on edge, block +#define SOLID_SLIDEBOX 3 // touch on edge, but not an onground +#define SOLID_BSP 4 // bsp clip, touch on edge, block +#define SOLID_PHASEH2 5 +#define SOLID_CORPSE 5 +#define SOLID_LADDER 20 //dmw. touch on edge, not blocking. Touching players have different physics. Otherwise a SOLID_TRIGGER + +#define DAMAGE_NO 0 +#define DAMAGE_YES 1 +#define DAMAGE_AIM 2 + +// edict->flags +#define FL_FLY 1 +#define FL_SWIM 2 +#define FL_GLIMPSE 4 +#define FL_CLIENT 8 +#define FL_INWATER 16 +#define FL_MONSTER 32 +#define FL_GODMODE 64 +#define FL_NOTARGET 128 +#define FL_ITEM 256 +#define FL_ONGROUND 512 +#define FL_PARTIALGROUND 1024 // not all corners are valid +#define FL_WATERJUMP 2048 // player jumping out of water + +#define FL_FINDABLE_NONSOLID 16384 //a cpqwsv feature +#define FL_MOVECHAIN_ANGLE 32768 // when in a move chain, will update the angle +#define FL_CLASS_DEPENDENT 2097152 + + + + + + diff --git a/engine/common/protocol.h b/engine/common/protocol.h index 004910ba0..c6a0320b4 100644 --- a/engine/common/protocol.h +++ b/engine/common/protocol.h @@ -254,6 +254,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcfte_updatestatstring 78 #define svcfte_updatestatfloat 79 +#define svcfte_trailparticles 80 // [short] entnum [short] effectnum [vector] start [vector] end +#define svcfte_pointparticles 81 // [short] effectnum [vector] start [vector] velocity [short] count +#define svcfte_pointparticles1 82 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 + + //DP extended svcs #define svcdp_downloaddata 50 @@ -264,6 +269,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #define svcdp_spawnbaseline2 55 #define svcdp_entities 57 #define svcdp_csqcentities 58 +#define svcdp_spawnstaticsound2 59 // [coord3] [short] samp [byte] vol [byte] aten +#define svcdp_trailparticles 60 // [short] entnum [short] effectnum [vector] start [vector] end +#define svcdp_pointparticles 61 // [short] effectnum [vector] start [vector] velocity [short] count +#define svcdp_pointparticles1 62 // [short] effectnum [vector] start, same as svc_pointparticles except velocity is zero and count is 1 @@ -323,6 +332,7 @@ enum clcq2_ops_e #define clc_tmove 6 // teleport request, spectator only #define clc_upload 7 // teleport request, spectator only +#define clcdp_ackframe 50 #define clcdp_ackdownloaddata 51 @@ -349,12 +359,11 @@ enum clcq2_ops_e (1<<13)) +#ifdef PEXT_HULLSIZE +#define PF_HULLSIZE_Z (1<<14) +#endif #define PF_EXTRA_PFS (1<<15) -//FIXME: Resolve this. - -// bits 11..13 are player move type bits - #ifdef PEXT_SCALE #define PF_SCALE_Z (1<<16) #endif @@ -364,9 +373,6 @@ enum clcq2_ops_e #ifdef PEXT_FATNESS #define PF_FATNESS_Z (1<<18) #endif -#ifdef PEXT_HULLSIZE -#define PF_HULLSIZE_Z (1<<14) -#endif #define PF_COLOURMOD (1<<19) @@ -761,6 +767,8 @@ typedef struct usercmd_s //freestyle qbyte weapon; int servertime; + float fservertime; + float fclienttime; } usercmd_t; typedef struct q2usercmd_s diff --git a/engine/common/q3common.c b/engine/common/q3common.c index b5a59312a..fefb0c881 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -1656,6 +1656,7 @@ void MSG_Q3_ReadDeltaUsercmd(int key, const usercmd_t *from, usercmd_t *to) to->servertime = MSG_ReadBits(8) + from->servertime; else to->servertime = MSG_ReadBits(32); + to->msec = to->servertime - from->servertime; if (!MSG_ReadBits(1)) { @@ -1674,9 +1675,10 @@ void MSG_Q3_ReadDeltaUsercmd(int key, const usercmd_t *from, usercmd_t *to) to->angles[0] = MSG_ReadDeltaKey(key, from->angles[0], 16); to->angles[1] = MSG_ReadDeltaKey(key, from->angles[1], 16); to->angles[2] = MSG_ReadDeltaKey(key, from->angles[2], 16); - to->forwardmove = MSG_ReadDeltaKey(key, from->forwardmove, 8); - to->sidemove = MSG_ReadDeltaKey(key, from->sidemove, 8); - to->upmove = MSG_ReadDeltaKey(key, from->upmove, 8); + //yeah, this is messy + to->forwardmove = (signed char)(unsigned char)MSG_ReadDeltaKey(key, (unsigned char)(signed char)from->forwardmove, 8); + to->sidemove = (signed char)(unsigned char)MSG_ReadDeltaKey(key, (unsigned char)(signed char)from->sidemove, 8); + to->upmove = (signed char)(unsigned char)MSG_ReadDeltaKey(key, (unsigned char)(signed char)from->upmove, 8); to->buttons = MSG_ReadDeltaKey(key, from->buttons, 16); to->weapon = MSG_ReadDeltaKey(key, from->weapon, 8); } diff --git a/engine/common/qvm.c b/engine/common/qvm.c index d91c2b053..543570290 100644 --- a/engine/common/qvm.c +++ b/engine/common/qvm.c @@ -236,6 +236,7 @@ void Sys_UnloadDLL(void *handle) // ------------------------- * QVM files * ------------------------- #define VM_MAGIC 0x12721444 +#define VM_MAGIC2 0x12721445 #define LL(x) x = LittleLong(x) #pragma pack(push,1) @@ -252,6 +253,9 @@ typedef struct vmHeader_s int dataLength; // should be byteswapped on load int litLength; // copy as is int bssLength; // zero filled memory appended to datalength + + //valid only in V2. + int jtrgLength; // number of jump table targets } vmHeader_t; #pragma pack(pop) @@ -418,8 +422,15 @@ qvm_t *QVM_Load(const char *name, sys_callqvm_t syscall) LL(header->litLength); LL(header->bssLength); + if (header->vmMagic==VM_MAGIC2) + { //version2 cotains a jump table of sorts + //it is redundant information and can be ignored + //its also more useful for jit rather than bytecode + LL(header->jtrgLength); + } + // check file - if(header->vmMagic!=VM_MAGIC || header->instructionCount<=0 || header->codeLength<=0) + if(header->vmMagic!=VM_MAGIC && header->vmMagic!=VM_MAGIC2 || header->instructionCount<=0 || header->codeLength<=0) { Con_Printf("%s: invalid qvm file\n", name); BZ_Free(raw); diff --git a/engine/common/sys.h b/engine/common/sys.h index fcb932e4b..6f1c9145e 100644 --- a/engine/common/sys.h +++ b/engine/common/sys.h @@ -55,6 +55,14 @@ void VARGS Sys_Printf (char *fmt, ...); void Sys_Quit (void); +typedef struct { + void **funcptr; + char *name; +} dllfunction_t; +typedef void *dllhandle_t; +dllhandle_t *Sys_LoadLibrary(char *name, dllfunction_t *funcs); +void Sys_CloseLibrary(dllhandle_t *lib); + unsigned int Sys_Milliseconds (void); double Sys_DoubleTime (void); diff --git a/engine/common/world.h b/engine/common/world.h index dcdf379b7..6d3d3f89d 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -85,8 +85,6 @@ typedef struct q2trace_s struct edict_s *ent; // not set by CM_*() functions } q2trace_t; -#ifndef CLIENTONLY - #define MOVE_NORMAL 0 #define MOVE_NOMONSTERS 1 #define MOVE_MISSILE 2 @@ -107,6 +105,7 @@ typedef struct areanode_s #define AREA_DEPTH 4 #define AREA_NODES 32 //pow(2, AREA_DEPTH+1) +#ifndef CLIENTONLY extern areanode_t sv_areanodes[AREA_NODES]; diff --git a/engine/common/zone.c b/engine/common/zone.c index bf8b5b05c..a46c729ad 100644 --- a/engine/common/zone.c +++ b/engine/common/zone.c @@ -81,7 +81,7 @@ zone_t *zone_head; void *zonelock; #endif -static void Z_DumpTree() +static void Z_DumpTree(void) { zone_t *zone; zone_t *nextlist; diff --git a/engine/d3d/d3d_draw.c b/engine/d3d/d3d_draw.c index 4f2cfef05..9c0cd3d85 100644 --- a/engine/d3d/d3d_draw.c +++ b/engine/d3d/d3d_draw.c @@ -98,7 +98,7 @@ static void Upload_Texture_32(LPDIRECTDRAWSURFACE7 surf, unsigned int *data, int surf->lpVtbl->Unlock(surf, NULL); } -void D3D_MipMap (qbyte *out, qbyte *in, int width, int height) +void D3D7_MipMap (qbyte *out, qbyte *in, int width, int height) { int i, j; @@ -117,7 +117,7 @@ void D3D_MipMap (qbyte *out, qbyte *in, int width, int height) } //create a basic shader from a 32bit image -void *D3D_LoadTexture_32(char *name, unsigned int *data, int width, int height, int flags) +void *D3D7_LoadTexture_32(char *name, unsigned int *data, int width, int height, int flags) { static unsigned char mipdata[(MAX_WIDTH/2)*(MAX_HEIGHT/2)][4]; @@ -159,7 +159,7 @@ void *D3D_LoadTexture_32(char *name, unsigned int *data, int width, int height, newsurf->lpVtbl->GetAttachedSurface(newsurf, &caps, &miptex); while (miptex) { - D3D_MipMap(mipdata, data, width, height); + D3D7_MipMap(mipdata, data, width, height); data = mipdata; width/=2; height/=2; @@ -176,7 +176,7 @@ void *D3D_LoadTexture_32(char *name, unsigned int *data, int width, int height, } //create a basic shader from an 8bit image with 24bit palette -void *D3D_LoadTexture_8_Pal24(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette, int transparentpix) +void *D3D7_LoadTexture_8_Pal24(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette, int transparentpix) { //just expands it to 32bpp and passes it on static unsigned char out[MAX_WIDTH*MAX_HEIGHT][4]; @@ -197,10 +197,10 @@ void *D3D_LoadTexture_8_Pal24(char *name, unsigned char *data, int width, int he } - return D3D_LoadTexture_32(name, (unsigned int*)out, width, height, flags); + return D3D7_LoadTexture_32(name, (unsigned int*)out, width, height, flags); } -void *D3D_LoadTexture_8_Pal32(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette) +void *D3D7_LoadTexture_8_Pal32(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette) { //just expands it to 32bpp and passes it on static unsigned char out[MAX_WIDTH*MAX_HEIGHT][4]; @@ -218,11 +218,11 @@ void *D3D_LoadTexture_8_Pal32(char *name, unsigned char *data, int width, int he } - return D3D_LoadTexture_32(name, (unsigned int*)out, width, height, flags); + return D3D7_LoadTexture_32(name, (unsigned int*)out, width, height, flags); } -void D3D_UnloadTexture(LPDIRECTDRAWSURFACE7 tex) +void D3D7_UnloadTexture(LPDIRECTDRAWSURFACE7 tex) { tex->lpVtbl->Release(tex); } @@ -253,7 +253,7 @@ static qbyte exptexture[16][16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; -void D3D_InitParticleTexture (void) +void D3D7_InitParticleTexture (void) { #define PARTICLETEXTURESIZE 64 int x,y; @@ -273,7 +273,7 @@ void D3D_InitParticleTexture (void) data[y*16+x][3] = exptexture[x][y]*255/9.0; } } - d3dexplosiontexture = D3D_LoadTexture_32("", (unsigned int*)data, 16, 16, TF_ALPHA|TF_NOTBUMPMAP|TF_NOMIPMAP); + d3dexplosiontexture = D3D7_LoadTexture_32("", (unsigned int*)data, 16, 16, TF_ALPHA|TF_NOTBUMPMAP|TF_NOMIPMAP); memset(data, 255, sizeof(data)); for (y = 0;y < PARTICLETEXTURESIZE;y++) @@ -288,7 +288,7 @@ void D3D_InitParticleTexture (void) } } - d3dballtexture = D3D_LoadTexture_32("", (unsigned int*)data, PARTICLETEXTURESIZE, PARTICLETEXTURESIZE, TF_ALPHA|TF_NOTBUMPMAP|TF_NOMIPMAP); + d3dballtexture = D3D7_LoadTexture_32("", (unsigned int*)data, PARTICLETEXTURESIZE, PARTICLETEXTURESIZE, TF_ALPHA|TF_NOTBUMPMAP|TF_NOMIPMAP); } @@ -299,7 +299,7 @@ void D3D_InitParticleTexture (void) -mpic_t *(D3D_Draw_SafePicFromWad) (char *name) +mpic_t *(D3D7_Draw_SafePicFromWad) (char *name) { LPDIRECTDRAWSURFACE7 *p; d3dcachepic_t *pic; @@ -333,13 +333,13 @@ mpic_t *(D3D_Draw_SafePicFromWad) (char *name) { *p = Mod_LoadReplacementTexture(pic->name, "wad", false, true, true); if (!*p) - *p = D3D_LoadTexture_8_Pal24(name, (unsigned char*)(qpic+1), qpic->width, qpic->height, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 255); + *p = D3D7_LoadTexture_8_Pal24(name, (unsigned char*)(qpic+1), qpic->width, qpic->height, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 255); } // Con_Printf("Fixme: D3D_Draw_SafePicFromWad\n"); return &pic->pic; } -mpic_t *(D3D_Draw_SafeCachePic) (char *path) +mpic_t *(D3D7_Draw_SafeCachePic) (char *path) { LPDIRECTDRAWSURFACE7 *p; d3dcachepic_t *pic; @@ -370,20 +370,20 @@ mpic_t *(D3D_Draw_SafeCachePic) (char *path) p = (LPDIRECTDRAWSURFACE7*)&pic->pic.data; *p = Mod_LoadReplacementTexture(pic->name, "gfx", false, true, true); if (!*p) - *p = D3D_LoadTexture_8_Pal24(path, (unsigned char*)(qpic+1), qpic->width, qpic->height, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 255); + *p = D3D7_LoadTexture_8_Pal24(path, (unsigned char*)(qpic+1), qpic->width, qpic->height, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 255); // Con_Printf("Fixme: D3D_Draw_SafeCachePic\n"); return &pic->pic; } -mpic_t *(D3D_Draw_CachePic) (char *path) +mpic_t *(D3D7_Draw_CachePic) (char *path) { mpic_t *pic; - pic = D3D_Draw_SafeCachePic(path); + pic = D3D7_Draw_SafeCachePic(path); if (!pic) Sys_Error("Couldn't load picture %s", path); return pic; } -void (D3D_Draw_ReInit) (void) +void (D3D7_Draw_ReInit) (void) { d3dmenu_numcachepics = 0; @@ -391,7 +391,7 @@ void (D3D_Draw_ReInit) (void) draw_chars_tex = Mod_LoadReplacementTexture("conchars", "gfx", false, true, true); if (!draw_chars_tex) - draw_chars_tex = D3D_LoadTexture_8_Pal24("conchars", draw_chars, 128, 128, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 0); + draw_chars_tex = D3D7_LoadTexture_8_Pal24("conchars", draw_chars, 128, 128, TF_NOMIPMAP|TF_ALPHA|TF_NOTBUMPMAP, host_basepal, 0); //now emit the conchars picture as if from a wad. @@ -402,17 +402,17 @@ void (D3D_Draw_ReInit) (void) d3dmenu_numcachepics++; - conback_tex = D3D_Draw_SafeCachePic("gfx/conback.lmp"); + conback_tex = D3D7_Draw_SafeCachePic("gfx/conback.lmp"); Plug_DrawReloadImages(); - D3D_InitParticleTexture(); + D3D7_InitParticleTexture(); } -void (D3D_Draw_Init) (void) +void (D3D7_Draw_Init) (void) { - D3D_Draw_ReInit(); + D3D7_Draw_ReInit(); } -void (D3D_Draw_Character) (int x, int y, unsigned int num) +void (D3D7_Draw_Character) (int x, int y, unsigned int num) { int row; int col; @@ -468,7 +468,7 @@ void (D3D_Draw_Character) (int x, int y, unsigned int num) pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dquadvert, 4, d3dquadindexes, 6, 0); } -void (D3D_Draw_ColouredCharacter) (int x, int y, unsigned int num) +void (D3D7_Draw_ColouredCharacter) (int x, int y, unsigned int num) { int row; int col; @@ -533,39 +533,39 @@ void (D3D_Draw_ColouredCharacter) (int x, int y, unsigned int num) pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dquadvert, 4, d3dquadindexes, 6, 0); } -void (D3D_Draw_String) (int x, int y, const qbyte *str) +void (D3D7_Draw_String) (int x, int y, const qbyte *str) { while(*str) { - D3D_Draw_Character(x, y, *str++); + D3D7_Draw_Character(x, y, *str++); x+=8; } } -void (D3D_Draw_Alt_String) (int x, int y, const qbyte *str) +void (D3D7_Draw_Alt_String) (int x, int y, const qbyte *str) { while(*str) { - D3D_Draw_Character(x, y, *str++ | 128); + D3D7_Draw_Character(x, y, *str++ | 128); x+=8; } } -void (D3D_Draw_Crosshair) (void) +void (D3D7_Draw_Crosshair) (void) { - D3D_Draw_Character(vid.width/2 - 4, vid.height/2 - 4, '+'); + D3D7_Draw_Character(vid.width/2 - 4, vid.height/2 - 4, '+'); } -void (D3D_Draw_DebugChar) (qbyte num) +void (D3D7_Draw_DebugChar) (qbyte num) { Sys_Error("D3D function not implemented\n"); } -void (D3D_Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *pic, qbyte *translation) +void (D3D7_Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *pic, qbyte *translation) { // Sys_Error("D3D function not implemented\n"); } -void (D3D_Draw_TileClear) (int x, int y, int w, int h) +void (D3D7_Draw_TileClear) (int x, int y, int w, int h) { // Sys_Error("D3D function not implemented\n"); } -void (D3D_Draw_Fill_I) (int x, int y, int w, int h, unsigned int imgcolour) +void (D3D7_Draw_Fill_I) (int x, int y, int w, int h, unsigned int imgcolour) { d3dquadvert[0].x = x; d3dquadvert[0].y = y; @@ -618,7 +618,7 @@ void (D3D_Draw_Fill_I) (int x, int y, int w, int h, unsigned int imgcolour) pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); } -void (D3D_Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b) +void (D3D7_Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b) { char colours[4]; colours[0] = b*255; @@ -626,34 +626,34 @@ void (D3D_Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float colours[2] = r*255; colours[3] = 255; - D3D_Draw_Fill_I(x, y, w, h, *(unsigned int*)colours); + D3D7_Draw_Fill_I(x, y, w, h, *(unsigned int*)colours); } -void (D3D_Draw_Fill) (int x, int y, int w, int h, int c) +void (D3D7_Draw_Fill) (int x, int y, int w, int h, unsigned int c) { - D3D_Draw_FillRGB(x, y, w, h, host_basepal[c*3+0]/255.0f, host_basepal[c*3+1]/255.0f, host_basepal[c*3+2]/255.0f); + D3D7_Draw_FillRGB(x, y, w, h, host_basepal[c*3+0]/255.0f, host_basepal[c*3+1]/255.0f, host_basepal[c*3+2]/255.0f); } -void (D3D_Draw_FadeScreen) (void) +void (D3D7_Draw_FadeScreen) (void) { // Sys_Error("D3D function not implemented\n"); } -void (D3D_Draw_BeginDisc) (void) +void (D3D7_Draw_BeginDisc) (void) { // Sys_Error("D3D function not implemented\n"); } -void (D3D_Draw_EndDisc) (void) +void (D3D7_Draw_EndDisc) (void) { // Sys_Error("D3D function not implemented\n"); } static int imgcolour; -void (D3D_Draw_Fill_Colours) (int x, int y, int w, int h) +void (D3D7_Draw_Fill_Colours) (int x, int y, int w, int h) { - D3D_Draw_Fill_I(x, y, w, h, imgcolour); + D3D7_Draw_Fill_I(x, y, w, h, imgcolour); } -void (D3D_Draw_Image) (float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic) +void (D3D7_Draw_Image) (float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic) { LPDIRECTDRAWSURFACE7 *p; if (!conback_tex) @@ -700,11 +700,11 @@ void (D3D_Draw_Image) (float x, float y, float w, float h, float s1, float t1 pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dquadvert, 4, d3dquadindexes, 6, 0); } -void (D3D_Draw_ScalePic) (int x, int y, int width, int height, mpic_t *pic) +void (D3D7_Draw_ScalePic) (int x, int y, int width, int height, mpic_t *pic) { - D3D_Draw_Image(x, y, width, height, 0, 0, 1, 1, pic); + D3D7_Draw_Image(x, y, width, height, 0, 0, 1, 1, pic); } -void (D3D_Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height) +void (D3D7_Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height) { float s, t; float sw, tw; @@ -715,21 +715,21 @@ void (D3D_Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int wi t = (float)srcy/pic->height; sw = (float)width/pic->width; tw = (float)height/pic->height; - D3D_Draw_Image(x, y, width, height, s, t, s+sw, t+tw, pic); + D3D7_Draw_Image(x, y, width, height, s, t, s+sw, t+tw, pic); } -void (D3D_Draw_TransPic) (int x, int y, mpic_t *pic) +void (D3D7_Draw_TransPic) (int x, int y, mpic_t *pic) { if (!pic) return; - D3D_Draw_Image(x, y, pic->width, pic->height, 0, 0, 1, 1, pic); + D3D7_Draw_Image(x, y, pic->width, pic->height, 0, 0, 1, 1, pic); } -void (D3D_Draw_Pic) (int x, int y, mpic_t *pic) +void (D3D7_Draw_Pic) (int x, int y, mpic_t *pic) { if (!pic) return; - D3D_Draw_Image(x, y, pic->width, pic->height, 0, 0, 1, 1, pic); + D3D7_Draw_Image(x, y, pic->width, pic->height, 0, 0, 1, 1, pic); } -void (D3D_Draw_ImageColours) (float r, float g, float b, float a) +void (D3D7_Draw_ImageColours) (float r, float g, float b, float a) { unsigned char *c = (unsigned char *)&imgcolour; @@ -739,35 +739,35 @@ void (D3D_Draw_ImageColours) (float r, float g, float b, float a) c[3] = a*255; } -void (D3D_Draw_ConsoleBackground) (int lines) +void (D3D7_Draw_ConsoleBackground) (int lines) { - D3D_Draw_ImageColours(1,1,1,1); - D3D_Draw_Image(0, 0, vid.width, lines, 0, 1 - (float)lines/vid.height, 1, 1, conback_tex); + D3D7_Draw_ImageColours(1,1,1,1); + D3D7_Draw_Image(0, 0, vid.width, lines, 0, 1 - (float)lines/vid.height, 1, 1, conback_tex); } -void (D3D_Draw_EditorBackground) (int lines) +void (D3D7_Draw_EditorBackground) (int lines) { - D3D_Draw_ConsoleBackground(lines); + D3D7_Draw_ConsoleBackground(lines); } -void (D3D_Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight) +void (D3D7_Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight) { mpic_t pic; LPDIRECTDRAWSURFACE7 *p; p = (LPDIRECTDRAWSURFACE7*)&pic.data; - *p = D3D_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); + *p = D3D7_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); - D3D_Set2D (); - D3D_Draw_ImageColours(1,1,1,1); + D3D7_Set2D (); + D3D7_Draw_ImageColours(1,1,1,1); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); - D3D_Draw_Image(0, 0, vid.width, vid.height, 0, 1, 1, 0, &pic); + D3D7_Draw_Image(0, 0, vid.width, vid.height, 0, 1, 1, 0, &pic); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); - D3D_UnloadTexture(*p); + D3D7_UnloadTexture(*p); } //input is bottom up... -void (D3D_Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight) +void (D3D7_Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight) { mpic_t pic; LPDIRECTDRAWSURFACE7 *p; @@ -776,29 +776,29 @@ void (D3D_Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight) pic.height = inheight; pic.flags = 0; p = (LPDIRECTDRAWSURFACE7*)&pic.data; - *p = D3D_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); + *p = D3D7_LoadTexture_32("", (unsigned int*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP); - D3D_Set2D (); - D3D_Draw_ImageColours(1,1,1,1); + D3D7_Set2D (); + D3D7_Draw_ImageColours(1,1,1,1); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); - D3D_Draw_Image(0, 0, vid.width, vid.height, 0, 0, 1, 1, &pic); + D3D7_Draw_Image(0, 0, vid.width, vid.height, 0, 0, 1, 1, &pic); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); - D3D_UnloadTexture(*p); + D3D7_UnloadTexture(*p); } //top down -void (D3D_Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette) +void (D3D7_Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette) { mpic_t pic; LPDIRECTDRAWSURFACE7 *p; p = (LPDIRECTDRAWSURFACE7*)&pic.data; - *p = D3D_LoadTexture_8_Pal24("", (unsigned char*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP, palette, 256); + *p = D3D7_LoadTexture_8_Pal24("", (unsigned char*)framedata, inwidth, inheight, TF_NOMIPMAP|TF_NOALPHA|TF_NOTBUMPMAP, palette, 256); - D3D_Set2D (); - D3D_Draw_ImageColours(1,1,1,1); + D3D7_Set2D (); + D3D7_Draw_ImageColours(1,1,1,1); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); - D3D_Draw_Image(0, 0, vid.width, vid.height, 0, 1, 1, 0, &pic); + D3D7_Draw_Image(0, 0, vid.width, vid.height, 0, 1, 1, 0, &pic); pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); - D3D_UnloadTexture(*p); + D3D7_UnloadTexture(*p); } //paletted topdown (framedata is 8bit indexes into palette) #endif diff --git a/engine/d3d/d3d_mesh.c b/engine/d3d/d3d_mesh.c index ce24ef2f3..a90e50f55 100644 --- a/engine/d3d/d3d_mesh.c +++ b/engine/d3d/d3d_mesh.c @@ -96,7 +96,7 @@ void d3d_GAliasFlushSkinCache(void) skincolourmapped.numbuckets = 0; } -static galiastexnum_t *D3D_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, entity_t *e) +static galiastexnum_t *D3D7_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, entity_t *e) { galiasskin_t *skins; galiastexnum_t *texnums; @@ -346,7 +346,7 @@ static galiastexnum_t *D3D_ChooseSkin(galiasinfo_t *inf, char *modelname, int su frac += fracstep; } } - texnums->base = D3D_LoadTexture_32 ("", pixels, scaled_width, scaled_height, 0); + texnums->base = D3D7_LoadTexture_32 ("", pixels, scaled_width, scaled_height, 0); /* texnums->base = texture_extension_number++; GL_Bind(texnums->base); qglTexImage2D (GL_TEXTURE_2D, 0, gl_solid_format, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); @@ -603,7 +603,7 @@ static void LotsOfLightDirectionHacks(entity_t *e, model_t *m, vec3_t lightaxis[ qboolean R_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int frame1, int frame2, float lerp, float alpha, float fg1time, float fg2time, qboolean nolightdir); //draws currententity -void D3D_DrawAliasModel(void) +void D3D7_DrawAliasModel(void) { mesh_t mesh; extern entity_t *currententity; @@ -676,9 +676,9 @@ if (e->flags & Q2RF_DEPTHHACK) for(i = 0;; i++) { - R_GAliasBuildMesh(&mesh, inf, e->frame, e->oldframe, e->lerpfrac, e->shaderRGBAf[3], e->frame1time, e->frame2time, 0); + R_GAliasBuildMesh(&mesh, inf, e->frame1, e->frame2, e->lerpfrac, e->shaderRGBAf[3], e->frame1time, e->frame2time, 0); - skin = D3D_ChooseSkin(inf, m->name, e->skinnum, e); + skin = D3D7_ChooseSkin(inf, m->name, e->skinnum, e); if (!skin) pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, NULL); else diff --git a/engine/d3d/d3d_rmain.c b/engine/d3d/d3d_rmain.c index 581ebbd71..de35bae11 100644 --- a/engine/d3d/d3d_rmain.c +++ b/engine/d3d/d3d_rmain.c @@ -1,7 +1,8 @@ #include "quakedef.h" #ifdef D3DQUAKE #include "d3dquake.h" -#include "glquake.h" +#include "glquake.h" +#include "renderque.h" extern mleaf_t *r_viewleaf, *r_oldviewleaf; extern mleaf_t *r_viewleaf2, *r_oldviewleaf2; @@ -25,19 +26,19 @@ entity_t *currententity; extern cvar_t gl_mindist; -void (D3D_R_DeInit) (void) +void (D3D7_R_DeInit) (void) { } -void (D3D_R_ReInit) (void) +void (D3D7_R_ReInit) (void) { } -void (D3D_R_Init) (void) +void (D3D7_R_Init) (void) { - D3D_R_ReInit(); + D3D7_R_ReInit(); } //most of this is a direct copy from gl -void (D3D_SetupFrame) (void) +void (D3D7_SetupFrame) (void) { mleaf_t *leaf; vec3_t temp; @@ -82,7 +83,7 @@ void (D3D_SetupFrame) (void) V_SetContentsColor (r_viewleaf->contents); } -void D3D_SetupViewPort(void) +void D3D7_SetupViewPort(void) { float screenaspect; int glwidth = vid.width, glheight=vid.height; @@ -92,7 +93,7 @@ void D3D_SetupViewPort(void) D3DVIEWPORT7 vport; - D3D_GetBufferSize(&glwidth, &glheight); + D3D7_GetBufferSize(&glwidth, &glheight); // // set up viewpoint @@ -305,7 +306,7 @@ struct { float wms, wmt; float lms, lmt; } worldvert[64]; -void D3D_DrawTextureChains(void) +void D3D7_DrawTextureChains(void) { texture_t *t; msurface_t *s; @@ -429,7 +430,7 @@ pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTUR pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); } -void D3D_BaseBModelTextures(entity_t *e) +void D3D7_BaseBModelTextures(entity_t *e) { texture_t *t; msurface_t *s; @@ -613,7 +614,7 @@ mspriteframe_t *R_GetSpriteFrame (entity_t *currententity) return pspriteframe; } */ -static void D3D_DrawSpriteModel (entity_t *e) +static void D3D7_DrawSpriteModel (entity_t *e) { vec3_t point; mspriteframe_t *frame; @@ -741,18 +742,18 @@ static void D3D_DrawSpriteModel (entity_t *e) //================================================================================== -void D3DR_DrawSprite(void *e, void *parm) +void D3D7R_DrawSprite(void *e, void *parm) { currententity = e; - D3D_DrawSpriteModel (currententity); + D3D7_DrawSpriteModel (currententity); // P_FlushRenderer(); } -qboolean D3D_ShouldDraw(void) +qboolean D3D7_ShouldDraw(void) { { if (currententity->flags & Q2RF_EXTERNALMODEL) @@ -768,7 +769,7 @@ qboolean D3D_ShouldDraw(void) } -void D3DR_DrawEntitiesOnList (void) +void D3D7R_DrawEntitiesOnList (void) { int i; @@ -780,14 +781,14 @@ void D3DR_DrawEntitiesOnList (void) { currententity = &cl_visedicts[i]; - if (!D3D_ShouldDraw()) + if (!D3D7_ShouldDraw()) continue; switch (currententity->rtype) { case RT_SPRITE: - RQ_AddDistReorder(D3DR_DrawSprite, currententity, NULL, currententity->origin); + RQ_AddDistReorder(D3D7R_DrawSprite, currententity, NULL, currententity->origin); continue; #ifdef Q3SHADERS case RT_BEAM: @@ -830,7 +831,7 @@ void D3DR_DrawEntitiesOnList (void) case mod_alias: // if (r_refdef.flags & Q2RDF_NOWORLDMODEL || !cl.worldmodel || cl.worldmodel->type != mod_brush || cl.worldmodel->fromgame == fg_doom) - D3D_DrawAliasModel (); + D3D7_DrawAliasModel (); break; #ifdef HALFLIFEMODELS @@ -841,11 +842,11 @@ void D3DR_DrawEntitiesOnList (void) case mod_brush: // if (!cl.worldmodel || cl.worldmodel->type != mod_brush || cl.worldmodel->fromgame == fg_doom) - D3D_BaseBModelTextures (currententity); + D3D7_BaseBModelTextures (currententity); break; case mod_sprite: - RQ_AddDistReorder(D3DR_DrawSprite, currententity, NULL, currententity->origin); + RQ_AddDistReorder(D3D7R_DrawSprite, currententity, NULL, currententity->origin); break; /* #ifdef TERRAIN @@ -870,7 +871,7 @@ void D3DR_DrawEntitiesOnList (void) } } -void D3D_DrawWorld(void) +void D3D7_DrawWorld(void) { RSpeedLocals(); entity_t ent; @@ -928,7 +929,7 @@ void D3D_DrawWorld(void) RSpeedEnd(RSPEED_WORLDNODE); TRACE(("dbg: calling PPL_DrawWorld\n")); // if (r_shadows.value >= 2 && gl_canstencil && gl_mtexable) - D3D_DrawTextureChains(); + D3D7_DrawTextureChains(); // else // DrawTextureChains (cl.worldmodel, 1, r_refdef.vieworg); @@ -939,7 +940,7 @@ void D3D_DrawWorld(void) } } -void D3D_R_RenderScene(void) +void D3D7_R_RenderScene(void) { if (!cl.worldmodel || (!cl.worldmodel->nodes && cl.worldmodel->type != mod_heightmap)) r_refdef.flags |= Q2RDF_NOWORLDMODEL; @@ -947,19 +948,501 @@ void D3D_R_RenderScene(void) if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { R_MarkLeaves (); // done here so we know if we're in water - D3D_DrawWorld (); // adds static entities to the list + D3D7_DrawWorld (); // adds static entities to the list } - D3DR_DrawEntitiesOnList (); + D3D7R_DrawEntitiesOnList (); P_DrawParticles(); } -void (D3D_R_RenderView) (void) +void (D3D7_R_RenderView) (void) { - D3D_SetupFrame(); - D3D_SetupViewPort(); + D3D7_SetupFrame(); + D3D7_SetupViewPort(); R_SetFrustum(); - D3D_R_RenderScene(); + D3D7_R_RenderScene(); } -#endif + + + + +#ifdef PSET_SCRIPT + +#include "particles.h" +#define TYPESONLY +#include "p_script.c" + +#define APPLYD3DBLEND(bm) \ + switch (bm) \ + { \ + case BM_ADD: \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE); \ + break; \ + case BM_SUBTRACT: \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR); \ + break; \ + case BM_BLENDCOLOUR: \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCCOLOR); \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCCOLOR); \ + break; \ + case BM_BLEND: \ + default: \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA); \ + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA); \ + break; \ + } + + +static part_type_t *lastgltype; +extern vec3_t pright, pup; +static float particletime; + +typedef struct d3dparticlevert_s { + float org[3]; + unsigned int colour; + float s, t; //these could actually be preinitialised +} d3dparticlevert_t; +static d3dparticlevert_t d3dparticlevert[4]; + +typedef struct d3dparticlevertut_s { + float org[3]; + unsigned int colour; +} d3dparticlevertut_t; +static d3dparticlevertut_t d3dparticlevertut[4]; + +static unsigned short d3dparticlevertindexes[] = +{ + 0, 1, 2, + 0, 2, 3 +}; + +static void D3D_DrawParticleBlob(particle_t *p, part_type_t *type) +{ + float scale; + float x; + float y; + unsigned int colour; + int cb, cg, cr, ca; + if (lastgltype != type) + { + lastgltype = type; + pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); + +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + + APPLYD3DBLEND(type->blendmode); + } + + scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1] + + (p->org[2] - r_origin[2])*vpn[2]; + scale = (scale*p->scale)*(type->invscalefactor) + p->scale * (type->scalefactor*250); + if (scale < 20) + scale = 0.25; + else + scale = 0.25 + scale * 0.001; + + cr = p->rgb[0]*255; + if (cr < 0) cr = 0; + if (cr > 255) cr = 255; + + cg = p->rgb[1]*255; + if (cg < 0) cg = 0; + if (cg > 255) cg = 255; + + cb = p->rgb[2]*255; + if (cb < 0) cb = 0; + if (cb > 255) cb = 255; + + ca = p->alpha*255; + if (ca < 0) ca = 0; + if (ca > 255) ca = 255; + + colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); + + if (p->angle) + { + x = sin(p->angle)*scale; + y = cos(p->angle)*scale; + } + else + { + x = 0; + y = scale; + } + d3dparticlevert[0].s = 0; + d3dparticlevert[0].t = 0; + d3dparticlevert[0].colour = colour; + d3dparticlevert[0].org[0] = p->org[0] - x*pright[0] - y*pup[0]; + d3dparticlevert[0].org[1] = p->org[1] - x*pright[1] - y*pup[1]; + d3dparticlevert[0].org[2] = p->org[2] - x*pright[2] - y*pup[2]; + + d3dparticlevert[1].s = 0; + d3dparticlevert[1].t = 1; + d3dparticlevert[1].colour = colour; + d3dparticlevert[1].org[0] = p->org[0] - y*pright[0] + x*pup[0]; + d3dparticlevert[1].org[1] = p->org[1] - y*pright[1] + x*pup[1]; + d3dparticlevert[1].org[2] = p->org[2] - y*pright[2] + x*pup[2]; + + d3dparticlevert[2].s = 1; + d3dparticlevert[2].t = 1; + d3dparticlevert[2].colour = colour; + d3dparticlevert[2].org[0] = p->org[0] + x*pright[0] + y*pup[0]; + d3dparticlevert[2].org[1] = p->org[1] + x*pright[1] + y*pup[1]; + d3dparticlevert[2].org[2] = p->org[2] + x*pright[2] + y*pup[2]; + + d3dparticlevert[3].s = 1; + d3dparticlevert[3].t = 0; + d3dparticlevert[3].colour = colour; + d3dparticlevert[3].org[0] = p->org[0] + y*pright[0] - x*pup[0]; + d3dparticlevert[3].org[1] = p->org[1] + y*pright[1] - x*pup[1]; + d3dparticlevert[3].org[2] = p->org[2] + y*pright[2] - x*pup[2]; + + pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); +} +static void D3D_DrawParticleSpark(particle_t *p, part_type_t *type) +{ + vec3_t v, crv, o2; + + unsigned int colour; + int cb, cg, cr, ca; + + if (lastgltype != type) + { + lastgltype = type; + pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); + +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + + APPLYD3DBLEND(type->blendmode); + } + + + cr = p->rgb[0]*255; + if (cr < 0) cr = 0; + if (cr > 255) cr = 255; + + cg = p->rgb[1]*255; + if (cg < 0) cg = 0; + if (cg > 255) cg = 255; + + cb = p->rgb[2]*255; + if (cb < 0) cb = 0; + if (cb > 255) cb = 255; + + ca = p->alpha*255; + if (ca < 0) ca = 0; + if (ca > 255) ca = 255; + + colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); + + + + + VectorSubtract(r_refdef.vieworg, p->org, v); + CrossProduct(v, p->vel, crv); + VectorNormalize(crv); + + VectorMA(p->org, -p->scale/2, crv, d3dparticlevert[0].org); + d3dparticlevert[0].s = 0; + d3dparticlevert[0].t = 0; + d3dparticlevert[0].colour = colour; + + VectorMA(p->org, p->scale/2, crv, d3dparticlevert[1].org); + d3dparticlevert[1].s = 0; + d3dparticlevert[1].t = 1; + d3dparticlevert[1].colour = colour; + + + VectorMA(p->org, 0.1, p->vel, o2); + + VectorSubtract(r_refdef.vieworg, o2, v); + CrossProduct(v, p->vel, crv); + VectorNormalize(crv); + + VectorMA(o2, p->scale/2, crv, d3dparticlevert[2].org); + d3dparticlevert[2].s = 1; + d3dparticlevert[2].t = 1; + d3dparticlevert[2].colour = colour; + + VectorMA(o2, -p->scale/2, crv, d3dparticlevert[3].org); + d3dparticlevert[3].s = 1; + d3dparticlevert[3].t = 0; + d3dparticlevert[3].colour = colour; + + + pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); +} +static void D3D_DrawParticleBeam(beamseg_t *b, part_type_t *type) +{ + vec3_t v; + vec3_t crv; + beamseg_t *c; + particle_t *p; + particle_t *q; + float ts; + + + unsigned int colour; + int cb, cg, cr, ca; + + if (lastgltype != type) + { + lastgltype = type; + pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, type->d3dtexture); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_MODULATE); + +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); +pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + + APPLYD3DBLEND(type->blendmode); + } + + + + + c = b->next; + q = c->p; + p = b->p; + + + cr = q->rgb[0]*255; + if (cr < 0) cr = 0; + if (cr > 255) cr = 255; + + cg = q->rgb[1]*255; + if (cg < 0) cg = 0; + if (cg > 255) cg = 255; + + cb = q->rgb[2]*255; + if (cb < 0) cb = 0; + if (cb > 255) cb = 255; + + ca = q->alpha*255; + if (ca < 0) ca = 0; + if (ca > 255) ca = 255; + + colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); + + + + + + c = b->next; + + q = c->p; + + p = b->p; + + VectorSubtract(r_refdef.vieworg, q->org, v); + VectorNormalize(v); + CrossProduct(c->dir, v, crv); + ts = c->texture_s*type->rotationstartmin + particletime*type->rotationmin; + + VectorMA(q->org, -q->scale, crv, d3dparticlevert[0].org); + d3dparticlevert[0].s = ts; + d3dparticlevert[0].t = 0; + d3dparticlevert[0].colour = colour; + + VectorMA(q->org, q->scale, crv, d3dparticlevert[1].org); + d3dparticlevert[1].s = ts; + d3dparticlevert[1].t = 1; + d3dparticlevert[1].colour = colour; + + + cr = p->rgb[0]*255; + if (cr < 0) cr = 0; + if (cr > 255) cr = 255; + + cg = p->rgb[1]*255; + if (cg < 0) cg = 0; + if (cg > 255) cg = 255; + + cb = p->rgb[2]*255; + if (cb < 0) cb = 0; + if (cb > 255) cb = 255; + + ca = p->alpha*255; + if (ca < 0) ca = 0; + if (ca > 255) ca = 255; + + colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); + + + VectorSubtract(r_refdef.vieworg, p->org, v); + VectorNormalize(v); + CrossProduct(b->dir, v, crv); // replace with old p->dir? + ts = b->texture_s*type->rotationstartmin + particletime*type->rotationmin; + + VectorMA(p->org, p->scale, crv, d3dparticlevert[2].org); + d3dparticlevert[2].s = ts; + d3dparticlevert[2].t = 1; + d3dparticlevert[2].colour = colour; + + VectorMA(p->org, -p->scale, crv, d3dparticlevert[3].org); + d3dparticlevert[3].s = ts; + d3dparticlevert[3].t = 0; + d3dparticlevert[3].colour = colour; + + + pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1, d3dparticlevert, 4, d3dparticlevertindexes, 6, 0); +} + +static void D3D_DrawParticleBeamUT(beamseg_t *b, part_type_t *type) +{ + vec3_t v; + vec3_t crv; + beamseg_t *c; + particle_t *p; + particle_t *q; + float ts; + + + unsigned int colour; + int cb, cg, cr, ca; + +// D3D_DrawParticleBeam(b, type); +// return; + + if (lastgltype != type) + { + lastgltype = type; + pD3DDev->lpVtbl->SetTexture(pD3DDev, 0, NULL); + pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2); + + pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); + + + APPLYD3DBLEND(type->blendmode); + } + + + + + c = b->next; + q = c->p; + p = b->p; + + + cr = q->rgb[0]*255; + if (cr < 0) cr = 0; + if (cr > 255) cr = 255; + + cg = q->rgb[1]*255; + if (cg < 0) cg = 0; + if (cg > 255) cg = 255; + + cb = q->rgb[2]*255; + if (cb < 0) cb = 0; + if (cb > 255) cb = 255; + + ca = q->alpha*255; + if (ca < 0) ca = 0; + if (ca > 255) ca = 255; + + colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); + + + + + + c = b->next; + + q = c->p; + + p = b->p; + + VectorSubtract(r_refdef.vieworg, q->org, v); + VectorNormalize(v); + CrossProduct(c->dir, v, crv); + ts = c->texture_s*type->rotationstartmin + particletime*type->rotationmin; + + VectorMA(q->org, -q->scale, crv, d3dparticlevertut[0].org); + d3dparticlevertut[0].colour = colour; + + VectorMA(q->org, q->scale, crv, d3dparticlevertut[1].org); + d3dparticlevertut[1].colour = colour; + + + cr = p->rgb[0]*255; + if (cr < 0) cr = 0; + if (cr > 255) cr = 255; + + cg = p->rgb[1]*255; + if (cg < 0) cg = 0; + if (cg > 255) cg = 255; + + cb = p->rgb[2]*255; + if (cb < 0) cb = 0; + if (cb > 255) cb = 255; + + ca = p->alpha*255; + if (ca < 0) ca = 0; + if (ca > 255) ca = 255; + + colour = (cb) | (cg<<8) | (cr << 16) | (ca << 24); + + + VectorSubtract(r_refdef.vieworg, p->org, v); + VectorNormalize(v); + CrossProduct(b->dir, v, crv); // replace with old p->dir? + ts = b->texture_s*type->rotationstartmin + particletime*type->rotationmin; + + VectorMA(p->org, p->scale, crv, d3dparticlevertut[2].org); + d3dparticlevertut[2].colour = colour; + + VectorMA(p->org, -p->scale, crv, d3dparticlevertut[3].org); + d3dparticlevertut[3].colour = colour; + + + pD3DDev->lpVtbl->DrawIndexedPrimitive(pD3DDev, D3DPT_TRIANGLELIST, D3DFVF_XYZ|D3DFVF_DIFFUSE, d3dparticlevertut, 4, d3dparticlevertindexes, 6, 0); +} + +qboolean D3D7_DrawParticles(float ptime) +{ + RSpeedLocals(); + + if (!pD3DDev) + return false; + + particletime = ptime; + + lastgltype = NULL; + PScript_DrawParticleTypes(D3D_DrawParticleBlob, D3D_DrawParticleSpark, D3D_DrawParticleSpark, D3D_DrawParticleSpark, D3D_DrawParticleBeam, D3D_DrawParticleBeamUT, NULL); + + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZWRITEENABLE, FALSE ); + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, FALSE ); + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE ); + + RSpeedRemark(); + RQ_RenderDistAndClear(); + RSpeedEnd(RSPEED_PARTICLESDRAW); + + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ZWRITEENABLE, TRUE ); + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHATESTENABLE, TRUE ); + pD3DDev->lpVtbl->SetRenderState(pD3DDev, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE ); + + pD3DDev->lpVtbl->SetTextureStageState(pD3DDev, 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + + return true; +} + +#endif +#endif \ No newline at end of file diff --git a/engine/d3d/d3d_rsurf.c b/engine/d3d/d3d_rsurf.c index e0868981a..23198996f 100644 --- a/engine/d3d/d3d_rsurf.c +++ b/engine/d3d/d3d_rsurf.c @@ -15,7 +15,7 @@ lightmapinfo_t **lightmap; -void D3D_BuildSurfaceDisplayList (msurface_t *fa) +void D3D7_BuildSurfaceDisplayList (msurface_t *fa) { int i, lindex, lnumverts; medge_t *pedges, *r_pedge; @@ -121,7 +121,7 @@ unsigned blocklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; unsigned greenblklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; unsigned blueblklights[MAX_LIGHTMAP_SIZE*MAX_LIGHTMAP_SIZE]; -void D3DR_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap *stainsrc, int shift) +void D3D7R_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap *stainsrc, int shift) { int smax, tmax; int t; @@ -983,7 +983,7 @@ store: -int D3DFillBlock (int texnum, int w, int h, int x, int y) +int D3D7FillBlock (int texnum, int w, int h, int x, int y) { int i, l; while (texnum >= numlightmaps) //allocate 4 more lightmap slots. not much memory usage, but we don't want any caps here. @@ -1100,7 +1100,7 @@ int D3D7_AllocBlock (int w, int h, int *x, int *y) } -void D3D_CreateSurfaceLightmap (msurface_t *surf, int shift) +void D3D7_CreateSurfaceLightmap (msurface_t *surf, int shift) { int smax, tmax; qbyte *base, *luxbase; stmap *stainbase; @@ -1122,7 +1122,7 @@ void D3D_CreateSurfaceLightmap (msurface_t *surf, int shift) } if (currentmodel->fromgame == fg_quake3) - D3DFillBlock(surf->lightmaptexturenum, smax, tmax, surf->light_s, surf->light_t); + D3D7FillBlock(surf->lightmaptexturenum, smax, tmax, surf->light_s, surf->light_t); else surf->lightmaptexturenum = D3D7_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t); base = lightmap[surf->lightmaptexturenum]->lightmaps; @@ -1134,7 +1134,7 @@ void D3D_CreateSurfaceLightmap (msurface_t *surf, int shift) stainbase = lightmap[surf->lightmaptexturenum]->stainmaps; stainbase += (surf->light_t * LMBLOCK_WIDTH + surf->light_s) * 3; - D3DR_BuildLightMap (surf, base, luxbase, stainbase, shift); + D3D7R_BuildLightMap (surf, base, luxbase, stainbase, shift); } @@ -1237,7 +1237,7 @@ dynamic: luxbase += fa->light_t * LMBLOCK_WIDTH * lightmap_bytes + fa->light_s * lightmap_bytes; stainbase = lightmap[fa->lightmaptexturenum]->stainmaps; stainbase += (fa->light_t * LMBLOCK_WIDTH + fa->light_s) * 3; - D3DR_BuildLightMap (fa, base, luxbase, stainbase, shift); + D3D7R_BuildLightMap (fa, base, luxbase, stainbase, shift); RSpeedEnd(RSPEED_DYNAMIC); } @@ -1245,7 +1245,7 @@ dynamic: -LPDIRECTDRAWSURFACE7 D3D_NewLightmap(void) +LPDIRECTDRAWSURFACE7 D3D7_NewLightmap(void) { DWORD tflags = D3DX_TEXTURE_NOMIPMAP; //for now DWORD twidth = LMBLOCK_WIDTH; @@ -1261,7 +1261,7 @@ LPDIRECTDRAWSURFACE7 D3D_NewLightmap(void) return newsurf; } -void D3D_BuildLightmaps (void) +void D3D7_BuildLightmaps (void) { DDSURFACEDESC2 desc; @@ -1321,11 +1321,11 @@ void D3D_BuildLightmaps (void) for (i=0 ; inumsurfaces ; i++) { - D3D_CreateSurfaceLightmap (m->surfaces + i, shift); + D3D7_CreateSurfaceLightmap (m->surfaces + i, shift); P_EmitSkyEffectTris(m, &m->surfaces[i]); if (m->surfaces[i].mesh) //there are some surfaces that have a display list already (the subdivided ones) continue; - D3D_BuildSurfaceDisplayList (m->surfaces + i); + D3D7_BuildSurfaceDisplayList (m->surfaces + i); } } @@ -1344,7 +1344,7 @@ void D3D_BuildLightmaps (void) if (!lightmap_d3dtextures[i]) { - lightmap_d3dtextures[i] = D3D_NewLightmap(); + lightmap_d3dtextures[i] = D3D7_NewLightmap(); if (!lightmap_d3dtextures[i]) { diff --git a/engine/d3d/d3dquake.h b/engine/d3d/d3dquake.h index b4903cf87..fc995dbf2 100644 --- a/engine/d3d/d3dquake.h +++ b/engine/d3d/d3dquake.h @@ -10,9 +10,9 @@ #include "d3dx.h" #include "glquake.h" -void *D3D_LoadTexture_32(char *name, unsigned int *data, int width, int height, int flags); -void *D3D_LoadTexture_8_Pal24(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette, int transparentpix); -void *D3D_LoadTexture_8_Pal32(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette); +void *D3D7_LoadTexture_32(char *name, unsigned int *data, int width, int height, int flags); +void *D3D7_LoadTexture_8_Pal24(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette, int transparentpix); +void *D3D7_LoadTexture_8_Pal32(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette); /* #define D3D9_LoadTexture8Pal32(skinname,width,height,data,palette,usemips,alpha) (int)D3D9_LoadTexture_8_Pal32(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, host_basepal) #define D3D9_LoadTexture(skinname,width,height,data,usemips,alpha) (int)D3D9_LoadTexture_8_Pal24(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, host_basepal, 255) @@ -30,10 +30,10 @@ void *D3D9_LoadTexture_8_Pal24(char *name, unsigned char *data, int width, int h void *D3D9_LoadTexture_8_Pal32(char *name, unsigned char *data, int width, int height, int flags, unsigned char *palette); -#define D3D_LoadTexture8Pal32(skinname,width,height,data,palette,usemips,alpha) (int)(pD3DDev?D3D_LoadTexture_8_Pal32:D3D9_LoadTexture_8_Pal32)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, palette) -#define D3D_LoadTexture8Pal24(skinname,width,height,data,palette,usemips,alpha) (int)(pD3DDev?D3D_LoadTexture_8_Pal24:D3D9_LoadTexture_8_Pal24)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, palette, 255) -#define D3D_LoadTexture(skinname,width,height,data,usemips,alpha) (int)(pD3DDev?D3D_LoadTexture_8_Pal24:D3D9_LoadTexture_8_Pal24)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, host_basepal, 255) -#define D3D_LoadTexture32(skinname,width,height,data,usemips,alpha) (int)(pD3DDev?D3D_LoadTexture_32:D3D9_LoadTexture_32)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP) +#define D3D_LoadTexture8Pal32(skinname,width,height,data,palette,usemips,alpha) (int)(pD3DDev?D3D7_LoadTexture_8_Pal32:D3D9_LoadTexture_8_Pal32)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, palette) +#define D3D_LoadTexture8Pal24(skinname,width,height,data,palette,usemips,alpha) (int)(pD3DDev?D3D7_LoadTexture_8_Pal24:D3D9_LoadTexture_8_Pal24)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, palette, 255) +#define D3D_LoadTexture(skinname,width,height,data,usemips,alpha) (int)(pD3DDev?D3D7_LoadTexture_8_Pal24:D3D9_LoadTexture_8_Pal24)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP, host_basepal, 255) +#define D3D_LoadTexture32(skinname,width,height,data,usemips,alpha) (int)(pD3DDev?D3D7_LoadTexture_32:D3D9_LoadTexture_32)(skinname, data, width, height, (usemips?TF_MIPMAP:TF_NOMIPMAP) | (alpha?TF_ALPHA:TF_NOALPHA) | TF_NOTBUMPMAP) #define D3D_LoadTextureFB(skinname,width,height,data,usemips,alpha) 0 #define D3D_LoadTexture8Bump(skinname,width,height,data,usemips,alpha) 0 diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 32716b038..d2f87160f 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -107,7 +107,7 @@ qbyte GetPaletteIndex(int red, int green, int blue) #endif void BuildGammaTable (float g, float c); -void D3D_VID_GenPaletteTables (unsigned char *palette) +void D3D7_VID_GenPaletteTables (unsigned char *palette) { qbyte *pal; unsigned r,g,b; @@ -489,7 +489,7 @@ static LRESULT WINAPI D3D7_WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA -qboolean D3D_VID_Init(rendererstate_t *info, unsigned char *palette) +qboolean D3D7_VID_Init(rendererstate_t *info, unsigned char *palette) { DWORD width = info->width; DWORD height = info->height; @@ -650,7 +650,7 @@ qboolean D3D_VID_Init(rendererstate_t *info, unsigned char *palette) GetWindowRect(mainwindow, &window_rect); - D3D_VID_GenPaletteTables(palette); + D3D7_VID_GenPaletteTables(palette); @@ -669,21 +669,21 @@ qboolean D3D_VID_Init(rendererstate_t *info, unsigned char *palette) -qboolean (D3D_R_CheckSky) (void) +qboolean (D3D7_R_CheckSky) (void) { return false; } -void (D3D_R_SetSky) (char *name, float rotate, vec3_t axis) +void (D3D7_R_SetSky) (char *name, float rotate, vec3_t axis) { } -void (D3D_R_NewMap) (void) +void (D3D7_R_NewMap) (void) { extern int skytexturenum; int i; r_worldentity.model = cl.worldmodel; GLR_AnimateLight(); - D3D_BuildLightmaps(); + D3D7_BuildLightmaps(); P_ClearParticles(); @@ -703,70 +703,70 @@ void (D3D_R_NewMap) (void) mleaf_t *r_viewleaf, *r_oldviewleaf; mleaf_t *r_viewleaf2, *r_oldviewleaf2; -void (D3D_R_PreNewMap) (void) +void (D3D7_R_PreNewMap) (void) { r_viewleaf = NULL; r_oldviewleaf = NULL; r_viewleaf2 = NULL; r_oldviewleaf2 = NULL; } -int (D3D_R_LightPoint) (vec3_t point) +int (D3D7_R_LightPoint) (vec3_t point) { return 0; } -void (D3D_R_PushDlights) (void) +void (D3D7_R_PushDlights) (void) { } -void (D3D_R_AddStain) (vec3_t org, float red, float green, float blue, float radius) +void (D3D7_R_AddStain) (vec3_t org, float red, float green, float blue, float radius) { } -void (D3D_R_LessenStains) (void) +void (D3D7_R_LessenStains) (void) { } -void (D3D_Mod_Init) (void) +void (D3D7_Mod_Init) (void) { } -void (D3D_Mod_ClearAll) (void) +void (D3D7_Mod_ClearAll) (void) { } -struct model_s *(D3D_Mod_ForName) (char *name, qboolean crash) +struct model_s *(D3D7_Mod_ForName) (char *name, qboolean crash) { return NULL; } -struct model_s *(D3D_Mod_FindName) (char *name) +struct model_s *(D3D7_Mod_FindName) (char *name) { return NULL; } -void *(D3D_Mod_Extradata) (struct model_s *mod) +void *(D3D7_Mod_Extradata) (struct model_s *mod) { return NULL; } // handles caching -void (D3D_Mod_TouchModel) (char *name) +void (D3D7_Mod_TouchModel) (char *name) { } -void (D3D_Mod_NowLoadExternal) (void) +void (D3D7_Mod_NowLoadExternal) (void) { } -void (D3D_Mod_Think) (void) +void (D3D7_Mod_Think) (void) { } -qboolean(D3D_Mod_GetTag) (struct model_s *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) +qboolean(D3D7_Mod_GetTag) (struct model_s *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result) { return false; } -int (D3D_Mod_TagNumForName) (struct model_s *model, char *name) +int (D3D7_Mod_TagNumForName) (struct model_s *model, char *name) { return 0; } -int (D3D_Mod_SkinForName) (struct model_s *model, char *name) +int (D3D7_Mod_SkinForName) (struct model_s *model, char *name) { return 0; } -void (D3D_VID_DeInit) (void) +void (D3D7_VID_DeInit) (void) { if (pPrimary) { @@ -799,39 +799,39 @@ void (D3D_VID_DeInit) (void) mainwindow = NULL; } } -void (D3D_VID_LockBuffer) (void) +void (D3D7_VID_LockBuffer) (void) { } -void (D3D_VID_UnlockBuffer) (void) +void (D3D7_VID_UnlockBuffer) (void) { } -void (D3D_D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height) +void (D3D7_D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height) { } -void (D3D_D_EndDirectRect) (int x, int y, int width, int height) +void (D3D7_D_EndDirectRect) (int x, int y, int width, int height) { } -void (D3D_VID_ForceLockState) (int lk) +void (D3D7_VID_ForceLockState) (int lk) { } -int (D3D_VID_ForceUnlockedAndReturnState) (void) +int (D3D7_VID_ForceUnlockedAndReturnState) (void) { return 0; } -void (D3D_VID_SetPalette) (unsigned char *palette) +void (D3D7_VID_SetPalette) (unsigned char *palette) { - D3D_VID_GenPaletteTables(palette); + D3D7_VID_GenPaletteTables(palette); } -void (D3D_VID_ShiftPalette) (unsigned char *palette) +void (D3D7_VID_ShiftPalette) (unsigned char *palette) { - D3D_VID_GenPaletteTables(palette); + D3D7_VID_GenPaletteTables(palette); } -char *(D3D_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight) +char *(D3D7_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight) { return NULL; } -void (D3D_VID_SetWindowCaption) (char *msg) +void (D3D7_VID_SetWindowCaption) (char *msg) { SetWindowText(mainwindow, msg); } @@ -841,7 +841,7 @@ void d3d7_ortho(float *m) D3DXMatrixOrthoOffCenter((D3DXMATRIX*)m, 0, vid.width, vid.height, 0, -100, 100); } -void D3D_Set2D (void) +void D3D7_Set2D (void) { int r; float m[16]; @@ -881,13 +881,13 @@ void D3D_Set2D (void) // pD3DDev->lpVtbl->BeginScene(pD3DDev); } -void D3D_GetBufferSize(int *width, int *height) +void D3D7_GetBufferSize(int *width, int *height) { pD3DX->lpVtbl->GetBufferSize((void*)pD3DX, width, height); } -void (D3D_SCR_UpdateScreen) (void) +void (D3D7_SCR_UpdateScreen) (void) { extern cvar_t vid_conheight; int uimenu; @@ -952,7 +952,7 @@ void (D3D_SCR_UpdateScreen) (void) #endif pD3DDev->lpVtbl->BeginScene(pD3DDev); - D3D_Set2D (); + D3D7_Set2D (); /* #ifdef TEXTEDITOR if (editormodal) @@ -1023,7 +1023,7 @@ void (D3D_SCR_UpdateScreen) (void) } - D3D_Set2D (); + D3D7_Set2D (); // GLR_BrightenScreen(); @@ -1087,82 +1087,82 @@ void (D3D_SCR_UpdateScreen) (void) -mpic_t *(D3D_Draw_SafePicFromWad) (char *name); -mpic_t *(D3D_Draw_CachePic) (char *path); -mpic_t *(D3D_Draw_SafeCachePic) (char *path); -void (D3D_Draw_Init) (void); -void (D3D_Draw_ReInit) (void); -void (D3D_Draw_Character) (int x, int y, unsigned int num); -void (D3D_Draw_ColouredCharacter) (int x, int y, unsigned int num); -void (D3D_Draw_String) (int x, int y, const qbyte *str); -void (D3D_Draw_Alt_String) (int x, int y, const qbyte *str); -void (D3D_Draw_Crosshair) (void); -void (D3D_Draw_DebugChar) (qbyte num); -void (D3D_Draw_Pic) (int x, int y, mpic_t *pic); -void (D3D_Draw_ScalePic) (int x, int y, int width, int height, mpic_t *pic); -void (D3D_Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height); -void (D3D_Draw_TransPic) (int x, int y, mpic_t *pic); -void (D3D_Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *pic, qbyte *translation); -void (D3D_Draw_ConsoleBackground) (int lines); -void (D3D_Draw_EditorBackground) (int lines); -void (D3D_Draw_TileClear) (int x, int y, int w, int h); -void (D3D_Draw_Fill) (int x, int y, int w, int h, int c); -void (D3D_Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b); -void (D3D_Draw_FadeScreen) (void); -void (D3D_Draw_BeginDisc) (void); -void (D3D_Draw_EndDisc) (void); +mpic_t *(D3D7_Draw_SafePicFromWad) (char *name); +mpic_t *(D3D7_Draw_CachePic) (char *path); +mpic_t *(D3D7_Draw_SafeCachePic) (char *path); +void (D3D7_Draw_Init) (void); +void (D3D7_Draw_ReInit) (void); +void (D3D7_Draw_Character) (int x, int y, unsigned int num); +void (D3D7_Draw_ColouredCharacter) (int x, int y, unsigned int num); +void (D3D7_Draw_String) (int x, int y, const qbyte *str); +void (D3D7_Draw_Alt_String) (int x, int y, const qbyte *str); +void (D3D7_Draw_Crosshair) (void); +void (D3D7_Draw_DebugChar) (qbyte num); +void (D3D7_Draw_Pic) (int x, int y, mpic_t *pic); +void (D3D7_Draw_ScalePic) (int x, int y, int width, int height, mpic_t *pic); +void (D3D7_Draw_SubPic) (int x, int y, mpic_t *pic, int srcx, int srcy, int width, int height); +void (D3D7_Draw_TransPic) (int x, int y, mpic_t *pic); +void (D3D7_Draw_TransPicTranslate) (int x, int y, int w, int h, qbyte *pic, qbyte *translation); +void (D3D7_Draw_ConsoleBackground) (int lines); +void (D3D7_Draw_EditorBackground) (int lines); +void (D3D7_Draw_TileClear) (int x, int y, int w, int h); +void (D3D7_Draw_Fill) (int x, int y, int w, int h, int c); +void (D3D7_Draw_FillRGB) (int x, int y, int w, int h, float r, float g, float b); +void (D3D7_Draw_FadeScreen) (void); +void (D3D7_Draw_BeginDisc) (void); +void (D3D7_Draw_EndDisc) (void); -void (D3D_Draw_Image) (float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic); //gl-style scaled/coloured/subpic -void (D3D_Draw_ImageColours) (float r, float g, float b, float a); +void (D3D7_Draw_Image) (float x, float y, float w, float h, float s1, float t1, float s2, float t2, mpic_t *pic); //gl-style scaled/coloured/subpic +void (D3D7_Draw_ImageColours) (float r, float g, float b, float a); -void (D3D_R_Init) (void); -void (D3D_R_DeInit) (void); -void (D3D_R_ReInit) (void); -void (D3D_R_RenderView) (void); // must set r_refdef first +void (D3D7_R_Init) (void); +void (D3D7_R_DeInit) (void); +void (D3D7_R_ReInit) (void); +void (D3D7_R_RenderView) (void); // must set r_refdef first -qboolean (D3D_R_CheckSky) (void); -void (D3D_R_SetSky) (char *name, float rotate, vec3_t axis); +qboolean (D3D7_R_CheckSky) (void); +void (D3D7_R_SetSky) (char *name, float rotate, vec3_t axis); -void (D3D_R_NewMap) (void); -void (D3D_R_PreNewMap) (void); -int (D3D_R_LightPoint) (vec3_t point); +void (D3D7_R_NewMap) (void); +void (D3D7_R_PreNewMap) (void); +int (D3D7_R_LightPoint) (vec3_t point); -void (D3D_R_PushDlights) (void); -void (D3D_R_AddStain) (vec3_t org, float red, float green, float blue, float radius); -void (D3D_R_LessenStains) (void); +void (D3D7_R_PushDlights) (void); +void (D3D7_R_AddStain) (vec3_t org, float red, float green, float blue, float radius); +void (D3D7_R_LessenStains) (void); -void (D3D_Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight); //input is bottom up... -void (D3D_Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight); //top down -void (D3D_Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette); //paletted topdown (framedata is 8bit indexes into palette) +void (D3D7_Media_ShowFrameBGR_24_Flip) (qbyte *framedata, int inwidth, int inheight); //input is bottom up... +void (D3D7_Media_ShowFrameRGBA_32) (qbyte *framedata, int inwidth, int inheight); //top down +void (D3D7_Media_ShowFrame8bit) (qbyte *framedata, int inwidth, int inheight, qbyte *palette); //paletted topdown (framedata is 8bit indexes into palette) -void (D3D_Mod_Init) (void); -void (D3D_Mod_ClearAll) (void); -struct model_s *(D3D_Mod_ForName) (char *name, qboolean crash); -struct model_s *(D3D_Mod_FindName) (char *name); -void *(D3D_Mod_Extradata) (struct model_s *mod); // handles caching -void (D3D_Mod_TouchModel) (char *name); +void (D3D7_Mod_Init) (void); +void (D3D7_Mod_ClearAll) (void); +struct model_s *(D3D7_Mod_ForName) (char *name, qboolean crash); +struct model_s *(D3D7_Mod_FindName) (char *name); +void *(D3D7_Mod_Extradata) (struct model_s *mod); // handles caching +void (D3D7_Mod_TouchModel) (char *name); -void (D3D_Mod_NowLoadExternal) (void); -void (D3D_Mod_Think) (void); -qboolean(D3D_Mod_GetTag) (struct model_s *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result); -int (D3D_Mod_TagNumForName) (struct model_s *model, char *name); -int (D3D_Mod_SkinForName) (struct model_s *model, char *name); +void (D3D7_Mod_NowLoadExternal) (void); +void (D3D7_Mod_Think) (void); +qboolean(D3D7_Mod_GetTag) (struct model_s *model, int tagnum, int frame1, int frame2, float f2ness, float f1time, float f2time, float *result); +int (D3D7_Mod_TagNumForName) (struct model_s *model, char *name); +int (D3D7_Mod_SkinForName) (struct model_s *model, char *name); -qboolean (D3D_VID_Init) (rendererstate_t *info, unsigned char *palette); -void (D3D_VID_DeInit) (void); -void (D3D_VID_LockBuffer) (void); -void (D3D_VID_UnlockBuffer) (void); -void (D3D_D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height); -void (D3D_D_EndDirectRect) (int x, int y, int width, int height); -void (D3D_VID_ForceLockState) (int lk); -int (D3D_VID_ForceUnlockedAndReturnState) (void); -void (D3D_VID_SetPalette) (unsigned char *palette); -void (D3D_VID_ShiftPalette) (unsigned char *palette); -char *(D3D_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight); -void (D3D_VID_SetWindowCaption) (char *msg); +qboolean (D3D7_VID_Init) (rendererstate_t *info, unsigned char *palette); +void (D3D7_VID_DeInit) (void); +void (D3D7_VID_LockBuffer) (void); +void (D3D7_VID_UnlockBuffer) (void); +void (D3D7_D_BeginDirectRect) (int x, int y, qbyte *pbitmap, int width, int height); +void (D3D7_D_EndDirectRect) (int x, int y, int width, int height); +void (D3D7_VID_ForceLockState) (int lk); +int (D3D7_VID_ForceUnlockedAndReturnState) (void); +void (D3D7_VID_SetPalette) (unsigned char *palette); +void (D3D7_VID_ShiftPalette) (unsigned char *palette); +char *(D3D7_VID_GetRGBInfo) (int prepad, int *truevidwidth, int *truevidheight); +void (D3D7_VID_SetWindowCaption) (char *msg); -void (D3D_SCR_UpdateScreen) (void); +void (D3D7_SCR_UpdateScreen) (void); @@ -1178,53 +1178,54 @@ rendererinfo_t d3d7rendererinfo = }, QR_DIRECT3D, - D3D_Draw_SafePicFromWad, - D3D_Draw_CachePic, - D3D_Draw_SafeCachePic, - D3D_Draw_Init, - D3D_Draw_ReInit, - D3D_Draw_Character, - D3D_Draw_ColouredCharacter, - D3D_Draw_String, - D3D_Draw_Alt_String, - D3D_Draw_Crosshair, - D3D_Draw_DebugChar, - D3D_Draw_Pic, - D3D_Draw_ScalePic, - D3D_Draw_SubPic, - D3D_Draw_TransPic, - D3D_Draw_TransPicTranslate, - D3D_Draw_ConsoleBackground, - D3D_Draw_EditorBackground, - D3D_Draw_TileClear, - D3D_Draw_Fill, - D3D_Draw_FillRGB, - D3D_Draw_FadeScreen, - D3D_Draw_BeginDisc, - D3D_Draw_EndDisc, + D3D7_Draw_SafePicFromWad, + D3D7_Draw_CachePic, + D3D7_Draw_SafeCachePic, + D3D7_Draw_Init, + D3D7_Draw_ReInit, + D3D7_Draw_Character, + D3D7_Draw_ColouredCharacter, + NULL, + D3D7_Draw_String, + D3D7_Draw_Alt_String, + D3D7_Draw_Crosshair, + D3D7_Draw_DebugChar, + D3D7_Draw_Pic, + D3D7_Draw_ScalePic, + D3D7_Draw_SubPic, + D3D7_Draw_TransPic, + D3D7_Draw_TransPicTranslate, + D3D7_Draw_ConsoleBackground, + D3D7_Draw_EditorBackground, + D3D7_Draw_TileClear, + D3D7_Draw_Fill, + D3D7_Draw_FillRGB, + D3D7_Draw_FadeScreen, + D3D7_Draw_BeginDisc, + D3D7_Draw_EndDisc, - D3D_Draw_Image, - D3D_Draw_ImageColours, + D3D7_Draw_Image, + D3D7_Draw_ImageColours, - D3D_R_Init, - D3D_R_DeInit, - D3D_R_ReInit, - D3D_R_RenderView, + D3D7_R_Init, + D3D7_R_DeInit, + D3D7_R_ReInit, + D3D7_R_RenderView, - D3D_R_CheckSky, - D3D_R_SetSky, + D3D7_R_CheckSky, + D3D7_R_SetSky, - D3D_R_NewMap, - D3D_R_PreNewMap, - D3D_R_LightPoint, + D3D7_R_NewMap, + D3D7_R_PreNewMap, + D3D7_R_LightPoint, - D3D_R_PushDlights, - D3D_R_AddStain, - D3D_R_LessenStains, + D3D7_R_PushDlights, + D3D7_R_AddStain, + D3D7_R_LessenStains, - D3D_Media_ShowFrameBGR_24_Flip, - D3D_Media_ShowFrameRGBA_32, - D3D_Media_ShowFrame8bit, + D3D7_Media_ShowFrameBGR_24_Flip, + D3D7_Media_ShowFrameRGBA_32, + D3D7_Media_ShowFrame8bit, GLMod_Init, GLMod_ClearAll, @@ -1235,25 +1236,25 @@ rendererinfo_t d3d7rendererinfo = GLMod_NowLoadExternal, GLMod_Think, - D3D_Mod_GetTag, - D3D_Mod_TagNumForName, - D3D_Mod_SkinForName, + D3D7_Mod_GetTag, + D3D7_Mod_TagNumForName, + D3D7_Mod_SkinForName, - D3D_VID_Init, - D3D_VID_DeInit, - D3D_VID_LockBuffer, - D3D_VID_UnlockBuffer, - D3D_D_BeginDirectRect, - D3D_D_EndDirectRect, - D3D_VID_ForceLockState, - D3D_VID_ForceUnlockedAndReturnState, - D3D_VID_SetPalette, - D3D_VID_ShiftPalette, - D3D_VID_GetRGBInfo, - D3D_VID_SetWindowCaption, + D3D7_VID_Init, + D3D7_VID_DeInit, + D3D7_VID_LockBuffer, + D3D7_VID_UnlockBuffer, + D3D7_D_BeginDirectRect, + D3D7_D_EndDirectRect, + D3D7_VID_ForceLockState, + D3D7_VID_ForceUnlockedAndReturnState, + D3D7_VID_SetPalette, + D3D7_VID_ShiftPalette, + D3D7_VID_GetRGBInfo, + D3D7_VID_SetWindowCaption, - D3D_SCR_UpdateScreen + D3D7_SCR_UpdateScreen }; #endif diff --git a/engine/d3d9/d3d9_draw.c b/engine/d3d9/d3d9_draw.c index 65ed558b5..a69d9b426 100644 --- a/engine/d3d9/d3d9_draw.c +++ b/engine/d3d9/d3d9_draw.c @@ -691,7 +691,7 @@ void D3D9_Draw_FillRGB (int x, int y, int w, int h, float r, float g, float b D3D9_Draw_Fill_I(x, y, w, h, *(unsigned int*)colours); } -void D3D9_Draw_Fill (int x, int y, int w, int h, int c) +void D3D9_Draw_Fill (int x, int y, int w, int h, unsigned int c) { D3D9_Draw_FillRGB(x, y, w, h, host_basepal[c*3+0]/255.0f, host_basepal[c*3+1]/255.0f, host_basepal[c*3+2]/255.0f); } @@ -700,8 +700,8 @@ void D3D9_Draw_FadeScreen (void) // Sys_Error("D3D function not implemented\n"); } void D3D9_Draw_BeginDisc (void) -{ -// Sys_Error("D3D function not implemented\n"); +{ +// Sys_Error("D3D function not implemented\n"); } void D3D9_Draw_EndDisc (void) { diff --git a/engine/d3d9/d3d9_mesh.c b/engine/d3d9/d3d9_mesh.c index baa09ad7d..6b7470ae2 100644 --- a/engine/d3d9/d3d9_mesh.c +++ b/engine/d3d9/d3d9_mesh.c @@ -113,7 +113,7 @@ static galiastexnum_t *D3D9_ChooseSkin(galiasinfo_t *inf, char *modelname, int s Skin_Find(e->scoreboard); tc = e->scoreboard->ttopcolor; bc = e->scoreboard->tbottomcolor; - +/* //colour forcing if (cl.splitclients<2 && !(cl.fpd & FPD_NO_FORCE_COLOR)) //no colour/skin forcing in splitscreen. { @@ -139,7 +139,7 @@ static galiastexnum_t *D3D9_ChooseSkin(galiasinfo_t *inf, char *modelname, int s if (cl_enemybottomcolor>=0) bc = cl_enemybottomcolor; } - } + }*/ } else { @@ -305,6 +305,45 @@ static galiastexnum_t *D3D9_ChooseSkin(galiasinfo_t *inf, char *modelname, int s scaled_width = gl_max_size.value < 512 ? gl_max_size.value : 512; scaled_height = gl_max_size.value < 512 ? gl_max_size.value : 512; +#if 1 + { + for (i=0 ; i<256 ; i++) + translate32[i] = d_8to24rgbtable[i]; + + for (i = 0; i < 16; i++) + { + if (tc >= 16) + { + //assumption: row 0 is pure white. + *((unsigned char*)&translate32[TOP_RANGE+i]+0) = (((tc&0xff0000)>>16)**((unsigned char*)&d_8to24rgbtable[i]+0))>>8; + *((unsigned char*)&translate32[TOP_RANGE+i]+1) = (((tc&0x00ff00)>> 8)**((unsigned char*)&d_8to24rgbtable[i]+1))>>8; + *((unsigned char*)&translate32[TOP_RANGE+i]+2) = (((tc&0x0000ff)>> 0)**((unsigned char*)&d_8to24rgbtable[i]+2))>>8; + *((unsigned char*)&translate32[TOP_RANGE+i]+3) = 0xff; + } + else + { + if (tc < 8) + translate32[TOP_RANGE+i] = d_8to24rgbtable[(tc<<4)+i]; + else + translate32[BOTTOM_RANGE+i] = d_8to24rgbtable[(tc<<4)+15-i]; + } + if (bc >= 16) + { + *((unsigned char*)&translate32[BOTTOM_RANGE+i]+0) = (((bc&0xff0000)>>16)**((unsigned char*)&d_8to24rgbtable[i]+0))>>8; + *((unsigned char*)&translate32[BOTTOM_RANGE+i]+1) = (((bc&0x00ff00)>> 8)**((unsigned char*)&d_8to24rgbtable[i]+1))>>8; + *((unsigned char*)&translate32[BOTTOM_RANGE+i]+2) = (((bc&0x0000ff)>> 0)**((unsigned char*)&d_8to24rgbtable[i]+2))>>8; + *((unsigned char*)&translate32[BOTTOM_RANGE+i]+3) = 0xff; + } + else + { + if (bc < 8) + translate32[BOTTOM_RANGE+i] = d_8to24rgbtable[(bc<<4)+i]; + else + translate32[BOTTOM_RANGE+i] = d_8to24rgbtable[(bc<<4)+15-i]; + } + } + } +#else for (i=0 ; i<256 ; i++) translate[i] = i; @@ -327,6 +366,7 @@ static galiastexnum_t *D3D9_ChooseSkin(galiasinfo_t *inf, char *modelname, int s for (i=0 ; i<256 ; i++) translate32[i] = d_8to24rgbtable[translate[i]]; +#endif out = pixels; fracstep = tinwidth*0x10000/scaled_width; @@ -680,7 +720,7 @@ if (e->flags & Q2RF_DEPTHHACK) for(i = 0;; i++) { - R_GAliasBuildMesh(&mesh, inf, e->frame, e->oldframe, e->lerpfrac, e->shaderRGBAf[3], e->frame1time, e->frame2time, 0); + R_GAliasBuildMesh(&mesh, inf, e->frame1, e->frame2, e->lerpfrac, e->shaderRGBAf[3], e->frame1time, e->frame2time, 0); skin = D3D9_ChooseSkin(inf, m->name, e->skinnum, e); if (!skin) diff --git a/engine/d3d9/d3d9_rmain.c b/engine/d3d9/d3d9_rmain.c index bb893f054..eb1f73ffe 100644 --- a/engine/d3d9/d3d9_rmain.c +++ b/engine/d3d9/d3d9_rmain.c @@ -1381,7 +1381,9 @@ void (D3D9_R_RenderView) (void) -#include "particles.h" +#include "particles.h" +#define TYPESONLY +#include "p_script.c" #define APPLYD3D9BLEND(bm) \ switch (bm) \ @@ -1417,7 +1419,7 @@ typedef struct d3dparticlevertut_s { float org[3]; unsigned int colour; } d3dparticlevertut_t; -d3dparticlevertut_t d3dparticlevertut[4]; +d3dparticlevertut_t d3dparticlevertut[4]; part_type_t *lastd3dtype; static vec3_t pright, pup; @@ -1857,7 +1859,7 @@ void D3D9_DrawParticles(float ptime) IDirect3DDevice9_SetSamplerState(pD3DDev9, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); lastd3dtype = NULL; - DrawParticleTypes(D3D9_DrawParticleBlob, D3D9_DrawParticleSpark, D3D9_DrawParticleSpark, D3D9_DrawParticleSpark, D3D9_DrawParticleBeam, D3D9_DrawParticleBeamUT, NULL); + PScript_DrawParticleTypes(D3D9_DrawParticleBlob, D3D9_DrawParticleSpark, D3D9_DrawParticleSpark, D3D9_DrawParticleSpark, D3D9_DrawParticleBeam, D3D9_DrawParticleBeamUT, NULL); IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ZWRITEENABLE, FALSE ); IDirect3DDevice9_SetRenderState(pD3DDev9, D3DRS_ALPHATESTENABLE, FALSE ); diff --git a/engine/d3d9/d3d9quake.h b/engine/d3d9/d3d9quake.h index 61187da71..8f0eb6398 100644 --- a/engine/d3d9/d3d9quake.h +++ b/engine/d3d9/d3d9quake.h @@ -1,4 +1,7 @@ -//#include "ddraw.h" +//#include "ddraw.h" + +#ifndef D3D9QUAKE_H +#define D3D9QUAKE_H #include "d3d9.h" @@ -61,11 +64,13 @@ static void LotsOfLightDirectionHacks (entity_t *e, model_t *m, vec3_t lighta // d3d9_rmain.c // void D3D9_BaseBModelTextures (entity_t *e); +/* void D3D9_DrawParticleBeam (beamseg_t *b, part_type_t *type); void D3D9_DrawParticleBeamUT (beamseg_t *b, part_type_t *type); -void D3D9_DrawParticleBlob (particle_t *p, part_type_t *type); +void D3D9_DrawParticleBlob (particle_t *p, part_type_t *type); +void D3D9_DrawParticleSpark (particle_t *p, part_type_t *type); +*/ void D3D9_DrawParticles (float ptime); -void D3D9_DrawParticleSpark (particle_t *p, part_type_t *type); static void D3D9_DrawSpriteModel (entity_t *e); void D3D9_DrawTextureChains (void); void D3D9_DrawWorld (void); @@ -195,3 +200,5 @@ extern index_t dummyindex; #else #define D3DFMT_QINDEX D3DFMT_INDEX32 #endif + +#endif diff --git a/engine/d3d9/vid_d3d9.c b/engine/d3d9/vid_d3d9.c index 075406a52..7e5af6457 100644 --- a/engine/d3d9/vid_d3d9.c +++ b/engine/d3d9/vid_d3d9.c @@ -1453,7 +1453,8 @@ rendererinfo_t d3d9rendererinfo = D3D9_Draw_Init, D3D9_Draw_ReInit, D3D9_Draw_Character, - D3D9_Draw_ColouredCharacter, + D3D9_Draw_ColouredCharacter, + NULL, D3D9_Draw_String, D3D9_Draw_Alt_String, D3D9_Draw_Crosshair, diff --git a/engine/dotnet2005/ftequake.sln b/engine/dotnet2005/ftequake.sln index 20130ecc6..33f334808 100644 --- a/engine/dotnet2005/ftequake.sln +++ b/engine/dotnet2005/ftequake.sln @@ -2,76 +2,132 @@ Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ftequake", "ftequake.vcproj", "{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}" - ProjectSection(ProjectDependencies) = postProject - {382E6790-D1CA-48F5-8E53-D114635EB61D} = {382E6790-D1CA-48F5-8E53-D114635EB61D} - EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gas2masm", "gas2masm.vcproj", "{382E6790-D1CA-48F5-8E53-D114635EB61D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution D3DDebug|Win32 = D3DDebug|Win32 + D3DDebug|x64 = D3DDebug|x64 Debug Dedicated Server|Win32 = Debug Dedicated Server|Win32 + Debug Dedicated Server|x64 = Debug Dedicated Server|x64 Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 GLDebug|Win32 = GLDebug|Win32 + GLDebug|x64 = GLDebug|x64 GLRelease|Win32 = GLRelease|Win32 + GLRelease|x64 = GLRelease|x64 MDebug|Win32 = MDebug|Win32 + MDebug|x64 = MDebug|x64 MinGLDebug|Win32 = MinGLDebug|Win32 + MinGLDebug|x64 = MinGLDebug|x64 MinGLRelease|Win32 = MinGLRelease|Win32 + MinGLRelease|x64 = MinGLRelease|x64 MinSW|Win32 = MinSW|Win32 + MinSW|x64 = MinSW|x64 MRelease|Win32 = MRelease|Win32 + MRelease|x64 = MRelease|x64 Release Dedicated Server|Win32 = Release Dedicated Server|Win32 + Release Dedicated Server|x64 = Release Dedicated Server|x64 Release|Win32 = Release|Win32 + Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.ActiveCfg = D3DDebug|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|Win32.Build.0 = D3DDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.ActiveCfg = D3DDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.D3DDebug|x64.Build.0 = D3DDebug|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.ActiveCfg = Debug Dedicated Server|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|Win32.Build.0 = Debug Dedicated Server|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug Dedicated Server|x64.Build.0 = GLDebug|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|Win32.ActiveCfg = Debug|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|Win32.Build.0 = Debug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|x64.ActiveCfg = D3DDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Debug|x64.Build.0 = D3DDebug|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.ActiveCfg = GLDebug|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|Win32.Build.0 = GLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.ActiveCfg = GLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLDebug|x64.Build.0 = GLDebug|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.ActiveCfg = GLRelease|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|Win32.Build.0 = GLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.GLRelease|x64.Build.0 = GLRelease|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.ActiveCfg = MDebug|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|Win32.Build.0 = MDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.ActiveCfg = GLRelease|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MDebug|x64.Build.0 = GLRelease|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.ActiveCfg = MinGLDebug|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|Win32.Build.0 = MinGLDebug|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.ActiveCfg = MinGLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLDebug|x64.Build.0 = MinGLDebug|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.ActiveCfg = MinGLRelease|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|Win32.Build.0 = MinGLRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.ActiveCfg = MinGLDebug|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinGLRelease|x64.Build.0 = MinGLDebug|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinSW|Win32.ActiveCfg = MinSW|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinSW|Win32.Build.0 = MinSW|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinSW|x64.ActiveCfg = MinSW|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MinSW|x64.Build.0 = MinSW|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.ActiveCfg = MRelease|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|Win32.Build.0 = MRelease|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.ActiveCfg = MinSW|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.MRelease|x64.Build.0 = MinSW|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.ActiveCfg = Release Dedicated Server|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|Win32.Build.0 = Release Dedicated Server|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.ActiveCfg = Release|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release Dedicated Server|x64.Build.0 = Release|x64 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|Win32.ActiveCfg = Release|Win32 {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|Win32.Build.0 = Release|Win32 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|x64.ActiveCfg = Release|x64 + {88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}.Release|x64.Build.0 = Release|x64 {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.D3DDebug|x64.Build.0 = Debug|x64 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug Dedicated Server|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug Dedicated Server|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug Dedicated Server|x64.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Debug|x64.Build.0 = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLDebug|x64.Build.0 = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.GLRelease|x64.Build.0 = Debug|x64 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MDebug|x64.Build.0 = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLDebug|x64.Build.0 = Debug|x64 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinGLRelease|x64.Build.0 = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinSW|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinSW|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinSW|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MinSW|x64.Build.0 = Debug|x64 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.MRelease|x64.Build.0 = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|x64.ActiveCfg = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release Dedicated Server|x64.Build.0 = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release|Win32.ActiveCfg = Debug|Win32 {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release|Win32.Build.0 = Debug|Win32 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release|x64.ActiveCfg = Debug|x64 + {382E6790-D1CA-48F5-8E53-D114635EB61D}.Release|x64.Build.0 = Debug|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index ce6a1c51c..c06a19218 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -4,11 +4,15 @@ Version="8.00" Name="ftequake" ProjectGUID="{88BFEE0E-7BC0-43AD-9CCC-6B1A6E4C1364}" + RootNamespace="ftequake" > + @@ -114,6 +118,107 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1253,120 +2491,6 @@ Name="Source Files" Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1383,6 +2507,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1393,6 +2527,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1403,6 +2547,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1413,6 +2567,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1423,6 +2587,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1433,6 +2607,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1443,6 +2627,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1453,6 +2647,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1463,6 +2667,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1473,6 +2687,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1483,6 +2707,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1493,6 +2727,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -1517,6 +2771,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1527,6 +2791,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1537,6 +2811,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1547,6 +2831,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1557,6 +2851,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1567,6 +2871,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1577,6 +2891,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1587,6 +2911,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1597,6 +2931,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1607,6 +2951,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1617,6 +2971,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -1645,6 +3019,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1655,6 +3039,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1665,6 +3059,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1675,6 +3079,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1685,6 +3099,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1695,6 +3119,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1705,6 +3139,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1715,6 +3159,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1725,6 +3179,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1735,6 +3199,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1745,6 +3219,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -1769,6 +3263,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1779,6 +3283,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1789,6 +3303,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1799,6 +3323,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1809,6 +3343,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1819,6 +3363,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1829,6 +3383,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1839,6 +3403,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1849,6 +3423,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1859,6 +3443,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1869,6 +3463,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -1893,6 +3507,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1903,6 +3527,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1913,6 +3547,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1923,6 +3567,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1933,6 +3587,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1943,6 +3607,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1953,6 +3627,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1963,6 +3647,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1973,6 +3667,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1983,6 +3687,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -1993,6 +3707,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2017,6 +3751,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2027,6 +3771,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2037,6 +3791,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2047,6 +3811,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2057,6 +3831,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2067,6 +3851,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2077,6 +3871,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2087,6 +3891,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2097,6 +3911,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2107,6 +3931,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2117,6 +3951,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2141,6 +3995,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2151,6 +4015,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2161,6 +4035,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2171,6 +4055,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2181,6 +4075,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2191,6 +4095,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2201,6 +4115,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2211,6 +4135,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2221,6 +4155,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2231,6 +4175,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2241,6 +4195,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2265,6 +4239,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2275,6 +4259,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2285,6 +4279,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2295,6 +4299,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2305,6 +4319,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2315,6 +4339,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2325,6 +4359,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2335,6 +4379,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2345,6 +4399,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2355,6 +4419,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2365,6 +4439,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2389,6 +4483,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2399,6 +4503,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2409,6 +4523,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2419,6 +4543,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2429,6 +4563,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2439,6 +4583,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2449,6 +4603,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2459,6 +4623,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2469,6 +4643,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2479,6 +4663,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2489,6 +4683,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2513,6 +4727,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2523,6 +4747,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2533,6 +4767,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2543,6 +4787,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2553,6 +4807,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2563,6 +4827,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2573,6 +4847,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2583,6 +4867,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2593,6 +4887,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2603,6 +4907,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2613,6 +4927,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2637,6 +4971,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2647,6 +4991,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2657,6 +5011,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2667,6 +5031,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2677,6 +5051,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2687,6 +5071,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2697,6 +5091,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2707,6 +5111,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2717,6 +5131,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2727,6 +5151,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2737,6 +5171,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2761,6 +5215,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2771,6 +5235,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2781,6 +5255,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2791,6 +5275,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2801,6 +5295,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2811,6 +5315,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2821,6 +5335,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2831,6 +5355,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2841,6 +5375,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2851,6 +5395,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2861,6 +5415,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -2885,6 +5459,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2895,6 +5479,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2905,6 +5499,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2915,6 +5519,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2925,6 +5539,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2935,6 +5559,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2945,6 +5579,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2955,6 +5599,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2965,6 +5619,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2975,6 +5639,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -2985,6 +5659,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3009,6 +5703,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3019,6 +5723,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3029,6 +5743,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3039,6 +5763,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3049,6 +5783,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3059,6 +5803,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3069,6 +5823,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3079,6 +5843,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3089,6 +5863,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3099,6 +5883,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3109,6 +5903,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3133,6 +5947,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3143,6 +5967,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3153,6 +5987,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3163,6 +6007,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3173,6 +6027,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3183,6 +6047,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3193,6 +6067,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3203,6 +6087,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3213,6 +6107,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3223,6 +6127,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3233,6 +6147,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3257,6 +6191,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3267,6 +6211,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3277,6 +6231,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3287,6 +6251,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3297,6 +6271,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3307,6 +6291,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3317,6 +6311,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3327,6 +6331,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3337,6 +6351,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3347,6 +6371,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3357,6 +6391,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3381,6 +6435,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3391,6 +6455,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3401,6 +6475,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3411,6 +6495,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3421,6 +6515,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3431,6 +6535,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3441,6 +6555,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3451,6 +6575,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3461,6 +6595,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3471,6 +6615,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3481,6 +6635,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3505,6 +6679,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3515,6 +6699,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3525,6 +6719,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3535,6 +6739,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3545,6 +6759,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3555,6 +6779,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3565,6 +6799,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3575,6 +6819,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3585,6 +6839,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3595,6 +6859,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3605,6 +6879,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3629,6 +6923,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3639,6 +6943,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3649,6 +6963,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3659,6 +6983,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3669,6 +7003,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3679,6 +7023,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3689,6 +7043,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3699,6 +7063,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3709,6 +7083,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3719,6 +7103,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3729,6 +7123,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3752,6 +7166,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -3791,6 +7244,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -3810,6 +7282,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -3839,6 +7340,15 @@ PreprocessorDefinitions="" /> + + + @@ -3848,6 +7358,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -3872,6 +7401,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3882,6 +7421,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3892,6 +7441,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3902,6 +7461,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3912,6 +7481,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3922,6 +7501,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3932,6 +7521,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3942,6 +7541,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3952,6 +7561,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3962,6 +7581,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + @@ -3972,6 +7601,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + @@ -3998,6 +7646,15 @@ PreprocessorDefinitions="" /> + + + @@ -4007,6 +7664,15 @@ PreprocessorDefinitions="" /> + + + @@ -4016,6 +7682,15 @@ PreprocessorDefinitions="" /> + + + @@ -4025,6 +7700,15 @@ PreprocessorDefinitions="" /> + + + @@ -4034,6 +7718,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4053,6 +7756,15 @@ PreprocessorDefinitions="" /> + + + @@ -4062,6 +7774,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4081,6 +7812,15 @@ PreprocessorDefinitions="" /> + + + @@ -4090,6 +7830,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4112,6 +7870,15 @@ PreprocessorDefinitions="" /> + + + @@ -4121,6 +7888,15 @@ PreprocessorDefinitions="" /> + + + @@ -4130,6 +7906,15 @@ PreprocessorDefinitions="" /> + + + @@ -4139,6 +7924,15 @@ PreprocessorDefinitions="" /> + + + @@ -4148,6 +7942,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4167,6 +7980,15 @@ PreprocessorDefinitions="" /> + + + @@ -4176,6 +7998,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4195,6 +8036,15 @@ PreprocessorDefinitions="" /> + + + @@ -4204,6 +8054,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4227,6 +8096,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -4266,6 +8174,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4285,6 +8212,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -4314,6 +8270,15 @@ PreprocessorDefinitions="" /> + + + @@ -4323,6 +8288,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4345,6 +8328,15 @@ PreprocessorDefinitions="" /> + + + @@ -4354,6 +8346,15 @@ PreprocessorDefinitions="" /> + + + @@ -4363,6 +8364,15 @@ PreprocessorDefinitions="" /> + + + @@ -4372,6 +8382,15 @@ PreprocessorDefinitions="" /> + + + @@ -4381,6 +8400,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4400,6 +8438,15 @@ PreprocessorDefinitions="" /> + + + @@ -4409,6 +8456,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4428,6 +8494,15 @@ PreprocessorDefinitions="" /> + + + @@ -4437,6 +8512,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4459,6 +8552,15 @@ PreprocessorDefinitions="" /> + + + @@ -4468,6 +8570,15 @@ PreprocessorDefinitions="" /> + + + @@ -4477,6 +8588,15 @@ PreprocessorDefinitions="" /> + + + @@ -4486,6 +8606,15 @@ PreprocessorDefinitions="" /> + + + @@ -4495,6 +8624,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4514,6 +8662,15 @@ PreprocessorDefinitions="" /> + + + @@ -4523,6 +8680,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4542,6 +8718,15 @@ PreprocessorDefinitions="" /> + + + @@ -4551,6 +8736,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4573,6 +8776,15 @@ PreprocessorDefinitions="" /> + + + @@ -4582,6 +8794,15 @@ PreprocessorDefinitions="" /> + + + @@ -4591,6 +8812,15 @@ PreprocessorDefinitions="" /> + + + @@ -4600,6 +8830,15 @@ PreprocessorDefinitions="" /> + + + @@ -4609,6 +8848,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4628,6 +8886,15 @@ PreprocessorDefinitions="" /> + + + @@ -4637,6 +8904,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4656,6 +8942,15 @@ PreprocessorDefinitions="" /> + + + @@ -4665,6 +8960,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4687,6 +9000,15 @@ PreprocessorDefinitions="" /> + + + @@ -4696,6 +9018,15 @@ PreprocessorDefinitions="" /> + + + @@ -4705,6 +9036,15 @@ PreprocessorDefinitions="" /> + + + @@ -4714,6 +9054,15 @@ PreprocessorDefinitions="" /> + + + @@ -4723,6 +9072,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4742,6 +9110,15 @@ PreprocessorDefinitions="" /> + + + @@ -4751,6 +9128,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4770,6 +9166,15 @@ PreprocessorDefinitions="" /> + + + @@ -4779,6 +9184,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4801,6 +9224,15 @@ PreprocessorDefinitions="" /> + + + @@ -4810,6 +9242,15 @@ PreprocessorDefinitions="" /> + + + @@ -4819,6 +9260,15 @@ PreprocessorDefinitions="" /> + + + @@ -4828,6 +9278,15 @@ PreprocessorDefinitions="" /> + + + @@ -4837,6 +9296,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4856,6 +9334,15 @@ PreprocessorDefinitions="" /> + + + @@ -4865,6 +9352,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4884,6 +9390,15 @@ PreprocessorDefinitions="" /> + + + @@ -4893,6 +9408,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4915,6 +9448,15 @@ PreprocessorDefinitions="" /> + + + @@ -4924,6 +9466,15 @@ PreprocessorDefinitions="" /> + + + @@ -4933,6 +9484,15 @@ PreprocessorDefinitions="" /> + + + @@ -4942,6 +9502,15 @@ PreprocessorDefinitions="" /> + + + @@ -4951,6 +9520,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4970,6 +9558,15 @@ PreprocessorDefinitions="" /> + + + @@ -4979,6 +9576,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -4998,6 +9614,15 @@ PreprocessorDefinitions="" /> + + + @@ -5007,6 +9632,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5029,6 +9672,15 @@ PreprocessorDefinitions="" /> + + + @@ -5038,6 +9690,15 @@ PreprocessorDefinitions="" /> + + + @@ -5047,6 +9708,15 @@ PreprocessorDefinitions="" /> + + + @@ -5056,6 +9726,15 @@ PreprocessorDefinitions="" /> + + + @@ -5065,6 +9744,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5084,6 +9782,15 @@ PreprocessorDefinitions="" /> + + + @@ -5093,6 +9800,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5112,6 +9838,15 @@ PreprocessorDefinitions="" /> + + + @@ -5121,6 +9856,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5143,6 +9896,15 @@ PreprocessorDefinitions="" /> + + + @@ -5152,6 +9914,15 @@ PreprocessorDefinitions="" /> + + + @@ -5161,6 +9932,15 @@ PreprocessorDefinitions="" /> + + + @@ -5170,6 +9950,15 @@ PreprocessorDefinitions="" /> + + + @@ -5179,6 +9968,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5198,6 +10006,15 @@ PreprocessorDefinitions="" /> + + + @@ -5207,6 +10024,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5226,6 +10062,15 @@ PreprocessorDefinitions="" /> + + + @@ -5235,6 +10080,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5257,6 +10120,15 @@ PreprocessorDefinitions="" /> + + + @@ -5266,6 +10138,15 @@ PreprocessorDefinitions="" /> + + + @@ -5275,6 +10156,15 @@ PreprocessorDefinitions="" /> + + + @@ -5284,6 +10174,15 @@ PreprocessorDefinitions="" /> + + + @@ -5293,6 +10192,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5312,6 +10230,15 @@ PreprocessorDefinitions="" /> + + + @@ -5321,6 +10248,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5340,6 +10286,15 @@ PreprocessorDefinitions="" /> + + + @@ -5349,6 +10304,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5371,6 +10344,15 @@ PreprocessorDefinitions="" /> + + + @@ -5380,6 +10362,15 @@ PreprocessorDefinitions="" /> + + + @@ -5389,6 +10380,15 @@ PreprocessorDefinitions="" /> + + + @@ -5398,6 +10398,15 @@ PreprocessorDefinitions="" /> + + + @@ -5407,6 +10416,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5426,6 +10454,15 @@ PreprocessorDefinitions="" /> + + + @@ -5435,6 +10472,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5454,6 +10510,15 @@ PreprocessorDefinitions="" /> + + + @@ -5463,6 +10528,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5485,6 +10568,15 @@ PreprocessorDefinitions="" /> + + + @@ -5494,6 +10586,15 @@ PreprocessorDefinitions="" /> + + + @@ -5503,6 +10604,15 @@ PreprocessorDefinitions="" /> + + + @@ -5512,6 +10622,15 @@ PreprocessorDefinitions="" /> + + + @@ -5521,6 +10640,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5540,6 +10678,15 @@ PreprocessorDefinitions="" /> + + + @@ -5549,6 +10696,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5568,6 +10734,15 @@ PreprocessorDefinitions="" /> + + + @@ -5577,6 +10752,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5599,6 +10792,15 @@ PreprocessorDefinitions="" /> + + + @@ -5608,6 +10810,15 @@ PreprocessorDefinitions="" /> + + + @@ -5617,6 +10828,15 @@ PreprocessorDefinitions="" /> + + + @@ -5626,6 +10846,15 @@ PreprocessorDefinitions="" /> + + + @@ -5635,6 +10864,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5654,6 +10902,15 @@ PreprocessorDefinitions="" /> + + + @@ -5663,6 +10920,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5682,6 +10958,15 @@ PreprocessorDefinitions="" /> + + + @@ -5691,6 +10976,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5714,6 +11018,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -5753,6 +11096,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5772,6 +11134,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -5801,6 +11192,15 @@ PreprocessorDefinitions="" /> + + + @@ -5810,6 +11210,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5832,6 +11250,15 @@ PreprocessorDefinitions="" /> + + + @@ -5841,6 +11268,15 @@ PreprocessorDefinitions="" /> + + + @@ -5850,6 +11286,15 @@ PreprocessorDefinitions="" /> + + + @@ -5859,6 +11304,15 @@ PreprocessorDefinitions="" /> + + + @@ -5868,6 +11322,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5887,6 +11360,15 @@ PreprocessorDefinitions="" /> + + + @@ -5896,6 +11378,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5915,6 +11416,15 @@ PreprocessorDefinitions="" /> + + + @@ -5924,6 +11434,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -5946,6 +11474,15 @@ PreprocessorDefinitions="" /> + + + @@ -5955,6 +11492,15 @@ PreprocessorDefinitions="" /> + + + @@ -5964,6 +11510,15 @@ PreprocessorDefinitions="" /> + + + @@ -5973,6 +11528,15 @@ PreprocessorDefinitions="" /> + + + @@ -5982,6 +11546,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6001,6 +11584,15 @@ PreprocessorDefinitions="" /> + + + @@ -6010,6 +11602,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6029,6 +11640,15 @@ PreprocessorDefinitions="" /> + + + @@ -6038,6 +11658,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6060,6 +11698,15 @@ PreprocessorDefinitions="" /> + + + @@ -6069,6 +11716,15 @@ PreprocessorDefinitions="" /> + + + @@ -6078,6 +11734,15 @@ PreprocessorDefinitions="" /> + + + @@ -6087,6 +11752,15 @@ PreprocessorDefinitions="" /> + + + @@ -6096,6 +11770,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6115,6 +11808,15 @@ PreprocessorDefinitions="" /> + + + @@ -6124,6 +11826,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6143,6 +11864,15 @@ PreprocessorDefinitions="" /> + + + @@ -6152,6 +11882,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6174,6 +11922,15 @@ PreprocessorDefinitions="" /> + + + @@ -6183,6 +11940,15 @@ PreprocessorDefinitions="" /> + + + @@ -6192,6 +11958,15 @@ PreprocessorDefinitions="" /> + + + @@ -6201,6 +11976,15 @@ PreprocessorDefinitions="" /> + + + @@ -6210,6 +11994,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6229,6 +12032,15 @@ PreprocessorDefinitions="" /> + + + @@ -6238,6 +12050,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6257,6 +12088,15 @@ PreprocessorDefinitions="" /> + + + @@ -6266,6 +12106,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6288,6 +12146,15 @@ PreprocessorDefinitions="" /> + + + @@ -6297,6 +12164,15 @@ PreprocessorDefinitions="" /> + + + @@ -6306,6 +12182,15 @@ PreprocessorDefinitions="" /> + + + @@ -6315,6 +12200,15 @@ PreprocessorDefinitions="" /> + + + @@ -6324,6 +12218,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6343,6 +12256,15 @@ PreprocessorDefinitions="" /> + + + @@ -6352,6 +12274,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6371,6 +12312,15 @@ PreprocessorDefinitions="" /> + + + @@ -6380,6 +12330,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6402,6 +12370,15 @@ PreprocessorDefinitions="" /> + + + @@ -6411,6 +12388,15 @@ PreprocessorDefinitions="" /> + + + @@ -6420,6 +12406,15 @@ PreprocessorDefinitions="" /> + + + @@ -6429,6 +12424,15 @@ PreprocessorDefinitions="" /> + + + @@ -6438,6 +12442,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6457,6 +12480,15 @@ PreprocessorDefinitions="" /> + + + @@ -6466,6 +12498,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6485,6 +12536,15 @@ PreprocessorDefinitions="" /> + + + @@ -6494,6 +12554,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6516,6 +12594,15 @@ PreprocessorDefinitions="" /> + + + @@ -6525,6 +12612,15 @@ PreprocessorDefinitions="" /> + + + @@ -6534,6 +12630,15 @@ PreprocessorDefinitions="" /> + + + @@ -6543,6 +12648,15 @@ PreprocessorDefinitions="" /> + + + @@ -6552,6 +12666,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6571,6 +12704,15 @@ PreprocessorDefinitions="" /> + + + @@ -6580,6 +12722,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6599,6 +12760,15 @@ PreprocessorDefinitions="" /> + + + @@ -6608,6 +12778,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6630,6 +12818,15 @@ PreprocessorDefinitions="" /> + + + @@ -6639,6 +12836,15 @@ PreprocessorDefinitions="" /> + + + @@ -6648,6 +12854,15 @@ PreprocessorDefinitions="" /> + + + @@ -6657,6 +12872,15 @@ PreprocessorDefinitions="" /> + + + @@ -6666,6 +12890,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6685,6 +12928,15 @@ PreprocessorDefinitions="" /> + + + @@ -6694,6 +12946,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6713,6 +12984,15 @@ PreprocessorDefinitions="" /> + + + @@ -6722,6 +13002,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6744,6 +13042,15 @@ PreprocessorDefinitions="" /> + + + @@ -6753,6 +13060,15 @@ PreprocessorDefinitions="" /> + + + @@ -6762,6 +13078,15 @@ PreprocessorDefinitions="" /> + + + @@ -6771,6 +13096,15 @@ PreprocessorDefinitions="" /> + + + @@ -6780,6 +13114,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6799,6 +13152,15 @@ PreprocessorDefinitions="" /> + + + @@ -6808,6 +13170,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6827,6 +13208,15 @@ PreprocessorDefinitions="" /> + + + @@ -6836,6 +13226,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6858,6 +13266,15 @@ PreprocessorDefinitions="" /> + + + @@ -6867,6 +13284,15 @@ PreprocessorDefinitions="" /> + + + @@ -6876,6 +13302,15 @@ PreprocessorDefinitions="" /> + + + @@ -6885,6 +13320,15 @@ PreprocessorDefinitions="" /> + + + @@ -6894,6 +13338,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6913,6 +13376,15 @@ PreprocessorDefinitions="" /> + + + @@ -6922,6 +13394,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6941,6 +13432,15 @@ PreprocessorDefinitions="" /> + + + @@ -6950,6 +13450,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -6972,6 +13490,15 @@ PreprocessorDefinitions="" /> + + + @@ -6981,6 +13508,15 @@ PreprocessorDefinitions="" /> + + + @@ -6990,6 +13526,15 @@ PreprocessorDefinitions="" /> + + + @@ -6999,6 +13544,15 @@ PreprocessorDefinitions="" /> + + + @@ -7008,6 +13562,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7027,6 +13600,15 @@ PreprocessorDefinitions="" /> + + + @@ -7036,6 +13618,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7055,6 +13656,15 @@ PreprocessorDefinitions="" /> + + + @@ -7064,6 +13674,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7086,6 +13714,15 @@ PreprocessorDefinitions="" /> + + + @@ -7095,6 +13732,15 @@ PreprocessorDefinitions="" /> + + + @@ -7104,6 +13750,15 @@ PreprocessorDefinitions="" /> + + + @@ -7113,6 +13768,15 @@ PreprocessorDefinitions="" /> + + + @@ -7122,6 +13786,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7141,6 +13824,15 @@ PreprocessorDefinitions="" /> + + + @@ -7150,6 +13842,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7169,6 +13880,15 @@ PreprocessorDefinitions="" /> + + + @@ -7178,6 +13898,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7200,6 +13938,15 @@ PreprocessorDefinitions="" /> + + + @@ -7209,6 +13956,15 @@ PreprocessorDefinitions="" /> + + + @@ -7218,6 +13974,15 @@ PreprocessorDefinitions="" /> + + + @@ -7227,6 +13992,15 @@ PreprocessorDefinitions="" /> + + + @@ -7236,6 +14010,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7255,6 +14048,15 @@ PreprocessorDefinitions="" /> + + + @@ -7264,6 +14066,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7283,6 +14104,15 @@ PreprocessorDefinitions="" /> + + + @@ -7292,6 +14122,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7314,6 +14162,15 @@ PreprocessorDefinitions="" /> + + + @@ -7323,6 +14180,15 @@ PreprocessorDefinitions="" /> + + + @@ -7332,6 +14198,15 @@ PreprocessorDefinitions="" /> + + + @@ -7341,6 +14216,15 @@ PreprocessorDefinitions="" /> + + + @@ -7350,6 +14234,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7369,6 +14272,15 @@ PreprocessorDefinitions="" /> + + + @@ -7378,6 +14290,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7397,6 +14328,15 @@ PreprocessorDefinitions="" /> + + + @@ -7406,6 +14346,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7428,6 +14386,15 @@ PreprocessorDefinitions="" /> + + + @@ -7437,6 +14404,15 @@ PreprocessorDefinitions="" /> + + + @@ -7446,6 +14422,15 @@ PreprocessorDefinitions="" /> + + + @@ -7455,6 +14440,15 @@ PreprocessorDefinitions="" /> + + + @@ -7464,6 +14458,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7483,6 +14496,15 @@ PreprocessorDefinitions="" /> + + + @@ -7492,6 +14514,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7511,6 +14552,15 @@ PreprocessorDefinitions="" /> + + + @@ -7520,6 +14570,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7542,6 +14610,15 @@ PreprocessorDefinitions="" /> + + + @@ -7551,6 +14628,15 @@ PreprocessorDefinitions="" /> + + + @@ -7560,6 +14646,15 @@ PreprocessorDefinitions="" /> + + + @@ -7569,6 +14664,15 @@ PreprocessorDefinitions="" /> + + + @@ -7578,6 +14682,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7597,6 +14720,15 @@ PreprocessorDefinitions="" /> + + + @@ -7606,6 +14738,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7625,6 +14776,15 @@ PreprocessorDefinitions="" /> + + + @@ -7634,6 +14794,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7656,6 +14834,15 @@ PreprocessorDefinitions="" /> + + + @@ -7665,6 +14852,15 @@ PreprocessorDefinitions="" /> + + + @@ -7674,6 +14870,15 @@ PreprocessorDefinitions="" /> + + + @@ -7683,6 +14888,15 @@ PreprocessorDefinitions="" /> + + + @@ -7692,6 +14906,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7711,6 +14944,15 @@ PreprocessorDefinitions="" /> + + + @@ -7720,6 +14962,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7740,6 +15002,15 @@ PreprocessorDefinitions="" /> + + + @@ -7749,6 +15020,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7771,6 +15060,15 @@ PreprocessorDefinitions="" /> + + + @@ -7780,6 +15078,15 @@ PreprocessorDefinitions="" /> + + + @@ -7789,6 +15096,15 @@ PreprocessorDefinitions="" /> + + + @@ -7798,6 +15114,15 @@ PreprocessorDefinitions="" /> + + + @@ -7807,6 +15132,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7826,6 +15170,15 @@ PreprocessorDefinitions="" /> + + + @@ -7835,6 +15188,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7854,6 +15226,15 @@ PreprocessorDefinitions="" /> + + + @@ -7863,6 +15244,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7885,6 +15284,15 @@ PreprocessorDefinitions="" /> + + + @@ -7894,6 +15302,15 @@ PreprocessorDefinitions="" /> + + + @@ -7903,6 +15320,15 @@ PreprocessorDefinitions="" /> + + + @@ -7912,6 +15338,15 @@ PreprocessorDefinitions="" /> + + + @@ -7921,6 +15356,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7940,6 +15394,15 @@ PreprocessorDefinitions="" /> + + + @@ -7949,6 +15412,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7968,6 +15450,15 @@ PreprocessorDefinitions="" /> + + + @@ -7977,6 +15468,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -7999,6 +15508,15 @@ PreprocessorDefinitions="" /> + + + @@ -8008,6 +15526,15 @@ PreprocessorDefinitions="" /> + + + @@ -8017,6 +15544,15 @@ PreprocessorDefinitions="" /> + + + @@ -8026,6 +15562,15 @@ PreprocessorDefinitions="" /> + + + @@ -8035,6 +15580,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8054,6 +15618,15 @@ PreprocessorDefinitions="" /> + + + @@ -8063,6 +15636,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8082,6 +15674,15 @@ PreprocessorDefinitions="" /> + + + @@ -8091,6 +15692,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8115,6 +15735,16 @@ UsePrecompiledHeader="0" /> + + + @@ -8125,6 +15755,16 @@ UsePrecompiledHeader="0" /> + + + @@ -8135,6 +15775,16 @@ UsePrecompiledHeader="0" /> + + + @@ -8145,6 +15795,16 @@ UsePrecompiledHeader="0" /> + + + @@ -8155,6 +15815,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -8176,6 +15857,16 @@ UsePrecompiledHeader="0" /> + + + @@ -8186,6 +15877,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -8207,6 +15919,16 @@ UsePrecompiledHeader="0" /> + + + @@ -8217,6 +15939,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -8239,6 +15980,15 @@ PreprocessorDefinitions="" /> + + + @@ -8248,6 +15998,15 @@ PreprocessorDefinitions="" /> + + + @@ -8257,6 +16016,15 @@ PreprocessorDefinitions="" /> + + + @@ -8266,6 +16034,15 @@ PreprocessorDefinitions="" /> + + + @@ -8275,6 +16052,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8294,6 +16090,15 @@ PreprocessorDefinitions="" /> + + + @@ -8303,6 +16108,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8322,6 +16146,15 @@ PreprocessorDefinitions="" /> + + + @@ -8331,6 +16164,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8353,6 +16204,15 @@ PreprocessorDefinitions="" /> + + + @@ -8362,6 +16222,15 @@ PreprocessorDefinitions="" /> + + + @@ -8371,6 +16240,15 @@ PreprocessorDefinitions="" /> + + + @@ -8380,6 +16258,15 @@ PreprocessorDefinitions="" /> + + + @@ -8389,6 +16276,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8408,6 +16314,15 @@ PreprocessorDefinitions="" /> + + + @@ -8417,6 +16332,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8436,6 +16370,15 @@ PreprocessorDefinitions="" /> + + + @@ -8445,6 +16388,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8467,6 +16428,15 @@ PreprocessorDefinitions="" /> + + + @@ -8476,6 +16446,15 @@ PreprocessorDefinitions="" /> + + + @@ -8485,6 +16464,15 @@ PreprocessorDefinitions="" /> + + + @@ -8494,6 +16482,15 @@ PreprocessorDefinitions="" /> + + + @@ -8503,6 +16500,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8522,6 +16538,15 @@ PreprocessorDefinitions="" /> + + + @@ -8531,6 +16556,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8550,6 +16594,15 @@ PreprocessorDefinitions="" /> + + + @@ -8559,6 +16612,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8581,6 +16652,15 @@ PreprocessorDefinitions="" /> + + + @@ -8590,6 +16670,15 @@ PreprocessorDefinitions="" /> + + + @@ -8599,6 +16688,15 @@ PreprocessorDefinitions="" /> + + + @@ -8608,6 +16706,15 @@ PreprocessorDefinitions="" /> + + + @@ -8617,6 +16724,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8636,6 +16762,15 @@ PreprocessorDefinitions="" /> + + + @@ -8645,6 +16780,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8664,6 +16818,15 @@ PreprocessorDefinitions="" /> + + + @@ -8673,6 +16836,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8695,6 +16876,15 @@ PreprocessorDefinitions="" /> + + + @@ -8704,6 +16894,15 @@ PreprocessorDefinitions="" /> + + + @@ -8713,6 +16912,15 @@ PreprocessorDefinitions="" /> + + + @@ -8722,6 +16930,15 @@ PreprocessorDefinitions="" /> + + + @@ -8731,6 +16948,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8750,6 +16986,15 @@ PreprocessorDefinitions="" /> + + + @@ -8759,6 +17004,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8778,6 +17042,15 @@ PreprocessorDefinitions="" /> + + + @@ -8787,6 +17060,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8809,6 +17100,15 @@ PreprocessorDefinitions="" /> + + + @@ -8818,6 +17118,15 @@ PreprocessorDefinitions="" /> + + + @@ -8827,6 +17136,15 @@ PreprocessorDefinitions="" /> + + + @@ -8836,6 +17154,15 @@ PreprocessorDefinitions="" /> + + + @@ -8845,6 +17172,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8864,6 +17210,15 @@ PreprocessorDefinitions="" /> + + + @@ -8873,6 +17228,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8892,6 +17266,15 @@ PreprocessorDefinitions="" /> + + + @@ -8901,6 +17284,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8923,6 +17324,15 @@ PreprocessorDefinitions="" /> + + + @@ -8932,6 +17342,15 @@ PreprocessorDefinitions="" /> + + + @@ -8941,6 +17360,15 @@ PreprocessorDefinitions="" /> + + + @@ -8950,6 +17378,15 @@ PreprocessorDefinitions="" /> + + + @@ -8959,6 +17396,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -8978,6 +17434,15 @@ PreprocessorDefinitions="" /> + + + @@ -8987,6 +17452,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9006,6 +17490,15 @@ PreprocessorDefinitions="" /> + + + @@ -9015,6 +17508,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9037,6 +17548,15 @@ PreprocessorDefinitions="" /> + + + @@ -9046,6 +17566,15 @@ PreprocessorDefinitions="" /> + + + @@ -9055,6 +17584,15 @@ PreprocessorDefinitions="" /> + + + @@ -9064,6 +17602,15 @@ PreprocessorDefinitions="" /> + + + @@ -9073,6 +17620,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9092,6 +17658,15 @@ PreprocessorDefinitions="" /> + + + @@ -9101,6 +17676,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9120,6 +17714,15 @@ PreprocessorDefinitions="" /> + + + @@ -9129,6 +17732,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9151,6 +17772,15 @@ PreprocessorDefinitions="" /> + + + @@ -9160,6 +17790,15 @@ PreprocessorDefinitions="" /> + + + @@ -9169,6 +17808,15 @@ PreprocessorDefinitions="" /> + + + @@ -9178,6 +17826,15 @@ PreprocessorDefinitions="" /> + + + @@ -9187,6 +17844,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9206,6 +17882,15 @@ PreprocessorDefinitions="" /> + + + @@ -9215,6 +17900,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9234,6 +17938,15 @@ PreprocessorDefinitions="" /> + + + @@ -9243,6 +17956,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9265,6 +17996,15 @@ PreprocessorDefinitions="" /> + + + @@ -9274,6 +18014,15 @@ PreprocessorDefinitions="" /> + + + @@ -9283,6 +18032,15 @@ PreprocessorDefinitions="" /> + + + @@ -9292,6 +18050,15 @@ PreprocessorDefinitions="" /> + + + @@ -9301,6 +18068,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9320,6 +18106,15 @@ PreprocessorDefinitions="" /> + + + @@ -9329,6 +18124,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9348,6 +18162,15 @@ PreprocessorDefinitions="" /> + + + @@ -9357,6 +18180,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9379,6 +18220,15 @@ PreprocessorDefinitions="" /> + + + @@ -9388,6 +18238,15 @@ PreprocessorDefinitions="" /> + + + @@ -9397,6 +18256,15 @@ PreprocessorDefinitions="" /> + + + @@ -9406,6 +18274,15 @@ PreprocessorDefinitions="" /> + + + @@ -9415,6 +18292,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9434,6 +18330,15 @@ PreprocessorDefinitions="" /> + + + @@ -9443,6 +18348,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9462,6 +18386,15 @@ PreprocessorDefinitions="" /> + + + @@ -9471,6 +18404,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9493,6 +18444,15 @@ PreprocessorDefinitions="" /> + + + @@ -9502,6 +18462,15 @@ PreprocessorDefinitions="" /> + + + @@ -9511,6 +18480,15 @@ PreprocessorDefinitions="" /> + + + @@ -9520,6 +18498,15 @@ PreprocessorDefinitions="" /> + + + @@ -9529,6 +18516,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9548,6 +18554,15 @@ PreprocessorDefinitions="" /> + + + @@ -9557,6 +18572,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9576,6 +18610,15 @@ PreprocessorDefinitions="" /> + + + @@ -9585,6 +18628,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9607,6 +18668,15 @@ PreprocessorDefinitions="" /> + + + @@ -9616,6 +18686,15 @@ PreprocessorDefinitions="" /> + + + @@ -9625,6 +18704,15 @@ PreprocessorDefinitions="" /> + + + @@ -9634,6 +18722,15 @@ PreprocessorDefinitions="" /> + + + @@ -9643,6 +18740,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9662,6 +18778,15 @@ PreprocessorDefinitions="" /> + + + @@ -9671,6 +18796,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9690,6 +18834,15 @@ PreprocessorDefinitions="" /> + + + @@ -9699,6 +18852,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9721,6 +18892,15 @@ PreprocessorDefinitions="" /> + + + @@ -9730,6 +18910,15 @@ PreprocessorDefinitions="" /> + + + @@ -9739,6 +18928,15 @@ PreprocessorDefinitions="" /> + + + @@ -9748,6 +18946,15 @@ PreprocessorDefinitions="" /> + + + @@ -9757,6 +18964,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9776,6 +19002,15 @@ PreprocessorDefinitions="" /> + + + @@ -9785,6 +19020,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9804,6 +19058,15 @@ PreprocessorDefinitions="" /> + + + @@ -9813,6 +19076,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9835,6 +19116,15 @@ PreprocessorDefinitions="" /> + + + @@ -9844,6 +19134,15 @@ PreprocessorDefinitions="" /> + + + @@ -9853,6 +19152,15 @@ PreprocessorDefinitions="" /> + + + @@ -9862,6 +19170,15 @@ PreprocessorDefinitions="" /> + + + @@ -9871,6 +19188,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9890,6 +19226,15 @@ PreprocessorDefinitions="" /> + + + @@ -9899,6 +19244,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9918,6 +19282,15 @@ PreprocessorDefinitions="" /> + + + @@ -9927,6 +19300,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -9949,6 +19340,15 @@ PreprocessorDefinitions="" /> + + + @@ -9958,6 +19358,15 @@ PreprocessorDefinitions="" /> + + + @@ -9967,6 +19376,15 @@ PreprocessorDefinitions="" /> + + + @@ -9976,6 +19394,15 @@ PreprocessorDefinitions="" /> + + + @@ -9985,6 +19412,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10004,6 +19450,15 @@ PreprocessorDefinitions="" /> + + + @@ -10013,6 +19468,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10032,6 +19506,15 @@ PreprocessorDefinitions="" /> + + + @@ -10041,6 +19524,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10063,6 +19564,15 @@ PreprocessorDefinitions="" /> + + + @@ -10072,6 +19582,15 @@ PreprocessorDefinitions="" /> + + + @@ -10081,6 +19600,15 @@ PreprocessorDefinitions="" /> + + + @@ -10090,6 +19618,15 @@ PreprocessorDefinitions="" /> + + + @@ -10099,6 +19636,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10118,6 +19674,15 @@ PreprocessorDefinitions="" /> + + + @@ -10127,6 +19692,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10146,6 +19730,15 @@ PreprocessorDefinitions="" /> + + + @@ -10155,6 +19748,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10177,6 +19788,15 @@ PreprocessorDefinitions="" /> + + + @@ -10186,6 +19806,15 @@ PreprocessorDefinitions="" /> + + + @@ -10195,6 +19824,15 @@ PreprocessorDefinitions="" /> + + + @@ -10204,6 +19842,15 @@ PreprocessorDefinitions="" /> + + + @@ -10213,6 +19860,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10232,6 +19898,15 @@ PreprocessorDefinitions="" /> + + + @@ -10241,6 +19916,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10260,6 +19954,15 @@ PreprocessorDefinitions="" /> + + + @@ -10269,6 +19972,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -10419,6 +20260,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -10448,6 +20318,15 @@ PreprocessorDefinitions="" /> + + + @@ -10457,6 +20336,15 @@ PreprocessorDefinitions="" /> + + + @@ -10466,6 +20354,15 @@ PreprocessorDefinitions="" /> + + + @@ -10475,6 +20372,15 @@ PreprocessorDefinitions="" /> + + + @@ -10484,6 +20390,15 @@ PreprocessorDefinitions="" /> + + + @@ -10493,6 +20408,15 @@ PreprocessorDefinitions="" /> + + + @@ -10502,6 +20426,15 @@ PreprocessorDefinitions="" /> + + + @@ -10511,6 +20444,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10533,6 +20484,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -10562,6 +20542,15 @@ PreprocessorDefinitions="" /> + + + @@ -10571,6 +20560,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10590,6 +20598,15 @@ PreprocessorDefinitions="" /> + + + @@ -10599,6 +20616,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10618,6 +20654,15 @@ PreprocessorDefinitions="" /> + + + @@ -10627,6 +20672,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10649,6 +20712,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10668,6 +20750,15 @@ PreprocessorDefinitions="" /> + + + @@ -10677,6 +20768,15 @@ PreprocessorDefinitions="" /> + + + @@ -10686,6 +20786,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10705,6 +20824,15 @@ PreprocessorDefinitions="" /> + + + @@ -10714,6 +20842,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10733,6 +20880,15 @@ PreprocessorDefinitions="" /> + + + @@ -10742,6 +20898,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10764,6 +20938,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -10793,6 +20996,15 @@ PreprocessorDefinitions="" /> + + + @@ -10802,6 +21014,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10821,6 +21052,15 @@ PreprocessorDefinitions="" /> + + + @@ -10830,6 +21070,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10849,6 +21108,15 @@ PreprocessorDefinitions="" /> + + + @@ -10858,6 +21126,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -10882,6 +21169,16 @@ UsePrecompiledHeader="0" /> + + + + + + + + + @@ -10914,6 +21233,16 @@ UsePrecompiledHeader="0" /> + + + @@ -10924,6 +21253,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -10945,6 +21295,16 @@ UsePrecompiledHeader="0" /> + + + @@ -10955,6 +21315,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -10976,6 +21357,16 @@ UsePrecompiledHeader="0" /> + + + @@ -10986,6 +21377,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -11008,6 +21418,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11027,6 +21456,15 @@ PreprocessorDefinitions="" /> + + + @@ -11036,6 +21474,15 @@ PreprocessorDefinitions="" /> + + + @@ -11045,6 +21492,15 @@ PreprocessorDefinitions="" /> + + + @@ -11054,6 +21510,15 @@ PreprocessorDefinitions="" /> + + + @@ -11063,6 +21528,15 @@ PreprocessorDefinitions="" /> + + + @@ -11072,6 +21546,15 @@ PreprocessorDefinitions="" /> + + + @@ -11081,6 +21564,15 @@ PreprocessorDefinitions="" /> + + + @@ -11090,6 +21582,15 @@ PreprocessorDefinitions="" /> + + + @@ -11099,6 +21600,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11121,6 +21640,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11150,6 +21698,15 @@ PreprocessorDefinitions="" /> + + + @@ -11159,6 +21716,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11178,6 +21754,15 @@ PreprocessorDefinitions="" /> + + + @@ -11187,6 +21772,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11206,6 +21810,15 @@ PreprocessorDefinitions="" /> + + + @@ -11215,6 +21828,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11237,6 +21868,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11266,6 +21926,15 @@ PreprocessorDefinitions="" /> + + + @@ -11275,6 +21944,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11294,6 +21982,15 @@ PreprocessorDefinitions="" /> + + + @@ -11303,6 +22000,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11322,6 +22038,15 @@ PreprocessorDefinitions="" /> + + + @@ -11331,6 +22056,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11353,6 +22096,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11382,6 +22154,15 @@ PreprocessorDefinitions="" /> + + + @@ -11391,6 +22172,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11410,6 +22210,15 @@ PreprocessorDefinitions="" /> + + + @@ -11419,6 +22228,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11438,6 +22266,15 @@ PreprocessorDefinitions="" /> + + + @@ -11447,6 +22284,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11469,6 +22324,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11498,6 +22382,15 @@ PreprocessorDefinitions="" /> + + + @@ -11507,6 +22400,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11526,6 +22438,15 @@ PreprocessorDefinitions="" /> + + + @@ -11535,6 +22456,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11554,6 +22494,15 @@ PreprocessorDefinitions="" /> + + + @@ -11563,6 +22512,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11585,6 +22552,15 @@ PreprocessorDefinitions="" /> + + + @@ -11594,6 +22570,15 @@ PreprocessorDefinitions="" /> + + + @@ -11603,6 +22588,15 @@ PreprocessorDefinitions="" /> + + + @@ -11612,6 +22606,15 @@ PreprocessorDefinitions="" /> + + + @@ -11621,6 +22624,15 @@ PreprocessorDefinitions="" /> + + + @@ -11630,6 +22642,15 @@ PreprocessorDefinitions="" /> + + + @@ -11639,6 +22660,15 @@ PreprocessorDefinitions="" /> + + + @@ -11648,6 +22678,15 @@ PreprocessorDefinitions="" /> + + + @@ -11657,6 +22696,15 @@ PreprocessorDefinitions="" /> + + + @@ -11666,6 +22714,15 @@ PreprocessorDefinitions="" /> + + + @@ -11675,6 +22732,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11697,6 +22772,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11726,6 +22830,15 @@ PreprocessorDefinitions="" /> + + + @@ -11735,6 +22848,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11754,6 +22886,15 @@ PreprocessorDefinitions="" /> + + + @@ -11763,6 +22904,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11782,6 +22942,15 @@ PreprocessorDefinitions="" /> + + + @@ -11791,6 +22960,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11813,6 +23000,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11842,6 +23058,15 @@ PreprocessorDefinitions="" /> + + + @@ -11851,6 +23076,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11870,6 +23114,15 @@ PreprocessorDefinitions="" /> + + + @@ -11879,6 +23132,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11898,6 +23170,15 @@ PreprocessorDefinitions="" /> + + + @@ -11907,6 +23188,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11929,6 +23228,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -11958,6 +23286,15 @@ PreprocessorDefinitions="" /> + + + @@ -11967,6 +23304,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -11986,6 +23342,15 @@ PreprocessorDefinitions="" /> + + + @@ -11995,6 +23360,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12014,6 +23398,15 @@ PreprocessorDefinitions="" /> + + + @@ -12023,6 +23416,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12045,6 +23456,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12074,6 +23514,15 @@ PreprocessorDefinitions="" /> + + + @@ -12083,6 +23532,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12102,6 +23570,15 @@ PreprocessorDefinitions="" /> + + + @@ -12111,6 +23588,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12130,6 +23626,15 @@ PreprocessorDefinitions="" /> + + + @@ -12139,6 +23644,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12161,6 +23684,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12190,6 +23742,15 @@ PreprocessorDefinitions="" /> + + + @@ -12199,6 +23760,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12218,6 +23798,15 @@ PreprocessorDefinitions="" /> + + + @@ -12227,6 +23816,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12246,6 +23854,15 @@ PreprocessorDefinitions="" /> + + + @@ -12255,6 +23872,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12277,6 +23912,15 @@ PreprocessorDefinitions="" /> + + + @@ -12286,6 +23930,15 @@ PreprocessorDefinitions="" /> + + + @@ -12295,6 +23948,15 @@ PreprocessorDefinitions="" /> + + + @@ -12304,6 +23966,15 @@ PreprocessorDefinitions="" /> + + + @@ -12313,6 +23984,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12332,6 +24022,15 @@ PreprocessorDefinitions="" /> + + + @@ -12341,6 +24040,15 @@ PreprocessorDefinitions="" /> + + + @@ -12350,6 +24058,15 @@ PreprocessorDefinitions="" /> + + + @@ -12359,6 +24076,15 @@ PreprocessorDefinitions="" /> + + + @@ -12368,6 +24094,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12390,6 +24134,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12419,6 +24192,15 @@ PreprocessorDefinitions="" /> + + + @@ -12428,6 +24210,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12447,6 +24248,15 @@ PreprocessorDefinitions="" /> + + + @@ -12456,6 +24266,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12475,6 +24304,15 @@ PreprocessorDefinitions="" /> + + + @@ -12484,6 +24322,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12506,6 +24362,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12535,6 +24420,15 @@ PreprocessorDefinitions="" /> + + + @@ -12544,6 +24438,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12563,6 +24476,15 @@ PreprocessorDefinitions="" /> + + + @@ -12572,6 +24494,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12591,6 +24532,15 @@ PreprocessorDefinitions="" /> + + + @@ -12600,6 +24550,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12622,6 +24590,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12651,6 +24648,15 @@ PreprocessorDefinitions="" /> + + + @@ -12660,6 +24666,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12679,6 +24704,15 @@ PreprocessorDefinitions="" /> + + + @@ -12688,6 +24722,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12707,6 +24760,15 @@ PreprocessorDefinitions="" /> + + + @@ -12716,6 +24778,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12738,6 +24818,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12767,6 +24876,15 @@ PreprocessorDefinitions="" /> + + + @@ -12776,6 +24894,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12795,6 +24932,15 @@ PreprocessorDefinitions="" /> + + + @@ -12804,6 +24950,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12833,6 +25008,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12855,6 +25048,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12884,6 +25106,15 @@ PreprocessorDefinitions="" /> + + + @@ -12893,6 +25124,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12912,6 +25162,15 @@ PreprocessorDefinitions="" /> + + + @@ -12921,6 +25180,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -12940,6 +25218,15 @@ PreprocessorDefinitions="" /> + + + @@ -12949,6 +25236,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -12986,6 +25302,15 @@ PreprocessorDefinitions="" /> + + + @@ -12995,6 +25320,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13034,6 +25398,15 @@ PreprocessorDefinitions="" /> + + + @@ -13043,6 +25416,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13062,6 +25454,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13105,6 +25536,15 @@ PreprocessorDefinitions="" /> + + + @@ -13114,6 +25554,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13153,6 +25632,15 @@ PreprocessorDefinitions="" /> + + + @@ -13162,6 +25650,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13181,6 +25688,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13224,6 +25770,15 @@ PreprocessorDefinitions="" /> + + + @@ -13233,6 +25788,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13272,6 +25866,15 @@ PreprocessorDefinitions="" /> + + + @@ -13281,6 +25884,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13300,6 +25922,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13343,6 +26004,15 @@ PreprocessorDefinitions="" /> + + + @@ -13352,6 +26022,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13391,6 +26100,15 @@ PreprocessorDefinitions="" /> + + + @@ -13400,6 +26118,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13419,6 +26156,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13462,6 +26238,15 @@ PreprocessorDefinitions="" /> + + + @@ -13471,6 +26256,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13510,6 +26334,15 @@ PreprocessorDefinitions="" /> + + + @@ -13519,6 +26352,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13538,6 +26390,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13581,6 +26472,15 @@ PreprocessorDefinitions="" /> + + + @@ -13590,6 +26490,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13629,6 +26568,15 @@ PreprocessorDefinitions="" /> + + + @@ -13638,6 +26586,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13657,6 +26624,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13700,6 +26706,15 @@ PreprocessorDefinitions="" /> + + + @@ -13709,6 +26724,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13748,6 +26802,15 @@ PreprocessorDefinitions="" /> + + + @@ -13757,6 +26820,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13776,6 +26858,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13819,6 +26940,15 @@ PreprocessorDefinitions="" /> + + + @@ -13828,6 +26958,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13867,6 +27036,15 @@ PreprocessorDefinitions="" /> + + + @@ -13876,6 +27054,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -13895,6 +27092,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13938,6 +27174,15 @@ PreprocessorDefinitions="" /> + + + @@ -13947,6 +27192,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -13986,6 +27270,15 @@ PreprocessorDefinitions="" /> + + + @@ -13995,6 +27288,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14014,6 +27326,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14057,6 +27408,15 @@ PreprocessorDefinitions="" /> + + + @@ -14066,6 +27426,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14105,6 +27504,15 @@ PreprocessorDefinitions="" /> + + + @@ -14114,6 +27522,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14133,6 +27560,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14176,6 +27642,15 @@ PreprocessorDefinitions="" /> + + + @@ -14185,6 +27660,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14224,6 +27738,15 @@ PreprocessorDefinitions="" /> + + + @@ -14233,6 +27756,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14252,6 +27794,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14295,6 +27876,15 @@ PreprocessorDefinitions="" /> + + + @@ -14304,6 +27894,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14343,6 +27972,15 @@ PreprocessorDefinitions="" /> + + + @@ -14352,6 +27990,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14371,6 +28028,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14414,6 +28110,15 @@ PreprocessorDefinitions="" /> + + + @@ -14423,6 +28128,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14462,6 +28206,15 @@ PreprocessorDefinitions="" /> + + + @@ -14471,6 +28224,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14490,6 +28262,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14533,6 +28344,15 @@ PreprocessorDefinitions="" /> + + + @@ -14542,6 +28362,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14581,6 +28440,15 @@ PreprocessorDefinitions="" /> + + + @@ -14590,6 +28458,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14609,6 +28496,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14652,6 +28578,15 @@ PreprocessorDefinitions="" /> + + + @@ -14661,6 +28596,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14700,6 +28674,15 @@ PreprocessorDefinitions="" /> + + + @@ -14709,6 +28692,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14728,6 +28730,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14771,6 +28812,15 @@ PreprocessorDefinitions="" /> + + + @@ -14780,6 +28830,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14819,6 +28908,15 @@ PreprocessorDefinitions="" /> + + + @@ -14828,6 +28926,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14847,6 +28964,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14890,6 +29046,15 @@ PreprocessorDefinitions="" /> + + + @@ -14899,6 +29064,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -14938,6 +29142,15 @@ PreprocessorDefinitions="" /> + + + @@ -14947,6 +29160,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -14966,6 +29198,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15009,6 +29280,15 @@ PreprocessorDefinitions="" /> + + + @@ -15018,6 +29298,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15057,6 +29376,15 @@ PreprocessorDefinitions="" /> + + + @@ -15066,6 +29394,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15085,6 +29432,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15128,6 +29514,15 @@ PreprocessorDefinitions="" /> + + + @@ -15137,6 +29532,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15176,6 +29610,15 @@ PreprocessorDefinitions="" /> + + + @@ -15185,6 +29628,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15204,6 +29666,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15247,6 +29748,15 @@ PreprocessorDefinitions="" /> + + + @@ -15256,6 +29766,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15295,6 +29844,15 @@ PreprocessorDefinitions="" /> + + + @@ -15304,6 +29862,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15323,6 +29900,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15366,6 +29982,15 @@ PreprocessorDefinitions="" /> + + + @@ -15375,6 +30000,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15414,6 +30078,15 @@ PreprocessorDefinitions="" /> + + + @@ -15423,6 +30096,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15442,6 +30134,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15485,6 +30216,15 @@ PreprocessorDefinitions="" /> + + + @@ -15494,6 +30234,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15533,6 +30312,15 @@ PreprocessorDefinitions="" /> + + + @@ -15542,6 +30330,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15561,6 +30368,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15604,6 +30450,15 @@ PreprocessorDefinitions="" /> + + + @@ -15613,6 +30468,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15652,6 +30546,15 @@ PreprocessorDefinitions="" /> + + + @@ -15661,6 +30564,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15680,6 +30602,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15723,6 +30684,15 @@ PreprocessorDefinitions="" /> + + + @@ -15732,6 +30702,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15771,6 +30780,15 @@ PreprocessorDefinitions="" /> + + + @@ -15780,6 +30798,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15799,6 +30836,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15842,6 +30918,15 @@ PreprocessorDefinitions="" /> + + + @@ -15851,6 +30936,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15890,6 +31014,15 @@ PreprocessorDefinitions="" /> + + + @@ -15899,6 +31032,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -15918,6 +31070,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -15961,6 +31152,15 @@ PreprocessorDefinitions="" /> + + + @@ -15970,6 +31170,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16009,6 +31248,15 @@ PreprocessorDefinitions="" /> + + + @@ -16018,6 +31266,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16037,6 +31304,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16080,6 +31386,15 @@ PreprocessorDefinitions="" /> + + + @@ -16089,6 +31404,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16128,6 +31482,15 @@ PreprocessorDefinitions="" /> + + + @@ -16137,6 +31500,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16156,6 +31538,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16199,6 +31620,15 @@ PreprocessorDefinitions="" /> + + + @@ -16208,6 +31638,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16247,6 +31716,15 @@ PreprocessorDefinitions="" /> + + + @@ -16256,6 +31734,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16275,6 +31772,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16318,6 +31854,15 @@ PreprocessorDefinitions="" /> + + + @@ -16327,6 +31872,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16366,6 +31950,15 @@ PreprocessorDefinitions="" /> + + + @@ -16375,6 +31968,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16394,6 +32006,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16437,6 +32088,15 @@ PreprocessorDefinitions="" /> + + + @@ -16446,6 +32106,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16485,6 +32184,15 @@ PreprocessorDefinitions="" /> + + + @@ -16494,6 +32202,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16513,6 +32240,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16556,6 +32322,15 @@ PreprocessorDefinitions="" /> + + + @@ -16565,6 +32340,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16604,6 +32418,15 @@ PreprocessorDefinitions="" /> + + + @@ -16613,6 +32436,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16632,6 +32474,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16675,6 +32556,15 @@ PreprocessorDefinitions="" /> + + + @@ -16684,6 +32574,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + @@ -16723,6 +32652,15 @@ PreprocessorDefinitions="" /> + + + @@ -16732,6 +32670,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16751,6 +32708,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + @@ -16791,6 +32776,15 @@ PreprocessorDefinitions="" /> + + + @@ -16800,6 +32794,15 @@ PreprocessorDefinitions="" /> + + + @@ -16809,6 +32812,15 @@ PreprocessorDefinitions="" /> + + + @@ -16818,6 +32830,15 @@ PreprocessorDefinitions="" /> + + + @@ -16827,6 +32848,15 @@ PreprocessorDefinitions="" /> + + + @@ -16836,6 +32866,15 @@ PreprocessorDefinitions="" /> + + + @@ -16845,6 +32884,15 @@ PreprocessorDefinitions="" /> + + + @@ -16854,6 +32902,15 @@ PreprocessorDefinitions="" /> + + + @@ -16863,6 +32920,15 @@ PreprocessorDefinitions="" /> + + + @@ -16872,6 +32938,15 @@ PreprocessorDefinitions="" /> + + + @@ -16881,6 +32956,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -16903,6 +32996,15 @@ PreprocessorDefinitions="" /> + + + @@ -16912,6 +33014,15 @@ PreprocessorDefinitions="" /> + + + @@ -16921,6 +33032,15 @@ PreprocessorDefinitions="" /> + + + @@ -16930,6 +33050,15 @@ PreprocessorDefinitions="" /> + + + @@ -16939,6 +33068,15 @@ PreprocessorDefinitions="" /> + + + @@ -16948,6 +33086,15 @@ PreprocessorDefinitions="" /> + + + @@ -16957,6 +33104,15 @@ PreprocessorDefinitions="" /> + + + @@ -16966,6 +33122,15 @@ PreprocessorDefinitions="" /> + + + @@ -16975,6 +33140,15 @@ PreprocessorDefinitions="" /> + + + @@ -16984,6 +33158,15 @@ PreprocessorDefinitions="" /> + + + @@ -16993,6 +33176,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17017,6 +33219,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17027,6 +33239,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17037,6 +33259,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17047,6 +33279,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17057,6 +33299,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17067,6 +33319,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17077,6 +33339,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17087,6 +33359,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17097,6 +33379,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17107,6 +33399,16 @@ UsePrecompiledHeader="1" /> + + + @@ -17117,6 +33419,16 @@ UsePrecompiledHeader="1" /> + + + + + + @@ -17139,6 +33460,15 @@ PreprocessorDefinitions="" /> + + + @@ -17148,6 +33478,15 @@ PreprocessorDefinitions="" /> + + + @@ -17157,6 +33496,15 @@ PreprocessorDefinitions="" /> + + + @@ -17166,6 +33514,15 @@ PreprocessorDefinitions="" /> + + + @@ -17175,6 +33532,15 @@ PreprocessorDefinitions="" /> + + + @@ -17184,6 +33550,15 @@ PreprocessorDefinitions="" /> + + + @@ -17193,6 +33568,15 @@ PreprocessorDefinitions="" /> + + + @@ -17202,6 +33586,15 @@ PreprocessorDefinitions="" /> + + + @@ -17211,6 +33604,15 @@ PreprocessorDefinitions="" /> + + + @@ -17220,6 +33622,15 @@ PreprocessorDefinitions="" /> + + + @@ -17229,6 +33640,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17251,6 +33680,15 @@ PreprocessorDefinitions="" /> + + + @@ -17260,6 +33698,15 @@ PreprocessorDefinitions="" /> + + + @@ -17269,6 +33716,15 @@ PreprocessorDefinitions="" /> + + + @@ -17278,6 +33734,15 @@ PreprocessorDefinitions="" /> + + + @@ -17287,6 +33752,15 @@ PreprocessorDefinitions="" /> + + + @@ -17296,6 +33770,15 @@ PreprocessorDefinitions="" /> + + + @@ -17305,6 +33788,15 @@ PreprocessorDefinitions="" /> + + + @@ -17314,6 +33806,15 @@ PreprocessorDefinitions="" /> + + + @@ -17323,6 +33824,15 @@ PreprocessorDefinitions="" /> + + + @@ -17332,6 +33842,15 @@ PreprocessorDefinitions="" /> + + + @@ -17341,6 +33860,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17363,6 +33900,15 @@ PreprocessorDefinitions="" /> + + + @@ -17372,6 +33918,15 @@ PreprocessorDefinitions="" /> + + + @@ -17381,6 +33936,15 @@ PreprocessorDefinitions="" /> + + + @@ -17390,6 +33954,15 @@ PreprocessorDefinitions="" /> + + + @@ -17399,6 +33972,15 @@ PreprocessorDefinitions="" /> + + + @@ -17408,6 +33990,15 @@ PreprocessorDefinitions="" /> + + + @@ -17417,6 +34008,15 @@ PreprocessorDefinitions="" /> + + + @@ -17426,6 +34026,15 @@ PreprocessorDefinitions="" /> + + + @@ -17435,6 +34044,15 @@ PreprocessorDefinitions="" /> + + + @@ -17444,6 +34062,15 @@ PreprocessorDefinitions="" /> + + + @@ -17453,6 +34080,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17475,6 +34120,15 @@ PreprocessorDefinitions="" /> + + + @@ -17484,6 +34138,15 @@ PreprocessorDefinitions="" /> + + + @@ -17493,6 +34156,15 @@ PreprocessorDefinitions="" /> + + + @@ -17502,6 +34174,15 @@ PreprocessorDefinitions="" /> + + + @@ -17511,6 +34192,15 @@ PreprocessorDefinitions="" /> + + + @@ -17520,6 +34210,15 @@ PreprocessorDefinitions="" /> + + + @@ -17529,6 +34228,15 @@ PreprocessorDefinitions="" /> + + + @@ -17538,6 +34246,15 @@ PreprocessorDefinitions="" /> + + + @@ -17547,6 +34264,15 @@ PreprocessorDefinitions="" /> + + + @@ -17556,6 +34282,15 @@ PreprocessorDefinitions="" /> + + + @@ -17565,6 +34300,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17587,6 +34340,15 @@ PreprocessorDefinitions="" /> + + + @@ -17596,6 +34358,15 @@ PreprocessorDefinitions="" /> + + + @@ -17605,6 +34376,15 @@ PreprocessorDefinitions="" /> + + + @@ -17614,6 +34394,15 @@ PreprocessorDefinitions="" /> + + + @@ -17623,6 +34412,15 @@ PreprocessorDefinitions="" /> + + + @@ -17632,6 +34430,15 @@ PreprocessorDefinitions="" /> + + + @@ -17641,6 +34448,15 @@ PreprocessorDefinitions="" /> + + + @@ -17650,6 +34466,15 @@ PreprocessorDefinitions="" /> + + + @@ -17659,6 +34484,15 @@ PreprocessorDefinitions="" /> + + + @@ -17668,6 +34502,15 @@ PreprocessorDefinitions="" /> + + + @@ -17677,6 +34520,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17699,6 +34560,15 @@ PreprocessorDefinitions="" /> + + + @@ -17708,6 +34578,15 @@ PreprocessorDefinitions="" /> + + + @@ -17717,6 +34596,15 @@ PreprocessorDefinitions="" /> + + + @@ -17726,6 +34614,15 @@ PreprocessorDefinitions="" /> + + + @@ -17735,6 +34632,15 @@ PreprocessorDefinitions="" /> + + + @@ -17744,6 +34650,15 @@ PreprocessorDefinitions="" /> + + + @@ -17753,6 +34668,15 @@ PreprocessorDefinitions="" /> + + + @@ -17762,6 +34686,15 @@ PreprocessorDefinitions="" /> + + + @@ -17771,6 +34704,15 @@ PreprocessorDefinitions="" /> + + + @@ -17780,6 +34722,15 @@ PreprocessorDefinitions="" /> + + + @@ -17789,6 +34740,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -17813,6 +34783,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17823,6 +34803,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17833,6 +34823,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17843,6 +34843,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17853,6 +34863,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17863,6 +34883,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17873,6 +34903,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17883,6 +34923,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17893,6 +34943,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17903,6 +34963,16 @@ UsePrecompiledHeader="0" /> + + + @@ -17913,6 +34983,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -17935,6 +35024,15 @@ PreprocessorDefinitions="" /> + + + @@ -17944,6 +35042,15 @@ PreprocessorDefinitions="" /> + + + @@ -17953,6 +35060,15 @@ PreprocessorDefinitions="" /> + + + @@ -17962,6 +35078,15 @@ PreprocessorDefinitions="" /> + + + @@ -17971,6 +35096,15 @@ PreprocessorDefinitions="" /> + + + @@ -17980,6 +35114,15 @@ PreprocessorDefinitions="" /> + + + @@ -17989,6 +35132,15 @@ PreprocessorDefinitions="" /> + + + @@ -17998,6 +35150,15 @@ PreprocessorDefinitions="" /> + + + @@ -18007,6 +35168,15 @@ PreprocessorDefinitions="" /> + + + @@ -18016,6 +35186,15 @@ PreprocessorDefinitions="" /> + + + @@ -18025,6 +35204,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18047,6 +35244,15 @@ PreprocessorDefinitions="" /> + + + @@ -18056,6 +35262,15 @@ PreprocessorDefinitions="" /> + + + @@ -18065,6 +35280,15 @@ PreprocessorDefinitions="" /> + + + @@ -18074,6 +35298,15 @@ PreprocessorDefinitions="" /> + + + @@ -18083,6 +35316,15 @@ PreprocessorDefinitions="" /> + + + @@ -18092,6 +35334,15 @@ PreprocessorDefinitions="" /> + + + @@ -18101,6 +35352,15 @@ PreprocessorDefinitions="" /> + + + @@ -18110,6 +35370,15 @@ PreprocessorDefinitions="" /> + + + @@ -18119,6 +35388,15 @@ PreprocessorDefinitions="" /> + + + @@ -18128,6 +35406,15 @@ PreprocessorDefinitions="" /> + + + @@ -18137,6 +35424,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18159,6 +35464,15 @@ PreprocessorDefinitions="" /> + + + @@ -18168,6 +35482,15 @@ PreprocessorDefinitions="" /> + + + @@ -18177,6 +35500,15 @@ PreprocessorDefinitions="" /> + + + @@ -18186,6 +35518,15 @@ PreprocessorDefinitions="" /> + + + @@ -18195,6 +35536,15 @@ PreprocessorDefinitions="" /> + + + @@ -18204,6 +35554,15 @@ PreprocessorDefinitions="" /> + + + @@ -18213,6 +35572,15 @@ PreprocessorDefinitions="" /> + + + @@ -18222,6 +35590,15 @@ PreprocessorDefinitions="" /> + + + @@ -18231,6 +35608,15 @@ PreprocessorDefinitions="" /> + + + @@ -18240,6 +35626,15 @@ PreprocessorDefinitions="" /> + + + @@ -18249,6 +35644,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18271,6 +35684,15 @@ PreprocessorDefinitions="" /> + + + @@ -18280,6 +35702,15 @@ PreprocessorDefinitions="" /> + + + @@ -18289,6 +35720,15 @@ PreprocessorDefinitions="" /> + + + @@ -18298,6 +35738,15 @@ PreprocessorDefinitions="" /> + + + @@ -18307,6 +35756,15 @@ PreprocessorDefinitions="" /> + + + @@ -18316,6 +35774,15 @@ PreprocessorDefinitions="" /> + + + @@ -18325,6 +35792,15 @@ PreprocessorDefinitions="" /> + + + @@ -18334,6 +35810,15 @@ PreprocessorDefinitions="" /> + + + @@ -18343,6 +35828,15 @@ PreprocessorDefinitions="" /> + + + @@ -18352,6 +35846,15 @@ PreprocessorDefinitions="" /> + + + @@ -18361,6 +35864,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18383,6 +35904,15 @@ PreprocessorDefinitions="" /> + + + @@ -18392,6 +35922,15 @@ PreprocessorDefinitions="" /> + + + @@ -18401,6 +35940,15 @@ PreprocessorDefinitions="" /> + + + @@ -18410,6 +35958,15 @@ PreprocessorDefinitions="" /> + + + @@ -18419,6 +35976,15 @@ PreprocessorDefinitions="" /> + + + @@ -18428,6 +35994,15 @@ PreprocessorDefinitions="" /> + + + @@ -18437,6 +36012,15 @@ PreprocessorDefinitions="" /> + + + @@ -18446,6 +36030,15 @@ PreprocessorDefinitions="" /> + + + @@ -18455,6 +36048,15 @@ PreprocessorDefinitions="" /> + + + @@ -18464,6 +36066,15 @@ PreprocessorDefinitions="" /> + + + @@ -18473,6 +36084,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18495,6 +36124,15 @@ PreprocessorDefinitions="" /> + + + @@ -18504,6 +36142,15 @@ PreprocessorDefinitions="" /> + + + @@ -18513,6 +36160,15 @@ PreprocessorDefinitions="" /> + + + @@ -18522,6 +36178,15 @@ PreprocessorDefinitions="" /> + + + @@ -18531,6 +36196,15 @@ PreprocessorDefinitions="" /> + + + @@ -18540,6 +36214,15 @@ PreprocessorDefinitions="" /> + + + @@ -18549,6 +36232,15 @@ PreprocessorDefinitions="" /> + + + @@ -18558,6 +36250,15 @@ PreprocessorDefinitions="" /> + + + @@ -18567,6 +36268,15 @@ PreprocessorDefinitions="" /> + + + @@ -18576,6 +36286,15 @@ PreprocessorDefinitions="" /> + + + @@ -18585,6 +36304,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18607,6 +36344,15 @@ PreprocessorDefinitions="" /> + + + @@ -18616,6 +36362,15 @@ PreprocessorDefinitions="" /> + + + @@ -18625,6 +36380,15 @@ PreprocessorDefinitions="" /> + + + @@ -18634,6 +36398,15 @@ PreprocessorDefinitions="" /> + + + @@ -18643,6 +36416,15 @@ PreprocessorDefinitions="" /> + + + @@ -18652,6 +36434,15 @@ PreprocessorDefinitions="" /> + + + @@ -18661,6 +36452,15 @@ PreprocessorDefinitions="" /> + + + @@ -18670,6 +36470,15 @@ PreprocessorDefinitions="" /> + + + @@ -18679,6 +36488,15 @@ PreprocessorDefinitions="" /> + + + @@ -18688,6 +36506,15 @@ PreprocessorDefinitions="" /> + + + @@ -18697,6 +36524,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18720,6 +36566,15 @@ PreprocessorDefinitions="" /> + + + @@ -18729,6 +36584,15 @@ PreprocessorDefinitions="" /> + + + @@ -18738,6 +36602,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18757,6 +36640,15 @@ PreprocessorDefinitions="" /> + + + @@ -18766,6 +36658,15 @@ PreprocessorDefinitions="" /> + + + @@ -18775,6 +36676,15 @@ PreprocessorDefinitions="" /> + + + @@ -18784,6 +36694,15 @@ PreprocessorDefinitions="" /> + + + @@ -18793,6 +36712,15 @@ PreprocessorDefinitions="" /> + + + @@ -18802,6 +36730,15 @@ PreprocessorDefinitions="" /> + + + @@ -18811,6 +36748,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18833,6 +36788,15 @@ PreprocessorDefinitions="" /> + + + @@ -18842,6 +36806,15 @@ PreprocessorDefinitions="" /> + + + @@ -18851,6 +36824,15 @@ PreprocessorDefinitions="" /> + + + @@ -18860,6 +36842,15 @@ PreprocessorDefinitions="" /> + + + @@ -18869,6 +36860,15 @@ PreprocessorDefinitions="" /> + + + @@ -18878,6 +36878,15 @@ PreprocessorDefinitions="" /> + + + @@ -18887,6 +36896,15 @@ PreprocessorDefinitions="" /> + + + @@ -18896,6 +36914,15 @@ PreprocessorDefinitions="" /> + + + @@ -18905,6 +36932,15 @@ PreprocessorDefinitions="" /> + + + @@ -18914,6 +36950,15 @@ PreprocessorDefinitions="" /> + + + @@ -18923,6 +36968,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -18945,6 +37008,15 @@ PreprocessorDefinitions="" /> + + + @@ -18954,6 +37026,15 @@ PreprocessorDefinitions="" /> + + + @@ -18963,6 +37044,15 @@ PreprocessorDefinitions="" /> + + + @@ -18972,6 +37062,15 @@ PreprocessorDefinitions="" /> + + + @@ -18981,6 +37080,15 @@ PreprocessorDefinitions="" /> + + + @@ -18990,6 +37098,15 @@ PreprocessorDefinitions="" /> + + + @@ -18999,6 +37116,15 @@ PreprocessorDefinitions="" /> + + + @@ -19008,6 +37134,15 @@ PreprocessorDefinitions="" /> + + + @@ -19017,6 +37152,15 @@ PreprocessorDefinitions="" /> + + + @@ -19026,6 +37170,15 @@ PreprocessorDefinitions="" /> + + + @@ -19035,6 +37188,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -19057,6 +37228,15 @@ PreprocessorDefinitions="" /> + + + @@ -19066,6 +37246,15 @@ PreprocessorDefinitions="" /> + + + @@ -19075,6 +37264,15 @@ PreprocessorDefinitions="" /> + + + @@ -19084,6 +37282,15 @@ PreprocessorDefinitions="" /> + + + @@ -19093,6 +37300,15 @@ PreprocessorDefinitions="" /> + + + @@ -19102,6 +37318,15 @@ PreprocessorDefinitions="" /> + + + @@ -19111,6 +37336,15 @@ PreprocessorDefinitions="" /> + + + @@ -19120,6 +37354,15 @@ PreprocessorDefinitions="" /> + + + @@ -19129,6 +37372,15 @@ PreprocessorDefinitions="" /> + + + @@ -19138,6 +37390,15 @@ PreprocessorDefinitions="" /> + + + @@ -19147,6 +37408,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -19175,6 +37455,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19185,6 +37475,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19195,6 +37495,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19205,6 +37515,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19215,6 +37535,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19225,6 +37555,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19235,6 +37575,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19245,6 +37595,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19255,6 +37615,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19265,6 +37635,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19275,6 +37655,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -19299,6 +37699,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19309,6 +37719,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19319,6 +37739,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19329,6 +37759,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19339,6 +37779,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19349,6 +37799,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19359,6 +37819,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19369,6 +37839,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19379,6 +37859,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19389,6 +37879,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19399,6 +37899,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -19423,6 +37943,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19433,6 +37963,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19443,6 +37983,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19453,6 +38003,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19463,6 +38023,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19473,6 +38043,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19483,6 +38063,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19493,6 +38083,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19503,6 +38103,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19513,6 +38123,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19523,6 +38143,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -19547,6 +38187,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19557,6 +38207,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19567,6 +38227,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19577,6 +38247,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19587,6 +38267,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19597,6 +38287,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19607,6 +38307,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19617,6 +38327,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19627,6 +38347,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19637,6 +38367,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19647,6 +38387,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -19671,6 +38431,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19681,6 +38451,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19691,6 +38471,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19701,6 +38491,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19711,6 +38511,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19721,6 +38531,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19731,6 +38551,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19741,6 +38571,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19751,6 +38591,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19761,6 +38611,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19771,6 +38631,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -19795,6 +38675,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19805,6 +38695,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19815,6 +38715,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19825,6 +38735,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19835,6 +38755,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19845,6 +38775,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19855,6 +38795,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19865,6 +38815,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19875,6 +38835,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19885,6 +38855,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19895,6 +38875,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -19919,6 +38919,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19929,6 +38939,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19939,6 +38959,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19949,6 +38979,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19959,6 +38999,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19969,6 +39019,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19979,6 +39039,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19989,6 +39059,16 @@ UsePrecompiledHeader="0" /> + + + @@ -19999,6 +39079,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20009,6 +39099,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20019,6 +39119,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -20043,6 +39163,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20053,6 +39183,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20063,6 +39203,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20073,6 +39223,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20083,6 +39243,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20093,6 +39263,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20103,6 +39283,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20113,6 +39303,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20123,6 +39323,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20133,6 +39343,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20143,6 +39363,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -20167,6 +39407,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20177,6 +39427,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20187,6 +39447,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20197,6 +39467,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20207,6 +39487,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20217,6 +39507,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20227,6 +39527,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20237,6 +39547,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20247,6 +39567,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20257,6 +39587,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20267,6 +39607,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -20291,6 +39651,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20301,6 +39671,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20311,6 +39691,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20321,6 +39711,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20331,6 +39731,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20341,6 +39751,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20351,6 +39771,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20361,6 +39791,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20371,6 +39811,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20381,6 +39831,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20391,6 +39851,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -20415,6 +39895,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20425,6 +39915,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20435,6 +39935,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20445,6 +39955,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20455,6 +39975,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20465,6 +39995,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20475,6 +40015,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20485,6 +40035,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20495,6 +40055,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20505,6 +40075,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20515,6 +40095,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -20539,6 +40139,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20549,6 +40159,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20559,6 +40179,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20569,6 +40199,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20579,6 +40219,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20589,6 +40239,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20599,6 +40259,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20609,6 +40279,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20619,6 +40299,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20629,6 +40319,16 @@ UsePrecompiledHeader="0" /> + + + @@ -20639,6 +40339,16 @@ UsePrecompiledHeader="0" /> + + + + + + + + + @@ -20672,6 +40398,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20681,6 +40416,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -20714,6 +40482,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20723,6 +40500,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -20740,6 +40534,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -20777,6 +40604,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20786,6 +40622,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -20819,6 +40688,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20828,6 +40706,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -20845,6 +40740,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -20882,6 +40810,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20891,6 +40828,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -20924,6 +40894,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20933,6 +40912,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -20950,6 +40946,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -20987,6 +41016,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -20996,6 +41034,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21029,6 +41100,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21038,6 +41118,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21055,6 +41152,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21092,6 +41222,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21101,6 +41240,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21134,6 +41306,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21143,6 +41324,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21160,6 +41358,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21197,6 +41428,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21206,6 +41446,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21239,6 +41512,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21248,6 +41530,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21265,6 +41564,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21302,6 +41634,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21311,6 +41652,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21344,6 +41718,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21353,6 +41736,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21370,6 +41770,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + @@ -21400,6 +41826,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21409,6 +41844,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21418,6 +41862,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21427,6 +41880,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21436,6 +41898,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21445,6 +41916,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21454,6 +41934,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21463,6 +41952,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21472,6 +41970,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21481,6 +41988,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21490,6 +42006,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + @@ -21519,6 +42060,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21528,6 +42078,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21561,6 +42144,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21570,6 +42162,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21587,6 +42196,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21624,6 +42266,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21633,6 +42284,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21666,6 +42350,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21675,6 +42368,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21692,6 +42402,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21729,6 +42472,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21738,6 +42490,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21771,6 +42556,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21780,6 +42574,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21797,6 +42608,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21834,6 +42678,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21843,6 +42696,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21876,6 +42762,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21885,6 +42780,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -21902,6 +42814,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21939,6 +42884,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21948,6 +42902,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -21981,6 +42968,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -21990,6 +42986,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22007,6 +43020,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + @@ -22037,6 +43076,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22046,6 +43094,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22055,6 +43112,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22064,6 +43130,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22073,6 +43148,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22090,6 +43182,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22099,6 +43200,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22116,6 +43234,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22125,6 +43252,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + @@ -22154,6 +43306,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22163,6 +43324,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -22196,6 +43390,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22205,6 +43408,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22222,6 +43442,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -22259,6 +43512,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22268,6 +43530,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + + + + @@ -22301,6 +43596,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22310,6 +43614,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22327,6 +43648,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + + + + @@ -22357,6 +43704,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22366,6 +43722,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22375,6 +43740,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22384,6 +43758,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22393,6 +43776,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22410,6 +43810,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22419,6 +43828,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22436,6 +43862,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22445,6 +43880,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22467,6 +43920,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22476,6 +43938,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22485,6 +43956,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22494,6 +43974,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22503,6 +43992,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22512,6 +44010,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22521,6 +44028,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22530,6 +44046,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22539,6 +44064,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22548,6 +44082,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + @@ -22557,6 +44100,15 @@ Outputs="$(OUTDIR)\$(InputName).obj" /> + + + + + + @@ -22583,6 +44144,15 @@ PreprocessorDefinitions="" /> + + + @@ -22592,6 +44162,15 @@ PreprocessorDefinitions="" /> + + + @@ -22601,6 +44180,15 @@ PreprocessorDefinitions="" /> + + + @@ -22610,6 +44198,15 @@ PreprocessorDefinitions="" /> + + + @@ -22619,6 +44216,15 @@ PreprocessorDefinitions="" /> + + + @@ -22628,6 +44234,15 @@ PreprocessorDefinitions="" /> + + + @@ -22637,6 +44252,15 @@ PreprocessorDefinitions="" /> + + + @@ -22646,6 +44270,15 @@ PreprocessorDefinitions="" /> + + + @@ -22655,6 +44288,15 @@ PreprocessorDefinitions="" /> + + + @@ -22664,6 +44306,15 @@ PreprocessorDefinitions="" /> + + + @@ -22673,6 +44324,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -22695,6 +44364,15 @@ PreprocessorDefinitions="" /> + + + @@ -22704,6 +44382,15 @@ PreprocessorDefinitions="" /> + + + @@ -22713,6 +44400,15 @@ PreprocessorDefinitions="" /> + + + @@ -22722,6 +44418,15 @@ PreprocessorDefinitions="" /> + + + @@ -22731,6 +44436,15 @@ PreprocessorDefinitions="" /> + + + @@ -22740,6 +44454,15 @@ PreprocessorDefinitions="" /> + + + @@ -22749,6 +44472,15 @@ PreprocessorDefinitions="" /> + + + @@ -22758,6 +44490,15 @@ PreprocessorDefinitions="" /> + + + @@ -22767,6 +44508,15 @@ PreprocessorDefinitions="" /> + + + @@ -22776,6 +44526,15 @@ PreprocessorDefinitions="" /> + + + @@ -22785,6 +44544,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -22807,6 +44584,15 @@ PreprocessorDefinitions="" /> + + + @@ -22816,6 +44602,15 @@ PreprocessorDefinitions="" /> + + + @@ -22825,6 +44620,15 @@ PreprocessorDefinitions="" /> + + + @@ -22834,6 +44638,15 @@ PreprocessorDefinitions="" /> + + + @@ -22843,6 +44656,15 @@ PreprocessorDefinitions="" /> + + + @@ -22852,6 +44674,15 @@ PreprocessorDefinitions="" /> + + + @@ -22861,6 +44692,15 @@ PreprocessorDefinitions="" /> + + + @@ -22870,6 +44710,15 @@ PreprocessorDefinitions="" /> + + + @@ -22879,6 +44728,15 @@ PreprocessorDefinitions="" /> + + + @@ -22888,6 +44746,15 @@ PreprocessorDefinitions="" /> + + + @@ -22897,6 +44764,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -22919,6 +44804,15 @@ PreprocessorDefinitions="" /> + + + @@ -22928,6 +44822,15 @@ PreprocessorDefinitions="" /> + + + @@ -22937,6 +44840,15 @@ PreprocessorDefinitions="" /> + + + @@ -22946,6 +44858,15 @@ PreprocessorDefinitions="" /> + + + @@ -22955,6 +44876,15 @@ PreprocessorDefinitions="" /> + + + @@ -22964,6 +44894,15 @@ PreprocessorDefinitions="" /> + + + @@ -22973,6 +44912,15 @@ PreprocessorDefinitions="" /> + + + @@ -22982,6 +44930,15 @@ PreprocessorDefinitions="" /> + + + @@ -22991,6 +44948,15 @@ PreprocessorDefinitions="" /> + + + @@ -23000,6 +44966,15 @@ PreprocessorDefinitions="" /> + + + @@ -23009,6 +44984,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -23033,6 +45027,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23043,6 +45047,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23053,6 +45067,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23063,6 +45087,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23073,6 +45107,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23083,6 +45127,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23093,6 +45147,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23103,6 +45167,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23113,6 +45187,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23123,6 +45207,16 @@ UsePrecompiledHeader="0" /> + + + @@ -23133,6 +45227,16 @@ UsePrecompiledHeader="0" /> + + + + + + @@ -23155,6 +45268,15 @@ PreprocessorDefinitions="" /> + + + @@ -23164,6 +45286,15 @@ PreprocessorDefinitions="" /> + + + @@ -23173,6 +45304,15 @@ PreprocessorDefinitions="" /> + + + @@ -23182,6 +45322,15 @@ PreprocessorDefinitions="" /> + + + @@ -23191,6 +45340,15 @@ PreprocessorDefinitions="" /> + + + @@ -23200,6 +45358,15 @@ PreprocessorDefinitions="" /> + + + @@ -23209,6 +45376,15 @@ PreprocessorDefinitions="" /> + + + @@ -23218,6 +45394,15 @@ PreprocessorDefinitions="" /> + + + @@ -23227,6 +45412,15 @@ PreprocessorDefinitions="" /> + + + @@ -23236,6 +45430,15 @@ PreprocessorDefinitions="" /> + + + @@ -23245,6 +45448,15 @@ PreprocessorDefinitions="" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -24295,6 +47503,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + + + + @@ -24325,6 +47563,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -24419,6 +47747,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + + + + @@ -24449,6 +47807,16 @@ PrecompiledHeaderThrough="qwsvdef.h" /> + + + + + + + + + + + + @@ -24495,6 +47892,15 @@ PreprocessorDefinitions="" /> + + + @@ -24504,6 +47910,15 @@ PreprocessorDefinitions="" /> + + + @@ -24513,6 +47928,15 @@ PreprocessorDefinitions="" /> + + + @@ -24522,6 +47946,15 @@ PreprocessorDefinitions="" /> + + + @@ -24531,6 +47964,15 @@ PreprocessorDefinitions="" /> + + + @@ -24540,6 +47982,15 @@ PreprocessorDefinitions="" /> + + + @@ -24549,6 +48000,15 @@ PreprocessorDefinitions="" /> + + + @@ -24558,6 +48018,15 @@ PreprocessorDefinitions="" /> + + + @@ -24567,6 +48036,15 @@ PreprocessorDefinitions="" /> + + + @@ -24576,6 +48054,15 @@ PreprocessorDefinitions="" /> + + + @@ -24585,6 +48072,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -24607,6 +48112,15 @@ PreprocessorDefinitions="" /> + + + @@ -24616,6 +48130,15 @@ PreprocessorDefinitions="" /> + + + @@ -24625,6 +48148,15 @@ PreprocessorDefinitions="" /> + + + @@ -24634,6 +48166,15 @@ PreprocessorDefinitions="" /> + + + @@ -24643,6 +48184,15 @@ PreprocessorDefinitions="" /> + + + @@ -24652,6 +48202,15 @@ PreprocessorDefinitions="" /> + + + @@ -24661,6 +48220,15 @@ PreprocessorDefinitions="" /> + + + @@ -24670,6 +48238,15 @@ PreprocessorDefinitions="" /> + + + @@ -24679,6 +48256,15 @@ PreprocessorDefinitions="" /> + + + @@ -24688,6 +48274,15 @@ PreprocessorDefinitions="" /> + + + @@ -24697,6 +48292,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -24719,6 +48332,15 @@ PreprocessorDefinitions="" /> + + + @@ -24728,6 +48350,15 @@ PreprocessorDefinitions="" /> + + + @@ -24737,6 +48368,15 @@ PreprocessorDefinitions="" /> + + + @@ -24746,6 +48386,15 @@ PreprocessorDefinitions="" /> + + + @@ -24755,6 +48404,15 @@ PreprocessorDefinitions="" /> + + + @@ -24764,6 +48422,15 @@ PreprocessorDefinitions="" /> + + + @@ -24773,6 +48440,15 @@ PreprocessorDefinitions="" /> + + + @@ -24782,6 +48458,15 @@ PreprocessorDefinitions="" /> + + + @@ -24791,6 +48476,15 @@ PreprocessorDefinitions="" /> + + + @@ -24800,6 +48494,15 @@ PreprocessorDefinitions="" /> + + + @@ -24809,6 +48512,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -24831,6 +48552,15 @@ PreprocessorDefinitions="" /> + + + @@ -24840,6 +48570,15 @@ PreprocessorDefinitions="" /> + + + @@ -24849,6 +48588,15 @@ PreprocessorDefinitions="" /> + + + @@ -24858,6 +48606,15 @@ PreprocessorDefinitions="" /> + + + @@ -24867,6 +48624,15 @@ PreprocessorDefinitions="" /> + + + @@ -24876,6 +48642,15 @@ PreprocessorDefinitions="" /> + + + @@ -24885,6 +48660,15 @@ PreprocessorDefinitions="" /> + + + @@ -24894,6 +48678,15 @@ PreprocessorDefinitions="" /> + + + @@ -24903,6 +48696,15 @@ PreprocessorDefinitions="" /> + + + @@ -24912,6 +48714,15 @@ PreprocessorDefinitions="" /> + + + @@ -24921,6 +48732,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -24943,6 +48772,15 @@ PreprocessorDefinitions="" /> + + + @@ -24952,6 +48790,15 @@ PreprocessorDefinitions="" /> + + + @@ -24961,6 +48808,15 @@ PreprocessorDefinitions="" /> + + + @@ -24970,6 +48826,15 @@ PreprocessorDefinitions="" /> + + + @@ -24979,6 +48844,15 @@ PreprocessorDefinitions="" /> + + + @@ -24988,6 +48862,15 @@ PreprocessorDefinitions="" /> + + + @@ -24997,6 +48880,15 @@ PreprocessorDefinitions="" /> + + + @@ -25006,6 +48898,15 @@ PreprocessorDefinitions="" /> + + + @@ -25015,6 +48916,15 @@ PreprocessorDefinitions="" /> + + + @@ -25024,6 +48934,15 @@ PreprocessorDefinitions="" /> + + + @@ -25033,6 +48952,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -25059,6 +48996,15 @@ PreprocessorDefinitions="" /> + + + @@ -25068,6 +49014,15 @@ PreprocessorDefinitions="" /> + + + @@ -25077,6 +49032,15 @@ PreprocessorDefinitions="" /> + + + @@ -25086,6 +49050,15 @@ PreprocessorDefinitions="" /> + + + @@ -25095,6 +49068,15 @@ PreprocessorDefinitions="" /> + + + @@ -25104,6 +49086,15 @@ PreprocessorDefinitions="" /> + + + @@ -25113,6 +49104,15 @@ PreprocessorDefinitions="" /> + + + @@ -25122,6 +49122,15 @@ PreprocessorDefinitions="" /> + + + @@ -25131,6 +49140,15 @@ PreprocessorDefinitions="" /> + + + @@ -25140,6 +49158,15 @@ PreprocessorDefinitions="" /> + + + @@ -25149,6 +49176,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -25171,6 +49216,15 @@ PreprocessorDefinitions="" /> + + + @@ -25180,6 +49234,15 @@ PreprocessorDefinitions="" /> + + + @@ -25189,6 +49252,15 @@ PreprocessorDefinitions="" /> + + + @@ -25198,6 +49270,15 @@ PreprocessorDefinitions="" /> + + + @@ -25207,6 +49288,15 @@ PreprocessorDefinitions="" /> + + + @@ -25216,6 +49306,15 @@ PreprocessorDefinitions="" /> + + + @@ -25225,6 +49324,15 @@ PreprocessorDefinitions="" /> + + + @@ -25234,6 +49342,15 @@ PreprocessorDefinitions="" /> + + + @@ -25243,6 +49360,15 @@ PreprocessorDefinitions="" /> + + + @@ -25252,6 +49378,15 @@ PreprocessorDefinitions="" /> + + + @@ -25261,6 +49396,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -25283,6 +49436,15 @@ PreprocessorDefinitions="" /> + + + @@ -25292,6 +49454,15 @@ PreprocessorDefinitions="" /> + + + @@ -25301,6 +49472,15 @@ PreprocessorDefinitions="" /> + + + @@ -25310,6 +49490,15 @@ PreprocessorDefinitions="" /> + + + @@ -25319,6 +49508,15 @@ PreprocessorDefinitions="" /> + + + @@ -25328,6 +49526,15 @@ PreprocessorDefinitions="" /> + + + @@ -25337,6 +49544,15 @@ PreprocessorDefinitions="" /> + + + @@ -25346,6 +49562,15 @@ PreprocessorDefinitions="" /> + + + @@ -25355,6 +49580,15 @@ PreprocessorDefinitions="" /> + + + @@ -25364,6 +49598,15 @@ PreprocessorDefinitions="" /> + + + @@ -25373,6 +49616,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -25395,6 +49656,15 @@ PreprocessorDefinitions="" /> + + + @@ -25404,6 +49674,15 @@ PreprocessorDefinitions="" /> + + + @@ -25413,6 +49692,15 @@ PreprocessorDefinitions="" /> + + + @@ -25422,6 +49710,15 @@ PreprocessorDefinitions="" /> + + + @@ -25431,6 +49728,15 @@ PreprocessorDefinitions="" /> + + + @@ -25440,6 +49746,15 @@ PreprocessorDefinitions="" /> + + + @@ -25449,6 +49764,15 @@ PreprocessorDefinitions="" /> + + + @@ -25458,6 +49782,15 @@ PreprocessorDefinitions="" /> + + + @@ -25467,6 +49800,15 @@ PreprocessorDefinitions="" /> + + + @@ -25476,6 +49818,15 @@ PreprocessorDefinitions="" /> + + + @@ -25485,6 +49836,15 @@ PreprocessorDefinitions="" /> + + + + + + @@ -25507,6 +49876,15 @@ PreprocessorDefinitions="" /> + + + @@ -25516,6 +49894,15 @@ PreprocessorDefinitions="" /> + + + @@ -25525,6 +49912,15 @@ PreprocessorDefinitions="" /> + + + @@ -25534,6 +49930,15 @@ PreprocessorDefinitions="" /> + + + @@ -25543,6 +49948,15 @@ PreprocessorDefinitions="" /> + + + @@ -25552,6 +49966,15 @@ PreprocessorDefinitions="" /> + + + @@ -25561,6 +49984,15 @@ PreprocessorDefinitions="" /> + + + @@ -25570,6 +50002,15 @@ PreprocessorDefinitions="" /> + + + @@ -25579,6 +50020,15 @@ PreprocessorDefinitions="" /> + + + @@ -25589,6 +50039,16 @@ UsePrecompiledHeader="0" /> + + + @@ -25598,6 +50058,15 @@ PreprocessorDefinitions="" /> + + + @@ -26122,10 +50591,6 @@ RelativePath="..\client\q2.ico" > - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/dotnet2005/gas2masm.vcproj b/engine/dotnet2005/gas2masm.vcproj index b48f8847f..62679ed32 100644 --- a/engine/dotnet2005/gas2masm.vcproj +++ b/engine/dotnet2005/gas2masm.vcproj @@ -9,6 +9,9 @@ + @@ -103,6 +106,97 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + diff --git a/engine/ftequake/ftequake.dsp b/engine/ftequake/ftequake.dsp index 87b815fe7..2139c8d8f 100644 --- a/engine/ftequake/ftequake.dsp +++ b/engine/ftequake/ftequake.dsp @@ -217,12 +217,12 @@ LINK32=link.exe # PROP BASE Target_Dir "" # PROP Use_MFC 0 # PROP Use_Debug_Libraries 1 -# PROP Output_Dir "ftequake___Win32_MinGLDebug" -# PROP Intermediate_Dir "ftequake___Win32_MinGLDebug" +# PROP Output_Dir "MinGLDebug" +# PROP Intermediate_Dir "MinGLDebug" # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client\gltod3d\sdk7\include" /I "..\client\gltod3d\D3DFrame" /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /I "..\client" /D "NQPROT" /D "_DEBUG" /D "GLQUAKE" /D "SERVERDLL" /D "WIN32" /D "_WINDOWS" /D "Q2SERVER" /D "DYNAMIC_ENTS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /YX /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c -# ADD CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "MINIMAL" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR".\GLDebug/" /Fp".\GLDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLDebug/" /Fd".\GLDebug/" /FD /c +# ADD CPP /nologo /G5 /ML /W3 /GX /ZI /Od /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "MINIMAL" /D "_DEBUG" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR".\GLMinDebug/" /Fp".\GLMinDebug/qwcl.pch" /Yu"quakedef.h" /Fo".\GLMinDebug/" /Fd".\GLMinDebug/" /FD /c # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "_DEBUG" @@ -250,7 +250,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /G6 /Gr /W3 /GX /O2 /Ob2 /I "..\client\gltod3d\sdk7\include" /I "..\client\gltod3d\D3DFrame" /I "..\dxsdk\sdk\inc" /I "..\scitech\include" /I "..\client" /D "NOSOUNDASM" /D "NDEBUG" /D "_MBCS" /D "GLQUAKE" /D "SERVERDLL" /D "NQPROT" /D "WIN32" /D "_WINDOWS" /D "Q2SERVER" /D "DYNAMIC_ENTS" /FR /YX /FD /c -# ADD CPP /nologo /G6 /Gr /W3 /GX /O2 /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "MINIMAL" /D "NDEBUG" /D "_MBCS" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR /Yu"quakedef.h" /FD /c +# ADD CPP /nologo /G6 /Gr /W3 /GX /O2 /I "..\client" /I "../common" /I "../server" /I "../gl" /I "../sw" /I "../qclib" /I "../libs" /I "../libs/dxsdk7/include" /D "MINIMAL" /D "NDEBUG" /D "_MBCS" /D "GLQUAKE" /D "WIN32" /D "_WINDOWS" /FR"MinGLRelease/" /Fp"MinGLRelease/ftequake.pch" /Yu"quakedef.h" /Fo"MinGLRelease/" /Fd"MinGLRelease/" /FD /c # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 # ADD BASE RSC /l 0x809 /d "NDEBUG" @@ -470,6 +470,11 @@ SOURCE=..\server\pr_cmds.c # End Source File # Begin Source File +SOURCE=..\server\pr_q1qvm.c +# ADD CPP /Yu"qwsvdef.h" +# End Source File +# Begin Source File + SOURCE=..\server\savegame.c # ADD CPP /Yu"qwsvdef.h" # End Source File @@ -1971,6 +1976,133 @@ SOURCE=..\client\net_master.c # End Source File # Begin Source File +SOURCE=..\client\p_classic.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\client\p_null.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\client\p_script.c + +!IF "$(CFG)" == "ftequake - Win32 Release" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# PROP Exclude_From_Build 1 + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +!ENDIF + +# End Source File +# Begin Source File + SOURCE=..\client\pr_csqc.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -1987,6 +2119,8 @@ SOURCE=..\client\pr_csqc.c !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" +# PROP Intermediate_Dir "MinGLDebug" + !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" @@ -2029,6 +2163,8 @@ SOURCE=..\client\pr_menu.c !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" +# PROP Intermediate_Dir "MinGLDebug" + !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" @@ -2200,6 +2336,7 @@ SOURCE=..\client\r_partset.c !ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" +# PROP Exclude_From_Build 1 # SUBTRACT CPP /YX /Yc /Yu !ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" @@ -2732,6 +2869,21 @@ SOURCE=..\client\snd_win.c # End Source File # Begin Source File +SOURCE=..\client\sys_linux.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=..\client\sys_morphos.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=..\client\sys_sdl.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + SOURCE=..\client\sys_win.c !IF "$(CFG)" == "ftequake - Win32 Release" @@ -6053,6 +6205,10 @@ SOURCE=..\common\pmovetst.c # End Source File # Begin Source File +SOURCE=..\common\pr_bgcmd.c +# End Source File +# Begin Source File + SOURCE=..\common\q1bsp.c # End Source File # Begin Source File @@ -6122,6 +6278,317 @@ SOURCE=..\QCLIB\Comprout.c # Begin Source File SOURCE=..\qclib\execloop.h + +!IF "$(CFG)" == "ftequake - Win32 Release" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebug" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLRelease" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 MDebug" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 MRelease" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinGLRelease" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated Server" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 Release Dedicated Server" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 MinSW" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 GLDebugQ3" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 Debug Dedicated ServerQ3" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ftequake - Win32 D3DDebug" + +# Begin Custom Build +InputDir=\ftesvn - Copy\engine\qclib +InputPath=..\qclib\execloop.h + +BuildCmds= \ + copy "$(InputPath)" "$(InputDir)\execloop16d.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32.h" \ + copy "$(InputPath)" "$(InputDir)\execloop32d.h" \ + + +"$(InputDir)\execloop16d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\execloop32d.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + # End Source File # Begin Source File @@ -6141,6 +6608,7 @@ SOURCE=..\QCLIB\pr_edict.c # Begin Source File SOURCE=..\QCLIB\Pr_exec.c +# ADD CPP /D "SEPARATEINCLUDES" # SUBTRACT CPP /WX /YX /Yc /Yu # End Source File # Begin Source File @@ -7424,7 +7892,7 @@ InputName=math !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # Begin Custom Build -OutDir=.\ftequake___Win32_MinGLDebug +OutDir=.\MinGLDebug InputPath=..\common\math.s InputName=math @@ -8282,7 +8750,7 @@ InputName=snd_mixa !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # Begin Custom Build -OutDir=.\ftequake___Win32_MinGLDebug +OutDir=.\MinGLDebug InputPath=..\client\snd_mixa.s InputName=snd_mixa @@ -8725,7 +9193,7 @@ InputName=sys_wina !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # Begin Custom Build -OutDir=.\ftequake___Win32_MinGLDebug +OutDir=.\MinGLDebug InputPath=..\client\sys_wina.s InputName=sys_wina @@ -8912,7 +9380,7 @@ InputName=worlda !ELSEIF "$(CFG)" == "ftequake - Win32 MinGLDebug" # Begin Custom Build -OutDir=.\ftequake___Win32_MinGLDebug +OutDir=.\MinGLDebug InputPath=..\server\worlda.s InputName=worlda @@ -9992,8 +10460,8 @@ SOURCE=..\client\winquake.rc !IF "$(CFG)" == "ftequake - Win32 Release" -# ADD BASE RSC /l 0x809 /i "\ftetgcvs\svnd3d\engine\client" /i "\ftetgcvs\svn\engine\client" /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" -# ADD RSC /l 0x809 /i "\ftetgcvs\svnd3d\engine\client" /i "\ftetgcvs\svn\engine\client" /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" /d "MINIMAL" +# ADD BASE RSC /l 0x809 /i "\ftesvn - Copy\engine\client" /i "\ftesvn\engine\client" /i "\ftetgcvs\svnd3d\engine\client" /i "\ftetgcvs\svn\engine\client" /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" +# ADD RSC /l 0x809 /i "\ftesvn - Copy\engine\client" /i "\ftesvn\engine\client" /i "\ftetgcvs\svnd3d\engine\client" /i "\ftetgcvs\svn\engine\client" /i "\ftetgcvs\engine\client" /i "\Projects\fteqw\engine\client" /i "\windows\J\ftetgcvs\engine\client" /i "\ftetgcvs\source\client" /i "\ftetgcvs\temp\client" /i "\ftetgcvs\fte\QW\client" /d "MINIMAL" !ELSEIF "$(CFG)" == "ftequake - Win32 Debug" diff --git a/engine/ftequake/ftequake.dsw b/engine/ftequake/ftequake.dsw index 687abcbe8..82c7c4d17 100644 --- a/engine/ftequake/ftequake.dsw +++ b/engine/ftequake/ftequake.dsw @@ -30,6 +30,33 @@ Package=<4> ############################################################################### +Project: "hud"=..\..\plugins\hud\hud.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name q3asm2 + End Project Dependency +}}} + +############################################################################### + +Project: "q3asm2"=..\..\Q3ASM2\q3asm2.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + Project: "qcc"=..\qclib\qcc.dsp - Package Owner=<4> Package=<5> diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 282c5e1fa..0804c5fb7 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1753,7 +1753,7 @@ void R_DrawGAliasModel (entity_t *e) qglEnable (GL_BLEND); qglBlendFunc(GL_ONE, GL_ONE); } - else if ((e->model->flags & EF_SPECIAL_TRANS)) //hexen2 flags. + else if ((e->model->flags & EFH2_SPECIAL_TRANS)) //hexen2 flags. { qglEnable (GL_BLEND); qglBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); @@ -1766,12 +1766,12 @@ void R_DrawGAliasModel (entity_t *e) qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); e->shaderRGBAf[3] = r_wateralpha.value; } - else if ((e->model->flags & EF_TRANSPARENT)) + else if ((e->model->flags & EFH2_TRANSPARENT)) { qglEnable (GL_BLEND); qglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - else if ((e->model->flags & EF_HOLEY)) + else if ((e->model->flags & EFH2_HOLEY)) { qglEnable (GL_ALPHA_TEST); // qglEnable (GL_BLEND); @@ -1911,7 +1911,7 @@ void R_DrawGAliasModel (entity_t *e) memset(&mesh, 0, sizeof(mesh)); for(surfnum=0; inf; ((inf->nextsurf)?(inf = (galiasinfo_t*)((char *)inf + inf->nextsurf)):(inf=NULL)), surfnum++) { - needrecolour = R_GAliasBuildMesh(&mesh, inf, e->frame, e->oldframe, e->lerpfrac, e->shaderRGBAf[3], e->frame1time, e->frame2time, nolightdir); + needrecolour = R_GAliasBuildMesh(&mesh, inf, e->frame1, e->frame2, e->lerpfrac, e->shaderRGBAf[3], e->frame1time, e->frame2time, nolightdir); c_alias_polys += mesh.numindexes/3; @@ -2001,14 +2001,36 @@ void R_DrawGAliasModel (entity_t *e) if (skin->loweroverlay && r_skin_overlays.value) { qglEnable(GL_BLEND); - qglColor4f(shadelight[0]/255, shadelight[1]/255, shadelight[2]/255, e->shaderRGBAf[3]); + qglBlendFunc (GL_SRC_ALPHA, GL_ONE); + mesh.colors_array = NULL; + if (e->scoreboard) + { + int c = e->scoreboard->tbottomcolor; + if (c >= 16) + qglColor4f(shadelight[0]/255, shadelight[1]/255, shadelight[2]/255, e->shaderRGBAf[3]); + else if (c >= 8) + qglColor4f(host_basepal[c*16*3]/255.0f, host_basepal[c*16*3+1]/255.0f, host_basepal[c*16*3+2]/255.0f, e->shaderRGBAf[3]); + else + qglColor4f(host_basepal[15+c*16*3]/255.0f, host_basepal[15+c*16*3+1]/255.0f, host_basepal[15+c*16*3+2]/255.0f, e->shaderRGBAf[3]); + } c_alias_polys += mesh.numindexes/3; GL_DrawAliasMesh(&mesh, skin->loweroverlay); } if (skin->upperoverlay && r_skin_overlays.value) { qglEnable(GL_BLEND); - qglColor4f(shadelight[0]/255, shadelight[1]/255, shadelight[2]/255, e->shaderRGBAf[3]); + qglBlendFunc (GL_SRC_ALPHA, GL_ONE); + mesh.colors_array = NULL; + if (e->scoreboard) + { + int c = e->scoreboard->ttopcolor; + if (c >= 16) + qglColor4f(shadelight[0]/255, shadelight[1]/255, shadelight[2]/255, e->shaderRGBAf[3]); + else if (c >= 8) + qglColor4f(host_basepal[c*16*3]/255.0f, host_basepal[c*16*3+1]/255.0f, host_basepal[c*16*3+2]/255.0f, e->shaderRGBAf[3]); + else + qglColor4f(host_basepal[15+c*16*3]/255.0f, host_basepal[15+c*16*3+1]/255.0f, host_basepal[15+c*16*3+2]/255.0f, e->shaderRGBAf[3]); + } c_alias_polys += mesh.numindexes/3; GL_DrawAliasMesh(&mesh, skin->upperoverlay); } @@ -2101,9 +2123,9 @@ qglColor3f(0,0,1); if (e->flags & Q2RF_DEPTHHACK) qglDepthRange (gldepthmin, gldepthmax); - if ((currententity->model->flags & EF_SPECIAL_TRANS) && gl_cull.value) + if ((currententity->model->flags & EFH2_SPECIAL_TRANS) && gl_cull.value) qglEnable( GL_CULL_FACE ); - if ((currententity->model->flags & EF_HOLEY)) + if ((currententity->model->flags & EFH2_HOLEY)) qglDisable( GL_ALPHA_TEST ); #ifdef SHOWLIGHTDIR //testing @@ -2596,7 +2618,7 @@ void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius) { if (inf->ofs_trineighbours) { - R_GAliasBuildMesh(&mesh, inf, e->frame, e->oldframe, e->lerpfrac, 1, e->frame1time, e->frame2time, true); + R_GAliasBuildMesh(&mesh, inf, e->frame1, e->frame2, e->lerpfrac, 1, e->frame1time, e->frame2time, true); R_CalcFacing(&mesh, lightorg); R_ProjectShadowVolume(&mesh, lightorg); R_DrawShadowVolume(&mesh); diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 1bee35ceb..9061e2e22 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -145,37 +145,6 @@ cvar_t r_detailtextures = SCVAR("r_detailtextures", "1"); cvar_t r_showtris = SCVAR("r_showtris", "1"); cvar_t r_shownormals = SCVAR("r_shownormals", "1"); -float Q_rsqrt( float number ) -{ - int i; - float x2, y; - const float threehalfs = 1.5F; - - x2 = number * 0.5F; - y = number; - i = * ( int * ) &y; // evil floating point bit level hacking - i = 0x5f3759df - ( i >> 1 ); // what the fuck? - y = * ( float * ) &i; - y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration -// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed - - return y; -} - -void VectorNormalizeFast( vec3_t v ) -{ - float ilength; - - ilength = Q_rsqrt( DotProduct( v, v ) ); - - v[0] *= ilength; - v[1] *= ilength; - v[2] *= ilength; -} - - - - mat3_t axisDefault={{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; @@ -1874,49 +1843,46 @@ void R_RenderMeshCombined ( meshbuffer_t *mb, shaderpass_t *pass ) { GL_SelectTexture( mtexid0 + i ); - if ( pass->blendmode ) + + switch ( pass->blendmode ) { - switch ( pass->blendmode ) - { - case GL_DOT3_RGB_ARB: - GL_TexEnv (GL_COMBINE_EXT); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); - qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, pass->blendmode); - break; + case GL_DOT3_RGB_ARB: + GL_TexEnv (GL_COMBINE_EXT); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, GL_PREVIOUS_ARB); + qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, pass->blendmode); + break; - case GL_REPLACE: - case GL_MODULATE: - case GL_ADD: - // these modes are best set with TexEnv, Combine4 would need much more setup - GL_TexEnv (pass->blendmode); - break; + case GL_REPLACE: + case GL_MODULATE: + case GL_ADD: + // these modes are best set with TexEnv, Combine4 would need much more setup + GL_TexEnv (pass->blendmode); + break; - case GL_DECAL: - // mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, theyre added - // this way it can be possible to use GL_DECAL in both texture-units, while still looking good - // normal mutlitexturing would multiply the alpha-channel which looks ugly - GL_TexEnv (GL_COMBINE_EXT); - qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); - qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD); + case GL_DECAL: + // mimics Alpha-Blending in upper texture stage, but instead of multiplying the alpha-channel, theyre added + // this way it can be possible to use GL_DECAL in both texture-units, while still looking good + // normal mutlitexturing would multiply the alpha-channel which looks ugly + GL_TexEnv (GL_COMBINE_EXT); + qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_INTERPOLATE_EXT); + qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD); - qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); - qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); - qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); - qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); - - qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); - qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); - qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); - qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); + qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT, GL_TEXTURE); + qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT, GL_TEXTURE); + qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + + qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); + qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); + qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); + qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); - qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE); - qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); - break; - } - } - else - { + qglTexEnvi (GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, GL_TEXTURE); + qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); + break; + + default: GL_TexEnv (GL_COMBINE4_NV); qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_ADD); qglTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA_EXT, GL_ADD); @@ -2034,6 +2000,7 @@ void R_RenderMeshCombined ( meshbuffer_t *mb, shaderpass_t *pass ) qglTexEnvi (GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_ONE_MINUS_SRC_ALPHA); break; } + break; } R_ModifyTextureCoords ( pass, i ); diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 010c5d10a..e3040761c 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -3095,7 +3095,7 @@ void GL_RoundDimensions(int *scaled_width, int *scaled_height, qboolean mipmap) GL_Upload32 =============== */ -void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha) +void GL_Upload32_Int (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, GLenum glcolormode) { int miplevel=0; int samples; @@ -3108,6 +3108,20 @@ void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean m scaled_height = height; GL_RoundDimensions(&scaled_width, &scaled_height, mipmap); + if (alpha) + { //make sure it does actually have those alpha pixels + int i; + alpha = false; + for (i = 3; i < width*height*4; i+=4) + { + if (((unsigned char*)data)[i] < 255) + { + alpha = true; + break; + } + } + } + TRACE(("dbg: GL_Upload32: %i %i\n", scaled_width, scaled_height)); if (scaled_width * scaled_height > sizeofuploadmemorybuffer/4) @@ -3130,7 +3144,7 @@ texels += scaled_width * scaled_height; if (!mipmap||gl_config.sgis_generate_mipmap) //gotta love this with NPOT textures... :) { TRACE(("dbg: GL_Upload32: non-mipmapped/unscaled\n")); - qglTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + qglTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, data); goto done; } memcpy (scaled, data, width*height*4); @@ -3139,7 +3153,7 @@ texels += scaled_width * scaled_height; GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height); TRACE(("dbg: GL_Upload32: recaled\n")); - qglTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled); + qglTexImage2D (GL_TEXTURE_2D, 0, samples, scaled_width, scaled_height, 0, glcolormode, GL_UNSIGNED_BYTE, scaled); if (mipmap && !gl_config.sgis_generate_mipmap) { miplevel = 0; @@ -3228,6 +3242,15 @@ done: } } +void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha) +{ + GL_Upload32_Int(name, data, width, height, mipmap, alpha, GL_RGBA); +} +void GL_Upload32_BGRA (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha) +{ + GL_Upload32_Int(name, data, width, height, mipmap, alpha, GL_BGRA_EXT); +} + void GL_Upload24BGR (char *name, qbyte *framedata, int inwidth, int inheight, qboolean mipmap, qboolean alpha) { int outwidth, outheight; diff --git a/engine/gl/gl_hlmdl.c b/engine/gl/gl_hlmdl.c index 1b5072972..436351494 100644 --- a/engine/gl/gl_hlmdl.c +++ b/engine/gl/gl_hlmdl.c @@ -133,6 +133,13 @@ qboolean Mod_LoadHLModel (model_t *mod, void *buffer) return false; } + if (header->numcontrollers > MAX_BONE_CONTROLLERS) + { + Con_Printf(CON_ERROR "Cannot load model %s - too many controllers %i\n", mod->name, header->numcontrollers); + Hunk_FreeToLowMark(start); + return false; + } + tex = (hlmdl_tex_t *) ((qbyte *) header + header->textures); bones = (hlmdl_bone_t *) ((qbyte *) header + header->boneindex); bonectls = (hlmdl_bonecontroller_t *) ((qbyte *) header + header->controllerindex); @@ -181,107 +188,19 @@ qboolean Mod_LoadHLModel (model_t *mod, void *buffer) return true; } -/* - ======================================================================================================================= - HL_CurSequence - return the current sequence - ======================================================================================================================= - */ -int HL_CurSequence(hlmodel_t model) -{ - return model.sequence; -} - -/* - ======================================================================================================================= - HL_NewSequence - animation control (just some range checking really) - ======================================================================================================================= - */ -int HL_NewSequence(hlmodel_t *model, int _inew) -{ - if(_inew < 0) - _inew = model->header->numseq - 1; - else if(_inew >= model->header->numseq) - _inew = 0; - - model->sequence = _inew; - model->frame = 0; - { - /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - hlmdl_sequencelist_t *pseqdesc; - /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - - if(_inew == 0) - { - pseqdesc = (hlmdl_sequencelist_t *) ((qbyte *) model->header + model->header->seqindex) + model->sequence; - } - else - { - pseqdesc = (hlmdl_sequencelist_t *) ((qbyte *) model->header + model->header->seqindex) + model->sequence; - } - - Sys_Printf("Current Sequence: %s\n", pseqdesc->name); - } - - return model->sequence; -} - -/* - ======================================================================================================================= - HL_SetController - control where the model is facing (upper body usually) - ======================================================================================================================= - */ -void HL_SetController(hlmodel_t *model, int num, float value) -{ - /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - int real, limit; - hlmdl_bonecontroller_t *control = (hlmdl_bonecontroller_t *) - ((qbyte *) model->header + model->header->controllerindex); - /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ - - if(num >= model->header->numcontrollers) return; - - if(num == 4) - { - limit = 64; - } - else - { - limit = 255; - } - - if(control->type & (0x0008 | 0x0010 | 0x0020)) - { - if(control->end < control->start) value = -value; - - if(control->start + 359.0 >= control->end) - { - if(value > ((control->start + control->end) / 2.0) + 180) value = value - 360; - if(value < ((control->start + control->end) / 2.0) - 180) value = value + 360; - } - else - { - if(value > 360) - value = value - (int) (value / 360.0) * 360.0; - else if(value < 0) - value = value + (int) ((value / -360.0) + 1) * 360.0; - } - } - - real = limit * (value - control[num].start) / (control[num].end - control[num].start); - if(real < 0) real = 0; - if(real > limit) real = limit; - model->controller[num] = real; -} - /* ======================================================================================================================= HL_CalculateBones - calculate bone positions - quaternion+vector in one function ======================================================================================================================= + + note, while ender may be proud of this function, it lacks the fact that interpolating eular angles is not as acurate as interpolating quaternions. + it is faster though. */ void HL_CalculateBones ( int offset, int frame, + float lerpfrac, vec4_t adjust, hlmdl_bone_t *bone, hlmdl_anim_t *animation, @@ -291,6 +210,8 @@ void HL_CalculateBones /*~~~~~~~~~~*/ int i; vec3_t angle; + float lerpifrac = 1-lerpfrac; + float t; /*~~~~~~~~~~*/ /* For each vector */ @@ -318,18 +239,21 @@ void HL_CalculateBones if(animvalue->num.valid > tempframe) { if(animvalue->num.valid > (tempframe + 1)) - angle[i] += animvalue[tempframe + 1].value * 1; // + 0 * animvalue[tempframe + 2].value * bone->scale[o]; + { + //we can lerp that + t = animvalue[tempframe + 1].value * lerpifrac + lerpfrac * animvalue[tempframe + 2].value; + } else - angle[i] = animvalue[animvalue->num.valid].value; - angle[i] = bone->value[o] + angle[i] * bone->scale[o]; + t = animvalue[animvalue->num.valid].value; + angle[i] = bone->value[o] + t * bone->scale[o]; } else { - if(animvalue->num.total <= tempframe + 1) + if(animvalue->num.total < tempframe + 1) { angle[i] += - (animvalue[animvalue->num.valid].value * 1 + - 0 * animvalue[animvalue->num.valid + 2].value) * + (animvalue[animvalue->num.valid].value * lerpifrac + + lerpfrac * animvalue[animvalue->num.valid + 2].value) * bone->scale[o]; } else @@ -339,7 +263,8 @@ void HL_CalculateBones } } - if(bone->bonecontroller[o] != -1) { /* Add the programmable offset. */ + if(bone->bonecontroller[o] != -1) + { /* Add the programmable offset. */ angle[i] += adjust[bone->bonecontroller[o]]; } } @@ -380,7 +305,7 @@ void HL_CalcBoneAdj(hlmodel_t *model) } else { - value = model->controller[j]; + value = (model->controller[j]+1)*0.5; //shifted to give a valid range between -1 and 1, with 0 being mid-range. if(value < 0) value = 0; else if(value > 1.0) @@ -401,15 +326,20 @@ void HL_CalcBoneAdj(hlmodel_t *model) HL_SetupBones - determine where vertex should be using bone movements ======================================================================================================================= */ -void HL_SetupBones(hlmodel_t *model) +void QuaternionSlerp( const vec4_t p, vec4_t q, float t, vec4_t qt ); +void HL_SetupBones(hlmodel_t *model, int seqnum, int firstbone, int lastbone, float subblendfrac) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ int i; float matrix[3][4]; - static vec3_t positions[128]; - static vec4_t quaternions[128]; + static vec3_t positions[2]; + static vec4_t quaternions[2], blended; + + float frametime; + int frame; + hlmdl_sequencelist_t *sequence = (hlmdl_sequencelist_t *) ((qbyte *) model->header + model->header->seqindex) + - model->sequence; + ((unsigned int)seqnum>=model->header->numseq?0:seqnum); hlmdl_sequencedata_t *sequencedata = (hlmdl_sequencedata_t *) ((qbyte *) model->header + model->header->seqgroups) + sequence->seqindex; @@ -417,40 +347,119 @@ void HL_SetupBones(hlmodel_t *model) ((qbyte *) model->header + sequencedata->data + sequence->index); /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + frametime = (cl.time - cl.lerpents[currententity->keynum].framechange)*sequence->timing; + frame = (int)frametime; + frametime -= frame; + + if (!sequence->numframes) + return; + if(frame >= sequence->numframes) + { + if (sequence->motiontype&1) + frame = sequence->numframes-1; + else + frame %= sequence->numframes; + } + + if (lastbone > model->header->numbones) + lastbone = model->header->numbones; + + + HL_CalcBoneAdj(model); /* Deal with programmable controllers */ - if(sequence->motiontype & 0x0001) positions[sequence->motionbone][0] = 0.0; - if(sequence->motiontype & 0x0002) positions[sequence->motionbone][1] = 0.0; - if(sequence->motiontype & 0x0004) positions[sequence->motionbone][2] = 0.0; + /*FIXME:this is useless*/ + /* + if(sequence->motiontype & 0x0001) + positions[sequence->motionbone][0] = 0.0; + if(sequence->motiontype & 0x0002) + positions[sequence->motionbone][1] = 0.0; + if(sequence->motiontype & 0x0004) + positions[sequence->motionbone][2] = 0.0; + */ - /* Sys_Printf("Frame: %i\n", model->frame); */ - for(i = 0; i < model->header->numbones; i++) - { - /* - * There are two vector offsets in the structure. The first seems to be the - * positions of the bones, the second the quats of the bone matrix itself. We - * convert it inside the routine - Inconsistant, but hey.. so's the whole model - * format. - */ - HL_CalculateBones(0, model->frame, model->adjust, model->bones + i, animation + i, positions[i]); - HL_CalculateBones(3, model->frame, model->adjust, model->bones + i, animation + i, quaternions[i]); + /* + this is hellish. + a hl model blends: + 4 controllers (on a player, it seems each one of them twists a separate bone in the chest) + a mouth (not used on players) + its a sequence (to be smooth we need to blend between two frames in the sequence) + up to four source animations (ironically used to pitch up/down) + alternate sequence (walking+firing) + frame2 (quake expectations.) - /* FIXME: Blend the bones and make them cry :) */ - QuaternionGLMatrix(quaternions[i][0], quaternions[i][1], quaternions[i][2], quaternions[i][3], matrix); - matrix[0][3] = positions[i][0]; - matrix[1][3] = positions[i][1]; - matrix[2][3] = positions[i][2]; + this is madness, quite frankly. - /* If we have a parent, take the addition. Otherwise just copy the values */ - if(model->bones[i].parent>=0) - { - R_ConcatTransforms(transform_matrix[model->bones[i].parent], matrix, transform_matrix[i]); - } - else - { - memcpy(transform_matrix[i], matrix, 12 * sizeof(float)); - } - } + luckily... + controllers and mouth control the entire thing. they should be interpolated outside, and have no affect on blending here + alternate sequences replace. we can just call this function twice (so long as bone ranges are incremental). + autoanimating sequence is handled inside HL_CalculateBones (sequences are weird and it has to be handled there anyway) + + this means we only have sources and alternate frames left to cope with. + + FIXME: we don't handle frame2. + */ + + if (sequence->hasblendseq>1) + { + if (subblendfrac < 0) + subblendfrac = 0; + if (subblendfrac > 1) + subblendfrac = 1; + for(i = firstbone; i < lastbone; i++) + { + HL_CalculateBones(0, frame, frametime, model->adjust, model->bones + i, animation + i, positions[0]); + HL_CalculateBones(3, frame, frametime, model->adjust, model->bones + i, animation + i, quaternions[0]); + + HL_CalculateBones(3, frame, frametime, model->adjust, model->bones + i, animation + i + model->header->numbones, quaternions[1]); + + QuaternionSlerp(quaternions[0], quaternions[1], subblendfrac, blended); + QuaternionGLMatrix(blended[0], blended[1], blended[2], blended[3], matrix); + matrix[0][3] = positions[0][0]; + matrix[1][3] = positions[0][1]; + matrix[2][3] = positions[0][2]; + + /* If we have a parent, take the addition. Otherwise just copy the values */ + if(model->bones[i].parent>=0) + { + R_ConcatTransforms(transform_matrix[model->bones[i].parent], matrix, transform_matrix[i]); + } + else + { + memcpy(transform_matrix[i], matrix, 12 * sizeof(float)); + } + } + + } + else + { + for(i = firstbone; i < lastbone; i++) + { + /* + * There are two vector offsets in the structure. The first seems to be the + * positions of the bones, the second the quats of the bone matrix itself. We + * convert it inside the routine - Inconsistant, but hey.. so's the whole model + * format. + */ + HL_CalculateBones(0, frame, frametime, model->adjust, model->bones + i, animation + i, positions[0]); + HL_CalculateBones(3, frame, frametime, model->adjust, model->bones + i, animation + i, quaternions[0]); + + QuaternionGLMatrix(quaternions[0][0], quaternions[0][1], quaternions[0][2], quaternions[0][3], matrix); + matrix[0][3] = positions[0][0]; + matrix[1][3] = positions[0][1]; + matrix[2][3] = positions[0][2]; + + /* If we have a parent, take the addition. Otherwise just copy the values */ + if(model->bones[i].parent>=0) + { + R_ConcatTransforms(transform_matrix[model->bones[i].parent], matrix, transform_matrix[i]); + } + else + { + memcpy(transform_matrix[i], matrix, 12 * sizeof(float)); + } + } + } } /* @@ -465,7 +474,6 @@ void R_DrawHLModel(entity_t *curent) hlmodel_t model; int b, m, v; short *skins; - hlmdl_sequencelist_t *sequence; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ //general model @@ -474,38 +482,10 @@ void R_DrawHLModel(entity_t *curent) model.bones = (hlmdl_bone_t *) ((char *)modelc + modelc->bones); model.bonectls = (hlmdl_bonecontroller_t *) ((char *)modelc + modelc->bonectls); - //specific to entity - model.sequence = curent->frame; - model.frame = 0; - model.frametime = 0; - - HL_NewSequence(&model, curent->frame); - skins = (short *) ((qbyte *) model.header + model.header->skins); - sequence = (hlmdl_sequencelist_t *) ((qbyte *) model.header + model.header->seqindex) + - model.sequence; - model.controller[0] = curent->bonecontrols[0]; - model.controller[1] = curent->bonecontrols[1]; - model.controller[2] = curent->bonecontrols[2]; - model.controller[3] = curent->bonecontrols[3]; - model.controller[4] = 0;//sin(cl.time)*127+127; - - model.frametime += (cl.time - cl.lerpents[curent->keynum].framechange)*sequence->timing; - - if (model.frametime>=1) - { - model.frame += (int) model.frametime; - model.frametime -= (int)model.frametime; - } - - if (!sequence->numframes) - return; - if(model.frame >= sequence->numframes) - model.frame %= sequence->numframes; - - if (sequence->motiontype) - model.frame = sequence->numframes-1; + for (b = 0; b < MAX_BONE_CONTROLLERS; b++) + model.controller[b] = curent->bonecontrols[b]; GL_TexEnv(GL_MODULATE); @@ -531,7 +511,8 @@ void R_DrawHLModel(entity_t *curent) R_RotateForEntity (curent); - HL_SetupBones(&model); /* Setup the bones */ + HL_SetupBones(&model, curent->baseframe1, 0, curent->basebone, (curent->basesubblendfrac+1)*0.5); /* Setup the bones */ + HL_SetupBones(&model, curent->frame1, curent->basebone, model.header->numbones, (curent->subblendfrac+1)*0.5); /* Setup the bones */ /* Manipulate each mesh directly */ for(b = 0; b < model.header->numbodyparts; b++) diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 0ea5bc9d2..c15f4f28d 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -490,10 +490,10 @@ model_t *GLMod_LoadModel (model_t *mod, qboolean crash) // get string used for replacement tokens ext = COM_FileExtension(mod->name); if (!Q_strcasecmp(ext, "spr") || !Q_strcasecmp(ext, "sp2")) - replstr = NULL; // sprite + replstr = ""; // sprite else if (!Q_strcasecmp(ext, "dsp")) // doom sprite { - replstr = NULL; + replstr = ""; doomsprite = true; } else // assume models @@ -501,20 +501,17 @@ model_t *GLMod_LoadModel (model_t *mod, qboolean crash) // gl_load24bit 0 disables all replacements if (!gl_load24bit.value) - replstr = NULL; + replstr = ""; COM_StripExtension(mod->name, mdlbase, sizeof(mdlbase)); - while (1) + while (replstr) { - for (replstr = COM_ParseStringSet(replstr); com_token[0] && !buf; replstr = COM_ParseStringSet(replstr)) + replstr = COM_ParseStringSet(replstr); + if (replstr) buf = (unsigned *)COM_LoadStackFile (va("%s.%s", mdlbase, com_token), stackbuf, sizeof(stackbuf)); - - if (!buf) + else { - if (lastload) // only load unreplaced file once - break; - lastload = true; buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); if (!buf) { @@ -530,6 +527,8 @@ model_t *GLMod_LoadModel (model_t *mod, qboolean crash) break; // failed to load unreplaced file and nothing left } } + if (!buf) + continue; // // allocate a new model @@ -2234,6 +2233,9 @@ qboolean GLMod_LoadClipnodes (lump_t *l) hull->clip_maxs[1] = 48; hull->clip_maxs[2] = 50; hull->available = true; + + //6 isn't used. + //7 isn't used. } else if (loadmodel->fromgame == fg_halflife) { @@ -2244,10 +2246,10 @@ qboolean GLMod_LoadClipnodes (lump_t *l) hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; - hull->clip_mins[2] = -36; + hull->clip_mins[2] = -32;//-36 is correct here, but we'll just copy mvdsv instead. hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; - hull->clip_maxs[2] = 36; + hull->clip_maxs[2] = hull->clip_mins[2]+72; hull->available = true; hull = &loadmodel->hulls[2]; @@ -2260,7 +2262,7 @@ qboolean GLMod_LoadClipnodes (lump_t *l) hull->clip_mins[2] = -32; hull->clip_maxs[0] = 32; hull->clip_maxs[1] = 32; - hull->clip_maxs[2] = 32; + hull->clip_maxs[2] = hull->clip_mins[2]+64; hull->available = true; hull = &loadmodel->hulls[3]; @@ -2273,7 +2275,7 @@ qboolean GLMod_LoadClipnodes (lump_t *l) hull->clip_mins[2] = -18; hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; - hull->clip_maxs[2] = 18; + hull->clip_maxs[2] = hull->clip_mins[2]+36; hull->available = true; } else diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 916ecdf60..130e0dbfd 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -703,22 +703,22 @@ typedef enum {fg_quake, fg_quake2, fg_quake3, fg_halflife, fg_new, fg_doom} from #define EF_TRACER3 128 // purple trail //hexen2. -#define EF_FIREBALL 256 // Yellow transparent trail in all directions -#define EF_ICE 512 // Blue-white transparent trail, with gravity -#define EF_MIP_MAP 1024 // This model has mip-maps -#define EF_SPIT 2048 // Black transparent trail with negative light -#define EF_TRANSPARENT 4096 // Transparent sprite -#define EF_SPELL 8192 // Vertical spray of particles -#define EF_HOLEY 16384 // Solid model with color 0 -#define EF_SPECIAL_TRANS 32768 // Translucency through the particle table -#define EF_FACE_VIEW 65536 // Poly Model always faces you -#define EF_VORP_MISSILE 131072 // leave a trail at top and bottom of model -#define EF_SET_STAFF 262144 // slowly move up and left/right -#define EF_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity -#define EF_BONESHARD 1048576 // a trickle of brown particles with gravity -#define EF_SCARAB 2097152 // white transparent particles with little gravity -#define EF_ACIDBALL 4194304 // Green drippy acid shit -#define EF_BLOODSHOT 8388608 // Blood rain shot trail +#define EFH2_FIREBALL 256 // Yellow transparent trail in all directions +#define EFH2_ICE 512 // Blue-white transparent trail, with gravity +#define EFH2_MIP_MAP 1024 // This model has mip-maps +#define EFH2_SPIT 2048 // Black transparent trail with negative light +#define EFH2_TRANSPARENT 4096 // Transparent sprite +#define EFH2_SPELL 8192 // Vertical spray of particles +#define EFH2_HOLEY 16384 // Solid model with color 0 +#define EFH2_SPECIAL_TRANS 32768 // Translucency through the particle table +#define EFH2_FACE_VIEW 65536 // Poly Model always faces you +#define EFH2_VORP_MISSILE 131072 // leave a trail at top and bottom of model +#define EFH2_SET_STAFF 262144 // slowly move up and left/right +#define EFH2_MAGICMISSILE 524288 // a trickle of blue/white particles with gravity +#define EFH2_BONESHARD 1048576 // a trickle of brown particles with gravity +#define EFH2_SCARAB 2097152 // white transparent particles with little gravity +#define EFH2_ACIDBALL 4194304 // Green drippy acid shit +#define EFH2_BLOODSHOT 8388608 // Blood rain shot trail typedef union { struct { diff --git a/engine/gl/gl_ppl.c b/engine/gl/gl_ppl.c index 1e758697a..7030da80d 100644 --- a/engine/gl/gl_ppl.c +++ b/engine/gl/gl_ppl.c @@ -417,6 +417,8 @@ static void PPL_BaseChain_NoBump_2TMU_Overbright(msurface_t *s, texture_t *tex) { if (!s->mesh) //urm. continue; + if (s->mesh->numvertexes <= 1) + continue; if (vi != s->lightmaptexturenum) { if (vi<0) @@ -1948,7 +1950,7 @@ void R_DrawLightning(entity_t *e) vec3_t points[4]; vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; - int indexarray[6] = {0, 1, 2, 0, 2, 3}; + index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; mesh_t mesh; meshbuffer_t mb; @@ -2016,7 +2018,7 @@ void R_DrawRailCore(entity_t *e) meshbuffer_t mb; vec3_t points[4]; vec2_t texcoords[4] = {{0, 0}, {0, 1}, {1, 1}, {1, 0}}; - int indexarray[6] = {0, 1, 2, 0, 2, 3}; + index_t indexarray[6] = {0, 1, 2, 0, 2, 3}; int colors[4]; qbyte colorsb[4]; @@ -2114,7 +2116,7 @@ void R_DrawBeam( entity_t *e ) scale = e->scale; if (!scale) - scale = e->frame; + scale = e->frame1; if (!scale) scale = 6; VectorScale( perpvec, scale / 2, perpvec ); @@ -2129,7 +2131,7 @@ void R_DrawBeam( entity_t *e ) #ifdef Q3SHADERS if (e->forcedshader) { - int indexarray[NUM_BEAM_SEGS*6]; + index_t indexarray[NUM_BEAM_SEGS*6]; vec2_t texcoords[NUM_BEAM_SEGS*2]; mesh_t mesh; meshbuffer_t mb; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 218c7e2ba..b8226da73 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -63,6 +63,7 @@ int c_brush_polys, c_alias_polys; qboolean envmap; // true during envmap command capture int particletexture; // little dot for particles +int particlecqtexture; // little dot for particles int explosiontexture; int balltexture; int playertextures; // up to 16 color translated skins @@ -793,6 +794,9 @@ void R_PolyBlend (void) if ((!v_blend[3] || !gl_nohwblend.value) && !cl.cshifts[CSHIFT_SERVER].percent) return; + if (r_refdef.flags & Q2RDF_NOWORLDMODEL) + return; + GLV_CalcBlendServer(shift); //figure out the shift we need (normally just the server specified one) //Con_Printf("R_PolyBlend(): %4.2f %4.2f %4.2f %4.2f\n",shift[0], shift[1], shift[2], shift[3]); @@ -835,6 +839,9 @@ void GLR_BrightenScreen (void) if (gl_contrast.value <= 1.0) return; + if (r_refdef.flags & Q2RDF_NOWORLDMODEL) + return; + f = gl_contrast.value; f = min (f, 3); @@ -1661,6 +1668,9 @@ void GLR_RenderView (void) if (qglGetError()) Con_Printf("GL Error drawing scene\n"); + if (r_refdef.flags & Q2RDF_NOWORLDMODEL) + return; + // SCENE POST PROCESSING // we check if we need to use any shaders - currently it's just waterwarp if (scenepp_ww_program) diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 7010fcdea..1779e4715 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -122,9 +122,10 @@ static qbyte exptexture[16][16] = {0,1,1,1,7,8,1,6,7,5,4,7,1,0,0,0}, {0,1,2,1,1,5,1,3,4,3,1,1,0,0,0,0}, {0,0,0,0,0,1,1,1,1,1,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; + void R_InitParticleTexture (void) { #define PARTICLETEXTURESIZE 64 @@ -156,6 +157,38 @@ void R_InitParticleTexture (void) qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + // + // particle triangle texture + // + particlecqtexture = texture_extension_number++; + GL_Bind(particlecqtexture); + + // clear to transparent white + for (x = 0; x < 32 * 32; x++) + { + data[x][0] = 255; + data[x][1] = 255; + data[x][2] = 255; + data[x][3] = 0; + } + //draw a circle in the top left. + for (x=0 ; x<16 ; x++) + { + for (y=0 ; y<16 ; y++) + { + if ((x - 7.5) * (x - 7.5) + (y - 7.5) * (y - 7.5) <= 8 * 8) + data[y*32+x][3] = 255; + } + } + qglTexImage2D (GL_TEXTURE_2D, 0, gl_alpha_format, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + + explosiontexture = texture_extension_number++; @@ -1064,7 +1097,9 @@ void GLR_NewMap (void) // FIXME: is this one short? for (i=0 ; inumleafs ; i++) cl.worldmodel->leafs[i].efrags = NULL; - + + GLSurf_DeInit(); + r_viewleaf = NULL; r_viewcluster = -1; r_oldviewcluster = 0; diff --git a/engine/gl/gl_rsurf.c b/engine/gl/gl_rsurf.c index b9386625f..28511cc34 100644 --- a/engine/gl/gl_rsurf.c +++ b/engine/gl/gl_rsurf.c @@ -754,6 +754,9 @@ void GLR_BuildLightMap (msurface_t *surf, qbyte *dest, qbyte *deluxdest, stmap * #endif int stride = LMBLOCK_WIDTH*lightmap_bytes; + if (!surf->samples) + return; + shift += 7; // increase to base value surf->cached_dlight = (surf->dlightframe == r_framecount); @@ -3186,6 +3189,7 @@ int GLAllocBlock (int w, int h, int *x, int *y) if (!lightmap[texnum]) { lightmap[texnum] = Z_Malloc(sizeof(*lightmap[texnum])); + lightmap[texnum]->modified = true; // reset stainmap since it now starts at 255 memset(lightmap[texnum]->stainmaps, 255, sizeof(lightmap[texnum]->stainmaps)); } @@ -3255,6 +3259,7 @@ int GLFillBlock (int texnum, int w, int h, int x, int y) if (!lightmap[i]) { lightmap[i] = BZ_Malloc(sizeof(*lightmap[i])); + lightmap[i]->modified = true; for (l=0 ; lallocated[l] = LMBLOCK_HEIGHT; @@ -3263,7 +3268,16 @@ int GLFillBlock (int texnum, int w, int h, int x, int y) //maybe someone screwed with my lightmap... memset(lightmap[i]->lightmaps, 255, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3); if (cl.worldmodel->lightdata) + { memcpy(lightmap[i]->lightmaps, cl.worldmodel->lightdata+3*LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3); + } + else + { + char basename[MAX_QPATH]; + COM_StripExtension(cl.worldmodel->name, basename, sizeof(basename)); + lightmap_textures[i] = Mod_LoadHiResTexture(va("%s/lm_%04i", basename, i), NULL, true, false, false); + lightmap[i]->modified = false; + } } else @@ -3522,6 +3536,7 @@ void GL_CreateSurfaceLightmap (msurface_t *surf, int shift) void GLSurf_DeInit(void) { int i; + qglDeleteTextures(numlightmaps, lightmap_textures); for (i = 0; i < numlightmaps; i++) { if (!lightmap[i]) @@ -3658,11 +3673,13 @@ void GL_BuildLightmaps (void) { if (!lightmap[i]) break; // no more used - lightmap[i]->modified = false; lightmap[i]->rectchange.l = LMBLOCK_WIDTH; lightmap[i]->rectchange.t = LMBLOCK_HEIGHT; lightmap[i]->rectchange.w = 0; lightmap[i]->rectchange.h = 0; + if (!lightmap[i]->modified) + continue; + lightmap[i]->modified = false; GL_Bind(lightmap_textures[i]); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 21ae3eed7..810e6405b 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -2495,6 +2495,38 @@ int R_LoadShader ( char *name, void(*defaultgen)(char *name, shader_t*)) return -1; } +cin_t *R_ShaderGetCinematic(char *name) +{ + int i, j; + char shortname[MAX_QPATH]; + shader_t *s; + + COM_StripExtension ( name, shortname, sizeof(shortname)); + + COM_CleanUpPath(shortname); + + //try and find it + for (i = 0; i < MAX_SHADERS; i++) + { + if (!r_shaders[i].registration_sequence) + continue; + + if (!Q_stricmp (shortname, r_shaders[i].name) ) + break; + } + if (i == MAX_SHADERS) + return NULL; + + //we have a currently-loaded shader. + s = &r_shaders[i]; + for (j = 0; j < s->numpasses; j++) + if (s->passes[j].cin) + return s->passes[j].cin; + + //but it has no cinematic passes. + return NULL; +} + shader_t *R_RegisterPic (char *name) { return &r_shaders[R_LoadShader (name, Shader_Default2D)]; diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index dba3dafbe..eba33d162 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -97,6 +97,8 @@ void (APIENTRY *qglFogf) (GLenum pname, GLfloat param); void (APIENTRY *qglFogi) (GLenum pname, GLint param); void (APIENTRY *qglFogfv) (GLenum pname, const GLfloat *params); +void (APIENTRY *qglDeleteTextures) (GLsizei n, const GLuint *textures); + /* PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; PFNGLGETPROGRAMIVARBPROC qglGetProgramivARB; @@ -540,6 +542,7 @@ void GL_Init(void *(*getglfunction) (char *name)) qglViewport = (void *)getglcore("glViewport"); qglGetError = (void *)getglcore("glGetError"); + qglDeleteTextures = (void *)getglcore("glDeleteTextures"); //various vertex array stuff. qglDrawElements = (void *)getglcore("glDrawElements"); diff --git a/engine/gl/gl_vidnt.c b/engine/gl/gl_vidnt.c index 586fcde16..4d0a74962 100644 --- a/engine/gl/gl_vidnt.c +++ b/engine/gl/gl_vidnt.c @@ -915,10 +915,13 @@ void GL_DoSwap (void) } else { - if ((key_dest == key_game||mouseusedforgui) && !mouseactive && ActiveApp) + if ((key_dest == key_game||(mouseusedforgui && key_dest != key_console)) && ActiveApp) { - IN_ActivateMouse (); - IN_HideMouse (); + if (!mouseactive) + { + IN_ActivateMouse (); + IN_HideMouse (); + } } else if (mouseactive && key_dest == key_console) {//!(key_dest == key_game || mouseusedforgui)) { diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 1f2ff5225..507ed4092 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -144,6 +144,7 @@ extern gl_config_t gl_config; extern float gldepthmin, gldepthmax; void GL_Upload32 (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha); //name was added for texture compression output +void GL_Upload32_BGRA (char *name, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha); //name was added for texture compression output void GL_Upload8 (char *name, qbyte *data, int width, int height, qboolean mipmap, qboolean alpha); void GL_Upload24BGR_Flip (char *name, qbyte *data, int width, int height, qboolean mipmap, qboolean alpha); void GL_Upload24BGR (char *name, qbyte *data, int width, int height, qboolean mipmap, qboolean alpha); @@ -230,6 +231,7 @@ extern int d_lightstylevalue[256]; // 8.8 fraction of base light value extern qboolean envmap; extern int particletexture; +extern int particlecqtexture; extern int explosiontexture; extern int balltexture; extern int netgraphtexture; // netgraph texture @@ -306,7 +308,6 @@ void R_DrawRailCore(entity_t *e); void R_DrawLightning(entity_t *e); void R_DrawBeam( entity_t *e ); -void P_FlushRenderer(void); #endif // diff --git a/engine/gl/model_hl.h b/engine/gl/model_hl.h index fd5b76ba4..746da1000 100644 --- a/engine/gl/model_hl.h +++ b/engine/gl/model_hl.h @@ -174,8 +174,8 @@ typedef struct int motionbone; vec3_t unknown3; int unknown4[2]; - vec3_t unknown5[2]; - int unknown6; + vec3_t bbox[2]; + int hasblendseq; int index; int unknown7[2]; float unknown[4]; @@ -203,9 +203,6 @@ typedef struct */ typedef struct { - int sequence; - int frame; /* Current animation sequence and frame */ - float frametime; /* Time of last frame drawn */ float controller[4]; /* Position of bone controllers */ float adjust[4]; @@ -231,7 +228,4 @@ void QuaternionGLMatrix(float x, float y, float z, float w, vec4_t *GLM); /* HL drawing */ qboolean Mod_LoadHLModel (model_t *mod, void *buffer); -int HL_CurSequence(hlmodel_t model); -int HL_NewSequence(hlmodel_t * model, int _inew); -void HL_SetController(hlmodel_t *model, int num, float value); void R_Draw_HL_AliasModel(hlmodel_t *model); diff --git a/engine/gl/shader.h b/engine/gl/shader.h index d432dff82..ce54effea 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -268,6 +268,8 @@ shader_t *R_RegisterShader_Flare (char *name); shader_t *R_RegisterSkin (char *name); shader_t *R_RegisterCustom (char *name, void(*defaultgen)(char *name, shader_t*)); +cin_t *R_ShaderGetCinematic(char *name); + void Shader_DefaultSkinShell(char *shortname, shader_t *s); diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index fa511ece0..1611ad9cc 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -289,14 +289,29 @@ reeval: //store a value to a pointer case OP_STOREP_IF: + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); ptr->_float = (float)OPA->_int; break; case OP_STOREP_FI: + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); ptr->_int = (int)OPA->_float; break; case OP_STOREP_I: + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); ptr->_int = OPA->_int; break; @@ -305,10 +320,20 @@ reeval: case OP_STOREP_FLD: // integers case OP_STOREP_S: case OP_STOREP_FNC: // pointers + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); ptr->_int = OPA->_int; break; case OP_STOREP_V: + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); ptr->_vector[0] = OPA->_vector[0]; ptr->_vector[1] = OPA->_vector[1]; @@ -316,6 +341,11 @@ reeval: break; case OP_STOREP_C: //store character in a string + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); *(unsigned char *)ptr = (char)OPA->_float; break; @@ -329,6 +359,11 @@ reeval: OPB->_vector[2] *= OPA->_float; break; case OP_MULSTOREP_F: // e.f *= f + if ((unsigned int)OPB->_int >= addressableused) + { + pr_xstatement = st-pr_statements; + PR_RunError (progfuncs, "bad pointer write in %s", progfuncs->stringtable + pr_xfunction->s_name); + } ptr = QCPOINTER(OPB); OPC->_float = (ptr->_float *= OPA->_float); break; @@ -726,7 +761,7 @@ if (pr_typecurrent != 0) OPC->_vector[2] = ptr->_vector[2]; break; - case OP_POWER_I: + case OP_XOR_I: OPC->_int = OPA->_int ^ OPB->_int; break; case OP_RSHIFT_I: diff --git a/engine/qclib/execloop16d.h b/engine/qclib/execloop16d.h deleted file mode 100644 index fa511ece0..000000000 --- a/engine/qclib/execloop16d.h +++ /dev/null @@ -1,1071 +0,0 @@ -//qc execution code. -//we have two conditions. -//one allows us to debug and trace through our code, the other doesn't. - -//hopefully, the compiler will do a great job at optimising this code for us, where required. -//if it dosn't, then bum. - -//the general overhead should be reduced significantly, and I would be supprised if it did run slower. - -//run away loops are checked for ONLY on gotos and function calls. This might give a poorer check, but it will run faster overall. - -//Appears to work fine. - -#if INTSIZE == 16 -#define cont cont16 -#define reeval reeval16 -#define st st16 -#define pr_statements pr_statements16 -#define fakeop fakeop16 -#define dstatement_t dstatement16_t -#define sofs signed short -#define uofs unsigned short -#elif INTSIZE == 32 -#define cont cont32 -#define reeval reeval32 -#define st st32 -#define pr_statements pr_statements32 -#define fakeop fakeop32 -#define dstatement_t dstatement32_t -#define sofs signed int -#define uofs unsigned int -#elif INTSIZE == 24 -#error INTSIZE should be set to 32. -#else -#error Bad cont size -#endif - -#define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable) -#define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable) -#define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable) - -//rely upon just st -{ -#ifdef DEBUGABLE -cont: //last statement may have been a breakpoint - s = st-pr_statements; - s+=1; - s=ShowStep(progfuncs, s); - st = pr_statements + s; - -reeval: -#else - st++; -#endif - - switch (st->op) - { - case OP_ADD_F: - OPC->_float = OPA->_float + OPB->_float; - break; - case OP_ADD_V: - OPC->_vector[0] = OPA->_vector[0] + OPB->_vector[0]; - OPC->_vector[1] = OPA->_vector[1] + OPB->_vector[1]; - OPC->_vector[2] = OPA->_vector[2] + OPB->_vector[2]; - break; - - case OP_SUB_F: - OPC->_float = OPA->_float - OPB->_float; - break; - case OP_SUB_V: - OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0]; - OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1]; - OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2]; - break; - - case OP_MUL_F: - OPC->_float = OPA->_float * OPB->_float; - break; - case OP_MUL_V: - OPC->_float = OPA->_vector[0]*OPB->_vector[0] - + OPA->_vector[1]*OPB->_vector[1] - + OPA->_vector[2]*OPB->_vector[2]; - break; - case OP_MUL_FV: - OPC->_vector[0] = OPA->_float * OPB->_vector[0]; - OPC->_vector[1] = OPA->_float * OPB->_vector[1]; - OPC->_vector[2] = OPA->_float * OPB->_vector[2]; - break; - case OP_MUL_VF: - OPC->_vector[0] = OPB->_float * OPA->_vector[0]; - OPC->_vector[1] = OPB->_float * OPA->_vector[1]; - OPC->_vector[2] = OPB->_float * OPA->_vector[2]; - break; - - case OP_DIV_F: - OPC->_float = OPA->_float / OPB->_float; - break; - case OP_DIV_VF: - OPC->_vector[0] = OPB->_float / OPA->_vector[0]; - OPC->_vector[1] = OPB->_float / OPA->_vector[1]; - OPC->_vector[2] = OPB->_float / OPA->_vector[2]; - break; - - case OP_BITAND: - OPC->_float = (float)((int)OPA->_float & (int)OPB->_float); - break; - - case OP_BITOR: - OPC->_float = (float)((int)OPA->_float | (int)OPB->_float); - break; - - - case OP_GE: - OPC->_float = (float)(OPA->_float >= OPB->_float); - break; - case OP_GE_I: - OPC->_int = (int)(OPA->_int >= OPB->_int); - break; - case OP_GE_IF: - OPC->_float = (float)(OPA->_int >= OPB->_float); - break; - case OP_GE_FI: - OPC->_float = (float)(OPA->_float >= OPB->_int); - break; - - case OP_LE: - OPC->_float = (float)(OPA->_float <= OPB->_float); - break; - case OP_LE_I: - OPC->_int = (int)(OPA->_int <= OPB->_int); - break; - case OP_LE_IF: - OPC->_float = (float)(OPA->_int <= OPB->_float); - break; - case OP_LE_FI: - OPC->_float = (float)(OPA->_float <= OPB->_int); - break; - - case OP_GT: - OPC->_float = (float)(OPA->_float > OPB->_float); - break; - case OP_GT_I: - OPC->_int = (int)(OPA->_int > OPB->_int); - break; - case OP_GT_IF: - OPC->_float = (float)(OPA->_int > OPB->_float); - break; - case OP_GT_FI: - OPC->_float = (float)(OPA->_float > OPB->_int); - break; - - case OP_LT: - OPC->_float = (float)(OPA->_float < OPB->_float); - break; - case OP_LT_I: - OPC->_int = (int)(OPA->_int < OPB->_int); - break; - case OP_LT_IF: - OPC->_float = (float)(OPA->_int < OPB->_float); - break; - case OP_LT_FI: - OPC->_float = (float)(OPA->_float < OPB->_int); - break; - - case OP_AND: - OPC->_float = (float)(OPA->_float && OPB->_float); - break; - case OP_OR: - OPC->_float = (float)(OPA->_float || OPB->_float); - break; - - case OP_NOT_F: - OPC->_float = (float)(!OPA->_float); - break; - case OP_NOT_V: - OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); - break; - case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); - break; - case OP_NOT_FNC: - OPC->_float = (float)(!(OPA->function & ~0xff000000)); - break; - case OP_NOT_ENT: - OPC->_float = (float)(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts); - break; - - case OP_EQ_F: - OPC->_float = (float)(OPA->_float == OPB->_float); - break; - case OP_EQ_IF: - OPC->_float = (float)(OPA->_int == OPB->_float); - break; - case OP_EQ_FI: - OPC->_float = (float)(OPA->_float == OPB->_int); - break; - - - case OP_EQ_V: - OPC->_float = (float)((OPA->_vector[0] == OPB->_vector[0]) && - (OPA->_vector[1] == OPB->_vector[1]) && - (OPA->_vector[2] == OPB->_vector[2])); - break; - case OP_EQ_S: - if (OPA->string==OPB->string) - OPC->_float = true; - else if (!OPA->string) - { - if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) - OPC->_float = true; - else - OPC->_float = false; - } - else if (!OPB->string) - { - if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) - OPC->_float = true; - else - OPC->_float = false; - } - else - OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); - break; - case OP_EQ_E: - OPC->_float = (float)(OPA->_int == OPB->_int); - break; - case OP_EQ_FNC: - OPC->_float = (float)(OPA->function == OPB->function); - break; - - - case OP_NE_F: - OPC->_float = (float)(OPA->_float != OPB->_float); - break; - case OP_NE_V: - OPC->_float = (float)((OPA->_vector[0] != OPB->_vector[0]) || - (OPA->_vector[1] != OPB->_vector[1]) || - (OPA->_vector[2] != OPB->_vector[2])); - break; - case OP_NE_S: - if (OPA->string==OPB->string) - OPC->_float = false; - else if (!OPA->string) - { - if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) - OPC->_float = false; - else - OPC->_float = true; - } - else if (!OPB->string) - { - if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) - OPC->_float = false; - else - OPC->_float = true; - } - else - OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); - break; - case OP_NE_E: - OPC->_float = (float)(OPA->_int != OPB->_int); - break; - case OP_NE_FNC: - OPC->_float = (float)(OPA->function != OPB->function); - break; - -//================== - case OP_STORE_IF: - OPB->_float = (float)OPA->_int; - break; - case OP_STORE_FI: - OPB->_int = (int)OPA->_float; - break; - case OP_STORE_I: - OPB->_int = OPA->_int; - break; - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FNC: // pointers - OPB->_int = OPA->_int; - break; - case OP_STORE_V: - OPB->_vector[0] = OPA->_vector[0]; - OPB->_vector[1] = OPA->_vector[1]; - OPB->_vector[2] = OPA->_vector[2]; - break; - - //store a value to a pointer - case OP_STOREP_IF: - ptr = QCPOINTER(OPB); - ptr->_float = (float)OPA->_int; - break; - case OP_STOREP_FI: - ptr = QCPOINTER(OPB); - ptr->_int = (int)OPA->_float; - break; - case OP_STOREP_I: - ptr = QCPOINTER(OPB); - ptr->_int = OPA->_int; - break; - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FNC: // pointers - ptr = QCPOINTER(OPB); - ptr->_int = OPA->_int; - break; - case OP_STOREP_V: - ptr = QCPOINTER(OPB); - ptr->_vector[0] = OPA->_vector[0]; - ptr->_vector[1] = OPA->_vector[1]; - ptr->_vector[2] = OPA->_vector[2]; - break; - - case OP_STOREP_C: //store character in a string - ptr = QCPOINTER(OPB); - *(unsigned char *)ptr = (char)OPA->_float; - break; - - case OP_MULSTORE_F: // f *= f - OPB->_float *= OPA->_float; - break; - case OP_MULSTORE_V: // v *= f - OPB->_vector[0] *= OPA->_float; - OPB->_vector[1] *= OPA->_float; - OPB->_vector[2] *= OPA->_float; - break; - case OP_MULSTOREP_F: // e.f *= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float *= OPA->_float); - break; - case OP_MULSTOREP_V: // e.v *= f - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float); - OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float); - OPC->_vector[0] = (ptr->_vector[2] *= OPA->_float); - break; - - case OP_DIVSTORE_F: // f /= f - OPB->_float /= OPA->_float; - break; - case OP_DIVSTOREP_F: // e.f /= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float /= OPA->_float); - break; - - case OP_ADDSTORE_F: // f += f - OPB->_float += OPA->_float; - break; - case OP_ADDSTORE_V: // v += v - OPB->_vector[0] += OPA->_vector[0]; - OPB->_vector[1] += OPA->_vector[1]; - OPB->_vector[2] += OPA->_vector[2]; - break; - case OP_ADDSTOREP_F: // e.f += f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float += OPA->_float); - break; - case OP_ADDSTOREP_V: // e.v += v - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]); - OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]); - OPC->_vector[2] = (ptr->_vector[2] += OPA->_vector[2]); - break; - - case OP_SUBSTORE_F: // f -= f - OPB->_float -= OPA->_float; - break; - case OP_SUBSTORE_V: // v -= v - OPB->_vector[0] -= OPA->_vector[0]; - OPB->_vector[1] -= OPA->_vector[1]; - OPB->_vector[2] -= OPA->_vector[2]; - break; - case OP_SUBSTOREP_F: // e.f -= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float -= OPA->_float); - break; - case OP_SUBSTOREP_V: // e.v -= v - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]); - OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]); - OPC->_vector[2] = (ptr->_vector[2] -= OPA->_vector[2]); - break; - - - //get a pointer to a field var - case OP_ADDRESS: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - if (!ed || ed->readonly) - { - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - } - -//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. -// if (ed->isfree) -// { -// pr_xstatement = st-pr_statements; -// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); -// } - OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); - break; - - //load a field to a value - case OP_LOAD_I: - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust); - OPC->_int = ptr->_int; - break; - - case OP_LOAD_V: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - -//================== - - case OP_IFNOTS: - RUNAWAYCHECK(); - if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFNOT: - RUNAWAYCHECK(); - if (!OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFS: - RUNAWAYCHECK(); - if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IF: - RUNAWAYCHECK(); - if (OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_GOTO: - RUNAWAYCHECK(); - st += (sofs)st->a - 1; // offset the s++ - break; - - case OP_CALL8H: - case OP_CALL7H: - case OP_CALL6H: - case OP_CALL5H: - case OP_CALL4H: - case OP_CALL3H: - case OP_CALL2H: - G_VECTOR(OFS_PARM1)[0] = OPC->_vector[0]; - G_VECTOR(OFS_PARM1)[1] = OPC->_vector[1]; - G_VECTOR(OFS_PARM1)[2] = OPC->_vector[2]; - case OP_CALL1H: - G_VECTOR(OFS_PARM0)[0] = OPB->_vector[0]; - G_VECTOR(OFS_PARM0)[1] = OPB->_vector[1]; - G_VECTOR(OFS_PARM0)[2] = OPB->_vector[2]; - - case OP_CALL8: - case OP_CALL7: - case OP_CALL6: - case OP_CALL5: - case OP_CALL4: - case OP_CALL3: - case OP_CALL2: - case OP_CALL1: - case OP_CALL0: - RUNAWAYCHECK(); - pr_xstatement = st-pr_statements; - - - if (st->op > OP_CALL8) - pr_argc = st->op - (OP_CALL1H-1); - else - pr_argc = st->op - OP_CALL0; - fnum = OPA->function; - if ((fnum & ~0xff000000)==0) - { - pr_trace++; - printf("NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name); -#ifndef DEBUGABLE - goto cont; -#endif - break; - } -/* -{ - static char buffer[1024*1024*8]; - int size = sizeof buffer; - progfuncs->save_ents(progfuncs, buffer, &size, 0); -}*/ - - - p=pr_typecurrent; -//about to switch. needs caching. - - //if it's an external call, switch now (before any function pointers are used) - PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p); - PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24); - - newf = &pr_functions[fnum & ~0xff000000]; - - if (newf->first_statement < 0) - { // negative statements are built in functions - -if (pr_typecurrent != 0) -{ - PR_MoveParms(progfuncs, 0, pr_typecurrent); - PR_SwitchProgs(progfuncs, 0); -} - i = -newf->first_statement; -// p = pr_typecurrent; - progfuncs->lastcalledbuiltinnumber = i; - if (i < externs->numglobalbuiltins) - { - prinst->numtempstringsstack = prinst->numtempstrings; - (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); - if (prinst->continuestatement!=-1) - { - st=&pr_statements[prinst->continuestatement]; - prinst->continuestatement=-1; - break; - } - } - else - { - i -= externs->numglobalbuiltins; - if (i >= current_progstate->numbuiltins) - { -// if (newf->first_statement == -0x7fffffff) -// ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals); -// else - PR_RunError (progfuncs, "Bad builtin call number - %i", -newf->first_statement); - } - else - current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals); - } - PR_MoveParms(progfuncs, p, pr_typecurrent); -// memcpy(&pr_progstate[p].globals[OFS_RETURN], ¤t_progstate->globals[OFS_RETURN], sizeof(vec3_t)); - PR_SwitchProgs(progfuncs, (progsnum_t)p); - -//#ifndef DEBUGABLE //decide weather non debugger wants to start debugging. - s = st-pr_statements; - goto restart; -//#endif -// break; - } -// PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent); -// PR_SwitchProgs((OPA->function & 0xff000000)>>24); - s = PR_EnterFunction (progfuncs, newf, p); - st = &pr_statements[s]; - - goto restart; -// break; - - case OP_DONE: - case OP_RETURN: - - RUNAWAYCHECK(); - - pr_globals[OFS_RETURN] = pr_globals[st->a]; - pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; - pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; -/* -{ - static char buffer[1024*1024*8]; - int size = sizeof buffer; - progfuncs->save_ents(progfuncs, buffer, &size, 0); -} -*/ - s = PR_LeaveFunction (progfuncs); - st = &pr_statements[s]; - if (pr_depth == prinst->exitdepth) - { - return; // all done - } - goto restart; -// break; - - case OP_STATE: - externs->stateop(progfuncs, OPA->_float, OPB->function); - break; - - case OP_ADD_I: - OPC->_int = OPA->_int + OPB->_int; - break; - case OP_ADD_FI: - OPC->_float = OPA->_float + (float)OPB->_int; - break; - case OP_ADD_IF: - OPC->_float = (float)OPA->_int + OPB->_float; - break; - - case OP_SUB_I: - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_SUB_FI: - OPC->_float = OPA->_float - (float)OPB->_int; - break; - case OP_SUB_IF: - OPC->_float = (float)OPA->_int - OPB->_float; - break; - - case OP_CONV_ITOF: - OPC->_float = (float)OPA->_int; - break; - case OP_CONV_FTOI: - OPC->_int = (int)OPA->_float; - break; - - case OP_CP_ITOF: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_float = (float)ptr->_int; - break; - - case OP_CP_FTOI: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_int = (int)ptr->_float; - break; - - case OP_BITAND_I: - OPC->_int = (OPA->_int & OPB->_int); - break; - - case OP_BITOR_I: - OPC->_int = (OPA->_int | OPB->_int); - break; - - case OP_MUL_I: - OPC->_int = OPA->_int * OPB->_int; - break; - case OP_DIV_I: - if (OPB->_int == 0) //no division by zero allowed... - OPC->_int = 0; - else - OPC->_int = OPA->_int / OPB->_int; - break; - case OP_EQ_I: - OPC->_int = (OPA->_int == OPB->_int); - break; - case OP_NE_I: - OPC->_int = (OPA->_int != OPB->_int); - break; - - - //array/structure reading/riting. - case OP_GLOBALADDRESS: - OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); - break; - case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors) - OPC->_int = OPA->_int + OPB->_int*4; - break; - - case OP_LOADA_I: - case OP_LOADA_F: - case OP_LOADA_FLD: - case OP_LOADA_ENT: - case OP_LOADA_S: - case OP_LOADA_FNC: - ptr = (eval_t *)(&OPA->_int + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADA_V: - ptr = (eval_t *)(&OPA->_int + OPB->_int); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - - - - case OP_ADD_SF: //(char*)c = (char*)a + (float)b - OPC->_int = OPA->_int + (int)OPB->_float; - break; - case OP_SUB_S: //(float)c = (char*)a - (char*)b - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_LOADP_C: //load character from a string - ptr = QCPOINTERM(OPA->_int + (int)OPB->_float); - OPC->_float = *(unsigned char *)ptr; - break; - case OP_LOADP_I: - case OP_LOADP_F: - case OP_LOADP_FLD: - case OP_LOADP_ENT: - case OP_LOADP_S: - case OP_LOADP_FNC: - ptr = QCPOINTERM(OPA->_int + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADP_V: - ptr = QCPOINTERM(OPA->_int + OPB->_int); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - - case OP_POWER_I: - OPC->_int = OPA->_int ^ OPB->_int; - break; - case OP_RSHIFT_I: - OPC->_int = OPA->_int >> OPB->_int; - break; - case OP_LSHIFT_I: - OPC->_int = OPA->_int << OPB->_int; - break; - - - case OP_FETCH_GBL_F: - case OP_FETCH_GBL_S: - case OP_FETCH_GBL_E: - case OP_FETCH_GBL_FNC: - i = (int)OPB->_float; - if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a + i]; - OPC->_int = t->_int; - break; - case OP_FETCH_GBL_V: - i = (int)OPB->_float; - if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a - +((int)OPB->_float)*3]; - OPC->_vector[0] = t->_vector[0]; - OPC->_vector[1] = t->_vector[1]; - OPC->_vector[2] = t->_vector[2]; - break; - - case OP_CSTATE: - externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_CWSTATE: - externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_THINKTIME: - externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float); - break; - - - case OP_BITSET: // b (+) a - OPB->_float = (float)((int)OPB->_float | (int)OPA->_float); - break; - case OP_BITSETP: // .b (+) a - ptr = QCPOINTER(OPB); - ptr->_float = (float)((int)ptr->_float | (int)OPA->_float); - break; - case OP_BITCLR: // b (-) a - OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float)); - break; - case OP_BITCLRP: // .b (-) a - ptr = QCPOINTER(OPB); - ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float)); - break; - - case OP_RAND0: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RAND1: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; - break; - case OP_RAND2: - if(OPA->_float < OPB->_float) - { - G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_float-OPA->_float)); - } - else - { - G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPA->_float-OPB->_float)); - } - break; - case OP_RANDV0: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RANDV1: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; - break; - case OP_RANDV2: - for(i = 0; i < 3; i++) - { - if(OPA->_vector[i] < OPB->_vector[i]) - { - G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_vector[i]-OPA->_vector[i])); - } - else - { - G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) - *(OPA->_vector[i]-OPB->_vector[i])); - } - } - break; - - - case OP_SWITCH_F: - case OP_SWITCH_V: - case OP_SWITCH_S: - case OP_SWITCH_E: - case OP_SWITCH_FNC: - swtch = OPA; - swtchtype = st->op; - RUNAWAYCHECK(); - st += (sofs)st->b - 1; // offset the st++ - break; - case OP_CASE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float == OPA->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_E: - case OP_SWITCH_FNC: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_S: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). - break; - if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_V: - if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2]) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype); - break; - } - break; - case OP_CASERANGE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->c-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype); - } - break; - - - - - - - - - - case OP_BITAND_IF: - OPC->_int = (OPA->_int & (int)OPB->_float); - break; - case OP_BITOR_IF: - OPC->_int = (OPA->_int | (int)OPB->_float); - break; - case OP_BITAND_FI: - OPC->_int = ((int)OPA->_float & OPB->_int); - break; - case OP_BITOR_FI: - OPC->_int = ((int)OPA->_float | OPB->_int); - break; - - case OP_MUL_IF: - OPC->_float = (OPA->_int * OPB->_float); - break; - case OP_MUL_FI: - OPC->_float = (OPA->_float * OPB->_int); - break; - - case OP_MUL_VI: - OPC->_vector[0] = OPA->_vector[0] * OPB->_int; - OPC->_vector[1] = OPA->_vector[0] * OPB->_int; - OPC->_vector[2] = OPA->_vector[0] * OPB->_int; - break; - case OP_MUL_IV: - OPC->_vector[0] = OPB->_int * OPA->_vector[0]; - OPC->_vector[1] = OPB->_int * OPA->_vector[1]; - OPC->_vector[2] = OPB->_int * OPA->_vector[2]; - break; - - case OP_DIV_IF: - OPC->_float = (OPA->_int / OPB->_float); - break; - case OP_DIV_FI: - OPC->_float = (OPA->_float / OPB->_int); - break; - - case OP_AND_I: - OPC->_int = (OPA->_int && OPB->_int); - break; - case OP_OR_I: - OPC->_int = (OPA->_int || OPB->_int); - break; - - case OP_AND_IF: - OPC->_int = (OPA->_int && OPB->_float); - break; - case OP_OR_IF: - OPC->_int = (OPA->_int || OPB->_float); - break; - - case OP_AND_FI: - OPC->_int = (OPA->_float && OPB->_int); - break; - case OP_OR_FI: - OPC->_int = (OPA->_float || OPB->_int); - break; - - case OP_NOT_I: - OPC->_int = !OPA->_int; - break; - - case OP_NE_IF: - OPC->_int = (OPA->_int != OPB->_float); - break; - case OP_NE_FI: - OPC->_int = (OPA->_float != OPB->_int); - break; - - case OP_GSTOREP_I: - case OP_GSTOREP_F: - case OP_GSTOREP_ENT: - case OP_GSTOREP_FLD: // integers - case OP_GSTOREP_S: - case OP_GSTOREP_FNC: // pointers - case OP_GSTOREP_V: - case OP_GADDRESS: - case OP_GLOAD_I: - case OP_GLOAD_F: - case OP_GLOAD_FLD: - case OP_GLOAD_ENT: - case OP_GLOAD_S: - case OP_GLOAD_FNC: - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Extra opcode not implemented\n"); - break; - - case OP_BOUNDCHECK: - if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b) - { - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int); - } - break; -/* case OP_PUSH: - OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]); - pr_spushed += OPA->_int; - if (pr_spushed + localstack_used >= LOCALSTACK_SIZE) - { - pr_spushed = 0; - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs pushed too much"); - } - break; - case OP_POP: - pr_spushed -= OPA->_int; - if (pr_spushed < 0) - { - pr_spushed = 0; - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs poped more than it pushed"); - } - break; -*/ - default: - if (st->op & 0x8000) //break point! - { - pr_xstatement = s = st-pr_statements; - - printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable); - if (pr_trace<1) - pr_trace=1; //this is what it's for - - s = ShowStep(progfuncs, s); - st = &pr_statements[s]; //let the user move execution - pr_xstatement = s = st-pr_statements; - -#if 0 //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement - memcpy(&fakeop, st, sizeof(dstatement_t)); //don't hit the new statement as a break point, cos it's probably the same one. - fakeop.op &= ~0x8000; - st = &fakeop; //a little remapping... -#else - st->op &= ~0x8000; //just remove the breakpoint and go around again, but this time in the debugger. -#endif - - goto reeval; //reexecute - } - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "Bad opcode %i", st->op); - } -} - - -#undef cont -#undef reeval -#undef st -#undef pr_statements -#undef fakeop -#undef dstatement_t -#undef sofs -#undef uofs - -#undef ENGINEPOINTER -#undef QCPOINTER -#undef QCPOINTERM - diff --git a/engine/qclib/execloop32.h b/engine/qclib/execloop32.h deleted file mode 100644 index fa511ece0..000000000 --- a/engine/qclib/execloop32.h +++ /dev/null @@ -1,1071 +0,0 @@ -//qc execution code. -//we have two conditions. -//one allows us to debug and trace through our code, the other doesn't. - -//hopefully, the compiler will do a great job at optimising this code for us, where required. -//if it dosn't, then bum. - -//the general overhead should be reduced significantly, and I would be supprised if it did run slower. - -//run away loops are checked for ONLY on gotos and function calls. This might give a poorer check, but it will run faster overall. - -//Appears to work fine. - -#if INTSIZE == 16 -#define cont cont16 -#define reeval reeval16 -#define st st16 -#define pr_statements pr_statements16 -#define fakeop fakeop16 -#define dstatement_t dstatement16_t -#define sofs signed short -#define uofs unsigned short -#elif INTSIZE == 32 -#define cont cont32 -#define reeval reeval32 -#define st st32 -#define pr_statements pr_statements32 -#define fakeop fakeop32 -#define dstatement_t dstatement32_t -#define sofs signed int -#define uofs unsigned int -#elif INTSIZE == 24 -#error INTSIZE should be set to 32. -#else -#error Bad cont size -#endif - -#define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable) -#define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable) -#define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable) - -//rely upon just st -{ -#ifdef DEBUGABLE -cont: //last statement may have been a breakpoint - s = st-pr_statements; - s+=1; - s=ShowStep(progfuncs, s); - st = pr_statements + s; - -reeval: -#else - st++; -#endif - - switch (st->op) - { - case OP_ADD_F: - OPC->_float = OPA->_float + OPB->_float; - break; - case OP_ADD_V: - OPC->_vector[0] = OPA->_vector[0] + OPB->_vector[0]; - OPC->_vector[1] = OPA->_vector[1] + OPB->_vector[1]; - OPC->_vector[2] = OPA->_vector[2] + OPB->_vector[2]; - break; - - case OP_SUB_F: - OPC->_float = OPA->_float - OPB->_float; - break; - case OP_SUB_V: - OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0]; - OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1]; - OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2]; - break; - - case OP_MUL_F: - OPC->_float = OPA->_float * OPB->_float; - break; - case OP_MUL_V: - OPC->_float = OPA->_vector[0]*OPB->_vector[0] - + OPA->_vector[1]*OPB->_vector[1] - + OPA->_vector[2]*OPB->_vector[2]; - break; - case OP_MUL_FV: - OPC->_vector[0] = OPA->_float * OPB->_vector[0]; - OPC->_vector[1] = OPA->_float * OPB->_vector[1]; - OPC->_vector[2] = OPA->_float * OPB->_vector[2]; - break; - case OP_MUL_VF: - OPC->_vector[0] = OPB->_float * OPA->_vector[0]; - OPC->_vector[1] = OPB->_float * OPA->_vector[1]; - OPC->_vector[2] = OPB->_float * OPA->_vector[2]; - break; - - case OP_DIV_F: - OPC->_float = OPA->_float / OPB->_float; - break; - case OP_DIV_VF: - OPC->_vector[0] = OPB->_float / OPA->_vector[0]; - OPC->_vector[1] = OPB->_float / OPA->_vector[1]; - OPC->_vector[2] = OPB->_float / OPA->_vector[2]; - break; - - case OP_BITAND: - OPC->_float = (float)((int)OPA->_float & (int)OPB->_float); - break; - - case OP_BITOR: - OPC->_float = (float)((int)OPA->_float | (int)OPB->_float); - break; - - - case OP_GE: - OPC->_float = (float)(OPA->_float >= OPB->_float); - break; - case OP_GE_I: - OPC->_int = (int)(OPA->_int >= OPB->_int); - break; - case OP_GE_IF: - OPC->_float = (float)(OPA->_int >= OPB->_float); - break; - case OP_GE_FI: - OPC->_float = (float)(OPA->_float >= OPB->_int); - break; - - case OP_LE: - OPC->_float = (float)(OPA->_float <= OPB->_float); - break; - case OP_LE_I: - OPC->_int = (int)(OPA->_int <= OPB->_int); - break; - case OP_LE_IF: - OPC->_float = (float)(OPA->_int <= OPB->_float); - break; - case OP_LE_FI: - OPC->_float = (float)(OPA->_float <= OPB->_int); - break; - - case OP_GT: - OPC->_float = (float)(OPA->_float > OPB->_float); - break; - case OP_GT_I: - OPC->_int = (int)(OPA->_int > OPB->_int); - break; - case OP_GT_IF: - OPC->_float = (float)(OPA->_int > OPB->_float); - break; - case OP_GT_FI: - OPC->_float = (float)(OPA->_float > OPB->_int); - break; - - case OP_LT: - OPC->_float = (float)(OPA->_float < OPB->_float); - break; - case OP_LT_I: - OPC->_int = (int)(OPA->_int < OPB->_int); - break; - case OP_LT_IF: - OPC->_float = (float)(OPA->_int < OPB->_float); - break; - case OP_LT_FI: - OPC->_float = (float)(OPA->_float < OPB->_int); - break; - - case OP_AND: - OPC->_float = (float)(OPA->_float && OPB->_float); - break; - case OP_OR: - OPC->_float = (float)(OPA->_float || OPB->_float); - break; - - case OP_NOT_F: - OPC->_float = (float)(!OPA->_float); - break; - case OP_NOT_V: - OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); - break; - case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); - break; - case OP_NOT_FNC: - OPC->_float = (float)(!(OPA->function & ~0xff000000)); - break; - case OP_NOT_ENT: - OPC->_float = (float)(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts); - break; - - case OP_EQ_F: - OPC->_float = (float)(OPA->_float == OPB->_float); - break; - case OP_EQ_IF: - OPC->_float = (float)(OPA->_int == OPB->_float); - break; - case OP_EQ_FI: - OPC->_float = (float)(OPA->_float == OPB->_int); - break; - - - case OP_EQ_V: - OPC->_float = (float)((OPA->_vector[0] == OPB->_vector[0]) && - (OPA->_vector[1] == OPB->_vector[1]) && - (OPA->_vector[2] == OPB->_vector[2])); - break; - case OP_EQ_S: - if (OPA->string==OPB->string) - OPC->_float = true; - else if (!OPA->string) - { - if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) - OPC->_float = true; - else - OPC->_float = false; - } - else if (!OPB->string) - { - if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) - OPC->_float = true; - else - OPC->_float = false; - } - else - OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); - break; - case OP_EQ_E: - OPC->_float = (float)(OPA->_int == OPB->_int); - break; - case OP_EQ_FNC: - OPC->_float = (float)(OPA->function == OPB->function); - break; - - - case OP_NE_F: - OPC->_float = (float)(OPA->_float != OPB->_float); - break; - case OP_NE_V: - OPC->_float = (float)((OPA->_vector[0] != OPB->_vector[0]) || - (OPA->_vector[1] != OPB->_vector[1]) || - (OPA->_vector[2] != OPB->_vector[2])); - break; - case OP_NE_S: - if (OPA->string==OPB->string) - OPC->_float = false; - else if (!OPA->string) - { - if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) - OPC->_float = false; - else - OPC->_float = true; - } - else if (!OPB->string) - { - if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) - OPC->_float = false; - else - OPC->_float = true; - } - else - OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); - break; - case OP_NE_E: - OPC->_float = (float)(OPA->_int != OPB->_int); - break; - case OP_NE_FNC: - OPC->_float = (float)(OPA->function != OPB->function); - break; - -//================== - case OP_STORE_IF: - OPB->_float = (float)OPA->_int; - break; - case OP_STORE_FI: - OPB->_int = (int)OPA->_float; - break; - case OP_STORE_I: - OPB->_int = OPA->_int; - break; - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FNC: // pointers - OPB->_int = OPA->_int; - break; - case OP_STORE_V: - OPB->_vector[0] = OPA->_vector[0]; - OPB->_vector[1] = OPA->_vector[1]; - OPB->_vector[2] = OPA->_vector[2]; - break; - - //store a value to a pointer - case OP_STOREP_IF: - ptr = QCPOINTER(OPB); - ptr->_float = (float)OPA->_int; - break; - case OP_STOREP_FI: - ptr = QCPOINTER(OPB); - ptr->_int = (int)OPA->_float; - break; - case OP_STOREP_I: - ptr = QCPOINTER(OPB); - ptr->_int = OPA->_int; - break; - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FNC: // pointers - ptr = QCPOINTER(OPB); - ptr->_int = OPA->_int; - break; - case OP_STOREP_V: - ptr = QCPOINTER(OPB); - ptr->_vector[0] = OPA->_vector[0]; - ptr->_vector[1] = OPA->_vector[1]; - ptr->_vector[2] = OPA->_vector[2]; - break; - - case OP_STOREP_C: //store character in a string - ptr = QCPOINTER(OPB); - *(unsigned char *)ptr = (char)OPA->_float; - break; - - case OP_MULSTORE_F: // f *= f - OPB->_float *= OPA->_float; - break; - case OP_MULSTORE_V: // v *= f - OPB->_vector[0] *= OPA->_float; - OPB->_vector[1] *= OPA->_float; - OPB->_vector[2] *= OPA->_float; - break; - case OP_MULSTOREP_F: // e.f *= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float *= OPA->_float); - break; - case OP_MULSTOREP_V: // e.v *= f - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float); - OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float); - OPC->_vector[0] = (ptr->_vector[2] *= OPA->_float); - break; - - case OP_DIVSTORE_F: // f /= f - OPB->_float /= OPA->_float; - break; - case OP_DIVSTOREP_F: // e.f /= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float /= OPA->_float); - break; - - case OP_ADDSTORE_F: // f += f - OPB->_float += OPA->_float; - break; - case OP_ADDSTORE_V: // v += v - OPB->_vector[0] += OPA->_vector[0]; - OPB->_vector[1] += OPA->_vector[1]; - OPB->_vector[2] += OPA->_vector[2]; - break; - case OP_ADDSTOREP_F: // e.f += f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float += OPA->_float); - break; - case OP_ADDSTOREP_V: // e.v += v - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]); - OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]); - OPC->_vector[2] = (ptr->_vector[2] += OPA->_vector[2]); - break; - - case OP_SUBSTORE_F: // f -= f - OPB->_float -= OPA->_float; - break; - case OP_SUBSTORE_V: // v -= v - OPB->_vector[0] -= OPA->_vector[0]; - OPB->_vector[1] -= OPA->_vector[1]; - OPB->_vector[2] -= OPA->_vector[2]; - break; - case OP_SUBSTOREP_F: // e.f -= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float -= OPA->_float); - break; - case OP_SUBSTOREP_V: // e.v -= v - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]); - OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]); - OPC->_vector[2] = (ptr->_vector[2] -= OPA->_vector[2]); - break; - - - //get a pointer to a field var - case OP_ADDRESS: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - if (!ed || ed->readonly) - { - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - } - -//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. -// if (ed->isfree) -// { -// pr_xstatement = st-pr_statements; -// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); -// } - OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); - break; - - //load a field to a value - case OP_LOAD_I: - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust); - OPC->_int = ptr->_int; - break; - - case OP_LOAD_V: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - -//================== - - case OP_IFNOTS: - RUNAWAYCHECK(); - if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFNOT: - RUNAWAYCHECK(); - if (!OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFS: - RUNAWAYCHECK(); - if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IF: - RUNAWAYCHECK(); - if (OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_GOTO: - RUNAWAYCHECK(); - st += (sofs)st->a - 1; // offset the s++ - break; - - case OP_CALL8H: - case OP_CALL7H: - case OP_CALL6H: - case OP_CALL5H: - case OP_CALL4H: - case OP_CALL3H: - case OP_CALL2H: - G_VECTOR(OFS_PARM1)[0] = OPC->_vector[0]; - G_VECTOR(OFS_PARM1)[1] = OPC->_vector[1]; - G_VECTOR(OFS_PARM1)[2] = OPC->_vector[2]; - case OP_CALL1H: - G_VECTOR(OFS_PARM0)[0] = OPB->_vector[0]; - G_VECTOR(OFS_PARM0)[1] = OPB->_vector[1]; - G_VECTOR(OFS_PARM0)[2] = OPB->_vector[2]; - - case OP_CALL8: - case OP_CALL7: - case OP_CALL6: - case OP_CALL5: - case OP_CALL4: - case OP_CALL3: - case OP_CALL2: - case OP_CALL1: - case OP_CALL0: - RUNAWAYCHECK(); - pr_xstatement = st-pr_statements; - - - if (st->op > OP_CALL8) - pr_argc = st->op - (OP_CALL1H-1); - else - pr_argc = st->op - OP_CALL0; - fnum = OPA->function; - if ((fnum & ~0xff000000)==0) - { - pr_trace++; - printf("NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name); -#ifndef DEBUGABLE - goto cont; -#endif - break; - } -/* -{ - static char buffer[1024*1024*8]; - int size = sizeof buffer; - progfuncs->save_ents(progfuncs, buffer, &size, 0); -}*/ - - - p=pr_typecurrent; -//about to switch. needs caching. - - //if it's an external call, switch now (before any function pointers are used) - PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p); - PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24); - - newf = &pr_functions[fnum & ~0xff000000]; - - if (newf->first_statement < 0) - { // negative statements are built in functions - -if (pr_typecurrent != 0) -{ - PR_MoveParms(progfuncs, 0, pr_typecurrent); - PR_SwitchProgs(progfuncs, 0); -} - i = -newf->first_statement; -// p = pr_typecurrent; - progfuncs->lastcalledbuiltinnumber = i; - if (i < externs->numglobalbuiltins) - { - prinst->numtempstringsstack = prinst->numtempstrings; - (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); - if (prinst->continuestatement!=-1) - { - st=&pr_statements[prinst->continuestatement]; - prinst->continuestatement=-1; - break; - } - } - else - { - i -= externs->numglobalbuiltins; - if (i >= current_progstate->numbuiltins) - { -// if (newf->first_statement == -0x7fffffff) -// ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals); -// else - PR_RunError (progfuncs, "Bad builtin call number - %i", -newf->first_statement); - } - else - current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals); - } - PR_MoveParms(progfuncs, p, pr_typecurrent); -// memcpy(&pr_progstate[p].globals[OFS_RETURN], ¤t_progstate->globals[OFS_RETURN], sizeof(vec3_t)); - PR_SwitchProgs(progfuncs, (progsnum_t)p); - -//#ifndef DEBUGABLE //decide weather non debugger wants to start debugging. - s = st-pr_statements; - goto restart; -//#endif -// break; - } -// PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent); -// PR_SwitchProgs((OPA->function & 0xff000000)>>24); - s = PR_EnterFunction (progfuncs, newf, p); - st = &pr_statements[s]; - - goto restart; -// break; - - case OP_DONE: - case OP_RETURN: - - RUNAWAYCHECK(); - - pr_globals[OFS_RETURN] = pr_globals[st->a]; - pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; - pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; -/* -{ - static char buffer[1024*1024*8]; - int size = sizeof buffer; - progfuncs->save_ents(progfuncs, buffer, &size, 0); -} -*/ - s = PR_LeaveFunction (progfuncs); - st = &pr_statements[s]; - if (pr_depth == prinst->exitdepth) - { - return; // all done - } - goto restart; -// break; - - case OP_STATE: - externs->stateop(progfuncs, OPA->_float, OPB->function); - break; - - case OP_ADD_I: - OPC->_int = OPA->_int + OPB->_int; - break; - case OP_ADD_FI: - OPC->_float = OPA->_float + (float)OPB->_int; - break; - case OP_ADD_IF: - OPC->_float = (float)OPA->_int + OPB->_float; - break; - - case OP_SUB_I: - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_SUB_FI: - OPC->_float = OPA->_float - (float)OPB->_int; - break; - case OP_SUB_IF: - OPC->_float = (float)OPA->_int - OPB->_float; - break; - - case OP_CONV_ITOF: - OPC->_float = (float)OPA->_int; - break; - case OP_CONV_FTOI: - OPC->_int = (int)OPA->_float; - break; - - case OP_CP_ITOF: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_float = (float)ptr->_int; - break; - - case OP_CP_FTOI: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_int = (int)ptr->_float; - break; - - case OP_BITAND_I: - OPC->_int = (OPA->_int & OPB->_int); - break; - - case OP_BITOR_I: - OPC->_int = (OPA->_int | OPB->_int); - break; - - case OP_MUL_I: - OPC->_int = OPA->_int * OPB->_int; - break; - case OP_DIV_I: - if (OPB->_int == 0) //no division by zero allowed... - OPC->_int = 0; - else - OPC->_int = OPA->_int / OPB->_int; - break; - case OP_EQ_I: - OPC->_int = (OPA->_int == OPB->_int); - break; - case OP_NE_I: - OPC->_int = (OPA->_int != OPB->_int); - break; - - - //array/structure reading/riting. - case OP_GLOBALADDRESS: - OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); - break; - case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors) - OPC->_int = OPA->_int + OPB->_int*4; - break; - - case OP_LOADA_I: - case OP_LOADA_F: - case OP_LOADA_FLD: - case OP_LOADA_ENT: - case OP_LOADA_S: - case OP_LOADA_FNC: - ptr = (eval_t *)(&OPA->_int + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADA_V: - ptr = (eval_t *)(&OPA->_int + OPB->_int); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - - - - case OP_ADD_SF: //(char*)c = (char*)a + (float)b - OPC->_int = OPA->_int + (int)OPB->_float; - break; - case OP_SUB_S: //(float)c = (char*)a - (char*)b - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_LOADP_C: //load character from a string - ptr = QCPOINTERM(OPA->_int + (int)OPB->_float); - OPC->_float = *(unsigned char *)ptr; - break; - case OP_LOADP_I: - case OP_LOADP_F: - case OP_LOADP_FLD: - case OP_LOADP_ENT: - case OP_LOADP_S: - case OP_LOADP_FNC: - ptr = QCPOINTERM(OPA->_int + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADP_V: - ptr = QCPOINTERM(OPA->_int + OPB->_int); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - - case OP_POWER_I: - OPC->_int = OPA->_int ^ OPB->_int; - break; - case OP_RSHIFT_I: - OPC->_int = OPA->_int >> OPB->_int; - break; - case OP_LSHIFT_I: - OPC->_int = OPA->_int << OPB->_int; - break; - - - case OP_FETCH_GBL_F: - case OP_FETCH_GBL_S: - case OP_FETCH_GBL_E: - case OP_FETCH_GBL_FNC: - i = (int)OPB->_float; - if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a + i]; - OPC->_int = t->_int; - break; - case OP_FETCH_GBL_V: - i = (int)OPB->_float; - if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a - +((int)OPB->_float)*3]; - OPC->_vector[0] = t->_vector[0]; - OPC->_vector[1] = t->_vector[1]; - OPC->_vector[2] = t->_vector[2]; - break; - - case OP_CSTATE: - externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_CWSTATE: - externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_THINKTIME: - externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float); - break; - - - case OP_BITSET: // b (+) a - OPB->_float = (float)((int)OPB->_float | (int)OPA->_float); - break; - case OP_BITSETP: // .b (+) a - ptr = QCPOINTER(OPB); - ptr->_float = (float)((int)ptr->_float | (int)OPA->_float); - break; - case OP_BITCLR: // b (-) a - OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float)); - break; - case OP_BITCLRP: // .b (-) a - ptr = QCPOINTER(OPB); - ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float)); - break; - - case OP_RAND0: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RAND1: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; - break; - case OP_RAND2: - if(OPA->_float < OPB->_float) - { - G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_float-OPA->_float)); - } - else - { - G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPA->_float-OPB->_float)); - } - break; - case OP_RANDV0: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RANDV1: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; - break; - case OP_RANDV2: - for(i = 0; i < 3; i++) - { - if(OPA->_vector[i] < OPB->_vector[i]) - { - G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_vector[i]-OPA->_vector[i])); - } - else - { - G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) - *(OPA->_vector[i]-OPB->_vector[i])); - } - } - break; - - - case OP_SWITCH_F: - case OP_SWITCH_V: - case OP_SWITCH_S: - case OP_SWITCH_E: - case OP_SWITCH_FNC: - swtch = OPA; - swtchtype = st->op; - RUNAWAYCHECK(); - st += (sofs)st->b - 1; // offset the st++ - break; - case OP_CASE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float == OPA->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_E: - case OP_SWITCH_FNC: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_S: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). - break; - if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_V: - if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2]) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype); - break; - } - break; - case OP_CASERANGE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->c-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype); - } - break; - - - - - - - - - - case OP_BITAND_IF: - OPC->_int = (OPA->_int & (int)OPB->_float); - break; - case OP_BITOR_IF: - OPC->_int = (OPA->_int | (int)OPB->_float); - break; - case OP_BITAND_FI: - OPC->_int = ((int)OPA->_float & OPB->_int); - break; - case OP_BITOR_FI: - OPC->_int = ((int)OPA->_float | OPB->_int); - break; - - case OP_MUL_IF: - OPC->_float = (OPA->_int * OPB->_float); - break; - case OP_MUL_FI: - OPC->_float = (OPA->_float * OPB->_int); - break; - - case OP_MUL_VI: - OPC->_vector[0] = OPA->_vector[0] * OPB->_int; - OPC->_vector[1] = OPA->_vector[0] * OPB->_int; - OPC->_vector[2] = OPA->_vector[0] * OPB->_int; - break; - case OP_MUL_IV: - OPC->_vector[0] = OPB->_int * OPA->_vector[0]; - OPC->_vector[1] = OPB->_int * OPA->_vector[1]; - OPC->_vector[2] = OPB->_int * OPA->_vector[2]; - break; - - case OP_DIV_IF: - OPC->_float = (OPA->_int / OPB->_float); - break; - case OP_DIV_FI: - OPC->_float = (OPA->_float / OPB->_int); - break; - - case OP_AND_I: - OPC->_int = (OPA->_int && OPB->_int); - break; - case OP_OR_I: - OPC->_int = (OPA->_int || OPB->_int); - break; - - case OP_AND_IF: - OPC->_int = (OPA->_int && OPB->_float); - break; - case OP_OR_IF: - OPC->_int = (OPA->_int || OPB->_float); - break; - - case OP_AND_FI: - OPC->_int = (OPA->_float && OPB->_int); - break; - case OP_OR_FI: - OPC->_int = (OPA->_float || OPB->_int); - break; - - case OP_NOT_I: - OPC->_int = !OPA->_int; - break; - - case OP_NE_IF: - OPC->_int = (OPA->_int != OPB->_float); - break; - case OP_NE_FI: - OPC->_int = (OPA->_float != OPB->_int); - break; - - case OP_GSTOREP_I: - case OP_GSTOREP_F: - case OP_GSTOREP_ENT: - case OP_GSTOREP_FLD: // integers - case OP_GSTOREP_S: - case OP_GSTOREP_FNC: // pointers - case OP_GSTOREP_V: - case OP_GADDRESS: - case OP_GLOAD_I: - case OP_GLOAD_F: - case OP_GLOAD_FLD: - case OP_GLOAD_ENT: - case OP_GLOAD_S: - case OP_GLOAD_FNC: - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Extra opcode not implemented\n"); - break; - - case OP_BOUNDCHECK: - if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b) - { - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int); - } - break; -/* case OP_PUSH: - OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]); - pr_spushed += OPA->_int; - if (pr_spushed + localstack_used >= LOCALSTACK_SIZE) - { - pr_spushed = 0; - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs pushed too much"); - } - break; - case OP_POP: - pr_spushed -= OPA->_int; - if (pr_spushed < 0) - { - pr_spushed = 0; - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs poped more than it pushed"); - } - break; -*/ - default: - if (st->op & 0x8000) //break point! - { - pr_xstatement = s = st-pr_statements; - - printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable); - if (pr_trace<1) - pr_trace=1; //this is what it's for - - s = ShowStep(progfuncs, s); - st = &pr_statements[s]; //let the user move execution - pr_xstatement = s = st-pr_statements; - -#if 0 //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement - memcpy(&fakeop, st, sizeof(dstatement_t)); //don't hit the new statement as a break point, cos it's probably the same one. - fakeop.op &= ~0x8000; - st = &fakeop; //a little remapping... -#else - st->op &= ~0x8000; //just remove the breakpoint and go around again, but this time in the debugger. -#endif - - goto reeval; //reexecute - } - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "Bad opcode %i", st->op); - } -} - - -#undef cont -#undef reeval -#undef st -#undef pr_statements -#undef fakeop -#undef dstatement_t -#undef sofs -#undef uofs - -#undef ENGINEPOINTER -#undef QCPOINTER -#undef QCPOINTERM - diff --git a/engine/qclib/execloop32d.h b/engine/qclib/execloop32d.h deleted file mode 100644 index fa511ece0..000000000 --- a/engine/qclib/execloop32d.h +++ /dev/null @@ -1,1071 +0,0 @@ -//qc execution code. -//we have two conditions. -//one allows us to debug and trace through our code, the other doesn't. - -//hopefully, the compiler will do a great job at optimising this code for us, where required. -//if it dosn't, then bum. - -//the general overhead should be reduced significantly, and I would be supprised if it did run slower. - -//run away loops are checked for ONLY on gotos and function calls. This might give a poorer check, but it will run faster overall. - -//Appears to work fine. - -#if INTSIZE == 16 -#define cont cont16 -#define reeval reeval16 -#define st st16 -#define pr_statements pr_statements16 -#define fakeop fakeop16 -#define dstatement_t dstatement16_t -#define sofs signed short -#define uofs unsigned short -#elif INTSIZE == 32 -#define cont cont32 -#define reeval reeval32 -#define st st32 -#define pr_statements pr_statements32 -#define fakeop fakeop32 -#define dstatement_t dstatement32_t -#define sofs signed int -#define uofs unsigned int -#elif INTSIZE == 24 -#error INTSIZE should be set to 32. -#else -#error Bad cont size -#endif - -#define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable) -#define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable) -#define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable) - -//rely upon just st -{ -#ifdef DEBUGABLE -cont: //last statement may have been a breakpoint - s = st-pr_statements; - s+=1; - s=ShowStep(progfuncs, s); - st = pr_statements + s; - -reeval: -#else - st++; -#endif - - switch (st->op) - { - case OP_ADD_F: - OPC->_float = OPA->_float + OPB->_float; - break; - case OP_ADD_V: - OPC->_vector[0] = OPA->_vector[0] + OPB->_vector[0]; - OPC->_vector[1] = OPA->_vector[1] + OPB->_vector[1]; - OPC->_vector[2] = OPA->_vector[2] + OPB->_vector[2]; - break; - - case OP_SUB_F: - OPC->_float = OPA->_float - OPB->_float; - break; - case OP_SUB_V: - OPC->_vector[0] = OPA->_vector[0] - OPB->_vector[0]; - OPC->_vector[1] = OPA->_vector[1] - OPB->_vector[1]; - OPC->_vector[2] = OPA->_vector[2] - OPB->_vector[2]; - break; - - case OP_MUL_F: - OPC->_float = OPA->_float * OPB->_float; - break; - case OP_MUL_V: - OPC->_float = OPA->_vector[0]*OPB->_vector[0] - + OPA->_vector[1]*OPB->_vector[1] - + OPA->_vector[2]*OPB->_vector[2]; - break; - case OP_MUL_FV: - OPC->_vector[0] = OPA->_float * OPB->_vector[0]; - OPC->_vector[1] = OPA->_float * OPB->_vector[1]; - OPC->_vector[2] = OPA->_float * OPB->_vector[2]; - break; - case OP_MUL_VF: - OPC->_vector[0] = OPB->_float * OPA->_vector[0]; - OPC->_vector[1] = OPB->_float * OPA->_vector[1]; - OPC->_vector[2] = OPB->_float * OPA->_vector[2]; - break; - - case OP_DIV_F: - OPC->_float = OPA->_float / OPB->_float; - break; - case OP_DIV_VF: - OPC->_vector[0] = OPB->_float / OPA->_vector[0]; - OPC->_vector[1] = OPB->_float / OPA->_vector[1]; - OPC->_vector[2] = OPB->_float / OPA->_vector[2]; - break; - - case OP_BITAND: - OPC->_float = (float)((int)OPA->_float & (int)OPB->_float); - break; - - case OP_BITOR: - OPC->_float = (float)((int)OPA->_float | (int)OPB->_float); - break; - - - case OP_GE: - OPC->_float = (float)(OPA->_float >= OPB->_float); - break; - case OP_GE_I: - OPC->_int = (int)(OPA->_int >= OPB->_int); - break; - case OP_GE_IF: - OPC->_float = (float)(OPA->_int >= OPB->_float); - break; - case OP_GE_FI: - OPC->_float = (float)(OPA->_float >= OPB->_int); - break; - - case OP_LE: - OPC->_float = (float)(OPA->_float <= OPB->_float); - break; - case OP_LE_I: - OPC->_int = (int)(OPA->_int <= OPB->_int); - break; - case OP_LE_IF: - OPC->_float = (float)(OPA->_int <= OPB->_float); - break; - case OP_LE_FI: - OPC->_float = (float)(OPA->_float <= OPB->_int); - break; - - case OP_GT: - OPC->_float = (float)(OPA->_float > OPB->_float); - break; - case OP_GT_I: - OPC->_int = (int)(OPA->_int > OPB->_int); - break; - case OP_GT_IF: - OPC->_float = (float)(OPA->_int > OPB->_float); - break; - case OP_GT_FI: - OPC->_float = (float)(OPA->_float > OPB->_int); - break; - - case OP_LT: - OPC->_float = (float)(OPA->_float < OPB->_float); - break; - case OP_LT_I: - OPC->_int = (int)(OPA->_int < OPB->_int); - break; - case OP_LT_IF: - OPC->_float = (float)(OPA->_int < OPB->_float); - break; - case OP_LT_FI: - OPC->_float = (float)(OPA->_float < OPB->_int); - break; - - case OP_AND: - OPC->_float = (float)(OPA->_float && OPB->_float); - break; - case OP_OR: - OPC->_float = (float)(OPA->_float || OPB->_float); - break; - - case OP_NOT_F: - OPC->_float = (float)(!OPA->_float); - break; - case OP_NOT_V: - OPC->_float = (float)(!OPA->_vector[0] && !OPA->_vector[1] && !OPA->_vector[2]); - break; - case OP_NOT_S: - OPC->_float = (float)(!(OPA->string) || !*PR_StringToNative(progfuncs, OPA->string)); - break; - case OP_NOT_FNC: - OPC->_float = (float)(!(OPA->function & ~0xff000000)); - break; - case OP_NOT_ENT: - OPC->_float = (float)(PROG_TO_EDICT(progfuncs, OPA->edict) == (edictrun_t *)sv_edicts); - break; - - case OP_EQ_F: - OPC->_float = (float)(OPA->_float == OPB->_float); - break; - case OP_EQ_IF: - OPC->_float = (float)(OPA->_int == OPB->_float); - break; - case OP_EQ_FI: - OPC->_float = (float)(OPA->_float == OPB->_int); - break; - - - case OP_EQ_V: - OPC->_float = (float)((OPA->_vector[0] == OPB->_vector[0]) && - (OPA->_vector[1] == OPB->_vector[1]) && - (OPA->_vector[2] == OPB->_vector[2])); - break; - case OP_EQ_S: - if (OPA->string==OPB->string) - OPC->_float = true; - else if (!OPA->string) - { - if (!OPB->string || !*PR_StringToNative(progfuncs, OPB->string)) - OPC->_float = true; - else - OPC->_float = false; - } - else if (!OPB->string) - { - if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) - OPC->_float = true; - else - OPC->_float = false; - } - else - OPC->_float = (float)(!strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); - break; - case OP_EQ_E: - OPC->_float = (float)(OPA->_int == OPB->_int); - break; - case OP_EQ_FNC: - OPC->_float = (float)(OPA->function == OPB->function); - break; - - - case OP_NE_F: - OPC->_float = (float)(OPA->_float != OPB->_float); - break; - case OP_NE_V: - OPC->_float = (float)((OPA->_vector[0] != OPB->_vector[0]) || - (OPA->_vector[1] != OPB->_vector[1]) || - (OPA->_vector[2] != OPB->_vector[2])); - break; - case OP_NE_S: - if (OPA->string==OPB->string) - OPC->_float = false; - else if (!OPA->string) - { - if (!OPB->string || !*(PR_StringToNative(progfuncs, OPB->string))) - OPC->_float = false; - else - OPC->_float = true; - } - else if (!OPB->string) - { - if (!OPA->string || !*PR_StringToNative(progfuncs, OPA->string)) - OPC->_float = false; - else - OPC->_float = true; - } - else - OPC->_float = (float)(strcmp(PR_StringToNative(progfuncs, OPA->string),PR_StringToNative(progfuncs, OPB->string))); - break; - case OP_NE_E: - OPC->_float = (float)(OPA->_int != OPB->_int); - break; - case OP_NE_FNC: - OPC->_float = (float)(OPA->function != OPB->function); - break; - -//================== - case OP_STORE_IF: - OPB->_float = (float)OPA->_int; - break; - case OP_STORE_FI: - OPB->_int = (int)OPA->_float; - break; - case OP_STORE_I: - OPB->_int = OPA->_int; - break; - case OP_STORE_F: - case OP_STORE_ENT: - case OP_STORE_FLD: // integers - case OP_STORE_S: - case OP_STORE_FNC: // pointers - OPB->_int = OPA->_int; - break; - case OP_STORE_V: - OPB->_vector[0] = OPA->_vector[0]; - OPB->_vector[1] = OPA->_vector[1]; - OPB->_vector[2] = OPA->_vector[2]; - break; - - //store a value to a pointer - case OP_STOREP_IF: - ptr = QCPOINTER(OPB); - ptr->_float = (float)OPA->_int; - break; - case OP_STOREP_FI: - ptr = QCPOINTER(OPB); - ptr->_int = (int)OPA->_float; - break; - case OP_STOREP_I: - ptr = QCPOINTER(OPB); - ptr->_int = OPA->_int; - break; - case OP_STOREP_F: - case OP_STOREP_ENT: - case OP_STOREP_FLD: // integers - case OP_STOREP_S: - case OP_STOREP_FNC: // pointers - ptr = QCPOINTER(OPB); - ptr->_int = OPA->_int; - break; - case OP_STOREP_V: - ptr = QCPOINTER(OPB); - ptr->_vector[0] = OPA->_vector[0]; - ptr->_vector[1] = OPA->_vector[1]; - ptr->_vector[2] = OPA->_vector[2]; - break; - - case OP_STOREP_C: //store character in a string - ptr = QCPOINTER(OPB); - *(unsigned char *)ptr = (char)OPA->_float; - break; - - case OP_MULSTORE_F: // f *= f - OPB->_float *= OPA->_float; - break; - case OP_MULSTORE_V: // v *= f - OPB->_vector[0] *= OPA->_float; - OPB->_vector[1] *= OPA->_float; - OPB->_vector[2] *= OPA->_float; - break; - case OP_MULSTOREP_F: // e.f *= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float *= OPA->_float); - break; - case OP_MULSTOREP_V: // e.v *= f - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] *= OPA->_float); - OPC->_vector[0] = (ptr->_vector[1] *= OPA->_float); - OPC->_vector[0] = (ptr->_vector[2] *= OPA->_float); - break; - - case OP_DIVSTORE_F: // f /= f - OPB->_float /= OPA->_float; - break; - case OP_DIVSTOREP_F: // e.f /= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float /= OPA->_float); - break; - - case OP_ADDSTORE_F: // f += f - OPB->_float += OPA->_float; - break; - case OP_ADDSTORE_V: // v += v - OPB->_vector[0] += OPA->_vector[0]; - OPB->_vector[1] += OPA->_vector[1]; - OPB->_vector[2] += OPA->_vector[2]; - break; - case OP_ADDSTOREP_F: // e.f += f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float += OPA->_float); - break; - case OP_ADDSTOREP_V: // e.v += v - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] += OPA->_vector[0]); - OPC->_vector[1] = (ptr->_vector[1] += OPA->_vector[1]); - OPC->_vector[2] = (ptr->_vector[2] += OPA->_vector[2]); - break; - - case OP_SUBSTORE_F: // f -= f - OPB->_float -= OPA->_float; - break; - case OP_SUBSTORE_V: // v -= v - OPB->_vector[0] -= OPA->_vector[0]; - OPB->_vector[1] -= OPA->_vector[1]; - OPB->_vector[2] -= OPA->_vector[2]; - break; - case OP_SUBSTOREP_F: // e.f -= f - ptr = QCPOINTER(OPB); - OPC->_float = (ptr->_float -= OPA->_float); - break; - case OP_SUBSTOREP_V: // e.v -= v - ptr = QCPOINTER(OPB); - OPC->_vector[0] = (ptr->_vector[0] -= OPA->_vector[0]); - OPC->_vector[1] = (ptr->_vector[1] -= OPA->_vector[1]); - OPC->_vector[2] = (ptr->_vector[2] -= OPA->_vector[2]); - break; - - - //get a pointer to a field var - case OP_ADDRESS: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_ADDRESS references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - if (!ed || ed->readonly) - { - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "assignment to read-only entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - } - -//Whilst the next block would technically be correct, we don't use it as it breaks too many quake mods. -// if (ed->isfree) -// { -// pr_xstatement = st-pr_statements; -// PR_RunError (progfuncs, "assignment to free entitiy in %s", progfuncs->stringtable + pr_xfunction->s_name); -// } - OPC->_int = ENGINEPOINTER((((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust)); - break; - - //load a field to a value - case OP_LOAD_I: - case OP_LOAD_F: - case OP_LOAD_FLD: - case OP_LOAD_ENT: - case OP_LOAD_S: - case OP_LOAD_FNC: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust); - OPC->_int = ptr->_int; - break; - - case OP_LOAD_V: - if ((unsigned)OPA->edict >= (unsigned)maxedicts) - PR_RunError (progfuncs, "OP_LOAD_V references invalid entity in %s", progfuncs->stringtable + pr_xfunction->s_name); - ed = PROG_TO_EDICT(progfuncs, OPA->edict); -#ifdef PARANOID - NUM_FOR_EDICT(ed); // make sure it's in range -#endif - ptr = (eval_t *)(((int *)edvars(ed)) + OPB->_int + progfuncs->fieldadjust); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - -//================== - - case OP_IFNOTS: - RUNAWAYCHECK(); - if (!OPA->string || !PR_StringToNative(progfuncs, OPA->string)) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFNOT: - RUNAWAYCHECK(); - if (!OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IFS: - RUNAWAYCHECK(); - if (OPA->string && PR_StringToNative(progfuncs, OPA->string)) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_IF: - RUNAWAYCHECK(); - if (OPA->_int) - st += (sofs)st->b - 1; // offset the s++ - break; - - case OP_GOTO: - RUNAWAYCHECK(); - st += (sofs)st->a - 1; // offset the s++ - break; - - case OP_CALL8H: - case OP_CALL7H: - case OP_CALL6H: - case OP_CALL5H: - case OP_CALL4H: - case OP_CALL3H: - case OP_CALL2H: - G_VECTOR(OFS_PARM1)[0] = OPC->_vector[0]; - G_VECTOR(OFS_PARM1)[1] = OPC->_vector[1]; - G_VECTOR(OFS_PARM1)[2] = OPC->_vector[2]; - case OP_CALL1H: - G_VECTOR(OFS_PARM0)[0] = OPB->_vector[0]; - G_VECTOR(OFS_PARM0)[1] = OPB->_vector[1]; - G_VECTOR(OFS_PARM0)[2] = OPB->_vector[2]; - - case OP_CALL8: - case OP_CALL7: - case OP_CALL6: - case OP_CALL5: - case OP_CALL4: - case OP_CALL3: - case OP_CALL2: - case OP_CALL1: - case OP_CALL0: - RUNAWAYCHECK(); - pr_xstatement = st-pr_statements; - - - if (st->op > OP_CALL8) - pr_argc = st->op - (OP_CALL1H-1); - else - pr_argc = st->op - OP_CALL0; - fnum = OPA->function; - if ((fnum & ~0xff000000)==0) - { - pr_trace++; - printf("NULL function from qc (%s).\n", progfuncs->stringtable + pr_xfunction->s_name); -#ifndef DEBUGABLE - goto cont; -#endif - break; - } -/* -{ - static char buffer[1024*1024*8]; - int size = sizeof buffer; - progfuncs->save_ents(progfuncs, buffer, &size, 0); -}*/ - - - p=pr_typecurrent; -//about to switch. needs caching. - - //if it's an external call, switch now (before any function pointers are used) - PR_MoveParms(progfuncs, (fnum & 0xff000000)>>24, p); - PR_SwitchProgs(progfuncs, (fnum & 0xff000000)>>24); - - newf = &pr_functions[fnum & ~0xff000000]; - - if (newf->first_statement < 0) - { // negative statements are built in functions - -if (pr_typecurrent != 0) -{ - PR_MoveParms(progfuncs, 0, pr_typecurrent); - PR_SwitchProgs(progfuncs, 0); -} - i = -newf->first_statement; -// p = pr_typecurrent; - progfuncs->lastcalledbuiltinnumber = i; - if (i < externs->numglobalbuiltins) - { - prinst->numtempstringsstack = prinst->numtempstrings; - (*externs->globalbuiltins[i]) (progfuncs, (struct globalvars_s *)current_progstate->globals); - if (prinst->continuestatement!=-1) - { - st=&pr_statements[prinst->continuestatement]; - prinst->continuestatement=-1; - break; - } - } - else - { - i -= externs->numglobalbuiltins; - if (i >= current_progstate->numbuiltins) - { -// if (newf->first_statement == -0x7fffffff) -// ((builtin_t)newf->profile) (progfuncs, (struct globalvars_s *)current_progstate->globals); -// else - PR_RunError (progfuncs, "Bad builtin call number - %i", -newf->first_statement); - } - else - current_progstate->builtins [i] (progfuncs, (struct globalvars_s *)current_progstate->globals); - } - PR_MoveParms(progfuncs, p, pr_typecurrent); -// memcpy(&pr_progstate[p].globals[OFS_RETURN], ¤t_progstate->globals[OFS_RETURN], sizeof(vec3_t)); - PR_SwitchProgs(progfuncs, (progsnum_t)p); - -//#ifndef DEBUGABLE //decide weather non debugger wants to start debugging. - s = st-pr_statements; - goto restart; -//#endif -// break; - } -// PR_MoveParms((OPA->function & 0xff000000)>>24, pr_typecurrent); -// PR_SwitchProgs((OPA->function & 0xff000000)>>24); - s = PR_EnterFunction (progfuncs, newf, p); - st = &pr_statements[s]; - - goto restart; -// break; - - case OP_DONE: - case OP_RETURN: - - RUNAWAYCHECK(); - - pr_globals[OFS_RETURN] = pr_globals[st->a]; - pr_globals[OFS_RETURN+1] = pr_globals[st->a+1]; - pr_globals[OFS_RETURN+2] = pr_globals[st->a+2]; -/* -{ - static char buffer[1024*1024*8]; - int size = sizeof buffer; - progfuncs->save_ents(progfuncs, buffer, &size, 0); -} -*/ - s = PR_LeaveFunction (progfuncs); - st = &pr_statements[s]; - if (pr_depth == prinst->exitdepth) - { - return; // all done - } - goto restart; -// break; - - case OP_STATE: - externs->stateop(progfuncs, OPA->_float, OPB->function); - break; - - case OP_ADD_I: - OPC->_int = OPA->_int + OPB->_int; - break; - case OP_ADD_FI: - OPC->_float = OPA->_float + (float)OPB->_int; - break; - case OP_ADD_IF: - OPC->_float = (float)OPA->_int + OPB->_float; - break; - - case OP_SUB_I: - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_SUB_FI: - OPC->_float = OPA->_float - (float)OPB->_int; - break; - case OP_SUB_IF: - OPC->_float = (float)OPA->_int - OPB->_float; - break; - - case OP_CONV_ITOF: - OPC->_float = (float)OPA->_int; - break; - case OP_CONV_FTOI: - OPC->_int = (int)OPA->_float; - break; - - case OP_CP_ITOF: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_float = (float)ptr->_int; - break; - - case OP_CP_FTOI: - ptr = (eval_t *)(((qbyte *)sv_edicts) + OPA->_int); - OPC->_int = (int)ptr->_float; - break; - - case OP_BITAND_I: - OPC->_int = (OPA->_int & OPB->_int); - break; - - case OP_BITOR_I: - OPC->_int = (OPA->_int | OPB->_int); - break; - - case OP_MUL_I: - OPC->_int = OPA->_int * OPB->_int; - break; - case OP_DIV_I: - if (OPB->_int == 0) //no division by zero allowed... - OPC->_int = 0; - else - OPC->_int = OPA->_int / OPB->_int; - break; - case OP_EQ_I: - OPC->_int = (OPA->_int == OPB->_int); - break; - case OP_NE_I: - OPC->_int = (OPA->_int != OPB->_int); - break; - - - //array/structure reading/riting. - case OP_GLOBALADDRESS: - OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); - break; - case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors) - OPC->_int = OPA->_int + OPB->_int*4; - break; - - case OP_LOADA_I: - case OP_LOADA_F: - case OP_LOADA_FLD: - case OP_LOADA_ENT: - case OP_LOADA_S: - case OP_LOADA_FNC: - ptr = (eval_t *)(&OPA->_int + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADA_V: - ptr = (eval_t *)(&OPA->_int + OPB->_int); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - - - - case OP_ADD_SF: //(char*)c = (char*)a + (float)b - OPC->_int = OPA->_int + (int)OPB->_float; - break; - case OP_SUB_S: //(float)c = (char*)a - (char*)b - OPC->_int = OPA->_int - OPB->_int; - break; - case OP_LOADP_C: //load character from a string - ptr = QCPOINTERM(OPA->_int + (int)OPB->_float); - OPC->_float = *(unsigned char *)ptr; - break; - case OP_LOADP_I: - case OP_LOADP_F: - case OP_LOADP_FLD: - case OP_LOADP_ENT: - case OP_LOADP_S: - case OP_LOADP_FNC: - ptr = QCPOINTERM(OPA->_int + OPB->_int); - OPC->_int = ptr->_int; - break; - - case OP_LOADP_V: - ptr = QCPOINTERM(OPA->_int + OPB->_int); - OPC->_vector[0] = ptr->_vector[0]; - OPC->_vector[1] = ptr->_vector[1]; - OPC->_vector[2] = ptr->_vector[2]; - break; - - case OP_POWER_I: - OPC->_int = OPA->_int ^ OPB->_int; - break; - case OP_RSHIFT_I: - OPC->_int = OPA->_int >> OPB->_int; - break; - case OP_LSHIFT_I: - OPC->_int = OPA->_int << OPB->_int; - break; - - - case OP_FETCH_GBL_F: - case OP_FETCH_GBL_S: - case OP_FETCH_GBL_E: - case OP_FETCH_GBL_FNC: - i = (int)OPB->_float; - if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a + i]; - OPC->_int = t->_int; - break; - case OP_FETCH_GBL_V: - i = (int)OPB->_float; - if(i < 0 || i > ((eval_t *)&glob[st->a-1])->_int) - { - PR_RunError(progfuncs, "array index out of bounds: %s[%d]", PR_GlobalStringNoContents(progfuncs, st->a), i); - } - t = (eval_t *)&pr_globals[(uofs)st->a - +((int)OPB->_float)*3]; - OPC->_vector[0] = t->_vector[0]; - OPC->_vector[1] = t->_vector[1]; - OPC->_vector[2] = t->_vector[2]; - break; - - case OP_CSTATE: - externs->cstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_CWSTATE: - externs->cwstateop(progfuncs, OPA->_float, OPB->_float, fnum); - break; - - case OP_THINKTIME: - externs->thinktimeop(progfuncs, (struct edict_s *)PROG_TO_EDICT(progfuncs, OPA->edict), OPB->_float); - break; - - - case OP_BITSET: // b (+) a - OPB->_float = (float)((int)OPB->_float | (int)OPA->_float); - break; - case OP_BITSETP: // .b (+) a - ptr = QCPOINTER(OPB); - ptr->_float = (float)((int)ptr->_float | (int)OPA->_float); - break; - case OP_BITCLR: // b (-) a - OPB->_float = (float)((int)OPB->_float & ~((int)OPA->_float)); - break; - case OP_BITCLRP: // .b (-) a - ptr = QCPOINTER(OPB); - ptr->_float = (float)((int)ptr->_float & ~((int)OPA->_float)); - break; - - case OP_RAND0: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RAND1: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; - break; - case OP_RAND2: - if(OPA->_float < OPB->_float) - { - G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_float-OPA->_float)); - } - else - { - G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff) - *(OPA->_float-OPB->_float)); - } - break; - case OP_RANDV0: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff); - break; - case OP_RANDV1: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; - break; - case OP_RANDV2: - for(i = 0; i < 3; i++) - { - if(OPA->_vector[i] < OPB->_vector[i]) - { - G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) - *(OPB->_vector[i]-OPA->_vector[i])); - } - else - { - G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) - *(OPA->_vector[i]-OPB->_vector[i])); - } - } - break; - - - case OP_SWITCH_F: - case OP_SWITCH_V: - case OP_SWITCH_S: - case OP_SWITCH_E: - case OP_SWITCH_FNC: - swtch = OPA; - swtchtype = st->op; - RUNAWAYCHECK(); - st += (sofs)st->b - 1; // offset the st++ - break; - case OP_CASE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float == OPA->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_E: - case OP_SWITCH_FNC: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_S: - if (swtch->_int == OPA->_int) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - if ((!swtch->_int && PR_StringToNative(progfuncs, OPA->string)) || (!OPA->_int && PR_StringToNative(progfuncs, swtch->string))) //one is null (cannot be not both). - break; - if (!strcmp(PR_StringToNative(progfuncs, swtch->string), PR_StringToNative(progfuncs, OPA->string))) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - case OP_SWITCH_V: - if (swtch->_vector[0] == OPA->_vector[0] && swtch->_vector[1] == OPA->_vector[1] && swtch->_vector[2] == OPA->_vector[2]) - { - RUNAWAYCHECK(); - st += (sofs)st->b-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASE with bad/missing OP_SWITCH %i", swtchtype); - break; - } - break; - case OP_CASERANGE: - switch(swtchtype) - { - case OP_SWITCH_F: - if (swtch->_float >= OPA->_float && swtch->_float <= OPB->_float) - { - RUNAWAYCHECK(); - st += (sofs)st->c-1; // -1 to offset the s++ - } - break; - default: - PR_RunError (progfuncs, "OP_CASERANGE with bad/missing OP_SWITCH %i", swtchtype); - } - break; - - - - - - - - - - case OP_BITAND_IF: - OPC->_int = (OPA->_int & (int)OPB->_float); - break; - case OP_BITOR_IF: - OPC->_int = (OPA->_int | (int)OPB->_float); - break; - case OP_BITAND_FI: - OPC->_int = ((int)OPA->_float & OPB->_int); - break; - case OP_BITOR_FI: - OPC->_int = ((int)OPA->_float | OPB->_int); - break; - - case OP_MUL_IF: - OPC->_float = (OPA->_int * OPB->_float); - break; - case OP_MUL_FI: - OPC->_float = (OPA->_float * OPB->_int); - break; - - case OP_MUL_VI: - OPC->_vector[0] = OPA->_vector[0] * OPB->_int; - OPC->_vector[1] = OPA->_vector[0] * OPB->_int; - OPC->_vector[2] = OPA->_vector[0] * OPB->_int; - break; - case OP_MUL_IV: - OPC->_vector[0] = OPB->_int * OPA->_vector[0]; - OPC->_vector[1] = OPB->_int * OPA->_vector[1]; - OPC->_vector[2] = OPB->_int * OPA->_vector[2]; - break; - - case OP_DIV_IF: - OPC->_float = (OPA->_int / OPB->_float); - break; - case OP_DIV_FI: - OPC->_float = (OPA->_float / OPB->_int); - break; - - case OP_AND_I: - OPC->_int = (OPA->_int && OPB->_int); - break; - case OP_OR_I: - OPC->_int = (OPA->_int || OPB->_int); - break; - - case OP_AND_IF: - OPC->_int = (OPA->_int && OPB->_float); - break; - case OP_OR_IF: - OPC->_int = (OPA->_int || OPB->_float); - break; - - case OP_AND_FI: - OPC->_int = (OPA->_float && OPB->_int); - break; - case OP_OR_FI: - OPC->_int = (OPA->_float || OPB->_int); - break; - - case OP_NOT_I: - OPC->_int = !OPA->_int; - break; - - case OP_NE_IF: - OPC->_int = (OPA->_int != OPB->_float); - break; - case OP_NE_FI: - OPC->_int = (OPA->_float != OPB->_int); - break; - - case OP_GSTOREP_I: - case OP_GSTOREP_F: - case OP_GSTOREP_ENT: - case OP_GSTOREP_FLD: // integers - case OP_GSTOREP_S: - case OP_GSTOREP_FNC: // pointers - case OP_GSTOREP_V: - case OP_GADDRESS: - case OP_GLOAD_I: - case OP_GLOAD_F: - case OP_GLOAD_FLD: - case OP_GLOAD_ENT: - case OP_GLOAD_S: - case OP_GLOAD_FNC: - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Extra opcode not implemented\n"); - break; - - case OP_BOUNDCHECK: - if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b) - { - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int); - } - break; -/* case OP_PUSH: - OPC->_int = ENGINEPOINTER(&localstack[localstack_used+pr_spushed]); - pr_spushed += OPA->_int; - if (pr_spushed + localstack_used >= LOCALSTACK_SIZE) - { - pr_spushed = 0; - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs pushed too much"); - } - break; - case OP_POP: - pr_spushed -= OPA->_int; - if (pr_spushed < 0) - { - pr_spushed = 0; - pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs poped more than it pushed"); - } - break; -*/ - default: - if (st->op & 0x8000) //break point! - { - pr_xstatement = s = st-pr_statements; - - printf("Break point hit in %s.\n", pr_xfunction->s_name+progfuncs->stringtable); - if (pr_trace<1) - pr_trace=1; //this is what it's for - - s = ShowStep(progfuncs, s); - st = &pr_statements[s]; //let the user move execution - pr_xstatement = s = st-pr_statements; - -#if 0 //fakeop stuff - not practical, the rest of the code is more optimised, st needs to point at the correct statement - memcpy(&fakeop, st, sizeof(dstatement_t)); //don't hit the new statement as a break point, cos it's probably the same one. - fakeop.op &= ~0x8000; - st = &fakeop; //a little remapping... -#else - st->op &= ~0x8000; //just remove the breakpoint and go around again, but this time in the debugger. -#endif - - goto reeval; //reexecute - } - pr_xstatement = st-pr_statements; - PR_RunError (progfuncs, "Bad opcode %i", st->op); - } -} - - -#undef cont -#undef reeval -#undef st -#undef pr_statements -#undef fakeop -#undef dstatement_t -#undef sofs -#undef uofs - -#undef ENGINEPOINTER -#undef QCPOINTER -#undef QCPOINTERM - diff --git a/engine/qclib/initlib.c b/engine/qclib/initlib.c index 200658598..d12c02975 100644 --- a/engine/qclib/initlib.c +++ b/engine/qclib/initlib.c @@ -345,7 +345,10 @@ eval_t *GetEdictFieldValue(progfuncs_t *progfuncs, struct edict_s *ed, char *nam struct edict_s *ProgsToEdict (progfuncs_t *progfuncs, int progs) { if ((unsigned)progs >= (unsigned)maxedicts) + { + printf("Bad entity index %i\n", progs); progs = 0; + } return (struct edict_s *)PROG_TO_EDICT(progfuncs, progs); } int EdictToProgs (progfuncs_t *progfuncs, struct edict_s *ed) diff --git a/engine/qclib/pr_comp.h b/engine/qclib/pr_comp.h index 09aad2929..a472ba2b3 100644 --- a/engine/qclib/pr_comp.h +++ b/engine/qclib/pr_comp.h @@ -214,7 +214,7 @@ enum { OP_DIV_VF, - OP_POWER_I, + OP_XOR_I, OP_RSHIFT_I, OP_LSHIFT_I, @@ -311,6 +311,42 @@ enum { OP_SWITCH_I,//hmm. OP_GLOAD_V, + OP_NUMREALOPS, + + /* + These ops are emulated out, always, and are only present in the compiler. + */ + + OP_BITSET_I, + OP_BITSETP_I, + + OP_MULSTORE_I, + OP_DIVSTORE_I, + OP_ADDSTORE_I, + OP_SUBSTORE_I, + OP_MULSTOREP_I, + OP_DIVSTOREP_I, + OP_ADDSTOREP_I, + OP_SUBSTOREP_I, + + OP_MULSTORE_IF, + OP_MULSTOREP_IF, + OP_DIVSTORE_IF, + OP_DIVSTOREP_IF, + OP_ADDSTORE_IF, + OP_ADDSTOREP_IF, + OP_SUBSTORE_IF, + OP_SUBSTOREP_IF, + + OP_MULSTORE_FI, + OP_MULSTOREP_FI, + OP_DIVSTORE_FI, + OP_DIVSTOREP_FI, + OP_ADDSTORE_FI, + OP_ADDSTOREP_FI, + OP_SUBSTORE_FI, + OP_SUBSTOREP_FI, + OP_NUMOPS }; diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index 0ef7a3871..81cd006c4 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -607,19 +607,53 @@ char *PR_UglyValueString (progfuncs_t *progfuncs, etype_t type, eval_t *val) sprintf (line, "unions cannot yet be saved"); break; case ev_string: - _snprintf (line, sizeof(line), "%s", PR_StringToNative(progfuncs, val->string)); + { + char *outs = line; + int outb = sizeof(line)-2; + char *ins = PR_StringToNative(progfuncs, val->string); + //markup the output string. + while(*ins && outb > 0) + { + switch(*ins) + { + case '\n': + *outs++ = '\\'; + *outs++ = 'n'; + ins++; + outb-=2; + break; + case '\"': + *outs++ = '\\'; + *outs++ = '"'; + ins++; + outb-=2; + break; + case '\\': + *outs++ = '\\'; + *outs++ = '\\'; + ins++; + outb-=2; + break; + default: + *outs++ = *ins++; + outb--; + break; + } + } + *outs = 0; + } break; case ev_entity: sprintf (line, "%i", val->_int); break; case ev_function: i = (val->function & 0xff000000)>>24; //progs number - if ((unsigned)i > maxprogs || !pr_progstate[(unsigned)i].progs) + if ((unsigned)i >= maxprogs || !pr_progstate[(unsigned)i].progs) sprintf (line, "BAD FUNCTION INDEX: %i", val->function); else { j = (val->function & ~0xff000000); //function number - if ((unsigned)j > pr_progstate[(unsigned)i].progs->numfunctions) + if ((unsigned)j >= pr_progstate[(unsigned)i].progs->numfunctions) sprintf(line, "%i:%s", i, "CORRUPT FUNCTION POINTER"); else { @@ -1143,9 +1177,13 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) if (qcc_token[0] == '}') break; if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); + { + printf ("ED_ParseEntity: EOF without closing brace"); + return NULL; + } - strcpy (keyname, qcc_token); + strncpy (keyname, qcc_token, sizeof(keyname)-1); + keyname[sizeof(keyname)-1] = 0; // another hack to fix heynames with trailing spaces n = strlen(keyname); @@ -1158,10 +1196,16 @@ char *ED_ParseEdict (progfuncs_t *progfuncs, char *data, edictrun_t *ent) // parse value data = QCC_COM_Parse (data); if (!data) - Sys_Error ("ED_ParseEntity: EOF without closing brace"); + { + printf ("ED_ParseEntity: EOF without closing brace"); + return NULL; + } if (qcc_token[0] == '}') - Sys_Error ("ED_ParseEntity: closing brace without data"); + { + printf ("ED_ParseEntity: closing brace without data"); + return NULL; + } init = true; diff --git a/engine/qclib/pr_exec.c b/engine/qclib/pr_exec.c index f7bafe30e..1262def8a 100644 --- a/engine/qclib/pr_exec.c +++ b/engine/qclib/pr_exec.c @@ -866,7 +866,11 @@ restart: //jumped to when the progs might have changed. while (pr_trace) { #define DEBUGABLE - #include "execloop16d.h" + #ifdef SEPARATEINCLUDES + #include "execloop16d.h" + #else + #include "execloop.h" + #endif #undef DEBUGABLE } @@ -884,13 +888,21 @@ restart: //jumped to when the progs might have changed. while (pr_trace) { #define DEBUGABLE - #include "execloop32d.h" + #ifdef SEPARATEINCLUDES + #include "execloop32d.h" + #else + #include "execloop.h" + #endif #undef DEBUGABLE } while(1) { - #include "execloop32.h" + #ifdef SEPARATEINCLUDES + #include "execloop32.h" + #else + #include "execloop.h" + #endif } #undef INTSIZE Sys_Error("PR_ExecuteProgram - should be unreachable"); diff --git a/engine/qclib/qcc.dsp b/engine/qclib/qcc.dsp index 4df54f56c..0c4be3df5 100644 --- a/engine/qclib/qcc.dsp +++ b/engine/qclib/qcc.dsp @@ -222,6 +222,10 @@ SOURCE=.\gui.h # End Source File # Begin Source File +SOURCE=.\pr_comp.h +# End Source File +# Begin Source File + SOURCE=.\qcc.h # End Source File # End Group diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index f2a0c57a1..4a89c2a2d 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -66,7 +66,7 @@ extern int MAX_CONSTANTS; #define MAXCONSTANTLENGTH 64 #define MAXCONSTANTVALUELENGTH 1024 #define MAXCONSTANTPARAMLENGTH 32 -#define MAXCONSTANTPARAMS 8 +#define MAXCONSTANTPARAMS 32 typedef enum {QCF_STANDARD, QCF_HEXEN2, QCF_DARKPLACES, QCF_FTE, QCF_FTEDEBUG, QCF_KK7} qcc_targetformat_t; extern qcc_targetformat_t qcc_targetformat; @@ -567,6 +567,7 @@ enum { WARN_ASSIGNMENTTOCONSTANTFUNC, WARN_MISSINGRETURNVALUE, WARN_WRONGRETURNTYPE, + WARN_CORRECTEDRETURNTYPE, WARN_POINTLESSSTATEMENT, WARN_MISSINGRETURN, WARN_DUPLICATEDEFINITION, diff --git a/engine/qclib/qcc_cmdlib.c b/engine/qclib/qcc_cmdlib.c index 42f1f7d84..186196394 100644 --- a/engine/qclib/qcc_cmdlib.c +++ b/engine/qclib/qcc_cmdlib.c @@ -240,7 +240,16 @@ skipwhite: do { c = *data++; - if (c=='\"'||c=='\0') + if (c=='\\' && *data == '\"') + c = *data++; //allow C-style string escapes + else if (c=='\\' && *data == '\\') + c = *data++; // \ is now a special character so it needs to be marked up using itself + else if (c=='\\' && *data == 'n') + { // and do new lines while we're at it. + c = '\n'; + data++; + } + else if (c=='\"'||c=='\0') { qcc_token[len] = 0; return data; @@ -266,7 +275,7 @@ skipwhite: data++; len++; c = *data; - if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c=='\"' || c==',') + if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':' || c=='\"' || c==',') break; } while (c>32); @@ -314,11 +323,16 @@ skipwhite: do { c = *data++; - if (c=='\"'||c=='\0') - { - qcc_token[len] = 0; - return data; + if (c=='\\' && *data == '\"') + c = *data++; //allow C-style string escapes + else if (c=='\\' && *data == '\\') + c = *data++; // \ is now a special character so it needs to be marked up using itself + else if (c=='\\' && *data == 'n') + { // and do new lines while we're at it. + c = '\n'; + data++; } + else if (c=='\"'||c=='\0') qcc_token[len] = c; len++; } while (1); @@ -440,6 +454,7 @@ For abnormal program terminations */ void VARGS QCC_Error (int errortype, const char *error, ...) { + extern int numsourcefiles; va_list argptr; char msg[2048]; @@ -452,6 +467,8 @@ void VARGS QCC_Error (int errortype, const char *error, ...) editbadfile(strings+s_file, pr_source_line); + numsourcefiles = 0; + #ifndef QCC longjmp(qcccompileerror, 1); #else diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index 27bf1f90d..b57387eec 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -134,6 +134,7 @@ QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto); void QCC_PR_ParseState (void); pbool simplestore; +pbool expandedemptymacro; QCC_pr_info_t pr; //QCC_def_t **pr_global_defs/*[MAX_REGS]*/; // to find def for a global variable @@ -318,8 +319,8 @@ QCC_opcode_t pr_opcodes[] = {7, "|=", "BITSET_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, {7, "|=", "BITSETP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, - {7, "(-)", "BITCLR_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, - {7, "(-)", "BITCLRP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, + {7, "&~=", "BITCLR_F", 6, ASSOC_RIGHT, &type_float, &type_float, &type_float}, + {7, "&~=", "BITCLRP_F", 6, ASSOC_RIGHT, &type_pointer, &type_float, &type_float}, {7, "", "RAND0", -1, ASSOC_LEFT, &type_void, &type_void, &type_float}, {7, "", "RAND1", -1, ASSOC_LEFT, &type_float, &type_void, &type_float}, @@ -386,7 +387,7 @@ QCC_opcode_t pr_opcodes[] = {7, "/", "DIV_VF", 3, ASSOC_LEFT, &type_vector, &type_float, &type_float}, - {7, "^", "POWER_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, + {7, "^", "XOR_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, {7, ">>", "RSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, {7, "<<", "LSHIFT_I", 3, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, @@ -474,7 +475,7 @@ QCC_opcode_t pr_opcodes[] = {7, "<>", "GSTOREP_ENT", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "<>", "GSTOREP_FLD", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "<>", "GSTOREP_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, -{7, "<>", "GSTORE_PFNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, +{7, "<>", "GSTOREP_FNC", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "<>", "GSTOREP_V", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, {7, "<>", "GADDRESS", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, @@ -492,16 +493,44 @@ QCC_opcode_t pr_opcodes[] = {7, "", "PUSH", -1, ASSOC_RIGHT, &type_float, &type_void, &type_pointer}, {7, "", "POP", -1, ASSOC_RIGHT, &type_float, &type_void, &type_void}, +{7, "", "SWITCH_I", -1, ASSOC_LEFT, &type_void, NULL, &type_void}, +{7, "<>", "GLOAD_S", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, + +/* emulated ops begin here */ + {7, "<>", "OP_EMULATED", -1, ASSOC_LEFT, &type_float, &type_float, &type_float}, + + {7, "|=", "BITSET_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer}, {7, "|=", "BITSETP_I", 6, ASSOC_RIGHT, &type_pointer, &type_integer, &type_integer}, + + {7, "*=", "MULSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "*=", "MULSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector}, {7, "/=", "DIVSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "/=", "DIVSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_vector}, {7, "+=", "ADDSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, {7, "-=", "SUBSTORE_I", 6, ASSOC_RIGHT_RESULT, &type_integer, &type_integer, &type_integer}, - {7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_vector, &type_vector}, + + {7, "*=", "MULSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, + {7, "/=", "DIVSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, + {7, "+=", "ADDSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, + {7, "-=", "SUBSTOREP_I", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_integer}, + + {7, "*=", "OP_MULSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "*=", "OP_MULSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "/=", "OP_DIVSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "/=", "OP_DIVSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "+=", "OP_ADDSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "+=", "OP_ADDSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "-=", "OP_SUBSTORE_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + {7, "-=", "OP_SUBSTOREP_IF", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_float, &type_integer}, + + {7, "*=", "OP_MULSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "*=", "OP_MULSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "/=", "OP_DIVSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "/=", "OP_DIVSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "+=", "OP_ADDSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "+=", "OP_ADDSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "-=", "OP_SUBSTORE_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, + {7, "-=", "OP_SUBSTOREP_FI", 6, ASSOC_RIGHT_RESULT, &type_pointer, &type_integer, &type_float}, {0, NULL} }; @@ -562,7 +591,7 @@ pbool OpAssignedTo(QCC_def_t *v, unsigned int op) //this system cuts out 10/120 //these evaluate as top first. -QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = +QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][128] = { { //don't use /* &pr_opcodes[OP_DONE], @@ -625,11 +654,15 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = &pr_opcodes[OP_BITAND], &pr_opcodes[OP_BITAND_I], + &pr_opcodes[OP_BITAND_IF], + &pr_opcodes[OP_BITAND_FI], &pr_opcodes[OP_BITOR], &pr_opcodes[OP_BITOR_I], + &pr_opcodes[OP_BITOR_IF], + &pr_opcodes[OP_BITOR_FI], - &pr_opcodes[OP_POWER_I], + &pr_opcodes[OP_XOR_I], &pr_opcodes[OP_RSHIFT_I], &pr_opcodes[OP_LSHIFT_I], @@ -667,6 +700,8 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = &pr_opcodes[OP_NE_E], &pr_opcodes[OP_NE_FNC], &pr_opcodes[OP_NE_I], + &pr_opcodes[OP_NE_IF], + &pr_opcodes[OP_NE_FI], &pr_opcodes[OP_LE], &pr_opcodes[OP_LE_I], @@ -710,24 +745,55 @@ QCC_opcode_t *opcodeprioritized[TOP_PRIORITY+1][64] = &pr_opcodes[OP_STOREP_P], &pr_opcodes[OP_DIVSTORE_F], + &pr_opcodes[OP_DIVSTORE_I], + &pr_opcodes[OP_DIVSTORE_FI], + &pr_opcodes[OP_DIVSTORE_IF], &pr_opcodes[OP_DIVSTOREP_F], + &pr_opcodes[OP_DIVSTOREP_I], + &pr_opcodes[OP_DIVSTOREP_IF], + &pr_opcodes[OP_DIVSTOREP_FI], &pr_opcodes[OP_MULSTORE_F], &pr_opcodes[OP_MULSTORE_V], + &pr_opcodes[OP_MULSTORE_I], + &pr_opcodes[OP_MULSTORE_IF], + &pr_opcodes[OP_MULSTORE_FI], &pr_opcodes[OP_MULSTOREP_F], &pr_opcodes[OP_MULSTOREP_V], + &pr_opcodes[OP_MULSTOREP_I], + &pr_opcodes[OP_MULSTOREP_IF], + &pr_opcodes[OP_MULSTOREP_FI], &pr_opcodes[OP_ADDSTORE_F], &pr_opcodes[OP_ADDSTORE_V], + &pr_opcodes[OP_ADDSTORE_I], + &pr_opcodes[OP_ADDSTORE_IF], + &pr_opcodes[OP_ADDSTORE_FI], &pr_opcodes[OP_ADDSTOREP_F], &pr_opcodes[OP_ADDSTOREP_V], + &pr_opcodes[OP_ADDSTOREP_I], + &pr_opcodes[OP_ADDSTOREP_IF], + &pr_opcodes[OP_ADDSTOREP_FI], &pr_opcodes[OP_SUBSTORE_F], &pr_opcodes[OP_SUBSTORE_V], + &pr_opcodes[OP_SUBSTORE_I], + &pr_opcodes[OP_SUBSTORE_IF], + &pr_opcodes[OP_SUBSTORE_FI], &pr_opcodes[OP_SUBSTOREP_F], &pr_opcodes[OP_SUBSTOREP_V], + &pr_opcodes[OP_SUBSTOREP_I], + &pr_opcodes[OP_SUBSTOREP_IF], + &pr_opcodes[OP_SUBSTOREP_FI], &pr_opcodes[OP_BITSET], + &pr_opcodes[OP_BITSET_I], +// &pr_opcodes[OP_BITSET_IF], +// &pr_opcodes[OP_BITSET_FI], &pr_opcodes[OP_BITSETP], + &pr_opcodes[OP_BITSETP_I], +// &pr_opcodes[OP_BITSETP_IF], +// &pr_opcodes[OP_BITSETP_FI], &pr_opcodes[OP_BITCLR], &pr_opcodes[OP_BITCLRP], + NULL }, { //7 &pr_opcodes[OP_AND], @@ -740,6 +806,7 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op) { int num; num = op - pr_opcodes; + switch(qcc_targetformat) { case QCF_STANDARD: @@ -757,11 +824,19 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op) return false; case QCF_FTE: case QCF_FTEDEBUG: + //no emulated opcodes + if (num >= OP_NUMREALOPS) + return false; return true; case QCF_DARKPLACES: //all id opcodes. if (num < OP_MULSTORE_F) return true; + + //no emulated opcodes + if (num >= OP_NUMREALOPS) + return false; + //extended opcodes. //DPFIXME: this is a list of the extended opcodes. I was conservative regarding supported ones. // at the time of writing, these are the ones that look like they'll work just fine in Blub\0's patch. @@ -951,7 +1026,7 @@ pbool QCC_OPCodeValid(QCC_opcode_t *op) case OP_LOADP_V: return true; - case OP_POWER_I: + case OP_XOR_I: case OP_RSHIFT_I: case OP_LSHIFT_I: return true; @@ -1781,6 +1856,20 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_a = var_c; var_c = var_a; break; + case OP_ADDSTORE_FI: + op = &pr_opcodes[OP_ADD_FI]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; + case OP_ADDSTORE_IF: + op = &pr_opcodes[OP_ADD_IF]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_SUBSTORE_F: op = &pr_opcodes[OP_SUB_F]; @@ -1789,6 +1878,20 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_a = var_c; var_c = var_a; break; + case OP_SUBSTORE_FI: + op = &pr_opcodes[OP_SUB_FI]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; + case OP_SUBSTORE_IF: + op = &pr_opcodes[OP_SUB_IF]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_DIVSTORE_F: op = &pr_opcodes[OP_DIV_F]; @@ -1797,6 +1900,20 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_a = var_c; var_c = var_a; break; + case OP_DIVSTORE_FI: + op = &pr_opcodes[OP_DIV_FI]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; + case OP_DIVSTORE_IF: + op = &pr_opcodes[OP_DIV_IF]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_MULSTORE_F: op = &pr_opcodes[OP_MUL_F]; @@ -1805,6 +1922,20 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_a = var_c; var_c = var_a; break; + case OP_MULSTORE_IF: + op = &pr_opcodes[OP_MUL_IF]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; + case OP_MULSTORE_FI: + op = &pr_opcodes[OP_MUL_FI]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_ADDSTORE_V: op = &pr_opcodes[OP_ADD_V]; @@ -1830,6 +1961,13 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_c = var_a; break; + case OP_BITSET_I: + op = &pr_opcodes[OP_BITOR_I]; + var_c = var_b; + var_b = var_a; + var_a = var_c; + var_c = var_a; + break; case OP_BITSET: op = &pr_opcodes[OP_BITOR]; var_c = var_b; @@ -1859,11 +1997,22 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var var_c = var_a; break; + case OP_SUBSTOREP_FI: + case OP_SUBSTOREP_IF: + case OP_ADDSTOREP_FI: + case OP_ADDSTOREP_IF: + case OP_MULSTOREP_FI: + case OP_MULSTOREP_IF: + case OP_DIVSTOREP_FI: + case OP_DIVSTOREP_IF: + + case OP_SUBSTOREP_F: case OP_ADDSTOREP_F: case OP_MULSTOREP_F: case OP_DIVSTOREP_F: case OP_BITSETP: + case OP_BITSETP_I: case OP_BITCLRP: // QCC_PR_ParseWarning(0, "XSTOREP_F emulation is still experimental"); QCC_UnFreeTemp(var_a); @@ -1907,6 +2056,30 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_SUBSTOREP_F: statement->op = OP_SUB_F; break; + case OP_SUBSTOREP_IF: + statement->op = OP_SUB_IF; + break; + case OP_SUBSTOREP_FI: + statement->op = OP_SUB_FI; + break; + case OP_ADDSTOREP_IF: + statement->op = OP_ADD_IF; + break; + case OP_ADDSTOREP_FI: + statement->op = OP_ADD_FI; + break; + case OP_MULSTOREP_IF: + statement->op = OP_MUL_IF; + break; + case OP_MULSTOREP_FI: + statement->op = OP_MUL_FI; + break; + case OP_DIVSTOREP_IF: + statement->op = OP_DIV_IF; + break; + case OP_DIVSTOREP_FI: + statement->op = OP_DIV_FI; + break; case OP_ADDSTOREP_F: statement->op = OP_ADD_F; break; @@ -1919,6 +2092,9 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var case OP_BITSETP: statement->op = OP_BITOR; break; + case OP_BITSETP_I: + statement->op = OP_BITOR_I; + break; case OP_BITCLRP: //float pointer float temp = QCC_GetTemp(type_float); @@ -3308,6 +3484,8 @@ QCC_def_t *QCC_MakeFloatDef(float value) pr.def_tail->next = cn; pr.def_tail = cn; + cn->s_file = s_file; + cn->s_line = pr_source_line; cn->type = type_float; cn->name = "IMMEDIATE"; cn->constant = true; @@ -5047,6 +5225,12 @@ void QCC_PR_ParseStatement (void) return; } e = QCC_PR_Expression (TOP_PRIORITY, true); + e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type); + if (e != e2) + { + QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name); + e = e2; + } QCC_PR_Expect (";"); if (pr_scope->type->aux_type->type != e->type->type) QCC_PR_ParseWarning(WARN_WRONGRETURNTYPE, "\'%s\' returned %s, expected %s", pr_scope->name, e->type->name, pr_scope->type->aux_type->name); @@ -5827,7 +6011,8 @@ void QCC_PR_ParseStatement (void) { int osl = pr_source_line; pr_source_line = statementstart; - QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Hanging ';'"); + if (!expandedemptymacro) + QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Hanging ';'"); pr_source_line = osl; return; } @@ -5836,6 +6021,7 @@ void QCC_PR_ParseStatement (void) qcc_usefulstatement = false; e = QCC_PR_Expression (TOP_PRIORITY, true); + expandedemptymacro = false; QCC_PR_Expect (";"); if (e->type->type != ev_void && !qcc_usefulstatement) @@ -6684,6 +6870,8 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) conditional = 0; + expandedemptymacro = false; + f = (void *)qccHunkAlloc (sizeof(QCC_function_t)); @@ -6900,17 +7088,17 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) if (num_continues) { num_continues=0; - QCC_PR_ParseError(ERR_ILLEGALCONTINUES, "%s: function contains illegal continues\n", pr_scope->name); + QCC_PR_ParseError(ERR_ILLEGALCONTINUES, "%s: function contains illegal continues", pr_scope->name); } if (num_breaks) { num_breaks=0; - QCC_PR_ParseError(ERR_ILLEGALBREAKS, "%s: function contains illegal breaks\n", pr_scope->name); + QCC_PR_ParseError(ERR_ILLEGALBREAKS, "%s: function contains illegal breaks", pr_scope->name); } if (num_cases) { num_cases = 0; - QCC_PR_ParseError(ERR_ILLEGALCASES, "%s: function contains illegal cases\n", pr_scope->name); + QCC_PR_ParseError(ERR_ILLEGALCASES, "%s: function contains illegal cases", pr_scope->name); } return f; @@ -7445,9 +7633,9 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool } if (type && typecmp(def->type, type)) - QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); + QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); if (def->arraysize != arraysize && arraysize) - QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name); + QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name); if (allocate && scope) { QCC_PR_ParseWarning (WARN_DUPLICATEDEFINITION, "%s duplicate definition ignored", name); @@ -7473,10 +7661,10 @@ QCC_def_t *QCC_PR_GetDef (QCC_type_t *type, char *name, QCC_def_t *scope, pbool if (type && typecmp(def->type, type)) { if (!pr_scope) - QCC_PR_ParseError (ERR_TYPEMISMATCHREDEC, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); + QCC_PR_ParseErrorPrintDef (ERR_TYPEMISMATCHREDEC, def, "Type mismatch on redeclaration of %s. %s, should be %s",name, TypeName(type), TypeName(def->type)); } if (def->arraysize != arraysize && arraysize) - QCC_PR_ParseError (ERR_TYPEMISMATCHARRAYSIZE, "Array sizes for redecleration of %s do not match",name); + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCHARRAYSIZE, def, "Array sizes for redecleration of %s do not match",name); if (allocate && scope) { if (pr_scope) @@ -7771,41 +7959,84 @@ void QCC_PR_ParseDefs (char *classname) if (QCC_PR_CheckKeyword(keyword_enum, "enum")) { - float v = 0; - QCC_PR_Expect("{"); - i = 0; - d = NULL; - while(1) + if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int")) { - name = QCC_PR_ParseName(); - if (QCC_PR_CheckToken("=")) + int iv = 0; + QCC_PR_Expect("{"); + i = 0; + d = NULL; + while(1) { - if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float) + name = QCC_PR_ParseName(); + if (QCC_PR_CheckToken("=")) { - def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false); - if (def) + if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_integer) { - if (!def->constant) - QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name); + def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false); + if (def) + { + if (!def->constant) + QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name); + else + iv = G_INT(def->ofs); + } else - v = G_FLOAT(def->ofs); + QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number"); } else - QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number"); + { + iv = pr_immediate._int; + QCC_PR_Lex(); + } } - else - { - v = pr_immediate._float; - QCC_PR_Lex(); - } - } - def = QCC_MakeFloatDef(v); - pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); - v++; + def = QCC_MakeIntDef(iv); + pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); + iv++; - if (QCC_PR_CheckToken("}")) - break; - QCC_PR_Expect(","); + if (QCC_PR_CheckToken("}")) + break; + QCC_PR_Expect(","); + } + } + else + { + float fv = 0; + QCC_PR_CheckKeyword(keyword_float, "float"); + QCC_PR_Expect("{"); + i = 0; + d = NULL; + while(1) + { + name = QCC_PR_ParseName(); + if (QCC_PR_CheckToken("=")) + { + if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float) + { + def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false); + if (def) + { + if (!def->constant) + QCC_PR_ParseError(ERR_NOTANUMBER, "enum - %s is not a constant", def->name); + else + fv = G_FLOAT(def->ofs); + } + else + QCC_PR_ParseError(ERR_NOTANUMBER, "enum - not a number"); + } + else + { + fv = pr_immediate._float; + QCC_PR_Lex(); + } + } + def = QCC_MakeFloatDef(fv); + pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); + fv++; + + if (QCC_PR_CheckToken("}")) + break; + QCC_PR_Expect(","); + } } QCC_PR_Expect(";"); return; @@ -7813,60 +8044,123 @@ void QCC_PR_ParseDefs (char *classname) if (QCC_PR_CheckKeyword(keyword_enumflags, "enumflags")) { - float v = 1; int bits; - QCC_PR_Expect("{"); - i = 0; - d = NULL; - while(1) + + if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int")) { - name = QCC_PR_ParseName(); - if (QCC_PR_CheckToken("=")) + int iv = 1; + QCC_PR_Expect("{"); + i = 0; + d = NULL; + while(1) { - if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float) + name = QCC_PR_ParseName(); + if (QCC_PR_CheckToken("=")) { - def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false); - if (def) + if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_integer) { - if (!def->constant) - QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name); + def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false); + if (def) + { + if (!def->constant) + QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name); + else + iv = G_INT(def->ofs); + } else - v = G_FLOAT(def->ofs); + QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number"); } else - QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number"); + { + iv = pr_immediate._int; + QCC_PR_Lex(); + } } + + bits = 0; + i = (int)iv; + if (i != iv) + QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", iv); else { - v = pr_immediate._float; - QCC_PR_Lex(); + while(i) + { + if (((i>>1)<<1) != i) + bits++; + i>>=1; + } + if (bits != 1) + QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)iv); } - } - bits = 0; - i = (int)v; - if (i != v) - QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", v); - else + def = QCC_MakeIntDef(iv); + pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); + + iv*=2; + + if (QCC_PR_CheckToken("}")) + break; + QCC_PR_Expect(","); + } + } + else + { + float fv = 1; + QCC_PR_CheckKeyword(keyword_float, "float"); + + QCC_PR_Expect("{"); + i = 0; + d = NULL; + while(1) { - while(i) + name = QCC_PR_ParseName(); + if (QCC_PR_CheckToken("=")) { - if (((i>>1)<<1) != i) - bits++; - i>>=1; + if (pr_token_type != tt_immediate && pr_immediate_type->type != ev_float) + { + def = QCC_PR_GetDef(NULL, QCC_PR_ParseName(), NULL, false, 0, false); + if (def) + { + if (!def->constant) + QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - %s is not a constant", def->name); + else + fv = G_FLOAT(def->ofs); + } + else + QCC_PR_ParseError(ERR_NOTANUMBER, "enumflags - not a number"); + } + else + { + fv = pr_immediate._float; + QCC_PR_Lex(); + } } - if (bits != 1) - QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)v); + + bits = 0; + i = (int)fv; + if (i != fv) + QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTINTEGER, "enumflags - %f not an integer", fv); + else + { + while(i) + { + if (((i>>1)<<1) != i) + bits++; + i>>=1; + } + if (bits != 1) + QCC_PR_ParseWarning(WARN_ENUMFLAGS_NOTBINARY, "enumflags - value %i not a single bit", (int)fv); + } + + def = QCC_MakeFloatDef(fv); + pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); + + fv*=2; + + if (QCC_PR_CheckToken("}")) + break; + QCC_PR_Expect(","); } - - def = QCC_MakeFloatDef(v); - pHash_Add(&globalstable, name, def, qccHunkAlloc(sizeof(bucket_t))); - - v*=2; - - if (QCC_PR_CheckToken("}")) - break; - QCC_PR_Expect(","); } QCC_PR_Expect(";"); return; @@ -8975,15 +9269,17 @@ pbool QCC_PR_CompileFile (char *string, char *filename) pr_source_line = 0; + memcpy(&oldjb, &pr_parse_abort, sizeof(oldjb)); + if( setjmp( pr_parse_abort ) ) { // dont count it as error } else { + //clock up the first line QCC_PR_NewLine (false); QCC_PR_Lex (); // read first token } - memcpy(&oldjb, &pr_parse_abort, sizeof(oldjb)); while (pr_token_type != tt_eof) { if (setjmp(pr_parse_abort)) @@ -8993,6 +9289,9 @@ pbool QCC_PR_CompileFile (char *string, char *filename) memcpy(&pr_parse_abort, &oldjb, sizeof(oldjb)); return false; } + num_continues = 0; + num_breaks = 0; + num_cases = 0; QCC_PR_SkipToSemicolon (); if (pr_token_type == tt_eof) { diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index 504e4aad1..80473c7bd 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -38,17 +38,19 @@ int pr_warning_count; CompilerConstant_t *CompilerConstant; int numCompilerConstants; +extern pbool expandedemptymacro; char *pr_punctuation[] = // longer symbols must be before a shorter partial match -{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "|=", "(-)", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL}; +{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "(+)", "(-)", "|=", "&~=", "++", "--", "->", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL}; char *pr_punctuationremap[] = //a nice bit of evilness. -//|= -> (+) +//(+) -> |= //-> -> . -{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "|=", "(-)", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL}; +//(-) -> &~= +{"&&", "||", "<=", ">=","==", "!=", "/=", "*=", "+=", "-=", "|=", "&~=", "|=", "&~=", "++", "--", ".", "::", ";", ",", "!", "*", "/", "(", ")", "-", "+", "=", "[", "]", "{", "}", "...", "..", ".", "<<", "<", ">>", ">" , "?", "#" , "@", "&" , "|", "^", ":", NULL}; // simple types. function types are dynamically allocated QCC_type_t *type_void;// = {ev_void/*, &def_void*/}; @@ -792,8 +794,8 @@ pbool QCC_PR_Precompiler(void) if (*pr_file_p == '\n') { - QCC_PR_NewLine(false); pr_file_p++; + QCC_PR_NewLine(false); } } } @@ -803,10 +805,29 @@ pbool QCC_PR_Precompiler(void) QCC_PR_ParseWarning(WARN_STRINGTOOLONG, "Copyright message is too long\n"); strncpy(QCC_copyright, msg, sizeof(QCC_copyright)-1); } - else if (!strncmp(directive, "forcecrc", 8)) + else if (!strncmp(qcc_token, "forcecrc", 8)) { ForcedCRC = atoi(msg); } + else if (!strncmp(qcc_token, "sourcefile", 10)) + { + #define MAXSOURCEFILESLIST 8 + extern char sourcefileslist[MAXSOURCEFILESLIST][1024]; + extern int currentsourcefile; + extern int numsourcefiles; + + int i; + + QCC_COM_Parse(msg); + + for (i = 0; i < numsourcefiles; i++) + { + if (!strcmp(sourcefileslist[i], qcc_token)) + break; + } + if (i == numsourcefiles) + strcpy(sourcefileslist[numsourcefiles++], qcc_token); + } else if (!QC_strcasecmp(qcc_token, "TARGET")) { if (qcc_targetformat == QCF_HEXEN2 && numstatements) @@ -971,16 +992,6 @@ Call at start of file and when *pr_file_p == '\n' */ void QCC_PR_NewLine (pbool incomment) { - pbool m; - - if (*pr_file_p == '\n') - { - pr_file_p++; - m = true; - } - else - m = false; - pr_source_line++; pr_line_start = pr_file_p; while(*pr_file_p==' ' || *pr_file_p == '\t') @@ -994,8 +1005,6 @@ void QCC_PR_NewLine (pbool incomment) // if (pr_dumpasm) // PR_PrintNextLine (); - if (m) - pr_file_p--; } /* @@ -1213,8 +1222,12 @@ void QCC_PR_LexString (void) while(*pr_file_p && *pr_file_p <= ' ') { if (*pr_file_p == '\n') + { + pr_file_p++; QCC_PR_NewLine(false); - pr_file_p++; + } + else + pr_file_p++; } if (*pr_file_p == '\"') //have annother go { @@ -1565,13 +1578,17 @@ void QCC_PR_LexWhitespace (void) { if (c=='\n') { + pr_file_p++; QCC_PR_NewLine (false); if (!pr_file_p) return; } - if (c == 0) - return; // end of file - pr_file_p++; + else + { + if (c == 0) + return; // end of file + pr_file_p++; + } } // skip // comments @@ -1579,8 +1596,10 @@ void QCC_PR_LexWhitespace (void) { while (*pr_file_p && *pr_file_p != '\n') pr_file_p++; + + if (*pr_file_p == '\n') + pr_file_p++; //don't break on eof. QCC_PR_NewLine(false); - pr_file_p++; continue; } @@ -1591,7 +1610,10 @@ void QCC_PR_LexWhitespace (void) { pr_file_p++; if (pr_file_p[0]=='\n') + { + pr_file_p++; QCC_PR_NewLine(true); + } if (pr_file_p[1] == 0) { pr_file_p++; @@ -1724,7 +1746,7 @@ pbool QCC_PR_LexMacroName(void) } i = 0; - while ( (c = *pr_file_p) > ' ' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(pr_file_p[0] == '.' && pr_file_p[1] == '.')) + while ( (c = *pr_file_p) > ' ' && c != '\n' && c != ',' && c != ';' && c != ')' && c != '(' && c != ']' && !(pr_file_p[0] == '.' && pr_file_p[1] == '.')) { pr_token[i] = c; i++; @@ -2018,21 +2040,21 @@ void QCC_PR_ConditionCompilation(void) { if (*pr_file_p == ',') { + if (cnst->numparams >= MAXCONSTANTPARAMS) + QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS); strncpy(cnst->params[cnst->numparams], s, pr_file_p-s); cnst->params[cnst->numparams][pr_file_p-s] = '\0'; cnst->numparams++; - if (cnst->numparams > MAXCONSTANTPARAMS) - QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS); pr_file_p++; s = pr_file_p; } if (*pr_file_p == ')') { + if (cnst->numparams >= MAXCONSTANTPARAMS) + QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS); strncpy(cnst->params[cnst->numparams], s, pr_file_p-s); cnst->params[cnst->numparams][pr_file_p-s] = '\0'; cnst->numparams++; - if (cnst->numparams > MAXCONSTANTPARAMS) - QCC_PR_ParseError(ERR_MACROTOOMANYPARMS, "May not have more than %i parameters to a macro", MAXCONSTANTPARAMS); pr_file_p++; break; } @@ -2280,13 +2302,19 @@ int QCC_PR_CheakCompConst(void) paramoffset[p][strlen(paramoffset[p])] = ')'; pr_file_p = oldpr_file_p; + if (!*buffer) + expandedemptymacro = true; QCC_PR_IncludeChunkEx(buffer, true, NULL, c); } else QCC_PR_ParseError(ERR_TOOFEWPARAMS, "Macro without opening brace"); } else + { + if (!*c->value) + expandedemptymacro = true; QCC_PR_IncludeChunkEx(c->value, false, NULL, c); + } QCC_PR_Lex(); return true; diff --git a/engine/qclib/qccguistuff.c b/engine/qclib/qccguistuff.c index 6198a89be..c9d03b55b 100644 --- a/engine/qclib/qccguistuff.c +++ b/engine/qclib/qccguistuff.c @@ -49,7 +49,10 @@ void GoToDefinition(char *name) return; } } - EditFile(def->s_file+strings, def->s_line-1); + if (!def->s_file) + GUI_DialogPrint("Not found", "Global definition of var was not specified."); + else + EditFile(def->s_file+strings, def->s_line-1); } else GUI_DialogPrint("Not found", "Global instance of var was not found."); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 919975b34..45fa7a583 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -38,6 +38,11 @@ int *qcc_tempofs; int tempsstart; int numtemps; +#define MAXSOURCEFILESLIST 8 +char sourcefileslist[MAXSOURCEFILESLIST][1024]; +int currentsourcefile; +int numsourcefiles; + void QCC_PR_ResetErrorScope(void); pbool compressoutput; @@ -543,7 +548,7 @@ void QCC_UnmarshalLocals(void) } CompilerConstant_t *QCC_PR_CheckCompConstDefined(char *def); -void QCC_WriteData (int crc) +pbool QCC_WriteData (int crc) { char element[MAX_NAME]; QCC_def_t *def, *comp_x, *comp_y, *comp_z; @@ -555,6 +560,12 @@ void QCC_WriteData (int crc) pbool types = false; int outputsize = 16; + if (numstatements==1 && numfunctions==1 && numglobaldefs==1 && numfielddefs==1) + { + printf("nothing to write\n"); + return false; + } + progs.blockscompressed=0; if (numstatements > MAX_STATEMENTS) @@ -747,7 +758,9 @@ void QCC_WriteData (int crc) // && def->type->type != ev_function && def->type->type != ev_field && def->scope == NULL)) + { dd->type |= DEF_SAVEGLOBAL; + } #endif if (def->shared) dd->type |= DEF_SHARED; @@ -762,6 +775,52 @@ void QCC_WriteData (int crc) dd->ofs = def->ofs; } + for (i = 0; i < numglobaldefs; i++) + { + dd = &qcc_globals[i]; + if (!(dd->type & DEF_SAVEGLOBAL)) //only warn about saved ones. + continue; + + for (h = 0; h < numglobaldefs; h++) + { + if (i == h) + continue; + if (dd->ofs == qcc_globals[h].ofs) + { + if (dd->type != qcc_globals[h].type) + { + if (dd->type != ev_vector && qcc_globals[h].type != ev_float) + QCC_PR_Warning(0, NULL, 0, "Mismatched union global types (%s and %s)", strings+dd->s_name, strings+qcc_globals[h].s_name); + } + //remove the saveglobal flag on the duplicate globals. + qcc_globals[h].type &= ~DEF_SAVEGLOBAL; + } + } + } + for (i = 1; i < numfielddefs; i++) + { + dd = &fields[i]; + + if (dd->type == ev_vector) //just ignore vectors. + continue; + + for (h = 1; h < numfielddefs; h++) + { + if (i == h) + continue; + if (dd->ofs == fields[h].ofs) + { + if (dd->type != fields[h].type) + { + if (fields[h].type != ev_vector) + { + QCC_PR_Warning(0, NULL, 0, "Mismatched union field types (%s and %s)", strings+dd->s_name, strings+fields[h].s_name); + } + } + } + } + } + if (numglobaldefs > MAX_GLOBALS) QCC_Error(ERR_TOOMANYGLOBALS, "Too many globals - %i\nAdd \"MAX_GLOBALS\" \"%i\" to qcc.cfg", numglobaldefs, (numglobaldefs+32768)&~32767); @@ -1161,6 +1220,8 @@ strofs = (strofs+3)&~3; SafeClose (h); } } + + return true; } @@ -1465,10 +1526,10 @@ void QCC_PR_BeginCompilation (void *memory, int memsize) //type_field->aux_type = type_float; - if (keyword_int) - QCC_PR_NewType("int", ev_integer); if (keyword_integer) - QCC_PR_NewType("integer", ev_integer); + type_integer = QCC_PR_NewType("integer", ev_integer); + if (keyword_int) + type_integer = QCC_PR_NewType("int", ev_integer); @@ -2388,6 +2449,7 @@ void QCC_PR_CommandLinePrecompilerOptions (void) qccwarningdisabled[WARN_UNDEFNOTDEFINED] = true; qccwarningdisabled[WARN_FIXEDRETURNVALUECONFLICT] = true; qccwarningdisabled[WARN_EXTRAPRECACHE] = true; + qccwarningdisabled[WARN_CORRECTEDRETURNTYPE] = true; } else { @@ -2856,17 +2918,37 @@ memset(pr_immediate_string, 0, sizeof(pr_immediate_string)); } else { - p = QCC_CheckParm ("-qc"); - if (!p || p >= argc-1 || argv[p+1][0] == '-') - p = QCC_CheckParm ("-srcfile"); - if (p && p < argc-1 ) - sprintf (qccmprogsdat, "%s%s", qccmsourcedir, argv[p+1]); - else - { //look for a preprogs.src... :o) - sprintf (qccmprogsdat, "%spreprogs.src", qccmsourcedir); - if (externs->FileSize(qccmprogsdat) <= 0) - sprintf (qccmprogsdat, "%sprogs.src", qccmsourcedir); + if (!numsourcefiles) + { + p = QCC_CheckParm ("-qc"); + if (!p || p >= argc-1 || argv[p+1][0] == '-') + p = QCC_CheckParm ("-srcfile"); + if (p && p < argc-1 ) + sprintf (qccmprogsdat, "%s%s", qccmsourcedir, argv[p+1]); + else + { //look for a preprogs.src... :o) + sprintf (qccmprogsdat, "%spreprogs.src", qccmsourcedir); + if (externs->FileSize(qccmprogsdat) <= 0) + sprintf (qccmprogsdat, "%sprogs.src", qccmsourcedir); + } + + numsourcefiles = 0; + strcpy(sourcefileslist[numsourcefiles++], qccmprogsdat); + currentsourcefile = 0; } + else if (currentsourcefile == numsourcefiles) + { + //no more. + qcc_compileactive = false; + numsourcefiles = 0; + currentsourcefile = 0; + return; + } + + if (currentsourcefile) + printf("-------------------------------------\n"); + + strcpy(qccmprogsdat, sourcefileslist[currentsourcefile++]); printf ("Source file: %s\n", qccmprogsdat); @@ -2996,6 +3078,11 @@ void QCC_ContinueCompile(void) return; } QCC_FinishCompile(); + + PostCompile(); + if (!PreCompile()) + return; + QCC_main(myargc, myargv); return; } s = qcc_token; @@ -3038,6 +3125,7 @@ void QCC_ContinueCompile(void) } void QCC_FinishCompile(void) { + pbool donesomething; int crc; // int p; currentchunk = NULL; @@ -3077,7 +3165,7 @@ void QCC_FinishCompile(void) crc = QCC_PR_WriteProgdefs ("progdefs.h"); // write data file - QCC_WriteData (crc); + donesomething = QCC_WriteData (crc); // regenerate bmodels if -bspmodels QCC_BspModels (); @@ -3085,58 +3173,61 @@ void QCC_FinishCompile(void) // report / copy the data files QCC_CopyFiles (); - printf ("Compile Complete\n\n"); + if (donesomething) + { + printf ("Compile Complete\n\n"); - if (optres_shortenifnots) - printf("optres_shortenifnots %i\n", optres_shortenifnots); - if (optres_overlaptemps) - printf("optres_overlaptemps %i\n", optres_overlaptemps); - if (optres_noduplicatestrings) - printf("optres_noduplicatestrings %i\n", optres_noduplicatestrings); - if (optres_constantarithmatic) - printf("optres_constantarithmatic %i\n", optres_constantarithmatic); - if (optres_nonvec_parms) - printf("optres_nonvec_parms %i\n", optres_nonvec_parms); - if (optres_constant_names) - printf("optres_constant_names %i\n", optres_constant_names); - if (optres_constant_names_strings) - printf("optres_constant_names_strings %i\n", optres_constant_names_strings); - if (optres_precache_file) - printf("optres_precache_file %i\n", optres_precache_file); - if (optres_filenames) - printf("optres_filenames %i\n", optres_filenames); - if (optres_assignments) - printf("optres_assignments %i\n", optres_assignments); - if (optres_unreferenced) - printf("optres_unreferenced %i\n", optres_unreferenced); - if (optres_locals) - printf("optres_locals %i\n", optres_locals); - if (optres_function_names) - printf("optres_function_names %i\n", optres_function_names); - if (optres_dupconstdefs) - printf("optres_dupconstdefs %i\n", optres_dupconstdefs); - if (optres_return_only) - printf("optres_return_only %i\n", optres_return_only); - if (optres_compound_jumps) - printf("optres_compound_jumps %i\n", optres_compound_jumps); -// if (optres_comexprremoval) -// printf("optres_comexprremoval %i\n", optres_comexprremoval); - if (optres_stripfunctions) - printf("optres_stripfunctions %i\n", optres_stripfunctions); - if (optres_locals_marshalling) - printf("optres_locals_marshalling %i\n", optres_locals_marshalling); - if (optres_logicops) - printf("optres_logicops %i\n", optres_logicops); + if (optres_shortenifnots) + printf("optres_shortenifnots %i\n", optres_shortenifnots); + if (optres_overlaptemps) + printf("optres_overlaptemps %i\n", optres_overlaptemps); + if (optres_noduplicatestrings) + printf("optres_noduplicatestrings %i\n", optres_noduplicatestrings); + if (optres_constantarithmatic) + printf("optres_constantarithmatic %i\n", optres_constantarithmatic); + if (optres_nonvec_parms) + printf("optres_nonvec_parms %i\n", optres_nonvec_parms); + if (optres_constant_names) + printf("optres_constant_names %i\n", optres_constant_names); + if (optres_constant_names_strings) + printf("optres_constant_names_strings %i\n", optres_constant_names_strings); + if (optres_precache_file) + printf("optres_precache_file %i\n", optres_precache_file); + if (optres_filenames) + printf("optres_filenames %i\n", optres_filenames); + if (optres_assignments) + printf("optres_assignments %i\n", optres_assignments); + if (optres_unreferenced) + printf("optres_unreferenced %i\n", optres_unreferenced); + if (optres_locals) + printf("optres_locals %i\n", optres_locals); + if (optres_function_names) + printf("optres_function_names %i\n", optres_function_names); + if (optres_dupconstdefs) + printf("optres_dupconstdefs %i\n", optres_dupconstdefs); + if (optres_return_only) + printf("optres_return_only %i\n", optres_return_only); + if (optres_compound_jumps) + printf("optres_compound_jumps %i\n", optres_compound_jumps); + // if (optres_comexprremoval) + // printf("optres_comexprremoval %i\n", optres_comexprremoval); + if (optres_stripfunctions) + printf("optres_stripfunctions %i\n", optres_stripfunctions); + if (optres_locals_marshalling) + printf("optres_locals_marshalling %i\n", optres_locals_marshalling); + if (optres_logicops) + printf("optres_logicops %i\n", optres_logicops); - if (optres_test1) - printf("optres_test1 %i\n", optres_test1); - if (optres_test2) - printf("optres_test2 %i\n", optres_test2); - - printf("numtemps %i\n", numtemps); + if (optres_test1) + printf("optres_test1 %i\n", optres_test1); + if (optres_test2) + printf("optres_test2 %i\n", optres_test2); + + printf("numtemps %i\n", numtemps); - printf("%i warnings\n", pr_warning_count); + printf("%i warnings\n", pr_warning_count); + } qcc_compileactive = false; } @@ -3162,6 +3253,9 @@ void StartNewStyleCompile(void) { if (++pr_error_count > MAX_ERRORS) return; + if (setjmp(pr_parse_abort)) + return; + QCC_PR_SkipToSemicolon (); if (pr_token_type == tt_eof) return; @@ -3200,6 +3294,11 @@ void new_QCC_ContinueCompile(void) if (pr_error_count) QCC_Error (ERR_PARSEERRORS, "Errors have occured"); QCC_FinishCompile(); + + PostCompile(); + if (!PreCompile()) + return; + QCC_main(myargc, myargv); return; } diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index 1cf7e1d37..ad965017f 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -290,6 +290,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case svcdp_showlmp: case svcdp_hidelmp: break; + case svc_sound: case svc_temp_entity: break; case svc_setangle: @@ -358,6 +359,24 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) { switch(majortype) { + case svc_sound: +#define NQSND_VOLUME (1<<0) // a qbyte +#define NQSND_ATTENUATION (1<<1) // a qbyte +#define DPSND_LOOPING (1<<2) // a long, supposedly +#define DPSND_LARGEENTITY (1<<3) +#define DPSND_LARGESOUND (1<<4) + protocollen = 5+sizeofcoord*3; + if (data & NQSND_VOLUME) + protocollen++; + if (data & NQSND_ATTENUATION) + protocollen++; + if (data & DPSND_LARGEENTITY) + protocollen++; + if (data & DPSND_LARGESOUND) + protocollen++; +#pragma message("NPP_NQWriteByte: this ignores SVC_SOUND from nq mods (nexuiz)") + ignoreprotocol = true; + break; case svc_temp_entity: switch(data) { diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 92bfb89ce..f33bd64ca 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -59,15 +59,11 @@ cvar_t progs = SCVARF("progs", "", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOTFROM cvar_t qc_nonetaccess = SCVAR("qc_nonetaccess", "0"); //prevent write_... builtins from doing anything. This means we can run any mod, specific to any engine, on the condition that it also has a qw or nq crc. cvar_t pr_overridebuiltins = SCVAR("pr_overridebuiltins", "1"); -cvar_t pr_brokenfloatconvert = SCVAR("pr_brokenfloatconvert", "0"); cvar_t pr_compatabilitytest = SCVARF("pr_compatabilitytest", "0", CVAR_LATCH); cvar_t pr_ssqc_coreonerror = SCVAR("pr_coreonerror", "1"); -cvar_t pr_tempstringcount = SCVAR("pr_tempstringcount", "");//"16"); -cvar_t pr_tempstringsize = SCVAR("pr_tempstringsize", "4096"); - cvar_t pr_droptofloorunits = SCVAR("pr_droptofloorunits", ""); cvar_t sv_gameplayfix_honest_tracelines = SCVAR("sv_gameplayfix_honest_tracelines", "1"); @@ -114,6 +110,8 @@ typedef struct { int qwnum; //standard qw. int h2num; //standard hexen2 int ebfsnum; //extra functions, these exist ONLY after being checked for. + + qboolean obsolete; } BuiltinList_t; builtin_t pr_builtin[1024]; extern BuiltinList_t BuiltinList[]; @@ -160,14 +158,6 @@ char *QC_ProgsNameForEnt(edict_t *ent) int pr_edict_size; -pbool QC_WriteFile(char *name, void *data, int len) -{ - char buffer[256]; - sprintf(buffer, "%s", name); - COM_WriteFile(buffer, data, len); - return true; -} - void ED_Spawned (struct edict_s *ent, int loading) { #ifdef VM_Q1 @@ -346,7 +336,6 @@ void VARGS PR_CB_Free(void *mem) { BZ_Free(mem); } -void PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals); int QCLibEditor(progfuncs_t *prinst, char *filename, int line, int nump, char **parms); int QCEditor (progfuncs_t *prinst, char *filename, int line, int nump, char **parms) { @@ -915,6 +904,8 @@ void PR_SSCoreDump_f(void) } } +void PR_SVExtensionList_f(void); + /* #ifdef _DEBUG void QCLibTest(void) @@ -934,11 +925,17 @@ char32 sv_addonname[MAXADDONS]; void PR_Init(void) { int i; + + PF_Common_RegisterCvars(); + Cmd_AddCommand ("breakpoint", PR_BreakPoint_f); Cmd_AddCommand ("decompile", PR_Decompile_f); Cmd_AddCommand ("compile", PR_Compile_f); Cmd_AddCommand ("applycompile", PR_ApplyCompilation_f); Cmd_AddCommand ("coredump_ssqc", PR_SSCoreDump_f); + + Cmd_AddCommand ("extensionlist_ssqc", PR_SVExtensionList_f); + /* #ifdef _DEBUG Cmd_AddCommand ("svtestprogs", QCLibTest); @@ -980,13 +977,8 @@ void PR_Init(void) Cvar_Register (&pr_ssqc_coreonerror, cvargroup_progs); - Cvar_Register (&pr_tempstringcount, cvargroup_progs); - Cvar_Register (&pr_tempstringsize, cvargroup_progs); - Cvar_Register (&pr_droptofloorunits, cvargroup_progs); - Cvar_Register (&pr_brokenfloatconvert, cvargroup_progs); - Cvar_Register (&sv_gameplayfix_honest_tracelines, cvargroup_progs); Cvar_Register (&sv_gameplayfix_blowupfallenzombies, cvargroup_progs); Cvar_Register (&sv_gameplayfix_noairborncorpse, cvargroup_progs); @@ -1164,7 +1156,7 @@ void Q_InitProgs(void) if (f) { pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, as); + G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, as); PR_ExecuteProgram (svprogfuncs, f); } else @@ -1282,7 +1274,7 @@ void Q_InitProgs(void) if (f) { pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, as); + G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, as); PR_ExecuteProgram (svprogfuncs, f); } else @@ -1324,7 +1316,7 @@ void Q_InitProgs(void) if (f) { pr_globals = PR_globals(svprogfuncs, PR_CURRENT); - G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, sv_addon[i2].string); + G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, sv_addon[i2].string); PR_ExecuteProgram (svprogfuncs, f); } else @@ -1433,9 +1425,9 @@ qboolean PR_GameCodePacket(char *s) - G_INT(OFS_PARM0) = PR_SetString(svprogfuncs, NET_AdrToString (adr, sizeof(adr), net_from)); + G_INT(OFS_PARM0) = PR_TempString(svprogfuncs, NET_AdrToString (adr, sizeof(adr), net_from)); - G_INT(OFS_PARM1) = PR_SetString(svprogfuncs, s); + G_INT(OFS_PARM1) = PR_TempString(svprogfuncs, s); PR_ExecuteProgram (svprogfuncs, SV_ParseConnectionlessPacket); return G_FLOAT(OFS_RETURN); } @@ -1458,7 +1450,7 @@ qboolean PR_KrimzonParseCommand(char *s) pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); - G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, s); + G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, s); PR_ExecuteProgram (svprogfuncs, SV_ParseClientCommand); return true; } @@ -1487,7 +1479,7 @@ qboolean PR_UserCmd(char *s) pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); - G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, s); + G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, s); PR_ExecuteProgram (svprogfuncs, SV_ParseClientCommand); return true; } @@ -1519,7 +1511,7 @@ qboolean PR_UserCmd(char *s) pr_global_struct->time = sv.time; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); - G_INT(OFS_PARM0) = (int)PR_SetString(svprogfuncs, s); + G_INT(OFS_PARM0) = (int)PR_TempString(svprogfuncs, s); PR_ExecuteProgram (svprogfuncs, mod_UserCmd); return !!G_FLOAT(OFS_RETURN); } @@ -1601,32 +1593,6 @@ void PR_LocalInfoChanged(char *name, char *oldivalue, char *newvalue) } } -void VARGS PR_BIError(progfuncs_t *progfuncs, char *format, ...) -{ - va_list argptr; - static char string[2048]; - - va_start (argptr, format); - vsnprintf (string,sizeof(string)-1, format,argptr); - va_end (argptr); - - if (developer.value) - { - globalvars_t *pr_globals = PR_globals(progfuncs, PR_CURRENT); - Con_Printf("%s\n", string); - *progfuncs->pr_trace = 1; - G_INT(OFS_RETURN)=0; //just in case it was a float and should be an ent... - G_INT(OFS_RETURN+1)=0; - G_INT(OFS_RETURN+2)=0; - } - else - { - PR_StackTrace(progfuncs); - PR_AbortStack(progfuncs); - progfuncs->parms->Abort ("%s", string); - } -} - void QC_Clear(void) { } @@ -1654,33 +1620,6 @@ qbyte *PR_OpenFile(char *filename, qbyte *buffer) char *Translate(char *message); -char *PF_VarString (progfuncs_t *prinst, int first, globalvars_t *pr_globals) -{ - int i; - static char buffer[2][4096]; - static int bufnum; - char *s, *out; - - out = buffer[(bufnum++)&1]; - - out[0] = 0; - for (i=first ; i<*prinst->callargc ; i++) - { -// if (G_INT(OFS_PARM0+i*3) < 0 || G_INT(OFS_PARM0+i*3) >= 1024*1024); -// break; - - s = PR_GetStringOfs(prinst, OFS_PARM0+i*3); - if (s) - { - s = Translate(s); - if (strlen(out)+strlen(s)+1 >= sizeof(buffer[0])) - SV_Error("VarString (builtin call ending with strings) exceeded maximum string length of %i chars", sizeof(buffer[0])); - - strcat (out, s); - } - } - return out; -} //#define RETURN_EDICT(pf, e) (((int *)pr_globals)[OFS_RETURN] = EDICT_TO_PROG(pf, e)) @@ -1704,57 +1643,7 @@ char *PF_VarString (progfuncs_t *prinst, int first, globalvars_t *pr_globals) int externcallsdepth; void PR_MoveParms(int progs1, int progs2); //from 2 to 1 -void PF_externcall (progfuncs_t *prinst, globalvars_t *pr_globals) //this func calls a function in annother progs (by name) -{ - int progsnum; - char *funcname; - int i; - string_t failedst = G_INT(OFS_PARM1); - func_t f; - progsnum = G_PROG(OFS_PARM0); - funcname = PR_GetStringOfs(prinst, OFS_PARM1); - - f = PR_FindFunction(prinst, funcname, progsnum); - if (f) - { - for (i = OFS_PARM0; i < OFS_PARM5; i+=3) - VectorCopy(G_VECTOR(i+(2*3)), G_VECTOR(i)); - - (*prinst->pr_trace)++; //continue debugging - PR_ExecuteProgram(prinst, f); - } - else if (!f) - { - f = PR_FindFunction(prinst, "MissingFunc", progsnum); - if (!f) - { - PR_BIError(prinst, "Couldn't find function %s", funcname); - return; - } - - for (i = OFS_PARM0; i < OFS_PARM6; i+=3) - VectorCopy(G_VECTOR(i+(1*3)), G_VECTOR(i)); - G_INT(OFS_PARM0) = failedst; - - (*prinst->pr_trace)++; //continue debugging - PR_ExecuteProgram(prinst, f); - } -} - -//this func calls a function in annother progs -//it works in the same way as the above func, except that it calls by reference to a function, as opposed to by it's name -//used for entity function variables - not actually needed anymore -void PF_externrefcall (progfuncs_t *prinst, globalvars_t *pr_globals) -{ - int progsnum; - func_t f; - progsnum = G_PROG(OFS_PARM0); - f = G_INT(OFS_PARM1); - - (*prinst->pr_trace)++; //continue debugging. - PR_ExecuteProgram(prinst, f); -} float PR_LoadAditionalProgs(char *s); void PF_addprogs(progfuncs_t *prinst, globalvars_t *pr_globals) @@ -1768,59 +1657,7 @@ void PF_addprogs(progfuncs_t *prinst, globalvars_t *pr_globals) G_PROG(OFS_RETURN) = AddProgs(s); } -void PF_externvalue (progfuncs_t *prinst, globalvars_t *pr_globals) //return a value in annother progs -{ - int n = G_PROG(OFS_PARM0); - char *varname = PF_VarString(prinst, 1, pr_globals); - eval_t *var; - var = prinst->FindGlobal(prinst, varname, n); - - if (var) - { - G_INT(OFS_RETURN+0) = ((int*)&var->_int)[0]; - G_INT(OFS_RETURN+1) = ((int*)&var->_int)[1]; - G_INT(OFS_RETURN+2) = ((int*)&var->_int)[2]; - } - else - G_INT(OFS_RETURN) = 0; -} - -void PF_externset (progfuncs_t *prinst, globalvars_t *pr_globals) //set a value in annother progs -{ - int n = G_PROG(OFS_PARM0); - int v = G_INT(OFS_PARM1); - char *varname = PF_VarString(prinst, 2, pr_globals); - eval_t *var; - - var = prinst->FindGlobal(prinst, varname, n); - - if (var) - var->_int = v; -} - -void PF_instr (progfuncs_t *prinst, globalvars_t *pr_globals) -{ - char *sub; - char *s1; - char *s2; - - s1 = PR_GetStringOfs(prinst, OFS_PARM0); - s2 = PF_VarString(prinst, 1, pr_globals); - - if (!s1 || !s2) - { - PR_BIError(prinst, "Null string in \"instr\"\n"); - return; - } - - sub = strstr(s1, s2); - - if (sub == NULL) - G_INT(OFS_RETURN) = 0; - else - RETURN_SSTRING(sub); //last as long as the original string -} @@ -1840,44 +1677,6 @@ char *PF_VarString (int first) } */ -/* -================= -PF_errror - -This is a TERMINAL error, which will kill off the entire server. -Dumps self. - -error(value) -================= -*/ -void PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals); -void PF_error (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *s; - - s = PF_VarString(prinst, 0, pr_globals); -/* Con_Printf ("======SERVER ERROR in %s:\n%s\n", PR_GetString(pr_xfunction->s_name) ,s); - ed = PROG_TO_EDICT(pr_global_struct->self); - ED_Print (ed); -*/ - - PR_StackTrace(prinst); - - Con_Printf("%s\n", s); - - if (developer.value) - { -// SV_Error ("Program error: %s", s); - PF_break(prinst, pr_globals); - (*prinst->pr_trace) = 2; - } - else - { - PR_AbortStack(prinst); - PR_BIError (prinst, "Program error: %s", s); - } -} - /* ================= PF_objerror @@ -2310,61 +2109,9 @@ void PF_centerprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) } } - /* ================= -PF_normalize - -vector normalize(vector) -================= -*/ -void PF_normalize (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float *value1; - vec3_t newvalue; - float newf; - - value1 = G_VECTOR(OFS_PARM0); - - newf = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; - newf = sqrt(newf); - - if (newf == 0) - newvalue[0] = newvalue[1] = newvalue[2] = 0; - else - { - newf = 1/newf; - newvalue[0] = value1[0] * newf; - newvalue[1] = value1[1] * newf; - newvalue[2] = value1[2] * newf; - } - - VectorCopy (newvalue, G_VECTOR(OFS_RETURN)); -} - -/* -================= -PF_vlen - -scalar vlen(vector) -================= -*/ -void PF_vlen (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float *value1; - float newv; - - value1 = G_VECTOR(OFS_PARM0); - - newv = value1[0] * value1[0] + value1[1] * value1[1] + value1[2]*value1[2]; - newv = sqrt(newv); - - G_FLOAT(OFS_RETURN) = newv; -} - -/* -================= -PF_vlen +PF_vhlen scalar vhlen(vector) ================= @@ -2382,32 +2129,6 @@ void PF_vhlen (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = newv; } -/* -================= -PF_vectoyaw - -float vectoyaw(vector) -================= -*/ -void PF_vectoyaw (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float *value1; - float yaw; - - value1 = G_VECTOR(OFS_PARM0); - - if (value1[1] == 0 && value1[0] == 0) - yaw = 0; - else - { - yaw = (int) (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - } - - G_FLOAT(OFS_RETURN) = yaw; -} - void PF_anglemod (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float v = G_FLOAT(OFS_PARM0); @@ -2420,86 +2141,6 @@ void PF_anglemod (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = v; } - -/* -================= -PF_vectoangles - -vector vectoangles(vector) -================= -*/ -void PF_vectoangles (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float *value1; - float forward; - float yaw, pitch; - - value1 = G_VECTOR(OFS_PARM0); - - if (value1[1] == 0 && value1[0] == 0) - { - yaw = 0; - if (value1[2] > 0) - pitch = 90; - else - pitch = 270; - } - else - { - yaw = /*(int)*/ (atan2(value1[1], value1[0]) * 180 / M_PI); - if (yaw < 0) - yaw += 360; - - forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]); - pitch = /*(int)*/ (atan2(value1[2], forward) * 180 / M_PI); - if (pitch < 0) - pitch += 360; - } - - G_FLOAT(OFS_RETURN+0) = pitch; - G_FLOAT(OFS_RETURN+1) = yaw; - G_FLOAT(OFS_RETURN+2) = 0; -} - - -static long predictablerandx = 1; - -void predictablesrand(unsigned int x) -{ - predictablerandx = x; -} -int predictablerandgetseed(void) -{ - return predictablerandx; -} - - -int predictablerand(void) -{ - return(((predictablerandx = predictablerandx*1103515245 + 12345)>>16) & 077777); -} - -/* -================= -PF_Random - -Returns a number from 0<= num < 1 - -random() -================= -*/ -void PF_random (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float num; - - if (svs.demorecording || svs.demoplayback) - num = (predictablerand ()&0x7fff) / ((float)0x7fff); - else - num = (rand ()&0x7fff) / ((float)0x7fff); - - G_FLOAT(OFS_RETURN) = num; -} - /* ================= PF_particle @@ -2735,7 +2376,7 @@ static void PF_particle4 (progfuncs_t *prinst, globalvars_t *pr_globals) SV_MulticastProtExt (org, MULTICAST_PVS, pr_global_struct->dimension_send, PEXT_HEXEN2, 0); } -void PF_particleexplosion(progfuncs_t *prinst, struct globalvars_s *pr_globals) +void PF_h2particleexplosion(progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *org; int color,radius,counter; @@ -2855,47 +2496,6 @@ void PF_LocalSound(progfuncs_t *prinst, struct globalvars_s *pr_globals) #endif }; -/* -================= -PF_break - -break() -================= -*/ -void PF_break (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ -#ifdef SERVERONLY //new break code - char *s; - - //I would like some sort of network activity here, - //but I don't want to mess up the sequence and stuff - //It should be possible, but would mean that I would - //need to alter the client, or rewrite a bit of the server.. - - if (pr_globals) - Con_TPrintf(STL_BREAKSTATEMENT); - else if (developer.value!=2) - return; //non developers cann't step. - for(;;) - { - s=Sys_ConsoleInput(); - if (s) - { - if (!*s) - break; - else - Con_Printf("%s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, s)); - } - } -#elif defined(TEXTEDITOR) - (*prinst->pr_trace)++; -#else //old break code -Con_Printf ("break statement\n"); -*(int *)-4 = 0; // dump to debugger -// PR_RunError ("break statement"); -#endif -} - /* ================= PF_traceline @@ -3361,26 +2961,6 @@ void PF_clienttype (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = 1; //an active, not-bot client. } -/* -================= -PF_localcmd - -Sends text over to the client's execution buffer - -localcmd (string) -================= -*/ -void PF_localcmd (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *str; - - str = PF_VarString(prinst, 0, pr_globals); - if (!strcmp(str, "host_framerate 0\n")) - Cbuf_AddText ("sv_mintic 0\n", RESTRICT_INSECURE); //hmm... do this better... - else - Cbuf_AddText (str, RESTRICT_INSECURE); -} - /* ================= PF_cvar @@ -3414,81 +2994,6 @@ static void PF_cvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) } } -void PF_cvar_string (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *str = PR_GetStringOfs(prinst, OFS_PARM0); - cvar_t *cv = Cvar_Get(str, "", 0, "QC variables"); - RETURN_CSTRING(cv->string); -} - -/* -================= -PF_cvar_set - -float cvar (string) -================= -*/ -void PF_cvar_set (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *var_name, *val; - cvar_t *var; - - var_name = PR_GetStringOfs(prinst, OFS_PARM0); - val = PR_GetStringOfs(prinst, OFS_PARM1); - - var = Cvar_Get(var_name, val, 0, "QC variables"); - if (!var) - return; - Cvar_Set (var, val); -} - -void PF_cvar_setf (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *var_name; - float val; - cvar_t *var; - - var_name = PR_GetStringOfs(prinst, OFS_PARM0); - val = G_FLOAT(OFS_PARM1); - - var = Cvar_FindVar(var_name); - if (!var) - Con_Printf("PF_cvar_set: variable %s not found\n", var_name); - else - Cvar_SetValue (var, val); -} - -/* -================= -PF_registercvar - -float registercvar (string name, string value) -================= -*/ -void PF_registercvar (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *name, *value; - value = PR_GetStringOfs(prinst, OFS_PARM0); - - if (Cvar_FindVar(value)) - G_FLOAT(OFS_RETURN) = 0; - else - { - name = BZ_Malloc(strlen(value)+1); - strcpy(name, value); - if (*prinst->callargc > 1) - value = PR_GetStringOfs(prinst, OFS_PARM1); - else - value = ""; - - // archive? - if (Cvar_Get(name, value, CVAR_USERCREATED, "QC created vars")) - G_FLOAT(OFS_RETURN) = 1; - else - G_FLOAT(OFS_RETURN) = 0; - } -} - void PF_sv_getlight (progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *point = G_VECTOR(OFS_PARM0); @@ -3549,27 +3054,6 @@ void PF_findradius (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_EDICT(prinst, chain); } - -/* -========= -PF_dprint -========= -*/ -void PF_dprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - Con_DPrintf ("%s",PF_VarString(prinst, 0, pr_globals)); -} - -/* -========= -PF_print -========= -*/ -void PF_print (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - Con_Printf ("%s",PF_VarString(prinst, 0, pr_globals)); -} - /* ========= PF_conprint @@ -3605,78 +3089,6 @@ void PF_printv (progfuncs_t *prinst, struct globalvars_s *pr_globals) Con_Printf (PR_GetStringOfs(prinst, OFS_PARM0),temp); } -#define MAX_TEMPSTRS ((int)pr_tempstringcount.value) -#define MAXTEMPBUFFERLEN ((int)pr_tempstringsize.value) -string_t PR_TempString(progfuncs_t *prinst, char *str) -{ - char *tmp; - if (!prinst->tempstringbase) - return prinst->TempString(prinst, str); - - if (!str || !*str) - return 0; - - if (prinst->tempstringnum == MAX_TEMPSTRS) - prinst->tempstringnum = 0; - tmp = prinst->tempstringbase + (prinst->tempstringnum++)*MAXTEMPBUFFERLEN; - - Q_strncpyz(tmp, str, MAXTEMPBUFFERLEN); - return tmp - prinst->stringtable; -} - -void PF_InitTempStrings(progfuncs_t *prinst) -{ - if (pr_tempstringcount.value > 0 && pr_tempstringcount.value < 2) - pr_tempstringcount.value = 2; - if (pr_tempstringsize.value < 256) - pr_tempstringsize.value = 256; - pr_tempstringcount.flags |= CVAR_NOSET; - pr_tempstringsize.flags |= CVAR_NOSET; - - if (pr_tempstringcount.value >= 2) - prinst->tempstringbase = prinst->AddString(prinst, "", MAXTEMPBUFFERLEN*MAX_TEMPSTRS); - else - prinst->tempstringbase = 0; - prinst->tempstringnum = 0; -} - -void PF_ftos (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float v; - char pr_string_temp[64]; - v = G_FLOAT(OFS_PARM0); - - if (v == (int)v) - sprintf (pr_string_temp, "%d",(int)v); - else if (pr_brokenfloatconvert.value) - sprintf (pr_string_temp, "%5.1f",v); - else - Q_ftoa (pr_string_temp, v); - RETURN_TSTRING(pr_string_temp); -} - -void PF_fabs (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float v; - v = G_FLOAT(OFS_PARM0); - G_FLOAT(OFS_RETURN) = fabs(v); -} - -void PF_vtos (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char pr_string_temp[64]; - sprintf (pr_string_temp, "'%5.1f %5.1f %5.1f'", G_VECTOR(OFS_PARM0)[0], G_VECTOR(OFS_PARM0)[1], G_VECTOR(OFS_PARM0)[2]); - PR_TempString(prinst, pr_string_temp); - RETURN_TSTRING(pr_string_temp); -} - -void PF_Spawn (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - struct edict_s *ed; - ed = ED_Alloc(prinst); - RETURN_EDICT(prinst, ed); -} - void PF_spawn_temp (progfuncs_t *prinst, struct globalvars_s *pr_globals) { edict_t *ed; @@ -3705,41 +3117,7 @@ void PF_Remove (progfuncs_t *prinst, struct globalvars_s *pr_globals) } -// entity (entity start, .string field, string match) find = #5; -void PF_FindString (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int e; - int f; - char *s; - string_t t; - edict_t *ed; - e = G_EDICTNUM(prinst, OFS_PARM0); - f = G_INT(OFS_PARM1)+prinst->fieldadjust; - s = PR_GetStringOfs(prinst, OFS_PARM2); - if (!s) - { - PR_BIError (prinst, "PF_FindString: bad search string"); - return; - } - - for (e++ ; e < *prinst->parms->sv_num_edicts ; e++) - { - ed = EDICT_NUM(prinst, e); - if (ed->isfree) - continue; - t = ((string_t *)ed->v)[f]; - if (!t) - continue; - if (!strcmp(PR_GetString(prinst, t),s)) - { - RETURN_EDICT(prinst, ed); - return; - } - } - - RETURN_EDICT(prinst, *prinst->parms->sv_edicts); -} /* void PR_CheckEmptyString (char *s) { @@ -3911,7 +3289,7 @@ void PF_WeapIndex (progfuncs_t *prinst, struct globalvars_s *pr_globals) } -void PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals) +void PF_svcoredump (progfuncs_t *prinst, struct globalvars_s *pr_globals) { int size = 1024*1024*8; char *buffer = BZ_Malloc(size); @@ -3920,26 +3298,6 @@ void PF_coredump (progfuncs_t *prinst, struct globalvars_s *pr_globals) BZ_Free(buffer); } -void PF_traceon (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - (*prinst->pr_trace) = true; -} - -void PF_traceoff (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - (*prinst->pr_trace) = false; -} - -void PF_eprint (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int size = 1024*1024; - char *buffer = BZ_Malloc(size); - char *buf; - buf = prinst->saveent(prinst, buffer, &size, G_EDICT(prinst, OFS_PARM0)); - Con_Printf("Entity %i:\n%s\n", G_EDICTNUM(prinst, OFS_PARM0), buf); - BZ_Free(buffer); -} - /* =============== PF_walkmove @@ -4170,25 +3528,6 @@ void PF_lightstylestatic (progfuncs_t *prinst, struct globalvars_s *pr_globals) PF_applylightstyle(style, val, col); } -void PF_rint (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - float f; - f = G_FLOAT(OFS_PARM0); - if (f > 0) - G_FLOAT(OFS_RETURN) = (int)(f + 0.5); - else - G_FLOAT(OFS_RETURN) = (int)(f - 0.5); -} -void PF_floor (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = floor(G_FLOAT(OFS_PARM0)); -} -void PF_ceil (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = ceil(G_FLOAT(OFS_PARM0)); -} - - /* ============= PF_checkbottom @@ -4231,41 +3570,6 @@ void PF_pointcontents (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = Q1CONTENTS_EMPTY; } -/* -============= -PF_nextent - -entity nextent(entity) -============= -*/ -void PF_nextent (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i; - edict_t *ent; - - i = G_EDICTNUM(prinst, OFS_PARM0); - while (1) - { - i++; - if (i == *prinst->parms->sv_num_edicts) - { - RETURN_EDICT(prinst, *prinst->parms->sv_edicts); - return; - } -/* if (i <= MAX_CLIENTS) - { - if (!svs.clients[i-1].state) - continue; - }*/ - ent = EDICT_NUM(prinst, i); - if (!ent->isfree) - { - RETURN_EDICT(prinst, ent); - return; - } - } -} - /* ============= PF_aim @@ -5351,40 +4655,6 @@ void PF_infokey (progfuncs_t *prinst, struct globalvars_s *pr_globals) G_INT(OFS_RETURN) = PR_TempString(prinst, value); } -/* -============== -PF_stof - -float(string s) stof -============== -*/ -void PF_stof (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *s; - - s = PR_GetStringOfs(prinst, OFS_PARM0); - - G_FLOAT(OFS_RETURN) = atof(s); -} - -void PF_Sin (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = sin(G_FLOAT(OFS_PARM0)); -} -void PF_Cos (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = cos(G_FLOAT(OFS_PARM0)); -} -void PF_Sqrt (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = sqrt(G_FLOAT(OFS_PARM0)); -} -void PF_pow (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = pow(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); -} - - /* ============== @@ -5418,7 +4688,10 @@ qboolean printedheader = false; { if (!printedheader) { - Con_Printf("\nMod forgot to ensure support for builtin %i\nPossible builtins:\n", prinst->lastcalledbuiltinnumber); + Con_Printf( "\n" + "Mod forgot to ensure support for builtin %i\n" + "Please consult the extensionlist_ssqc command.\n" + "Possible builtins:\n", prinst->lastcalledbuiltinnumber); printedheader = true; } Con_Printf("%s\n", BuiltinList[i].name); @@ -5431,7 +4704,7 @@ qboolean printedheader = false; prinst->RunError(prinst, "\nBuiltin %i not implemented.\nMods designed for mvdsv may need pr_imitatemvdsv to be enabled.", prinst->lastcalledbuiltinnumber); else prinst->RunError(prinst, "\nBuiltin %i not implemented.\nMod is not compatible.", prinst->lastcalledbuiltinnumber); - PR_BIError (prinst, "bulitin not implemented"); + PR_BIError (prinst, "builtin not implemented"); } void PF_Ignore(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -5477,38 +4750,6 @@ void PF_newstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) //mvdsv RETURN_SSTRING(s+8); } -void PF_dupstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) //frik_file -{ - char *s, *in; - int len; - in = PF_VarString(prinst, 0, pr_globals); - len = strlen(in)+1; - s = Z_TagMalloc(len+8, Z_QC_TAG); - ((int *)s)[0] = PRSTR; - ((int *)s)[1] = len; - strcpy(s+8, in); - RETURN_SSTRING(s+8); -} - -void PF_forgetstring(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *s=PR_GetStringOfs(prinst, OFS_PARM0); - s-=8; - if (((int *)s)[0] != PRSTR) - { - Con_Printf("QC tried to free a non allocated string: "); - Con_Printf("%s\n", s+8); //two prints, so that logged prints ensure the first is written. - (*prinst->pr_trace) = 1; - PR_StackTrace(prinst); - return; - } - ((int *)s)[0] = 0xabcd1234; - Z_TagFree(s); -} -void PF_strlen(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - G_FLOAT(OFS_RETURN) = strlen(PR_GetStringOfs(prinst, OFS_PARM0)); -} void PF_strcatp(progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -5587,766 +4828,16 @@ void PF_chat (progfuncs_t *prinst, struct globalvars_s *pr_globals) -//FRIK_FILE extensions. -//returns a section of a string as a tempstring -void PF_substring (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i, start, length; - char *s; - char string[4096]; - s = PR_GetStringOfs(prinst, OFS_PARM0); - start = G_FLOAT(OFS_PARM1); - length = G_FLOAT(OFS_PARM2); - if (start < 0) - start = strlen(s)-start; - if (length < 0) - length = strlen(s)-start+(length+1); - if (start >= strlen(s) || length<=0 || !*s) - { - RETURN_TSTRING(""); - return; - } - if (length >= MAXTEMPBUFFERLEN) - length = MAXTEMPBUFFERLEN-1; - for (i = 0; i < start && *s; i++, s++) - ; - for (i = 0; *s && i < length; i++, s++) - string[i] = *s; - string[i] = 0; - RETURN_TSTRING(string); -} - - -//vector(string s) stov = #117 -//returns vector value from a string -void PF_stov (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i; - char *s; - float *out; - - s = PF_VarString(prinst, 0, pr_globals); - out = G_VECTOR(OFS_RETURN); - out[0] = out[1] = out[2] = 0; - - if (*s == '\'') - s++; - - for (i = 0; i < 3; i++) - { - while (*s == ' ' || *s == '\t') - s++; - out[i] = atof (s); - if (!out[i] && *s != '-' && *s != '+' && (*s < '0' || *s > '9')) - break; // not a number - while (*s && *s != ' ' && *s !='\t' && *s != '\'') - s++; - if (*s == '\'') - break; - } -} - - - -//FTE_STRINGS -//strstr, without generating a new string. Use in conjunction with FRIK_FILE's substring for more similar strstr. -void PF_strstrofs (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *instr = PR_GetStringOfs(prinst, OFS_PARM0); - char *match = PR_GetStringOfs(prinst, OFS_PARM1); - - int firstofs = (*prinst->callargc>2)?G_FLOAT(OFS_PARM2):0; - - if (firstofs && (firstofs < 0 || firstofs > strlen(instr))) - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - - match = strstr(instr+firstofs, match); - if (!match) - G_FLOAT(OFS_RETURN) = -1; - else - G_FLOAT(OFS_RETURN) = match - instr; -} - -//FTE_STRINGS -//returns character at position X -void PF_str2chr (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *instr = PR_GetStringOfs(prinst, OFS_PARM0); - int ofs = (*prinst->callargc>1)?G_FLOAT(OFS_PARM1):0; - - if (ofs < 0) - ofs = strlen(instr)+ofs; - - if (ofs && (ofs < 0 || ofs > strlen(instr))) - G_FLOAT(OFS_RETURN) = '\0'; - else - G_FLOAT(OFS_RETURN) = instr[ofs]; -} - -//FTE_STRINGS -//returns a string containing one character per parameter (up to the qc max params of 8). -void PF_chr2str (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i; - - char string[16]; - for (i = 0; i < *prinst->callargc; i++) - string[i] = G_FLOAT(OFS_PARM0 + i*3); - string[i] = '\0'; - RETURN_TSTRING(string); -} -static int chrconv_number(int i, int base, int conv) -{ - i -= base; - switch (conv) - { - default: - case 5: - case 6: - case 0: - break; - case 1: - base = '0'; - break; - case 2: - base = '0'+128; - break; - case 3: - base = '0'-30; - break; - case 4: - base = '0'+128-30; - break; - } - return i + base; -} -static int chrconv_punct(int i, int base, int conv) -{ - i -= base; - switch (conv) - { - default: - case 0: - break; - case 1: - base = 0; - break; - case 2: - base = 128; - break; - } - return i + base; -} - -static int chrchar_alpha(int i, int basec, int baset, int convc, int convt, int charnum) -{ - //convert case and colour seperatly... - - i -= baset + basec; - switch (convt) - { - default: - case 0: - break; - case 1: - baset = 0; - break; - case 2: - baset = 128; - break; - - case 5: - case 6: - baset = 128*((charnum&1) == (convt-5)); - break; - } - - switch (convc) - { - default: - case 0: - break; - case 1: - basec = 'a'; - break; - case 2: - basec = 'A'; - break; - } - return i + basec + baset; -} -//FTE_STRINGS -//bulk convert a string. change case or colouring. -void PF_strconv (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int ccase = G_FLOAT(OFS_PARM0); //0 same, 1 lower, 2 upper - int redalpha = G_FLOAT(OFS_PARM1); //0 same, 1 white, 2 red, 5 alternate, 6 alternate-alternate - int rednum = G_FLOAT(OFS_PARM2); //0 same, 1 white, 2 red, 3 redspecial, 4 whitespecial, 5 alternate, 6 alternate-alternate - unsigned char *string = PF_VarString(prinst, 3, pr_globals); - int len = strlen(string); - int i; - unsigned char resbuf[8192]; - unsigned char *result = resbuf; - - if (len >= MAXTEMPBUFFERLEN) - len = MAXTEMPBUFFERLEN-1; - - for (i = 0; i < len; i++, string++, result++) //should this be done backwards? - { - if (*string >= '0' && *string <= '9') //normal numbers... - *result = chrconv_number(*string, '0', rednum); - else if (*string >= '0'+128 && *string <= '9'+128) - *result = chrconv_number(*string, '0'+128, rednum); - else if (*string >= '0'+128-30 && *string <= '9'+128-30) - *result = chrconv_number(*string, '0'+128-30, rednum); - else if (*string >= '0'-30 && *string <= '9'-30) - *result = chrconv_number(*string, '0'-30, rednum); - - else if (*string >= 'a' && *string <= 'z') //normal numbers... - *result = chrchar_alpha(*string, 'a', 0, ccase, redalpha, i); - else if (*string >= 'A' && *string <= 'Z') //normal numbers... - *result = chrchar_alpha(*string, 'A', 0, ccase, redalpha, i); - else if (*string >= 'a'+128 && *string <= 'z'+128) //normal numbers... - *result = chrchar_alpha(*string, 'a', 128, ccase, redalpha, i); - else if (*string >= 'A'+128 && *string <= 'Z'+128) //normal numbers... - *result = chrchar_alpha(*string, 'A', 128, ccase, redalpha, i); - - else if ((*string & 127) < 16 || !redalpha) //special chars.. - *result = *string; - else if (*string < 128) - *result = chrconv_punct(*string, 0, redalpha); - else - *result = chrconv_punct(*string, 128, redalpha); - } - *result = '\0'; - - RETURN_TSTRING(((char*)resbuf)); -} - -//FTE_STRINGS -//C style strncmp (compare first n characters - case sensative. Note that there is no strcmp provided) -void PF_strncmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *a = PR_GetStringOfs(prinst, OFS_PARM0); - char *b = PR_GetStringOfs(prinst, OFS_PARM1); - float len = G_FLOAT(OFS_PARM2); - - G_FLOAT(OFS_RETURN) = strncmp(a, b, len); -} - -//FTE_STRINGS -//C style strcasecmp (case insensative string compare) -void PF_strcasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *a = PR_GetStringOfs(prinst, OFS_PARM0); - char *b = PR_GetStringOfs(prinst, OFS_PARM1); - - G_FLOAT(OFS_RETURN) = stricmp(a, b); -} - -//FTE_STRINGS -//C style strncasecmp (compare first n characters - case insensative) -void PF_strncasecmp (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *a = PR_GetStringOfs(prinst, OFS_PARM0); - char *b = PR_GetStringOfs(prinst, OFS_PARM1); - float len = G_FLOAT(OFS_PARM2); - - G_FLOAT(OFS_RETURN) = strnicmp(a, b, len); -} - -//uses qw style \key\value strings -void PF_infoadd (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *info = PR_GetStringOfs(prinst, OFS_PARM0); - char *key = PR_GetStringOfs(prinst, OFS_PARM1); - char *value = PF_VarString(prinst, 2, pr_globals); - char temp[8192]; - - Q_strncpyz(temp, info, MAXTEMPBUFFERLEN); - - Info_SetValueForStarKey(temp, key, value, MAXTEMPBUFFERLEN); - - RETURN_TSTRING(temp); -} - -//uses qw style \key\value strings -void PF_infoget (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *info = PR_GetStringOfs(prinst, OFS_PARM0); - char *key = PR_GetStringOfs(prinst, OFS_PARM1); - - key = Info_ValueForKey(info, key); - - RETURN_TSTRING(key); -} - -//DP_QC_STRINGCOLORFUNCTIONS -// #476 float(string s) strlennocol - returns how many characters are in a string, minus color codes -void PF_strlennocol (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *in = PR_GetStringOfs(prinst, OFS_PARM0); - G_FLOAT(OFS_RETURN) = COM_FunStringLength(in); -} - -//DP_QC_STRINGCOLORFUNCTIONS -// string (string s) strdecolorize - returns the passed in string with color codes stripped -void PF_strdecolorize (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *in = PR_GetStringOfs(prinst, OFS_PARM0); - char result[8192]; - unsigned long flagged[8192]; - COM_ParseFunString(in, flagged, sizeof(flagged)/sizeof(flagged[0])); - COM_DeFunString(flagged, result, sizeof(result), true); - - RETURN_TSTRING(result); -} - - -//back to frik_file support. - - - -#define MAX_QC_FILES 8 - -#define FIRST_QC_FILE_INDEX 1000 - -typedef struct { - char name[256]; - char *data; - int bufferlen; - int len; - int ofs; - int accessmode; - progfuncs_t *prinst; -} pf_fopen_files_t; -pf_fopen_files_t pf_fopen_files[MAX_QC_FILES]; - -void PF_fopen (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char *name = PR_GetStringOfs(prinst, OFS_PARM0); - int fmode = G_FLOAT(OFS_PARM1); - int i; - - for (i = 0; i < MAX_QC_FILES; i++) - if (!pf_fopen_files[i].data) - break; - - if (i == MAX_QC_FILES) //too many already open - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - - if (name[1] == ':' || //dos filename absolute path specified - reject. - strchr(name, '\\') || *name == '/' || //absolute path was given - reject - strstr(name, "..")) //someone tried to be cleaver. - { - G_FLOAT(OFS_RETURN) = -1; - return; - } - - Q_strncpyz(pf_fopen_files[i].name, va("data/%s", name), sizeof(pf_fopen_files[i].name)); - - pf_fopen_files[i].accessmode = fmode; - switch (fmode) - { - case 0: //read - pf_fopen_files[i].data = COM_LoadMallocFile(pf_fopen_files[i].name); - if (!pf_fopen_files[i].data) - { - Q_strncpyz(pf_fopen_files[i].name, name, sizeof(pf_fopen_files[i].name)); - pf_fopen_files[i].data = COM_LoadMallocFile(pf_fopen_files[i].name); - } - - if (pf_fopen_files[i].data) - { - G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; - pf_fopen_files[i].prinst = prinst; - } - else - G_FLOAT(OFS_RETURN) = -1; - - pf_fopen_files[i].bufferlen = pf_fopen_files[i].len = com_filesize; - pf_fopen_files[i].ofs = 0; - break; - case 1: //append - pf_fopen_files[i].data = COM_LoadMallocFile(pf_fopen_files[i].name); - pf_fopen_files[i].ofs = pf_fopen_files[i].bufferlen = pf_fopen_files[i].len = com_filesize; - if (pf_fopen_files[i].data) - { - G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; - pf_fopen_files[i].prinst = prinst; - break; - } - //file didn't exist - fall through - case 2: //write - pf_fopen_files[i].bufferlen = 8192; - pf_fopen_files[i].data = BZ_Malloc(pf_fopen_files[i].bufferlen); - pf_fopen_files[i].len = 0; - pf_fopen_files[i].ofs = 0; - G_FLOAT(OFS_RETURN) = i + FIRST_QC_FILE_INDEX; - pf_fopen_files[i].prinst = prinst; - break; - default: //bad - G_FLOAT(OFS_RETURN) = -1; - break; - } -} - -void PF_fclose_i (int fnum) -{ - if (fnum < 0 || fnum >= MAX_QC_FILES) - { - Con_Printf("PF_fclose: File out of range\n"); - return; //out of range - } - - if (!pf_fopen_files[fnum].data) - { - Con_Printf("PF_fclose: File is not open\n"); - return; //not open - } - - switch(pf_fopen_files[fnum].accessmode) - { - case 0: - BZ_Free(pf_fopen_files[fnum].data); - break; - case 1: - case 2: - COM_WriteFile(pf_fopen_files[fnum].name, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); - BZ_Free(pf_fopen_files[fnum].data); - break; - } - pf_fopen_files[fnum].data = NULL; - pf_fopen_files[fnum].prinst = NULL; -} - -void PF_fclose (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int fnum = G_FLOAT(OFS_PARM0)-FIRST_QC_FILE_INDEX; - - if (fnum < 0 || fnum >= MAX_QC_FILES) - { - Con_Printf("PF_fclose: File out of range\n"); - return; //out of range - } - - if (pf_fopen_files[fnum].prinst != prinst) - { - Con_Printf("PF_fclose: File is from wrong instance\n"); - return; //this just isn't ours. - } - - PF_fclose_i(fnum); -} - -void PF_fgets (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char c, *s, *o, *max; - int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; - char pr_string_temp[4096]; - - *pr_string_temp = '\0'; - G_INT(OFS_RETURN) = 0; //EOF - if (fnum < 0 || fnum >= MAX_QC_FILES) - { - PR_BIError(prinst, "PF_fgets: File out of range\n"); - return; //out of range - } - - if (!pf_fopen_files[fnum].data) - { - PR_BIError(prinst, "PF_fgets: File is not open\n"); - return; //not open - } - - if (pf_fopen_files[fnum].prinst != prinst) - { - PR_BIError(prinst, "PF_fgets: File is from wrong instance\n"); - return; //this just isn't ours. - } - - //read up to the next \n, ignoring any \rs. - o = pr_string_temp; - max = o + MAXTEMPBUFFERLEN-1; - s = pf_fopen_files[fnum].data+pf_fopen_files[fnum].ofs; - while(*s) - { - c = *s++; - if (c == '\n') - break; - if (c == '\r') - continue; - - if (o == max) - break; - *o++ = c; - } - *o = '\0'; - - pf_fopen_files[fnum].ofs = s - pf_fopen_files[fnum].data; - - if (!pr_string_temp[0] && !*s) - G_INT(OFS_RETURN) = 0; //EOF - else - RETURN_TSTRING(pr_string_temp); -} - -void PF_fputs (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int fnum = G_FLOAT(OFS_PARM0) - FIRST_QC_FILE_INDEX; - char *msg = PF_VarString(prinst, 1, pr_globals); - int len = strlen(msg); - if (fnum < 0 || fnum >= MAX_QC_FILES) - { - Con_Printf("PF_fgets: File out of range\n"); - return; //out of range - } - - if (!pf_fopen_files[fnum].data) - { - Con_Printf("PF_fgets: File is not open\n"); - return; //not open - } - - if (pf_fopen_files[fnum].prinst != prinst) - { - Con_Printf("PF_fgets: File is from wrong instance\n"); - return; //this just isn't ours. - } - - if (pf_fopen_files[fnum].bufferlen < pf_fopen_files[fnum].ofs + len) - { - char *newbuf; - pf_fopen_files[fnum].bufferlen = pf_fopen_files[fnum].bufferlen*2 + len; - newbuf = BZF_Malloc(pf_fopen_files[fnum].bufferlen); - memcpy(newbuf, pf_fopen_files[fnum].data, pf_fopen_files[fnum].len); - BZ_Free(pf_fopen_files[fnum].data); - pf_fopen_files[fnum].data = newbuf; - } - - memcpy(pf_fopen_files[fnum].data + pf_fopen_files[fnum].ofs, msg, len); - if (pf_fopen_files[fnum].len < pf_fopen_files[fnum].ofs + len) - pf_fopen_files[fnum].len = pf_fopen_files[fnum].ofs + len; - pf_fopen_files[fnum].ofs+=len; -} - -void PF_fcloseall (progfuncs_t *prinst) -{ - int i; - for (i = 0; i < MAX_QC_FILES; i++) - { - if (pf_fopen_files[i].prinst != prinst) - continue; - PF_fclose_i(i); - } -} - - - -typedef struct prvmsearch_s { - int handle; - progfuncs_t *fromprogs; //share across menu/server - int entries; - char **names; - int *sizes; - - struct prvmsearch_s *next; -} prvmsearch_t; -prvmsearch_t *prvmsearches; -int prvm_nextsearchhandle; - -void search_close (progfuncs_t *prinst, int handle) -{ - int i; - prvmsearch_t *prev, *s; - - prev = NULL; - for (s = prvmsearches; s; ) - { - if (s->handle == handle) - { //close it down. - if (s->fromprogs != prinst) - { - Con_Printf("Handle wasn't valid with that progs\n"); - return; - } - if (prev) - prev->next = s->next; - else - prvmsearches = s->next; - - for (i = 0; i < s->entries; i++) - { - BZ_Free(s->names[i]); - } - BZ_Free(s->names); - BZ_Free(s->sizes); - BZ_Free(s); - - return; - } - - prev = s; - s = s->next; - } -} -//a progs was closed... hunt down it's searches, and warn about any searches left open. -void search_close_progs(progfuncs_t *prinst, qboolean complain) -{ - int i; - prvmsearch_t *prev, *s; - - prev = NULL; - for (s = prvmsearches; s; ) - { - if (s->fromprogs == prinst) - { //close it down. - - if (complain) - Con_Printf("Warning: Progs search was still active\n"); - if (prev) - prev->next = s->next; - else - prvmsearches = s->next; - - for (i = 0; i < s->entries; i++) - { - BZ_Free(s->names[i]); - } - BZ_Free(s->names); - BZ_Free(s->sizes); - BZ_Free(s); - - if (prev) - s = prev->next; - else - s = prvmsearches; - continue; - } - - prev = s; - s = s->next; - } - - if (!prvmsearches) - prvm_nextsearchhandle = 0; //might as well. -} - -int search_enumerate(char *name, int fsize, void *parm) -{ - prvmsearch_t *s = parm; - - s->names = BZ_Realloc(s->names, ((s->entries+64)&~63) * sizeof(char*)); - s->sizes = BZ_Realloc(s->sizes, ((s->entries+64)&~63) * sizeof(int)); - s->names[s->entries] = BZ_Malloc(strlen(name)+1); - strcpy(s->names[s->entries], name); - s->sizes[s->entries] = fsize; - - s->entries++; - return true; -} - -//float search_begin(string pattern, float caseinsensitive, float quiet) = #74; -void PF_search_begin (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ //< 0 for error, > 0 for handle. - char *pattern = PR_GetStringOfs(prinst, OFS_PARM0); -// qboolean caseinsensative = G_FLOAT(OFS_PARM1); -// qboolean quiet = G_FLOAT(OFS_PARM2); - prvmsearch_t *s; - - s = Z_Malloc(sizeof(*s)); - s->fromprogs = prinst; - s->handle = prvm_nextsearchhandle++; - - COM_EnumerateFiles(pattern, search_enumerate, s); - - if (s->entries==0) - { - BZ_Free(s); - G_FLOAT(OFS_RETURN) = -1; - return; - } - s->next = prvmsearches; - prvmsearches = s; - G_FLOAT(OFS_RETURN) = s->handle; -} -//void search_end(float handle) = #75; -void PF_search_end (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int handle = G_FLOAT(OFS_PARM0); - search_close(prinst, handle); -} -//float search_getsize(float handle) = #76; -void PF_search_getsize (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int handle = G_FLOAT(OFS_PARM0); - prvmsearch_t *s; - G_FLOAT(OFS_RETURN) = -1; - for (s = prvmsearches; s; s = s->next) - { - if (s->handle == handle) - { //close it down. - if (s->fromprogs != prinst) - { - Con_Printf("Handle wasn't valid with that progs\n"); - return; - } - - G_FLOAT(OFS_RETURN) = s->entries; - return; - } - } -} -//string search_getfilename(float handle, float num) = #77; -void PF_search_getfilename (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int handle = G_FLOAT(OFS_PARM0); - int num = G_FLOAT(OFS_PARM1); - prvmsearch_t *s; - G_INT(OFS_RETURN) = 0; - - for (s = prvmsearches; s; s = s->next) - { - if (s->handle == handle) - { //close it down. - if (s->fromprogs != prinst) - { - Con_Printf("Search handle wasn't valid with that progs\n"); - return; - } - - if (num < 0 || num >= s->entries) - return; - RETURN_TSTRING(s->names[num]); - return; - } - } - - Con_Printf("Search handle wasn't valid\n"); -} - -//closes filesystem type stuff for when a progs has stopped needing it. -void PR_fclose_progs (progfuncs_t *prinst) -{ - PF_fcloseall(prinst); - search_close_progs(prinst, true); -} // FTE SQL functions #ifdef SQL @@ -7356,203 +5847,6 @@ void SQL_DeInit(void) - - - - - -//the lh extension system asks for a name for the extension. -//the ebfs version is a function that returns a builtin number. -//thus lh's system requires various builtins to exist at specific numbers. -typedef struct lh_extension_s { - char *name; - int numbuiltins; - qboolean *enabled; - char *builtins[18]; //extend freely -} lh_extension_t; - - - -lh_extension_t QSG_Extensions[] = { - {"BX_COLOREDTEXT"}, - {"DP_CON_SET"}, -#ifndef SERVERONLY - {"DP_CON_SETA"}, //because the server doesn't write configs. -#endif - {"DP_EF_BLUE"}, //hah!! This is QuakeWorld!!! - {"DP_EF_FULLBRIGHT"}, //Rerouted to hexen2 support. - {"DP_EF_NODRAW"}, //implemented by sending it with no modelindex - {"DP_EF_RED"}, - {"DP_ENT_COLORMOD"}, - {"DP_ENT_EXTERIORMODELTOCLIENT"}, - //only in dp6 currently {"DP_ENT_GLOW"}, - {"DP_ENT_VIEWMODEL"}, - {"DP_GFX_QUAKE3MODELTAGS"}, - {"DP_GFX_SKINFILES"}, - {"DP_GFX_SKYBOX"}, //according to the spec. :) - {"DP_HALFLIFE_MAP_CVAR"}, - //to an extend {"DP_HALFLIFE_SPRITE"}, - {"DP_INPUTBUTTONS"}, - {"DP_LITSUPPORT"}, - {"DP_MONSTERWALK"}, - {"DP_MOVETYPEBOUNCEMISSILE"}, //I added the code for hexen2 support. - {"DP_MOVETYPEFOLLOW"}, - {"DP_SV_BOTCLIENT", 2, NULL, {"spawnclient", "clienttype"}}, - {"DP_QC_CHANGEPITCH", 1, NULL, {"changepitch"}}, - {"DP_QC_COPYENTITY", 1, NULL, {"copyentity"}}, - {"DP_QC_CVAR_STRING", 1, NULL, {"dp_cvar_string"}}, //448 builtin. - {"DP_QC_ETOS", 1, NULL, {"etos"}}, - {"DP_QC_FINDCHAIN", 1, NULL, {"findchain"}}, - {"DP_QC_FINDCHAINFLOAT", 1, NULL, {"findchainfloat"}}, - {"DP_QC_FINDFLAGS", 1, NULL, {"findflags"}}, - {"DP_QC_FINDCHAINFLAGS", 1, NULL, {"findchainflags"}}, - {"DP_QC_FINDFLOAT", 1, NULL, {"findfloat"}}, - {"DP_QC_FS_SEARCH", 4, NULL, {"search_begin", "search_end", "search_getsize", "search_getfilename"}}, - {"DP_QC_MINMAXBOUND", 3, NULL, {"min", "max", "bound"}}, - {"DP_QC_MULTIPLETEMPSTRINGS"}, - {"DP_QC_RANDOMVEC", 1, NULL, {"randomvec"}}, - {"DP_QC_SINCOSSQRTPOW", 4, NULL, {"sin", "cos", "sqrt", "pow"}}, - {"DP_QC_STRINGCOLORFUNCTIONS", 2, NULL, {"strlennocol", "strdecolorize"}}, - {"DP_QC_UNLIMITEDTEMPSTRINGS"}, - {"DP_QC_TRACEBOX", 1, NULL, {"tracebox"}}, - {"DP_QC_TRACETOSS"}, - {"DP_QC_TRACE_MOVETYPE_HITMODEL"}, - {"DP_QC_TRACE_MOVETYPE_WORLDONLY"}, - {"DP_QC_TRACE_MOVETYPES"}, //this one is just a lame excuse to add annother extension... - {"DP_QC_VECTORVECTORS", 1, NULL, {"vectorvectors"}}, - {"DP_QUAKE2_MODEL"}, - {"DP_QUAKE2_SPRITE"}, - {"DP_QUAKE3_MODEL"}, - {"DP_REGISTERCVAR", 1, NULL, {"registercvar"}}, - {"DP_SND_STEREOWAV"}, - {"DP_SND_OGGVORBIS"}, - {"DP_SOLIDCORPSE"}, - {"DP_SPRITE32"}, //hmm... is it legal to advertise this one? - {"DP_SV_CLIENTCOLORS"}, - {"DP_SV_CLIENTNAME"}, - {"DP_SV_DRAWONLYTOCLIENT"}, - {"DP_SV_DROPCLIENT", 1, NULL, {"dropclient"}}, - {"DP_SV_EFFECT", 1, NULL, {"effect"}}, - {"DP_SV_EXTERIORMODELFORCLIENT"}, - {"DP_SV_NODRAWTOCLIENT"}, //I prefer my older system. Guess I might as well remove that older system at some point. - {"DP_SV_PLAYERPHYSICS"}, - {"DP_SV_PRECACHEANYTIME"}, - {"DP_SV_SETCOLOR"}, - {"DP_SV_WRITEUNTERMINATEDSTRING", 1, NULL, {"WriteUnterminatedString"}}, - {"DP_TE_BLOOD", 1, NULL, {"te_blood"}}, - {"DP_TE_BLOODSHOWER", 1, NULL, {"te_bloodshower"}}, - {"DP_TE_CUSTOMFLASH", 1, NULL, {"te_customflash"}}, - {"DP_TE_EXPLOSIONRGB"}, - //flamejet - {"DP_TE_PARTICLECUBE", 1, NULL, {"te_particlecube"}}, - //particlerain - //particlesnow - {"DP_TE_PLASMABURN", 1, NULL, {"te_plasmaburn"}}, - {"DP_TE_QUADEFFECTS1"}, - {"DP_TE_SMALLFLASH", 1, NULL, {"te_smallflash"}}, - {"DP_TE_SPARK", 1, NULL, {"te_spark"}}, - {"DP_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", "te_teleport", "te_explosion2", "te_lightning1", "te_lightning2", "te_lightning3", "te_beam"}}, - {"DP_VIEWZOOM"}, - {"EXT_BITSHIFT", 1, NULL, {"bitshift"}}, - {"EXT_DIMENSION_VISIBILITY"}, - {"EXT_DIMENSION_PHYSICS"}, - {"EXT_DIMENSION_GHOST"}, - {"FRIK_FILE", 11, NULL, {"stof", "fopen","fclose","fgets","fputs","strlen","strcat","substring","stov","strzone","strunzone"}}, - {"FTE_CALLTIMEOFDAY", 1, NULL, {"calltimeofday"}}, - {"FTE_ENT_UNIQUESPAWNID"}, - {"FTE_EXTENDEDTEXTCODES"}, - {"FTE_FORCEINFOKEY", 1, NULL, {"forceinfokey"}}, - {"FTE_GFX_QUAKE3SHADERS"}, - {"FTE_ISBACKBUFFERED", 1, NULL, {"isbackbuffered"}}, -#ifndef NOMEDIA - {"FTE_MEDIA_AVI"}, //playfilm supports avi files. - {"FTE_MEDIA_CIN"}, //playfilm command supports q2 cin files. - {"FTE_MEDIA_ROQ"}, //playfilm command supports q3 roq files -#endif - {"FTE_MULTIPROGS"}, //multiprogs functions are available. - {"FTE_MULTITHREADED", 3, NULL, {"sleep", "fork", "abort"}}, - {"FTE_MVD_PLAYBACK"}, -#ifdef SVCHAT - {"FTE_NPCCHAT", 1, NULL, {"chat"}}, //server looks at chat files. It automagically branches through calling qc functions as requested. -#endif - {"FTE_QC_CHECKPVS", 1, NULL, {"checkpvs"}}, - {"FTE_QC_MATCHCLIENTNAME", 1, NULL, {"matchclientname"}}, - {"FTE_QC_PAUSED"}, - {"FTE_QC_SENDPACKET", 1, NULL, {"sendpacket"}}, - {"FTE_QC_TRACETRIGGER"}, - {"FTE_SOLID_LADDER"}, //part of a worthy hl implementation. Allows a simple trigger to remove effects of gravity (solid 20) - -#ifdef SQL - // serverside SQL functions for managing an SQL database connection - {"FTE_SQL", 9, NULL, {"sqlconnect","sqldisconnect","sqlopenquery","sqlclosequery","sqlreadfield","sqlerror","sqlescape","sqlversion", - "sqlreadfloat"}}, -#endif - //eperimental advanced strings functions. - //reuses the FRIK_FILE builtins (with substring extension) - {"FTE_STRINGS", 16, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone", - "strstrofs", "str2chr", "chr2str", "strconv", "infoadd", "infoget", "strncmp", "strcasecmp", "strncasecmp"}}, - {"FTE_SV_REENTER"}, - {"FTE_TE_STANDARDEFFECTBUILTINS", 14, NULL, {"te_gunshot", "te_spike", "te_superspike", "te_explosion", "te_tarexplosion", "te_wizspike", "te_knightspike", "te_lavasplash", - "te_teleport", "te_lightning1", "te_lightning2", "te_lightning3", "te_lightningblood", "te_bloodqw"}}, - - {"KRIMZON_SV_PARSECLIENTCOMMAND", 3, NULL, {"clientcommand", "tokenize", "argv"}}, //very very similar to the mvdsv system. - {"NEH_CMD_PLAY2"}, - {"NEH_RESTOREGAME"}, - //{"PRYDON_CLIENTCURSOR"}, - {"QSG_CVARSTRING", 1, NULL, {"cvar_string"}}, - {"QW_ENGINE", 1, NULL, {"infokey", "stof", "logfrag"}}, //warning: interpretation of .skin on players can be dodgy, as can some other QW features that differ from NQ. - {"QWE_MVD_RECORD"}, //Quakeworld extended get the credit for this one. (mvdsv) - {"TEI_MD3_MODEL"}, -// {"TQ_RAILTRAIL"}, //treat this as the ZQ style railtrails which the client already supports, okay so the preparse stuff needs strengthening. - {"ZQ_MOVETYPE_FLY"}, - {"ZQ_MOVETYPE_NOCLIP"}, - {"ZQ_MOVETYPE_NONE"}, -// {"ZQ_QC_PARTICLE"}, //particle builtin works in QW ( we don't mimic ZQ fully though) - - - {"ZQ_QC_STRINGS", 7, NULL, {"stof", "strlen","strcat","substring","stov","strzone","strunzone"}} //a trimmed down FRIK_FILE. -}; - -//some of these are overkill yes, but they are all derived from the fteextensions flags and document the underlaying protocol available. -//(which is why there are two lists of extensions here) -//note: not all of these are actually supported. This list mearly reflects the values of the PEXT_ constants. -//Check protocol.h to make sure that the related PEXT is enabled. The engine will only accept if they are actually supported. -lh_extension_t FTE_Protocol_Extensions[] = -{ - {"FTE_PEXT_SETVIEW"}, //nq setview works. - {"DP_ENT_SCALE"}, //entities may be rescaled - {"FTE_PEXT_LIGHTSTYLECOL"}, //lightstyles may have colours. - {"DP_ENT_ALPHA"}, //transparent entites - {"FTE_PEXT_VIEW2"}, //secondary view. - {"FTE_PEXT_BULLETENS"}, //bulleten boards (scrolling text on walls) - {"FTE_PEXT_ZLIBDL"}, //supposed download optimisation (unimportant to qc) - {"FTE_PEXT_LIGHTUPDATES"}, //zap.mdl is sent as a nail packet. - {"FTE_PEXT_FATNESS"}, //entities may be expanded along their vertex normals - {"DP_HALFLIFE_MAP"}, //entitiy can visit a hl bsp - {"FTE_PEXT_TE_BULLET"}, //additional particle effect. Like TE_SPIKE and TE_SUPERSPIKE - {"FTE_PEXT_HULLSIZE"}, //means we can tell a client to go to crouching hull - {"FTE_PEXT_MODELDBL"}, //max of 512 models - {"FTE_PEXT_ENTITYDBL"}, //max of 1024 ents - {"FTE_PEXT_ENTITYDBL2"}, //max of 2048 ents - {"FTE_PEXT_ORIGINDBL"}, //-8k to +8k map size. - {"FTE_PEXT_VWEAP"}, - {"FTE_PEXT_Q2BSP"}, //supports q2 maps. No bugs are apparent. - {"FTE_PEXT_Q3BSP"}, //quake3 bsp support. dp probably has an equivelent, but this is queryable per client. - {"DP_ENT_COLORMOD"}, - {NULL}, //splitscreen - not queryable. - {"FTE_HEXEN2"}, //client can use hexen2 maps. server can use hexen2 progs - {"FTE_PEXT_SPAWNSTATIC"}, //means that static entities can have alpha/scale and anything else the engine supports on normal ents. (Added for >256 models, while still being compatible - previous system failed with -1 skins) - {"FTE_PEXT_CUSTOMTENTS", 2, NULL, {"RegisterTempEnt", "CustomTempEnt"}}, - {"FTE_PEXT_256PACKETENTITIES"}, //client is able to receive unlimited packet entities (server caps itself to 256 to prevent insanity). - {"FTE_PEXT_64PLAYERS"}, - {"TEI_SHOWLMP2", 6, NULL, {"showpic", "hidepic", "movepic", "changepic", "showpicent", "hidepicent"}}, //telejano doesn't actually export the moveent/changeent (we don't want to either cos it would stop frik_file stuff being autoregistered) - {"DP_GFX_QUAKE3MODELTAGS", 1, NULL, {"setattachment"}}, - {"FTE_PK3DOWNLOADS"}, - {"PEXT_CHUNKEDDOWNLOADS"}, - {"EXT_CSQC"} -}; - - int PR_EnableEBFSBuiltin(char *name, int binum) { int i; @@ -7587,13 +5881,13 @@ int PR_EnableEBFSBuiltin(char *name, int binum) lh_extension_t *checkfteextensioncl(int mask, char *name) //true if the cient extension mask matches an extension name { int i; - for (i = 0; i < sizeof(FTE_Protocol_Extensions)/sizeof(lh_extension_t); i++) + for (i = 0; i < 32; i++) { if (mask & (1<numbuiltins; i++) { - if (!PR_EnableEBFSBuiltin(ext->builtins[i], 0)) + if (!PR_EnableEBFSBuiltin(ext->builtinnames[i], 0)) { - Con_Printf("Failed to initialise builtin \"%s\" for extension \"%s\"", ext->builtins[i], s); + Con_Printf("Failed to initialise builtin \"%s\" for extension \"%s\"", ext->builtinnames[i], s); return; //whoops, we failed. } } @@ -7713,28 +6007,6 @@ void PF_ExecuteCommand (progfuncs_t *prinst, struct globalvars_s *pr_globals) / pr_global_struct->self = old_self; pr_global_struct->other = old_other; } -void PF_ArgC (progfuncs_t *prinst, struct globalvars_s *pr_globals) //85 //float() argc; -{ - G_FLOAT(OFS_RETURN) = Cmd_Argc(); -} - -//KRIMZON_SV_PARSECLIENTCOMMAND added these two. -void PF_Tokenize (progfuncs_t *prinst, struct globalvars_s *pr_globals) //84 //void(string str) tokanize; -{ - Cmd_TokenizeString(PR_GetStringOfs(prinst, OFS_PARM0), false, true); - G_FLOAT(OFS_RETURN) = Cmd_Argc(); -} -void PF_ArgV (progfuncs_t *prinst, struct globalvars_s *pr_globals) //86 //string(float num) argv; -{ - int i = G_FLOAT(OFS_PARM0); - if (i < 0) - { - PR_BIError(prinst, "pr_argv with i < 0"); - G_INT(OFS_RETURN) = 0; - return; - } - RETURN_TSTRING(Cmd_Argv(i)); -} /* ================= @@ -7788,70 +6060,7 @@ void PF_substr (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_TSTRING(dest); } -/* -================= -PF_strcat -string strcat(string str1, string str2) -================= -*/ - -void PF_strcat (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char dest[4096]; - char *src = PF_VarString(prinst, 0, pr_globals); - Q_strncpyz(dest, src, MAXTEMPBUFFERLEN); - RETURN_TSTRING(dest); -} - -/* -================= -PF_strpad - -string strpad(float pad, string str1, ...) -================= -*/ - -void PF_strpad (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char destbuf[4096]; - char *dest = destbuf; - int pad = G_FLOAT(OFS_PARM0); - char *src = PF_VarString(prinst, 1, pr_globals); - - if (pad < 0) - { //pad left - pad = -pad - strlen(src); - if (pad>=MAXTEMPBUFFERLEN) - pad = MAXTEMPBUFFERLEN-1; - if (pad < 0) - pad = 0; - - Q_strncpyz(dest+pad, src, MAXTEMPBUFFERLEN-pad); - while(pad--) - { - pad--; - dest[pad] = ' '; - } - } - else - { //pad right - if (pad>=MAXTEMPBUFFERLEN) - pad = MAXTEMPBUFFERLEN-1; - pad -= strlen(src); - if (pad < 0) - pad = 0; - - Q_strncpyz(dest, src, MAXTEMPBUFFERLEN); - dest+=strlen(dest); - - while(pad-->0) - *dest++ = ' '; - *dest = '\0'; - } - - RETURN_TSTRING(destbuf); -} /* ================= @@ -8175,16 +6384,6 @@ static void PF_copyentity (progfuncs_t *prinst, struct globalvars_s *pr_globals) SV_LinkEdict(out, false); } -//EXTENSION: DP_QC_ETOS - -//string(entity ent) etos = #65 -void PF_etos (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - char s[64]; - snprintf (s, sizeof(s), "entity %i", G_EDICTNUM(prinst, OFS_PARM0)); - RETURN_TSTRING(s); -} - //EXTENSION: DP_QC_FINDCHAIN @@ -8280,85 +6479,6 @@ void PF_findchainflags (progfuncs_t *prinst, struct globalvars_s *pr_globals) RETURN_EDICT(prinst, chain); } -//EXTENSION: DP_QC_FINDFLOAT - -//entity(entity start, float fld, float match) findfloat = #98 -void PF_FindFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int e, f; - int s; - edict_t *ed; - - if (*prinst->callargc != 3) //I can hate mvdsv if I want to. - { - PR_BIError(prinst, "PF_FindFloat (#98): callargc != 3\nDid you mean to set pr_imitatemvdsv to 1?"); - return; - } - - e = G_EDICTNUM(prinst, OFS_PARM0); - f = G_INT(OFS_PARM1)+prinst->fieldadjust; - s = G_INT(OFS_PARM2); - - for (e++; e < *prinst->parms->sv_num_edicts; e++) - { - ed = EDICT_NUM(prinst, e); - if (ed->isfree) - continue; - if (((int *)ed->v)[f] == s) - { - RETURN_EDICT(prinst, ed); - return; - } - } - - RETURN_EDICT(prinst, *prinst->parms->sv_edicts); -} - -//EXTENSION: DP_QC_FINDFLAGS - -//entity(entity start, float fld, float match) findflags = #449 -void PF_FindFlags (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int e, f; - int s; - edict_t *ed; - - e = G_EDICTNUM(prinst, OFS_PARM0); - f = G_INT(OFS_PARM1)+prinst->fieldadjust; - s = G_FLOAT(OFS_PARM2); - - for (e++; e < *prinst->parms->sv_num_edicts; e++) - { - ed = EDICT_NUM(prinst, e); - if (ed->isfree) - continue; - if ((int)((float *)ed->v)[f] & s) - { - RETURN_EDICT(prinst, ed); - return; - } - } - - RETURN_EDICT(prinst, *prinst->parms->sv_edicts); -} - - - -//EXTENSION: DP_QC_RANDOMVEC - -//vector() randomvec = #91 -void PF_randomvector (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - vec3_t temp; - do - { - temp[0] = (rand() & 32767) * (2.0 / 32767.0) - 1.0; - temp[1] = (rand() & 32767) * (2.0 / 32767.0) - 1.0; - temp[2] = (rand() & 32767) * (2.0 / 32767.0) - 1.0; - } while (DotProduct(temp, temp) >= 1); - VectorCopy (temp, G_VECTOR(OFS_RETURN)); -} - //EXTENSION: DP_QC_VECTORVECTORS //void(vector dir) vectorvectors = #432 @@ -8370,69 +6490,6 @@ static void PF_vectorvectors (progfuncs_t *prinst, struct globalvars_s *pr_globa VectorVectors(P_VEC(v_forward), P_VEC(v_right), P_VEC(v_up)); } - -//EXTENSION: DP_QC_MINMAXBOUND - -//float(float a, floats) min = #94 -void PF_min (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i; - float f; - - if (*prinst->callargc == 2) - { - G_FLOAT(OFS_RETURN) = min(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); - } - else if (*prinst->callargc >= 3) - { - f = G_FLOAT(OFS_PARM0); - for (i = 1; i < *prinst->callargc; i++) - { - if (G_FLOAT((OFS_PARM0 + i * 3)) < f) - f = G_FLOAT((OFS_PARM0 + i * 3)); - } - G_FLOAT(OFS_RETURN) = f; - } - else - PR_BIError(prinst, "PF_min: must supply at least 2 floats\n"); -} - -//float(float a, floats) max = #95 -void PF_max (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int i; - float f; - - if (*prinst->callargc == 2) - { - G_FLOAT(OFS_RETURN) = max(G_FLOAT(OFS_PARM0), G_FLOAT(OFS_PARM1)); - } - else if (*prinst->callargc >= 3) - { - f = G_FLOAT(OFS_PARM0); - for (i = 1; i < *prinst->callargc; i++) { - if (G_FLOAT((OFS_PARM0 + i * 3)) > f) - f = G_FLOAT((OFS_PARM0 + i * 3)); - } - G_FLOAT(OFS_RETURN) = f; - } - else - { - PR_BIError(prinst, "PF_min: must supply at least 2 floats\n"); - } -} - -//float(float minimum, float val, float maximum) bound = #96 -void PF_bound (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - if (G_FLOAT(OFS_PARM1) > G_FLOAT(OFS_PARM2)) - G_FLOAT(OFS_RETURN) = G_FLOAT(OFS_PARM2); - else if (G_FLOAT(OFS_PARM1) < G_FLOAT(OFS_PARM0)) - G_FLOAT(OFS_RETURN) = G_FLOAT(OFS_PARM0); - else - G_FLOAT(OFS_RETURN) = G_FLOAT(OFS_PARM1); -} - //EXTENSION: KRIMZON_SV_PARSECLIENTCOMMAND //void(entity e, string s) clientcommand = #440 @@ -8951,10 +7008,94 @@ void PF_CustomTEnt(progfuncs_t *prinst, struct globalvars_s *pr_globals) SV_MulticastProtExt (org, MULTICAST_PVS, pr_global_struct->dimension_send, PEXT_CUSTOMTEMPEFFECTS, 0); //now send the new multicast to all that will. } -void PF_Abort(progfuncs_t *prinst, struct globalvars_s *pr_globals) +//float(string effectname) particleeffectnum (EXT_CSQC) +void PF_sv_particleeffectnum(progfuncs_t *prinst, struct globalvars_s *pr_globals) { - prinst->AbortStack(prinst); +#pragma message("PF_sv_particleeffectnum: which effect index values to use?") + char *efname = PR_GetStringOfs(prinst, OFS_PARM0); + G_FLOAT(OFS_RETURN) = COM_Effectinfo_ForName(efname); } +//void(float effectnum, entity ent, vector start, vector end) trailparticles (EXT_CSQC), +void PF_sv_trailparticles(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ +#pragma message("PF_sv_trailparticles: first two parameters differ from dp, but comply with spec") + int efnum = G_FLOAT(OFS_PARM0); + int ednum = G_EDICTNUM(prinst, OFS_PARM1); + float *start = G_VECTOR(OFS_PARM2); + float *end = G_VECTOR(OFS_PARM3); + + MSG_WriteByte(&sv.multicast, svcfte_trailparticles); + MSG_WriteShort(&sv.multicast, ednum); + MSG_WriteShort(&sv.multicast, efnum); + MSG_WriteCoord(&sv.multicast, start[0]); + MSG_WriteCoord(&sv.multicast, start[1]); + MSG_WriteCoord(&sv.multicast, start[2]); + MSG_WriteCoord(&sv.multicast, end[0]); + MSG_WriteCoord(&sv.multicast, end[1]); + MSG_WriteCoord(&sv.multicast, end[2]); + + MSG_WriteByte(&sv.nqmulticast, svcdp_trailparticles); + MSG_WriteShort(&sv.nqmulticast, ednum); + MSG_WriteShort(&sv.nqmulticast, efnum); + MSG_WriteCoord(&sv.nqmulticast, start[0]); + MSG_WriteCoord(&sv.nqmulticast, start[1]); + MSG_WriteCoord(&sv.nqmulticast, start[2]); + MSG_WriteCoord(&sv.nqmulticast, end[0]); + MSG_WriteCoord(&sv.nqmulticast, end[1]); + MSG_WriteCoord(&sv.nqmulticast, end[2]); + + SV_MulticastProtExt(start, MULTICAST_PHS, ~0, PEXT_CSQC, 0); +} +//void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) +void PF_sv_pointparticles(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int efnum = G_FLOAT(OFS_PARM0); + float *org = G_VECTOR(OFS_PARM1); + float *vel = G_VECTOR(OFS_PARM2); + int count = G_FLOAT(OFS_PARM3); + + if (count > 65535) + count = 65535; + + if (count == 1 && DotProduct(org, org) == 0) + { + MSG_WriteByte(&sv.multicast, svcfte_pointparticles1); + MSG_WriteShort(&sv.multicast, efnum); + MSG_WriteCoord(&sv.multicast, org[0]); + MSG_WriteCoord(&sv.multicast, org[1]); + MSG_WriteCoord(&sv.multicast, org[2]); + + MSG_WriteByte(&sv.nqmulticast, svcdp_pointparticles1); + MSG_WriteShort(&sv.nqmulticast, efnum); + MSG_WriteCoord(&sv.nqmulticast, org[0]); + MSG_WriteCoord(&sv.nqmulticast, org[1]); + MSG_WriteCoord(&sv.nqmulticast, org[2]); + } + else + { + MSG_WriteByte(&sv.multicast, svcfte_pointparticles); + MSG_WriteShort(&sv.multicast, efnum); + MSG_WriteCoord(&sv.multicast, org[0]); + MSG_WriteCoord(&sv.multicast, org[1]); + MSG_WriteCoord(&sv.multicast, org[2]); + MSG_WriteCoord(&sv.multicast, vel[0]); + MSG_WriteCoord(&sv.multicast, vel[1]); + MSG_WriteCoord(&sv.multicast, vel[2]); + MSG_WriteShort(&sv.multicast, count); + + MSG_WriteByte(&sv.nqmulticast, svcdp_pointparticles); + MSG_WriteShort(&sv.nqmulticast, efnum); + MSG_WriteCoord(&sv.nqmulticast, org[0]); + MSG_WriteCoord(&sv.nqmulticast, org[1]); + MSG_WriteCoord(&sv.nqmulticast, org[2]); + MSG_WriteCoord(&sv.nqmulticast, vel[0]); + MSG_WriteCoord(&sv.nqmulticast, vel[1]); + MSG_WriteCoord(&sv.nqmulticast, vel[2]); + MSG_WriteShort(&sv.nqmulticast, count); + } + SV_MulticastProtExt(org, MULTICAST_PHS, ~0, PEXT_CSQC, 0); +} + typedef struct qcstate_s { float resumetime; @@ -9055,26 +7196,6 @@ void PF_Fork(progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = 0; } - -//QSG_DIMENSION_PLANES -//helper function -//float(float number, float quantity) bitshift = #218; -void PF_bitshift(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int bitmask; - int shift; - - bitmask = G_FLOAT(OFS_PARM0); - shift = G_FLOAT(OFS_PARM1); - - if (shift < 0) - bitmask >>= shift; - else - bitmask <<= shift; - - G_FLOAT(OFS_RETURN) = bitmask; -} - //DP_TE_STANDARDEFFECTBUILTINS //void(vector org) te_gunshot = #418; void PF_te_gunshot(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -10083,16 +8204,18 @@ void PF_gettagindex(progfuncs_t *prinst, struct globalvars_s *pr_globals) G_FLOAT(OFS_RETURN) = tagidx; } -void EdictToTransform(edict_t *ed, float *trans) +static void EdictToTransform(edict_t *ed, float *trans) { AngleVectors(ed->v->angles, trans+0, trans+4, trans+8); + VectorInverse(trans+4); + trans[3] = ed->v->origin[0]; trans[7] = ed->v->origin[1]; trans[11] = ed->v->origin[2]; } // #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) -void PF_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) +void PF_sv_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) { float transtag[12]; float transent[12]; @@ -10115,6 +8238,7 @@ void PF_gettaginfo(progfuncs_t *prinst, struct globalvars_s *pr_globals) return; } +#pragma message("This function doesn't honour attachments") EdictToTransform(ent, transent); R_ConcatTransforms((void*)transent, (void*)transtag, (void*)result); @@ -10137,15 +8261,69 @@ void PF_clientstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) SV_QCStatFieldIdx(G_FLOAT(OFS_PARM1), G_INT(OFS_PARM2)+prinst->fieldadjust, G_FLOAT(OFS_PARM0)); #endif } +void PF_globalstat(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + char *name = PF_VarString(prinst, 2, pr_globals); +#if 0 //this is the old code + SV_QCStatName(G_FLOAT(OFS_PARM0), name, G_FLOAT(OFS_PARM1)); +#else + SV_QCStatGlobal(G_FLOAT(OFS_PARM1), name, G_FLOAT(OFS_PARM0)); +#endif +} void PF_runclientphys(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ +{ + extern vec3_t player_maxs, player_mins; + float msecs; + pmove.sequence = *pr_nqglobal_struct->clientcommandframe; + pmove.pm_type = PM_NORMAL; + + pmove.jump_msec = 0;//(cls.z_ext & Z_EXT_PM_TYPE) ? 0 : from->jump_msec; + if (pr_nqglobal_struct->pmove_jump_held) + pmove.jump_held = *pr_nqglobal_struct->pmove_jump_held; + if (pr_nqglobal_struct->pmove_waterjumptime) + pmove.waterjumptime = *pr_nqglobal_struct->pmove_waterjumptime; + +//set up the movement command + msecs = *pr_nqglobal_struct->input_timelength*1000 + 0.5f; + //precision inaccuracies. :( +#define ANGLE2SHORT(x) (x) * (65536/360.0) + pmove.cmd.angles[0] = ANGLE2SHORT(pr_nqglobal_struct->input_angles[0]); + pmove.cmd.angles[1] = ANGLE2SHORT(pr_nqglobal_struct->input_angles[1]); + pmove.cmd.angles[2] = ANGLE2SHORT(pr_nqglobal_struct->input_angles[2]); + VectorCopy(pr_nqglobal_struct->input_angles, pmove.angles); + + pmove.cmd.forwardmove = (*pr_nqglobal_struct->input_movevalues)[0]; + pmove.cmd.sidemove = (*pr_nqglobal_struct->input_movevalues)[1]; + pmove.cmd.upmove = (*pr_nqglobal_struct->input_movevalues)[2]; + pmove.cmd.buttons = *pr_nqglobal_struct->input_buttons; + + VectorCopy(*pr_nqglobal_struct->pmove_org, pmove.origin); + VectorCopy(*pr_nqglobal_struct->pmove_vel, pmove.velocity); + VectorCopy(*pr_nqglobal_struct->pmove_maxs, player_maxs); + VectorCopy(*pr_nqglobal_struct->pmove_mins, player_mins); + pmove.hullnum = 1; + pmove.numphysent = 1; pmove.physents[0].model = sv.worldmodel; -// AddLinksToPmove ( sv_areanodes ); + AddLinksToPmove ( PROG_TO_EDICT(svprogfuncs, pr_global_struct->self), sv_areanodes ); - PM_PlayerMove(sv.gamespeed); + while(msecs) //break up longer commands + { + pmove.cmd.msec = msecs; + if (pmove.cmd.msec > 50) + pmove.cmd.msec = 50; + msecs -= pmove.cmd.msec; + PM_PlayerMove(1); + } + + if (pr_nqglobal_struct->pmove_jump_held) + *pr_nqglobal_struct->pmove_jump_held = pmove.jump_held; + if (pr_nqglobal_struct->pmove_waterjumptime) + *pr_nqglobal_struct->pmove_waterjumptime = pmove.waterjumptime; + VectorCopy(pmove.origin, *pr_nqglobal_struct->pmove_org); + VectorCopy(pmove.velocity, *pr_nqglobal_struct->pmove_vel); } //DP_QC_GETSURFACE @@ -10408,13 +8586,6 @@ void PF_SendPacket(progfuncs_t *prinst, struct globalvars_s *pr_globals) NET_SendPacket(NS_SERVER, strlen(contents), contents, to); } -void PF_WasFreed (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - edict_t *ent; - ent = (edict_t*)G_EDICT(prinst, OFS_PARM0); - G_FLOAT(OFS_RETURN) = ent->isfree; -} - BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"fixme", PF_Fixme, 0, 0, 0}, {"ignore", PF_Ignore, 0, 0, 0}, @@ -10512,7 +8683,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"AdvanceFrame", PF_AdvanceFrame, 0, 0, 63, 0}, {"printvec", PF_printv, 0, 0, 64, 0}, //64 {"RewindFrame", PF_RewindFrame, 0, 0, 65, 0}, - {"particleexplosion",PF_particleexplosion,0, 0, 81, 0}, + {"particleexplosion",PF_h2particleexplosion,0, 0, 81, 0}, {"movestep", PF_movestep, 0, 0, 82, 0}, {"advanceweaponframe",PF_advanceweaponframe,0, 0, 83, 0}, @@ -10540,26 +8711,26 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"setspawnparms", PF_setspawnparms, 78, 78, 78}, //78 {"plaque_draw", PF_plaque_draw, 0, 0, 79}, //79 - {"logfrag", PF_logfrag, 0, 79, 0}, //79 + {"logfrag", PF_logfrag, 0, 79, 0, 79}, //79 // Tomaz - QuakeC String Manipulation Begin - {"tq_zone", PF_dupstring, 0, 0, 0, 79}, //79 - {"tq_unzone", PF_forgetstring, 0, 0, 0, 80}, //80 - //stof - {"tq_strcat", PF_strcat, 0, 0, 0, 82}, //82 - {"tq_substring", PF_substring, 0, 0, 0, 83}, //83 - {"tq_stof", PF_stof, 0, 0, 0, 84}, //84 - {"tq_stov", PF_stov, 0, 0, 0, 85}, //85 + {"tq_zone", PF_dupstring, 0, 0, 0, 79, true}, //79 + {"tq_unzone", PF_forgetstring, 0, 0, 0, 80, true}, //80 + {"tq_stof", PF_stof, 0, 0, 0, 81, true}, //81 + {"tq_strcat", PF_strcat, 0, 0, 0, 82, true}, //82 + {"tq_substring", PF_substring, 0, 0, 0, 83, true}, //83 + {"tq_stof", PF_stof, 0, 0, 0, 84, true}, //84 + {"tq_stov", PF_stov, 0, 0, 0, 85, true}, //85 // Tomaz - QuakeC String Manipulation End // Tomaz - QuakeC File System Begin (new mods use frik_file instead) - {"tq_fopen", PF_fopen, 0, 0, 0, 86},// #86 float(string filename, float mode) fopen (QSG_FILE) - {"tq_fclose", PF_fclose, 0, 0, 0, 87},// #87 void(float fhandle) fclose (QSG_FILE) - {"tq_fgets", PF_fgets, 0, 0, 0, 88},// #88 string(float fhandle) fgets (QSG_FILE) - {"tq_fputs", PF_fputs, 0, 0, 0, 89},// #89 void(float fhandle, string s) fputs (QSG_FILE) + {"tq_fopen", PF_fopen, 0, 0, 0, 86, true},// #86 float(string filename, float mode) fopen (QSG_FILE) + {"tq_fclose", PF_fclose, 0, 0, 0, 87, true},// #87 void(float fhandle) fclose (QSG_FILE) + {"tq_fgets", PF_fgets, 0, 0, 0, 88, true},// #88 string(float fhandle) fgets (QSG_FILE) + {"tq_fputs", PF_fputs, 0, 0, 0, 89, true},// #89 void(float fhandle, string s) fputs (QSG_FILE) // Tomaz - QuakeC File System End - {"rain_go", PF_rain_go, 0, 0, 80}, //80 + {"rain_go", PF_rain_go, 0, 0, 80, 0}, //80 {"infokey", PF_infokey, 0, 80, 0, 80}, //80 {"stof", PF_stof, 0, 81, 0, 81}, //81 @@ -10568,32 +8739,32 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //mvdsv (don't require ebfs usage in qw) - {"executecommand", PF_ExecuteCommand, 0, 83, 0, 83}, //83 //void() exec; please don't use. - {"mvdtokenize", PF_Tokenize, 0, 84, 0, 84}, //84 //void(string str) tokanize; - {"mvdargc", PF_ArgC, 0, 85, 0, 85}, //85 //float() argc; - {"mvdargv", PF_ArgV, 0, 86, 0, 86}, //86 //string(float num) argv; + {"executecommand", PF_ExecuteCommand, 0, 0, 0, 83, true}, //83 //void() exec; please don't use. + {"mvdtokenize", PF_Tokenize, 0, 0, 0, 84, true}, //84 //void(string str) tokanize; + {"mvdargc", PF_ArgC, 0, 0, 0, 85, true}, //85 //float() argc; + {"mvdargv", PF_ArgV, 0, 0, 0, 86, true}, //86 //string(float num) argv; //mvd commands //some of these are a little iffy. //we support them for mvdsv compatability but some of them look very hacky. //these ones are not honoured with numbers, but can be used via the proper means. - {"teamfield", PF_teamfield, 0, 0, 0, 0}, - {"substr", PF_substr, 0, 0, 0, 0}, - {"mvdstrcat", PF_strcat, 0, 0, 0, 0}, - {"mvdstrlen", PF_strlen, 0, 0, 0, 0}, - {"str2byte", PF_str2byte, 0, 0, 0, 0}, - {"str2short", PF_str2short, 0, 0, 0, 0}, - {"mvdnewstr", PF_newstring, 0, 0, 0, 0}, - {"mvdfreestr", PF_forgetstring, 0, 0, 0, 0}, - {"conprint", PF_conprint, 0, 0, 0, 0}, - {"readcmd", PF_readcmd, 0, 0, 0, 0}, - {"mvdstrcpy", PF_MVDSV_strcpy, 0, 0, 0, 0}, - {"strstr", PF_strstr, 0, 0, 0, 0}, - {"mvdstrncpy", PF_MVDSV_strncpy, 0, 0, 0, 0}, - {"log", PF_log, 0, 0, 0, 0}, -// {"redirectcmd", PF_redirectcmd, 0, 0, 0, 101}, - {"mvdcalltimeofday",PF_calltimeofday, 0, 0, 0, 102}, - {"forcedemoframe", PF_forcedemoframe, 0, 0, 0, 103}, + {"teamfield", PF_teamfield, 0, 0, 0, 87, true}, + {"substr", PF_substr, 0, 0, 0, 88, true}, + {"mvdstrcat", PF_strcat, 0, 0, 0, 89, true}, + {"mvdstrlen", PF_strlen, 0, 0, 0, 90, true}, + {"str2byte", PF_str2byte, 0, 0, 0, 91, true}, + {"str2short", PF_str2short, 0, 0, 0, 92, true}, + {"mvdnewstr", PF_newstring, 0, 0, 0, 93, true}, + {"mvdfreestr", PF_forgetstring, 0, 0, 0, 94, true}, + {"conprint", PF_conprint, 0, 0, 0, 95, true}, + {"readcmd", PF_readcmd, 0, 0, 0, 96, true}, + {"mvdstrcpy", PF_MVDSV_strcpy, 0, 0, 0, 97, true}, + {"strstr", PF_strstr, 0, 0, 0, 98, true}, + {"mvdstrncpy", PF_MVDSV_strncpy, 0, 0, 0, 99, true}, + {"log", PF_log, 0, 0, 0, 100, true}, +// {"redirectcmd", PF_redirectcmd, 0, 0, 0, 101, true}, + {"mvdcalltimeofday",PF_calltimeofday, 0, 0, 0, 102, true}, + {"forcedemoframe", PF_forcedemoframe, 0, 0, 0, 103, true}, //end of mvdsv {"setpuzzlemodel", PF_set_puzzle_model,0, 0, 87, 0}, @@ -10628,14 +8799,14 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"max", PF_max, 0, 0, 0, 95}, // #95 float(float a, floats) max (DP_QC_MINMAXBOUND) {"bound", PF_bound, 0, 0, 0, 96}, // #96 float(float minimum, float val, float maximum) bound (DP_QC_MINMAXBOUND) {"pow", PF_pow, 0, 0, 0, 97}, - {"tj_cvar_string", PF_cvar_string, 0, 0, 0, 97}, //telejano + {"tj_cvar_string", PF_cvar_string, 0, 0, 0, 97, true}, //telejano //DP_QC_FINDFLOAT {"findfloat", PF_FindFloat, 0, 0, 0, 98}, // #98 entity(entity start, float fld, float match) findfloat (DP_QC_FINDFLOAT) {"checkextension", PF_checkextension, 99, 99, 0, 99}, // #99 //darkplaces system - query a string to see if the mod supports X Y and Z. {"builtin_find", PF_builtinsupported,100, 100, 0, 100}, // #100 //per builtin system. {"anglemod", PF_anglemod, 0, 0, 0, 102}, - {"cvar_string", PF_cvar_string, 0, 0, 0, 103}, + {"qsg_cvar_string", PF_cvar_string, 0, 0, 0, 103}, //TEI_SHOWLMP2 {"showpic", PF_ShowPic, 0, 0, 0, 104}, @@ -10739,17 +8910,21 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"sqlversion", PF_sqlversion, 0, 0, 0, 257}, // #257 string(float serveridx) sqlversion (FTE_SQL) {"sqlreadfloat", PF_sqlreadfloat, 0, 0, 0, 258}, // #258 float(float serveridx, float queryidx, float row, float column) sqlreadfloat (FTE_SQL) #endif + {"stoi", PF_stoi, 0, 0, 0, 259}, + {"itos", PF_itos, 0, 0, 0, 260}, + {"stoh", PF_stoh, 0, 0, 0, 261}, + {"htos", PF_htos, 0, 0, 0, 262}, //EXT_CSQC // {"setmodelindex", PF_sv_SetModelIndex,0, 0, 0, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) // {"modelnameforindex",PF_sv_ModelnameForIndex,0, 0, 0, 334}, // #334 string(float mdlindex) modelnameforindex (EXT_CSQC) -// {"particleeffectnum",PF_sv_particlesloaded,0, 0, 0, 335}, // #335 float(string effectname) particleeffectnum (EXT_CSQC) -// {"trailparticles", PF_sv_trailparticles,0, 0, 0, 336}, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC), -// {"pointparticles", PF_sv_pointparticles,0, 0, 0, 337}, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) + {"particleeffectnum",PF_sv_particleeffectnum,0, 0, 0, 335}, // #335 float(string effectname) particleeffectnum (EXT_CSQC) + {"trailparticles", PF_sv_trailparticles,0, 0, 0, 336}, // #336 void(entity ent, float effectnum, vector start, vector end) trailparticles (EXT_CSQC), + {"pointparticles", PF_sv_pointparticles,0, 0, 0, 337}, // #337 void(float effectnum, vector origin [, vector dir, float count]) pointparticles (EXT_CSQC) // {"cprint", PF_sv_cprint, 0, 0, 0, 338}, // #338 void(string s) cprint (EXT_CSQC) -// {"print", PF_sv_print, 0, 0, 0, 339}, // #339 void(string s) print (EXT_CSQC) + {"print", PF_print, 0, 0, 0, 339}, // #339 void(string s) print (EXT_CSQC) // {"runningserver", PF_sv_runningserver,0, 0, 0, 350}, // #350 float() isserver (EXT_CSQC) // {"registercommand", PF_sv_registercommand,0, 0, 0, 352}, // #352 void(string cmdname) registercommand (EXT_CSQC) @@ -10760,6 +8935,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs //end fte extras //DP extras + //DP_QC_COPYENTITY {"copyentity", PF_copyentity, 0, 0, 0, 400},// #400 void(entity from, entity to) copyentity (DP_QC_COPYENTITY) //DP_SV_SETCOLOR @@ -10842,7 +9018,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"findchainflags", PF_findchainflags, 0, 0, 0, 450},// #450 entity(.float fld, float match) findchainflags //DP_MD3_TAGSINFO {"gettagindex", PF_gettagindex, 0, 0, 0, 451},// #451 float(entity ent, string tagname) gettagindex (DP_MD3_TAGSINFO) - {"gettaginfo", PF_gettaginfo, 0, 0, 0, 452},// #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) + {"gettaginfo", PF_sv_gettaginfo, 0, 0, 0, 452},// #452 vector(entity ent, float tagindex) gettaginfo (DP_MD3_TAGSINFO) //DP_SV_BOTCLIENT {"dropclient", PF_dropclient, 0, 0, 0, 453},// #453 void(entity player) dropclient @@ -10851,10 +9027,106 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"WriteUnterminatedString",PF_WriteString2,0, 0, 0, 456}, //writestring but without the null terminator. makes things a little nicer. +//DP_TE_FLAMEJET +// {"te_flamejet", PF_te_flamejet, 0, 0, 0, 457}, // #457 void(vector org, vector vel, float howmany) te_flamejet + + //no 458 documented. + +//DP_QC_EDICT_NUM + {"edict_num", PF_edict_for_num, 0, 0, 0, 459}, // #459 entity(float entnum) edict_num + +//DP_QC_STRINGBUFFERS + {"buf_create", PF_buf_create, 0, 0, 0, 460}, // #460 float() buf_create + {"buf_del", PF_buf_del, 0, 0, 0, 461}, // #461 void(float bufhandle) buf_del + {"buf_getsize", PF_buf_getsize, 0, 0, 0, 462}, // #462 float(float bufhandle) buf_getsize + {"buf_copy", PF_buf_copy, 0, 0, 0, 463}, // #463 void(float bufhandle_from, float bufhandle_to) buf_copy + {"buf_sort", PF_buf_sort, 0, 0, 0, 464}, // #464 void(float bufhandle, float sortpower, float backward) buf_sort + {"buf_implode", PF_buf_implode, 0, 0, 0, 465}, // #465 string(float bufhandle, string glue) buf_implode + {"bufstr_get", PF_bufstr_get, 0, 0, 0, 466}, // #466 string(float bufhandle, float string_index) bufstr_get + {"bufstr_set", PF_bufstr_set, 0, 0, 0, 467}, // #467 void(float bufhandle, float string_index, string str) bufstr_set + {"bufstr_add", PF_bufstr_add, 0, 0, 0, 468}, // #468 float(float bufhandle, string str, float order) bufstr_add + {"bufstr_free", PF_bufstr_free, 0, 0, 0, 469}, // #469 void(float bufhandle, float string_index) bufstr_free + + //no 470 documented + +//DP_QC_ASINACOSATANATAN2TAN + {"asin", PF_asin, 0, 0, 0, 471}, // #471 float(float s) asin + {"acos", PF_acos, 0, 0, 0, 472}, // #472 float(float c) acos + {"atan", PF_atan, 0, 0, 0, 473}, // #473 float(float t) atan + {"atan2", PF_atan2, 0, 0, 0, 474}, // #474 float(float c, float s) atan2 + {"tan", PF_tan, 0, 0, 0, 475}, // #475 float(float a) tan + + +//DP_QC_STRINGCOLORFUNCTIONS {"strlennocol", PF_strlennocol, 0, 0, 0, 476}, // #476 float(string s) strlennocol {"strdecolorize", PF_strdecolorize, 0, 0, 0, 477}, // #477 string(string s) strdecolorize -//end other peoples extras +//DP_QC_STRFTIME + {"strftime", PF_strftime, 0, 0, 0, 478}, // #478 string(float uselocaltime, string format, ...) strftime + +//DP_QC_TOKENIZEBYSEPARATOR + {"tokenizebyseparator",PF_tokenizebyseparator,0,0, 0, 479}, // #479 float(string s, string separator1, ...) tokenizebyseparator + +//DP_QC_STRING_CASE_FUNCTIONS + {"strtolower", PF_strtolower, 0, 0, 0, 480}, // #476 string(string s) strtolower + {"strtoupper", PF_strtoupper, 0, 0, 0, 481}, // #476 string(string s) strlennocol + +//DP_QC_CVAR_DEFSTRING + {"cvar_defstring", PF_cvar_defstring, 0, 0, 0, 482}, // #482 string(string s) cvar_defstring + +//DP_SV_POINTSOUND + {"pointsound", PF_pointsound, 0, 0, 0, 483}, // #483 void(vector origin, string sample, float volume, float attenuation) pointsound + +//DP_QC_STRREPLACE + {"strreplace", PF_strreplace, 0, 0, 0, 484}, // #484 string(string search, string replace, string subject) strreplace + {"strireplace", PF_strireplace, 0, 0, 0, 485}, // #485 string(string search, string replace, string subject) strireplace + + +//DP_QC_GETSURFACEPOINTATTRIBUTE + {"getsurfacepointattribute",PF_getsurfacepointattribute,0,0,0, 486}, // #486vector(entity e, float s, float n, float a) getsurfacepointattribute + +//DP_GECKO_SUPPORT + {"gecko_create", PF_gecko_create, 0, 0, 0, 487}, // #487 float(string name) gecko_create( string name ) + {"gecko_destroy", PF_gecko_destroy, 0, 0, 0, 488}, // #488 void(string name) gecko_destroy( string name ) + {"gecko_navigate", PF_gecko_navigate, 0, 0, 0, 489}, // #489 void(string name) gecko_navigate( string name, string URI ) + {"gecko_keyevent", PF_gecko_keyevent, 0, 0, 0, 490}, // #490 float(string name) gecko_keyevent( string name, float key, float eventtype ) + {"gecko_mousemove", PF_gecko_mousemove, 0, 0, 0, 491}, // #491 void gecko_mousemove( string name, float x, float y ) + {"gecko_resize", PF_gecko_resize, 0, 0, 0, 492}, // #492 void gecko_resize( string name, float w, float h ) + {"gecko_get_texture_extent",PF_gecko_get_texture_extent,0,0,0, 493}, // #493 vector gecko_get_texture_extent( string name ) + +//DP_QC_CRC16 + {"crc16", PF_crc16, 0, 0, 0, 494}, // #494 float(float caseinsensitive, string s, ...) crc16 + +//DP_QC_CVAR_TYPE + {"cvar_type", PF_cvar_type, 0, 0, 0, 495}, // #495 float(string name) cvar_type + +//DP_QC_ENTITYDATA + {"numentityfields", PF_numentityfields, 0, 0, 0, 496}, // #496 float() numentityfields + {"entityfieldname", PF_entityfieldname, 0, 0, 0, 497}, // #497 string(float fieldnum) entityfieldname + {"entityfieldtype", PF_entityfieldtype, 0, 0, 0, 498}, // #498 float(float fieldnum) entityfieldtype + {"getentityfieldstring",PF_getentityfieldstring,0,0, 0, 499}, // #499 string(float fieldnum, entity ent) getentityfieldstring + {"putentityfieldstring",PF_putentityfieldstring,0,0, 0, 500}, // #500 float(float fieldnum, entity ent, string s) putentityfieldstring + +//DP_SV_WRITEPICTURE + {"WritePicture", PF_WritePicture, 0, 0, 0, 501}, // #501 void(float to, string s, float sz) WritePicture + + //no 502 documented + +//DP_QC_WHICHPACK + {"whichpack", PF_whichpack, 0, 0, 0, 503}, // #503 string(string filename) whichpack + +//DP_QC_URI_ESCAPE + {"uri_escape", PF_uri_escape, 0, 0, 0, 510}, // #510 string(string in) uri_escape + {"uri_unescape", PF_uri_unescape, 0, 0, 0, 511}, // #511 string(string in) uri_unescape = #511; + +//DP_QC_NUM_FOR_EDICT + {"num_for_edict", PF_num_for_edict, 0, 0, 0, 512}, // #512 float(entity ent) num_for_edict + +//DP_QC_URI_GET + {"uri_get", PF_uri_get, 0, 0, 0, 513}, // #513 float(string uril, float id) uri_get + + //no 504 +//end dp extras //don't exceed sizeof(pr_builtin)/sizeof(pr_builtin[0]) (currently 1024) without modifing the size of pr_builtin @@ -10943,13 +9215,14 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any { for (i = 0; BuiltinList[i].name; i++) { - builtincount[BuiltinList[i].ebfsnum]++; + if (BuiltinList[i].ebfsnum && !BuiltinList[i].obsolete) + builtincount[BuiltinList[i].ebfsnum]++; } for (i = 0; BuiltinList[i].name; i++) { if (BuiltinList[i].ebfsnum) { - if (pr_builtin[BuiltinList[i].ebfsnum] == PF_Fixme && builtincount[BuiltinList[i].ebfsnum] == 1) + if (pr_builtin[BuiltinList[i].ebfsnum] == PF_Fixme && builtincount[BuiltinList[i].ebfsnum] == (BuiltinList[i].obsolete?0:1)) { pr_builtin[BuiltinList[i].ebfsnum] = BuiltinList[i].bifunc; Con_DPrintf("Enabled %s\n", BuiltinList[i].name); @@ -10986,7 +9259,7 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any } - for (i = 0; i < sizeof(QSG_Extensions)/sizeof(QSG_Extensions[0]); i++) + for (i = 0; i < QSG_Extensions_count; i++) { if (QSG_Extensions[i].enabled) *QSG_Extensions[i].enabled = false; @@ -11017,6 +9290,104 @@ void PR_ResetBuiltins(progstype_t type) //fix all nulls to PF_FIXME and add any } } +void PR_SVExtensionList_f(void) +{ + int i; + int ebi; + int bi; + lh_extension_t *extlist; + +#define SHOW_ACTIVEEXT 1 +#define SHOW_ACTIVEBI 2 +#define SHOW_NOTSUPPORTEDEXT 4 +#define SHOW_NOTACTIVEEXT 8 +#define SHOW_NOTACTIVEBI 16 + + int showflags = atoi(Cmd_Argv(1)); + if (!showflags) + showflags = SHOW_ACTIVEEXT|SHOW_NOTACTIVEEXT; + + if (showflags & (SHOW_ACTIVEBI|SHOW_NOTACTIVEBI)) + for (i = 0; BuiltinList[i].name; i++) + { + if (!BuiltinList[i].ebfsnum) + continue; //a reserved builtin. + if (BuiltinList[i].bifunc == PF_Fixme) + Con_Printf("^1%s:%i needs to be added\n", BuiltinList[i].name, BuiltinList[i].ebfsnum); + else if (pr_builtin[BuiltinList[i].ebfsnum] == BuiltinList[i].bifunc) + { + if (showflags & SHOW_ACTIVEBI) + Con_Printf("%s is active on %i\n", BuiltinList[i].name, BuiltinList[i].ebfsnum); + } + else + { + if (showflags & SHOW_NOTACTIVEBI) + Con_Printf("^4%s is NOT active (%i)\n", BuiltinList[i].name, BuiltinList[i].ebfsnum); + } + } + + if (showflags & (SHOW_NOTSUPPORTEDEXT|SHOW_NOTACTIVEEXT|SHOW_ACTIVEEXT)) + { + extlist = QSG_Extensions; + + for (i = 0; i < QSG_Extensions_count; i++) + { + if (!extlist[i].name) + continue; + + if (i < 32) + { + if (!(svs.fteprotocolextensions & (1<ents = gd32->ents; + gd->ents = (struct edict_s *)gd32->ents; gd->sizeofent = gd32->sizeofent; - gd->global = gd32->global; - gd->fields = gd32->fields; + gd->global = (q1qvmglobalvars_t *)gd32->global; + gd->fields = (field_t *)gd32->fields; gd->APIversion = gd32->APIversion; pr_edict_size = gd->sizeofent; diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index bc75650e3..07cf27bc6 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -80,6 +80,19 @@ typedef struct nqglobalvars_s func_t *SetChangeParms; float *cycle_wrapped; float *dimension_send; + + + float *clientcommandframe; + float *input_timelength; + float *input_angles; + vec3_t *input_movevalues; + float *input_buttons; + float *pmove_jump_held; + float *pmove_waterjumptime; + vec3_t *pmove_org; + vec3_t *pmove_vel; + vec3_t *pmove_mins; + vec3_t *pmove_maxs; } nqglobalvars_t; #define P_VEC(v) (pr_global_struct->V_##v) @@ -236,11 +249,14 @@ typedef struct extentvars_s //csqc stuph. func_t SendEntity; + float SendFlags; float Version; float pvsflags; //FTE_ENT_UNIQUESPAWNID float uniquespawnid; + + func_t customizeentityforclient; #ifdef VM_Q1 } extentvars_t; #else diff --git a/engine/server/savegame.c b/engine/server/savegame.c index df2a86fdd..209d494b2 100644 --- a/engine/server/savegame.c +++ b/engine/server/savegame.c @@ -834,7 +834,7 @@ void SV_SaveLevelCache(qboolean dontharmgame) if (sv.strings.lightstyles[i]) fprintf (f, "%s\n", sv.strings.lightstyles[i]); else - fprintf (f,"m\n"); + fprintf (f, "\n", sv.strings.lightstyles[i]); } for (i=1 ; iprotocol == SCP_QUAKEWORLD) #define ISQ2CLIENT(cl) ((cl)->protocol == SCP_QUAKE2) +#define ISQ3CLIENT(cl) ((cl)->protocol == SCP_QUAKE3) #define ISNQCLIENT(cl) ((cl)->protocol >= SCP_NETQUAKE) +#define ISDPCLIENT(cl) ((cl)->protocol >= SCP_DARKPLACES6) // a client can leave the server in one of four ways: // dropping properly by quiting or disconnecting @@ -718,14 +721,7 @@ typedef struct // used to check late spawns int framenum; //physics frame number for out-of-sequence thinks (fix for slow rockets) - int socketip; - int socketip6; - int socketipx; - -#ifdef TCPCONNECT - int sockettcp; - svtcpstream_t *tcpstreams; -#endif + struct ftenet_connections_s *sockets; client_t clients[MAX_CLIENTS]; int serverflags; // episode completion information @@ -794,11 +790,6 @@ typedef struct #define SOLID_CORPSE 5 #define SOLID_LADDER 20 //dmw. touch on edge, not blocking. Touching players have different physics. Otherwise a SOLID_TRIGGER -// edict->deadflag values -#define DEAD_NO 0 -#define DEAD_DYING 1 -#define DEAD_DEAD 2 - #define DAMAGE_NO 0 #define DAMAGE_YES 1 #define DAMAGE_AIM 2 @@ -1009,6 +1000,7 @@ void SV_SetMoveVars(void); qboolean SV_ChallengePasses(int challenge); void SV_QCStatName(int type, char *name, int statnum); void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum); +void SV_QCStatGlobal(int type, char *globalname, int statnum); void SV_ClearQCStats(void); void SV_SendClientMessages (void); diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index 4b8f08914..0f9c1fef9 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -325,13 +325,17 @@ void SV_Give_f (void) return; } - if (!SV_SetPlayer ()) + if (developer.value) { int oldself; oldself = pr_global_struct->self; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv.edicts); Con_Printf("Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args())); pr_global_struct->self = oldself; + } + + if (!SV_SetPlayer ()) + { return; } @@ -343,7 +347,7 @@ void SV_Give_f (void) t = Cmd_Argv(2); v = atoi (Cmd_Argv(3)); - switch (t[0]) + switch ((t[1]==0)?t[0]:0) { case '2': case '3': @@ -376,6 +380,7 @@ void SV_Give_f (void) int oldself; oldself = pr_global_struct->self; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); + Cmd_ShiftArgs(1, false); Con_Printf("Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args())); pr_global_struct->self = oldself; } @@ -598,6 +603,9 @@ void SV_Map_f (void) continue; if (host_client->state>=cs_connected) { + if (host_client->protocol == SCP_QUAKE3) + continue; + if (ISNQCLIENT(host_client)) SVNQ_New_f(); else @@ -1297,11 +1305,6 @@ void SV_Status_f (void) if (!sv.state) { - if (net_local_sv_ipadr.type != NA_LOOPBACK) - Con_Printf ("ip address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_ipadr)); - if (net_local_sv_ip6adr.type != NA_LOOPBACK) - Con_Printf ("ipv6 address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_ip6adr)); - Con_Printf("Server is not running\n"); return; } @@ -1315,22 +1318,7 @@ void SV_Status_f (void) avg = 1000*svs.stats.latched_active / STATFRAMES; pak = (float)svs.stats.latched_packets/ STATFRAMES; - if (svs.socketip != INVALID_SOCKET && net_local_sv_ipadr.type != NA_LOOPBACK) - { - extern cvar_t pr_imitatemvdsv; - if (pr_imitatemvdsv.value) //ktpro requires 'net address' for some reason that I don't remember - Con_Printf ("net address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_ipadr)); - else - Con_Printf ("ip address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_ipadr)); - } - if (svs.socketip6 != INVALID_SOCKET && net_local_sv_ip6adr.type != NA_LOOPBACK) - Con_Printf ("ipv6 address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_ip6adr)); - if (svs.socketipx != INVALID_SOCKET && net_local_sv_ipxadr.type != NA_LOOPBACK) - Con_Printf ("ipx address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_ipxadr)); -#ifdef TCPCONNECT - if (svs.sockettcp != INVALID_SOCKET && net_local_sv_tcpipadr.type != NA_LOOPBACK) - Con_Printf ("tcp address : %s\n",NET_AdrToString (adr, sizeof(adr), net_local_sv_tcpipadr)); -#endif + NET_PrintAddresses(svs.sockets); Con_Printf ("cpu utilization : %3i%%\n",(int)cpu); Con_Printf ("avg response time: %i ms\n",(int)avg); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 8dcd308ea..9579a8ac0 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -304,8 +304,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) edict_t *ent; qboolean writtenheader = false; -// if (!csqcnuments) -// return; + //we don't check that we got some already - because this is delta compressed! if (!(client->csqcactive)) return; @@ -320,6 +319,12 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) { ent = csqcent[en]; + if (ent->xv->SendFlags) + { + ent->xv->SendFlags = 0; + ent->xv->Version+=1; + } + //prevent mishaps with entities being respawned and things. if ((int)ent->xv->Version < sv.csqcentversion[ent->entnum]) ent->xv->Version = sv.csqcentversion[ent->entnum]; @@ -334,6 +339,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) csqcmsgbuffer.currentbit = 0; //Ask CSQC to write a buffer for it. G_INT(OFS_PARM0) = EDICT_TO_PROG(svprogfuncs, client->edict); + G_INT(OFS_PARM0) = 0xffffff; //psudo compatibility with SendFlags (fte doesn't support properly) pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); PR_ExecuteProgram(svprogfuncs, ent->xv->SendEntity); if (G_INT(OFS_RETURN)) //0 means not to tell the client about it. @@ -365,7 +371,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) // Con_Printf("Sending update packet %i\n", ent->entnum); } else if (sv.csqcentversion[ent->entnum] && !((int)ent->xv->pvsflags & PVSF_NOREMOVE)) - { //Don't want to send. + { //Don't want to send, but they have it already if (!writtenheader) { writtenheader=true; @@ -379,6 +385,7 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) client->csqcentversions[ent->entnum] = sv.csqcentversion[ent->entnum]; client->csqcentsequence[ent->entnum] = currentsequence; } + //now remove any out dated ones for (en = 1; en < sv.num_edicts; en++) { ent = EDICT_NUM(svprogfuncs, en); @@ -516,16 +523,21 @@ void SV_WriteDelta (entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qb fromeffects = 0; //force is true if we're going from baseline else //old quakeworld protocols do not include effects in the baseline fromeffects = from->effects; //so old clients will see the effects baseline as 0 - if ( (to->effects&0x00ff) != (fromeffects&0x00ff) ) + if ((to->effects&0x00ff) != (fromeffects&0x00ff)) bits |= U_EFFECTS; - if ( (to->effects&0xff00) != (fromeffects&0xff00) ) + if ((to->effects&0xff00) != (fromeffects&0xff00) && protext & PEXT_DPFLAGS) evenmorebits |= U_EFFECTS16; - if ( to->modelindex != from->modelindex ) + if (to->modelindex != from->modelindex) { bits |= U_MODEL; if (to->modelindex > 255) - evenmorebits |= U_MODELDBL; + { + if (protext & PEXT_DPFLAGS) + evenmorebits |= U_MODELDBL; + else + return; + } } #ifdef PROTOCOLEXTENSIONS @@ -854,12 +866,11 @@ void SV_EmitPacketEntities (client_t *client, packet_entities_t *to, sizebuf_t * // bits2 > 0 #define E5_EXTEND4 (1<<31) -void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew) +void SVDP_EmitEntityDelta(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, qboolean isnew) { int bits; if (!isnew && !memcmp(from, to, sizeof(entity_state_t))) { - to->bitmask = 0; return; //didn't change } @@ -867,7 +878,6 @@ void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, q if (isnew) { bits |= E5_FULLUPDATE; - to->bitmask = 0; //no point... } if (!VectorCompare(from->origin, to->origin)) @@ -914,6 +924,7 @@ void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, q else if (to->effects >= 256) bits |= E5_EFFECTS16; } + if (bits >= 256) bits |= E5_EXTEND1; if (bits >= 65536) @@ -921,9 +932,6 @@ void SVDP_EmitEntity(entity_state_t *from, entity_state_t *to, sizebuf_t *msg, q if (bits >= 16777216) bits |= E5_EXTEND3; - bits |= to->bitmask; - to->bitmask = bits; - if (!bits) return; @@ -1065,7 +1073,7 @@ void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t if (newnum == oldnum) { // delta update from old position //Con_Printf ("delta %i\n", newnum); - SVDP_EmitEntity (&from->entities[oldindex], &to->entities[newindex], msg, false); + SVDP_EmitEntityDelta (&from->entities[oldindex], &to->entities[newindex], msg, false); oldindex++; newindex++; continue; @@ -1075,14 +1083,14 @@ void SVDP_EmitEntitiesUpdate (client_t *client, packet_entities_t *to, sizebuf_t { // this is a new entity, send it from the baseline... as far as dp understands it... ent = EDICT_NUM(svprogfuncs, newnum); //Con_Printf ("baseline %i\n", newnum); - SVDP_EmitEntity (&defaultstate, &to->entities[newindex], msg, true); + SVDP_EmitEntityDelta (&defaultstate, &to->entities[newindex], msg, true); newindex++; continue; } if (newnum > oldnum) { // the old entity isn't present in the new message -//Con_Printf ("remove %i\n", oldnum); +Con_Printf ("remove %i\n", oldnum); MSG_WriteShort(msg, oldnum | 0x8000); oldindex++; continue; @@ -1101,7 +1109,7 @@ int SV_HullNumForPlayer(int h2hull, float *mins, float *maxs) int best; int hullnum, i; - if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3) + if (sv.worldmodel->fromgame != fg_quake) { VectorSubtract (maxs, mins, size); return size[2]; //clients are expected to decide themselves. @@ -1823,8 +1831,9 @@ void SV_WritePlayersToClient (client_t *client, edict_t *clent, qbyte *pvs, size } -void SVNQ_EmitEntity(sizebuf_t *msg, edict_t *ent, int entnum) +void SVNQ_EmitEntityState(sizebuf_t *msg, entity_state_t *ent) { + entity_state_t *baseline = &EDICT_NUM(svprogfuncs, ent->number)->baseline; #define NQU_MOREBITS (1<<0) #define NQU_ORIGIN1 (1<<1) #define NQU_ORIGIN2 (1<<2) @@ -1873,50 +1882,51 @@ int glowsize=0, glowcolor=0, colourmod=0; for (i=0 ; i<3 ; i++) { - miss = ent->v->origin[i] - ent->baseline.origin[i]; + miss = ent->origin[i] - baseline->origin[i]; if ( miss < -0.1 || miss > 0.1 ) bits |= NQU_ORIGIN1<v->angles[0] != ent->baseline.angles[0] ) + if (ent->angles[0] != baseline->angles[0] ) bits |= NQU_ANGLE1; - if (ent->v->angles[1] != ent->baseline.angles[1] ) + if (ent->angles[1] != baseline->angles[1] ) bits |= NQU_ANGLE2; - if (ent->v->angles[2] != ent->baseline.angles[2] ) + if (ent->angles[2] != baseline->angles[2] ) bits |= NQU_ANGLE3; - if ((ent->v->movetype == MOVETYPE_STEP || (ent->v->movetype == MOVETYPE_PUSH)) && (bits & (U_ANGLE1|U_ANGLE2|U_ANGLE3))) - bits |= NQU_NOLERP; // don't mess up the step animation +// if ((ent->movetype == MOVETYPE_STEP || (ent->movetype == MOVETYPE_PUSH)) && (bits & (U_ANGLE1|U_ANGLE2|U_ANGLE3))) +// bits |= NQU_NOLERP; // don't mess up the step animation - if (ent->baseline.colormap != ent->v->colormap && ent->v->colormap>=0) + if (baseline->colormap != ent->colormap && ent->colormap>=0) bits |= NQU_COLORMAP; - if (ent->baseline.skinnum != ent->v->skin) + if (baseline->skinnum != ent->skinnum) bits |= NQU_SKIN; - if (ent->baseline.frame != ent->v->frame) + if (baseline->frame != ent->frame) bits |= NQU_FRAME; - eff = ent->v->effects; + eff = ent->effects; - if ((ent->baseline.effects & 0x00ff) != ((int)eff & 0x00ff)) + if ((baseline->effects & 0x00ff) != ((int)eff & 0x00ff)) bits |= NQU_EFFECTS; - if (ent->baseline.modelindex != ent->v->modelindex) + if (baseline->modelindex != ent->modelindex) bits |= NQU_MODEL; - if (entnum >= 256) + if (ent->number >= 256) bits |= NQU_LONGENTITY; if (0) { - if (ent->baseline.trans != ent->xv->alpha) - if (!(ent->baseline.trans == 1 && !ent->xv->alpha)) +#if 0 + if (baseline.trans != ent->xv->alpha) + if (!(baseline.trans == 1 && !ent->xv->alpha)) bits |= DPU_ALPHA; - if (ent->baseline.scale != ent->xv->scale) + if (baseline.scale != ent->xv->scale) { if (ent->xv->scale != 0 || ent->baseline.scale != 1) bits |= DPU_SCALE; @@ -1925,7 +1935,7 @@ int glowsize=0, glowcolor=0, colourmod=0; if (ent->v->modelindex >= 256) //as much as protocols can handle bits |= DPU_MODEL2; - if ((ent->baseline.effects&0xff00) != ((int)eff & 0xff00)) + if ((baseline.effects&0xff00) != ((int)eff & 0xff00)) bits |= DPU_EFFECTS2; if (ent->xv->exteriormodeltoclient == EDICT_TO_PROG(svprogfuncs, host_client->edict)) @@ -1946,12 +1956,13 @@ int glowsize=0, glowcolor=0, colourmod=0; if (0 != colourmod) bits |= DPU_COLORMOD; +#endif } else { - if (ent->v->modelindex >= 256) //as much as protocols can handle + if (ent->modelindex >= 256) //as much as protocols can handle return; - if (entnum >= 600) //too many for a conventional nq client. + if (ent->number >= 600) //too many for a conventional nq client. return; } @@ -1978,30 +1989,30 @@ int glowsize=0, glowcolor=0, colourmod=0; if (bits & DPU_EXTEND2) MSG_WriteByte (msg, bits>>24); if (bits & NQU_LONGENTITY) - MSG_WriteShort (msg,entnum); + MSG_WriteShort (msg,ent->number); else - MSG_WriteByte (msg,entnum); + MSG_WriteByte (msg,ent->number); - if (bits & NQU_MODEL) MSG_WriteByte (msg, ent->v->modelindex); - if (bits & NQU_FRAME) MSG_WriteByte (msg, ent->v->frame); - if (bits & NQU_COLORMAP) MSG_WriteByte (msg, ent->v->colormap); - if (bits & NQU_SKIN) MSG_WriteByte (msg, ent->v->skin); + if (bits & NQU_MODEL) MSG_WriteByte (msg, ent->modelindex); + if (bits & NQU_FRAME) MSG_WriteByte (msg, ent->frame); + if (bits & NQU_COLORMAP) MSG_WriteByte (msg, ent->colormap); + if (bits & NQU_SKIN) MSG_WriteByte (msg, ent->skinnum); if (bits & NQU_EFFECTS) MSG_WriteByte (msg, eff & 0x00ff); - if (bits & NQU_ORIGIN1) MSG_WriteCoord (msg, ent->v->origin[0]); - if (bits & NQU_ANGLE1) MSG_WriteAngle(msg, ent->v->angles[0]); - if (bits & NQU_ORIGIN2) MSG_WriteCoord (msg, ent->v->origin[1]); - if (bits & NQU_ANGLE2) MSG_WriteAngle(msg, ent->v->angles[1]); - if (bits & NQU_ORIGIN3) MSG_WriteCoord (msg, ent->v->origin[2]); - if (bits & NQU_ANGLE3) MSG_WriteAngle(msg, ent->v->angles[2]); + if (bits & NQU_ORIGIN1) MSG_WriteCoord (msg, ent->origin[0]); + if (bits & NQU_ANGLE1) MSG_WriteAngle(msg, ent->angles[0]); + if (bits & NQU_ORIGIN2) MSG_WriteCoord (msg, ent->origin[1]); + if (bits & NQU_ANGLE2) MSG_WriteAngle(msg, ent->angles[1]); + if (bits & NQU_ORIGIN3) MSG_WriteCoord (msg, ent->origin[2]); + if (bits & NQU_ANGLE3) MSG_WriteAngle(msg, ent->angles[2]); - if (bits & DPU_ALPHA) MSG_WriteByte(msg, ent->xv->alpha*255); - if (bits & DPU_SCALE) MSG_WriteByte(msg, ent->xv->scale*16); + if (bits & DPU_ALPHA) MSG_WriteByte(msg, ent->trans*255); + if (bits & DPU_SCALE) MSG_WriteByte(msg, ent->scale*16); if (bits & DPU_EFFECTS2) MSG_WriteByte(msg, eff >> 8); if (bits & DPU_GLOWSIZE) MSG_WriteByte(msg, glowsize); if (bits & DPU_GLOWCOLOR) MSG_WriteByte(msg, glowcolor); if (bits & DPU_COLORMOD) MSG_WriteByte(msg, colourmod); - if (bits & DPU_FRAME2) MSG_WriteByte(msg, (int)ent->v->frame >> 8); - if (bits & DPU_MODEL2) MSG_WriteByte(msg, (int)ent->v->modelindex >> 8); + if (bits & DPU_FRAME2) MSG_WriteByte(msg, (int)ent->frame >> 8); + if (bits & DPU_MODEL2) MSG_WriteByte(msg, (int)ent->modelindex >> 8); } typedef struct gibfilter_s { @@ -2139,77 +2150,11 @@ qboolean Q2BSP_EdictInFatPVS(model_t *mod, edict_t *ent) } #endif -/* -============= -SV_WriteEntitiesToClient - -Encodes the current state of the world as -a svc_packetentities messages and possibly -a svc_nails message and -svc_playerinfo messages -============= -*/ -void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignorepvs) +void SV_Snapshot_Build_Playback(client_t *client, packet_entities_t *pack) { -#define DEPTHOPTIMISE -#ifdef DEPTHOPTIMISE - float distances[MAX_EXTENDED_PACKET_ENTITIES]; - float dist; -#endif - - int e, i; - qbyte *pvs; - vec3_t org; - edict_t *ent; - packet_entities_t *pack; - mvdentity_state_t *dement; - edict_t *clent; - client_frame_t *frame; + int e; entity_state_t *state; - int pvsflags; - - client_t *split; - - // this is the frame we are creating - frame = &client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK]; - - // find the client's PVS - - if (!ignorepvs) - { - clent = client->edict; - VectorAdd (clent->v->origin, clent->v->view_ofs, org); - - sv.worldmodel->funcs.FatPVS(sv.worldmodel, org, false); - -#ifdef PEXT_VIEW2 - if (clent->xv->view2) - sv.worldmodel->funcs.FatPVS(sv.worldmodel, PROG_TO_EDICT(svprogfuncs, clent->xv->view2)->v->origin, true); -#endif - for (split = client->controlled; split; split = split->controlled) - sv.worldmodel->funcs.FatPVS(sv.worldmodel, split->edict->v->origin, true); - } - else - clent = NULL; - - pvs = fatpvs; - - host_client = client; - - // send over the players in the PVS - SV_WritePlayersToClient (client, clent, pvs, msg); - - // put other visible entities into either a packet_entities or a nails message - pack = &frame->entities; - pack->num_entities = 0; - - numnails = 0; -#ifdef PEXT_LIGHTUPDATES - numlight = 0; -#endif - - if (sv.demostatevalid) //generate info from demo stats - { + mvdentity_state_t *dement; for (e=1, dement=&sv.demostate[e] ; e<=sv.demomaxents ; e++, dement++) { if (!dement->modelindex) @@ -2261,79 +2206,225 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore if (SV_DemoNailUpdate (e)) continue; } +} - // encode the packet entities as a delta from the - // last packetentities acknowledged by the client - SV_EmitPacketEntities (client, pack, msg); +void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *client) +{ +//builds an entity_state from an entity +//note that client can be null, for building baselines. - // now add the specialized nail update - SV_EmitNailUpdate (msg, ignorepvs); + int i; - return; +//FIXME: move these +// these are bits for the 'flags' field of the entity_state_t +#define RENDER_STEP 1 +#define RENDER_GLOWTRAIL 2 +#define RENDER_VIEWMODEL 4 +#define RENDER_EXTERIORMODEL 8 +#define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth +#define RENDER_COLORMAPPED 32 + +#ifdef Q2SERVER + state->modelindex2 = 0; + state->modelindex3 = 0; + state->modelindex4 = 0; + state->event = 0; + state->solid = 0; + state->sound = 0; + state->renderfx = 0; + state->old_origin[0] = 0; + state->old_origin[1] = 0; + state->old_origin[2] = 0; +#endif + + state->dpflags = 0; + if (ent->xv->viewmodelforclient) + { //this ent would have been filtered out by now if its not ours + //if ent->viewmodelforclient == client then: + state->dpflags |= RENDER_VIEWMODEL; } + if (ent->xv->exteriormodeltoclient && client) + { + if (ent->xv->exteriormodeltoclient == EDICT_TO_PROG(svprogfuncs, client->edict)) + state->dpflags |= RENDER_EXTERIORMODEL; + //everyone else sees it normally. + } + + state->number = NUM_FOR_EDICT(svprogfuncs, ent); + state->flags = 0; + VectorCopy (ent->v->origin, state->origin); + VectorCopy (ent->v->angles, state->angles); + state->modelindex = ent->v->modelindex; + state->frame = ent->v->frame; + state->colormap = ent->v->colormap; + state->skinnum = ent->v->skin; + state->effects = ent->v->effects; + state->hexen2flags = ent->xv->drawflags; + state->abslight = (int)(ent->xv->abslight*255) & 255; + state->tagentity = ent->xv->tag_entity; + state->tagindex = ent->xv->tag_index; + + state->light[0] = ent->xv->color[0]*255; + state->light[1] = ent->xv->color[1]*255; + state->light[2] = ent->xv->color[2]*255; + state->light[3] = ent->xv->light_lev; + state->lightstyle = ent->xv->style; + state->lightpflags = ent->xv->pflags; + + if ((int)ent->v->flags & FL_CLASS_DEPENDENT && client->playerclass) //hexen2 wierdness. + { + char modname[MAX_QPATH]; + Q_strncpyz(modname, sv.strings.model_precache[state->modelindex], sizeof(modname)); + if (strlen(modname)>5) + { + modname[strlen(modname)-5] = client->playerclass+'0'; + state->modelindex = SV_ModelIndex(modname); + } + } + + if (state->effects & 0x00400000) //DP's EF_LOWPRECISION + state->effects &= ~0x00400000; //we don't support it, nor does dp any more. strip it. + + if (state->effects & EF_FULLBRIGHT) //wrap the field for fte clients (this is horrible) + { + state->hexen2flags |= MLS_FULLBRIGHT; + } + + if (progstype != PROG_QW && state->effects && client && ISQWCLIENT(client)) //don't send extra nq effects to a qw client. + { + //EF_NODRAW doesn't draw the model. + //The client still needs to know about it though, as it might have other effects on it. + if (progstype == PROG_H2) + { + if (state->effects == H2EF_NODRAW) + { + //actually, H2 is pretty lame about this + state->effects = 0; + state->modelindex = 0; + state->frame = 0; + state->colormap = 0; + state->abslight = 0; + state->skinnum = 0; + state->hexen2flags = 0; + } + } + else + { + if (state->effects & NQEF_NODRAW) + state->modelindex = 0; + } + + if (state->number <= sv.allocated_client_slots) // clear only client ents + state->effects &= ~ (QWEF_FLAG1|QWEF_FLAG2); + } + + if (!ent->xv->colormod[0] && !ent->xv->colormod[1] && !ent->xv->colormod[2]) + { + state->colormod[0] = (256)/8; + state->colormod[1] = (256)/8; + state->colormod[2] = (256)/8; + } + else + { + i = ent->xv->colormod[0]*(256/8); state->colormod[0] = bound(0, i, 255); + i = ent->xv->colormod[1]*(256/8); state->colormod[1] = bound(0, i, 255); + i = ent->xv->colormod[2]*(256/8); state->colormod[2] = bound(0, i, 255); + } + state->glowsize = ent->xv->glow_size*0.25; + state->glowcolour = ent->xv->glow_color; + if (ent->xv->glow_trail) + state->dpflags |= RENDER_GLOWTRAIL; + + +#ifdef PEXT_SCALE + state->scale = ent->xv->scale*16; + if (!ent->xv->scale) + state->scale = 1*16; +#endif +#ifdef PEXT_TRANS + state->trans = ent->xv->alpha*255; + if (!ent->xv->alpha) + state->trans = 255; + + //QSG_DIMENSION_PLANES - if the only shared dimensions are ghost dimensions, Set half alpha. + if (client && client->edict) + { + if (((int)client->edict->xv->dimension_see & (int)ent->xv->dimension_ghost)) + if (!((int)client->edict->xv->dimension_see & ((int)ent->xv->dimension_seen & ~(int)ent->xv->dimension_ghost)) ) + { + if (ent->xv->dimension_ghost_alpha) + state->trans *= ent->xv->dimension_ghost_alpha; + else + state->trans *= 0.5; + } + } +#endif +#ifdef PEXT_FATNESS + state->fatness = ent->xv->fatness*2; +#endif +} + +void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, edict_t *clent, qboolean ignorepvs) +{ +//pvs and clent can be null, but only if the other is also null + int e, i; + edict_t *ent; + entity_state_t *state; +#define DEPTHOPTIMISE +#ifdef DEPTHOPTIMISE + vec3_t org; + float distances[MAX_EXTENDED_PACKET_ENTITIES]; + float dist; +#endif + globalvars_t *pr_globals = PR_globals(svprogfuncs, PR_CURRENT); + int pvsflags; if (client->viewent #ifdef NQPROT && ISQWCLIENT(client) #endif - ) //this entity is watching from outside themselves. The client is tricked into thinking that they themselves are in the view ent, and a new dummy ent (the old them) must be spawned. + ) //this entity is watching from outside themselves. The client is tricked into thinking that they themselves are in the view ent, and a new dummy ent (the old them) must be spawned. { + +//FIXME: this hack needs cleaning up +#ifdef DEPTHOPTIMISE distances[0] = 0; +#endif state = &pack->entities[pack->num_entities]; pack->num_entities++; + SV_Snapshot_BuildStateQ1(state, clent, client); + state->number = client - svs.clients + 1; - state->flags = 0; - VectorCopy (clent->v->origin, state->origin); - VectorCopy (clent->v->angles, state->angles); - state->modelindex = clent->v->modelindex; - state->frame = clent->v->frame; - state->colormap = clent->v->colormap; - state->skinnum = clent->v->skin; - state->effects = clent->v->effects; - state->hexen2flags = clent->xv->drawflags; - state->abslight = clent->xv->abslight; - -#ifdef PEXT_SCALE - state->scale = clent->xv->scale*16; - if (!state->scale) - state->scale = 1*16; -#endif -#ifdef PEXT_TRANS - state->trans = clent->xv->alpha*255; - if (!state->trans) - state->trans = 255; -#endif -#ifdef PEXT_FATNESS - state->fatness = clent->xv->fatness*2; -#endif + //yeah, I doubt anyone will need this if (progstype == PROG_QW) { - if (state->effects & QWEF_FLAG1) + if ((int)clent->v->effects & QWEF_FLAG1) { memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); state = &pack->entities[pack->num_entities]; pack->num_entities++; state->modelindex = SV_ModelIndex("progs/flag.mdl"); state->frame = 0; - state->number++; + state->number++; //yeek state->skinnum = 0; } - else if (state->effects & QWEF_FLAG2) + else if ((int)clent->v->effects & QWEF_FLAG2) { memcpy(&pack->entities[pack->num_entities], state, sizeof(*state)); state = &pack->entities[pack->num_entities]; pack->num_entities++; state->modelindex = SV_ModelIndex("progs/flag.mdl"); state->frame = 0; - state->number++; + state->number++; //yeek state->skinnum = 1; } } - state->effects &= ~(QWEF_FLAG1 | QWEF_FLAG2); } + + #ifdef NQPROT for (e=(ISQWCLIENT(client)?sv.allocated_client_slots+1:1) ; exv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC)) - continue; - - pvsflags = ent->xv->pvsflags; - if (progstype != PROG_QW) + if (ent->xv->customizeentityforclient) { -// if (progstype == PROG_H2) -// if (ent->v->effects == H2EF_NODRAW) -// continue; - if ((int)ent->v->effects & EF_MUZZLEFLASH) - { - if (needcleanup < e) - { - needcleanup = e; - MSG_WriteByte(&sv.multicast, svc_muzzleflash); - MSG_WriteShort(&sv.multicast, e); - SV_Multicast(ent->v->origin, MULTICAST_PVS); - } - } + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); + pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, clent); + PR_ExecuteProgram(svprogfuncs, ent->xv->customizeentityforclient); + if(!G_FLOAT(OFS_RETURN)) + continue; } - if (!ignorepvs && ent != clent) + if (ent == clent) { - if ((pvsflags & PVSF_MODE_MASK) < PVSF_USEPHS) + pvsflags = PVSF_IGNOREPVS; + } + else + { + + // ignore ents without visible models + if (!ent->xv->SendEntity && (!ent->v->modelindex || !*PR_GetString(svprogfuncs, ent->v->model)) && !((int)ent->xv->pflags & PFLAGS_FULLDYNAMIC)) + continue; + + pvsflags = ent->xv->pvsflags; + if (progstype != PROG_QW) { - //branch out to the pvs testing. - if (ent->xv->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, client->edict)) + // if (progstype == PROG_H2) + // if (ent->v->effects == H2EF_NODRAW) + // continue; + if ((int)ent->v->effects & EF_MUZZLEFLASH) { - //unconditional - } - else if (ent->xv->tag_entity) - { - edict_t *p = ent; - int c = 10; - while(p->xv->tag_entity&&c-->0) + if (needcleanup < e) { - p = EDICT_NUM(svprogfuncs, p->xv->tag_entity); + needcleanup = e; + MSG_WriteByte(&sv.multicast, svc_muzzleflash); + MSG_WriteShort(&sv.multicast, e); + SV_Multicast(ent->v->origin, MULTICAST_PVS); } - if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, p)) - continue; - } - else - { - if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, ent)) - continue; } } - else if ((pvsflags & PVSF_MODE_MASK) == PVSF_USEPHS && sv.worldmodel->fromgame == fg_quake) - { - int leafnum; - unsigned char *mask; - leafnum = sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, host_client->edict->v->origin); - mask = sv.phs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5); - leafnum = sv.worldmodel->funcs.LeafnumForPoint (sv.worldmodel, ent->v->origin)-1; - if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + if (pvs && ent != clent) //self doesn't get a pvs test, to cover teleporters + { + if ((int)ent->v->effects & EF_NODEPTHTEST) { - Con_Printf ("PHS supressed entity\n"); - continue; } + else if ((pvsflags & PVSF_MODE_MASK) < PVSF_USEPHS) + { + //branch out to the pvs testing. + if (ent->xv->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, clent)) + { + //unconditional + } + else if (ent->xv->tag_entity) + { + edict_t *p = ent; + int c = 10; + while(p->xv->tag_entity&&c-->0) + { + p = EDICT_NUM(svprogfuncs, p->xv->tag_entity); + } + if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, p)) + continue; + } + else + { + if (!sv.worldmodel->funcs.EdictInFatPVS(sv.worldmodel, ent)) + continue; + } + } + else if ((pvsflags & PVSF_MODE_MASK) == PVSF_USEPHS && sv.worldmodel->fromgame == fg_quake) + { + int leafnum; + unsigned char *mask; + leafnum = sv.worldmodel->funcs.LeafnumForPoint(sv.worldmodel, host_client->edict->v->origin); + mask = sv.phs + leafnum * 4*((sv.worldmodel->numleafs+31)>>5); + + leafnum = sv.worldmodel->funcs.LeafnumForPoint (sv.worldmodel, ent->v->origin)-1; + if ( !(mask[leafnum>>3] & (1<<(leafnum&7)) ) ) + { + Con_Printf ("PHS supressed entity\n"); + continue; + } + } + + if (client->gibfilter && SV_GibFilter(ent)) + continue; } } - - - - if (client->gibfilter && SV_GibFilter(ent)) - continue; - -// if (strstr(sv.model_precache[(int)ent->v->modelindex], "gib")) -// continue; - - + //fte's gib filters + //DP_SV_NODRAWONLYTOCLIENT if (ent->xv->nodrawtoclient) //DP extension. if (ent->xv->nodrawtoclient == EDICT_TO_PROG(svprogfuncs, client->edict)) continue; + //DP_ENT_VIEWMODEL + if (ent->xv->viewmodelforclient) //only the one set sees it + if (ent->xv->viewmodelforclient != EDICT_TO_PROG(svprogfuncs, client->edict)) + continue; + //DP_SV_DRAWONLYTOCLIENT if (ent->xv->drawonlytoclient) if (ent->xv->drawonlytoclient != EDICT_TO_PROG(svprogfuncs, client->edict)) { @@ -2439,60 +2550,58 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore continue; //not in this dimension - sorry... - if (!ignorepvs && ent != clent && (pvsflags & PVSF_MODE_MASK)==PVSF_NORMALPVS && !((unsigned int)ent->v->effects & (EF_DIMLIGHT|EF_BLUE|EF_RED|EF_BRIGHTLIGHT|EF_BRIGHTFIELD))) + if (!ignorepvs && ent != clent && (pvsflags & PVSF_MODE_MASK)==PVSF_NORMALPVS && !((unsigned int)ent->v->effects & (EF_DIMLIGHT|EF_BLUE|EF_RED|EF_BRIGHTLIGHT|EF_BRIGHTFIELD|EF_NODEPTHTEST))) { //more expensive culling if ((e <= sv.allocated_client_slots && sv_cullplayers_trace.value) || sv_cullentities_trace.value) if (Cull_Traceline(clent, ent)) continue; } + //EXT_CSQC if (SV_AddCSQCUpdate(client, ent)) //csqc took it. continue; -#ifdef NQPROT - if (client->protocol == SCP_NETQUAKE) - { - if (msg->cursize + 32 > msg->maxsize) - break; - SVNQ_EmitEntity(msg, ent, e); - continue; - } -#endif if (ISQWCLIENT(client)) + { if (SV_AddNailUpdate (ent)) continue; // added to the special update list #ifdef PEXT_LIGHTUPDATES - if (client->fteprotocolextensions & PEXT_LIGHTUPDATES) - if (SV_AddLightUpdate (ent)) - continue; + if (client->fteprotocolextensions & PEXT_LIGHTUPDATES) + if (SV_AddLightUpdate (ent)) + continue; #endif + } //the entity would mess up the client and possibly disconnect them. //FIXME: add an option to drop clients... entity fog could be killed in this way. - if (e >= 512) + if (!ISDPCLIENT(client)) { - if (!(client->fteprotocolextensions & PEXT_ENTITYDBL)) + if (e >= 512) { + if (!(client->fteprotocolextensions & PEXT_ENTITYDBL)) + { + continue; + } + else if (e >= 1024) + { + if (!(client->fteprotocolextensions & PEXT_ENTITYDBL2)) + continue; + else if (e >= 2048) + continue; + } + } + if (ent->v->modelindex >= 256 && !(client->fteprotocolextensions & PEXT_MODELDBL)) continue; - } - else if (e >= 1024) - { - if (!(client->fteprotocolextensions & PEXT_ENTITYDBL2)) - continue; - else if (e >= 2048) - continue; - } } - if (ent->v->modelindex >= 256 && !(client->fteprotocolextensions & PEXT_MODELDBL)) - continue; #ifdef DEPTHOPTIMISE if (clent) { //find distance based upon absolute mins/maxs so bsps are treated fairly. + //org = clentorg + -0.5*(max+min) VectorAdd(ent->v->absmin, ent->v->absmax, org); VectorMA(clent->v->origin, -0.5, org, org); - dist = Length(org); + dist = DotProduct(org, org); //Length // add to the packetentities if (pack->num_entities == pack->max_entities) @@ -2541,145 +2650,110 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore } } -// these are bits for the 'flags' field of the entity_state_t -#define RENDER_STEP 1 -#define RENDER_GLOWTRAIL 2 -#define RENDER_VIEWMODEL 4 -#define RENDER_EXTERIORMODEL 8 -#define RENDER_LOWPRECISION 16 // send as low precision coordinates to save bandwidth -#define RENDER_COLORMAPPED 32 + //its not a nail or anything, pack it up and ship it on + SV_Snapshot_BuildStateQ1(state, ent, client); + } +} - state->dpflags = 0; - if (ent->xv->viewmodelforclient) - { - if (ent->xv->viewmodelforclient == EDICT_TO_PROG(svprogfuncs, client->edict)) - state->dpflags |= RENDER_VIEWMODEL; - else - { //noone else sees it. - pack->num_entities--; - continue; - } - } - if (ent->xv->exteriormodeltoclient) - { - if (ent->xv->exteriormodeltoclient == EDICT_TO_PROG(svprogfuncs, client->edict)) - state->dpflags |= RENDER_EXTERIORMODEL; - //everyone else sees it normally. - } - - state->number = e; - state->flags = 0; - VectorCopy (ent->v->origin, state->origin); - VectorCopy (ent->v->angles, state->angles); - state->modelindex = ent->v->modelindex; - state->frame = ent->v->frame; - state->colormap = ent->v->colormap; - state->skinnum = ent->v->skin; - state->effects = ent->v->effects; - state->hexen2flags = ent->xv->drawflags; - state->abslight = (int)(ent->xv->abslight*255) & 255; - state->tagentity = ent->xv->tag_entity; - state->tagindex = ent->xv->tag_index; +qbyte *SV_Snapshot_SetupPVS(client_t *client) +{ +//fixme: fatpvs is still a global. + vec3_t org; + int leavepvs = false; - state->light[0] = ent->xv->color[0]*255; - state->light[1] = ent->xv->color[1]*255; - state->light[2] = ent->xv->color[2]*255; - state->light[3] = ent->xv->light_lev; - state->lightstyle = ent->xv->style; - state->lightpflags = ent->xv->pflags; + for (; client; client = client->controlled) + { + VectorAdd (client->edict->v->origin, client->edict->v->view_ofs, org); + sv.worldmodel->funcs.FatPVS(sv.worldmodel, org, leavepvs); + leavepvs = true; - if ((int)ent->v->flags & FL_CLASS_DEPENDENT && client->playerclass) //hexen2 wierdness. - { - char modname[MAX_QPATH]; - Q_strncpyz(modname, sv.strings.model_precache[state->modelindex], sizeof(modname)); - if (strlen(modname)>5) - { - modname[strlen(modname)-5] = client->playerclass+'0'; - state->modelindex = SV_ModelIndex(modname); - } - } - - if (state->effects & 0x32) - state->effects |= 0; - - if (state->effects & 0x00400000) - state->effects &= ~0x00400000; - - if (state->effects & EF_FULLBRIGHT) - { - state->hexen2flags |= MLS_FULLBRIGHT; - } - if (progstype != PROG_QW && state->effects && ISQWCLIENT(client)) //don't send extra nq effects to a qw client. - { - //EF_NODRAW doesn't draw the model. - //The client still needs to know about it though, as it might have other effects on it. - if (progstype == PROG_H2) - { - if (state->effects == H2EF_NODRAW) - { - //actually, H2 is pretty lame about this - state->effects = 0; - state->modelindex = 0; - state->frame = 0; - state->colormap = 0; - state->abslight = 0; - state->skinnum = 0; - state->hexen2flags = 0; - } - } - else - { - if (state->effects & NQEF_NODRAW) - state->modelindex = 0; - } - - if (e <= sv.allocated_client_slots) // clear only client ents - state->effects &= ~ (QWEF_FLAG1|QWEF_FLAG2); - } - - if (!ent->xv->colormod[0] && !ent->xv->colormod[1] && !ent->xv->colormod[2]) - { - state->colormod[0] = (256)/8; - state->colormod[1] = (256)/8; - state->colormod[2] = (256)/8; - } - else - { - i = ent->xv->colormod[0]*(256/8); state->colormod[0] = bound(0, i, 255); - i = ent->xv->colormod[1]*(256/8); state->colormod[1] = bound(0, i, 255); - i = ent->xv->colormod[2]*(256/8); state->colormod[2] = bound(0, i, 255); - } - state->glowsize = ent->xv->glow_size*0.25; - state->glowcolour = ent->xv->glow_color; - if (ent->xv->glow_trail) - state->dpflags |= RENDER_GLOWTRAIL; - - -#ifdef PEXT_SCALE - state->scale = ent->xv->scale*16; - if (!ent->xv->scale) - state->scale = 1*16; -#endif -#ifdef PEXT_TRANS - state->trans = ent->xv->alpha*255; - if (!ent->xv->alpha) - state->trans = 255; - - //QSG_DIMENSION_PLANES - if the only shared dimensions are ghost dimensions, Set half alpha. - if (client->edict) - if (((int)client->edict->xv->dimension_see & (int)ent->xv->dimension_ghost)) - if (!((int)client->edict->xv->dimension_see & ((int)ent->xv->dimension_seen & ~(int)ent->xv->dimension_ghost)) ) - { - if (ent->xv->dimension_ghost_alpha) - state->trans *= ent->xv->dimension_ghost_alpha; - else - state->trans *= 0.5; - } -#endif -#ifdef PEXT_FATNESS - state->fatness = ent->xv->fatness*2; +#ifdef PEXT_VIEW2 + if (client->edict->xv->view2) //add a second view point to the pvs + sv.worldmodel->funcs.FatPVS(sv.worldmodel, PROG_TO_EDICT(svprogfuncs, client->edict->xv->view2)->v->origin, leavepvs); #endif } + + return fatpvs; +} + +void SV_Snapshot_Clear(packet_entities_t *pack) +{ + pack->num_entities = 0; + + csqcnuments = 0; + numnails = 0; +#ifdef PEXT_LIGHTUPDATES + numlight = 0; +#endif +} + +/* +============= +SVQ3Q1_BuildEntityPacket + +Builds a temporary q1 style entity packet for a q3 client +============= +*/ +void SVQ3Q1_BuildEntityPacket(client_t *client, packet_entities_t *pack) +{ + qbyte *pvs; + SV_Snapshot_Clear(pack); + pvs = SV_Snapshot_SetupPVS(client); + SV_Snapshot_BuildQ1(client, pack, pvs, client->edict, false); +} + +/* +============= +SV_WriteEntitiesToClient + +Encodes the current state of the world as +a svc_packetentities messages and possibly +a svc_nails message and +svc_playerinfo messages +============= +*/ +void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignorepvs) +{ + int e; + qbyte *pvs; + packet_entities_t *pack; + edict_t *clent; + client_frame_t *frame; + + + // this is the frame we are creating + frame = &client->frameunion.frames[client->netchan.incoming_sequence & UPDATE_MASK]; + + // find the client's PVS + if (ignorepvs) + { + clent = NULL; + pvs = NULL; + } + else + { + clent = client->edict; + pvs = SV_Snapshot_SetupPVS(client); + } + + host_client = client; + pack = &frame->entities; + SV_Snapshot_Clear(pack); + + // send over the players in the PVS + SV_WritePlayersToClient (client, clent, pvs, msg); + + // put other visible entities into either a packet_entities or a nails message + + if (sv.demostatevalid) //generate info from demo stats + { + SV_Snapshot_Build_Playback(client, pack); + } + else + { + SV_Snapshot_BuildQ1(client, pack, pvs, clent, ignorepvs); + } + #ifdef NQPROT if (ISNQCLIENT(client)) { @@ -2691,6 +2765,12 @@ void SV_WriteEntitiesToClient (client_t *client, sizebuf_t *msg, qboolean ignore } else { + for (e = 0; e < pack->num_entities; e++) + { + if (msg->cursize + 32 > msg->maxsize) + break; + SVNQ_EmitEntityState(msg, &pack->entities[e]); + } client->netchan.incoming_sequence++; return; } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 9bce4fa4b..d16fe6c7a 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -47,12 +47,14 @@ int host_hunklevel; // callbacks void SV_Masterlist_Callback(struct cvar_s *var, char *oldvalue); void SV_Tcpport_Callback(struct cvar_s *var, char *oldvalue); +void SV_Tcpport6_Callback(struct cvar_s *var, char *oldvalue); void SV_Port_Callback(struct cvar_s *var, char *oldvalue); void SV_PortIPv6_Callback(struct cvar_s *var, char *oldvalue); void SV_PortIPX_Callback(struct cvar_s *var, char *oldvalue); typedef struct { - qboolean isdp; + enum { + } isdp; cvar_t cv; netadr_t adr; } sv_masterlist_t; @@ -66,9 +68,9 @@ sv_masterlist_t sv_masterlist[] = { {false, SCVARC("sv_master7", "", SV_Masterlist_Callback)}, {false, SCVARC("sv_master8", "", SV_Masterlist_Callback)}, - {true, SCVARC("sv_masterextra1", "ghdigital.com", SV_Masterlist_Callback)}, //69.59.212.88 - {true, SCVARC("sv_masterextra2", "dpmaster.deathmask.net", SV_Masterlist_Callback)}, //209.164.24.243 - {true, SCVARC("sv_masterextra3", "12.166.196.192", SV_Masterlist_Callback)}, //blaze.mindphukd.org (doesn't resolve currently but works as an ip) + {true, SCVARC("sv_masterextra1", "ghdigital.com", SV_Masterlist_Callback)}, //69.59.212.88 (admin: LordHavoc) + {true, SCVARC("sv_masterextra2", "dpmaster.deathmask.net", SV_Masterlist_Callback)}, //209.164.24.243 (admin: Willis) + {true, SCVARC("sv_masterextra3", "dpmaster.tchr.no", SV_Masterlist_Callback)}, // (admin: tChr) {false, SCVAR(NULL, NULL)} }; @@ -117,6 +119,7 @@ cvar_t sv_public = SCVAR("sv_public", "0"); cvar_t sv_listen_qw = FCVAR("sv_listen_qw", "sv_listen", "1", 0); cvar_t sv_listen_nq = SCVAR("sv_listen_nq", "0"); cvar_t sv_listen_dp = SCVAR("sv_listen_dp", "1"); +cvar_t sv_listen_q3 = SCVAR("sv_listen_q3", "0"); cvar_t sv_reportheartbeats = SCVAR("sv_reportheartbeats", "1"); cvar_t sv_highchars = SCVAR("sv_highchars", "1"); cvar_t sv_loadentfiles = SCVAR("sv_loadentfiles", "1"); @@ -138,7 +141,10 @@ cvar_t sv_voicechat = SCVAR("sv_voicechat", "0"); //still development. cvar_t sv_gamespeed = SCVAR("sv_gamespeed", "1"); cvar_t sv_csqcdebug = SCVAR("sv_csqcdebug", "0"); #ifdef TCPCONNECT -cvar_t sv_port_tcp = SCVARC("sv_port_tcp", "0", SV_Tcpport_Callback); +cvar_t sv_port_tcp = SCVARC("sv_port_tcp", "", SV_Tcpport_Callback); +#ifdef IPPROTO_IPV6 +cvar_t sv_port_tcp6 = SCVARC("sv_port_tcp6", "", SV_Tcpport6_Callback); +#endif #endif cvar_t sv_port = SCVARC("sv_port", "27500", SV_Port_Callback); #ifdef IPPROTO_IPV6 @@ -359,29 +365,27 @@ or crashing. void SV_DropClient (client_t *drop) { laggedpacket_t *lp; - if (drop->controller) + if (!drop->controller) { - SV_DropClient(drop->controller); - return; - } - // add the disconnect - if (drop->state != cs_zombie) - { - switch (drop->protocol) + // add the disconnect + if (drop->state != cs_zombie) { - case SCP_QUAKE2: - MSG_WriteByte (&drop->netchan.message, svcq2_disconnect); - break; - case SCP_QUAKEWORLD: - case SCP_NETQUAKE: - case SCP_DARKPLACES6: - case SCP_DARKPLACES7: - MSG_WriteByte (&drop->netchan.message, svc_disconnect); - break; - case SCP_BAD: - break; - case SCP_QUAKE3: - break; + switch (drop->protocol) + { + case SCP_QUAKE2: + MSG_WriteByte (&drop->netchan.message, svcq2_disconnect); + break; + case SCP_QUAKEWORLD: + case SCP_NETQUAKE: + case SCP_DARKPLACES6: + case SCP_DARKPLACES7: + MSG_WriteByte (&drop->netchan.message, svc_disconnect); + break; + case SCP_BAD: + break; + case SCP_QUAKE3: + break; + } } } @@ -459,6 +463,9 @@ void SV_DropClient (client_t *drop) PR_ExecuteProgram (svprogfuncs, SpectatorDisconnect); } } + + if (progstype == PROG_NQ) + ED_ClearEdict(svprogfuncs, drop->edict); } if (drop->spawninfo) @@ -782,7 +789,7 @@ void SV_FullClientUpdate (client_t *client, sizebuf_t *buf, unsigned int ftepext MSG_WriteByte (buf, i); MSG_WriteFloat (buf, 0); - strcpy (info, sv.recordedplayer[i].userinfo); + Q_strncpyz (info, sv.recordedplayer[i].userinfo, sizeof(info)); Info_RemoveKey(info, "password"); //main password key Info_RemoveKey(info, "*ip"); //don't broadcast this in playback Info_RemovePrefixedKeys (info, '_'); // server passwords, etc @@ -812,10 +819,11 @@ void SV_FullClientUpdate (client_t *client, sizebuf_t *buf, unsigned int ftepext MSG_WriteByte (buf, i); MSG_WriteFloat (buf, realtime - client->connection_started); +#pragma message("this is a bug: it can be broadcast to all qw clients") if (ftepext & PEXT_BIGUSERINFOS) - strcpy (info, client->userinfo); + Q_strncpyz (info, client->userinfo, sizeof(info)); else - strcpy (info, client->userinfobasic); + Q_strncpyz (info, client->userinfobasic, sizeof(info)); Info_RemoveKey(info, "password"); //main password key Info_RemovePrefixedKeys (info, '_'); // server passwords, etc @@ -1198,6 +1206,9 @@ void SVC_GetChallenge (void) int oldest; int oldestTime; + if (!sv_listen_qw.value && !sv_listen_dp.value && !sv_listen_q3.value) + return; + oldest = 0; oldestTime = 0x7fffffff; @@ -1281,6 +1292,16 @@ void SVC_GetChallenge (void) buf = va("challenge "DISTRIBUTION"%i", svs.challenges[i].challenge); Netchan_OutOfBand(NS_SERVER, net_from, strlen(buf)+1, buf); } +#ifdef Q3SERVER + if (svs.gametype == GT_PROGS || svs.gametype == GT_Q1QVM) + { + if (sv_listen_q3.value) + { + buf = va("challengeResponse %i", svs.challenges[i].challenge); + Netchan_OutOfBand(NS_SERVER, net_from, strlen(buf), buf); + } + } +#endif } // Netchan_OutOfBandPrint (net_from, "%c%i", S2C_CHALLENGE, @@ -1398,6 +1419,7 @@ void VARGS SV_RejectMessage(int protocol, char *format, ...) #endif case SCP_QUAKE2: + case SCP_QUAKE3: default: strcpy(string, "print\n"); vsnprintf (string+6,sizeof(string)-1-6, format,argptr); @@ -1421,6 +1443,9 @@ void SV_AcceptMessage(int protocol) char string[8192]; sizebuf_t sb; int len; +#ifdef NQPROT + netadr_t localaddr; +#endif memset(&sb, 0, sizeof(sb)); sb.maxsize = sizeof(string); @@ -1433,7 +1458,8 @@ void SV_AcceptMessage(int protocol) SZ_Clear(&sb); MSG_WriteLong(&sb, 0); MSG_WriteByte(&sb, CCREP_ACCEPT); - MSG_WriteLong(&sb, ShortSwap(net_local_sv_ipadr.port)); + NET_LocalAddressForRemote(svs.sockets, &net_from, &localaddr, 0); + MSG_WriteLong(&sb, ShortSwap(localaddr.port)); *(int*)sb.data = BigLong(NETFLAG_CTL|sb.cursize); NET_SendPacket(NS_SERVER, sb.cursize, sb.data, net_from); return; @@ -1444,6 +1470,10 @@ void SV_AcceptMessage(int protocol) break; #endif + case SCP_QUAKE3: + strcpy(string, "connectResponse"); + len = strlen(string); + break; case SCP_QUAKE2: default: strcpy(string, "client_connect\n"); @@ -1501,8 +1531,41 @@ client_t *SVC_DirectConnect(void) char *name; char adrbuf[MAX_ADR_SIZE]; - if (*(Cmd_Argv(0)+7) == '\\') + if (*Cmd_Argv(1) == '\\') + { //connect "\key\val" + + //this is used by q3 (note, we already decrypted the huffman connection packet in a hack) + if (!sv_listen_q3.value) + return NULL; + numssclients = 1; + protocol = SCP_QUAKE3; + + Q_strncpyz (userinfo[0], Cmd_Argv(1), sizeof(userinfo[0])-1); + + switch (atoi(Info_ValueForKey(userinfo[0], "protocol"))) { + case 68: //regular q3 1.32 + break; +// case 43: //q3 1.11 (most 'recent' demo) +// break; + default: + SV_RejectMessage (SCP_BAD, "Server is "DISTRIBUTION" build %i.\n", build_number()); + Con_Printf ("* rejected connect from incompatable client\n"); + return NULL; + } + + s = Info_ValueForKey(userinfo[0], "challenge"); + challenge = atoi(s); + + s = Info_ValueForKey(userinfo[0], "qport"); + qport = atoi(s); + + s = Info_ValueForKey(userinfo[0], "name"); + if (!*s) + Info_SetValueForKey(userinfo[0], "name", "UnnamedQ3", sizeof(userinfo[0])); + } + else if (*(Cmd_Argv(0)+7) == '\\') + { //DP has the userinfo attached directly to the end of the connect command if (!sv_listen_dp.value) return NULL; Q_strncpyz (userinfo[0], net_message.data + 11, sizeof(userinfo[0])-1); @@ -1534,6 +1597,10 @@ client_t *SVC_DirectConnect(void) else challenge = atoi(s); + Info_RemoveKey(userinfo[0], "protocol"); + Info_RemoveKey(userinfo[0], "protocols"); + Info_RemoveKey(userinfo[0], "challenge"); + s = Info_ValueForKey(userinfo[0], "name"); if (!*s) Info_SetValueForKey(userinfo[0], "name", "CONNECTING", sizeof(userinfo[0])); @@ -1562,7 +1629,7 @@ client_t *SVC_DirectConnect(void) else if (version == 3) { numssclients = 1; - protocol = SCP_NETQUAKE; + protocol = SCP_NETQUAKE; //because we can } else if (version != PROTOCOL_VERSION_QW) { @@ -1712,9 +1779,19 @@ client_t *SVC_DirectConnect(void) Con_Printf("%s: diff prot connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); else Con_Printf("%s:dup connect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + + SV_DropClient(cl); + /* nextuserid--; return NULL; + */ } + else if (cl->state == cs_zombie) + { + Con_Printf ("%s:reconnect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); + SV_DropClient (cl); + } + else { Con_Printf ("%s:reconnect\n", NET_AdrToString (adrbuf, sizeof(adrbuf), adr)); // SV_DropClient (cl); @@ -1762,6 +1839,15 @@ client_t *SVC_DirectConnect(void) } else if (!stricmp(name, "console")) name = "Not Console"; //have fun dudes. + else + { + char *t = name; + //work around an ezquake bug that has been there since the beginning in one form or another. + while (*(unsigned char*)t == 0xff) + t++; + if (!*t) + name = "invisible"; + } // count up the clients and spectators clients = 0; @@ -1864,16 +1950,29 @@ client_t *SVC_DirectConnect(void) // build a new connection // accept the new client - // this is the only place a client_t is ever initialized - temp.frameunion.frames = newcl->frameunion.frames; //don't touch these. - if (temp.frameunion.frames) - Z_Free(temp.frameunion.frames); - - temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); - for (i = 0; i < UPDATE_BACKUP; i++) + // this is the only place a client_t is ever initialized, for q1 mods at least +#ifdef Q3SERVER + if (ISQ3CLIENT(newcl)) { - temp.frameunion.frames[i].entities.max_entities = maxpacketentities; - temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities; + Huff_PreferedCompressionCRC(); + temp.frameunion.q3frames = BZ_Malloc(Q3UPDATE_BACKUP*sizeof(*temp.frameunion.q3frames)); + } + else +#endif + { + temp.frameunion.frames = newcl->frameunion.frames; //don't touch these. + if (temp.frameunion.frames) + { + Con_Printf("Debug: frames were set?\n"); + Z_Free(temp.frameunion.frames); + } + + temp.frameunion.frames = Z_Malloc((sizeof(client_frame_t)+sizeof(entity_state_t)*maxpacketentities)*UPDATE_BACKUP); + for (i = 0; i < UPDATE_BACKUP; i++) + { + temp.frameunion.frames[i].entities.max_entities = maxpacketentities; + temp.frameunion.frames[i].entities.entities = (entity_state_t*)(temp.frameunion.frames+UPDATE_BACKUP) + i*temp.frameunion.frames[i].entities.max_entities; + } } break; @@ -1913,14 +2012,13 @@ client_t *SVC_DirectConnect(void) newcl->team = t; } + newcl->challenge = challenge; newcl->zquake_extensions = atoi(Info_ValueForKey(newcl->userinfo, "*z_ext")); if (*Info_ValueForKey(newcl->userinfo, "*fuhquake")) //fuhquake doesn't claim to support z_ext but does look at our z_ext serverinfo key. { //so switch on the bits that it should be sending. newcl->zquake_extensions |= Z_EXT_PM_TYPE|Z_EXT_PM_TYPE_NEW; } - //dmw - delayed - Netchan_OutOfBandPrint (adr, "%c", S2C_CONNECTION ); - Netchan_Setup (NS_SERVER, &newcl->netchan , adr, qport); if (huffcrc) @@ -1935,6 +2033,9 @@ client_t *SVC_DirectConnect(void) newcl->state = cs_connected; +#ifdef Q3SERVER + newcl->gamestatesequence = -1; +#endif newcl->datagram.allowoverflow = true; newcl->datagram.data = newcl->datagram_buf; newcl->datagram.maxsize = sizeof(newcl->datagram_buf); @@ -2411,10 +2512,24 @@ qboolean SV_ConnectionlessPacket (void) SVQ3_DirectConnect(); return true; } - else + + if (sv_listen_q3.value) + { + if (!strstr(s, "\\name\\")) + { //if name isn't in the string, assume they're q3 + //this isn't quite true though, hence the listen check. but users shouldn't be connecting with an empty name anyway. more fool them. + Huff_DecryptPacket(&net_message, 12); + MSG_BeginReading(); + MSG_ReadLong(); + s = MSG_ReadStringLine(); + Cmd_TokenizeString(s, false, false); + } + } #endif if (secure.value) //FIXME: possible problem for nq clients when enabled + { Netchan_OutOfBandPrint (NS_SERVER, net_from, "%c\nThis server requires client validation.\nPlease use the "DISTRIBUTION" validation program\n", A2C_PRINT); + } else { SVC_DirectConnect (); @@ -2687,6 +2802,19 @@ void SV_ReadPackets (void) break; } #endif + +#ifdef Q3SERVER + if (ISQ3CLIENT(cl)) + { +#pragma message("qwoverq3: fixme: this will block qw+q3 clients from the same ip") + if (cl->state != cs_zombie) + { + SVQ3_HandleClient(); + } + break; + } +#endif + if (cl->netchan.qport != qport) continue; if (cl->netchan.remote_address.port != net_from.port) @@ -3256,11 +3384,16 @@ void SV_InitLocal (void) Cvar_Register (&sv_listen_qw, cvargroup_servercontrol); Cvar_Register (&sv_listen_nq, cvargroup_servercontrol); Cvar_Register (&sv_listen_dp, cvargroup_servercontrol); + Cvar_Register (&sv_listen_q3, cvargroup_servercontrol); sv_listen_qw.restriction = RESTRICT_MAX; #ifdef TCPCONNECT Cvar_Register (&sv_port_tcp, cvargroup_servercontrol); sv_port_tcp.restriction = RESTRICT_MAX; +#ifdef IPPROTO_IPV6 + Cvar_Register (&sv_port_tcp6, cvargroup_servercontrol); + sv_port_tcp6.restriction = RESTRICT_MAX; +#endif #endif #ifdef IPPROTO_IPV6 Cvar_Register (&sv_port_ipv6, cvargroup_servercontrol); @@ -3936,6 +4069,10 @@ void SV_InitNet (void) // NET_StringToAdr ("192.246.40.70:27000", &idmaster_adr); } +void SV_IgnoreCommand_f(void) +{ +} + /* ==================== @@ -3946,6 +4083,7 @@ SV_Init void SV_Demo_Init(void); void SV_Init (quakeparms_t *parms) { + int i; #ifndef SERVERONLY if (isDedicated) #endif @@ -4007,6 +4145,8 @@ void SV_Init (quakeparms_t *parms) host_initialized = true; + //get rid of the worst of the spam + Cmd_AddRemCommand("bind", SV_IgnoreCommand_f); Con_TPrintf (TL_EXEDATETIME, __DATE__, __TIME__); Con_TPrintf (TL_HEAPSIZE,parms->memsize/ (1024*1024.0)); @@ -4018,7 +4158,14 @@ void SV_Init (quakeparms_t *parms) Con_TPrintf (STL_INITED); - Cbuf_InsertText ("exec server.cfg\nexec ftesrv.cfg\n", RESTRICT_LOCAL, false); + i = COM_CheckParm("+gamedir"); + if (i) + COM_Gamedir(com_argv[i+1]); + + if (COM_FileSize("server.cfg") != -1) + Cbuf_InsertText ("exec server.cfg\nexec ftesrv.cfg\n", RESTRICT_LOCAL, false); + else + Cbuf_InsertText ("exec quake.rc\nexec ftesrv.cfg\n", RESTRICT_LOCAL, false); // process command line arguments Cbuf_Execute (); @@ -4027,6 +4174,9 @@ void SV_Init (quakeparms_t *parms) Cbuf_Execute (); + //and warn about any future times this is used. + Cmd_RemoveCommand("bind"); + // if a map wasn't specified on the command line, spawn start.map if (sv.state == ss_dead) Cmd_ExecuteString ("map start", RESTRICT_LOCAL); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index e1ad93d88..f0b79306f 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -1725,6 +1725,36 @@ void SV_WalkMove (edict_t *ent) } #endif +void SV_MoveChain(edict_t *ent, edict_t *movechain, float *initial_origin, float *initial_angle) +{ + qboolean callfunc; + if ((callfunc=DotProduct(ent->v->origin, initial_origin)) || DotProduct(ent->v->angles, initial_angle)) + { + vec3_t moveang, moveorg; + int i; + VectorSubtract(ent->v->angles, initial_angle, moveang) + VectorSubtract(ent->v->origin, initial_origin, moveorg) + + for(i=16;i && movechain != sv.edicts && !movechain->isfree;i--, movechain = PROG_TO_EDICT(svprogfuncs, movechain->xv->movechain)) + { + if ((int)movechain->v->flags & FL_MOVECHAIN_ANGLE) + VectorAdd(movechain->v->angles, moveang, movechain->v->angles); + VectorAdd(movechain->v->origin, moveorg, movechain->v->origin); + + if (movechain->xv->chainmoved && callfunc) + { + pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, movechain); + pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); +#ifdef VM_Q1 + if (svs.gametype == GT_Q1QVM) + Q1QVM_ChainMoved(); + else +#endif + PR_ExecuteProgram(svprogfuncs, movechain->xv->chainmoved); + } + } + } +} #define FL_JUMPRELEASED 4096 /* @@ -1836,33 +1866,7 @@ void SV_RunEntity (edict_t *ent) if (movechain != sv.edicts) { - qboolean callfunc; - if ((callfunc=DotProduct(ent->v->origin, initial_origin)) || DotProduct(ent->v->angles, initial_angle)) - { - vec3_t moveang, moveorg; - int i; - VectorSubtract(ent->v->angles, initial_angle, moveang) - VectorSubtract(ent->v->origin, initial_origin, moveorg) - - for(i=16;i && movechain != sv.edicts && !movechain->isfree;i--, movechain = PROG_TO_EDICT(svprogfuncs, movechain->xv->movechain)) - { - if ((int)movechain->v->flags & FL_MOVECHAIN_ANGLE) - VectorAdd(movechain->v->angles, moveang, movechain->v->angles); - VectorAdd(movechain->v->origin, moveorg, movechain->v->origin); - - if (movechain->xv->chainmoved && callfunc) - { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, movechain); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); -#ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_ChainMoved(); - else -#endif - PR_ExecuteProgram(svprogfuncs, movechain->xv->chainmoved); - } - } - } + SV_MoveChain(ent, movechain, initial_origin, initial_angle); } if (ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots) diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index 74fffbdbb..72a9dc16b 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -565,6 +565,9 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int default: SV_Error("Multicast: Client is using a bad protocl"); + case SCP_QUAKE3: + Con_Printf("Skipping multicast for q3 client\n"); + break; #ifdef NQPROT case SCP_NETQUAKE: case SCP_DARKPLACES6: @@ -653,15 +656,16 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int continue; } + if (svprogfuncs) + if (!((int)client->edict->xv->dimension_see & dimension_mask)) + continue; + if (to == MULTICAST_PHS_R || to == MULTICAST_PHS) { vec3_t delta; VectorSubtract(origin, client->edict->v->origin, delta); if (Length(delta) <= 1024) goto inrange; } - else if (svprogfuncs) - if (!((int)client->edict->xv->dimension_see & dimension_mask)) - continue; // -1 is because pvs rows are 1 based, not 0 based like leafs if (mask != sv.pvs) @@ -682,6 +686,10 @@ void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int default: SV_Error("multicast: Client is using a bad protocol"); + case SCP_QUAKE3: + Con_Printf("Skipping multicast for q3 client\n"); + break; + #ifdef NQPROT case SCP_NETQUAKE: case SCP_DARKPLACES6: @@ -1172,14 +1180,17 @@ void SV_WriteClientdataToMessage (client_t *client, sizebuf_t *msg) } typedef struct { - int type; + int type; //negative means a global. char name[64]; - evalc_t evalc; + union { + evalc_t c; + eval_t *g; //just store a pointer to it. + } eval; int statnum; } qcstat_t; qcstat_t qcstats[MAX_CL_STATS-32]; int numqcstats; -void SV_QCStatEval(int type, char *name, evalc_t *cache, int statnum) +void SV_QCStatEval(int type, char *name, evalc_t *field, eval_t *global, int statnum) { int i; if (numqcstats == sizeof(qcstats)/sizeof(qcstats[0])) @@ -1206,17 +1217,36 @@ void SV_QCStatEval(int type, char *name, evalc_t *cache, int statnum) qcstats[i].type = type; qcstats[i].statnum = statnum; Q_strncpyz(qcstats[i].name, name, sizeof(qcstats[i].name)); - memcpy(&qcstats[i].evalc, cache, sizeof(evalc_t)); + if (type < 0) + qcstats[i].eval.g = global; + else + memcpy(&qcstats[i].eval.c, field, sizeof(evalc_t)); +} + +void SV_QCStatGlobal(int type, char *globalname, int statnum) +{ + eval_t *glob; + + glob = svprogfuncs->FindGlobal(svprogfuncs, globalname, PR_ANY); + if (!glob) + { + Con_Printf("couldn't find named global for csqc stat (%s)\n", globalname); + return; + } + SV_QCStatEval(type, globalname, NULL, glob, statnum); } void SV_QCStatName(int type, char *name, int statnum) { evalc_t cache; + if (type < 0) + return; + memset(&cache, 0, sizeof(cache)); if (!svprogfuncs->GetEdictFieldValue(svprogfuncs, NULL, name, &cache)) return; - SV_QCStatEval(type, name, &cache, statnum); + SV_QCStatEval(type, name, &cache, NULL, statnum); } void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum) @@ -1225,12 +1255,15 @@ void SV_QCStatFieldIdx(int type, unsigned int fieldindex, int statnum) char *name; etype_t ftype; + if (type < 0) + return; + if (!svprogfuncs->QueryField(svprogfuncs, fieldindex, &ftype, &name, &cache)) { Con_Printf("invalid field for csqc stat\n"); return; } - SV_QCStatEval(type, name, &cache, statnum); + SV_QCStatEval(type, name, &cache, NULL, statnum); } void SV_ClearQCStats(void) @@ -1242,15 +1275,25 @@ void SV_UpdateQCStats(edict_t *ent, int *statsi, char **statss, float *statsf) { char *s; int i; + int t; for (i = 0; i < numqcstats; i++) { eval_t *eval; - eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, qcstats[i].name, &qcstats[i].evalc); + t = qcstats[i].type; + if (t < 0) + { + t = -t; + eval = qcstats[i].eval.g; + } + else + { + eval = svprogfuncs->GetEdictFieldValue(svprogfuncs, ent, qcstats[i].name, &qcstats[i].eval.c); + } if (!eval) continue; - switch(qcstats[i].type) + switch(t) { case ev_float: statsf[qcstats[i].statnum] = eval->_float; @@ -1341,9 +1384,9 @@ void SV_UpdateClientStats (client_t *client, int pnum) #endif if (!ent->xv->viewzoom) - statsf[STAT_VIEWZOOM] = 255; + statsi[STAT_VIEWZOOM] = 255; else - statsf[STAT_VIEWZOOM] = ent->xv->viewzoom*255; + statsi[STAT_VIEWZOOM] = ent->xv->viewzoom*255; if (host_client->protocol == SCP_DARKPLACES7) { @@ -1411,11 +1454,11 @@ void SV_UpdateClientStats (client_t *client, int pnum) if (!ISQWCLIENT(client)) { if (!statsi[i]) - statsi[i] = *(int*)&statsf[i]; + statsi[i] = statsf[i]; if (statsi[i] != client->statsi[i]) { client->statsi[i] = statsi[i]; - ClientReliableWrite_Begin(client, svc_updatestat, 3); + ClientReliableWrite_Begin(client, svc_updatestat, 6); ClientReliableWrite_Byte(client, i); ClientReliableWrite_Long(client, statsi[i]); } @@ -1779,7 +1822,7 @@ void SV_UpdateToReliableMessages (void) SZ_Clear (&sv.datagram); #ifdef NQPROT - if (sv.nqdatagram.overflowed) +// if (sv.nqdatagram.overflowed) SZ_Clear (&sv.nqdatagram); #endif #ifdef Q2SERVER @@ -1926,6 +1969,16 @@ void SV_SendClientMessages (void) continue; } +#ifdef Q3SERVER + if (ISQ3CLIENT(c)) + { //q3 protocols bypass backbuffering and pretty much everything else + if (c->state <= cs_zombie) + continue; + SVQ3_SendMessage(c); + continue; + } +#endif + // check to see if we have a backbuf to stick in the reliable if (c->num_backbuf) { diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 18ce81759..38cd5d252 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -375,7 +375,7 @@ void SVNQ_New_f (void) #endif MSG_WriteString (&host_client->netchan.message,message); - if (host_client->protocol == SCP_DARKPLACES7) + if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7) { extern cvar_t allow_download; char *f; @@ -749,9 +749,11 @@ void SV_PK3List_f (void) //spawns. These functions are written to not overflow if (host_client->num_backbuf) { - Con_Printf("WARNING %s: [SV_Soundlist] Back buffered (%d), clearing", host_client->name, host_client->netchan.message.cursize); - host_client->num_backbuf = 0; - SZ_Clear(&host_client->netchan.message); + char *msg = va("cmd pk3list %s %s\n", Cmd_Argv(1), Cmd_Argv(2)); + Con_TPrintf(STL_BACKBUFSET, host_client->name, host_client->netchan.message.cursize); + ClientReliableWrite_Begin(host_client, svc_stufftext, 2+strlen(msg)); + ClientReliableWrite_String(&host_client->netchan.message, msg); + return; } if (i < 0) { @@ -814,10 +816,13 @@ void SV_Soundlist_f (void) //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow - if (host_client->num_backbuf) { - Con_Printf("WARNING %s: [SV_Soundlist] Back buffered (%d), clearing", host_client->name, host_client->netchan.message.cursize); - host_client->num_backbuf = 0; - SZ_Clear(&host_client->netchan.message); + if (host_client->num_backbuf) + { + char *msg = va("cmd soundlist %s %s\n", Cmd_Argv(1), Cmd_Argv(2)); + Con_TPrintf(STL_BACKBUFSET, host_client->name, host_client->netchan.message.cursize); + ClientReliableWrite_Begin(host_client, svc_stufftext, 1+strlen(msg)); + ClientReliableWrite_String(host_client, msg); + return; } if (n >= MAX_SOUNDS) @@ -886,10 +891,13 @@ void SV_Modellist_f (void) //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow - if (host_client->num_backbuf) { - Con_Printf("WARNING %s: [SV_Modellist] Back buffered (%d), clearing", host_client->name, host_client->netchan.message.cursize); - host_client->num_backbuf = 0; - SZ_Clear(&host_client->netchan.message); + if (host_client->num_backbuf) + { + char *msg = va("cmd modellist %s %s\n", Cmd_Argv(1), Cmd_Argv(2)); + Con_TPrintf(STL_BACKBUFSET, host_client->name, host_client->netchan.message.cursize); + ClientReliableWrite_Begin(host_client, svc_stufftext, 1+strlen(msg)); + ClientReliableWrite_String(host_client, msg); + return; } if (n >= MAX_MODELS) @@ -1013,10 +1021,13 @@ void SV_PreSpawn_f (void) //NOTE: This doesn't go through ClientReliableWrite since it's before the user //spawns. These functions are written to not overflow - if (host_client->num_backbuf) { - Con_Printf("WARNING %s: [SV_PreSpawn] Back buffered (%d), clearing", host_client->name, host_client->netchan.message.cursize); - host_client->num_backbuf = 0; - SZ_Clear(&host_client->netchan.message); + if (host_client->num_backbuf) + { + char *msg = va("cmd prespawn %s %s %s\n", Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3)); + Con_TPrintf(STL_BACKBUFSET, host_client->name, host_client->netchan.message.cursize); + ClientReliableWrite_Begin(host_client, svc_stufftext, 1+strlen(msg)); + ClientReliableWrite_String(host_client, msg); + return; } if (buf >= bufs && !sv.democausesreconnect) @@ -1341,47 +1352,13 @@ void SV_SpawnSpectator (void) } -/* -================== -SV_Begin_f -================== -*/ -void SV_Begin_f (void) -{ - client_t *split, *oh; - unsigned pmodel = 0, emodel = 0; +void SV_Begin_Core(client_t *split) +{ //this is the client-protocol-independant core, for q1/q2 gamecode + + client_t *oh; int i; - qboolean sendangles=false; - - if (!SV_CheckRealIP(host_client, true)) - { - if (host_client->protocol == SCP_QUAKE2) - ClientReliableWrite_Begin (host_client, svcq2_stufftext, 13+strlen(Cmd_Args())); - else - ClientReliableWrite_Begin (host_client, svc_stufftext, 13+strlen(Cmd_Args())); - ClientReliableWrite_String (host_client, va("cmd begin %s\n", Cmd_Args())); - return; - } - - if (host_client->state == cs_spawned) - return; // don't begin again - - for (split = host_client; split; split = split->controlled) - split->state = cs_spawned; - - // handle the case of a level changing while a client was connecting - if ( atoi(Cmd_Argv(1)) != svs.spawncount && !sv.msgfromdemo) - { - Con_Printf ("SV_Begin_f from different level\n"); - SV_New_f (); - return; - } - if (progstype == PROG_H2 && host_client->playerclass) host_client->edict->xv->playerclass = host_client->playerclass; //make sure it's set the same as the userinfo - - for (split = host_client; split; split = split->controlled) - { #ifdef Q2SERVER if (ge) { @@ -1393,7 +1370,6 @@ void SV_Begin_f (void) if (split->istobeloaded) { func_t f; - sendangles = true; split->istobeloaded = false; f = PR_FindFunction(svprogfuncs, "RestoreGame", PR_ANY); @@ -1488,6 +1464,8 @@ void SV_Begin_f (void) } oh = host_client; + host_client = split; + sv_player = host_client->edict; SV_PreRunCmd(); { usercmd_t cmd; @@ -1501,12 +1479,57 @@ void SV_Begin_f (void) } SV_PostRunCmd(); host_client = oh; + sv_player = host_client->edict; } } } } } +/* +================== +SV_Begin_f +================== +*/ +void SV_Begin_f (void) +{ + client_t *split; + unsigned pmodel = 0, emodel = 0; + qboolean sendangles=false; + + if (!SV_CheckRealIP(host_client, true)) + { + if (host_client->protocol == SCP_QUAKE2) + ClientReliableWrite_Begin (host_client, svcq2_stufftext, 13+strlen(Cmd_Args())); + else + ClientReliableWrite_Begin (host_client, svc_stufftext, 13+strlen(Cmd_Args())); + ClientReliableWrite_String (host_client, va("cmd begin %s\n", Cmd_Args())); + return; + } + + if (host_client->state == cs_spawned) + return; // don't begin again + + for (split = host_client; split; split = split->controlled) + split->state = cs_spawned; + + // handle the case of a level changing while a client was connecting + if ( atoi(Cmd_Argv(1)) != svs.spawncount && !sv.msgfromdemo) + { + Con_Printf ("SV_Begin_f from different level\n"); + SV_New_f (); + return; + } + + if (host_client->istobeloaded) + sendangles = true; + + + for (split = host_client; split; split = split->controlled) + { //tell the gamecode they're ready + SV_Begin_Core(split); + } + // clear the net statistics, because connecting gives a bogus picture host_client->netchan.frame_latency = 0; host_client->netchan.frame_rate = 0; @@ -1655,28 +1678,93 @@ void SV_DarkPlacesDownloadAck(client_t *cl) } } -void SV_NextChunkedDownload(int chunknum) +void SV_NextChunkedDownload(int chunknum, int ezpercent, int ezfilenum) { #define CHUNKSIZE 1024 char buffer[CHUNKSIZE]; + qbyte oobdata[1+ (sizeof("\\chunk")-1) + 4 + 1 + 4 + CHUNKSIZE]; + sizebuf_t *msg, msg_oob; int i; + qboolean error = false; + + msg = &host_client->datagram; + + if (chunknum < 0 || (chunknum*CHUNKSIZE > host_client->downloadsize)) + { + Con_Printf ("Invalid file chunk requested %i to %i of .\n", chunknum*CHUNKSIZE, (chunknum+1)*CHUNKSIZE, host_client->downloadsize); + error = true; + } + + if (!error && VFS_SEEK (host_client->download, chunknum*CHUNKSIZE) == false) + error = true; + else + { + if (host_client->downloadcount < chunknum*CHUNKSIZE) + host_client->downloadcount = chunknum*CHUNKSIZE; + } if (host_client->datagram.cursize + CHUNKSIZE+5+50 > host_client->datagram.maxsize) - return; //choked! + { + //would overflow the packet. + msg = &msg_oob; - if (VFS_SEEK (host_client->download, chunknum*CHUNKSIZE) == false) - return; + if (!ezfilenum) + return; - i = VFS_READ (host_client->download, buffer, CHUNKSIZE); + if (!Netchan_CanPacket(&host_client->netchan, SV_RateForClient(host_client))) + return; + } + + if (error) + i = 0; + else + i = VFS_READ (host_client->download, buffer, CHUNKSIZE); if (i > 0) { + if (msg == &msg_oob)//host_client->datagram.cursize + CHUNKSIZE+5+50 > host_client->datagram.maxsize) + { + msg = &msg_oob; + msg->cursize = 0; + msg->maxsize = sizeof(oobdata); + msg->currentbit = 0; + msg->packing = SZ_RAWBYTES; + msg->allowoverflow = 0; + msg->overflowed = 0; + msg->data = oobdata; + MSG_WriteByte(msg, A2C_PRINT); + SZ_Write(msg, "\\chunk", 6); + MSG_WriteLong(msg, ezfilenum); + } + if (i != CHUNKSIZE) memset(buffer+i, 0, CHUNKSIZE-i); - MSG_WriteByte(&host_client->datagram, svc_download); - MSG_WriteLong(&host_client->datagram, chunknum); - SZ_Write(&host_client->datagram, buffer, CHUNKSIZE); + MSG_WriteByte(msg, svc_download); + MSG_WriteLong(msg, chunknum); + SZ_Write(msg, buffer, CHUNKSIZE); + + if (msg == &msg_oob) + { + Netchan_OutOfBand(NS_SERVER, host_client->netchan.remote_address, msg_oob.cursize, msg_oob.data); + Netchan_Block(&host_client->netchan, msg_oob.cursize, SV_RateForClient(host_client)); + } + } + else if (i < 0) + error = true; + + if (error) + { + VFS_CLOSE (host_client->download); + host_client->download = NULL; + + ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(host_client->downloadfn)); + ClientReliableWrite_Long (host_client, -1); + ClientReliableWrite_Long (host_client, -3); + ClientReliableWrite_String (host_client, host_client->downloadfn); + + + host_client->downloadstarted = false; } } @@ -1698,7 +1786,7 @@ void SV_NextDownload_f (void) #ifdef PEXT_CHUNKEDDOWNLOADS if (host_client->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS) { - SV_NextChunkedDownload(atoi(Cmd_Argv(1))); + SV_NextChunkedDownload(atoi(Cmd_Argv(1)), atoi(Cmd_Argv(2)), atoi(Cmd_Argv(3))); return; } #endif @@ -1912,13 +2000,166 @@ qboolean SV_AllowDownload (char *name) //root of gamedir if (!strchr(name, '/') && !allow_download_root.value) { - if (strcmp(name, "csprogs.dat")) //we always allow csprogs.dat to be downloaded. + if (strcmp(name, "csprogs.dat")) //we always allow csprogs.dat to be downloaded (if downloads are permitted). return false; } //any other subdirs are allowed return true; } + +static int SV_LocateDownload(char *name, flocation_t *loc, char **replacementname, qboolean redirectpaks) +{ + extern cvar_t allow_download_anymap, allow_download_pakcontents; + extern cvar_t sv_demoDir; + qboolean protectedpak; + qboolean found; + + if (replacementname) + *replacementname = NULL; + + //mangle the name by making it lower case. + { + char *p; + + for (p = name; *p; p++) + *p = (char)tolower(*p); + } + + if (!SV_AllowDownload(name)) + return -2; //not permitted (even if it exists). + + //mvdsv demo downloading support demonum/ -> demos/XXXX (sets up the client paths) + if (!strncmp(name, "demonum/", 8)) + { + if (replacementname) + { + char mvdnamebuffer[MAX_QPATH]; + char *mvdname = SV_MVDNum(mvdnamebuffer, sizeof(mvdnamebuffer), atoi(name+8)); + if (!mvdname) + { + SV_ClientPrintf (host_client, PRINT_HIGH, "%s is an invalid MVD demonum.\n", name+8); + Sys_Printf ("%s requested invalid demonum %s\n", host_client->name, name+8); + return -1; //not found + } + *replacementname = va("demos/%s\n", mvdname); + return -4; //redirect + } + } + + //mvdsv demo downloading support. demos/ -> demodir (sets up the server paths) + if (!strncmp(name, "demos/", 6)) + name = va("%s/%s", sv_demoDir.string, name+6); + + found = FS_FLocateFile(name, FSLFRT_IFFOUND, loc); + + //nexuiz names certain files as .wav but they're really .ogg on disk. + if (!found && replacementname) + { + if (!strcmp(COM_FileExtension(name), "wav")) + { + char tryogg[MAX_QPATH]; + COM_StripExtension(name, tryogg, sizeof(tryogg)); + COM_DefaultExtension(tryogg, ".ogg", sizeof(tryogg)); + + found = FS_FLocateFile(tryogg, FSLFRT_IFFOUND, loc); + if (found) + { + name = *replacementname = va("%s", tryogg); + } + } + } + //nexuiz also names files with absolute paths (yet sounds are meant to have an extra prefix) + //this results in clients asking for sound/sound/blah.wav (or sound/sound/blah.ogg for nexuiz) + if (!found && replacementname) + { + if (!strncmp(name, "sound/", 6)) + { + int result; + result = SV_LocateDownload(name+6, loc, replacementname, redirectpaks); + if (!result) + { //if that was successful... redirect to it. + result = -4; + *replacementname = name+6; + } + return result; + } + } + + if (found) + { + protectedpak = com_file_copyprotected; + + // special check for maps, if it came from a pak file, don't allow download + if (protectedpak) + { + if (!allow_download_anymap.value && !strncmp(name, "maps/", 5)) + return -2; + } + + if (replacementname) + { + char *pakname = FS_WhichPackForLocation(loc); + if (pakname && SV_AllowDownload(pakname)) + { + //return loc of the pak instead. + if (FS_FLocateFile(name, FSLFRT_IFFOUND, loc)) + { + //its inside a pak file, return the name of this file instead + *replacementname = pakname; + return -4; //redirect + } + else + Con_Printf("Failed to read %s\n", pakname); + } + } + + if (protectedpak) + { //if its in a pak file, don't allow downloads if we don't allow the contents of paks to be sent. + if (!allow_download_pakcontents.value) + return -2; + } + + if (replacementname && *replacementname) + return -4; + return 0; + } + return -1; //not found +} + +//this function is only meaningful for nq/qw +void SV_DownloadSize_f(void) +{ + flocation_t loc; + char *name = Cmd_Argv(1); + char *redirected = ""; + + switch(SV_LocateDownload(name, &loc, &redirected, true)) + { + case -4: + name = va("dlsize \"%s\" r \"%s\"\n", name, redirected); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); + ClientReliableWrite_String (host_client, name); + break; + default: + case -1: + name = va("dlsize \"%s\" e\n", name); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); + ClientReliableWrite_String (host_client, name); + break; + case -2: + name = va("dlsize \"%s\" p\n", name); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); + ClientReliableWrite_String (host_client, name); + break; + case 0: + name = va("dlsize \"%s\" %u\n", name, loc.len); + ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(name)); + ClientReliableWrite_String (host_client, name); + break; + } +} + /* ================== SV_BeginDownload_f @@ -1927,8 +2168,11 @@ SV_BeginDownload_f void SV_BeginDownload_f(void) { char *name = Cmd_Argv(1); + char *redirection = NULL; extern cvar_t allow_download_anymap, allow_download_pakcontents; extern cvar_t sv_demoDir; + flocation_t loc; + int result; if (ISNQCLIENT(host_client) && host_client->protocol != SCP_DARKPLACES7) { @@ -1936,65 +2180,47 @@ void SV_BeginDownload_f(void) return; } - // MVD hacked junk - if (!strncmp(name, "demonum/", 8)) + result = SV_LocateDownload(name, &loc, &redirection, false); + + *host_client->downloadfn = 0; + if (host_client->download) { - char mvdnamebuffer[MAX_QPATH]; - char *mvdname = SV_MVDNum(mvdnamebuffer, sizeof(mvdnamebuffer), atoi(name+8)); - - if (!mvdname) - { - SV_ClientPrintf (host_client, PRINT_HIGH, "%s is an invalid MVD demonum.\n", name+8); - Sys_Printf ("%s requested invalid demonum %s\n", host_client->name, name+8); - } - else if (ISQ2CLIENT(host_client)) - { - Sys_Printf ("Rejected MVD download of %s to %s (Q2 client)\n", mvdname, host_client->name); - ClientReliableWrite_Begin (host_client, svcq2_download, 4); - ClientReliableWrite_Short (host_client, -1); - ClientReliableWrite_Byte (host_client, 0); - return; - } - else - SV_ClientPrintf (host_client, PRINT_HIGH, "Sending demo %s...\n", mvdname); - - // this is needed to cancel the current download - if (ISNQCLIENT(host_client)) - { - ClientReliableWrite_Begin (host_client, svc_stufftext, 2+12); - ClientReliableWrite_String (host_client, "\nstopdownload\n"); - } - else -#ifdef PEXT_CHUNKEDDOWNLOADS - if (host_client->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS) - { - ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(name)); - ClientReliableWrite_Long (host_client, -1); - ClientReliableWrite_Long (host_client, -1); - ClientReliableWrite_String (host_client, name); - } - else -#endif - { - ClientReliableWrite_Begin (host_client, svc_download, 4); - ClientReliableWrite_Short (host_client, -1); - ClientReliableWrite_Byte (host_client, 0); - } - - if (mvdname) - { - ClientReliableWrite_Begin (host_client, svc_stufftext, 2+15+strlen(mvdname)); - ClientReliableWrite_String (host_client, va("\ndownload demos/%s\n", mvdname)); - } - return; + VFS_CLOSE (host_client->download); + host_client->download = NULL; } -// hacked by zoid to allow more conrol over download - if (!SV_AllowDownload(name)) + //redirection protocol-specific code goes here. + if (result == -4) + { + } + + if (result == 0) + { //if we are allowed and could find it + host_client->download = FS_OpenReadLocation(&loc); + if (!host_client->download) + result = -1; //this isn't likely, but hey. + } + + //handle errors + if (result != 0) { // don't allow anything with .. path + char *error; + switch(result) + { + default: + error = "Download could not be found\n"; + break; + case -2: + error = "Download permission denied\n"; + break; + case -4: + result = -1; + error = ""; + break; + } if (ISNQCLIENT(host_client)) { - SV_PrintToClient(host_client, PRINT_HIGH, "Download rejected by server settings\n"); + SV_PrintToClient(host_client, PRINT_HIGH, error); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+12); ClientReliableWrite_String (host_client, "\nstopdownload\n"); @@ -2004,76 +2230,33 @@ void SV_BeginDownload_f(void) { ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(name)); ClientReliableWrite_Long (host_client, -1); - ClientReliableWrite_Long (host_client, -2); + ClientReliableWrite_Long (host_client, result); ClientReliableWrite_String (host_client, name); } else #endif { + SV_PrintToClient(host_client, PRINT_HIGH, error); + ClientReliableWrite_Begin (host_client, ISQ2CLIENT(host_client)?svcq2_download:svc_download, 4); ClientReliableWrite_Short (host_client, -1); ClientReliableWrite_Byte (host_client, 0); } + + //it errored because it was a redirection. + //ask the client to grab the alternate file instead. + if (redirection) + { + //tell the client to download the new one. + ClientReliableWrite_Begin (host_client, ISQ2CLIENT(host_client)?svcq2_stufftext:svc_stufftext, 2+strlen(redirection)); + ClientReliableWrite_String (host_client, va("\ndownload \"%s\"\n", redirection)); + } return; } - if (host_client->download) - { - VFS_CLOSE (host_client->download); - host_client->download = NULL; - } - - // lowercase name (needed for casesen file systems) - { - char *p; - - for (p = name; *p; p++) - *p = (char)tolower(*p); - } - - // yet another hack for MVD junk - if (!strncmp(name, "demos/", 6)) - host_client->download = FS_OpenVFS(va("%s/%s", sv_demoDir.string, name+6), "rb", FS_GAME); - else - host_client->download = FS_OpenVFS(name, "rb", FS_GAME); + Q_strncpyz(host_client->downloadfn, name, sizeof(host_client->downloadfn)); host_client->downloadcount = 0; - if (!host_client->download - // special check for maps, if it came from a pak file, don't allow - // download ZOID - || ((!allow_download_pakcontents.value || (!allow_download_anymap.value && strncmp(name, "maps/", 5) == 0)) && com_file_copyprotected)) - { - if (host_client->download) - { - VFS_CLOSE(host_client->download); - host_client->download = NULL; - } - - Sys_Printf ("Couldn't download %s to %s\n", name, host_client->name); - if (ISNQCLIENT(host_client)) - { - ClientReliableWrite_Begin (host_client, svc_stufftext, 2+12); - ClientReliableWrite_String (host_client, "\nstopdownload\n"); - } - else -#ifdef PEXT_CHUNKEDDOWNLOADS - if (host_client->fteprotocolextensions & PEXT_CHUNKEDDOWNLOADS) - { - ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(name)); - ClientReliableWrite_Long (host_client, -1); - ClientReliableWrite_Long (host_client, -1); - ClientReliableWrite_String (host_client, name); - } - else -#endif - { - ClientReliableWrite_Begin (host_client, ISQ2CLIENT(host_client)?svcq2_download:svc_download, 4); - ClientReliableWrite_Short (host_client, -1); - ClientReliableWrite_Byte (host_client, 0); - } - return; - } - host_client->downloadsize = VFS_GETLEN(host_client->download); #ifdef PEXT_CHUNKEDDOWNLOADS @@ -2101,16 +2284,17 @@ void SV_BeginDownload_f(void) host_client->download = tmp; } - ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(name)); + ClientReliableWrite_Begin (host_client, svc_download, 10+strlen(host_client->downloadfn)); ClientReliableWrite_Long (host_client, -1); ClientReliableWrite_Long (host_client, host_client->downloadsize); - ClientReliableWrite_String (host_client, name); + ClientReliableWrite_String (host_client, host_client->downloadfn); } + else #endif if (ISNQCLIENT(host_client)) { - char *s = va("\ncl_downloadbegin %i %s\n", host_client->downloadsize, name); + char *s = va("\ncl_downloadbegin %i %s\n", host_client->downloadsize, host_client->downloadfn); ClientReliableWrite_Begin (host_client, svc_stufftext, 2+strlen(s)); ClientReliableWrite_String (host_client, s); } @@ -2118,7 +2302,7 @@ void SV_BeginDownload_f(void) SV_NextDownload_f (); SV_EndRedirect(); - Con_Printf ("Downloading %s to %s\n", name, host_client->name); + Con_Printf ("Downloading %s to %s\n", host_client->downloadfn, host_client->name); } void SV_StopDownload_f(void) @@ -3129,12 +3313,12 @@ void Cmd_Give_f (void) break; } } - else if (host_client->netchan.remote_address.type == NA_LOOPBACK) //we don't want clients doing nasty things... like setting movetype 3123 + else if (developer.value || host_client->netchan.remote_address.type == NA_LOOPBACK) //we don't want clients doing nasty things... like setting movetype 3123 { int oldself; oldself = pr_global_struct->self; pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); - Con_Printf("Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args())); + SV_ClientPrintf(host_client, PRINT_HIGH, "Result: %s\n", svprogfuncs->EvaluateDebugString(svprogfuncs, Cmd_Args())); pr_global_struct->self = oldself; } @@ -3550,6 +3734,7 @@ ucmd_t ucmds[] = {"serverinfo", SV_ShowServerinfo_f}, + {"dlsize", SV_DownloadSize_f}, {"download", SV_BeginDownload_f}, {"nextdl", SV_NextDownload_f}, @@ -3665,11 +3850,11 @@ void SV_ExecuteUserCommand (char *s, qboolean fromQC) host_client = oldhost; return; } - SV_BeginRedirect (RD_CLIENT, host_client->language); +// SV_BeginRedirect (RD_CLIENT, host_client->language); if (u->func) u->func (); host_client = oldhost; - SV_EndRedirect (); +// SV_EndRedirect (); return; } @@ -4083,13 +4268,13 @@ void SVNQ_Ping_f(void) int i; client_t *cl; - Con_Printf ("Ping times:\n"); + SV_PrintToClient(host_client, PRINT_HIGH, "Client ping times:\n"); for (i=0,cl=svs.clients ; istate) continue; - Con_Printf ("%3i %s\n", SV_CalcPing (cl), cl->name); + SV_PrintToClient(host_client, PRINT_HIGH, va("%3i %s\n", SV_CalcPing (cl), cl->name)); } } @@ -4276,7 +4461,7 @@ AddLinksToPmove ==================== */ -void AddLinksToPmove ( areanode_t *node ) +void AddLinksToPmove ( edict_t *player, areanode_t *node ) { int Q1_HullPointContents (hull_t *hull, int num, vec3_t p); link_t *l, *next; @@ -4287,7 +4472,7 @@ void AddLinksToPmove ( areanode_t *node ) model_t *model; - pl = EDICT_TO_PROG(svprogfuncs, sv_player); + pl = EDICT_TO_PROG(svprogfuncs, player); // touch linked edicts for (l = node->solid_edicts.next ; l != &node->solid_edicts ; l = next) @@ -4301,7 +4486,7 @@ void AddLinksToPmove ( areanode_t *node ) || check->v->solid == SOLID_BBOX || check->v->solid == SOLID_SLIDEBOX) { - if (check == sv_player) + if (check == player) continue; for (i=0 ; i<3 ; i++) @@ -4314,8 +4499,8 @@ void AddLinksToPmove ( areanode_t *node ) if (pmove.numphysent == MAX_PHYSENTS) break; pe = &pmove.physents[pmove.numphysent]; - pe->notouch = !((int)sv_player->xv->dimension_solid & (int)check->xv->dimension_hit); - if (!((int)sv_player->xv->dimension_hit & (int)check->xv->dimension_solid)) + pe->notouch = !((int)player->xv->dimension_solid & (int)check->xv->dimension_hit); + if (!((int)player->xv->dimension_hit & (int)check->xv->dimension_solid)) continue; pmove.numphysent++; @@ -4337,7 +4522,7 @@ void AddLinksToPmove ( areanode_t *node ) } } } - if (sv_player->v->mins[2] != 24) //crouching/dead + if (player->v->mins[2] != 24) //crouching/dead for (l = node->trigger_edicts.next ; l != &node->trigger_edicts ; l = next) { next = l->next; @@ -4354,14 +4539,14 @@ void AddLinksToPmove ( areanode_t *node ) if (i != 3) continue; - if (!((int)sv_player->xv->dimension_hit & (int)check->xv->dimension_solid)) + if (!((int)player->xv->dimension_hit & (int)check->xv->dimension_solid)) continue; model = sv.models[(int)check->v->modelindex]; if (model) // test the point - if ( model->funcs.PointContents (model, sv_player->v->origin) == FTECONTENTS_SOLID ) - sv_player->xv->fteflags = (int)sv_player->xv->fteflags | FF_LADDER; //touch that ladder! + if (model->funcs.PointContents (model, player->v->origin) == FTECONTENTS_SOLID) + player->xv->fteflags = (int)player->xv->fteflags | FF_LADDER; //touch that ladder! } } @@ -4369,10 +4554,10 @@ void AddLinksToPmove ( areanode_t *node ) if (node->axis == -1) return; - if ( pmove_maxs[node->axis] > node->dist ) - AddLinksToPmove ( node->children[0] ); - if ( pmove_mins[node->axis] < node->dist ) - AddLinksToPmove ( node->children[1] ); + if (pmove_maxs[node->axis] > node->dist) + AddLinksToPmove (player, node->children[0]); + if (pmove_mins[node->axis] < node->dist) + AddLinksToPmove (player, node->children[1]); } @@ -4758,7 +4943,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) pmove.numphysent = 1; pmove.physents[0].model = sv.worldmodel; pmove.cmd = *ucmd; - if (sv.worldmodel->fromgame == fg_quake2 || sv.worldmodel->fromgame == fg_quake3) + if (sv.worldmodel->fromgame == fg_quake) pmove.hullnum = ((int)sv_player->xv->fteflags&FF_CROUCHING)?3:1; else pmove.hullnum = SV_HullNumForPlayer(sv_player->xv->hull, sv_player->v->mins, sv_player->v->maxs); @@ -4782,7 +4967,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) } sv_player->xv->fteflags = (int)sv_player->xv->fteflags & ~FF_LADDER; //assume not touching ladder trigger #if 1 - AddLinksToPmove ( sv_areanodes ); + AddLinksToPmove ( sv_player, sv_areanodes ); #else AddAllEntsToPmove (); #endif @@ -5421,6 +5606,8 @@ void SVNQ_ReadClientMove (usercmd_t *move) int i; int bits; client_frame_t *frame; + float timesincelast; + float cltime; frame = &host_client->frameunion.frames[host_client->netchan.incoming_acknowledged & UPDATE_MASK]; @@ -5428,7 +5615,18 @@ void SVNQ_ReadClientMove (usercmd_t *move) host_client->last_sequence = MSG_ReadLong (); else host_client->last_sequence = 0; - frame->ping_time = sv.time - MSG_ReadFloat (); + cltime = MSG_ReadFloat (); + if (cltime > sv.time) + cltime = sv.time; + if (cltime < sv.time - 2) //if you do lag more than this, you won't get your free time. + cltime = sv.time - 2; + if (cltime < move->fservertime) + cltime = move->fservertime; + timesincelast = cltime - move->fservertime; + move->fservertime = cltime; + move->servertime = move->fservertime; + + frame->ping_time = sv.time - cltime; // read current angles @@ -5444,7 +5642,7 @@ void SVNQ_ReadClientMove (usercmd_t *move) move->sidemove = MSG_ReadShort (); move->upmove = MSG_ReadShort (); - move->msec=(1/72.0f)*1000;//MSG_ReadFloat; + move->msec=timesincelast*1000;//MSG_ReadFloat; // read buttons if (host_client->protocol == SCP_DARKPLACES6 || host_client->protocol == SCP_DARKPLACES7) @@ -5519,7 +5717,13 @@ void SVNQ_ReadClientMove (usercmd_t *move) host_client->edict->xv->button8 = ((bits >> 7) & 1); if (host_client->last_sequence) + { + host_frametime = timesincelast; SV_RunEntity(host_client->edict); + host_client->isindependant = true; + } + else + host_client->isindependant = false; } void SVNQ_ExecuteClientMessage (client_t *cl) @@ -5599,6 +5803,9 @@ void SVNQ_ExecuteClientMessage (client_t *cl) sv_player = cl->edict; break; + case 50: + MSG_ReadLong(); + break; case clcdp_ackdownloaddata: SV_DarkPlacesDownloadAck(host_client); break; diff --git a/engine/server/svmodel.c b/engine/server/svmodel.c index 44b5523fd..8167f7605 100644 --- a/engine/server/svmodel.c +++ b/engine/server/svmodel.c @@ -1242,10 +1242,10 @@ qboolean Mod_LoadClipnodes (lump_t *l) hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; - hull->clip_mins[2] = -36; + hull->clip_mins[2] = -32;//-36 is correct here, but we'll just copy mvdsv instead. hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; - hull->clip_maxs[2] = 36; + hull->clip_maxs[2] = hull->clip_mins[2]+72; hull->available = true; hull = &loadmodel->hulls[2]; @@ -1258,7 +1258,7 @@ qboolean Mod_LoadClipnodes (lump_t *l) hull->clip_mins[2] = -32; hull->clip_maxs[0] = 32; hull->clip_maxs[1] = 32; - hull->clip_maxs[2] = 32; + hull->clip_maxs[2] = hull->clip_mins[2]+64; hull->available = true; hull = &loadmodel->hulls[3]; @@ -1271,7 +1271,7 @@ qboolean Mod_LoadClipnodes (lump_t *l) hull->clip_mins[2] = -18; hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; - hull->clip_maxs[2] = 18; + hull->clip_maxs[2] = hull->clip_mins[2]+36; hull->available = true; } else diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 5a127e798..bc0fcb879 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -4,7 +4,6 @@ //requires qvm implementation and existing q3 client stuff (or at least the overlapping stuff in q3common.c). #ifdef Q3SERVER - float RadiusFromBounds (vec3_t mins, vec3_t maxs); @@ -249,6 +248,7 @@ static qboolean BoundsIntersect (vec3_t mins1, vec3_t maxs1, vec3_t mins2, vec3_ void SVQ3_CreateBaseline(void); void SVQ3_ClientThink(client_t *cl); +void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3); char *mapentspointer; @@ -791,8 +791,8 @@ qboolean SVQ3_GetUserCmd(int clientnumber, q3usercmd_t *ucmd) ucmd->angles[0] = cmd->angles[0]; ucmd->angles[1] = cmd->angles[1]; ucmd->angles[2] = cmd->angles[2]; - ucmd->serverTime = cmd->servertime; - ucmd->forwardmove = cmd->forwardmove; + ucmd->serverTime = (signed char)cmd->servertime; + ucmd->forwardmove = (signed char)cmd->forwardmove; ucmd->rightmove = cmd->sidemove; ucmd->upmove = cmd->upmove; ucmd->buttons = cmd->buttons; @@ -1115,7 +1115,7 @@ int Q3G_SystemCallsEx(void *offset, unsigned int mask, int fn, const int *arg) { void *dst = VM_POINTER(arg[0]); void *src = VM_POINTER(arg[1]); - Q_strncpyS(src, dst, arg[2]); + Q_strncpyS(dst, src, arg[2]); } break; case G_SIN: @@ -1665,7 +1665,7 @@ void BL_Free(void *mem) { int *memref = ((int *)mem) - 1; botlibmemoryavailable+=memref[0]; - Z_Free(memref); + Z_TagFree(memref); } void *BL_HunkMalloc(int size) { @@ -1848,7 +1848,7 @@ qboolean SVQ3_InitGame(void) } else { - if (sv.worldmodel->fromgame == fg_quake || sv.worldmodel->fromgame == fg_quake2) + if (sv.worldmodel->fromgame == fg_quake || sv.worldmodel->fromgame == fg_halflife || sv.worldmodel->fromgame == fg_quake2) return false; //always fail on q1bsp } @@ -1996,7 +1996,7 @@ void SVQ3_CreateBaseline(void) //Writes the entities to the clients void SVQ3_EmitPacketEntities(client_t *client, q3client_frame_t *from, q3client_frame_t *to, sizebuf_t *msg) { - q3entityState_t *oldent = {0}, *newent = {0}; + q3entityState_t *oldent, *newent; int oldindex, newindex; int oldnum, newnum; int from_num_entities; @@ -2050,7 +2050,16 @@ void SVQ3_EmitPacketEntities(client_t *client, q3client_frame_t *from, q3client_ if(newnum < oldnum) { // this is a new entity, send it from the baseline + if (svs.gametype == GT_QUAKE3) MSGQ3_WriteDeltaEntity( msg, &q3_baselines[newnum], newent, true ); + else + { + q3entityState_t q3base; + edict_t *e; + e = EDICT_NUM(svprogfuncs, newnum); + SVQ3Q1_ConvertEntStateQ1ToQ3(&e->baseline, &q3base); + MSGQ3_WriteDeltaEntity( msg, &q3base, newent, true ); + } newindex++; continue; } @@ -2074,7 +2083,7 @@ void SVQ3_WriteSnapshotToClient(client_t *client, sizebuf_t *msg) int delta; int i; - // this is a frame we are creating + // this is the frame we are transmitting snap = &client->frameunion.q3frames[client->netchan.outgoing_sequence & Q3UPDATE_MASK]; if(client->state < cs_spawned) @@ -2149,15 +2158,18 @@ int clientarea; qbyte *areabits; qbyte *bitvector; -static int VARGS SVQ3_QsortEntityStates( const void *arg1, const void *arg2 ) { +static int VARGS SVQ3_QsortEntityStates( const void *arg1, const void *arg2 ) +{ const q3entityState_t *s1 = *(const q3entityState_t **)arg1; const q3entityState_t *s2 = *(const q3entityState_t **)arg2; - if( s1->number > s2->number ) { + if( s1->number > s2->number ) + { return 1; } - if( s1->number < s2->number ) { + if( s1->number < s2->number ) + { return -1; } @@ -2167,44 +2179,55 @@ static int VARGS SVQ3_QsortEntityStates( const void *arg1, const void *arg2 ) { } -static qboolean SVQ3_EntityIsVisible( q3sharedEntity_t *ent ) { +static qboolean SVQ3_EntityIsVisible( q3sharedEntity_t *ent ) +{ q3serverEntity_t *sent; int i; int l; - if( !ent->r.linked ) { + if (!ent->r.linked) + { return false; // not active entity } - if( ent->r.svFlags & SVF_NOCLIENT ) { + if (ent->r.svFlags & SVF_NOCLIENT ) + { return false; // set to invisible } - if( ent->r.svFlags & SVF_CLIENTMASK ) { - if( clientNum > 32 ) { + if (ent->r.svFlags & SVF_CLIENTMASK) + { + if (clientNum > 32) + { SV_Error("SVF_CLIENTMASK: clientNum > 32" ); } - if( ent->r.singleClient & (1 << (clientNum & 7)) ) { + if (ent->r.singleClient & (1 << (clientNum & 7))) + { return true; } return false; } - if( ent->r.svFlags & SVF_SINGLECLIENT ) { - if( ent->r.singleClient == clientNum ) { + if (ent->r.svFlags & SVF_SINGLECLIENT) + { + if ( ent->r.singleClient == clientNum) + { return true; } return false; } - if( ent->r.svFlags & SVF_NOTSINGLECLIENT ) { - if( ent->r.singleClient == clientNum ) { + if (ent->r.svFlags & SVF_NOTSINGLECLIENT) + { + if (ent->r.singleClient == clientNum) + { return false; } // FIXME: fall through } - if( ent->r.svFlags & SVF_BROADCAST ) { + if (ent->r.svFlags & SVF_BROADCAST) + { return true; } @@ -2214,40 +2237,51 @@ static qboolean SVQ3_EntityIsVisible( q3sharedEntity_t *ent ) { sent = SENTITY_FOR_GENTITY( ent ); // check area - if( sent->areanum < 0 || !(areabits[sent->areanum >> 3] & (1 << (sent->areanum & 7))) ) { + if (sent->areanum < 0 || !(areabits[sent->areanum >> 3] & (1 << (sent->areanum & 7)))) + { // doors can legally straddle two areas, so // we may need to check another one - if( sent->areanum2 < 0 || !(areabits[sent->areanum2 >> 3] & (1 << (sent->areanum2 & 7))) ) { + if (sent->areanum2 < 0 || !(areabits[sent->areanum2 >> 3] & (1 << (sent->areanum2 & 7)))) + { return false; // blocked by a door } } /* // check area - if( !CM_AreasConnected( clientarea, sent->areanum ) ) { + if( !CM_AreasConnected( clientarea, sent->areanum ) ) + { // doors can legally straddle two areas, so // we may need to check another one - if( !CM_AreasConnected( clientarea, sent->areanum2 ) ) { + if( !CM_AreasConnected( clientarea, sent->areanum2 ) ) + { return false; // blocked by a door } } */ - if( sent->num_clusters == -1 ) { + if (sent->num_clusters == -1) + { // too many leafs for individual check, go by headnode - if( !CM_HeadnodeVisible(sv.worldmodel, sent->headnode, bitvector ) ) { + if (!CM_HeadnodeVisible(sv.worldmodel, sent->headnode, bitvector)) + { return false; } - } else { + } + else + { // check individual leafs - for( i=0 ; i < sent->num_clusters ; i++ ) { + for (i=0; i < sent->num_clusters; i++) + { l = sent->clusternums[i]; - if( bitvector[l >> 3] & (1 << (l & 7) ) ) { + if (bitvector[l >> 3] & (1 << (l & 7))) + { break; } } - if( i == sent->num_clusters ) { + if (i == sent->num_clusters) + { return false; // not visible } } @@ -2255,6 +2289,57 @@ static qboolean SVQ3_EntityIsVisible( q3sharedEntity_t *ent ) { return true; } +q3playerState_t *SVQ3Q1_BuildPlayerState(client_t *client) +{ + static q3playerState_t state; + extern cvar_t sv_gravity; + + memset(&state, 0, sizeof(state)); + +#pragma message("qwoverq3: other things will need to be packed into here.") + + state.commandTime = client->lastcmd.servertime; + + state.pm_type = client->edict->v->movetype; + state.origin[0] = client->edict->v->origin[0]; + state.origin[1] = client->edict->v->origin[1]; + state.origin[2] = client->edict->v->origin[2]; + state.velocity[0] = client->edict->v->velocity[0]; + state.velocity[1] = client->edict->v->velocity[1]; + state.velocity[2] = client->edict->v->velocity[2]; + + client->maxspeed = client->edict->xv->maxspeed; + if (!client->maxspeed) + client->maxspeed = sv_maxspeed.value; + client->entgravity = client->edict->xv->gravity * sv_gravity.value; + if (!client->entgravity) + client->entgravity = sv_gravity.value; + if (client->edict->xv->hasted) + client->maxspeed *= client->edict->xv->hasted; + state.speed = client->maxspeed; + state.gravity = client->entgravity; + + state.viewangles[0] = client->edict->v->angles[0]; + state.viewangles[1] = client->edict->v->angles[1]; + state.viewangles[2] = client->edict->v->angles[2]; + + state.clientNum = client - svs.clients; + state.weapon = client->edict->v->weapon; + + state.stats[0] = client->edict->v->health; + state.stats[2] = (int)client->edict->v->items&1023; + state.stats[3] = client->edict->v->armorvalue; + state.stats[4] = client->edict->v->angles[1]; + state.stats[6] = client->edict->v->max_health; + state.persistant[0] = client->edict->v->frags; + state.ammo[0] = client->edict->v->currentammo; + state.ammo[1] = client->edict->v->ammo_shells; + state.ammo[2] = client->edict->v->ammo_nails; + state.ammo[3] = client->edict->v->ammo_rockets; + state.ammo[4] = client->edict->v->ammo_cells; + return &state; +} + void SVQ3_BuildClientSnapshot( client_t *client ) { q3entityState_t *entityStates[MAX_ENTITIES_IN_SNAPSHOT]; @@ -2267,9 +2352,24 @@ void SVQ3_BuildClientSnapshot( client_t *client ) int portalarea; int i; + if (!q3_snapshot_entities) + { + q3_num_snapshot_entities = 32 * Q3UPDATE_BACKUP * 32; + q3_next_snapshot_entities = 0; + q3_snapshot_entities = BZ_Malloc(sizeof( q3entityState_t ) * q3_num_snapshot_entities); + } + clientNum = client - svs.clients; + if (svs.gametype == GT_QUAKE3) + { clent = GENTITY_FOR_NUM( clientNum ); ps = PS_FOR_NUM( clientNum ); + } + else + { + clent = NULL; + ps = SVQ3Q1_BuildPlayerState(client); + } // this is the frame we are creating snap = &client->frameunion.q3frames[client->netchan.outgoing_sequence & Q3UPDATE_MASK]; @@ -2315,25 +2415,19 @@ void SVQ3_BuildClientSnapshot( client_t *client ) snap->num_entities = 0; snap->first_entity = q3_next_snapshot_entities; + if (svs.gametype == GT_QUAKE3) + { // check for SVF_PORTAL entities first for( i=0 ; ir.svFlags & SVF_PORTAL) ) - { continue; - } - if( !SVQ3_EntityIsVisible( ent ) ) - { continue; - } // merge PVS if portal portalarea = CM_PointLeafnum(sv.worldmodel, ent->s.origin2); @@ -2349,16 +2443,13 @@ void SVQ3_BuildClientSnapshot( client_t *client ) { ent = GENTITY_FOR_NUM( i ); - if( ent == clent ) { + if (ent == clent) continue; - } - if( !SVQ3_EntityIsVisible( ent ) ) - { continue; - } - if( ent->s.number != i ) { + if (ent->s.number != i) + { Con_DPrintf( "FIXING ENT->S.NUMBER!!!\n" ); ent->s.number = i; } @@ -2370,7 +2461,22 @@ void SVQ3_BuildClientSnapshot( client_t *client ) Con_DPrintf( "MAX_ENTITIES_IN_SNAPSHOT\n" ); break; } - + } + } + else + { //our q1->q3 converter + packet_entities_t pack; + entity_state_t packentities[64]; + q3entityState_t q3packentities[64]; + pack.entities = packentities; + pack.max_entities = sizeof(packentities)/sizeof(packentities[0]); + //get the q1 code to generate a packet + SVQ3Q1_BuildEntityPacket(client, &pack); + for (i = 0; i < pack.num_entities; i++) + { //map the packet fields to q3. + SVQ3Q1_ConvertEntStateQ1ToQ3(&pack.entities[i], &q3packentities[i]); + entityStates[snap->num_entities++] = &q3packentities[i]; + } } if( q3_next_snapshot_entities + snap->num_entities >= 0x7FFFFFFE ) @@ -2399,6 +2505,165 @@ void SVQ3_BuildClientSnapshot( client_t *client ) } +void SVQ3Q1_ConvertEntStateQ1ToQ3(entity_state_t *q1, q3entityState_t *q3) +{ +#pragma message("qwoverq3: This _WILL_ need extending") + q3->number = q1->number; + + q3->pos.trTime = 0; + q3->pos.trBase[0] = 0; + q3->pos.trBase[1] = 0; + q3->pos.trDelta[0] = 0; + q3->pos.trDelta[1] = 0; + q3->pos.trBase[2] = 0; + q3->apos.trBase[1] = 0; + q3->pos.trDelta[2] = 0; + q3->apos.trBase[0] = 0; + q3->event = q1->event; + q3->angles2[1] = 0; + q3->eType = 0; + q3->torsoAnim = q1->skinnum; + q3->eventParm = 0; + q3->legsAnim = 0; + q3->groundEntityNum = 0; + q3->pos.trType = 0; + q3->eFlags = q1->flags; + q3->otherEntityNum = 0; + q3->weapon = 0; + q3->clientNum = q1->colormap; + q3->angles[1] = q1->angles[0]; + q3->pos.trDuration = 0; + q3->apos.trType = 0; + q3->origin[0] = q1->origin[0]; + q3->origin[1] = q1->origin[1]; + q3->origin[2] = q1->origin[2]; + q3->solid = q1->solid; + q3->powerups = q1->effects; + q3->modelindex = q1->modelindex; + q3->otherEntityNum2 = 0; + q3->loopSound = q1->sound; + q3->generic1 = q1->trans; + q3->origin2[2] = q1->old_origin[2]; + q3->origin2[0] = q1->old_origin[0]; + q3->origin2[1] = q1->old_origin[1]; + q3->modelindex2 = q1->modelindex2; + q3->angles[0] = q1->angles[0]; + q3->time = 0; + q3->apos.trTime = 0; + q3->apos.trDuration = 0; + q3->apos.trBase[2] = 0; + q3->apos.trDelta[0] = 0; + q3->apos.trDelta[1] = 0; + q3->apos.trDelta[2] = 0; + q3->time2 = 0; + q3->angles[2] = q1->angles[2]; + q3->angles2[0] = 0; + q3->angles2[2] = 0; + q3->constantLight = q1->abslight; + q3->frame = q1->frame; + +#if 0 + +//these are the things I've not packed in to the above structure yet. +#if defined(Q2CLIENT) || defined(Q2SERVER) + int renderfx; //q2 + qbyte modelindex3; //q2 + qbyte modelindex4; //q2 +#endif + qbyte glowsize; + qbyte glowcolour; + qbyte scale; + char fatness; + qbyte hexen2flags; + qbyte dpflags; + qbyte colormod[3];//multiply this by 8 to read as 0 to 1... + qbyte lightstyle; + qbyte lightpflags; + unsigned short light[4]; + unsigned short tagentity; + unsigned short tagindex; +#endif +} + +void SVQ3Q1_SendGamestateConfigstrings(sizebuf_t *msg) +{ + const int cs_models = 32; + const int cs_sounds = cs_models + 256; + const int cs_players = cs_sounds + 256; + + int i, j; + + char *str; + char sysinfo[MAX_SERVERINFO_STRING]; + char *cfgstr[MAX_CONFIGSTRINGS]; + + //an empty crc string means we let the client use any + //but then it doesn't download our qwoverq3 thing. + char *refpackcrcs = "";//"-1309355180 0 0 0 0 0 0 0 0 0"; + char *refpacknames = "baseq3/pak0 baseq3/pak1 baseq3/pak2 baseq3/pak3 baseq3/pak4 baseq3/pak5 baseq3/pak6 baseq3/pak7 baseq3/pak8 fte/qwoverq3"; + + memset(cfgstr, 0, sizeof(cfgstr)); + + sysinfo[0] = 0; + Info_SetValueForKey(sysinfo, "sv_serverid", va("%i", svs.spawncount), sizeof(sysinfo)); + + str = refpackcrcs;//FS_GetPackHashes(buffer, sizeof(buffer), false); + Info_SetValueForKey(sysinfo, "sv_paks", str, sizeof(sysinfo)); + + str = refpacknames;//FS_GetPackNames(buffer, sizeof(buffer), false); + Info_SetValueForKey(sysinfo, "sv_pakNames", str, sizeof(sysinfo)); + + str = refpackcrcs;//FS_GetPackHashes(buffer, sizeof(buffer), true); + Info_SetValueForKey(sysinfo, "sv_referencedPaks", str, sizeof(sysinfo)); + + str = refpacknames;//FS_GetPackNames(buffer, sizeof(buffer), true); + Info_SetValueForKey(sysinfo, "sv_referencedPakNames", str, sizeof(sysinfo)); + +Con_Printf("Sysinfo: %s\n", sysinfo); + str = "0"; + Info_SetValueForKey(sysinfo, "sv_pure", str, sizeof(sysinfo)); + + str = "qwoverq3"; + Info_SetValueForKey(sysinfo, "fs_game", str, sizeof(sysinfo)); + + cfgstr[0] = svs.info; + cfgstr[1] = sysinfo; + + cfgstr[2] = NULL;//sv.cdtrack; + cfgstr[3] = sv.mapname; + cfgstr[20] = "QuakeWorld-Over-Q3"; //you can get the gamedir out of the serverinfo + + //add in 32 clients + for (i = 0; i < MAX_CLIENTS; i++) + { + cfgstr[cs_players+i] = svs.clients[i].userinfo; + } + + //fill up the last half with sound/model names + //note that we're limited to only 256 models/sounds + for (i = 2; i < 256; i++) + { + cfgstr[cs_models+i] = sv.strings.model_precache[i]; + } + for (i = 0; i < 256; i++) + { + cfgstr[cs_sounds+i] = sv.strings.sound_precache[i]; + } + + // write configstrings + for (i = 0; i < MAX_CONFIGSTRINGS; i++) + { + str = cfgstr[i]; + if (!str || !*str) + continue; + + MSG_WriteBits(msg, svcq3_configstring, 8); + MSG_WriteBits(msg, i, 16); + for (j = 0; str[j]; j++) + MSG_WriteBits(msg, str[j], 8); + MSG_WriteBits(msg, 0, 8); + } +} //writes initial gamestate void SVQ3_SendGameState(client_t *client) @@ -2422,6 +2687,9 @@ void SVQ3_SendGameState(client_t *client) MSG_WriteBits(&msg, svcq3_gamestate, 8 ); MSG_WriteBits(&msg, client->num_client_commands, 32); + switch (svs.gametype) + { + case GT_QUAKE3: // write configstrings for( i=0; ibaseline.modelindex) + { + q3entityState_t q3base; + SVQ3Q1_ConvertEntStateQ1ToQ3(&e->baseline, &q3base); + MSG_WriteBits(&msg, svcq3_baseline, 8); + MSGQ3_WriteDeltaEntity(&msg, NULL, &q3base, true); + } + } + break; + } // write svc_eom command MSG_WriteBits(&msg, svcq3_eom, 8); @@ -2670,6 +2956,7 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta) // read delta sequenced usercmds from = &nullcmd; + from->servertime = client->lastcmd.servertime; for(i=0, to=commands; ilastcmd, &commands[cmdCount-1], sizeof(client->lastcmd)); - SVQ3_ClientBegin(client); + if (svs.gametype == GT_QUAKE3) + SVQ3_ClientBegin(client); + else + { + sv_player = host_client->edict; + SV_Begin_Core(client); + } client->state = cs_spawned; break; case cs_spawned: // run G_ClientThink() on each usercmd + if (svs.gametype != GT_QUAKE3) + { + sv_player = host_client->edict; + SV_PreRunCmd(); + } for(i=0,to=commands; iservertime <= client->lastcmd.servertime ) -// continue; + if(to->servertime <= client->lastcmd.servertime ) + continue; memcpy( &client->lastcmd, to, sizeof(client->lastcmd)); + if (svs.gametype == GT_QUAKE3) SVQ3_ClientThink(client); + else + { + usercmd_t temp; + temp = client->lastcmd; +#pragma message("qwoverq3: you need to be aware of this if you're making a compatible cgame") + //if you read the q3 code, you'll see that the speed value used is 64 for walking, and 127 for running (full speed). + //so we map full to full here. + temp.sidemove *= client->maxspeed/127.0f; + temp.forwardmove *= client->maxspeed/127.0f; + temp.upmove *= client->maxspeed/127.0f; + + temp.buttons &= ~2; + if (temp.buttons & 64) + temp.buttons |= 2; + SV_RunCmd(&temp, false); } + } + if (svs.gametype != GT_QUAKE3) + SV_PostRunCmd(); break; default: break; // outdated usercmd packet @@ -2707,6 +3024,7 @@ void SVQ3_UpdateUserinfo_f(client_t *cl) SV_ExtractFromUserinfo (cl); + if (svs.gametype == GT_QUAKE3) VM_Call(q3gamevm, GAME_CLIENT_USERINFO_CHANGED, (int)(cl-svs.clients)); } @@ -2784,6 +3102,7 @@ void SVQ3_ParseClientCommand(client_t *client) // TODO - flood protection + if (svs.gametype == GT_QUAKE3) if(!u->name && sv.state == ss_active) SVQ3_ClientCommand(client); } @@ -2822,7 +3141,9 @@ void SVQ3_ParseClientMessage(client_t *client) if(client->gamestatesequence>=0) { if( client->last_sequence - client->gamestatesequence < 100 ) + { return; // don't resend gameState too frequently + } Con_DPrintf( "%s : dropped gamestate, resending\n", client->name ); } @@ -2917,6 +3238,7 @@ void SVQ3_HandleClient(void) bannedips_t *SV_BannedAddress (netadr_t *a); void SVQ3_DirectConnect(void) //Actually connect the client, use up a slot, and let the gamecode know of it. { + //this is only called when running q3 gamecode char *reason; client_t *cl; char *userinfo = NULL; diff --git a/engine/server/world.c b/engine/server/world.c index 74081824e..464289e4c 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -1753,7 +1753,7 @@ void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) if (touch == clip->passedict) continue; if (touch->v->solid == SOLID_TRIGGER || touch->v->solid == SOLID_LADDER) - SV_Error ("Trigger in clipping list"); + SV_Error ("Trigger (%s) in clipping list", PR_StringToNative(svprogfuncs, touch->v->classname)); if (clip->type & MOVE_NOMONSTERS && touch->v->solid != SOLID_BSP) continue; diff --git a/engine/sw/d_iface.h b/engine/sw/d_iface.h index 29c2513c6..c00d1fa29 100644 --- a/engine/sw/d_iface.h +++ b/engine/sw/d_iface.h @@ -143,7 +143,7 @@ void D_PolysetDraw16 (void); void D_PolysetDraw32 (void); void D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts); void D_PolysetDrawFinalVerts32Trans (finalvert_t *fv, int numverts); -void D_DrawParticle (particle_t *pparticle); +void D_DrawParticle (vec3_t porg, float palpha, float pscale, unsigned int pcolour); void D_DrawPoly (void); void D_DrawSprite (void); void D_DrawSurfaces (void); diff --git a/engine/sw/d_ifacea.h b/engine/sw/d_ifacea.h index 2824204fa..79bd9835c 100644 --- a/engine/sw/d_ifacea.h +++ b/engine/sw/d_ifacea.h @@ -46,8 +46,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // particle_t structure // !!! if this is changed, it must be changed in d_iface.h too !!! // driver-usable fields -#define pt_org 8 -#define pt_color 20 +//#define pt_org 8 +//#define pt_color 20 // drivers never touch the following fields /*#define pt_next 16 #define pt_vel 20 diff --git a/engine/sw/d_part.c b/engine/sw/d_part.c index 88954a8ce..e8ba11d16 100644 --- a/engine/sw/d_part.c +++ b/engine/sw/d_part.c @@ -46,14 +46,14 @@ void D_StartParticles (void) // not used by software driver } -#if !id386 - /* ============== D_DrawParticle ============== */ -void D_DrawParticle (particle_t *pparticle) +#if !id386 + +void D_DrawParticleC (vec3_t porg, float palpha, float pscale, unsigned int pcolour) { vec3_t local, transformed; float zi; @@ -62,7 +62,7 @@ void D_DrawParticle (particle_t *pparticle) int i, izi, pix, count, u, v; // transform point - VectorSubtract (pparticle->org, r_origin, local); + VectorSubtract (porg, r_origin, local); transformed[0] = DotProduct(local, r_pright); transformed[1] = DotProduct(local, r_pup); @@ -90,7 +90,7 @@ void D_DrawParticle (particle_t *pparticle) izi = (int)(zi * PARTICLEFACTOR); pix = izi >> d_pix_shift; - pix *= pparticle->scale; + pix *= pscale; if (pix < d_pix_min) pix = d_pix_min; @@ -107,7 +107,7 @@ void D_DrawParticle (particle_t *pparticle) if (pz[0] <= izi) { // pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pcolour; } } break; @@ -120,13 +120,13 @@ void D_DrawParticle (particle_t *pparticle) if (pz[0] <= izi) { // pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pcolour; } if (pz[1] <= izi) { // pz[1] = izi; - pdest[1] = pparticle->color; + pdest[1] = pcolour; } } break; @@ -139,19 +139,19 @@ void D_DrawParticle (particle_t *pparticle) if (pz[0] <= izi) { // pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pcolour; } if (pz[1] <= izi) { // pz[1] = izi; - pdest[1] = pparticle->color; + pdest[1] = pcolour; } if (pz[2] <= izi) { // pz[2] = izi; - pdest[2] = pparticle->color; + pdest[2] = pcolour; } } break; @@ -164,25 +164,25 @@ void D_DrawParticle (particle_t *pparticle) if (pz[0] <= izi) { // pz[0] = izi; - pdest[0] = pparticle->color; + pdest[0] = pcolour; } if (pz[1] <= izi) { // pz[1] = izi; - pdest[1] = pparticle->color; + pdest[1] = pcolour; } if (pz[2] <= izi) { // pz[2] = izi; - pdest[2] = pparticle->color; + pdest[2] = pcolour; } if (pz[3] <= izi) { // pz[3] = izi; - pdest[3] = pparticle->color; + pdest[3] = pcolour; } } break; @@ -197,7 +197,7 @@ void D_DrawParticle (particle_t *pparticle) if (pz[i] <= izi) { // pz[i] = izi; - pdest[i] = pparticle->color; + pdest[i] = pcolour; } } } @@ -207,7 +207,7 @@ void D_DrawParticle (particle_t *pparticle) #endif // !id386 -void D_DrawParticle16 (particle_t *pparticle) +void D_DrawParticle16 (vec3_t porg, float palpha, float pscale, unsigned int pcolour) { vec3_t local, transformed; float zi; @@ -216,11 +216,11 @@ void D_DrawParticle16 (particle_t *pparticle) short *pz; int i, izi, pix, count, u, v; - if (pparticle->alpha <= 0.2) + if (palpha <= 0.2) return; // transform point - VectorSubtract (pparticle->org, r_origin, local); + VectorSubtract (porg, r_origin, local); transformed[0] = DotProduct(local, r_pright); transformed[1] = DotProduct(local, r_pup); @@ -246,7 +246,7 @@ void D_DrawParticle16 (particle_t *pparticle) pz = d_pzbuffer + (d_zwidth * v) + u; izi = (int)(zi * PARTICLEFACTOR); - pix = ((int)(izi*pparticle->scale)); + pix = ((int)(izi*pscale)); if (pix < d_pix_min) pix = d_pix_min; @@ -259,7 +259,7 @@ void D_DrawParticle16 (particle_t *pparticle) if (v < 0) v = 0; pdest = (unsigned short *)d_viewbuffer + ((d_scantable[v] + u)); - a = 255*pparticle->alpha; + a = 255*palpha; switch (pix) { @@ -273,7 +273,7 @@ void D_DrawParticle16 (particle_t *pparticle) if (pz[i] <= izi) { // pz[i] = izi; - pdest[i] = d_8to16table[(int)pparticle->color]; + pdest[i] = d_8to16table[pcolour]; } } } @@ -281,7 +281,7 @@ void D_DrawParticle16 (particle_t *pparticle) } } -void D_DrawParticle32 (particle_t *pparticle) +void D_DrawParticle32 (vec3_t porg, float palpha, float pscale, unsigned int pcolour) { vec3_t local, transformed; float zi; @@ -291,11 +291,11 @@ void D_DrawParticle32 (particle_t *pparticle) short *pz; int i, izi, pix, count, u, v; - if (pparticle->alpha <= 0.0) + if (palpha <= 0.0) return; // transform point - VectorSubtract (pparticle->org, r_origin, local); + VectorSubtract (porg, r_origin, local); transformed[0] = DotProduct(local, r_pright); transformed[1] = DotProduct(local, r_pup); @@ -321,7 +321,7 @@ void D_DrawParticle32 (particle_t *pparticle) pz = d_pzbuffer + (d_zwidth * v) + u; izi = (int)(zi * PARTICLEFACTOR); - pix = ((int)(izi*pparticle->scale)) >> d_pix_shift; + pix = ((int)(izi*pscale)) >> d_pix_shift; if (pix < d_pix_min) pix = d_pix_min; @@ -333,9 +333,9 @@ void D_DrawParticle32 (particle_t *pparticle) if (u < 0) u = 0; if (v < 0) v = 0; pdest = d_viewbuffer + ((d_scantable[v] + u)<<2); - pal = (qbyte *)&d_8to32table[(int)pparticle->color]; + pal = (qbyte *)&d_8to32table[pcolour]; - a = 255*pparticle->alpha; + a = 255*palpha; switch (pix) { @@ -361,41 +361,38 @@ void D_DrawParticle32 (particle_t *pparticle) #define draw(x, y) x=Trans(x,y) #define addblend(x, y) x=AddBlend(x,y) -void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) +void D_DrawParticleTrans (vec3_t porg, float palpha, float pscale, unsigned int pcolour, blendmode_t blendmode) { vec3_t local, transformed; float zi; qbyte *pdest; - qbyte pcolor; short *pz; int i, izi, pix, count, u, v; if (r_pixbytes == 4) { - D_DrawParticle32(pparticle); + D_DrawParticle32(porg, palpha, pscale, pcolour); return; } if (r_pixbytes == 2) { - D_DrawParticle16(pparticle); + D_DrawParticle16(porg, palpha, pscale, pcolour); return; } - if (pparticle->alpha < TRANS_LOWER_CAP) + if (palpha < TRANS_LOWER_CAP) return; - if (pparticle->alpha > TRANS_UPPER_CAP && blendmode == BM_BLEND) + if (palpha > TRANS_UPPER_CAP && blendmode == BM_BLEND) { - D_DrawParticle(pparticle); + D_DrawParticle(porg, palpha, pscale, pcolour); return; } - D_SetTransLevel(pparticle->alpha, blendmode); - - pcolor = pparticle->color; + D_SetTransLevel(palpha, blendmode); // transform point - VectorSubtract (pparticle->org, r_origin, local); + VectorSubtract (porg, r_origin, local); transformed[0] = DotProduct(local, r_pright); transformed[1] = DotProduct(local, r_pup); @@ -421,7 +418,7 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) pz = d_pzbuffer + (d_zwidth * v) + u; izi = (int)(zi * PARTICLEFACTOR); - pix = ((int)(izi*pparticle->scale)) >> d_pix_shift; + pix = ((int)(izi*pscale)) >> d_pix_shift; if (pix < d_pix_min) pix = d_pix_min; @@ -446,7 +443,7 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - addblend(pdest[0], pcolor); + addblend(pdest[0], pcolour); } } break; @@ -459,13 +456,13 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - addblend(pdest[0], pcolor); + addblend(pdest[0], pcolour); } if (pz[1] <= izi) { // pz[1] = izi; - addblend(pdest[1], pcolor); + addblend(pdest[1], pcolour); } } break; @@ -478,19 +475,19 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - addblend(pdest[0], pcolor); + addblend(pdest[0], pcolour); } if (pz[1] <= izi) { // pz[1] = izi; - addblend(pdest[1], pcolor); + addblend(pdest[1], pcolour); } if (pz[2] <= izi) { // pz[2] = izi; - addblend(pdest[2], pcolor); + addblend(pdest[2], pcolour); } } break; @@ -503,25 +500,25 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - addblend(pdest[0], pcolor); + addblend(pdest[0], pcolour); } if (pz[1] <= izi) { // pz[1] = izi; - addblend(pdest[1], pcolor); + addblend(pdest[1], pcolour); } if (pz[2] <= izi) { // pz[2] = izi; - addblend(pdest[2], pcolor); + addblend(pdest[2], pcolour); } if (pz[3] <= izi) { // pz[3] = izi; - addblend(pdest[3], pcolor); + addblend(pdest[3], pcolour); } } break; @@ -536,7 +533,7 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[i] <= izi) { // pz[i] = izi; - addblend(pdest[i], pcolor); + addblend(pdest[i], pcolour); } } } @@ -555,7 +552,7 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - draw(pdest[0], pcolor); + draw(pdest[0], pcolour); } } break; @@ -568,13 +565,13 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - draw(pdest[0], pcolor); + draw(pdest[0], pcolour); } if (pz[1] <= izi) { // pz[1] = izi; - draw(pdest[1], pcolor); + draw(pdest[1], pcolour); } } break; @@ -587,19 +584,19 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - draw(pdest[0], pcolor); + draw(pdest[0], pcolour); } if (pz[1] <= izi) { // pz[1] = izi; - draw(pdest[1], pcolor); + draw(pdest[1], pcolour); } if (pz[2] <= izi) { // pz[2] = izi; - draw(pdest[2], pcolor); + draw(pdest[2], pcolour); } } break; @@ -612,25 +609,25 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[0] <= izi) { // pz[0] = izi; - draw(pdest[0], pcolor); + draw(pdest[0], pcolour); } if (pz[1] <= izi) { // pz[1] = izi; - draw(pdest[1], pcolor); + draw(pdest[1], pcolour); } if (pz[2] <= izi) { // pz[2] = izi; - draw(pdest[2], pcolor); + draw(pdest[2], pcolour); } if (pz[3] <= izi) { // pz[3] = izi; - draw(pdest[3], pcolor); + draw(pdest[3], pcolour); } } break; @@ -645,7 +642,7 @@ void D_DrawParticleTrans (particle_t *pparticle, blendmode_t blendmode) if (pz[i] <= izi) { // pz[i] = izi; - draw(pdest[i], pcolor); + draw(pdest[i], pcolour); } } } @@ -687,7 +684,7 @@ vec_t VI2Length(int x, int y) length = sqrt (length); return length; } -void D_DrawSparkTrans32 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw a line in 3d space +void D_DrawSparkTrans32 (vec3_t src, vec3_t dest, float palpha, unsigned int pcolour) //draw a line in 3d space { /* Finds 2d coords for the points, then draws a line between them with an appropriate alpha @@ -700,7 +697,7 @@ void D_DrawSparkTrans32 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw int du, dv, dz, da; - if (pparticle->alpha <= 0.0) + if (palpha <= 0.0) return; D_2dPos(src, &u1, &v1, &z1); @@ -721,8 +718,8 @@ void D_DrawSparkTrans32 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw { return; } -pal = (qbyte *)(d_8to32table + (int)pparticle->color); - a1 = 255 * pparticle->alpha; + pal = (qbyte *)(d_8to32table + pcolour); + a1 = 255 * palpha; du = u2 - u1; dv = v2 - v1; @@ -775,7 +772,7 @@ pal = (qbyte *)(d_8to32table + (int)pparticle->color); } while (count--); } -void D_DrawSparkTrans16 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw a line in 3d space, 8bpp +void D_DrawSparkTrans16 (vec3_t src, vec3_t dest, float palpha, unsigned int pcolour) //draw a line in 3d space, 8bpp { unsigned short *pdest; short *pz; @@ -784,7 +781,7 @@ void D_DrawSparkTrans16 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw int du, dv, dz; - if (pparticle->alpha <= 0.0) + if (palpha <= 0.0) return; D_2dPos(src, &u1, &v1, &z1); @@ -839,7 +836,7 @@ void D_DrawSparkTrans16 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw // *pz = z1>>16; pdest = (unsigned short*)d_viewbuffer + d_scantable[v1>>16] + (u1>>16); - *pdest = d_8to16table[(int)pparticle->color]; + *pdest = d_8to16table[pcolour]; } u1 += du; @@ -848,7 +845,7 @@ void D_DrawSparkTrans16 (particle_t *pparticle, vec3_t src, vec3_t dest) //draw } while (count--); } -void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest, blendmode_t blendmode) //draw a line in 3d space, 8bpp +void D_DrawSparkTrans (vec3_t src, vec3_t dest, float palpha, unsigned int pcolour, blendmode_t blendmode) //draw a line in 3d space, 8bpp { qbyte *pdest; short *pz; @@ -862,16 +859,16 @@ void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest, blendmode */ if (r_pixbytes == 4) { - D_DrawSparkTrans32(pparticle, src, dest); + D_DrawSparkTrans32(src, dest, palpha, pcolour); return; } if (r_pixbytes == 2) { - D_DrawSparkTrans16(pparticle, src, dest); + D_DrawSparkTrans16(src, dest, palpha, pcolour); return; } - D_SetTransLevel(pparticle->alpha, blendmode); + D_SetTransLevel(palpha, blendmode); D_2dPos(src, &u1, &v1, &z1); D_2dPos(dest, &u2, &v2, &z2); @@ -925,7 +922,7 @@ void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest, blendmode { // *pz = z1>>16; pdest = d_viewbuffer + d_scantable[v1>>16] + (u1>>16); - addblend(*pdest, (qbyte)pparticle->color); + addblend(*pdest, (qbyte)pcolour); } u1 += du; @@ -943,7 +940,7 @@ void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest, blendmode { // *pz = z1>>16; pdest = d_viewbuffer + d_scantable[v1>>16] + (u1>>16); - draw(*pdest, (qbyte)pparticle->color); + draw(*pdest, (qbyte)pcolour); } u1 += du; diff --git a/engine/sw/d_parta.s b/engine/sw/d_parta.s index ce3f7c1e0..cec47a28b 100644 --- a/engine/sw/d_parta.s +++ b/engine/sw/d_parta.s @@ -41,7 +41,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. .text -#define P 12+4 +#define P0 12+4 +#define P1 12+8 +#define P2 12+12 +#define P3 12+16 + +//void D_DrawParticle (vec3_t porg, float palpha, float pscale, unsigned int pcolour) .align 4 .globl C(D_DrawParticle) @@ -50,17 +55,17 @@ C(D_DrawParticle): pushl %edi // preserve register variables pushl %ebx - movl P(%esp),%edi + movl P0(%esp),%edi // FIXME: better FP overlap in general here // transform point // VectorSubtract (p->org, r_origin, local); flds C(r_origin) - fsubrs pt_org(%edi) - flds pt_org+4(%edi) + fsubrs 0(%edi) + flds 4(%edi) fsubs C(r_origin)+4 - flds pt_org+8(%edi) + flds 8(%edi) fsubs C(r_origin)+8 fxch %st(2) // local[0] | local[1] | local[2] @@ -167,9 +172,12 @@ C(D_DrawParticle): cmpl %ecx,%eax jl LPop1AndDone - flds pt_color(%edi) // color | 1/z * 0x8000 + movl P3(%esp),%edi + movl %edi,DP_Color + +// flds P3(%esp) // color | 1/z * 0x8000 // FIXME: use Terje's fast fp->int trick? - fistpl DP_Color // 1/z * 0x8000 +// fistpl DP_Color // 1/z * 0x8000 movl C(d_viewbuffer),%ebx diff --git a/engine/sw/r_alias.c b/engine/sw/r_alias.c index cc3f317d7..2737270ad 100644 --- a/engine/sw/r_alias.c +++ b/engine/sw/r_alias.c @@ -124,7 +124,7 @@ qboolean R_AliasCheckBBox (void) R_AliasSetUpTransform (0); // construct the base bounding box for this frame - nframe = currententity->frame; + nframe = currententity->frame1; // TODO: don't repeat this check when drawing? if ((nframe >= pmdl->numframes) || (nframe < 0)) { @@ -134,7 +134,7 @@ qboolean R_AliasCheckBBox (void) } // construct the base bounding box for this frame - oframe = currententity->oldframe; + oframe = currententity->frame2; // TODO: don't repeat this check when drawing? if ((oframe >= pmdl->numframes) || (oframe < 0)) { @@ -771,13 +771,13 @@ void R_AliasSetupFrame (void) // vec3_t max1, max2; float fl, bl; - frame = currententity->frame; + frame = currententity->frame1; if ((frame >= pmdl->numframes) || (frame < 0)) { Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); frame = 0; } - oframe = currententity->oldframe; + oframe = currententity->frame2; if ((oframe >= pmdl->numframes) || (oframe < 0)) { // Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", oframe); //pointless @@ -785,6 +785,10 @@ void R_AliasSetupFrame (void) } bl = currententity->lerpfrac; + if (bl < 0) + bl = 0; + else if (bl > 1) + bl = 1; fl = 1.0 - bl; for (i = 0; i < 3; i++) diff --git a/engine/sw/r_local.h b/engine/sw/r_local.h index 0ecfca519..0ee08ab60 100644 --- a/engine/sw/r_local.h +++ b/engine/sw/r_local.h @@ -18,6 +18,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // r_local.h -- private refresh defs +#ifndef R_LOCAL_H +#define R_LOCAL_H #ifdef SWQUAKE @@ -314,9 +316,10 @@ void SWR_NetGraph (void); qbyte *SWMod_LeafPVS (model_t *model, mleaf_t *leaf, qbyte *buffer); -void D_DrawSparkTrans (particle_t *pparticle, vec3_t src, vec3_t dest, int blendmode); +void D_DrawSparkTrans (struct particle_s *pparticle, vec3_t src, vec3_t dest, int blendmode); void D_Shutdown (void); #endif //def SWQUAKE +#endif diff --git a/engine/sw/r_main.c b/engine/sw/r_main.c index a7b7f2617..17514c2be 100644 --- a/engine/sw/r_main.c +++ b/engine/sw/r_main.c @@ -678,19 +678,17 @@ void SWR_MarkLeaves (void) //temporary void SWR_DrawBeam(entity_t *e) { - particle_t p; vec3_t o1, o2; vec3_t dir; int len; VectorSubtract(e->origin, e->oldorigin, dir); VectorCopy(e->oldorigin, o1); len = VectorNormalize(dir); - p.alpha = 1; - p.color = 15; +// p.color = 15; for (; len>=0; len--) { VectorAdd(o1, dir, o2); - D_DrawSparkTrans (&p, o1, o2, 0); + D_DrawSparkTrans (o1, o2, 1, 0); VectorCopy(o2, o1); } } diff --git a/engine/sw/r_surf.c b/engine/sw/r_surf.c index b019eb2ee..3000df9f7 100644 --- a/engine/sw/r_surf.c +++ b/engine/sw/r_surf.c @@ -1030,7 +1030,7 @@ texture_t *SWR_TextureAnimation (texture_t *base) int reletive; int count; - if (currententity->frame) + if (currententity->frame1) { if (base->alternate_anims) base = base->alternate_anims; diff --git a/engine/sw/sw_model.c b/engine/sw/sw_model.c index 7ba23f0b8..9683ff284 100644 --- a/engine/sw/sw_model.c +++ b/engine/sw/sw_model.c @@ -338,31 +338,46 @@ model_t *SWMod_LoadModel (model_t *mod, qboolean crash) // get string used for replacement tokens ext = COM_FileExtension(mod->name); - if (isDedicated) - replstr = NULL; - else if (!Q_strcasecmp(ext, "spr") || !Q_strcasecmp(ext, "sp2")) - replstr = NULL; // sprite + if (!Q_strcasecmp(ext, "spr") || !Q_strcasecmp(ext, "sp2")) + replstr = ""; // sprite else if (!Q_strcasecmp(ext, "dsp")) // doom sprite - replstr = NULL; + { + replstr = ""; +// doomsprite = true; + } else // assume models replstr = r_replacemodels.string; + // gl_load24bit 0 disables all replacements +// if (!gl_load24bit.value) +// replstr = ""; + COM_StripExtension(mod->name, mdlbase, sizeof(mdlbase)); - while (1) + while (replstr) { - for (replstr = COM_ParseStringSet(replstr); com_token[0] && !buf; replstr = COM_ParseStringSet(replstr)) + replstr = COM_ParseStringSet(replstr); + if (replstr) buf = (unsigned *)COM_LoadStackFile (va("%s.%s", mdlbase, com_token), stackbuf, sizeof(stackbuf)); - - if (!buf) + else { - if (lastload) // only load unreplaced file once - break; - lastload = true; buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf)); - if (!buf) // we would attempt Doom sprites here, but SW doesn't support them + if (!buf) + { +#ifdef DOOMWADS + if (doomsprite) // special case needed for doom sprites + { + mod->needload = false; + GLMod_LoadDoomSprite(mod); + P_DefaultTrail(mod); + return mod; + } +#endif break; // failed to load unreplaced file and nothing left + } } + if (!buf) + continue; // // allocate a new model @@ -1679,10 +1694,10 @@ qboolean SWMod_LoadClipnodes (lump_t *l) hull->planes = loadmodel->planes; hull->clip_mins[0] = -16; hull->clip_mins[1] = -16; - hull->clip_mins[2] = -36; + hull->clip_mins[2] = -32; //I dont know what is correct here, but we'll just copy mvdsv for now hull->clip_maxs[0] = 16; hull->clip_maxs[1] = 16; - hull->clip_maxs[2] = 36; + hull->clip_maxs[2] = 32; hull->available = true; hull = &loadmodel->hulls[2];