diff --git a/engine/client/cd_win.c b/engine/client/cd_win.c index 9f8f3024..b03e1059 100644 --- a/engine/client/cd_win.c +++ b/engine/client/cd_win.c @@ -129,9 +129,6 @@ void CDAudio_Play(int track, qboolean looping) CDAudio_GetAudioDiskInfo(); if (!cdValid) { -#ifndef NOMEDIA - Media_FakeTrack(track, looping); -#endif return; } } @@ -143,9 +140,6 @@ void CDAudio_Play(int track, qboolean looping) if (track < 1 || track > maxTrack) { -#ifndef NOMEDIA - Media_FakeTrack(track, looping); -#endif Con_DPrintf("CDAudio: Bad track number %u.\n", track); return; } diff --git a/engine/client/cl_cam.c b/engine/client/cl_cam.c index ff6acccf..8479ea6e 100644 --- a/engine/client/cl_cam.c +++ b/engine/client/cl_cam.c @@ -174,7 +174,7 @@ static float Cam_TryFlyby(vec3_t selforigin, vec3_t playerorigin, vec3_t vec, qb player_maxs[0] = player_maxs[1] = 16; player_maxs[2] = 32; - vectoangles(vec, v); + VectorAngles(vec, NULL, v); // v[0] = -v[0]; VectorCopy (v, pmove.angles); VectorNormalize(vec); @@ -409,7 +409,7 @@ void Cam_SelfTrack(int pnum) VectorCopy(desired_position[pnum], r_refdef.vieworg); VectorSubtract(cl.simorg[pnum], desired_position[pnum], vec); - vectoangles(vec, r_refdef.viewangles); + VectorAngles(vec, NULL, r_refdef.viewangles); r_refdef.viewangles[0] = -r_refdef.viewangles[0]; } } @@ -509,7 +509,7 @@ void Cam_Track(int pnum, usercmd_t *cmd) VectorCopy(desired_position[pnum], self->origin); VectorSubtract(player->origin, desired_position[pnum], vec); - vectoangles(vec, cl.viewangles[pnum]); + VectorAngles(vec, NULL, cl.viewangles[pnum]); cl.viewangles[pnum][0] = -cl.viewangles[pnum][0]; } diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 7eff1493..78199549 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -568,8 +568,8 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con mod = &box_model; else mod = cl.model_precache[modhandle+1]; - if (mod) - pc = cl.worldmodel->funcs.NativeContents(mod, 0, 0, NULL, VM_POINTER(arg[0]), vec3_origin, vec3_origin); + if (mod && !mod->needload) + pc = mod->funcs.NativeContents(mod, 0, 0, NULL, VM_POINTER(arg[0]), vec3_origin, vec3_origin); else pc = 1;//FTECONTENTS_SOLID; VM_LONG(ret) = pc;//Contents_To_Q3(pc); @@ -648,8 +648,8 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con TransformedNativeTrace(mod, 0, 0, start, end, mins, maxs, brushmask, &tr, origin, angles); #else { -#ifdef _MSC_VER -#pragma message("FIXME: G3 CGame requires TransformedNativeTrace!") +#ifdef warningmsg +#pragma warningmsg("FIXME: G3 CGame requires TransformedNativeTrace!") #endif memset(&tr, 0, sizeof(tr)); tr.allsolid = tr.startsolid = true; @@ -1042,7 +1042,7 @@ static qintptr_t CG_SystemCalls(void *offset, quintptr_t mask, qintptr_t fn, con case CG_FTE_SPAWNPARTICLEEFFECT: 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 pe->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]), 0, VM_POINTER(arg[3])); case CG_FTE_FREEPARTICLESTATE: pe->DelinkTrailstate(VM_POINTER(arg[0])); break; diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index 86e0a3cc..e7fd26ea 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -23,6 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. void CL_FinishTimeDemo (void); float demtime; +int demoframe; int cls_lastto; int cls_lasttype; @@ -430,12 +431,12 @@ qboolean CL_GetDemoMessage (void) olddemotime = 0; return 0; } - if ((cls.timedemo && cls.netchan.last_received == (float)realtime) || (!cls.timedemo && demtime<= cl.gametime && cl.gametime))// > dem_lasttime+demtime) + cls.netchan.last_received = realtime; + if ((cls.timedemo && host_framecount == demoframe) || (!cls.timedemo && demtime<= cl.gametime && cl.gametime))// > dem_lasttime+demtime) { if (demtime <= cl.gametime-1) { demtime = cl.gametime; - cls.netchan.last_received = realtime; } { @@ -457,6 +458,7 @@ qboolean CL_GetDemoMessage (void) } return 0; } + demoframe = host_framecount; } if (readdemobytes(&demopos, &msglength, 4) != 4) { @@ -537,13 +539,12 @@ readnext: // decide if it is time to grab the next message if (cls.timedemo) { - if (cls.state == ca_active) + if (cls.state == ca_active || cl.validsequence) { if (cls.td_lastframe < 0) - cls.td_lastframe = host_framecount; + cls.td_lastframe = demotime; else if (host_framecount == cls.td_lastframe) { - cls.td_lastframe = host_framecount; return 0; // already read this frame's message } if (cls.td_startframe == -1) @@ -780,6 +781,7 @@ readit: demo_flushbytes(demopos); olddemotime = demotime; + cls.td_lastframe = host_framecount; return 1; } @@ -796,7 +798,7 @@ qboolean CL_GetMessage (void) if (cls.demoplayback != DPB_NONE) return CL_GetDemoMessage (); - if (!NET_GetPacket (NS_CLIENT)) + if (NET_GetPacket (NS_CLIENT, 0) < 0) return false; CL_WriteDemoMessage (&net_message); @@ -1418,8 +1420,8 @@ void CL_PlayDemo_f (void) } #ifdef WEBCLIENT -#ifdef _MSC_VER -#pragma message("playdemo http://blah is broken right now") +#ifdef warningmsg +#pragma warningmsg("playdemo http://blah is broken right now") #endif #if 0 if (!strncmp(Cmd_Argv(1), "ftp://", 6) || !strncmp(Cmd_Argv(1), "http://", 7)) @@ -1597,8 +1599,8 @@ void CL_Demo_ClientCommand(char *commandtext) { unsigned char b = 1; unsigned short len = LittleShort((unsigned short)(strlen(commandtext) + 4)); -#ifndef _MSC_VER -#warning "this needs buffering safely" +#ifdef warningmsg +#pragma warningmsg("this needs buffering safely") #endif if (cls.demoplayback == DPB_EZTV) { diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 63db9854..fe15cf96 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -85,8 +85,8 @@ qboolean CL_FilterModelindex(int modelindex, int frame) void CL_FreeDlights(void) { -#ifdef _MSC_VER -#pragma message("not freeing shadowmeshes") +#ifdef warningmsg +#pragma warningmsg("not freeing shadowmeshes") #endif rtlights_max = cl_maxdlights = 0; BZ_Free(cl_dlights); @@ -103,12 +103,12 @@ static void CL_ClearDlight(dlight_t *dl, int key) { void *sm; texid_t st; - st = dl->stexture; + TEXASSIGNF(st, dl->stexture); sm = dl->worldshadowmesh; memset (dl, 0, sizeof(*dl)); dl->rebuildcache = true; dl->worldshadowmesh = sm; - dl->stexture = st; + TEXASSIGNF(dl->stexture, st); dl->axis[0][0] = 1; dl->axis[1][1] = 1; dl->axis[2][2] = 1; @@ -305,7 +305,7 @@ CL_ParseDelta Can go from either a baseline or a previous packet_entity ================== */ -int bitcounts[32]; /// just for protocol profiling +//int bitcounts[32]; /// just for protocol profiling void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean new) { int i; @@ -326,9 +326,9 @@ void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int bits, qboolean } // count the bits for net profiling - for (i=0 ; i<16 ; i++) - if (bits&(1<dpflags = i; s->flags = 0; if (i & RENDER_VIEWMODEL) s->flags |= Q2RF_WEAPONMODEL|Q2RF_MINLIGHT|Q2RF_DEPTHHACK; @@ -1422,7 +1423,7 @@ void CLQ1_AddShadow(entity_t *ent) "alphagen vertex\n" "}\n" "}\n"); - s->defaulttextures.base = balltexture; + TEXASSIGN(s->defaulttextures.base, balltexture); tx = ent->model->maxs[0] - ent->model->mins[0]; ty = ent->model->maxs[1] - ent->model->mins[1]; @@ -1530,7 +1531,7 @@ void CLQ1_AddPowerupShell(entity_t *ent, qboolean viewweap, unsigned int effects "noshadows\n" "surfaceparm nodlight\n" "{\n" - "map $whitetexture\n" + "map $whiteimage\n" "rgbgen entity\n" "alphagen entity\n" "blendfunc src_alpha one\n" @@ -1548,7 +1549,7 @@ void CLQ1_AddPowerupShell(entity_t *ent, qboolean viewweap, unsigned int effects "noshadows\n" "surfaceparm nodlight\n" "{\n" - "map $whitetexture\n" + "map $whiteimage\n" "rgbgen entity\n" "alphagen entity\n" "blendfunc src_alpha one\n" @@ -1756,12 +1757,12 @@ static void CL_TransitionPacketEntities(packet_entities_t *newpack, packet_entit //ignore the old packet entirely, except for maybe its time. if (!VectorEquals(le->neworigin, snew->origin) || !VectorEquals(le->newangle, snew->angles)) { - le->orglerpdeltatime = bound(0, oldpack->servertime - le->orglerpstarttime, 0.1); //clamp to 10 tics per second + le->orglerpdeltatime = bound(0, oldpack->servertime - le->orglerpstarttime, 0.11); //clamp to 10 tics per second le->orglerpstarttime = oldpack->servertime; VectorCopy(le->neworigin, le->oldorigin); VectorCopy(le->newangle, le->oldangle); - + VectorCopy(snew->origin, le->neworigin); VectorCopy(snew->angles, le->newangle); } @@ -1932,7 +1933,6 @@ void CL_LinkPacketEntities (void) float servertime; - CL_CalcClientTime(); if (cls.protocol == CP_QUAKEWORLD && (cls.demoplayback == DPB_MVD || cls.demoplayback == DPB_EZTV)) { servertime = cl.servertime; @@ -1955,7 +1955,10 @@ void CL_LinkPacketEntities (void) i = servertime*20; if (flickertime != i) + { + flickertime = i; flicker = rand(); + } autorotate = anglemod(100*servertime); @@ -2088,6 +2091,8 @@ void CL_LinkPacketEntities (void) ent->flags |= Q2RF_ADDITIVE; if (state->effects & EF_NODEPTHTEST) ent->flags |= RF_NODEPTHTEST; + if (state->effects & DPEF_NOSHADOW) + ent->flags |= RF_NOSHADOW; if (state->trans != 0xff) ent->flags |= Q2RF_TRANSLUCENT; @@ -2154,7 +2159,7 @@ void CL_LinkPacketEntities (void) #endif // rotate binary objects locally - if (model && model->flags & EF_ROTATE) + if (model && model->flags & MF_ROTATE) { angles[0] = 0; angles[1] = autorotate; @@ -2192,10 +2197,10 @@ void CL_LinkPacketEntities (void) CLQ1_AddPowerupShell(ent, false, state->effects); // add automatic particle trails - if (!model || (!(model->flags&~EF_ROTATE) && model->particletrail<0 && model->particleeffect<0)) + if (!model || (!(model->flags&~MF_ROTATE) && model->particletrail<0 && model->particleeffect<0)) continue; - if (!cls.allow_anyparticles && !(model->flags & ~EF_ROTATE)) + if (!cls.allow_anyparticles && !(model->flags & ~MF_ROTATE)) continue; if (le->isnew) @@ -2215,7 +2220,7 @@ void CL_LinkPacketEntities (void) } } - if (model->particletrail == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, model->particletrail, &(le->trailstate))) + if (model->particletrail == P_INVALID || pe->ParticleTrail (old_origin, ent->origin, model->particletrail, ent->keynum, &(le->trailstate))) if (model->traildefaultindex >= 0) pe->ParticleTrailIndex(old_origin, ent->origin, model->traildefaultindex, 0, &(le->trailstate)); @@ -2237,28 +2242,29 @@ void CL_LinkPacketEntities (void) dclr[1] = 0.10; dclr[2] = 0; - if (model->flags & EF_ROCKET) + if (model->flags & MF_ROCKET) { -#ifdef _MSC_VER -#pragma message("Replace this flag on load for hexen2 models") +#ifdef warningmsg +#pragma warningmsg("Replace this flag on load for hexen2 models") #endif if (strncmp(model->name, "models/sflesh", 13)) { //hmm. hexen spider gibs... rad = 200; dclr[2] = 0.05; + rad += r_lightflicker.value?((flicker + state->number)&31):0; } } - else if (model->flags & EFH2_FIREBALL) + else if (model->flags & MFH2_FIREBALL) { rad = 120 - (rand() % 20); } - else if (model->flags & EFH2_ACIDBALL) + else if (model->flags & MFH2_ACIDBALL) { rad = 120 - (rand() % 20); dclr[0] = 0.1; dclr[1] = 0.2; } - else if (model->flags & EFH2_SPIT) + else if (model->flags & MFH2_SPIT) { // as far as I can tell this effect inverses the light... dclr[0] = -dclr[0]; @@ -2273,7 +2279,7 @@ void CL_LinkPacketEntities (void) memcpy(dl->axis, ent->axis, sizeof(dl->axis)); VectorCopy (ent->origin, dl->origin); dl->die = (float)cl.time; - if (model->flags & EF_ROCKET) + if (model->flags & MF_ROCKET) dl->origin[2] += 1; // is this even necessary dl->radius = rad * r_rocketlight.value; VectorCopy(dclr, dl->color); diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index db8ba0ff..296934cf 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -777,8 +777,11 @@ void CLNQ_SendMove (usercmd_t *cmd, int pnum, sizebuf_t *buf) // always dump the first two message, because it may contain leftover inputs // from the last level // - if (++cl.movemessages <= 2) + if (++cl.movemessages <= 2 || cls.state == ca_connected) + { + MSG_WriteByte (buf, clc_nop); return; + } MSG_WriteByte (buf, clc_move); @@ -1018,9 +1021,9 @@ void CL_AllowIndependantSendCmd(qboolean allow) if (allowindepphys != allow && runningindepphys) { if (allow) - Sys_UnlockMutex(&indeplock); + Sys_UnlockMutex(indeplock); else - Sys_LockMutex(&indeplock); + Sys_LockMutex(indeplock); allowindepphys = allow; } } @@ -1043,11 +1046,11 @@ int CL_IndepPhysicsThread(void *param) spare = 15; time -= spare/1000.0f; - Sys_LockMutex(&indeplock); + Sys_LockMutex(indeplock); if (cls.state) CL_SendCmd(time - lasttime, false); lasttime = time; - Sys_UnlockMutex(&indeplock); + Sys_UnlockMutex(indeplock); } fps = cl_netfps.value; @@ -1225,6 +1228,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf) int checksumIndex, firstsize, plnum; int clientcount, lost; int curframe = cls.netchan.outgoing_sequence & UPDATE_MASK; + int st = buf->cursize; seq_hash = cls.netchan.outgoing_sequence; @@ -1316,7 +1320,7 @@ qboolean CL_SendCmdQW (sizebuf_t *buf) cl.frames[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = -1; if (cl.sendprespawn) - buf->cursize = 0; //tastyspleen.net is alergic. + buf->cursize = st; //tastyspleen.net is alergic. return dontdrop; } @@ -1413,6 +1417,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) return; // sendcmds come from the demo } + memset(&buf, 0, sizeof(buf)); buf.maxsize = sizeof(data); buf.cursize = 0; buf.data = data; @@ -1451,7 +1456,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) if (!runningindepphys) { // while we're not playing send a slow keepalive fullsend to stop mvdsv from screwing up - if (cls.state < ca_active) + if (cls.state < ca_active && !cls.downloadmethod) { #ifdef IRCCONNECT //don't spam irc. if (cls.netchan.remote_address.type == NA_IRC) @@ -1513,7 +1518,7 @@ void CL_SendCmd (double frametime, qboolean mainloop) // if (skipcmd) // return; - if (!fullsend && cls.state == ca_active) + if (!fullsend) return; // when we're actually playing we try to match netfps exactly to avoid gameplay problems #ifdef NQPROT @@ -1527,14 +1532,14 @@ void CL_SendCmd (double frametime, qboolean mainloop) next = clientcmdlist->next; if (clientcmdlist->reliable) { - if (cls.netchan.message.cursize + 2+strlen(clientcmdlist->command) > cls.netchan.message.maxsize) + if (cls.netchan.message.cursize + 2+strlen(clientcmdlist->command)+100 > cls.netchan.message.maxsize) break; MSG_WriteByte (&cls.netchan.message, clc_stringcmd); MSG_WriteString (&cls.netchan.message, clientcmdlist->command); } else { - if (buf.cursize + 2+strlen(clientcmdlist->command) <= buf.maxsize) + if (buf.cursize + 2+strlen(clientcmdlist->command)+100 <= buf.maxsize) { MSG_WriteByte (&buf, clc_stringcmd); MSG_WriteString (&buf, clientcmdlist->command); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index a553dd37..566f196e 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -60,6 +60,7 @@ cvar_t cl_defaultport = CVARAF("cl_defaultport", STRINGIFY(PORT_QWSERVER), "por cvar_t cfg_save_name = CVARF("cfg_save_name", "fte", CVAR_ARCHIVE); +cvar_t cl_packagedownloads = CVAR("cl_packagedownloads", "1"); cvar_t cl_splitscreen = CVAR("cl_splitscreen", "0"); cvar_t lookspring = CVARF("lookspring","0", CVAR_ARCHIVE); @@ -73,7 +74,6 @@ cvar_t m_yaw = CVARF("m_yaw","0.022", CVAR_ARCHIVE); cvar_t m_forward = CVARF("m_forward","1", CVAR_ARCHIVE); cvar_t m_side = CVARF("m_side","0.8", CVAR_ARCHIVE); -cvar_t entlatency = CVAR("entlatency", "20"); cvar_t cl_predict_players = CVAR("cl_predict_players", "1"); cvar_t cl_solid_players = CVAR("cl_solid_players", "1"); cvar_t cl_noblink = CVAR("cl_noblink", "0"); @@ -91,8 +91,6 @@ cvar_t cl_threadedphysics = CVAR("cl_threadedphysics", "0"); cvar_t localid = SCVAR("localid", ""); -cvar_t cl_antibunch = CVAR("cl_antibunch", "0"); - cvar_t r_drawflame = CVAR("r_drawflame", "1"); static qboolean allowremotecmd = true; @@ -138,17 +136,17 @@ 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 = SCVARF("allow_download_csprogs", "1", 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_download_csprogs = CVARFD("cl_download_csprogs", "1", CVAR_NOTFROMSERVER, "Download updated client gamecode if available."); +cvar_t cl_download_redirection = CVARFD("cl_download_redirection", "0", CVAR_NOTFROMSERVER, "Follow download redirection to download packages instead of individual files."); +cvar_t cl_download_mapsrc = CVARD("cl_download_mapsrc", "", "Specifies an http location prefix for map downloads. EG: \"http://bigfoot.morphos-team.net/misc/quakemaps/\""); +cvar_t cl_download_packages = CVARFD("cl_download_packages", "1", CVAR_NOTFROMSERVER, "0=Do not download packages simply because the server is using them. 1=Do download, but don't use them by default. 2=Do download and install permanently (use with caution!)"); +cvar_t requiredownloads = CVARFD("requiredownloads","1", CVAR_ARCHIVE, "0=join the game before downloads have even finished (might be laggy). 1=wait for all downloads to complete before joining."); 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 cl_download_mapsrc = SCVAR("cl_download_mapsrc", ""); //EG: "http://bigfoot.morphos-team.net/misc/quakemaps/" - 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); @@ -636,6 +634,9 @@ char *CL_TryingToConnect(void) return cls.servername; } +int SV_NewChallenge (void); +client_t *SVC_DirectConnect(void); + /* ================= CL_CheckForResend @@ -670,12 +671,26 @@ void CL_CheckForResend (void) break; #endif default: + cl.movemessages = 0; if (!strcmp(cl_loopbackprotocol.string, "qw")) cls.protocol = CP_QUAKEWORLD; else if (!strcmp(cl_loopbackprotocol.string, "nq")) + { cls.protocol = CP_NETQUAKE; + cls.protocol_nq = CPNQ_ID; + } else if (!strcmp(cl_loopbackprotocol.string, "q3")) cls.protocol = CP_QUAKE3; + else if (!strcmp(cl_loopbackprotocol.string, "dp6")) + { + cls.protocol = CP_NETQUAKE; + cls.protocol_nq = CPNQ_DP7; + } + else if (!strcmp(cl_loopbackprotocol.string, "dp7")) + { + cls.protocol = CP_NETQUAKE; + cls.protocol_nq = CPNQ_DP7; + } else if (progstype == PROG_QW) cls.protocol = CP_QUAKEWORLD; else @@ -695,8 +710,15 @@ void CL_CheckForResend (void) } NET_AdrToString(data, sizeof(data), adr); - //by NQ, we mean to try using the DP protocol extensions to the underlying NQ protocol - CL_ConnectToDarkPlaces("", adr); + if (cls.protocol_nq == CPNQ_ID) + { + net_from = adr; + Cmd_TokenizeString (va("connect %i %i %i \"\\name\\unconnected\"", NET_PROTOCOL_VERSION, 0, SV_NewChallenge()), false, false); + + SVC_DirectConnect(); + } + else + CL_ConnectToDarkPlaces("", adr); } else CL_SendConnectPacket (svs.fteprotocolextensions, svs.fteprotocolextensions2, false); @@ -1458,6 +1480,41 @@ void CL_Color_f (void) #endif } +void FS_GenCachedPakName(char *pname, char *crc, char *local, int llen); +qboolean CL_CheckDLFile(char *filename); +void CL_PakDownloads(int mode) +{ + /* + mode=0 no downloads (forced to 1 for pure) + mode=1 archived names so local stuff is not poluted + mode=2 downloaded packages will always be present. Use With Caution. + */ + char local[256]; + char *pname; + char *s = cl.serverpakcrcs; + int i; + + if (!cl.serverpakschanged || !mode) + return; + + Cmd_TokenizeString(cl.serverpaknames, false, false); + for (i = 0; i < Cmd_Argc(); i++) + { + s = COM_Parse(s); + pname = Cmd_Argv(i); + + if (mode != 2) + { + /*if we already have such a file, this is a no-op*/ + if (CL_CheckDLFile(va("package/%s", pname))) + continue; + FS_GenCachedPakName(pname, com_token, local, sizeof(local)); + } + else + Q_strncpyz(local, pname, sizeof(local)); + CL_CheckOrEnqueDownloadFile(pname, local, DLLF_NONGAME); + } +} void CL_CheckServerInfo(void) { @@ -1477,10 +1534,7 @@ void CL_CheckServerInfo(void) cls.allow_skyboxes=false; cls.allow_mirrors=false; cls.allow_luma=false; - cls.allow_bump=false; -#ifdef FISH - cls.allow_fish=false; -#endif + cls.allow_postproc=false; cls.allow_fbskins = 1; // cls.allow_fbskins = 0; // cls.allow_overbrightlight; @@ -1503,13 +1557,9 @@ void CL_CheckServerInfo(void) if (cl.spectator || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "allow_lmgamma"))) cls.allow_lightmapgamma=true; - s = Info_ValueForKey(cl.serverinfo, "allow_bump"); - if (cl.spectator || cls.demoplayback || atoi(s) || !*s) //admin doesn't care. - cls.allow_bump=true; -#ifdef FISH - if (cl.spectator || cls.demoplayback || atoi(Info_ValueForKey(cl.serverinfo, "allow_fish"))) - cls.allow_fish=true; -#endif + s = Info_ValueForKey(cl.serverinfo, "allow_fish"); + if (cl.spectator || cls.demoplayback || !*s || atoi(s)) + cls.allow_postproc=true; s = Info_ValueForKey(cl.serverinfo, "fbskins"); if (*s) @@ -1579,12 +1629,8 @@ void CL_CheckServerInfo(void) //16 if (allowed & 32) cls.allow_luma = true; - if (allowed & 64) - cls.allow_bump = true; -#ifdef FISH if (allowed & 128) - cls.allow_fish = true; -#endif + cls.allow_postproc = true; if (allowed & 256) cls.allow_lightmapgamma = true; if (allowed & 512) @@ -1613,6 +1659,17 @@ void CL_CheckServerInfo(void) if (oldstate != cl.matchstate) cl.matchgametime = 0; + if (atoi(Info_ValueForKey(cl.serverinfo, "sv_pure"))) + { + CL_PakDownloads((!cl_packagedownloads.ival)?1:cl_packagedownloads.ival); + FS_ForceToPure(cl.serverpaknames, cl.serverpakcrcs, cls.challenge); + } + else + { + CL_PakDownloads(cl_packagedownloads.ival); + FS_ImpurePacks(cl.serverpaknames, cl.serverpakcrcs); + } + Cvar_ForceCheatVars(cls.allow_semicheats, cls.allow_cheats); Validation_Apply_Ruleset(); @@ -2362,7 +2419,7 @@ void CL_ConnectionlessPacket (void) CL_ParseEstablished(); Con_DPrintf ("CL_EstablishConnection: connected to %s\n", cls.servername); - + /*this is a DP server... but we don't know which version*/ cls.netchan.isnqprotocol = true; cls.protocol = CP_NETQUAKE; cls.protocol_nq = CPNQ_ID; @@ -2503,6 +2560,7 @@ void CLNQ_ConnectionlessPacket(void) { char *s; int length; + unsigned short port; MSG_BeginReading (msg_nullnetprim); length = LongSwap(MSG_ReadLong ()); @@ -2521,8 +2579,11 @@ void CLNQ_ConnectionlessPacket(void) Con_TPrintf (TLC_DUPCONNECTION); return; } + port = htons((unsigned short)MSG_ReadLong()); //this is the port that we're meant to respond to. - net_from.port = htons((short)MSG_ReadLong()); + + if (port) + net_from.port = port; cls.protocol_nq = CPNQ_ID; if (MSG_ReadByte() == 1) //a proquake server adds a little extra info @@ -2581,38 +2642,6 @@ void CL_ReadPackets (void) // while (NET_GetPacket ()) for(;;) { - if (cl.oldgametime && cl_antibunch.value) - { - float want; - static float clamp; - - want = cl.oldgametime + realtime - cl.gametimemark - clamp; - if (want>cl.time) //don't decrease - { - clamp = 0; - cl.time = want; - } - - if (cl.time > cl.gametime) - { - clamp += cl.time - cl.gametime; - cl.time = cl.gametime; - } - if (cl.time < cl.oldgametime) - { - clamp -= cl.time - cl.gametime; - cl.time = cl.oldgametime; - } - - if (cl.time < cl.gametime-(1/cl_antibunch.value)) - { -// if (cl.gametime - 2 > cl.time) -// cl.gametime = 0; - break; - } - - } - if (!CL_GetMessage()) break; @@ -2844,7 +2873,7 @@ void CL_DownloadSize_f(void) dl = CL_DownloadFailed(rname); - if (allow_download_redirection.ival) + if (cl_download_redirection.ival) { Con_DPrintf("Download of \"%s\" redirected to \"%s\".\n", rname, redirection); CL_CheckOrEnqueDownloadFile(redirection, NULL, dl->flags); @@ -3069,7 +3098,6 @@ void CL_Init (void) Cvar_Register (&rcon_password, cl_controlgroup); Cvar_Register (&rcon_address, cl_controlgroup); - Cvar_Register (&entlatency, cl_predictiongroup); Cvar_Register (&cl_predict_players, cl_predictiongroup); Cvar_Register (&cl_solid_players, cl_predictiongroup); @@ -3100,8 +3128,8 @@ void CL_Init (void) Cvar_Register (&r_drawflame, "Item effects"); - Cvar_Register (&allow_download_csprogs, cl_controlgroup); - Cvar_Register (&allow_download_redirection, cl_controlgroup); + Cvar_Register (&cl_download_csprogs, cl_controlgroup); + Cvar_Register (&cl_download_redirection, cl_controlgroup); // // info mirrors @@ -3113,7 +3141,7 @@ void CL_Init (void) Cvar_Register (&model, cl_controlgroup); Cvar_Register (&team, cl_controlgroup); Cvar_Register (&topcolor, cl_controlgroup); - Cvar_Register (&bottomcolor, cl_controlgroup); + Cvar_Register (&bottomcolor, cl_controlgroup); Cvar_Register (&rate, cl_controlgroup); Cvar_Register (&drate, cl_controlgroup); Cvar_Register (&msg, cl_controlgroup); @@ -3138,12 +3166,12 @@ void CL_Init (void) Cvar_Register (&host_mapname, "Scripting"); + Cvar_Register (&cl_packagedownloads, cl_controlgroup); #ifndef SERVERONLY Cvar_Register (&cl_loopbackprotocol, cl_controlgroup); #endif Cvar_Register (&cl_countpendingpl, cl_controlgroup); Cvar_Register (&cl_threadedphysics, cl_controlgroup); - Cvar_Register (&cl_antibunch, "evil hacks"); Cvar_Register (&hud_tracking_show, "statusbar"); Cvar_Register (&cl_download_mapsrc, cl_controlgroup); @@ -3560,6 +3588,7 @@ double Host_Frame (double time) // fetch results from server CL_ReadPackets (); + CL_CalcClientTime(); // send intentions now // resend a connection request if necessary diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 23ef6f5a..71a56296 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -343,6 +343,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) return false; } + /*reject if it already failed*/ if (!(flags & DLLF_IGNOREFAILED)) { #ifdef NQPROT @@ -362,6 +363,7 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) } } + /*check for dupes*/ for (dl = cl.downloadlist; dl; dl = dl->next) //It's already on our list. Ignore it. { if (!strcmp(dl->rname, filename)) @@ -398,7 +400,9 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) | PEXT_PK3DOWNLOADS #endif ))) + { CL_SendClientCommand(true, "dlsize \"%s\"", dl->rname); + } if (flags & DLLF_VERBOSE) Con_Printf("Enqued download of \"%s\"\n", filename); @@ -406,8 +410,8 @@ qboolean CL_EnqueDownload(char *filename, char *localname, unsigned int flags) return true; } -#ifdef _MSC_VER -#pragma message("fix this") +#ifdef warningmsg +#pragma warningmsg("fix this") #endif int downloadsize; void CL_GetDownloadSizes(unsigned int *filecount, unsigned int *totalsize, qboolean *somesizesunknown) @@ -528,7 +532,17 @@ void CL_DownloadFinished(void) { if (strcmp(tempname, filename)) { - if (strncmp(tempname,"skins/",6)) + if (!strncmp(tempname,"package/",8)) + { + if (FS_Rename(tempname+8, filename+8, FS_ROOT)) + { + char nativetmp[MAX_OSPATH], nativefinal[MAX_OSPATH];; + FS_NativePath(tempname+8, FS_ROOT, nativetmp, sizeof(nativetmp)); + FS_NativePath(filename+8, FS_ROOT, nativefinal, sizeof(nativefinal)); + Con_Printf("Couldn't rename %s to %s\n", nativetmp, nativefinal); + } + } + else if (strncmp(tempname,"skins/",6)) { if (FS_Rename(tempname, filename, FS_GAME)) { @@ -555,8 +569,11 @@ void CL_DownloadFinished(void) - if (!strcmp(ext, "pk3") || !strcmp(ext, "pak")) + if (!strncmp(ext, "pk4", 3) || !strncmp(ext, "pk3", 3) || !strncmp(ext, "pak", 3)) + { FS_ReloadPackFiles(); + CL_CheckServerInfo(); + } else if (!strcmp(filename, "gfx/palette.lmp")) { Cbuf_AddText("vid_restart\n", RESTRICT_LOCAL); @@ -614,6 +631,23 @@ qboolean CL_CheckFile(char *filename) } return false; } + +qboolean CL_CheckDLFile(char *filename) +{ + if (!strncmp(filename, "package/", 8)) + { + vfsfile_t *f; + f = FS_OpenVFS(filename+8, "rb", FS_ROOT); + if (f) + { + VFS_CLOSE(f); + return true; + } + return false; + } + else + return COM_FCheckExists(filename); +} /* =============== CL_CheckOrEnqueDownloadFile @@ -624,16 +658,31 @@ Returns true if the file exists, returns false if it triggered a download. qboolean CL_CheckOrEnqueDownloadFile (char *filename, char *localname, unsigned int flags) { //returns false if we don't have the file yet. + + if (flags & DLLF_NONGAME) + { + /*pak/pk3 downloads have an explicit leading package/ as an internal/network marker*/ + filename = va("package/%s", filename); + localname = va("package/%s", localname); + } + /*files with a leading * should not be downloaded (inline models, sexed sounds, etc)*/ + else if (*filename == '*' || !strncmp(filename, "package/", 8)) + return true; + if (!localname) localname = filename; #ifndef CLIENTONLY + /*no downloading if we're the one we'd be downloading from*/ if (sv.state) return true; #endif - if (!(flags & DLLF_OVERWRITE) && CL_CheckFile(localname)) - return true; + if (!(flags & DLLF_OVERWRITE)) + { + if (CL_CheckDLFile(localname)) + return true; + } //ZOID - can't download when recording if (cls.demorecording) @@ -886,7 +935,7 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) extern model_t *loadmodel; int i; - float giveuptime = Sys_DoubleTime()+0.1; //small things get padded into a single frame + float giveuptime = Sys_DoubleTime()+0.3; //small things get padded into a single frame #define atstage() ((cl.contentstage == stage++ && !dontactuallyload)?++cl.contentstage:false) #define endstage() if (!cls.timedemo && giveuptimenext) { - if (dl->flags & DLLF_REQUIRED) + if (dl->flags & DLLF_NONGAME) break; } if (!dl) - dl = cl.downloadlist; + { + for (dl = cl.downloadlist; dl; dl = dl->next) + { + if (dl->flags & DLLF_REQUIRED) + break; + } + if (!dl) + dl = cl.downloadlist; + } fl = dl->flags; + /*if we don't require downloads don't queue requests until we're actually on the server, slightly more deterministic*/ if (cls.state == ca_active || requiredownloads.value || (fl & DLLF_REQUIRED)) { - if ((fl & DLLF_OVERWRITE) || !COM_FCheckExists (dl->localname)) + if ((fl & DLLF_OVERWRITE) || !CL_CheckFile (dl->localname)) { CL_SendDownloadStartRequest(dl->rname, dl->localname); return; @@ -1283,10 +1343,8 @@ void CL_RequestNextDownload (void) return; cl.sendprespawn = false; -#ifdef _MSC_VER - //FIXME: timedemo timer should start here. -#else -#warning timedemo timer should start here +#ifdef warningmsg +#pragma warningmsg("timedemo timer should start here") #endif if (!cl.worldmodel || cl.worldmodel->needload) @@ -1342,8 +1400,24 @@ void CL_SendDownloadReq(sizebuf_t *msg) if (cls.downloadmethod == DL_QWCHUNKS) { extern int download_file_number; + extern cvar_t drate; + static float lasttime; int p; - for (p = 0; p < 8; p++) + if (!drate.ival) + p = 64; + else + { + lasttime = fabs(realtime - lasttime); + if (lasttime > 1) + lasttime = 1; + p = lasttime * drate.ival; + if (p > 90) + p = 90; + } + lasttime = realtime; + if (!p) + p = 1; + while (p-->0) { int i = CL_RequestADownloadChunk(); if (i >= 0) @@ -1424,6 +1498,12 @@ downloadlist_t *CL_DownloadFailed(char *name) { VFS_CLOSE(cls.downloadqw); cls.downloadqw = NULL; + if (!strncmp(cls.downloadtempname, "package/", 8)) + FS_Remove(cls.downloadtempname, FS_ROOT); + else if (!strncmp(cls.downloadtempname,"skins/",6)) + FS_Remove(va("qw/%s", cls.downloadtempname), FS_ROOT); + else + FS_Remove(cls.downloadtempname, FS_GAME); CL_SendClientCommand(true, "stopdownload"); } *cls.downloadlocalname = 0; @@ -1449,11 +1529,14 @@ downloadlist_t *CL_DownloadFailed(char *name) float downloadstarttime; #ifdef PEXT_CHUNKEDDOWNLOADS -#define MAXBLOCKS 64 //must be power of 2 +#define MAXBLOCKS 512 //must be power of 2 #define DLBLOCKSIZE 1024 int downloadsize; int receivedbytes; -int recievedblock[MAXBLOCKS]; +struct +{ + int chunkno; +} dlblock[MAXBLOCKS]; int firstblock; int blockcycle; int download_file_number; @@ -1468,7 +1551,7 @@ void CL_ParseChunkedDownload(void) qbyte *svname; //qbyte osname[MAX_OSPATH]; //unreferenced int totalsize; - int chunknum; + int chunknum, ridx; char data[DLBLOCKSIZE]; chunknum = MSG_ReadLong(); @@ -1527,7 +1610,12 @@ void CL_ParseChunkedDownload(void) COM_DefaultExtension(cls.downloadtempname, ".tmp"); */ - if (!strncmp(cls.downloadtempname,"skins/",6)) + if (!strncmp(cls.downloadtempname, "package/", 8)) + { + FS_CreatePath(cls.downloadtempname+8, FS_ROOT); + cls.downloadqw = FS_OpenVFS(cls.downloadtempname + 8, "wb", FS_ROOT); + } + else if (!strncmp(cls.downloadtempname,"skins/",6)) { FS_CreatePath (va("qw/%s", cls.downloadtempname), FS_ROOT); cls.downloadqw = FS_OpenVFS (va("qw/%s", cls.downloadtempname), "wb", FS_ROOT); @@ -1548,7 +1636,8 @@ void CL_ParseChunkedDownload(void) firstblock = 0; receivedbytes = 0; blockcycle = -1; //so it requests 0 first. :) - memset(recievedblock, 0, sizeof(recievedblock)); + for (chunknum = 0; chunknum < MAXBLOCKS; chunknum++) + dlblock[chunknum].chunkno = ~0u; return; } @@ -1563,31 +1652,21 @@ void CL_ParseChunkedDownload(void) { //err, yeah, when playing demos we don't actually pay any attention to this. return; } - if (chunknum < firstblock) - { -// Con_Printf("too old\n", chunknum); - return; - } - if (chunknum-firstblock >= MAXBLOCKS) - { -// Con_Printf("^1too new!\n", chunknum); - return; - } - if (recievedblock[chunknum&(MAXBLOCKS-1)]) + for (ridx = 0; ridx < MAXBLOCKS; ridx++) { -// Con_Printf("duplicated\n", chunknum); + if (dlblock[ridx].chunkno == chunknum) + break; + } + if (ridx == MAXBLOCKS) + { + Con_DPrintf("dupe/invalid chunk received\n", chunknum); return; } + dlblock[ridx].chunkno = ~0; + // Con_Printf("usable\n", chunknum); receivedbytes+=DLBLOCKSIZE; - recievedblock[chunknum&(MAXBLOCKS-1)] = true; - - while(recievedblock[firstblock&(MAXBLOCKS-1)]) - { - recievedblock[firstblock&(MAXBLOCKS-1)] = false; - firstblock++; - } VFS_SEEK(cls.downloadqw, chunknum*DLBLOCKSIZE); if (downloadsize - chunknum*DLBLOCKSIZE < DLBLOCKSIZE) //final block is actually meant to be smaller than we recieve. @@ -1611,7 +1690,7 @@ int CL_CountQueuedDownloads(void) int CL_RequestADownloadChunk(void) { int i; - int b; + int ridx; if (cls.downloadmethod != DL_QWCHUNKS) { @@ -1619,18 +1698,17 @@ int CL_RequestADownloadChunk(void) return -1; } - blockcycle++; for (i = 0; i < MAXBLOCKS; i++) { - b = ((i+blockcycle)&(MAXBLOCKS-1)) - + firstblock; - if (!recievedblock[b&(MAXBLOCKS-1)]) //don't ask for ones we've already got. + blockcycle++; + ridx = blockcycle&(MAXBLOCKS-1); + if (dlblock[ridx].chunkno == ~0u) { - if (b >= (downloadsize+DLBLOCKSIZE-1)/DLBLOCKSIZE) //don't ask for blocks that are over the size of the file. + if (firstblock >= (downloadsize+DLBLOCKSIZE-1)/DLBLOCKSIZE) continue; -// Con_Printf("Requesting block %i\n", b); - return b; + dlblock[ridx].chunkno = firstblock++; } + return dlblock[ridx].chunkno; } // Con_Printf("^1 EOF?\n"); @@ -2465,6 +2543,24 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. cls.protocol_nq = CPNQ_FITZ666; Con_DPrintf("FitzQuake 666 protocol\n"); } + else if (protover == RMQ_PROTOCOL_VERSION) + { + int fl; + cls.protocol_nq = CPNQ_FITZ666; + Con_DPrintf("RMQ extensions to FitzQuake's protocol\n"); + fl = MSG_ReadLong(); + + if (fl & RMQFL_SHORTANGLE) + netprim.anglesize = 2; + if (fl & RMQFL_FLOATANGLE) + netprim.anglesize = 4; + if (fl & RMQFL_24BITCOORD) + netprim.coordsize = 3; + if (fl & RMQFL_FLOATCOORD) + netprim.coordsize = 4; + if (fl & ~(RMQFL_SHORTANGLE|RMQFL_FLOATANGLE|RMQFL_24BITCOORD|RMQFL_FLOATCOORD)) + Con_Printf("WARNING: Server is using unsupported RMQ extensions\n"); + } else if (protover == DP5_PROTOCOL_VERSION) { //darkplaces5 @@ -2502,7 +2598,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } else if (protover != NQ_PROTOCOL_VERSION) { - Host_EndGame ("Server returned version %i, not %i\nYou will need to use a different client.", protover, NQ_PROTOCOL_VERSION); + Host_EndGame ("Server is using protocol version %i, which is not supported by this version of " FULLENGINENAME ".", protover); } else { @@ -2545,7 +2641,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } strcpy (cl.model_name[nummodels], str); if (*str != '*') //not inline models! - CL_CheckOrEnqueDownloadFile(str, NULL, 0); + CL_CheckOrEnqueDownloadFile(str, NULL, ((nummodels==1)?DLLF_REQUIRED:0)); Mod_TouchModel (str); } @@ -2562,10 +2658,8 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } strcpy (cl.sound_name[numsounds], str); -#ifdef _MSC_VER -#pragma message("CLNQ_ParseServerData: no sound autodownloads") -#endif - //CL_CheckOrEnqueDownloadFile(str, NULL, 0); + if (*str != '*') //not inline models! + CL_CheckOrEnqueDownloadFile(va("sound/%s", str), NULL, 0); S_TouchSound (str); } @@ -4705,6 +4799,17 @@ void CL_ParseStuffCmd(char *msg, int destsplit) //this protects stuffcmds from n Cbuf_AddText ("\n", RESTRICT_SERVER+destsplit); } } + else if (!strncmp(stufftext, "//paknames ", 11)) + { + Q_strncpyz(cl.serverpaknames, stufftext+11, sizeof(cl.serverpaknames)); + cl.serverpakschanged = true; + } + else if (!strncmp(stufftext, "//paks ", 7)) + { + Q_strncpyz(cl.serverpakcrcs, stufftext+7, sizeof(cl.serverpakcrcs)); + cl.serverpakschanged = true; + CL_CheckServerInfo(); + } else if (!strncmp(stufftext, "//vwep ", 7)) { int i; diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 2183c545..417f367b 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -665,15 +665,35 @@ void CL_CalcClientTime(void) } else { - want = cl.oldgametime + (realtime - cl.gametimemark); - if (want>cl.servertime) - cl.servertime = want; + oldst = cl.servertime; + + cl.servertime += host_frametime; if (cl.servertime > cl.gametime) + { cl.servertime = cl.gametime; +// Con_Printf("clamped to new time\n"); + } if (cl.servertime < cl.oldgametime) - cl.servertime = cl.oldgametime; + { + if (cl.servertime < cl.oldgametime-0.5) + { + cl.servertime = cl.oldgametime-0.5; +// Con_Printf("clamped to old time\n"); + } + else if (cl.servertime < cl.oldgametime-0.3) + { + cl.servertime += 0.02*(cl.oldgametime - cl.servertime); +// Con_Printf("running really slow\n"); + } + else + { + cl.servertime += 0.01*(cl.oldgametime - cl.servertime); +// Con_Printf("running slow\n"); + } + } } + cl.time = cl.servertime; if (oldst == 0) { int i; @@ -682,6 +702,7 @@ void CL_CalcClientTime(void) cl.players[i].entertime += cl.servertime; } } + return; } if (cls.protocol == CP_NETQUAKE || (cls.demoplayback && cls.demoplayback != DPB_MVD && cls.demoplayback != DPB_EZTV)) @@ -755,8 +776,6 @@ void CL_PredictMovePNum (int pnum) if (cl.paused && !(cls.demoplayback!=DPB_MVD && cls.demoplayback!=DPB_EZTV) && (!cl.spectator || !autocam[pnum])) return; - CL_CalcClientTime(); - if (cl.intermission && cl.intermission != 3 && cls.protocol == CP_QUAKEWORLD) { cl.crouch[pnum] = 0; @@ -885,7 +904,7 @@ fixedorg: cl.onground[pnum] = pmove.onground; - if (to->senttime >= cl.time) + if (to->senttime >= realtime) break; from = to; } @@ -895,7 +914,7 @@ fixedorg: from = to; to = &ind; to->cmd[pnum] = independantphysics[pnum]; - to->senttime = cl.time; + to->senttime = realtime; CL_PredictUsercmd (pnum, &from->playerstate[cl.playernum[pnum]] , &to->playerstate[cl.playernum[pnum]], &to->cmd[pnum]); @@ -918,7 +937,7 @@ fixedorg: f = 0; else { - f = (cl.time - from->senttime) / (to->senttime - from->senttime); + f = (realtime - from->senttime) / (to->senttime - from->senttime); if (f < 0) f = 0; diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 70728120..d95c0d87 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -183,6 +183,7 @@ extern cvar_t scr_sshot_type; extern cvar_t scr_sshot_compression; extern cvar_t crosshair; extern cvar_t scr_consize; +cvar_t scr_neticontimeout = CVAR("scr_neticontimeout", "0.3"); qboolean scr_initialized; // ready to draw @@ -238,6 +239,7 @@ void CLSCR_Init(void) Cvar_Register(&show_speed, cl_screengroup); Cvar_Register(&show_speed_x, cl_screengroup); Cvar_Register(&show_speed_y, cl_screengroup); + Cvar_Register(&scr_neticontimeout, cl_screengroup); } /* @@ -987,7 +989,7 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) extern cvar_t cl_crossx, cl_crossy, crosshaircorrect, v_viewheight; vrect_t rect; - SCR_VRectForPlayer(&rect, pnum); + rect = r_refdef.vrect; if (cl.worldmodel && crosshaircorrect.ival) { @@ -1136,7 +1138,7 @@ SCR_DrawNet */ void SCR_DrawNet (void) { - if (cls.netchan.outgoing_sequence - cls.netchan.incoming_acknowledged < UPDATE_BACKUP-1) + if (realtime - cls.netchan.last_received < scr_neticontimeout.value) return; if (cls.demoplayback || !scr_net) return; @@ -1776,8 +1778,8 @@ qboolean SCR_ScreenShot (char *filename) ext = COM_FileExtension(filename); buffer = VID_GetRGBInfo(MAX_PREPAD, &truewidth, &trueheight); -#ifdef _MSC_VER -#pragma message("Need to ensure that the various image writing routines can cope with ((width|height)&3") +#ifdef warningmsg +#pragma warningmsg("Need to ensure that the various image writing routines can cope with ((width|height)&3") #endif if (!buffer) diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 68ed9e5a..369432d1 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -175,6 +175,7 @@ typedef struct { int entity; short tag; + qbyte active; qbyte flags; qbyte type; qbyte skin; @@ -571,6 +572,7 @@ beam_t *CL_NewBeam (int entity, int tag) for (i=0, b=cl_beams; i < beams_running; i++, b++) if (b->entity == entity && b->tag == tag) { + b->active = true; return b; } } @@ -578,8 +580,9 @@ beam_t *CL_NewBeam (int entity, int tag) // find a free beam for (i=0, b=cl_beams; i < beams_running; i++, b++) { - if (!b->model) + if (!b->active) { + b->active = true; return b; } } @@ -587,6 +590,7 @@ beam_t *CL_NewBeam (int entity, int tag) if (i == beams_running && i != MAX_BEAMS) { beams_running++; + cl_beams[i].active = true; return &cl_beams[i]; } @@ -603,6 +607,7 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n int i; vec3_t impact, normal; vec3_t extra; + char *mname; switch(tent) { @@ -610,12 +615,12 @@ 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, rtqw_railtrail, NULL)) + if (P_ParticleTrail(start, end, rtqw_railtrail, -ent, NULL)) P_ParticleTrailIndex(start, end, 208, 8, NULL); return; } default: - m = Mod_ForName("progs/bolt.mdl", false); + mname = "progs/bolt.mdl"; btype = rtfte_lightning1; etype = ptfte_lightning1_end; break; @@ -623,37 +628,43 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n if (ent < 0 && ent >= -MAX_CLIENTS) //based on the railgun concept - this adds a rogue style TE_BEAM effect. { case 5: - m = Mod_ForName("progs/beam.mdl", false); //remember to precache! + mname = "progs/beam.mdl"; //remember to precache! btype = P_FindParticleType("te_beam"); etype = P_FindParticleType("te_beam_end"); } else { - m = Mod_ForName("progs/bolt2.mdl", false); + mname = "progs/bolt2.mdl"; btype = rtfte_lightning2; etype = ptfte_lightning2_end; } break; case 2: - m = Mod_ForName("progs/bolt3.mdl", false); + mname = "progs/bolt3.mdl"; btype = rtfte_lightning3; etype = ptfte_lightning3_end; break; #ifdef Q2CLIENT case 3: - m = Mod_ForName(q2tentmodels[q2cl_mod_parasite_segment].modelname, false); + mname = q2tentmodels[q2cl_mod_parasite_segment].modelname; btype = P_FindParticleType("te_parasite_attack"); etype = P_FindParticleType("te_parasite_attack_end"); break; case 4: - m = Mod_ForName(q2tentmodels[q2cl_mod_grapple_cable].modelname, false); + mname = q2tentmodels[q2cl_mod_grapple_cable].modelname; btype = P_FindParticleType("te_grapple_cable"); etype = P_FindParticleType("te_grapple_cable_end"); break; #endif } - if (!m || m->needload) + /*don't bother loading the model if we have a particle effect for it instead*/ + if (ruleset_allow_particle_lightning.ival && btype >= 0) + m = NULL; + else + m = Mod_ForName(mname, false); + + if (m && m->needload) CL_CheckOrEnqueDownloadFile(m->name, NULL, 0); // save end position for truelightning @@ -695,11 +706,11 @@ void CL_AddBeam (int tent, int ent, vec3_t start, vec3_t end) //fixme: use TE_ n b->entity = ent; b->model = m; + b->particleeffect = btype; b->tag = -1; b->flags |= /*STREAM_ATTACHED|*/1; b->endtime = cl.time + 0.2; b->alpha = 1; - b->particleeffect = btype; VectorCopy (start, b->start); VectorCopy (end, b->end); @@ -765,6 +776,7 @@ void CL_ParseStream (int type) b->tag = tag; b->flags = flags; b->model = NULL; + b->particleeffect = -1; b->endtime = cl.time + duration; b->alpha = 1; b->skin = skin; @@ -1282,8 +1294,8 @@ void CL_ParseTEnt (void) pos2[1] = MSG_ReadCoord (); pos2[2] = MSG_ReadCoord (); - if (P_ParticleTrail(pos, pos2, rtqw_railtrail, NULL)) - if (P_ParticleTrail(pos, pos2, rtq2_railtrail, NULL)) + if (P_ParticleTrail(pos, pos2, rtqw_railtrail, 0, NULL)) + if (P_ParticleTrail(pos, pos2, rtq2_railtrail, 0, NULL)) P_ParticleTrailIndex(pos, pos2, 208, 8, NULL); break; @@ -1421,7 +1433,7 @@ void CL_ParseTEnt (void) // stain (Hopefully this is close to how DP does it) R_AddStain(pos, -10, -10, -10, 30); - if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_plasmaburn"), NULL)) + if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_plasmaburn"), 0, NULL)) P_ParticleTrailIndex(pos, pos2, 15, 0, NULL); break; @@ -1439,7 +1451,7 @@ void CL_ParseTEnt (void) MSG_ReadCoord (); MSG_ReadCoord (); - if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_nexbeam"), NULL)) + if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_nexbeam"), 0, NULL)) P_ParticleTrailIndex(pos, pos2, 15, 0, NULL); break; @@ -1634,7 +1646,7 @@ void CL_ParseCustomTEnt(void) { MSG_ReadPos (pos); MSG_ReadPos (pos2); - failed = P_ParticleTrail(pos, pos2, t->particleeffecttype, NULL); + failed = P_ParticleTrail(pos, pos2, t->particleeffecttype, 0, NULL); } else { @@ -1736,8 +1748,8 @@ void CLDP_ParseTrailParticles(void) ts = NULL; effectindex = P_FindParticleType(COM_Effectinfo_ForNumber(effectindex)); - if (P_ParticleTrail(start, end, effectindex, ts)) - P_ParticleTrail(start, end, rt_blood, ts); + if (P_ParticleTrail(start, end, effectindex, entityindex, ts)) + P_ParticleTrail(start, end, rt_blood, entityindex, ts); } void CLDP_ParsePointParticles(qboolean compact) @@ -2111,7 +2123,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_RAILTRAIL: // railgun effect MSG_ReadPos (pos); MSG_ReadPos (pos2); - if (P_ParticleTrail(pos, pos2, rtq2_railtrail, NULL)) + if (P_ParticleTrail(pos, pos2, rtq2_railtrail, 0, NULL)) P_ParticleTrailIndex(pos, pos2, 0x74, 8, NULL); Q2S_StartSound (pos, 0, 0, S_PrecacheSound ("weapons/railgf1a.wav"), 1, ATTN_NORM, 0); break; @@ -2321,7 +2333,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_BUBBLETRAIL: MSG_ReadPos (pos); MSG_ReadPos (pos2); - if (P_ParticleTrail(pos, pos2, rtq2_bubbletrail, NULL)) + if (P_ParticleTrail(pos, pos2, rtq2_bubbletrail, 0, NULL)) P_ParticleTrailIndex(pos, pos2, 4, 8, NULL); break; @@ -2496,7 +2508,7 @@ void CLQ2_ParseTEnt (void) case Q2TE_DEBUGTRAIL: MSG_ReadPos (pos); MSG_ReadPos (pos2); - if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), NULL)) + if (P_ParticleTrail(pos, pos2, P_FindParticleType("te_debugtrail"), 0, NULL)) P_ParticleTrailIndex(pos, pos2, 116, 8, NULL); break; @@ -2800,7 +2812,7 @@ void CL_UpdateBeams (void) // update lightning for (bnum=0, b=cl_beams; bnum < beams_running; bnum++, b++) { - if (!b->model) + if (!b->active) continue; if (b->endtime < cl.time) @@ -2809,7 +2821,7 @@ void CL_UpdateBeams (void) { /*don't let lightning decay while paused*/ P_DelinkTrailstate(&b->trailstate); P_DelinkTrailstate(&b->emitstate); - b->model = NULL; + b->active = false; continue; } } @@ -2851,7 +2863,7 @@ void CL_UpdateBeams (void) VectorSubtract (playerbeam_end[j], vieworg, org); len = VectorLength(org); org[2] -= 22; // adjust for view height - vectoangles (org, ang); + VectorAngles (org, NULL, ang); // lerp pitch ang[0] = -ang[0]; @@ -2926,9 +2938,11 @@ void CL_UpdateBeams (void) pitch += 360; } - if (ruleset_allow_particle_lightning.ival) - if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, &b->trailstate)) + if (ruleset_allow_particle_lightning.ival || !b->model) + if (b->particleeffect >= 0 && !P_ParticleTrail(b->start, b->end, b->particleeffect, b->entity, &b->trailstate)) continue; + if (!b->model) + continue; // add new entities for the lightning VectorCopy (b->start, org); diff --git a/engine/client/client.h b/engine/client/client.h index d5d8529f..b4f15125 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -261,6 +261,11 @@ typedef struct dlight_s float minlight; // don't add when contributing less float color[3]; float channelfade[3]; + float ambientscale; + float diffusescale; + float specularscale; + float corona; + float coronascale; unsigned int flags; @@ -411,11 +416,8 @@ typedef struct qboolean allow_mirrors; qboolean allow_watervis; qboolean allow_luma; - qboolean allow_bump; float allow_fbskins; //fraction of allowance -#ifdef FISH - qboolean allow_fish; -#endif + qboolean allow_postproc; qboolean allow_cheats; qboolean allow_semicheats; //defaults to true, but this allows a server to enforce a strict ruleset (smackdown type rules). float maxfps; //server capped @@ -436,11 +438,12 @@ typedef struct downloadlist_s { 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 +#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 //download's size isn't known +#define DLLF_IGNOREFAILED 16 // +#define DLLF_NONGAME 32 //means the requested download filename+localname is gamedir explicit (so id1/foo.txt is distinct from qw/foo.txt) struct downloadlist_s *next; } downloadlist_t; @@ -487,6 +490,9 @@ typedef struct qboolean allowsendpacket; char serverinfo[MAX_SERVERINFO_STRING]; + char serverpaknames[1024]; + char serverpakcrcs[1024]; + qboolean serverpakschanged; int parsecount; // server message counter int oldparsecount; @@ -1094,7 +1100,7 @@ void Cam_TrackPlayer(int pnum, char *cmdname, char *plrarg); void Cam_Lock(int pnum, int playernum); void CL_InitCam(void); -void QDECL vectoangles(vec3_t vec, vec3_t ang); +void QDECL vectoangles(vec3_t fwd, vec3_t ang); // //zqtp.c @@ -1237,7 +1243,7 @@ void Media_Init(void); qboolean Media_PlayFilm(char *name); typedef struct cin_s cin_t; struct cin_s *Media_StartCin(char *name); -texid_t Media_UpdateForShader(cin_t *cin); +texid_tf Media_UpdateForShader(cin_t *cin); void Media_ShutdownCin(cin_t *cin); qboolean Media_FakeTrack(int i, qboolean loop); diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index de898357..b51beee6 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1007,6 +1007,11 @@ void CLQ2_ParseFrame (void) cl.q2frame.deltaframe = MSG_ReadLong (); cl.q2frame.servertime = cl.q2frame.serverframe*100; + cl.oldgametime = cl.gametime; + cl.oldgametimemark = cl.gametimemark; + cl.gametime = cl.q2frame.servertime/1000.f; + cl.gametimemark = realtime; + i = MSG_ReadByte (); for (j=0 ; jlerp_origin, ent.origin, rtq2_rocket, ¢->trailstate)) - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_rocket, ent.keynum, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_rocket, ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xdc, 4, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.2, 0); @@ -1597,7 +1602,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } else { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_blastertrail, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_blastertrail, ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe0, 1, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 200, 0.2, 0.2, 0); } @@ -1612,14 +1617,14 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } else if (effects & Q2EF_GIB) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_gib, ¢->trailstate)) - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blood, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_gib, ent.keynum, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_blood, ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0xe8, 8, ¢->trailstate); } else if (effects & Q2EF_GRENADE) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_grenade, ¢->trailstate)) - if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_grenade, ent.keynum, ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, rt_grenade, ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 4, 8, ¢->trailstate); } else if (effects & Q2EF_FLIES) @@ -1651,13 +1656,13 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } else if (effects & Q2EF_FLAG1) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_flag1"), ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_flag1"), ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 242, 1, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.05, 0.05); } else if (effects & Q2EF_FLAG2) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_flag2"), ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_flag2"), ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 115, 1, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 225, 0.05, 0.05, 0.2); } @@ -1665,7 +1670,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) //ROGUE else if (effects & Q2EF_TAGTRAIL) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_tagtrail"), ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_tagtrail"), ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 220, 1, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 225, 0.2, 0.2, 0.0); } @@ -1688,7 +1693,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) } else if (effects & Q2EF_TRACKER) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_tracker"), ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_tracker"), ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 0, 1, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 200, -0.2, -0.2, -0.2); } @@ -1697,13 +1702,13 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) // RAFAEL else if (effects & Q2EF_GREENGIB) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_greengib"), ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_greengib"), ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 219, 8, ¢->trailstate); } // RAFAEL else if (effects & Q2EF_IONRIPPER) { - if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_ionripper"), ¢->trailstate)) + if (P_ParticleTrail(cent->lerp_origin, ent.origin, P_FindParticleType("ef_ionripper"), ent.keynum, ¢->trailstate)) P_ParticleTrailIndex(cent->lerp_origin, ent.origin, 228, 4, ¢->trailstate); V_AddLight (ent.keynum, ent.origin, 100, 0.2, 0.1, 0.1); } @@ -1717,7 +1722,7 @@ void CLQ2_AddPacketEntities (q2frame_t *frame) { if (effects & Q2EF_ANIM_ALLFAST) { - P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_blastertrail, ¢->trailstate); + P_ParticleTrail(cent->lerp_origin, ent.origin, rtq2_blastertrail, ent.keynum, ¢->trailstate); } V_AddLight (ent.keynum, ent.origin, 130, 0.2, 0.1, 0.1); } diff --git a/engine/client/image.c b/engine/client/image.c index 8f369865..d87b24ef 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -642,7 +642,7 @@ void (PNGAPI *qpng_read_end) PNGARG((png_structp png_ptr, png_infop info_ptr)) P void (PNGAPI *qpng_read_image) PNGARG((png_structp png_ptr, png_bytepp image)) PSTATIC(png_read_image); png_byte (PNGAPI *qpng_get_bit_depth) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_bit_depth); png_byte (PNGAPI *qpng_get_channels) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_channels); -png_uint_32 (PNGAPI *qpng_get_rowbytes) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_rowbytes); +png_size_t (PNGAPI *qpng_get_rowbytes) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_get_rowbytes); void (PNGAPI *qpng_read_update_info) PNGARG((png_structp png_ptr, png_infop info_ptr)) PSTATIC(png_read_update_info); void (PNGAPI *qpng_set_strip_16) PNGARG((png_structp png_ptr)) PSTATIC(png_set_strip_16); void (PNGAPI *qpng_set_expand) PNGARG((png_structp png_ptr)) PSTATIC(png_set_expand); @@ -2168,7 +2168,7 @@ typedef struct { } ddsheader; -texid_t GL_LoadTextureDDS(unsigned char *buffer, int filesize) +texid_tf GL_LoadTextureDDS(char *iname, unsigned char *buffer, int filesize) { extern int gl_filter_min; extern int gl_filter_max; @@ -2216,7 +2216,7 @@ texid_t GL_LoadTextureDDS(unsigned char *buffer, int filesize) if (!qglCompressedTexImage2DARB) return r_nulltex; - texnum = GL_AllocNewTexture(fmtheader.dwWidth, fmtheader.dwHeight); + texnum = GL_AllocNewTexture(iname, fmtheader.dwWidth, fmtheader.dwHeight); GL_MTBind(0, GL_TEXTURE_2D, texnum); datasize = fmtheader.dwPitchOrLinearSize; @@ -2233,12 +2233,12 @@ texid_t GL_LoadTextureDDS(unsigned char *buffer, int filesize) h = 1; qglCompressedTexImage2DARB(GL_TEXTURE_2D, mipnum, intfmt, w, h, 0, datasize, buffer); if (qglGetError()) - Con_Printf("Incompatible dds file (mip %i)\n", mipnum); + Con_Printf("Incompatible dds file %s (mip %i)\n", iname, mipnum); buffer += datasize; datasize/=4; } if (qglGetError()) - Con_Printf("Incompatible dds file\n"); + Con_Printf("Incompatible dds file %s\n", iname); if (nummips>1) @@ -2355,7 +2355,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) image_width = 0; image_height = 0; - COM_StripAllExtensions(name, nicename, sizeof(nicename)); + COM_StripExtension(name, nicename, sizeof(nicename)); while((data = strchr(nicename, '*'))) { @@ -2421,7 +2421,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) if ((buf = COM_LoadFile (fname, 5))) { #ifdef DDS - tex = GL_LoadTextureDDS(buf, com_filesize); + tex = GL_LoadTextureDDS(fname, buf, com_filesize); if (TEXVALID(tex)) { BZ_Free(buf); @@ -2494,7 +2494,7 @@ texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags) if ((buf = COM_LoadFile (fname, 5))) { extern cvar_t vid_hardwaregamma; - tex = r_nulltex; + TEXASSIGNF(tex, r_nulltex); if (com_filesize >= 8) { image_width = LittleLong(((int*)buf)[0]); @@ -2582,7 +2582,7 @@ texid_t R_LoadBumpmapTexture(char *name, char *subpath) if ((data = ReadTargaFile(buf, com_filesize, &image_width, &image_height, 2))) //Only load a greyscale image. { TRACE(("dbg: Mod_LoadBumpmapTexture: tga %s loaded\n", name)); - tex = R_LoadTexture8Bump(name, image_width, image_height, data, IF_NOALPHA|IF_NOGAMMA); + TEXASSIGNF(tex, R_LoadTexture8Bump(name, image_width, image_height, data, IF_NOALPHA|IF_NOGAMMA)); BZ_Free(data); } else diff --git a/engine/client/in_win.c b/engine/client/in_win.c index c741a4f0..a1b3741e 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -1317,6 +1317,10 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) if (mousecursor_y >= vid.height) mousecursor_y = vid.height - 1; mx=my=0; + +#ifdef PEXT_CSQC + CSQC_MousePosition(mousecursor_x, mousecursor_y); +#endif } else { @@ -1326,13 +1330,6 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) mx = 0; my = 0; } -#endif -#ifdef PEXT_CSQC - if (CSQC_MousePosition(mx, my)) - { - mx = 0; - my = 0; - } #endif } diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 67c26636..b8a74153 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -2083,7 +2083,9 @@ int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend, switch (bulk->variant) { case -1: // end of menu + default: bulk = NULL; + control = NULL; continue; case 0: // white text control = (union menuoption_s *)MC_AddWhiteText(menu, x, y, bulk->text, bulk->rightalign); @@ -2093,6 +2095,7 @@ int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend, break; case 2: // spacing spacing = bulk->spacing; + control = NULL; break; } break; @@ -2149,11 +2152,11 @@ int MC_AddBulk(struct menu_s *menu, menubulk_t *bulk, int xstart, int xtextend, if (bulk->ret) *bulk->ret = control; - if (MI_Selectable(control) && !selected) + if (control && MI_Selectable(control) && !selected) selected = control; - if (bulk->tooltip) + if (control && bulk->tooltip) control->common.tooltip = bulk->tooltip; - if (xleft > 0) + if (control && xleft > 0) control->common.extracollide = xleft; y += spacing; diff --git a/engine/client/m_master.c b/engine/client/m_master.c index 0a4c46c3..9e8b1b8f 100644 --- a/engine/client/m_master.c +++ b/engine/client/m_master.c @@ -85,8 +85,8 @@ static void NM_PrintWhite (int cx, int cy, qbyte *str) static void NM_PrintColoured (int cx, int cy, int colour, qbyte *str) { -#ifdef _MSC_VER -#pragma message("NM_PrintColoured: needs reimplementing") +#ifdef warningmsg +#pragma warningmsg("NM_PrintColoured: needs reimplementing") #endif /* while (*str) @@ -100,8 +100,8 @@ static void NM_PrintColoured (int cx, int cy, int colour, qbyte *str) static void NM_PrintHighlighted (int cx, int cy, int colour, int bg, qbyte *str) { -#ifdef _MSC_VER -#pragma message("NM_PrintHighlighted: needs reimplementing") +#ifdef warningmsg +#pragma warningmsg("NM_PrintHighlighted: needs reimplementing") #endif /* while (*str) @@ -265,8 +265,8 @@ int M_AddColumn (int right, int y, char *text, int maxchars, int colour, int hig right = left; -#ifdef _MSC_VER -#pragma message("M_AddColumn: needs reimplementing") +#ifdef warningmsg +#pragma warningmsg("M_AddColumn: needs reimplementing") #endif /* if (highlight >= 0) diff --git a/engine/client/m_mp3.c b/engine/client/m_mp3.c index e688b8f6..cd442281 100644 --- a/engine/client/m_mp3.c +++ b/engine/client/m_mp3.c @@ -1755,7 +1755,7 @@ qboolean Media_ShowFilm(void) } #if defined(GLQUAKE) || defined(D3DQUAKE) -texid_t Media_UpdateForShader(cin_t *cin) +texid_tf Media_UpdateForShader(cin_t *cin) { if (!cin) return r_nulltex; @@ -1767,7 +1767,7 @@ texid_t Media_UpdateForShader(cin_t *cin) if (!cin->outunchanged) { if (!TEXVALID(cin->texture)) - cin->texture = R_AllocNewTexture(cin->outwidth, cin->outheight); + TEXASSIGN(cin->texture, R_AllocNewTexture("***cin***", cin->outwidth, cin->outheight)); R_Upload(cin->texture, "cin", cin->outtype, cin->outdata, cin->outpalette, cin->outwidth, cin->outheight, IF_NOMIPMAP|IF_NOALPHA|IF_NOGAMMA); } diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 1fc5ccb5..fc93daf1 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -692,7 +692,7 @@ void M_Menu_Teamplay_f (void) MB_CHECKBOXCVARTIP("Parse Macros", cl_parseSay, 0, "Whether to parse teamplay macros like %l etc."), MB_CHECKBOXCVARTIP("Load Locs", tp_loadlocs, 0, "Whether to load teamplay locations from .loc files"), MB_CHECKBOXCVARTIP("No Blink", cl_noblink, 0, "No blinking characters"), - MB_EDITCVARTIP("Sound Trigger", "tp_soundtrigger", "Character that indicates the following text is a wav file.\nExample:\nsay_team ~location.wav$\me: I'm at %l #a"), + MB_EDITCVARTIP("Sound Trigger", "tp_soundtrigger", "Character that indicates the following text is a wav file.\nExample:\nsay_team ~location.wav$\\me: I'm at %l #a"), MB_EDITCVARTIP("Weapon Order", "tp_weapon_order","Weapon preference order:\n8 = Lightning Gun\n7 = Rocket Launcher\n6 = Grenade Launcher\n5 = Super Nailgun\n4 = Nailgun\n3 = Super Shotgun\n2 = Shotgun\n1 = Axe"), MB_CHECKBOXCVARTIP("Teamplay Triggers", cl_triggers, 0, "Enable or disable teamplay triggers"), MB_CHECKBOXCVARTIP("Force Triggers", tp_forceTriggers, 0, "Whether to force teamplay triggers in non-teamplay play like in a 1 on 1 situation"), @@ -935,7 +935,7 @@ void M_Menu_Network_f (void) NULL }; static const char *splitvalues[] = {"0", "1", "2", "3", NULL}; - extern cvar_t allow_download_csprogs, allow_download_redirection, requiredownloads, cl_solid_players; + extern cvar_t cl_download_csprogs, cl_download_redirection, requiredownloads, cl_solid_players; extern cvar_t cl_splitscreen, cl_predict_players; menu_t *menu; int y; @@ -948,10 +948,10 @@ void M_Menu_Network_f (void) MB_EDITCVARSLIM("Download Rate", "drate", "Maximum bytes per second that the server should send maps and demos to the client"), MB_SPACING(4), MB_CHECKBOXCVARTIP("Require Download", requiredownloads, 0, "Ignore downloaded content sent to the client and connect immediatly"), - MB_CHECKBOXCVARTIP("Redirect Download", allow_download_redirection, 0, "Whether the client will ignore download redirection from servers"), - MB_CHECKBOXCVARTIP("Download CSQC", allow_download_csprogs, 0, "Whether to allow the client to download CSQC (client-side QuakeC) progs from servers"), + MB_CHECKBOXCVARTIP("Redirect Download", cl_download_redirection, 0, "Whether the client will ignore download redirection from servers"), + MB_CHECKBOXCVARTIP("Download CSQC", cl_download_csprogs, 0, "Whether to allow the client to download CSQC (client-side QuakeC) progs from servers"), MB_SPACING(4), - MB_CHECKBOXCVARTIP("Predict Players", cl_predict_players, 0, "Toggle player prediction"), + MB_CHECKBOXCVARTIP("Predict Other Players", cl_predict_players, 0, "Toggle player prediction"), MB_CHECKBOXCVARTIP("Solid Players", cl_solid_players, 0, "When running/clipping into other players, ON make it appear they are solid, OFF will make it appear like running into a marshmellon."), MB_COMBOCVAR("Split-screen", cl_splitscreen, splitopts, splitvalues, "Enables split screen with a number of clients. This feature requires server support."), MB_END() diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 9ca433eb..d6037261 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -426,7 +426,6 @@ const char *presetexec[] = "r_nolightdir 1;" "r_dynamic 0;" "gl_flashblend 0;" - "gl_bump 0;" "gl_specular 0;" "r_loadlit 0;" "r_fastsky 1;" @@ -466,7 +465,6 @@ const char *presetexec[] = "r_particlesystem script;" "r_particledesc \"spikeset tsshaft\";" #endif -// "gl_bump 1;" // requires restart "gl_specular 1;" "r_loadlit 2;" // "r_fastsky -1;" @@ -699,7 +697,7 @@ void M_Menu_Textures_f (void) NULL }; - extern cvar_t gl_load24bit, gl_specular, gl_bump, gl_detail, gl_compress, gl_picmip, gl_picmip2d, gl_max_size, r_drawflat; + extern cvar_t gl_load24bit, gl_specular, gl_detail, gl_compress, gl_picmip, gl_picmip2d, gl_max_size, r_drawflat; extern cvar_t gl_texture_anisotropic_filtering, gl_texturemode, gl_texturemode2d; int y; menubulk_t bulk[] = @@ -712,7 +710,7 @@ void M_Menu_Textures_f (void) MB_COMBOCVAR("2D Filter Mode", gl_texturemode2d, texture2dfilternames, texture2dfiltervalues, "Chooses the texture filtering method used for HUD, menus, and other 2D assets."), MB_COMBOCVAR("Anisotropy", gl_texture_anisotropic_filtering, anisotropylevels, anisotropyvalues, NULL), MB_SPACING(4), - MB_CHECKBOXCVAR("Bumpmapping", gl_bump, 0), + MB_CHECKBOXCVAR("Deluxemapping", r_deluxemapping, 0), MB_CHECKBOXCVAR("Specular Highlights", gl_specular, 0), MB_CHECKBOXCVAR("Detail Textures", gl_detail, 0), MB_SPACING(4), diff --git a/engine/client/merged.h b/engine/client/merged.h index 431ff8cc..156a82d6 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -147,18 +147,41 @@ void Draw_FunString(int x, int y, const void *str); void Draw_AltFunString(int x, int y, const void *str); void Draw_FunStringWidth(int x, int y, const void *str, int width); +int r_regsequence; #ifdef SERVERONLY #define Mod_Q1LeafPVS Mod_LeafPVS // qbyte *Mod_LeafPVS (struct mleaf_s *leaf, struct model_s *model, qbyte *buffer); #endif -typedef union { - unsigned int num; +typedef struct +{ + int regsequence; +} texcom_t; +struct texid_s +{ + union + { + unsigned int num; #ifdef D3DQUAKE - void *ptr; + void *ptr; +#endif + }; + texcom_t *ref; +}; +#if 1 +typedef struct texid_s texid_t; +#define texid_tf texid_t +#define TEXASSIGN(d,s) d=s +#define TEXASSIGNF(d,s) d=s +#define TEXVALID(t) ((t).ref!=NULL) +#else +typedef struct texid_s texid_t[1]; +typedef struct texid_s texid_tf; +#define TEXASSIGN(d,s) memcpy(&d,&s,sizeof(d)) +#define TEXASSIGNF(d,s) memcpy(&d,&s,sizeof(d)) +#define TEXVALID(t) 1 #endif -} texid_t; typedef enum uploadfmt uploadfmt_t; //not all modes accept meshes - STENCIL(intentional) and DEPTHONLY(not implemented) typedef enum backendmode_e @@ -182,12 +205,12 @@ typedef struct rendererinfo_s { void (*Draw_Init) (void); void (*Draw_Shutdown) (void); - texid_t (*IMG_LoadTexture) (char *identifier, int width, int height, uploadfmt_t fmt, void *data, unsigned int flags); - texid_t (*IMG_LoadTexture8Pal24) (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); - texid_t (*IMG_LoadTexture8Pal32) (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); - texid_t (*IMG_LoadCompressed) (char *name); - texid_t (*IMG_FindTexture) (char *identifier); - texid_t (*IMG_AllocNewTexture) (int w, int h); + texid_tf (*IMG_LoadTexture) (char *identifier, int width, int height, uploadfmt_t fmt, void *data, unsigned int flags); + texid_tf (*IMG_LoadTexture8Pal24) (char *identifier, int width, int height, qbyte *data, qbyte *palette24, unsigned int flags); + texid_tf (*IMG_LoadTexture8Pal32) (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); + texid_tf (*IMG_LoadCompressed) (char *name); + texid_tf (*IMG_FindTexture) (char *identifier); + texid_tf (*IMG_AllocNewTexture) (char *identifier, int w, int h); void (*IMG_Upload) (texid_t tex, char *name, uploadfmt_t fmt, void *data, void *palette, int width, int height, unsigned int flags); void (*IMG_DestroyTexture) (texid_t tex); @@ -248,6 +271,7 @@ typedef struct rendererinfo_s { //Uploads all modified lightmaps void (*BE_UploadAllLightmaps)(void); void (*BE_SelectEntity)(struct entity_s *ent); + void (*BE_SelectDLight)(struct dlight_s *dl, vec3_t colour); /*check to see if an ent should be drawn for the selected light*/ qboolean (*BE_LightCullModel)(vec3_t org, struct model_s *model); @@ -272,6 +296,7 @@ typedef struct rendererinfo_s { #define BE_UploadAllLightmaps rf->BE_UploadAllLightmaps #define BE_LightCullModel rf->BE_LightCullModel #define BE_SelectEntity rf->BE_SelectEntity +#define BE_SelectDLight rf->BE_SelectDLight #define BE_GetTempBatch rf->BE_GetTempBatch #define BE_SubmitBatch rf->BE_SubmitBatch #define BE_DrawMesh_List rf->BE_DrawMesh_List diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 583a40a6..0c18b6ef 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -591,8 +591,8 @@ void Master_AddMaster (char *address, int type, char *description) return; } -#ifdef _MSC_VER -#pragma message("Master_AddMaster: add ipv6. don't care about tcp/irc.") +#ifdef warningmsg +#pragma warningmsg("Master_AddMaster: add ipv6. don't care about tcp/irc.") #endif if (adr.type != NA_IP && adr.type != NA_IPX) { @@ -797,8 +797,8 @@ void NET_SendPollPacket(int len, void *data, netadr_t to) int ret; struct sockaddr_qstorage addr; -#ifdef _MSC_VER -#pragma message("NET_SendPollPacket: no support for ipv6") +#ifdef warningmsg +#pragma warningmsg("NET_SendPollPacket: no support for ipv6") #endif NetadrToSockadr (&to, &addr); diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index e681c50c..6e38b5e3 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -25,6 +25,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "shader.h" #include "renderque.h" +#define POLYS + void D_DrawParticleTrans (vec3_t porg, float palpha, float pscale, unsigned int pcolour, blendmode_t blendmode); @@ -82,7 +84,7 @@ static int ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66}; static int ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3}; #define qpal(q) ((default_quakepal[(q)*3+0]<<0) | (default_quakepal[(q)*3+1]<<8) | (default_quakepal[(q)*3+2]<<16)) - +#ifndef POLYS #define BUFFERVERTS 2048*3 static vecV_t classicverts[BUFFERVERTS]; static union c @@ -93,6 +95,7 @@ static union c static vec2_t classictexcoords[BUFFERVERTS]; static index_t classicindexes[BUFFERVERTS]; mesh_t classicmesh; +#endif static shader_t *classicshader; @@ -197,6 +200,7 @@ static qboolean PClassic_InitParticles (void) particles = (cparticle_t *) BZ_Malloc (r_numparticles * sizeof(cparticle_t)); +#ifndef POLYS for (i = 0; i < BUFFERVERTS; i += 3) { classictexcoords[i+1][0] = 1; @@ -210,6 +214,7 @@ static qboolean PClassic_InitParticles (void) classicmesh.st_array = classictexcoords; classicmesh.colors4b_array = (byte_vec4_t*)classiccolours; classicmesh.indexes = classicindexes; +#endif classicshader = R_RegisterShader("particles_classic", "{\n" "nomipmaps\n" @@ -221,7 +226,7 @@ static qboolean PClassic_InitParticles (void) "}\n" "}\n" ); - classicshader->defaulttextures.base = particlecqtexture; + TEXASSIGN(classicshader->defaulttextures.base, particlecqtexture); return true; } @@ -279,8 +284,13 @@ static void PClassic_DrawParticles(void) float time2, time3, time1, dvel, frametime, grav; vec3_t up, right; float dist, scale, r_partscale=0; - union c usecolours; unsigned int *palette; +#ifdef POLYS + scenetris_t *scenetri; +#else + union c usecolours; +#endif + static float oldtime; RSpeedMark(); /*#ifdef D3DQUAKE @@ -302,7 +312,9 @@ static void PClassic_DrawParticles(void) VectorScale (vup, 1.5, up); VectorScale (vright, 1.5, right); - frametime = host_frametime; + frametime = cl.time - oldtime; + oldtime = cl.time; + frametime = bound(0, frametime, 1); if (cl.paused || r_secondaryview || r_refdef.recurse) frametime = 0; time3 = frametime * 15; @@ -311,6 +323,25 @@ static void PClassic_DrawParticles(void) grav = frametime * 800 * 0.05; dvel = 4 * frametime; +#ifdef POLYS + if (cl_numstris && cl_stris[cl_numstris-1].shader == classicshader) + scenetri = &cl_stris[cl_numstris-1]; + else + { + if (cl_numstris == cl_maxstris) + { + cl_maxstris+=8; + cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris); + } + scenetri = &cl_stris[cl_numstris++]; + scenetri->shader = classicshader; + scenetri->firstidx = cl_numstrisidx; + scenetri->firstvert = cl_numstrisvert; + scenetri->numvert = 0; + scenetri->numidx = 0; + } +#endif + while(1) { kill = active_particles; @@ -339,6 +370,49 @@ static void PClassic_DrawParticles(void) break; } + // 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; + +#ifdef POLYS + if (cl_numstrisvert+3 > cl_maxstrisvert) + { + cl_maxstrisvert+=64*3; + cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert); + cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert); + cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); + } + + Vector4Set(cl_strisvertc[cl_numstrisvert+0],1,1,1,1); + Vector4Set(cl_strisvertc[cl_numstrisvert+1],1,1,1,1); + Vector4Set(cl_strisvertc[cl_numstrisvert+2],1,1,1,1); + + Vector4Set(cl_strisvertc[cl_numstrisvert+0], ((p->rgb&0xff)>>0)/256.0, ((p->rgb&0xff00)>>8)/256.0, ((p->rgb&0xff0000)>>16)/256.0, ((p->type == pt_fire)?((6 - p->ramp) *0.166666):1.0)); + Vector4Copy(cl_strisvertc[cl_numstrisvert+0], cl_strisvertc[cl_numstrisvert+1]); + Vector4Copy(cl_strisvertc[cl_numstrisvert+0], cl_strisvertc[cl_numstrisvert+2]); + + Vector2Set(cl_strisvertt[cl_numstrisvert+0], 0, 0); + Vector2Set(cl_strisvertt[cl_numstrisvert+1], 1, 0); + Vector2Set(cl_strisvertt[cl_numstrisvert+2], 0, 1); + + VectorCopy(p->org, cl_strisvertv[cl_numstrisvert+0]); + VectorMA(p->org, scale, up, cl_strisvertv[cl_numstrisvert+1]); + VectorMA(p->org, scale, right, cl_strisvertv[cl_numstrisvert+2]); + + if (cl_numstrisidx+3 > cl_maxstrisidx) + { + cl_maxstrisidx += 64*3; + cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); + } + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 0; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 1; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - scenetri->firstvert) + 2; + + cl_numstrisvert += 3; + + scenetri->numvert += 3; + scenetri->numidx += 3; +#else if (classicmesh.numvertexes >= BUFFERVERTS-3) { classicmesh.numindexes = classicmesh.numvertexes; @@ -346,11 +420,6 @@ static void PClassic_DrawParticles(void) classicmesh.numvertexes = 0; } - // 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; - - usecolours.i = p->rgb; if (p->type == pt_fire) usecolours.b[3] = 255 * (6 - p->ramp) / 6; @@ -365,9 +434,7 @@ static void PClassic_DrawParticles(void) classiccolours[classicmesh.numvertexes].i = usecolours.i; VectorMA(p->org, scale, right, classicverts[classicmesh.numvertexes]); classicmesh.numvertexes++; - - - +#endif p->org[0] += p->vel[0] * frametime; p->org[1] += p->vel[1] * frametime; @@ -421,14 +488,14 @@ static void PClassic_DrawParticles(void) break; } } - +#ifndef POLYS if (classicmesh.numvertexes) { classicmesh.numindexes = classicmesh.numvertexes; BE_DrawMesh_Single(classicshader, &classicmesh, NULL, &classicshader->defaulttextures, 0); classicmesh.numvertexes = 0; } - +#endif RSpeedEnd(RSPEED_PARTICLESDRAW); } @@ -741,7 +808,7 @@ done: //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) +static int PClassic_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, trailstate_t **tsk) { float leftover; diff --git a/engine/client/p_null.c b/engine/client/p_null.c index c657f219..24d99a5a 100644 --- a/engine/client/p_null.c +++ b/engine/client/p_null.c @@ -19,7 +19,7 @@ static int PNULL_FindParticleType(char *name) } 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_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, 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){} diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 0e73744d..79147a43 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -246,7 +246,7 @@ typedef struct part_type_s { vec3_t dl_rgb; float dl_radius; float dl_time; - vec3_t dl_decay; + vec4_t dl_decay; vec3_t stain_rgb; float stain_radius; @@ -534,7 +534,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) "rgbgen vertex\n" "alphagen vertex\n" "}\n" - "polygonoffset\n" +// "polygonoffset\n" "}\n" ; break; @@ -549,7 +549,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) "rgbgen vertex\n" "alphagen vertex\n" "}\n" - "polygonoffset\n" +// "polygonoffset\n" "}\n" ; break; @@ -564,7 +564,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) "rgbgen vertex\n" "alphagen vertex\n" "}\n" - "polygonoffset\n" +// "polygonoffset\n" "}\n" ; break; @@ -579,7 +579,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) "rgbgen vertex\n" "alphagen vertex\n" "}\n" - "polygonoffset\n" +// "polygonoffset\n" "}\n" ; break; @@ -594,7 +594,7 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) "rgbgen vertex\n" "alphagen vertex\n" "}\n" - "polygonoffset\n" +// "polygonoffset\n" "}\n" ; break; @@ -616,26 +616,26 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) { /*untextured beams get a single continuous blob*/ ptype->looks.shader = R_RegisterShader(va("beam%s", namepostfix), defaultshader); - tn.base = beamtexture; + TEXASSIGNF(tn.base, beamtexture); } else if (ptype->looks.type == PT_SPARKFAN) { /*untextured beams get a single continuous blob*/ ptype->looks.shader = R_RegisterShader(va("fan%s", namepostfix), defaultshader); - tn.base = ptritexture; + TEXASSIGNF(tn.base, ptritexture); } else if (strstr(ptype->texname, "glow") || strstr(ptype->texname, "ball") || ptype->looks.type == PT_TEXTUREDSPARK) { /*sparks and special names get a nice circular texture. as these are fully default, we can basically discard the texture name in the shader, and get better batching*/ ptype->looks.shader = R_RegisterShader(va("ball%s", namepostfix), defaultshader); - tn.base = balltexture; + TEXASSIGNF(tn.base, balltexture); } else { /*anything else gets a fuzzy texture*/ ptype->looks.shader = R_RegisterShader(va("default%s", namepostfix), defaultshader); - tn.base = explosiontexture; + TEXASSIGNF(tn.base, explosiontexture); } } else @@ -680,7 +680,52 @@ static void P_ParticleEffect_f(void) return; } - ptype = P_GetParticleType(Cmd_Argv(1)); + var = Cmd_Argv(1); + if (*var == '+') + { + ptype = P_GetParticleType(var+1); + if (ptype->loaded) + { + int i, parenttype; + char newname[256]; + for (i = 0; i < 64; i++) + { + parenttype = ptype - part_type; + snprintf(newname, sizeof(newname), "+%i%s", i, var); + ptype = P_GetParticleType(newname); + if (!ptype->loaded) + { + if (part_type[parenttype].assoc != P_INVALID) + Con_Printf("warning: assoc on particle chain %s overridden\n", var+1); + part_type[parenttype].assoc = ptype - part_type; + break; + } + } + if (i == 64) + { + Con_Printf("Too many duplicate names, gave up\n"); + return; + } + } + } + else + { + ptype = P_GetParticleType(Cmd_Argv(1)); + if (ptype->loaded) + { + assoc = ptype->assoc; + while (assoc != P_INVALID && assoc < FALLBACKBIAS) + { + if (*part_type[assoc].name == '+') + { + part_type[assoc].loaded = false; + assoc = part_type[assoc].assoc; + } + else + break; + } + } + } if (!ptype) { Con_Printf("Bad name\n"); @@ -811,6 +856,7 @@ static void P_ParticleEffect_f(void) else if (!strcmp(var, "beamtexstep")) { ptype->rotationstartmin = 1/atof(value); + ptype->rotationstartrand = 0; setbeamlen = true; } else if (!strcmp(var, "beamtexspeed")) @@ -1247,6 +1293,25 @@ static void P_ParticleEffect_f(void) ptype->flags |= PT_NOSPREADFIRST; else if (!strcmp(var, "nospreadlast")) ptype->flags |= PT_NOSPREADLAST; + + else if (!strcmp(var, "lightradius")) + ptype->dl_radius = atof(value); + else if (!strcmp(var, "lightradiusfade")) + ptype->dl_decay[3] = atof(value); + else if (!strcmp(var, "lightrgb")) + { + ptype->dl_rgb[0] = atof(value); + ptype->dl_rgb[1] = atof(Cmd_Argv(2)); + ptype->dl_rgb[2] = atof(Cmd_Argv(3)); + } + else if (!strcmp(var, "lightrgbfade")) + { + ptype->dl_decay[0] = atof(value); + ptype->dl_decay[1] = atof(Cmd_Argv(2)); + ptype->dl_decay[2] = atof(Cmd_Argv(3)); + } + else if (!strcmp(var, "lighttime")) + ptype->dl_time = atof(value); else Con_DPrintf("%s is not a recognised particle type field (in %s)\n", var, ptype->name); } @@ -2295,7 +2360,7 @@ static vec2_t avelocities[NUMVERTEXNORMALS]; // float timescale = 0.01; -static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir) +static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir, int dlkey) { if (*ptype->modelname) { @@ -2306,10 +2371,11 @@ static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir) } if (ptype->dl_radius) { - dlight_t *dl = CL_NewDlightRGB(0, org, ptype->dl_radius, ptype->dl_time, ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]); + dlight_t *dl = CL_NewDlightRGB(dlkey, org, ptype->dl_radius, ptype->dl_time, ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]); dl->channelfade[0] = ptype->dl_decay[0]; dl->channelfade[1] = ptype->dl_decay[1]; dl->channelfade[2] = ptype->dl_decay[2]; + dl->decay = ptype->dl_decay[3]; } if (ptype->stain_radius) R_AddStain(org, ptype->stain_rgb[0], ptype->stain_rgb[1], ptype->stain_rgb[2], ptype->stain_radius); @@ -2378,7 +2444,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, while(ptype) { - PScript_EffectSpawned(ptype, org, dir); + PScript_EffectSpawned(ptype, org, dir, 0); if (ptype->looks.type == PT_DECAL) { @@ -3139,7 +3205,7 @@ static void PScript_RunParticleWeather(vec3_t minb, vec3_t maxb, vec3_t dir, flo } } -static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype, trailstate_t **tsk) +static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype, trailstate_t **tsk, int dlkey) { vec3_t vec, vstep, right, up, start; float len; @@ -3187,14 +3253,14 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype else ts = NULL; - PScript_EffectSpawned(ptype, start, vec3_origin); + PScript_EffectSpawned(ptype, start, vec3_origin, dlkey); if (ptype->assoc>=0) { if (ts) - P_ParticleTrail(start, end, ptype->assoc, &(ts->assoc)); + P_ParticleTrail(start, end, ptype->assoc, dlkey, &(ts->assoc)); else - P_ParticleTrail(start, end, ptype->assoc, NULL); + P_ParticleTrail(start, end, ptype->assoc, dlkey, NULL); } // time limit for trails @@ -3608,14 +3674,14 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype return; } -static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailstate_t **tsk) +static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, int dlkey, trailstate_t **tsk) { part_type_t *ptype = &part_type[type]; // TODO: fallback particle system won't have a decent trailstate which will mess up // high fps trails if (type >= FALLBACKBIAS && fallback) - return fallback->ParticleTrail(startpos, end, type-FALLBACKBIAS, NULL); + return fallback->ParticleTrail(startpos, end, type-FALLBACKBIAS, dlkey, NULL); if (type < 0 || type >= numparticletypes) return 1; //bad value @@ -3633,7 +3699,7 @@ static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailst ptype = &part_type[ptype->inwater]; } - P_ParticleTrailDraw (startpos, end, ptype, tsk); + P_ParticleTrailDraw (startpos, end, ptype, tsk, dlkey); return 0; } @@ -3641,7 +3707,7 @@ static void PScript_ParticleTrailIndex (vec3_t start, vec3_t end, int color, int { part_type[pe_defaulttrail].colorindex = color; part_type[pe_defaulttrail].colorrand = crnd; - P_ParticleTrail(start, end, pe_defaulttrail, tsk); + P_ParticleTrail(start, end, pe_defaulttrail, 0, tsk); } static vec3_t pright, pup; @@ -3779,8 +3845,8 @@ static void GL_DrawTrifanParticle(int count, particle_t **plist, plooks_t *type) static void GL_DrawLineSparkParticle(int count, particle_t **plist, plooks_t *type) { -#ifdef _MSC_VER -#pragma message("fixme: no line sparks") +#ifdef warningmsg +#pragma warningmsg("fixme: no line sparks") #endif #if 0 particle_t *p; @@ -3810,6 +3876,89 @@ static void GL_DrawLineSparkParticle(int count, particle_t **plist, plooks_t *ty #endif } +static void R_AddTSparkParticle(scenetris_t *t, particle_t *p, plooks_t *type) +{ + vec3_t v, cr, o2; + float scale; + + if (cl_numstrisvert+4 > cl_maxstrisvert) + { + cl_maxstrisvert+=64*4; + cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert); + cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert); + cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); + } + + if (type->scalefactor == 1) + scale = p->scale*0.25; + else + { + 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; + } + + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+0]); + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+1]); + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+2]); + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+3]); + + Vector2Set(cl_strisvertt[cl_numstrisvert+0], p->s1, p->t1); + Vector2Set(cl_strisvertt[cl_numstrisvert+1], p->s1, p->t2); + Vector2Set(cl_strisvertt[cl_numstrisvert+2], p->s2, p->t2); + Vector2Set(cl_strisvertt[cl_numstrisvert+3], p->s2, p->t1); + + + + if (type->stretch) + { + VectorMA(p->org, type->stretch, p->vel, o2); + VectorMA(p->org, -type->stretch, p->vel, v); + VectorSubtract(r_refdef.vieworg, v, v); + } + else + { + VectorMA(p->org, 0.1, p->vel, o2); + VectorSubtract(r_refdef.vieworg, p->org, v); + } + + CrossProduct(v, p->vel, cr); + VectorNormalize(cr); + + VectorMA(p->org, -p->scale/2, cr, cl_strisvertv[cl_numstrisvert+0]); + VectorMA(p->org, p->scale/2, cr, cl_strisvertv[cl_numstrisvert+1]); + + VectorSubtract(r_refdef.vieworg, o2, v); + CrossProduct(v, p->vel, cr); + VectorNormalize(cr); + + VectorMA(o2, p->scale/2, cr, cl_strisvertv[cl_numstrisvert+2]); + VectorMA(o2, -p->scale/2, cr, cl_strisvertv[cl_numstrisvert+3]); + + + + if (cl_numstrisidx+6 > cl_maxstrisidx) + { + cl_maxstrisidx += 64*6; + cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); + } + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 0; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 1; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 2; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 0; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 2; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 3; + + cl_numstrisvert += 4; + + t->numvert += 4; + t->numidx += 6; +} + static void GL_DrawTexturedSparkParticle(int count, particle_t **plist, plooks_t *type) { particle_t *p; @@ -3902,6 +4051,7 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) VectorSubtract(r_refdef.vieworg, q->org, v); VectorNormalize(v); CrossProduct(c->dir, v, cr); + VectorNormalize(cr); ts = c->texture_s*q->angle + particletime*q->rotationspeed; Vector4Copy(q->rgba, pscriptcolours[pscriptmesh.numvertexes+0]); Vector4Copy(q->rgba, pscriptcolours[pscriptmesh.numvertexes+1]); @@ -3913,6 +4063,7 @@ static void GL_DrawParticleBeam(int count, beamseg_t **blist, plooks_t *type) VectorSubtract(r_refdef.vieworg, p->org, v); VectorNormalize(v); CrossProduct(b->dir, v, cr); // replace with old p->dir? + VectorNormalize(cr); ts = b->texture_s*p->angle + particletime*p->rotationspeed; Vector4Copy(p->rgba, pscriptcolours[pscriptmesh.numvertexes+2]); Vector4Copy(p->rgba, pscriptcolours[pscriptmesh.numvertexes+3]); @@ -3970,6 +4121,85 @@ static void GL_DrawClippedDecal(int count, clippeddecal_t **dlist, plooks_t *typ } } +static void R_AddTexturedParticle(scenetris_t *t, particle_t *p, plooks_t *type) +{ + float scale, x, y; + + if (cl_numstrisvert+4 > cl_maxstrisvert) + { + cl_maxstrisvert+=64*4; + cl_strisvertv = BZ_Realloc(cl_strisvertv, sizeof(*cl_strisvertv)*cl_maxstrisvert); + cl_strisvertt = BZ_Realloc(cl_strisvertt, sizeof(*cl_strisvertt)*cl_maxstrisvert); + cl_strisvertc = BZ_Realloc(cl_strisvertc, sizeof(*cl_strisvertc)*cl_maxstrisvert); + } + + if (type->scalefactor == 1) + scale = p->scale*0.25; + else + { + 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; + } + + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+0]); + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+1]); + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+2]); + Vector4Copy(p->rgba, cl_strisvertc[cl_numstrisvert+3]); + + Vector2Set(cl_strisvertt[cl_numstrisvert+0], p->s1, p->t1); + Vector2Set(cl_strisvertt[cl_numstrisvert+1], p->s1, p->t2); + Vector2Set(cl_strisvertt[cl_numstrisvert+2], p->s2, p->t2); + Vector2Set(cl_strisvertt[cl_numstrisvert+3], p->s2, p->t1); + + if (p->angle) + { + x = sin(p->angle)*scale; + y = cos(p->angle)*scale; + + cl_strisvertv[cl_numstrisvert+0][0] = p->org[0] - x*pright[0] - y*pup[0]; + cl_strisvertv[cl_numstrisvert+0][1] = p->org[1] - x*pright[1] - y*pup[1]; + cl_strisvertv[cl_numstrisvert+0][2] = p->org[2] - x*pright[2] - y*pup[2]; + cl_strisvertv[cl_numstrisvert+1][0] = p->org[0] - y*pright[0] + x*pup[0]; + cl_strisvertv[cl_numstrisvert+1][1] = p->org[1] - y*pright[1] + x*pup[1]; + cl_strisvertv[cl_numstrisvert+1][2] = p->org[2] - y*pright[2] + x*pup[2]; + cl_strisvertv[cl_numstrisvert+2][0] = p->org[0] + x*pright[0] + y*pup[0]; + cl_strisvertv[cl_numstrisvert+2][1] = p->org[1] + x*pright[1] + y*pup[1]; + cl_strisvertv[cl_numstrisvert+2][2] = p->org[2] + x*pright[2] + y*pup[2]; + cl_strisvertv[cl_numstrisvert+3][0] = p->org[0] + y*pright[0] - x*pup[0]; + cl_strisvertv[cl_numstrisvert+3][1] = p->org[1] + y*pright[1] - x*pup[1]; + cl_strisvertv[cl_numstrisvert+3][2] = p->org[2] + y*pright[2] - x*pup[2]; + } + else + { + VectorMA(p->org, -scale, pup, cl_strisvertv[cl_numstrisvert+0]); + VectorMA(p->org, -scale, pright, cl_strisvertv[cl_numstrisvert+1]); + VectorMA(p->org, scale, pup, cl_strisvertv[cl_numstrisvert+2]); + VectorMA(p->org, scale, pright, cl_strisvertv[cl_numstrisvert+3]); + } + + if (cl_numstrisidx+6 > cl_maxstrisidx) + { + cl_maxstrisidx += 64*6; + cl_strisidx = BZ_Realloc(cl_strisidx, sizeof(*cl_strisidx)*cl_maxstrisidx); + } + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 0; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 1; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 2; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 0; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 2; + cl_strisidx[cl_numstrisidx++] = (cl_numstrisvert - t->firstvert) + 3; + + cl_numstrisvert += 4; + + t->numvert += 4; + t->numidx += 6; +} + static void PScript_DrawParticleTypes (void) { void (*sparklineparticles)(int count, particle_t **,plooks_t*)=GL_DrawLineSparkParticle; @@ -3978,6 +4208,7 @@ static void PScript_DrawParticleTypes (void) qboolean (*tr) (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); void *pdraw, *bdraw; + void (*tdraw)(scenetris_t *t, particle_t *p, plooks_t *type); vec3_t oldorg; vec3_t stop, normal; @@ -3987,6 +4218,7 @@ static void PScript_DrawParticleTypes (void) ramp_t *ramp; float grav; vec3_t friction; + scenetris_t *scenetri; 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. @@ -4116,6 +4348,7 @@ static void PScript_DrawParticleTypes (void) bdraw = NULL; pdraw = NULL; + tdraw = NULL; // set drawing methods by type and cvars and hope branch // prediction takes care of the rest @@ -4131,6 +4364,7 @@ static void PScript_DrawParticleTypes (void) break; case PT_NORMAL: pdraw = GL_DrawTexturedParticle; + tdraw = R_AddTexturedParticle; break; case PT_SPARK: pdraw = sparklineparticles; @@ -4140,9 +4374,29 @@ static void PScript_DrawParticleTypes (void) break; case PT_TEXTUREDSPARK: pdraw = sparktexturedparticles; + tdraw = R_AddTSparkParticle; break; } + if (!tdraw || type->looks.shader->sort == SHADER_SORT_BLEND) + scenetri = NULL; + else if (cl_numstris && cl_stris[cl_numstris-1].shader == type->looks.shader) + scenetri = &cl_stris[cl_numstris-1]; + else + { + if (cl_numstris == cl_maxstris) + { + cl_maxstris+=8; + cl_stris = BZ_Realloc(cl_stris, sizeof(*cl_stris)*cl_maxstris); + } + scenetri = &cl_stris[cl_numstris++]; + scenetri->shader = type->looks.shader; + scenetri->firstidx = cl_numstrisidx; + scenetri->firstvert = cl_numstrisvert; + scenetri->numvert = 0; + scenetri->numidx = 0; + } + if (!type->die) { while ((p=type->particles)) @@ -4358,7 +4612,7 @@ static void PScript_DrawParticleTypes (void) if (type->emit >= 0) { if (type->emittime < 0) - P_ParticleTrail(oldorg, p->org, type->emit, &p->state.trailstate); + P_ParticleTrail(oldorg, p->org, type->emit, 0, &p->state.trailstate); else if (p->state.nextemit < particletime) { p->state.nextemit = particletime + type->emittime + frandom()*type->emitrand; @@ -4387,16 +4641,18 @@ static void PScript_DrawParticleTypes (void) p->vel[2] *= type->clipbounce; if (!*type->texname && Length(p->vel)<1000*pframetime && type->looks.type == PT_NORMAL) + { p->die = -1; + continue; + } } else { p->die = -1; VectorNormalize(p->vel); P_RunParticleEffectType(stop, p->vel, type->clipcount/part_type[type->cliptype].count, type->cliptype); + continue; } - - continue; } } else if (type->stainonimpact && r_bloodstains.ival) @@ -4412,7 +4668,11 @@ static void PScript_DrawParticleTypes (void) } } - if (pdraw) + if (scenetri) + { + tdraw(scenetri, p, type->slooks); + } + else if (pdraw) RQ_AddDistReorder((void*)pdraw, p, type->slooks, p->org); } diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index c4c54064..bd680ea9 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -39,7 +39,7 @@ typedef struct csqctreadstate_s { struct csqctreadstate_s *next; } csqctreadstate_t; -static unsigned int csqcchecksum; +static unsigned int csprogs_checksum, csaddon_checksum; static csqctreadstate_t *csqcthreads; qboolean csqc_resortfrags; qboolean csqc_drawsbar; @@ -49,6 +49,7 @@ world_t csqc_world; static int csqc_lplayernum; static qboolean csqc_isdarkplaces; +static qboolean csqc_singlecheats; /*single player or cheats active, allowing custom addons*/ static char csqc_printbuffer[8192]; @@ -156,6 +157,7 @@ typedef enum globalfloat(svtime, "time"); /*float Written before entering most qc functions*/ \ globalfloat(frametime, "frametime"); /*float Written before entering most qc functions*/ \ globalfloat(cltime, "cltime"); /*float Written before entering most qc functions*/ \ + globalfloat(physics_mode, "physics_mode"); /*float Written before entering most qc functions*/ \ globalentity(self, "self"); /*entity Written before entering most qc functions*/ \ globalentity(other, "other"); /*entity Written before entering most qc functions*/ \ \ @@ -266,6 +268,7 @@ static void CSQC_ChangeLocalPlayer(int lplayernum) static void CSQC_FindGlobals(void) { + static float csphysicsmode = 0; #define globalfloat(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); #define globalvector(name,qcname) csqcg.name = (float*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); #define globalentity(name,qcname) csqcg.name = (int*)PR_FindGlobal(csqcprogs, qcname, 0, NULL); @@ -290,9 +293,16 @@ static void CSQC_FindGlobals(void) csqc_world.g.self = csqcg.self; csqc_world.g.other = csqcg.other; csqc_world.g.force_retouch = (float*)PR_FindGlobal(csqcprogs, "force_retouch", 0, NULL); + csqc_world.g.physics_mode = csqcg.physics_mode; csqc_world.g.frametime = csqcg.frametime; csqc_world.g.newmis = (int*)PR_FindGlobal(csqcprogs, "newmis", 0, NULL); csqc_world.g.time = csqcg.svtime; + csqc_world.g.v_forward = csqcg.forward; + csqc_world.g.v_right = csqcg.right; + csqc_world.g.v_up = csqcg.up; + + if (!csqc_world.g.physics_mode) + csqc_world.g.physics_mode = &csphysicsmode; if (csqcg.maxclients) *csqcg.maxclients = cl.allocated_client_slots; @@ -459,27 +469,6 @@ static int csqcentsize; static char *csqcmapentitydata; static qboolean csqcmapentitydataloaded; - - -#define MAX_SKEL_OBJECTS 1024 - -typedef struct { - int inuse; - - model_t *model; - qboolean absolute; - - unsigned int numbones; - float *bonematrix; -} skelobject_t; - -skelobject_t skelobjects[MAX_SKEL_OBJECTS]; -int numskelobjectsused; - -skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount); -void skel_dodelete(void); - - qboolean csqc_deprecated_warned; #define csqc_deprecated(s) do {if (!csqc_deprecated_warned){Con_Printf("csqc warning: %s\n", s); csqc_deprecated_warned = true;}}while(0) @@ -551,13 +540,7 @@ static void cs_getframestate(csqcedict_t *in, unsigned int rflags, framestate_t out->bonestate = NULL; if (in->xv->skeletonindex) { - skelobject_t *so; - so = skel_get(csqcprogs, in->xv->skeletonindex, 0); - if (so && so->inuse == 1) - { - out->bonecount = so->numbones; - out->bonestate = so->bonematrix; - } + skel_lookup(csqcprogs, in->xv->skeletonindex, out); } } @@ -656,6 +639,7 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) int ival; model_t *model; unsigned int rflags; + unsigned int effects; ival = in->v->modelindex; model = CSQC_GetModelForIndex(ival); @@ -665,7 +649,8 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) memset(out, 0, sizeof(*out)); out->model = model; - if (in->xv->renderflags) + rflags = in->xv->renderflags; + if (rflags) { rflags = in->xv->renderflags; if (rflags & CSQCRF_VIEWMODEL) @@ -681,10 +666,13 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) out->flags |= RF_NOSHADOW; //CSQCRF_FRAMETIMESARESTARTTIMES is below } - else - rflags = 0; - if ((int)in->v->effects & EF_NODEPTHTEST) + effects = in->v->effects; + if (effects & NQEF_ADDITIVE) + out->flags |= Q2RF_ADDITIVE; + if (effects & DPEF_NOSHADOW) + out->flags |= RF_NOSHADOW; + if (effects & EF_NODEPTHTEST) out->flags |= RF_NODEPTHTEST; cs_getframestate(in, rflags, &out->framestate); @@ -901,6 +889,7 @@ static void QCBUILTIN PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_ csqcedict_t *ent; entity_t rent; int e; + int maxe; int oldself = *csqcg.self; @@ -913,7 +902,8 @@ static void QCBUILTIN PF_R_AddEntityMask(progfuncs_t *prinst, struct globalvars_ } } - for (e=1; e < *prinst->parms->sv_num_edicts; e++) + maxe = *prinst->parms->sv_num_edicts; + for (e=1; e < maxe; e++) { ent = (void*)EDICT_NUM(prinst, e); if (ent->isfree) @@ -1134,7 +1124,7 @@ static void QCBUILTIN PF_R_ClearScene (progfuncs_t *prinst, struct globalvars_s CL_SetUpPlayerPrediction(true); } - skel_dodelete(); + skel_dodelete(csqcprogs); CL_SwapEntityLists(); view_frame = &cl.frames[cls.netchan.incoming_sequence & UPDATE_MASK]; @@ -1173,8 +1163,8 @@ static void QCBUILTIN PF_R_GetViewFlag(progfuncs_t *prinst, struct globalvars_s *r = r_refdef.fov_y; break; -#ifdef _MSC_VER -#pragma message("fixme: AFOV not retrievable") +#ifdef warningmsg +#pragma warningmsg("fixme: AFOV not retrievable") #endif case VF_AFOV: *r = r_refdef.fov_x; @@ -1938,9 +1928,9 @@ static void QCBUILTIN PF_cs_trailparticles (progfuncs_t *prinst, struct globalva } if (!ent->entnum) //world trails are non-state-based. - pe->ParticleTrail(start, end, efnum, NULL); + pe->ParticleTrail(start, end, efnum, 0, NULL); else - pe->ParticleTrail(start, end, efnum, &ent->trailstate); + pe->ParticleTrail(start, end, efnum, -ent->entnum, &ent->trailstate); } static void QCBUILTIN PF_cs_particleeffectnum (progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -2221,7 +2211,15 @@ static void QCBUILTIN PF_cs_serverkey (progfuncs_t *prinst, struct globalvars_s char adr[MAX_ADR_SIZE]; if (!strcmp(keyname, "ip")) - ret = NET_AdrToString(adr, sizeof(adr), cls.netchan.remote_address); + { + if (cls.demoplayback) + { + extern char lastdemoname[]; + ret = lastdemoname; + } + else + ret = NET_AdrToString(adr, sizeof(adr), cls.netchan.remote_address); + } else if (!strcmp(keyname, "protocol")) { //using this is pretty acedemic, really. Not particuarly portable. switch (cls.protocol) @@ -3332,8 +3330,8 @@ static void QCBUILTIN PF_cs_gettaginfo (progfuncs_t *prinst, struct globalvars_s cs_getframestate(ent, ent->xv->renderflags, &fstate); -#ifdef _MSC_VER -#pragma message("PF_cs_gettaginfo: This function doesn't honour attachments (but setattachment isn't implemented yet anyway)") +#ifdef warningmsg +#pragma warningmsg("PF_cs_gettaginfo: This function doesn't honour attachments (but setattachment isn't implemented yet anyway)") #endif if (!Mod_GetTag(mod, tagnum, &fstate, transforms)) { @@ -3442,481 +3440,6 @@ static void QCBUILTIN PF_shaderforname (progfuncs_t *prinst, struct globalvars_s G_FLOAT(OFS_RETURN) = 0; } -void skel_reset(void) -{ - while (numskelobjectsused > 0) - { - numskelobjectsused--; - skelobjects[numskelobjectsused].numbones = 0; - skelobjects[numskelobjectsused].inuse = false; - } -} - -void skel_dodelete(void) -{ - int skelidx; - for (skelidx = 0; skelidx < numskelobjectsused; skelidx++) - { - if (skelobjects[skelidx].inuse == 2) - skelobjects[skelidx].inuse = 0; - } -} - -skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount) -{ - if (skelidx == 0) - { - //allocation - if (!bonecount) - return NULL; - - for (skelidx = 0; skelidx < numskelobjectsused; skelidx++) - { - if (!skelobjects[skelidx].inuse && skelobjects[skelidx].numbones == bonecount) - return &skelobjects[skelidx]; - } - - for (skelidx = 0; skelidx <= numskelobjectsused; skelidx++) - { - if (!skelobjects[skelidx].inuse && !skelobjects[skelidx].numbones) - { - skelobjects[skelidx].numbones = bonecount; - skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount); - if (skelidx <= numskelobjectsused) - { - numskelobjectsused = skelidx + 1; - skelobjects[skelidx].model = NULL; - skelobjects[skelidx].inuse = 1; - } - return &skelobjects[skelidx]; - } - } - - return NULL; - } - else - { - skelidx--; - if ((unsigned int)skelidx >= numskelobjectsused) - return NULL; - if (skelobjects[skelidx].inuse != 1) - return NULL; - if (bonecount && skelobjects[skelidx].numbones != bonecount) - return NULL; - return &skelobjects[skelidx]; - } -} - -//float(float modelindex) skel_create (FTE_CSQC_SKELETONOBJECTS) -static void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int numbones; - skelobject_t *skelobj; - qboolean isabs; - model_t *model; - int midx; - - midx = G_FLOAT(OFS_PARM0); - - //default to failure - G_FLOAT(OFS_RETURN) = 0; - - model = CSQC_GetModelForIndex(midx); - if (!model) - return; //no model set, can't get a skeleton - - isabs = false; - numbones = Mod_GetNumBones(model, isabs); - if (!numbones) - { -// isabs = true; -// numbones = Mod_GetNumBones(model, isabs); -// if (!numbones) - return; //this isn't a skeletal model. - } - - skelobj = skel_get(prinst, 0, numbones); - if (!skelobj) - return; //couldn't get one, ran out of memory or something? - - skelobj->model = model; - skelobj->absolute = isabs; - - G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; -} - -//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build (FTE_CSQC_SKELETONOBJECTS) -static void QCBUILTIN PF_skel_build(progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - csqcedict_t *ent = (csqcedict_t*)G_EDICT(prinst, OFS_PARM1); - int midx = G_FLOAT(OFS_PARM2); - float retainfrac = G_FLOAT(OFS_PARM3); - int firstbone = G_FLOAT(OFS_PARM4)-1; - int lastbone = G_FLOAT(OFS_PARM5)-1; - float addition = 1?G_FLOAT(OFS_PARM6):1-retainfrac; - - int i, j; - int numbones; - framestate_t fstate; - skelobject_t *skelobj; - model_t *model; - - //default to failure - G_FLOAT(OFS_RETURN) = 0; - - model = CSQC_GetModelForIndex(midx); - if (!model) - return; //invalid model, can't get a skeleton - - cs_getframestate(ent, ent->xv->renderflags, &fstate); - - //heh... don't copy. - fstate.bonecount = 0; - fstate.bonestate = NULL; - - numbones = Mod_GetNumBones(model, false); - if (!numbones) - { - return; //this isn't a skeletal model. - } - - skelobj = skel_get(prinst, skelidx, 0); - if (!skelobj) - return; //couldn't get one, ran out of memory or something? - - if (lastbone < 0) - lastbone = numbones; - if (lastbone > numbones) - lastbone = numbones; - if (firstbone < 0) - firstbone = 0; - - if (retainfrac == 0 && addition == 1) - { - /*replace everything*/ - Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, skelobj->bonematrix); - } - else - { - if (retainfrac != 1) - { - //rescale the existing bones - for (i = firstbone; i < lastbone; i++) - { - for (j = 0; j < 12; j++) - skelobj->bonematrix[i*12+j] *= retainfrac; - } - } - if (addition == 1) - { - //just add - float relationsbuf[MAX_BONES*12]; - Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, relationsbuf); - for (i = firstbone; i < lastbone; i++) - { - for (j = 0; j < 12; j++) - skelobj->bonematrix[i*12+j] += relationsbuf[i*12+j]; - } - } - else if (addition) - { - //add+scale - float relationsbuf[MAX_BONES*12]; - Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, relationsbuf); - for (i = firstbone; i < lastbone; i++) - { - for (j = 0; j < 12; j++) - skelobj->bonematrix[i*12+j] += addition*relationsbuf[i*12+j]; - } - } - } - - G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; -} - -//float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) -static void QCBUILTIN PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - skelobject_t *skelobj; - - skelobj = skel_get(prinst, skelidx, 0); - - if (!skelobj) - G_FLOAT(OFS_RETURN) = 0; - else - G_FLOAT(OFS_RETURN) = skelobj->numbones; -} - -//string(float skel, float bonenum) skel_get_bonename (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) -static void QCBUILTIN PF_skel_get_bonename (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - int boneidx = G_FLOAT(OFS_PARM1); - skelobject_t *skelobj; - - skelobj = skel_get(prinst, skelidx, 0); - - if (!skelobj) - G_INT(OFS_RETURN) = 0; - else - { - RETURN_TSTRING(Mod_GetBoneName(skelobj->model, boneidx)); - } -} - -//float(float skel, float bonenum) skel_get_boneparent (FTE_CSQC_SKELETONOBJECTS) -static void QCBUILTIN PF_skel_get_boneparent (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - int boneidx = G_FLOAT(OFS_PARM1); - skelobject_t *skelobj; - - skelobj = skel_get(prinst, skelidx, 0); - - if (!skelobj) - G_FLOAT(OFS_RETURN) = 0; - else - G_FLOAT(OFS_RETURN) = Mod_GetBoneParent(skelobj->model, boneidx); -} - -//float(float skel, string tagname) gettagindex (DP_MD3_TAGSINFO) -static void QCBUILTIN PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - char *bname = PR_GetStringOfs(prinst, OFS_PARM1); - skelobject_t *skelobj; - - skelobj = skel_get(prinst, skelidx, 0); - if (!skelobj) - G_FLOAT(OFS_RETURN) = 0; - else - G_FLOAT(OFS_RETURN) = Mod_TagNumForName(skelobj->model, bname); -} - -static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) -{ - out[0] = vx[0]; - out[1] = -vy[0]; - out[2] = vz[0]; - out[3] = t[0]; - out[4] = vx[1]; - out[5] = -vy[1]; - out[6] = vz[1]; - out[7] = t[1]; - out[8] = vx[2]; - out[9] = -vy[2]; - out[10] = vz[2]; - out[11] = t[2]; -} -void bonemat_toqcvectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) -{ - vx[0] = in[0]; - vx[1] = in[4]; - vx[2] = in[8]; - vy[0] = -in[1]; - vy[1] = -in[5]; - vy[2] = -in[9]; - vz[0] = in[2]; - vz[1] = in[6]; - vz[2] = in[10]; - t [0] = in[3]; - t [1] = in[7]; - t [2] = in[11]; -} - -void bonematident_toqcvectors(float vx[3], float vy[3], float vz[3], float t[3]) -{ - vx[0] = 1; - vx[1] = 0; - vx[2] = 0; - vy[0] = -0; - vy[1] = -1; - vy[2] = -0; - vz[0] = 0; - vz[1] = 0; - vz[2] = 1; - t [0] = 0; - t [1] = 0; - t [2] = 0; -} - -//vector(float skel, float bonenum) skel_get_bonerel (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) -static void QCBUILTIN PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - int boneidx = G_FLOAT(OFS_PARM1)-1; - skelobject_t *skelobj = skel_get(prinst, skelidx, 0); - if (!skelobj || skelobj->absolute || (unsigned int)boneidx >= skelobj->numbones) - bonematident_toqcvectors(csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_RETURN)); - else - bonemat_toqcvectors(skelobj->bonematrix+12*boneidx, csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_RETURN)); -} - -//vector(float skel, float bonenum) skel_get_boneabs (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) -static void QCBUILTIN PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - int boneidx = G_FLOAT(OFS_PARM1)-1; - float workingm[12], tempmatrix[3][4]; - int i; - skelobject_t *skelobj = skel_get(prinst, skelidx, 0); - - if (!skelobj || (unsigned int)boneidx >= skelobj->numbones) - bonematident_toqcvectors(csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_RETURN)); - else if (skelobj->absolute) - { - //can just copy it out - bonemat_toqcvectors(skelobj->bonematrix + boneidx*12, csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_RETURN)); - } - else - { - //we need to work out the abs position - - //testme - - //set up an identity matrix - for (i = 0;i < 12;i++) - workingm[i] = 0; - workingm[0] = 1; - workingm[5] = 1; - workingm[10] = 1; - - while(boneidx >= 0) - { - //copy out the previous working matrix, so we don't stomp on it - memcpy(tempmatrix, workingm, sizeof(tempmatrix)); - R_ConcatTransforms((void*)(skelobj->bonematrix + boneidx*12), (void*)tempmatrix, (void*)workingm); - - boneidx = Mod_GetBoneParent(skelobj->model, boneidx+1)-1; - } - bonemat_toqcvectors(workingm, csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_RETURN)); - } -} - -//void(float skel, float bonenum, vector org) skel_set_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) -static void QCBUILTIN PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - unsigned int boneidx = G_FLOAT(OFS_PARM1)-1; - float *matrix[3]; - skelobject_t *skelobj; - float *bone; - - if (*prinst->callargc > 5) - { - matrix[0] = G_VECTOR(OFS_PARM3); - matrix[1] = G_VECTOR(OFS_PARM4); - matrix[2] = G_VECTOR(OFS_PARM5); - } - else - { - matrix[0] = csqcg.forward; - matrix[1] = csqcg.right; - matrix[2] = csqcg.up; - } - - skelobj = skel_get(prinst, skelidx, 0); - if (!skelobj || boneidx >= skelobj->numbones) - return; - - bone = skelobj->bonematrix+12*boneidx; - bonemat_fromqcvectors(skelobj->bonematrix+12*boneidx, matrix[0], matrix[1], matrix[2], G_VECTOR(OFS_PARM2)); -} - -//void(float skel, float bonenum, vector org [, vector fwd, vector right, vector up]) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) -static void QCBUILTIN PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - int boneidx = G_FLOAT(OFS_PARM1)-1; - float temp[3][4]; - float mult[3][4]; - skelobject_t *skelobj; - if (*prinst->callargc > 5) - bonemat_fromqcvectors((float*)mult, G_VECTOR(OFS_PARM3), G_VECTOR(OFS_PARM4), G_VECTOR(OFS_PARM5), G_VECTOR(OFS_PARM2)); - else - bonemat_fromqcvectors((float*)mult, csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_PARM2)); - - skelobj = skel_get(prinst, skelidx, 0); - if (!skelobj || boneidx >= skelobj->numbones) - return; -//testme - Vector4Copy(skelobj->bonematrix+12*boneidx+0, temp[0]); - Vector4Copy(skelobj->bonematrix+12*boneidx+4, temp[1]); - Vector4Copy(skelobj->bonematrix+12*boneidx+8, temp[2]); - R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*boneidx)); -} - -//void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) -static void QCBUILTIN PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - unsigned int startbone = G_FLOAT(OFS_PARM1)-1; - unsigned int endbone = G_FLOAT(OFS_PARM2)-1; - float temp[3][4]; - float mult[3][4]; - skelobject_t *skelobj; - if (*prinst->callargc > 6) - bonemat_fromqcvectors((float*)mult, G_VECTOR(OFS_PARM4), G_VECTOR(OFS_PARM5), G_VECTOR(OFS_PARM6), G_VECTOR(OFS_PARM3)); - else - bonemat_fromqcvectors((float*)mult, csqcg.forward, csqcg.right, csqcg.up, G_VECTOR(OFS_PARM3)); - - skelobj = skel_get(prinst, skelidx, 0); - if (!skelobj) - return; - - if (startbone == -1) - startbone = 0; -//testme - while(startbone < endbone && startbone < skelobj->numbones) - { - Vector4Copy(skelobj->bonematrix+12*startbone+0, temp[0]); - Vector4Copy(skelobj->bonematrix+12*startbone+4, temp[1]); - Vector4Copy(skelobj->bonematrix+12*startbone+8, temp[2]); - R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*startbone)); - } -} - -//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS) -static void QCBUILTIN PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skeldst = G_FLOAT(OFS_PARM0); - int skelsrc = G_FLOAT(OFS_PARM1); - int startbone = G_FLOAT(OFS_PARM2)-1; - int endbone = G_FLOAT(OFS_PARM3)-1; - - skelobject_t *skelobjdst; - skelobject_t *skelobjsrc; - - skelobjdst = skel_get(prinst, skeldst, 0); - skelobjsrc = skel_get(prinst, skelsrc, 0); - if (!skelobjdst || !skelobjsrc) - return; - if (skelobjsrc->absolute != skelobjdst->absolute) - return; - - if (startbone == -1) - startbone = 0; -//testme - while(startbone < endbone && startbone < skelobjdst->numbones && startbone < skelobjsrc->numbones) - { - Vector4Copy(skelobjsrc->bonematrix+12*startbone+0, skelobjdst->bonematrix+12*startbone+0); - Vector4Copy(skelobjsrc->bonematrix+12*startbone+4, skelobjdst->bonematrix+12*startbone+4); - Vector4Copy(skelobjsrc->bonematrix+12*startbone+8, skelobjdst->bonematrix+12*startbone+8); - } -} - -//void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS) -static void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_globals) -{ - int skelidx = G_FLOAT(OFS_PARM0); - skelobject_t *skelobj; - - skelobj = skel_get(prinst, skelidx, 0); - if (skelobj) - skelobj->inuse = 2; //2 means don't reuse yet. -} @@ -4079,7 +3602,7 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src //use entnum as a test to see if its new (if the old origin isn't usable) if (ent->xv->entnum) { - if (model->particletrail == P_INVALID || pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, &(le->trailstate))) + if (model->particletrail == P_INVALID || pe->ParticleTrail (ent->v->origin, src->origin, model->particletrail, src->number, &(le->trailstate))) if (model->traildefaultindex >= 0) pe->ParticleTrailIndex(ent->v->origin, src->origin, model->traildefaultindex, 0, &(le->trailstate)); } @@ -4118,7 +3641,7 @@ void CSQC_EntStateToCSQC(unsigned int flags, float lerptime, entity_state_t *src if (model) { - if (!(flags & RSES_NOROTATE) && (model->flags & EF_ROTATE)) + if (!(flags & RSES_NOROTATE) && (model->flags & MF_ROTATE)) { ent->v->angles[0] = 0; ent->v->angles[1] = 100*lerptime; @@ -4445,8 +3968,8 @@ static void QCBUILTIN PF_ReadServerEntityState(progfuncs_t *prinst, struct globa src = &pack->entities[i]; // CL_LinkPacketEntities -#ifndef _MSC_VER -#warning what to do here? +#ifdef warningmsg +#pragma warningmsg("what to do here?") #endif // if (csqcent[src->number]) // continue; //don't add the entity if we have one sent specially via csqc protocols. @@ -5172,6 +4695,11 @@ model_t *CSQC_World_ModelForIndex(world_t *w, int modelindex) { return CSQC_GetModelForIndex(modelindex); } +void CSQC_World_GetFrameState(world_t *w, wedict_t *win, framestate_t *out) +{ + csqcedict_t *in = (csqcedict_t *)win; + cs_getframestate(in, in->xv->renderflags, out); +} void CSQC_Shutdown(void) { @@ -5215,21 +4743,21 @@ qbyte *CSQC_PRLoadFile (const char *path, void *buffer, int bufsize) if (!strcmp(path, "csprogs.dat")) { char newname[MAX_QPATH]; - snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csqcchecksum); + snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csprogs_checksum); - if (csqcchecksum) + if (csprogs_checksum) { file = COM_LoadStackFile(newname, buffer, bufsize); if (file) { if (cls.protocol == CP_NETQUAKE) { - if (QCRC_Block(file, com_filesize) == csqcchecksum) + if (QCRC_Block(file, com_filesize) == csprogs_checksum) return file; } else { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csqcchecksum) //and the user wasn't trying to be cunning. + if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csprogs_checksum) //and the user wasn't trying to be cunning. return file; } } @@ -5238,16 +4766,16 @@ qbyte *CSQC_PRLoadFile (const char *path, void *buffer, int bufsize) 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 (csqcchecksum) + if (csprogs_checksum) { if (cls.protocol == CP_NETQUAKE) { - if (QCRC_Block(file, com_filesize) != csqcchecksum) + if (QCRC_Block(file, com_filesize) != csprogs_checksum) return NULL; } else { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csqcchecksum) + if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csprogs_checksum) return NULL; //not valid } @@ -5270,21 +4798,21 @@ int CSQC_PRFileSize (const char *path) if (!strcmp(path, "csprogs.dat")) { char newname[MAX_QPATH]; - snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csqcchecksum); + snprintf(newname, MAX_QPATH, "csprogsvers/%x.dat", csprogs_checksum); - if (csqcchecksum) + if (csprogs_checksum) { file = COM_LoadTempFile (newname); if (file) { if (cls.protocol == CP_NETQUAKE) { - if (QCRC_Block(file, com_filesize) == csqcchecksum) + if (QCRC_Block(file, com_filesize) == csprogs_checksum) return com_filesize+1; } else { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csqcchecksum) //and the user wasn't trying to be cunning. + if (LittleLong(Com_BlockChecksum(file, com_filesize)) == csprogs_checksum) //and the user wasn't trying to be cunning. return com_filesize+1; } } @@ -5293,16 +4821,16 @@ int CSQC_PRFileSize (const char *path) 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 (csqcchecksum) + if (csprogs_checksum) { if (cls.protocol == CP_NETQUAKE) { - if (QCRC_Block(file, com_filesize) != csqcchecksum) + if (QCRC_Block(file, com_filesize) != csprogs_checksum) return -1; //not valid } else { - if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csqcchecksum) + if (LittleLong(Com_BlockChecksum(file, com_filesize)) != csprogs_checksum) return -1; //not valid } } @@ -5329,9 +4857,15 @@ qboolean CSQC_Init (unsigned int checksum) int i; string_t *str; csqcedict_t *worldent; - csqcchecksum = checksum; + qboolean loaded; + csprogs_checksum = checksum; csqc_usinglistener = false; + csqc_singlecheats = false; +#ifndef CLIENTONLY + if ((sv.state == ss_active && sv.allocated_client_slots == 1) || atoi(Info_ValueForKey(cl.serverinfo, "*cheats"))) + csqc_singlecheats = true; +#endif //its already running... if (csqcprogs) @@ -5354,7 +4888,7 @@ qboolean CSQC_Init (unsigned int checksum) } csqc_deprecated_warned = false; - skel_reset(); + skel_reset(csqcprogs); memset(cl.model_csqcname, 0, sizeof(cl.model_csqcname)); memset(cl.model_csqcprecache, 0, sizeof(cl.model_csqcprecache)); @@ -5393,6 +4927,7 @@ qboolean CSQC_Init (unsigned int checksum) csqcprogparms.sv_num_edicts = &csqc_world.num_edicts; csqcprogparms.useeditor = QCEditor;//void (*useeditor) (char *filename, int line, int nump, char **parms); + csqcprogparms.user = &csqc_world; csqctime = Sys_DoubleTime(); if (!csqcprogs) @@ -5406,26 +4941,31 @@ qboolean CSQC_Init (unsigned int checksum) csqc_world.worldmodel = cl.worldmodel; csqc_world.Event_Touch = CSQC_Event_Touch; csqc_world.Event_Think = CSQC_Event_Think; - csqc_world.GetCModel = CSQC_World_ModelForIndex; + csqc_world.Get_CModel = CSQC_World_ModelForIndex; + csqc_world.Get_FrameState = CSQC_World_GetFrameState; World_ClearWorld(&csqc_world); CSQC_InitFields(); //let the qclib know the field order that the engine needs. - csqc_isdarkplaces = false; - if (PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0) < 0) //no per-progs builtins. + if (setjmp(csqc_abort)) { - if (PR_LoadProgs(csqcprogs, "csprogs.dat", 52195, NULL, 0) < 0) //no per-progs builtins. - { - if (PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0) < 0) //no per-progs builtins. - { - CSQC_Shutdown(); - //failed to load or something - return false; - } - } - else - csqc_isdarkplaces = true; + CSQC_Shutdown(); + return false; + } - Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n"); + csqc_isdarkplaces = false; + if (PR_LoadProgs(csqcprogs, "csprogs.dat", 22390, NULL, 0) >= 0) + loaded = true; + else + { + if (PR_LoadProgs(csqcprogs, "csprogs.dat", 52195, NULL, 0) >= 0) + loaded = true; + else if (PR_LoadProgs(csqcprogs, "csprogs.dat", 0, NULL, 0) >= 0) + loaded = true; + else + loaded = false; + + if (loaded) + Con_Printf(CON_WARNING "Running outdated or unknown csprogs.dat version\n"); } if (setjmp(csqc_abort)) { @@ -5433,6 +4973,18 @@ qboolean CSQC_Init (unsigned int checksum) return false; } + if (csqc_singlecheats) + { + if (PR_LoadProgs(csqcprogs, "csaddon.dat", 0, NULL, 0) >= 0) + loaded = true; + } + + if (!loaded) + { + CSQC_Shutdown(); + return false; + } + PR_AutoCvarSetup(csqcprogs); PF_InitTempStrings(csqcprogs); @@ -5678,7 +5230,7 @@ void CSQC_RegisterCvarsAndThings(void) Cvar_Register(&cl_csqcdebug, CSQCPROGSGROUP); Cvar_Register(&cl_nocsqc, CSQCPROGSGROUP); Cvar_Register(&pr_csqc_coreonerror, CSQCPROGSGROUP); - Cvar_Register(&dpcompat_corruptglobals, CSQCPROGSGROUP); + Cvar_Register(&dpcompat_corruptglobals, "Darkplaces compatibility"); } void CSQC_CvarChanged(cvar_t *var) @@ -5724,12 +5276,15 @@ qboolean CSQC_DrawView(void) World_ODE_Frame(&csqc_world, ft, 800); - //World_Physics_Frame(&csqc_world); + World_Physics_Frame(&csqc_world); } #else csqc_world.physicstime = cl.servertime; #endif + if (csqcg.frametime) + *csqcg.frametime = host_frametime; + DropPunchAngle (0); if (cl.worldmodel) R_LessenStains(); @@ -5841,8 +5396,8 @@ static void CSQC_GameCommand_f(void) PR_ExecuteProgram (csqcprogs, csqcg.gamecommand); } -#ifdef _MSC_VER -#pragma message("do we really need the firstbyte parameter here?") +#ifdef warningmsg +#pragma warningmsg("do we really need the firstbyte parameter here?") #endif qboolean CSQC_ParseTempEntity(unsigned char firstbyte) { diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 909cdd46..ebe9ceda 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -1948,8 +1948,8 @@ qboolean MP_Init (void) if (mp_time) *mp_time = Sys_DoubleTime(); -#ifdef _MSC_VER -#pragma message("disabled until csqc gets forked or some such") +#ifdef warningmsg +#pragma warningmsg("disabled until csqc gets forked or some such") #endif //mp_globs.drawfont = (float*)PR_FindGlobal(menuprogs, "drawfont", 0, NULL); //mp_globs.drawfontscale = (float*)PR_FindGlobal(menuprogs, "drawfontscale", 0, NULL); diff --git a/engine/client/pr_skelobj.c b/engine/client/pr_skelobj.c new file mode 100644 index 00000000..bcfbeb48 --- /dev/null +++ b/engine/client/pr_skelobj.c @@ -0,0 +1,671 @@ +/* +Copyright (C) 2011 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. + +*/ +/* +this file deals with qc builtins to apply custom skeletal blending (skeletal objects extension), as well as the logic required to perform realtime ragdoll, if I ever implement that. +*/ + +#include "quakedef.h" +#include "pr_common.h" + +#define MAX_SKEL_OBJECTS 1024 + +/*this is the description of the ragdoll, it is how the doll flops around*/ +typedef struct doll_s +{ + char *name; + struct doll_s *next; + + int numbodies; + struct + { + int joint; + char *name; + } body[32]; +// struct +// { + +// }; +} doll_t; + +enum +{ + BF_ACTIVE, /*used to avoid traces if doll is stationary*/ + BF_INSOLID +}; +typedef struct { + int jointo; /*multiple of 12*/ + int flags; + vec3_t vel; +} body_t; + +/*this is the skeletal object*/ +typedef struct { + int inuse; + + model_t *model; + enum + { + SKOT_HBLEND, + SKOT_ABLEND, + SKOT_ARAG + } type; + + unsigned int numbones; + float *bonematrix; +/* + unsigned int numbodies; + body_t *body; + doll_t *doll; + */ +} skelobject_t; + +static doll_t *dolllist; +static skelobject_t skelobjects[MAX_SKEL_OBJECTS]; +static int numskelobjectsused; + +static qboolean pendingkill; /*states that there is a skel waiting to be killed*/ +#if 0 +doll_t *rag_loaddoll(char *fname) +{ + doll_t *d; + void *fptr = NULL; + int fsize; + + for (d = dolllist; d; d = d->next) + { + if (!strcmp(d->name, fname)) + return d; + } + + fsize = FS_LoadFile(fname, &fptr); + if (!fptr) + return NULL; + FS_FreeFile(fptr); +} + +void skel_integrate(progfuncs_t *prinst, skelobject_t *sko, float ft) +{ + unsigned int p; + trace_t t; + vec3_t npos, opos; + world_t *w = prinst->parms->user; + body_t *b; + float gravity = 800; + + for (p = 0, b = sko->body; p < sko->numbodies; p++, b++) + { + /*handle gravity*/ + b->vel[2] = b->vel[2] - gravity * ft / 2; + + opos[0] = sko->bonematrix[b->jointo + 3 ]; + opos[1] = sko->bonematrix[b->jointo + 7 ]; + opos[2] = sko->bonematrix[b->jointo + 11]; + npos[0] = opos[0] + b->vel[0]*ft; + npos[1] = opos[1] + b->vel[1]*ft; + npos[2] = opos[2] + b->vel[2]*ft; + t = World_Move(w, opos, vec3_origin, vec3_origin, npos, MOVE_NOMONSTERS, w->edicts); + sko->bonematrix[b->jointo + 3 ] = t.endpos[0]; + sko->bonematrix[b->jointo + 7 ] = t.endpos[1]; + sko->bonematrix[b->jointo + 11] = t.endpos[2]; + + /*handle gravity again to compensate for framerate*/ + b->vel[2] = b->vel[2] - gravity * ft / 2; + } + + /*draw points*/ + for (p = 0, b = sko->body; p < sko->numbodies; p++, b++) + { + opos[0] = sko->bonematrix[b->jointo + 3 ]; + opos[1] = sko->bonematrix[b->jointo + 7 ]; + opos[2] = sko->bonematrix[b->jointo + 11]; + P_RunParticleEffectTypeString(opos, b->vel, 1, "ragdolltest"); + } +} +#endif + +/*destroys all skeletons*/ +void skel_reset(progfuncs_t *prinst) +{ + while (numskelobjectsused > 0) + { + numskelobjectsused--; + skelobjects[numskelobjectsused].numbones = 0; + skelobjects[numskelobjectsused].inuse = false; + } +} + +/*deletes any skeletons marked for deletion*/ +void skel_dodelete(progfuncs_t *prinst) +{ + int skelidx; + if (!pendingkill) + return; + + pendingkill = false; + for (skelidx = 0; skelidx < numskelobjectsused; skelidx++) + { + if (skelobjects[skelidx].inuse == 2) + skelobjects[skelidx].inuse = 0; + } + + while (numskelobjectsused && !skelobjects[numskelobjectsused-1].inuse) + numskelobjectsused--; +} + +skelobject_t *skel_get(progfuncs_t *prinst, int skelidx, int bonecount) +{ + if (skelidx == 0) + { + //allocation + if (!bonecount) + return NULL; + + for (skelidx = 0; skelidx < numskelobjectsused; skelidx++) + { + if (!skelobjects[skelidx].inuse && skelobjects[skelidx].numbones == bonecount) + return &skelobjects[skelidx]; + } + + for (skelidx = 0; skelidx <= numskelobjectsused; skelidx++) + { + if (!skelobjects[skelidx].inuse && !skelobjects[skelidx].numbones) + { + skelobjects[skelidx].numbones = bonecount; + /*so bone matrix list can be mmapped some day*/ + skelobjects[skelidx].bonematrix = (float*)PR_AddString(prinst, "", sizeof(float)*12*bonecount); + if (skelidx <= numskelobjectsused) + { + numskelobjectsused = skelidx + 1; + skelobjects[skelidx].model = NULL; + skelobjects[skelidx].inuse = 1; + } + return &skelobjects[skelidx]; + } + } + + return NULL; + } + else + { + skelidx--; + if ((unsigned int)skelidx >= numskelobjectsused) + return NULL; + if (skelobjects[skelidx].inuse != 1) + return NULL; + if (bonecount && skelobjects[skelidx].numbones != bonecount) + return NULL; + return &skelobjects[skelidx]; + } +} + +void skel_lookup(progfuncs_t *prinst, int skelidx, framestate_t *out) +{ + skelobject_t *sko = skel_get(prinst, skelidx, 0); + if (sko && sko->inuse) + { + out->bonecount = sko->numbones; + out->bonestate = sko->bonematrix; + } +} + +//float(float modelindex) skel_create (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_create (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + + int numbones; + skelobject_t *skelobj; + model_t *model; + int midx; + int type; + char *afname; + + midx = G_FLOAT(OFS_PARM0); + + if (*prinst->callargc > 1) + afname = PR_GetStringOfs(prinst, OFS_PARM1); + else + afname = ""; + + //default to failure + G_FLOAT(OFS_RETURN) = 0; + + model = w->Get_CModel(w, midx); + if (!model) + return; //no model set, can't get a skeleton + + type = SKOT_HBLEND; + numbones = Mod_GetNumBones(model, type != SKOT_HBLEND); + if (!numbones) + { +// isabs = true; +// numbones = Mod_GetNumBones(model, isabs); +// if (!numbones) + return; //this isn't a skeletal model. + } + + skelobj = skel_get(prinst, 0, numbones); + if (!skelobj) + return; //couldn't get one, ran out of memory or something? + + skelobj->model = model; + skelobj->type = type; + + G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; +} + +//float(float skel, entity ent, float modelindex, float retainfrac, float firstbone, float lastbone) skel_build (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_build(progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + wedict_t *ent = (wedict_t*)G_EDICT(prinst, OFS_PARM1); + int midx = G_FLOAT(OFS_PARM2); + float retainfrac = G_FLOAT(OFS_PARM3); + int firstbone = G_FLOAT(OFS_PARM4)-1; + int lastbone = G_FLOAT(OFS_PARM5)-1; + float addition = 1?G_FLOAT(OFS_PARM6):1-retainfrac; + + int i, j; + int numbones; + framestate_t fstate; + skelobject_t *skelobj; + model_t *model; + + //default to failure + G_FLOAT(OFS_RETURN) = 0; + + model = w->Get_CModel(w, midx); + if (!model) + return; //invalid model, can't get a skeleton + + w->Get_FrameState(w, ent, &fstate); + + //heh... don't copy. + fstate.bonecount = 0; + fstate.bonestate = NULL; + + numbones = Mod_GetNumBones(model, false); + if (!numbones) + { + return; //this isn't a skeletal model. + } + + skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj) + return; //couldn't get one, ran out of memory or something? + + if (lastbone < 0) + lastbone = numbones; + if (lastbone > numbones) + lastbone = numbones; + if (firstbone < 0) + firstbone = 0; + + if (retainfrac == 0) + { + /*replace everything*/ + if (addition == 1) + Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, skelobj->bonematrix); + else + { + //scale new + float relationsbuf[MAX_BONES*12]; + Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, relationsbuf); + for (i = firstbone; i < lastbone; i++) + { + for (j = 0; j < 12; j++) + skelobj->bonematrix[i*12+j] = addition*relationsbuf[i*12+j]; + } + } + } + else + { + if (retainfrac != 1) + { + //rescale the existing bones + for (i = firstbone; i < lastbone; i++) + { + for (j = 0; j < 12; j++) + skelobj->bonematrix[i*12+j] *= retainfrac; + } + } + if (addition == 1) + { + //just add + float relationsbuf[MAX_BONES*12]; + Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, relationsbuf); + for (i = firstbone; i < lastbone; i++) + { + for (j = 0; j < 12; j++) + skelobj->bonematrix[i*12+j] += relationsbuf[i*12+j]; + } + } + else if (addition) + { + //add+scale + float relationsbuf[MAX_BONES*12]; + Mod_GetBoneRelations(model, firstbone, lastbone, &fstate, relationsbuf); + for (i = firstbone; i < lastbone; i++) + { + for (j = 0; j < 12; j++) + skelobj->bonematrix[i*12+j] += addition*relationsbuf[i*12+j]; + } + } + } + + G_FLOAT(OFS_RETURN) = (skelobj - skelobjects) + 1; +} + +//float(float skel) skel_get_numbones (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_get_numbones (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skelidx = G_FLOAT(OFS_PARM0); + skelobject_t *skelobj; + + skelobj = skel_get(prinst, skelidx, 0); + + if (!skelobj) + G_FLOAT(OFS_RETURN) = 0; + else + G_FLOAT(OFS_RETURN) = skelobj->numbones; +} + +//string(float skel, float bonenum) skel_get_bonename (FTE_CSQC_SKELETONOBJECTS) (returns tempstring) +void QCBUILTIN PF_skel_get_bonename (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skelidx = G_FLOAT(OFS_PARM0); + int boneidx = G_FLOAT(OFS_PARM1); + skelobject_t *skelobj; + + skelobj = skel_get(prinst, skelidx, 0); + + if (!skelobj) + G_INT(OFS_RETURN) = 0; + else + { + RETURN_TSTRING(Mod_GetBoneName(skelobj->model, boneidx)); + } +} + +//float(float skel, float bonenum) skel_get_boneparent (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_get_boneparent (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skelidx = G_FLOAT(OFS_PARM0); + int boneidx = G_FLOAT(OFS_PARM1); + skelobject_t *skelobj; + + skelobj = skel_get(prinst, skelidx, 0); + + if (!skelobj) + G_FLOAT(OFS_RETURN) = 0; + else + G_FLOAT(OFS_RETURN) = Mod_GetBoneParent(skelobj->model, boneidx); +} + +//float(float skel, string tagname) skel_find_bone (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_find_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skelidx = G_FLOAT(OFS_PARM0); + char *bname = PR_GetStringOfs(prinst, OFS_PARM1); + skelobject_t *skelobj; + + skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj) + G_FLOAT(OFS_RETURN) = 0; + else + G_FLOAT(OFS_RETURN) = Mod_TagNumForName(skelobj->model, bname); +} + +static void bonemat_fromqcvectors(float *out, const float vx[3], const float vy[3], const float vz[3], const float t[3]) +{ + out[0] = vx[0]; + out[1] = -vy[0]; + out[2] = vz[0]; + out[3] = t[0]; + out[4] = vx[1]; + out[5] = -vy[1]; + out[6] = vz[1]; + out[7] = t[1]; + out[8] = vx[2]; + out[9] = -vy[2]; + out[10] = vz[2]; + out[11] = t[2]; +} +static void bonemat_toqcvectors(const float *in, float vx[3], float vy[3], float vz[3], float t[3]) +{ + vx[0] = in[0]; + vx[1] = in[4]; + vx[2] = in[8]; + vy[0] = -in[1]; + vy[1] = -in[5]; + vy[2] = -in[9]; + vz[0] = in[2]; + vz[1] = in[6]; + vz[2] = in[10]; + t [0] = in[3]; + t [1] = in[7]; + t [2] = in[11]; +} + +static void bonematident_toqcvectors(float vx[3], float vy[3], float vz[3], float t[3]) +{ + vx[0] = 1; + vx[1] = 0; + vx[2] = 0; + vy[0] = -0; + vy[1] = -1; + vy[2] = -0; + vz[0] = 0; + vz[1] = 0; + vz[2] = 1; + t [0] = 0; + t [1] = 0; + t [2] = 0; +} + +//vector(float skel, float bonenum) skel_get_bonerel (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) +void QCBUILTIN PF_skel_get_bonerel (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + int boneidx = G_FLOAT(OFS_PARM1)-1; + skelobject_t *skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj || (unsigned int)boneidx >= skelobj->numbones) + bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); + else if (skelobj->type!=SKOT_HBLEND) + { + //FIXME + bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); + } + else + bonemat_toqcvectors(skelobj->bonematrix+12*boneidx, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); +} + +//vector(float skel, float bonenum) skel_get_boneabs (FTE_CSQC_SKELETONOBJECTS) (sets v_forward etc) +void QCBUILTIN PF_skel_get_boneabs (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + int boneidx = G_FLOAT(OFS_PARM1)-1; + float workingm[12], tempmatrix[3][4]; + int i; + skelobject_t *skelobj = skel_get(prinst, skelidx, 0); + + if (!skelobj || (unsigned int)boneidx >= skelobj->numbones) + bonematident_toqcvectors(w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); + else if (skelobj->type != SKOT_HBLEND) + { + //can just copy it out + bonemat_toqcvectors(skelobj->bonematrix + boneidx*12, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); + } + else + { + //we need to work out the abs position + + //testme + + //set up an identity matrix + for (i = 0;i < 12;i++) + workingm[i] = 0; + workingm[0] = 1; + workingm[5] = 1; + workingm[10] = 1; + + while(boneidx >= 0) + { + //copy out the previous working matrix, so we don't stomp on it + memcpy(tempmatrix, workingm, sizeof(tempmatrix)); + R_ConcatTransforms((void*)(skelobj->bonematrix + boneidx*12), (void*)tempmatrix, (void*)workingm); + + boneidx = Mod_GetBoneParent(skelobj->model, boneidx+1)-1; + } + bonemat_toqcvectors(workingm, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_RETURN)); + } +} + +//void(float skel, float bonenum, vector org) skel_set_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +void QCBUILTIN PF_skel_set_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + unsigned int boneidx = G_FLOAT(OFS_PARM1)-1; + float *matrix[3]; + skelobject_t *skelobj; + float *bone; + + if (*prinst->callargc > 5) + { + matrix[0] = G_VECTOR(OFS_PARM3); + matrix[1] = G_VECTOR(OFS_PARM4); + matrix[2] = G_VECTOR(OFS_PARM5); + } + else + { + matrix[0] = w->g.v_forward; + matrix[1] = w->g.v_right; + matrix[2] = w->g.v_up; + } + + skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj || boneidx >= skelobj->numbones) + return; + + bone = skelobj->bonematrix+12*boneidx; + bonemat_fromqcvectors(skelobj->bonematrix+12*boneidx, matrix[0], matrix[1], matrix[2], G_VECTOR(OFS_PARM2)); +} + +//void(float skel, float bonenum, vector org [, vector fwd, vector right, vector up]) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +void QCBUILTIN PF_skel_mul_bone (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + int boneidx = G_FLOAT(OFS_PARM1)-1; + float temp[3][4]; + float mult[3][4]; + skelobject_t *skelobj; + if (*prinst->callargc > 5) + bonemat_fromqcvectors((float*)mult, G_VECTOR(OFS_PARM3), G_VECTOR(OFS_PARM4), G_VECTOR(OFS_PARM5), G_VECTOR(OFS_PARM2)); + else + bonemat_fromqcvectors((float*)mult, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_PARM2)); + + skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj || boneidx >= skelobj->numbones) + return; +//testme + Vector4Copy(skelobj->bonematrix+12*boneidx+0, temp[0]); + Vector4Copy(skelobj->bonematrix+12*boneidx+4, temp[1]); + Vector4Copy(skelobj->bonematrix+12*boneidx+8, temp[2]); + R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*boneidx)); +} + +//void(float skel, float startbone, float endbone, vector org) skel_mul_bone (FTE_CSQC_SKELETONOBJECTS) (reads v_forward etc) +void QCBUILTIN PF_skel_mul_bones (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + world_t *w = prinst->parms->user; + int skelidx = G_FLOAT(OFS_PARM0); + unsigned int startbone = G_FLOAT(OFS_PARM1)-1; + unsigned int endbone = G_FLOAT(OFS_PARM2)-1; + float temp[3][4]; + float mult[3][4]; + skelobject_t *skelobj; + if (*prinst->callargc > 6) + bonemat_fromqcvectors((float*)mult, G_VECTOR(OFS_PARM4), G_VECTOR(OFS_PARM5), G_VECTOR(OFS_PARM6), G_VECTOR(OFS_PARM3)); + else + bonemat_fromqcvectors((float*)mult, w->g.v_forward, w->g.v_right, w->g.v_up, G_VECTOR(OFS_PARM3)); + + skelobj = skel_get(prinst, skelidx, 0); + if (!skelobj) + return; + + if (startbone == -1) + startbone = 0; +//testme + while(startbone < endbone && startbone < skelobj->numbones) + { + Vector4Copy(skelobj->bonematrix+12*startbone+0, temp[0]); + Vector4Copy(skelobj->bonematrix+12*startbone+4, temp[1]); + Vector4Copy(skelobj->bonematrix+12*startbone+8, temp[2]); + R_ConcatTransforms(mult, temp, (float(*)[4])(skelobj->bonematrix+12*startbone)); + } +} + +//void(float skeldst, float skelsrc, float startbone, float entbone) skel_copybones (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_copybones (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skeldst = G_FLOAT(OFS_PARM0); + int skelsrc = G_FLOAT(OFS_PARM1); + int startbone = G_FLOAT(OFS_PARM2)-1; + int endbone = G_FLOAT(OFS_PARM3)-1; + + skelobject_t *skelobjdst; + skelobject_t *skelobjsrc; + + skelobjdst = skel_get(prinst, skeldst, 0); + skelobjsrc = skel_get(prinst, skelsrc, 0); + if (!skelobjdst || !skelobjsrc) + return; + if (skelobjsrc->type != skelobjdst->type) + return; + + if (startbone == -1) + startbone = 0; +//testme + while(startbone < endbone && startbone < skelobjdst->numbones && startbone < skelobjsrc->numbones) + { + Vector4Copy(skelobjsrc->bonematrix+12*startbone+0, skelobjdst->bonematrix+12*startbone+0); + Vector4Copy(skelobjsrc->bonematrix+12*startbone+4, skelobjdst->bonematrix+12*startbone+4); + Vector4Copy(skelobjsrc->bonematrix+12*startbone+8, skelobjdst->bonematrix+12*startbone+8); + } +} + +//void(float skel) skel_delete (FTE_CSQC_SKELETONOBJECTS) +void QCBUILTIN PF_skel_delete (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + int skelidx = G_FLOAT(OFS_PARM0); + skelobject_t *skelobj; + + skelobj = skel_get(prinst, skelidx, 0); + if (skelobj) + { + skelobj->inuse = 2; //2 means don't reuse yet. + pendingkill = true; + } +} diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index 154d536e..fcaaf16d 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -24,6 +24,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "bothdefs.h" //first thing included by ALL files. +//for msvc #pragma message lines +#if defined(_MSC_VER) +#define MSVC_LINE __FILE__"("STRINGIFY(__LINE__)"):" +#define warningmsg(s) message(MSVC_LINE s) +#elif __GNUC__ >=4 +#define warningmsg(s) message(s) +#endif + #ifdef MSVCDISABLEWARNINGS //#pragma warning( disable : 4244 4127 4201 4214 4514 4305 4115 4018) /*#pragma warning( disable : 4244) //conversion from const double to float diff --git a/engine/client/r_2d.c b/engine/client/r_2d.c index 239e04ba..9a1cc7a9 100644 --- a/engine/client/r_2d.c +++ b/engine/client/r_2d.c @@ -103,8 +103,8 @@ void R2D_Init(void) Font_Init(); -#ifdef _MSC_VER -#pragma message("Fixme: move conwidth handling into here") +#ifdef warningmsg +#pragma warningmsg("Fixme: move conwidth handling into here") #endif missing_texture = R_LoadTexture8("no_texture", 16, 16, (unsigned char*)r_notexture_mip + r_notexture_mip->offsets[0], IF_NOALPHA|IF_NOGAMMA, 0); @@ -214,7 +214,7 @@ void R2D_Init(void) "}\n" "][\n" "{\n" - "map $whitetexture\n" + "map $whiteimage\n" "blendfunc gl_dst_color gl_zero\n" "rgbgen const $r_menutint\n" "}\n" @@ -407,7 +407,7 @@ void R2D_TransPicTranslate (int x, int y, int width, int height, qbyte *pic, qby if (!TEXVALID(translate_texture)) { - translate_texture = R_AllocNewTexture(64, 64); + translate_texture = R_AllocNewTexture("***translatedpic***", 64, 64); translate_shader = R_RegisterShader("translatedpic", "{\n" "if $nofixed\n" "[\n" @@ -937,7 +937,7 @@ void R2D_Crosshair_Update(void) c = c % (sizeof(crosshair_pixels) / (CS_HEIGHT*sizeof(*crosshair_pixels))); if (!TEXVALID(ch_int_texture)) - ch_int_texture = R_AllocNewTexture(CS_WIDTH, CS_HEIGHT); + ch_int_texture = R_AllocNewTexture("***crosshair***", CS_WIDTH, CS_HEIGHT); shader_crosshair->defaulttextures.base = ch_int_texture; Q_memset(crossdata, 0, sizeof(crossdata)); diff --git a/engine/client/r_part.c b/engine/client/r_part.c index 70bbd5a5..4e199185 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -38,7 +38,7 @@ void R_Rockettrail_Callback(struct cvar_s *var, char *oldvalue) for (i=0 , mod=mod_known ; ineedload) - if (mod->flags & EF_ROCKET) + if (mod->flags & MF_ROCKET) P_DefaultTrail(mod); } } @@ -56,7 +56,7 @@ void R_Grenadetrail_Callback(struct cvar_s *var, char *oldvalue) for (i=0 , mod=mod_known ; ineedload) - if (mod->flags & EF_GRENADE) + if (mod->flags & MF_GRENADE) P_DefaultTrail(mod); } } @@ -215,7 +215,7 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) pe = &pmove.physents[i]; if (pe->nonsolid) continue; - if (pe->model) + if (pe->model && !pe->model->needload) { VectorSubtract(start, pe->origin, ts); VectorSubtract(end, pe->origin, te); @@ -362,86 +362,86 @@ void P_DefaultTrail (model_t *model) if (model->engineflags & MDLF_NODEFAULTTRAIL) return; - if (model->flags & EF_ROCKET) + if (model->flags & MF_ROCKET) P_SelectableTrail(model, &r_rockettrail, P_FindParticleType("TR_ROCKET"), 109, P_FindParticleType("TR_GRENADE"), 6); - else if (model->flags & EF_GRENADE) + else if (model->flags & MF_GRENADE) P_SelectableTrail(model, &r_grenadetrail, P_FindParticleType("TR_GRENADE"), 6, P_FindParticleType("TR_ROCKET"), 109); - else if (model->flags & EF_GIB) + else if (model->flags & MF_GIB) { model->particletrail = P_FindParticleType("TR_BLOOD"); model->traildefaultindex = 70; } - else if (model->flags & EF_TRACER) + else if (model->flags & MF_TRACER) { model->particletrail = P_FindParticleType("TR_WIZSPIKE"); model->traildefaultindex = 60; } - else if (model->flags & EF_ZOMGIB) + else if (model->flags & MF_ZOMGIB) { model->particletrail = P_FindParticleType("TR_SLIGHTBLOOD"); model->traildefaultindex = 70; } - else if (model->flags & EF_TRACER2) + else if (model->flags & MF_TRACER2) { model->particletrail = P_FindParticleType("TR_KNIGHTSPIKE"); model->traildefaultindex = 238; } - else if (model->flags & EF_TRACER3) + else if (model->flags & MF_TRACER3) { model->particletrail = P_FindParticleType("TR_VORESPIKE"); model->traildefaultindex = 154; } - else if (model->flags & EFH2_BLOODSHOT) //these are the hexen2 ones. + else if (model->flags & MFH2_BLOODSHOT) //these are the hexen2 ones. { model->particletrail = P_FindParticleType("tr_bloodshot"); model->traildefaultindex = 136; } - else if (model->flags & EFH2_FIREBALL) + else if (model->flags & MFH2_FIREBALL) { model->particletrail = P_FindParticleType("tr_fireball"); model->traildefaultindex = 424; } - else if (model->flags & EFH2_ACIDBALL) + else if (model->flags & MFH2_ACIDBALL) { model->particletrail = P_FindParticleType("tr_acidball"); model->traildefaultindex = 440; } - else if (model->flags & EFH2_ICE) + else if (model->flags & MFH2_ICE) { model->particletrail = P_FindParticleType("tr_ice"); model->traildefaultindex = 408; } - else if (model->flags & EFH2_SPIT) + else if (model->flags & MFH2_SPIT) { model->particletrail = P_FindParticleType("tr_spit"); model->traildefaultindex = 260; } - else if (model->flags & EFH2_SPELL) + else if (model->flags & MFH2_SPELL) { model->particletrail = P_FindParticleType("tr_spell"); model->traildefaultindex = 260; } - else if (model->flags & EFH2_VORP_MISSILE) + else if (model->flags & MFH2_VORP_MISSILE) { model->particletrail = P_FindParticleType("tr_vorpmissile"); model->traildefaultindex = 302; } - else if (model->flags & EFH2_SET_STAFF) + else if (model->flags & MFH2_SET_STAFF) { model->particletrail = P_FindParticleType("tr_setstaff"); model->traildefaultindex = 424; } - else if (model->flags & EFH2_MAGICMISSILE) + else if (model->flags & MFH2_MAGICMISSILE) { model->particletrail = P_FindParticleType("tr_magicmissile"); model->traildefaultindex = 149; } - else if (model->flags & EFH2_BONESHARD) + else if (model->flags & MFH2_BONESHARD) { model->particletrail = P_FindParticleType("tr_boneshard"); model->traildefaultindex = 384; } - else if (model->flags & EFH2_SCARAB) + else if (model->flags & MFH2_SCARAB) { model->particletrail = P_FindParticleType("tr_scarab"); model->traildefaultindex = 254; diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 9cecb515..79749a1d 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include extern cvar_t r_ambient; -extern cvar_t gl_bump; static vec3_t modelorg; /*set before recursively entering the visible surface finder*/ static qbyte areabits[MAX_Q2MAP_AREAS/8]; @@ -1221,7 +1220,7 @@ dynamic: if ((theRect->h + theRect->t) < (fa->light_t + tmax)) theRect->h = (fa->light_t-theRect->t)+tmax; - if (gl_bump.ival) + if (r_deluxemapping.ival) { lightmap[fa->lightmaptexturenum]->deluxmodified = true; theRect = &lightmap[fa->lightmaptexturenum]->deluxrectchange; @@ -1307,7 +1306,7 @@ dynamic: if ((theRect->h + theRect->t) < (fa->light_t + tmax)) theRect->h = (fa->light_t-theRect->t)+tmax; - if (gl_bump.ival) + if (r_deluxemapping.ival) { lightmap[fa->lightmaptexturenum]->deluxmodified = true; theRect = &lightmap[fa->lightmaptexturenum]->deluxrectchange; @@ -2141,16 +2140,10 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) lightmap[numlightmaps+3] = NULL; lightmap_textures = BZ_Realloc(lightmap_textures, sizeof(*lightmap_textures)*(numlightmaps+4)); - lightmap_textures[numlightmaps+0] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - lightmap_textures[numlightmaps+1] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - lightmap_textures[numlightmaps+2] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - lightmap_textures[numlightmaps+3] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + memset(lightmap_textures+numlightmaps, 0, sizeof(*lightmap_textures)*(4)); deluxmap_textures = BZ_Realloc(deluxmap_textures, sizeof(*deluxmap_textures)*(numlightmaps+4)); - deluxmap_textures[numlightmaps+0] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - deluxmap_textures[numlightmaps+1] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - deluxmap_textures[numlightmaps+2] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - deluxmap_textures[numlightmaps+3] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + memset(deluxmap_textures+numlightmaps, 0, sizeof(*deluxmap_textures)*(4)); numlightmaps+=4; } if (!lightmap[texnum]) @@ -2159,11 +2152,12 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) lightmap[texnum]->meshchain = NULL; lightmap[texnum]->modified = true; lightmap[texnum]->shader = shader; + lightmap[texnum]->external = true; // reset stainmap since it now starts at 255 memset(lightmap[texnum]->stainmaps, 255, sizeof(lightmap[texnum]->stainmaps)); //clear out the deluxmaps incase there is none on the map. - for (j = 0; j < LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3; j+=3) + for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3; j+=3) { lightmap[texnum]->deluxmaps[j+0] = 128; lightmap[texnum]->deluxmaps[j+1] = 128; @@ -2172,7 +2166,11 @@ static int Surf_LM_AllocBlock (int w, int h, int *x, int *y, shader_t *shader) } if (lightmap[texnum]->external) - lightmap_textures[texnum] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + { + TEXASSIGN(lightmap_textures[texnum], R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); + TEXASSIGN(deluxmap_textures[texnum], R_AllocNewTexture("***deluxmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); + lightmap[texnum]->external = false; + } /*not required, but using one lightmap per texture can result in better texture unit switching*/ if (lightmap[texnum]->shader != shader) @@ -2225,16 +2223,10 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) lightmap[numlightmaps+3] = NULL; lightmap_textures = BZ_Realloc(lightmap_textures, sizeof(*lightmap_textures)*(numlightmaps+4)); - lightmap_textures[numlightmaps+0] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - lightmap_textures[numlightmaps+1] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - lightmap_textures[numlightmaps+2] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - lightmap_textures[numlightmaps+3] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + memset(lightmap_textures+numlightmaps, 0, sizeof(*lightmap_textures)*(4)); deluxmap_textures = BZ_Realloc(deluxmap_textures, sizeof(*deluxmap_textures)*(numlightmaps+4)); - deluxmap_textures[numlightmaps+0] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - deluxmap_textures[numlightmaps+1] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - deluxmap_textures[numlightmaps+2] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); - deluxmap_textures[numlightmaps+3] = R_AllocNewTexture(LMBLOCK_WIDTH, LMBLOCK_HEIGHT); + memset(deluxmap_textures+numlightmaps, 0, sizeof(*deluxmap_textures)*(4)); numlightmaps+=4; } for (i = texnum; i >= 0; i--) @@ -2244,7 +2236,8 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) lightmap[i] = BZ_Malloc(sizeof(*lightmap[i])); lightmap[i]->meshchain = NULL; lightmap[i]->modified = true; - for (l=0 ; lexternal = true; + for (l=0 ; lallocated[l] = LMBLOCK_HEIGHT; } @@ -2254,7 +2247,7 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) lightmap[i]->rectchange.h = LMBLOCK_HEIGHT; //clear out the deluxmaps incase there is none on the map. - for (l = 0; l < LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3; l+=3) + for (l = 0; l < LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3; l+=3) { lightmap[i]->deluxmaps[l+0] = 0; lightmap[i]->deluxmaps[l+1] = 0; @@ -2263,26 +2256,32 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) if (cl.worldmodel->lightdata) { + if (lightmap[i]->external) + { + TEXASSIGN(lightmap_textures[i], R_AllocNewTexture("***lightmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); + TEXASSIGN(deluxmap_textures[i], R_AllocNewTexture("***deluxmap***", LMBLOCK_WIDTH, LMBLOCK_HEIGHT)); + lightmap[i]->external = false; + } if (lightmap_bytes == 4) { int j; if (lightmap_bgra) { - for (j = 0; j < LMBLOCK_HEIGHT*LMBLOCK_HEIGHT; j++) + for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT; j++) { - lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[2]; - lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[1]; - lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[0]; + lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[2]; + lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[1]; + lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[0]; lightmap[i]->lightmaps[(j<<2)+3] = 255; } } else { - for (j = 0; j < LMBLOCK_HEIGHT*LMBLOCK_HEIGHT; j++) + for (j = 0; j < LMBLOCK_WIDTH*LMBLOCK_HEIGHT; j++) { - lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[0]; - lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[1]; - lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i))[2]; + lightmap[i]->lightmaps[(j<<2)+0] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[0]; + lightmap[i]->lightmaps[(j<<2)+1] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[1]; + lightmap[i]->lightmaps[(j<<2)+2] = (cl.worldmodel->lightdata+3*(j + LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i))[2]; lightmap[i]->lightmaps[(j<<2)+3] = 255; } } @@ -2290,14 +2289,14 @@ static int Surf_LM_FillBlock (int texnum, int w, int h, int x, int y) else { /*BUG: assumes RGB. if its BGR then wrong colours, but whys that going to happen*/ - memcpy(lightmap[i]->lightmaps, cl.worldmodel->lightdata+3*LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*i, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3); + memcpy(lightmap[i]->lightmaps, cl.worldmodel->lightdata+3*LMBLOCK_WIDTH*LMBLOCK_HEIGHT*i, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3); } } else { char basename[MAX_QPATH]; //maybe someone screwed with my lightmap... - memset(lightmap[i]->lightmaps, 255, LMBLOCK_HEIGHT*LMBLOCK_HEIGHT*3); + memset(lightmap[i]->lightmaps, 255, LMBLOCK_WIDTH*LMBLOCK_HEIGHT*3); COM_StripExtension(cl.worldmodel->name, basename, sizeof(basename)); if (!lightmap[i]->external) @@ -2474,10 +2473,18 @@ void Surf_DeInit(void) if (lightmap_textures) { for (i = 0; i < numlightmaps; i++) + { if (!lightmap[i] || lightmap[i]->external) + { R_DestroyTexture(lightmap_textures[i]); + R_DestroyTexture(deluxmap_textures[i]); + } + } BZ_Free(lightmap_textures); + BZ_Free(deluxmap_textures); } + lightmap_textures=NULL; + deluxmap_textures = NULL; for (i = 0; i < numlightmaps; i++) { @@ -2490,7 +2497,6 @@ void Surf_DeInit(void) if (lightmap) BZ_Free(lightmap); - lightmap_textures=NULL; lightmap=NULL; numlightmaps=0; } diff --git a/engine/client/render.h b/engine/client/render.h index 99d8769f..c61edccb 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -36,7 +36,6 @@ struct texnums_s; struct texture_s; static const texid_t r_nulltex = {0}; -#define TEXVALID(t) ((t).num!=0) #if defined(D3DQUAKE) || defined(ANDROID) @@ -76,6 +75,7 @@ typedef enum { RT_MAX_REF_ENTITY_TYPE } refEntityType_t; +struct dlight_s; typedef struct entity_s { int keynum; // for matching entities in different frames @@ -166,6 +166,9 @@ typedef struct qboolean recurse; /*in a mirror/portal/half way through drawing something else*/ qboolean flipcull; /*reflected/flipped view, requires inverted culling*/ qboolean useperspective; /*not orthographic*/ + + int postprocshader; /*if set, renders to texture then invokes this shader*/ + int postproccube; /*postproc shader wants a cubemap, this is the mask of sides required*/ } refdef_t; extern refdef_t r_refdef; @@ -181,7 +184,7 @@ void BE_GenModelBatches(struct batch_s **batches); void R_GAlias_DrawBatch(struct batch_s *batch); void R_GAlias_GenerateBatches(entity_t *e, struct batch_s **batches); void R_LightArraysByte_BGR(const entity_t *entity, vecV_t *coords, byte_vec4_t *colours, int vertcount, vec3_t *normals); -void R_LightArrays(const entity_t *entity, vecV_t *coords, vec4_t *colours, int vertcount, vec3_t *normals); +void R_LightArrays(const entity_t *entity, vecV_t *coords, vec4_t *colours, int vertcount, vec3_t *normals, float scale); void R_DrawSkyChain (struct batch_s *batch); /*called from the backend, and calls back into it*/ void R_InitSky (struct texnums_s *ret, struct texture_s *mt, qbyte *src); /*generate q1 sky texnums*/ @@ -268,6 +271,7 @@ enum imageflags IF_NOMIPMAP = 1<<2, IF_NOALPHA = 1<<3, IF_NOGAMMA = 1<<4, + IF_NEAREST = 1<<5, IF_SUBDIRONLY = 1<<31 }; @@ -303,9 +307,9 @@ enum uploadfmt /*it seems a little excessive to have to include glquake (and windows headers), just to load some textures/shaders for the backend*/ #ifdef GLQUAKE -texid_t GL_AllocNewTexture(int w, int h); +texid_tf GL_AllocNewTexture(char *name, int w, int h); void GL_UploadFmt(texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); -texid_t GL_LoadTextureFmt (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags); +texid_tf GL_LoadTextureFmt (char *identifier, int width, int height, enum uploadfmt fmt, void *data, unsigned int flags); void GL_DestroyTexture(texid_t tex); #endif #ifdef D3DQUAKE @@ -314,15 +318,16 @@ texid_t D3D9_LoadTexture8Pal24 (char *identifier, int width, int height, qbyte * texid_t D3D9_LoadTexture8Pal32 (char *identifier, int width, int height, qbyte *data, qbyte *palette32, unsigned int flags); texid_t D3D9_LoadCompressed (char *name); texid_t D3D9_FindTexture (char *identifier); -texid_t D3D9_AllocNewTexture(int width, int height); +texid_t D3D9_AllocNewTexture(char *ident, int width, int height); void D3D9_Upload (texid_t tex, char *name, enum uploadfmt fmt, void *data, void *palette, int width, int height, unsigned int flags); void D3D9_DestroyTexture (texid_t tex); +void D3D_Image_Shutdown(void); #endif extern int image_width, image_height; -texid_t R_LoadReplacementTexture(char *name, char *subpath, unsigned int flags); -texid_t R_LoadHiResTexture(char *name, char *subpath, unsigned int flags); -texid_t R_LoadBumpmapTexture(char *name, char *subpath); +texid_tf R_LoadReplacementTexture(char *name, char *subpath, unsigned int flags); +texid_tf R_LoadHiResTexture(char *name, char *subpath, unsigned int flags); +texid_tf R_LoadBumpmapTexture(char *name, char *subpath); extern texid_t particletexture; extern texid_t particlecqtexture; @@ -431,6 +436,7 @@ extern cvar_t r_wateralpha; extern cvar_t r_dynamic; extern cvar_t r_novis; extern cvar_t r_netgraph; +extern cvar_t r_deluxemapping; #ifdef R_XFLIP extern cvar_t r_xflip; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 28c9fa56..46a3395d 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -224,8 +224,6 @@ cvar_t gl_ati_truform_type = CVAR ("gl_ati_truform_type", "1"); cvar_t gl_ati_truform_tesselation = CVAR ("gl_ati_truform_tesselation", "3"); cvar_t gl_blend2d = CVAR ("gl_blend2d", "1"); cvar_t gl_blendsprites = CVAR ("gl_blendsprites", "1"); -cvar_t gl_bump = CVARF ("gl_bump", "0", - CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t r_deluxemapping = CVARAF ("r_deluxemapping", "0", "r_glsl_deluxemapping", CVAR_ARCHIVE | CVAR_RENDERERLATCH); cvar_t gl_compress = CVARF ("gl_compress", "0", @@ -294,6 +292,7 @@ cvar_t vid_triplebuffer = CVARAF ("vid_triplebuffer", "1", "gl_triplebuffer", CVAR_ARCHIVE); cvar_t r_noportals = SCVAR ("r_noportals", "0"); +cvar_t dpcompat_psa_ungroup = SCVAR ("dpcompat_psa_ungroup", "0"); cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE); cvar_t r_shadows = SCVARF ("r_shadows", "0", @@ -355,13 +354,12 @@ void GLRenderer_Init(void) Cvar_Register (&gl_affinemodels, GLRENDEREROPTIONS); Cvar_Register (&gl_nohwblend, GLRENDEREROPTIONS); - Cvar_Register (&r_flashblend, GLRENDEREROPTIONS); - Cvar_Register (&r_flashblendscale, GLRENDEREROPTIONS); Cvar_Register (&gl_nocolors, GLRENDEREROPTIONS); Cvar_Register (&gl_finish, GLRENDEREROPTIONS); Cvar_Register (&gl_lateswap, GLRENDEREROPTIONS); Cvar_Register (&gl_lerpimages, GLRENDEREROPTIONS); + Cvar_Register (&dpcompat_psa_ungroup, GLRENDEREROPTIONS); Cvar_Register (&r_noportals, GLRENDEREROPTIONS); Cvar_Register (&r_noaliasshadows, GLRENDEREROPTIONS); Cvar_Register (&gl_maxshadowlights, GLRENDEREROPTIONS); @@ -381,7 +379,6 @@ void GLRenderer_Init(void) Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES); - Cvar_Register (&gl_bump, GRAPHICALNICETIES); Cvar_Register (&r_deluxemapping, GRAPHICALNICETIES); Cvar_Register (&r_glsl_offsetmapping, GRAPHICALNICETIES); Cvar_Register (&r_glsl_offsetmapping_scale, GRAPHICALNICETIES); @@ -539,6 +536,8 @@ void Renderer_Init(void) Cvar_Register(&r_stainfadetime, GRAPHICALNICETIES); Cvar_Register(&r_stainfadeammount, GRAPHICALNICETIES); Cvar_Register(&r_lightprepass, GRAPHICALNICETIES); + Cvar_Register (&r_flashblend, GLRENDEREROPTIONS); + Cvar_Register (&r_flashblendscale, GLRENDEREROPTIONS); Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); @@ -773,6 +772,7 @@ rendererinfo_t dedicatedrendererinfo = { NULL, NULL, NULL, + NULL, "" }; @@ -2147,7 +2147,7 @@ void R_InitParticleTexture (void) } } - particletexture = R_LoadTexture32("", 8, 8, data, IF_NOMIPMAP|IF_NOPICMIP); + TEXASSIGN(particletexture, R_LoadTexture32("", 8, 8, data, IF_NOMIPMAP|IF_NOPICMIP)); // diff --git a/engine/client/sbar.c b/engine/client/sbar.c index f7faf9a6..31bbce7b 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -22,11 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "quakedef.h" #include "shader.h" -#ifdef _MSC_VER -#pragma message("hipnotic/rogue: Find out") -#endif -#define FINDOUT 1024 - extern cvar_t hud_tracking_show; extern cvar_t com_parseutf8; @@ -539,7 +534,7 @@ void Sbar_ExecuteLayoutString (char *s) color = 0; // green if (cl.q2frame.playerstate.stats[Q2STAT_FLASHES] & 2) - R2D_ScalePic (x, y, FINDOUT, FINDOUT, R2D_SafeCachePic("field_3")); + R2D_ScalePic (x, y, 64, 64, R2D_SafeCachePic("field_3")); SCR_DrawField (x, y, color, width, value); continue; diff --git a/engine/client/skin.c b/engine/client/skin.c index f1d70d6d..9b003f79 100644 --- a/engine/client/skin.c +++ b/engine/client/skin.c @@ -223,9 +223,9 @@ qbyte *Skin_Cache8 (skin_t *skin) if (skin->failedload) return NULL; - skin->tex_base = r_nulltex; - skin->tex_lower = r_nulltex; - skin->tex_upper = r_nulltex; + TEXASSIGN(skin->tex_base, r_nulltex); + TEXASSIGN(skin->tex_lower, r_nulltex); + TEXASSIGN(skin->tex_upper, r_nulltex); out = Cache_Check (&skin->cache); if (out) @@ -279,13 +279,13 @@ qbyte *Skin_Cache8 (skin_t *skin) #if defined(GLQUAKE) || defined(D3DQUAKE) if (qrenderer == QR_OPENGL || qrenderer == QR_DIRECT3D) { - skin->tex_base = R_LoadReplacementTexture(skin->name, "skins", IF_NOALPHA); + TEXASSIGN(skin->tex_base, R_LoadReplacementTexture(skin->name, "skins", IF_NOALPHA)); if (TEXVALID(skin->tex_base)) { Q_snprintfz (name, sizeof(name), "%s_shirt", skin->name); - skin->tex_upper = R_LoadReplacementTexture(name, "skins", 0); + TEXASSIGN(skin->tex_upper, R_LoadReplacementTexture(name, "skins", 0)); Q_snprintfz (name, sizeof(name), "%s_pants", skin->name); - skin->tex_lower = R_LoadReplacementTexture(name, "skins", 0); + TEXASSIGN(skin->tex_lower, R_LoadReplacementTexture(name, "skins", 0)); skin->failedload = true; return NULL; diff --git a/engine/client/snd_mix.c b/engine/client/snd_mix.c index 19460e82..dfa0d032 100644 --- a/engine/client/snd_mix.c +++ b/engine/client/snd_mix.c @@ -167,8 +167,8 @@ void S_PaintChannels(soundcardinfo_t *sc, int endtime) // start = ch->end - scache->length; // samples = end - start; -#ifdef _MSC_VER -#pragma message("pitch fix needed") +#ifdef warningmsg +#pragma warningmsg("pitch fix needed") #endif ch->sfx->decoder->decodemore(ch->sfx, end - (ch->end - scache->length) + 1); diff --git a/engine/client/sys_axfte.cpp b/engine/client/sys_axfte.cpp new file mode 100644 index 00000000..7ca79449 --- /dev/null +++ b/engine/client/sys_axfte.cpp @@ -0,0 +1,850 @@ +#include "quakedef.h" + +#ifdef _WIN32 +#include "sys_plugfte.h" + +#include /*IObjectSafety*/ +#include /*DISPID_SECURITYCTX*/ + +#include /*common dispid values*/ + +const GUID axfte_iid = {0x7d676c9f, 0xfb84, 0x40b6, {0xb3, 0xff, 0xe1, 0x08, 0x31, 0x55, 0x7e, 0xeb}}; +#define axfte_iid_str "7d676c9f-fb84-40b6-b3ff-e10831557eeb" +extern "C" extern HINSTANCE global_hInstance; + +#pragma warning(disable:4584) /*shush now*/ +class axfte : public IUnknown, public IDispatch, public IClassFactory, public IObjectSafety, + public IOleObject, public IOleInPlaceObjectWindowless, public IViewObject, public IPersistPropertyBag2 +{ +private: + unsigned int ref; + IUnknown *site; + struct context *plug; + const struct plugfuncs *funcs; + HWND phwnd; + static const struct browserfuncs axbrowserfuncs; + +public: + axfte() + { + ref = 0; + site = NULL; + phwnd = NULL; + funcs = Plug_GetFuncs(PLUG_APIVER); + plug = funcs->CreateContext(this, &axbrowserfuncs); + } + ~axfte() + { + funcs->DestroyContext(plug); + if (site) + site->Release(); + site = NULL; + } + static void statuschanged(void *arg) + { + axfte *fte = (axfte*)arg; + InvalidateRect(NULL, NULL, FALSE); + } + + /*IUnknown*/ + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject) + { + *ppvObject = NULL; + if (riid == IID_IUnknown) + { + *ppvObject = (IUnknown*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IDispatch) + { + *ppvObject = (IDispatch*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IClassFactory) + { + *ppvObject = (IClassFactory*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IObjectSafety) + { + *ppvObject = (IObjectSafety*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } +/* else if (riid == IID_IPersistPropertyBag2) + { + *ppvObject = (IPersistPropertyBag2*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + }*/ + else if (riid == IID_IOleObject) + { + *ppvObject = (IOleObject*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IOleInPlaceObject) + { + *ppvObject = (IOleInPlaceObject*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IOleInPlaceObjectWindowless) + { + *ppvObject = (IOleInPlaceObjectWindowless*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + + else if (riid == IID_IOleWindow) + { + *ppvObject = (IOleWindow*)(IOleInPlaceObject*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IOleInPlaceObject) + { + *ppvObject = (IOleInPlaceObject*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + else if (riid == IID_IViewObject) + { + *ppvObject = (IViewObject*)this; + ((LPUNKNOWN)*ppvObject)->AddRef(); + return S_OK; + } + + return E_NOINTERFACE; + } + + virtual ULONG STDMETHODCALLTYPE AddRef( void) + { + return ++ref; + } + + virtual ULONG STDMETHODCALLTYPE Release( void) + { + if (ref == 1) + { + delete this; + return 0; + } + return --ref; + } + + + + + + + /*IDispatch*/ + virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount( + /* [out] */ UINT *pctinfo) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetTypeInfo( + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames( + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId) + { + char tmp[1024]; + HRESULT ret = S_OK; + int i; + int prop; + for (i = 0; i < cNames; i++) + { + wcstombs(tmp, rgszNames[i], sizeof(tmp)); + prop = funcs->FindProp(plug, tmp); + if (prop >= 0) + { + rgDispId[i] = prop; + } + else if (!stricmp(tmp, "unselectable")) + rgDispId[i] = 5001; + else + { + rgDispId[i] = DISPID_UNKNOWN; + ret = DISP_E_UNKNOWNNAME; + } + } + return ret; + } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke( + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr) + { + if(wFlags & DISPATCH_METHOD) + { + MessageBox(NULL, "", "invoke method!", 0); + return DISP_E_MEMBERNOTFOUND; + } + else if (wFlags & DISPATCH_PROPERTYGET) + { + VariantClear(pVarResult); + switch(dispIdMember) + { + case DISPID_READYSTATE: + pVarResult->vt = VT_INT; + pVarResult->intVal = READYSTATE_COMPLETE; + break; + case DISPID_ENABLED: + return DISP_E_MEMBERNOTFOUND; + case DISPID_SECURITYCTX: + return DISP_E_MEMBERNOTFOUND; + default: + if (dispIdMember >= 0 && dispIdMember < 1000) + { + const char *tmpa; + wchar_t tmpw[1024]; + if (funcs->GetFloat(plug, dispIdMember, &pVarResult->fltVal)) + pVarResult->vt = VT_R4; + else if (funcs->GetInteger(plug, dispIdMember, &pVarResult->intVal)) + pVarResult->vt = VT_I4; + else if (funcs->GetString(plug, dispIdMember, &tmpa)) + { + mbstowcs(tmpw, tmpa, sizeof(tmpw)/sizeof(tmpw[0])); + funcs->GotString(tmpa); + pVarResult->vt = VT_BSTR; + pVarResult->bstrVal = SysAllocString(tmpw); + } + else + return DISP_E_MEMBERNOTFOUND; + } + else + { + char tmp[1024]; + sprintf(tmp, "DISPATCH_PROPERTYGET dispIdMember=%i", dispIdMember); + OutputDebugStringA(tmp); + return DISP_E_MEMBERNOTFOUND; + } + } + } + else if (wFlags & DISPATCH_PROPERTYPUT) + { + if (dispIdMember >= 0 && dispIdMember < 1000) + { + VARIANT *v = &pDispParams->rgvarg[0]; + switch(v->vt) + { + case VT_R4: + funcs->SetFloat(plug, dispIdMember, v->fltVal); + break; + case VT_R8: + funcs->SetFloat(plug, dispIdMember, v->dblVal); + break; + case VT_INT: + case VT_I4: + funcs->SetInteger(plug, dispIdMember, v->intVal); + break; + case VT_BSTR: + funcs->SetWString(plug, dispIdMember, v->bstrVal); + break; + default: + return DISP_E_TYPEMISMATCH; + } + return S_OK; + } + else + { + char tmp[1024]; + sprintf(tmp, "DISPATCH_PROPERTYPUT dispIdMember=%i", dispIdMember); + OutputDebugStringA(tmp); + return DISP_E_MEMBERNOTFOUND; + } + } + else if (wFlags & DISPATCH_PROPERTYPUTREF) + { + char tmp[1024]; + sprintf(tmp, "DISPATCH_PROPERTYPUTREF dispIdMember=%i", dispIdMember); + OutputDebugStringA(tmp); + return DISP_E_MEMBERNOTFOUND; + } + else + return DISP_E_MEMBERNOTFOUND; + + return S_OK; + } + + + /*IClassFactory*/ + virtual /* [local] */ HRESULT STDMETHODCALLTYPE CreateInstance( + /* [unique][in] */ IUnknown *pUnkOuter, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject) + { + HRESULT res; + + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + axfte *newaxfte = new axfte(); + res = newaxfte->QueryInterface(riid, ppvObject); + if (!*ppvObject) + delete newaxfte; + return res; + } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE LockServer( + /* [in] */ BOOL fLock) + { + return S_OK; + } + + /*IObjectSafety*/ + virtual HRESULT STDMETHODCALLTYPE GetInterfaceSafetyOptions( + /* [in] */ REFIID riid, + /* [out] */ DWORD *pdwSupportedOptions, + /* [out] */ DWORD *pdwEnabledOptions) + { + *pdwSupportedOptions = *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; + return S_OK; + } + virtual HRESULT STDMETHODCALLTYPE SetInterfaceSafetyOptions( + /* [in] */ REFIID riid, + /* [in] */ DWORD dwOptionSetMask, + /* [in] */ DWORD dwEnabledOptions) + { + return S_OK; + } + + /*IOleWindow*/ + virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE GetWindow( + /* [out] */ HWND *phwnd) + { + *phwnd = NULL; + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp( + /* [in] */ BOOL fEnterMode) + { + return E_NOTIMPL; + } + + /*IOleInPlaceObject*/ + virtual HRESULT STDMETHODCALLTYPE InPlaceDeactivate( void) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE UIDeactivate( void) + { + return E_NOTIMPL; + } + + virtual /* [input_sync] */ HRESULT STDMETHODCALLTYPE SetObjectRects( + /* [in] */ LPCRECT lprcPosRect, + /* [in] */ LPCRECT lprcClipRect) + { + if (phwnd) + funcs->ChangeWindow(plug, phwnd, lprcPosRect->left, lprcPosRect->top, lprcPosRect->right - lprcPosRect->left, lprcPosRect->bottom - lprcPosRect->top); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE ReactivateAndUndo( void) + { + return E_NOTIMPL; + } + + /*IOleObject*/ + virtual HRESULT STDMETHODCALLTYPE SetClientSite( + /* [unique][in] */ IOleClientSite *pClientSite) + { + IUnknown *osite = site; + site = pClientSite; + if (site) + site->AddRef(); + + IOleInPlaceSiteWindowless *oipc; + if (site) + if (!FAILED(site->QueryInterface(IID_IOleInPlaceSiteWindowless, (void**)&oipc))) + { + IOleInPlaceFrame *pframe; + IOleInPlaceUIWindow *pdoc; + RECT posrect; + RECT cliprect; + OLEINPLACEFRAMEINFO frameinfo; + memset(&frameinfo, 0, sizeof(frameinfo)); + frameinfo.cb = sizeof(frameinfo); + oipc->GetWindowContext(&pframe, &pdoc, &posrect, &cliprect, &frameinfo); + if (pframe) pframe->Release(); + if (pdoc) pdoc->Release(); + phwnd = frameinfo.hwndFrame; + oipc->Release(); + } + + if (osite) + osite->Release(); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE GetClientSite( + /* [out] */ IOleClientSite **ppClientSite) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE SetHostNames( + /* [in] */ LPCOLESTR szContainerApp, + /* [unique][in] */ LPCOLESTR szContainerObj) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE Close( + /* [in] */ DWORD dwSaveOption) + { + funcs->SetInteger(plug, funcs->FindProp(plug, "running"), 0); + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE SetMoniker( + /* [in] */ DWORD dwWhichMoniker, + /* [unique][in] */ IMoniker *pmk) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetMoniker( + /* [in] */ DWORD dwAssign, + /* [in] */ DWORD dwWhichMoniker, + /* [out] */ IMoniker **ppmk) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE InitFromData( + /* [unique][in] */ IDataObject *pDataObject, + /* [in] */ BOOL fCreation, + /* [in] */ DWORD dwReserved) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetClipboardData( + /* [in] */ DWORD dwReserved, + /* [out] */ IDataObject **ppDataObject) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE DoVerb( + /* [in] */ LONG iVerb, + /* [unique][in] */ LPMSG lpmsg, + /* [unique][in] */ IOleClientSite *pActiveSite, + /* [in] */ LONG lindex, + /* [in] */ HWND hwndParent, + /* [unique][in] */ LPCRECT lprcPosRect) + { + switch(iVerb) + { + case OLEIVERB_INPLACEACTIVATE: + IOleInPlaceSiteWindowless *oipc; + if (!FAILED(pActiveSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void**)&oipc))) + { + IOleInPlaceFrame *pframe; + IOleInPlaceUIWindow *pdoc; + RECT posrect; + RECT cliprect; + OLEINPLACEFRAMEINFO frameinfo; + memset(&frameinfo, 0, sizeof(frameinfo)); + frameinfo.cb = sizeof(frameinfo); + oipc->GetWindowContext(&pframe, &pdoc, &posrect, &cliprect, &frameinfo); + if (pframe) pframe->Release(); + if (pdoc) pdoc->Release(); + + phwnd = frameinfo.hwndFrame; + funcs->ChangeWindow(plug, frameinfo.hwndFrame, lprcPosRect->left, lprcPosRect->top, lprcPosRect->right - lprcPosRect->left, lprcPosRect->bottom - lprcPosRect->top); + oipc->OnInPlaceActivateEx(NULL, 1); + oipc->Release(); + } + break; + } + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE EnumVerbs( + /* [out] */ IEnumOLEVERB **ppEnumOleVerb) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE Update( void) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE IsUpToDate( void) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetUserClassID( + /* [out] */ CLSID *pClsid) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetUserType( + /* [in] */ DWORD dwFormOfType, + /* [out] */ LPOLESTR *pszUserType) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE SetExtent( + /* [in] */ DWORD dwDrawAspect, + /* [in] */ SIZEL *psizel) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetExtent( + /* [in] */ DWORD dwDrawAspect, + /* [out] */ SIZEL *psizel) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE Advise( + /* [unique][in] */ IAdviseSink *pAdvSink, + /* [out] */ DWORD *pdwConnection) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE Unadvise( + /* [in] */ DWORD dwConnection) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE EnumAdvise( + /* [out] */ IEnumSTATDATA **ppenumAdvise) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE GetMiscStatus( + /* [in] */ DWORD dwAspect, + /* [out] */ DWORD *pdwStatus) + { + *pdwStatus = OLEMISC_RECOMPOSEONRESIZE; + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE SetColorScheme( + /* [in] */ LOGPALETTE *pLogpal) + { + return E_NOTIMPL; + } + + /*IViewObject*/ + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Draw( + /* [in] */ DWORD dwDrawAspect, + /* [in] */ LONG lindex, + /* [unique][in] */ void *pvAspect, + /* [unique][in] */ DVTARGETDEVICE *ptd, + /* [in] */ HDC hdcTargetDev, + /* [in] */ HDC hdcDraw, + /* [in] */ LPCRECTL lprcBounds, + /* [unique][in] */ LPCRECTL lprcWBounds, + /* [in] */ BOOL ( STDMETHODCALLTYPE *pfnContinue )( + ULONG_PTR dwContinue), + /* [in] */ ULONG_PTR dwContinue) + { + int width, height; + HBITMAP bmp = (HBITMAP)funcs->GetSplashBack(plug, hdcDraw, &width, &height); + if (bmp) + { + HDC memDC; + RECT irect; + irect.left = lprcBounds->left; + irect.right = lprcBounds->right; + irect.top = lprcBounds->top; + irect.bottom = lprcBounds->bottom; + + memDC = CreateCompatibleDC(hdcDraw); + SelectObject(memDC, bmp); + StretchBlt(hdcDraw, irect.left, irect.top, irect.right-irect.left,irect.bottom-irect.top, memDC, 0, 0, width, height, SRCCOPY); + SelectObject(memDC, NULL); + DeleteDC(memDC); + funcs->ReleaseSplashBack(plug, bmp); + } + + return S_OK; + } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetColorSet( + /* [in] */ DWORD dwDrawAspect, + /* [in] */ LONG lindex, + /* [unique][in] */ void *pvAspect, + /* [unique][in] */ DVTARGETDEVICE *ptd, + /* [in] */ HDC hicTargetDev, + /* [out] */ LOGPALETTE **ppColorSet) + { + return E_NOTIMPL; + } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE Freeze( + /* [in] */ DWORD dwDrawAspect, + /* [in] */ LONG lindex, + /* [unique][in] */ void *pvAspect, + /* [out] */ DWORD *pdwFreeze) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE Unfreeze( + /* [in] */ DWORD dwFreeze) + { + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE SetAdvise( + /* [in] */ DWORD aspects, + /* [in] */ DWORD advf, + /* [unique][in] */ IAdviseSink *pAdvSink) + { + return E_NOTIMPL; + } + + virtual /* [local] */ HRESULT STDMETHODCALLTYPE GetAdvise( + /* [unique][out] */ DWORD *pAspects, + /* [unique][out] */ DWORD *pAdvf, + /* [out] */ IAdviseSink **ppAdvSink) + { + return E_NOTIMPL; + } + + /*IOleInPlaceObjectWindowless*/ + virtual HRESULT STDMETHODCALLTYPE OnWindowMessage( + /* [in] */ UINT msg, + /* [in] */ WPARAM wParam, + /* [in] */ LPARAM lParam, + /* [out] */ LRESULT *plResult) + { + switch(msg) + { + case WM_LBUTTONDOWN: + funcs->SetInteger(plug, funcs->FindProp(plug, "running"), 1); + return S_OK; + default: + return E_NOTIMPL; + } + } + + virtual HRESULT STDMETHODCALLTYPE GetDropTarget( + /* [out] */ IDropTarget **ppDropTarget) + { + return E_NOTIMPL; + } + + /*IPersist*/ + virtual HRESULT STDMETHODCALLTYPE GetClassID( + /* [out] */ CLSID *pClassID) + { + return E_NOTIMPL; + } + + /*IPersistPropertyBag2*/ + virtual HRESULT STDMETHODCALLTYPE InitNew( void) + { + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE Load( + /* [in] */ IPropertyBag2 *pPropBag, + /* [in] */ IErrorLog *pErrLog) + { + PROPBAG2 prop[] = + { + {PROPBAG2_TYPE_DATA, VT_BSTR, 0, 0, L"splash", NULL}, + {PROPBAG2_TYPE_DATA, VT_BSTR, 0, 0, L"game", NULL}, + {PROPBAG2_TYPE_DATA, VT_BSTR, 0, 0, L"dataDownload", NULL} + }; + VARIANT val[sizeof(prop)/sizeof(prop[0])]; + HRESULT res[sizeof(prop)/sizeof(prop[0])]; + memset(val, 0, sizeof(val)); + pPropBag->Read(sizeof(prop)/sizeof(prop[0]), prop, NULL, val, res); + + funcs->SetWString(plug, funcs->FindProp(plug, "splash"), val[0].bstrVal); + funcs->SetWString(plug, funcs->FindProp(plug, "game"), val[1].bstrVal); + funcs->SetWString(plug, funcs->FindProp(plug, "dataDownload"), val[2].bstrVal); + return S_OK; + } + + virtual HRESULT STDMETHODCALLTYPE Save( + /* [in] */ IPropertyBag2 *pPropBag, + /* [in] */ BOOL fClearDirty, + /* [in] */ BOOL fSaveAllProperties) + { + /*we don't actually save anything*/ + return E_NOTIMPL; + } + + virtual HRESULT STDMETHODCALLTYPE IsDirty( void) + { + return E_NOTIMPL; + } +}; + +const struct browserfuncs axfte::axbrowserfuncs = {NULL, axfte::statuschanged}; + + +extern "C" +{ + +HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + *ppv = NULL; + + if (rclsid == axfte_iid) + { + HRESULT res; + axfte *newaxfte = new axfte(); + res = newaxfte->QueryInterface(riid, ppv); + if (!*ppv) + delete newaxfte; + return res; + } + + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllCanUnloadNow(void) +{ + return S_OK; +} + +struct +{ + char *key; + char *value; +} regkeys[] = +{ + {"Software\\Classes\\FTE.FTEPlug\\", "FTEPlug Class"}, + {"Software\\Classes\\FTE.FTEPlug\\CurVer\\", "FTE.FTEPlug.1"}, + {"Software\\Classes\\FTE.FTEPlug.1\\", "FTEPlug Class"}, + {"Software\\Classes\\FTE.FTEPlug.1\\CLSID\\", "{"axfte_iid_str"}"}, + + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\", ""}, + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\InprocHandler32\\", "ole32.dll"}, + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\InprocServer32\\", "***DLLNAME***"}, + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\InprocServer32\\ThreadingModel", "Apartment"}, + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\Programmable\\", ""}, + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\VersionIndependentProgID\\", "FTE.FTEPlug"}, + {"Software\\Classes\\CLSID\\{"axfte_iid_str"}\\ProgID\\", "FTE.FTEPlug.1.0"}, + +#ifdef warningmsg +#pragma warningmsg("Hey, moodles, do you want the plugin to register itself as a firefox plugin at the same time as it registers itself for support in IE?") +#endif + /* + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\Description", ENGINEWEBSITE}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\GeckoVersion", "1.00"}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\Path", "***DLLNAME***"}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\ProductName", FULLENGINENAME}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\Vendor", DISTRIBUTIONLONG}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\Version", "***VERSION***"}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-fteplugin\\Description", "FTE Game Engine Plugin"}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-qtv\\Description", "QuakeTV Stream Information File"}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\MimeTypes\\application/x-qtv\\Suffixes", "qtv"}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\Suffixes\\qtv", ""}, + {"Software\\MozillaPlugins\\@fteqw.com/FTE\\Suffixes\\mvd", ""}, + */ + {NULL} +}; +HRESULT WINAPI DllRegisterServer(void) +{ + char binaryname[1024]; + char tmp[1024]; + GetModuleFileName(global_hInstance, binaryname, sizeof(binaryname)); + + HKEY h; + bool allusers = false; + int i; + char *ls; + + for (i = 0; regkeys[i].key; i++) + { + ls = strrchr(regkeys[i].key, '\\') + 1; + memcpy(tmp, regkeys[i].key, ls - regkeys[i].key); + tmp[ls - regkeys[i].key] = 0; + + if (RegCreateKeyExA(allusers?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, tmp, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &h, NULL)) + continue; + if (!strcmp(regkeys[i].value, "***DLLNAME***")) + RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)binaryname, strlen(binaryname)); + else if (!strcmp(regkeys[i].value, "***VERSION***")) + { + char *ver = version_string(); + RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)ver, strlen(ver)); + } + else + RegSetValueExA(h, ls, 0, REG_SZ, (BYTE*)regkeys[i].value, strlen(regkeys[i].value)); + RegCloseKey(h); + } + + return S_OK; +} + +HRESULT WINAPI DllUnregisterServer(void) +{ + int i; + bool allusers = false; + char *ls; + char tmp[1024]; + HKEY h; + + for (i = 0; regkeys[i].key; i++) + { + } + + /*go backwards*/ + for (i--; i>=0; i--) + { + ls = strrchr(regkeys[i].key, '\\') + 1; + memcpy(tmp, regkeys[i].key, ls - regkeys[i].key); + tmp[ls - regkeys[i].key] = 0; + + if (*ls) + { + h = NULL; + if (!RegOpenKeyEx(allusers?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, tmp, 0, KEY_SET_VALUE, &h)) + { + RegDeleteValue(h, ls); + RegCloseKey(h); + } + } + else + RegDeleteKey(allusers?HKEY_LOCAL_MACHINE:HKEY_CURRENT_USER, tmp); + } + + return S_OK; +} + +}//externC +#endif diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 2d299b07..3df38842 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -490,7 +490,9 @@ void *Sys_GetGameAPI(void *parms) result = getcwd(curpath, sizeof(curpath)); // do something with result? -#warning Search for both gamei386.so and game.so +#ifdef warningmsg +#pragma warningmsg("Search for both gamei386.so and game.so") +#endif Con_DPrintf("Searching for %s but not %s\n", agamename, ggamename); searchpath = 0; diff --git a/engine/client/sys_npfte.c b/engine/client/sys_npfte.c index 8cb9cba0..a11dbff7 100644 --- a/engine/client/sys_npfte.c +++ b/engine/client/sys_npfte.c @@ -66,9 +66,10 @@ qboolean NPFTE_BeginDownload(void *ctx, struct pipetype *ftype, char *url) return NPERR_NO_ERROR==browserfuncs->geturlnotify(ctx, url, NULL, ftype); } -void NPFTE_StatusChanged(struct context *ctx) +void NPFTE_StatusChanged(void *sysctx) { - struct contextpublic *pub = (struct contextpublic*)ctx; + NPP instance = sysctx; + struct contextpublic *pub = instance->pdata; InvalidateRgn(pub->oldwnd, NULL, FALSE); } @@ -263,7 +264,7 @@ NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window) return NPERR_INVALID_INSTANCE_ERROR; //if the window changed - if (Plug_ChangeWindow(ctx, window->window, window->width, window->height)) + if (Plug_ChangeWindow(ctx, window->window, 0, 0, window->width, window->height)) { //we switched window? if (pub->oldwnd && pub->oldproc) @@ -501,7 +502,7 @@ bool npscript_getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) struct npscript *obj = (struct npscript *)npobj; struct context *ctx = obj->ctx; NPUTF8 *pname; - struct pscript_property *prop; + int prop; bool success = false; char *strval; int intval; @@ -510,7 +511,7 @@ bool npscript_getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) Plug_LockPlugin(ctx, true); prop = Plug_FindProp(obj->ctx, pname); - if (prop) + if (prop >= 0) { if (Plug_GetString(ctx, prop, &strval)) { @@ -554,13 +555,13 @@ bool npscript_setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *v struct context *ctx = obj->ctx; NPUTF8 *pname; NPString str; - struct pscript_property *prop; + int prop; bool success = false; pname = browserfuncs->utf8fromidentifier(name); Plug_LockPlugin(ctx, true); prop = Plug_FindProp(obj->ctx, pname); - if (prop) + if (prop >= 0) { success = true; if (NPVARIANT_IS_STRING(*value)) diff --git a/engine/client/sys_npqtv.c b/engine/client/sys_npqtv.c deleted file mode 100644 index 9569c50c..00000000 --- a/engine/client/sys_npqtv.c +++ /dev/null @@ -1,697 +0,0 @@ -#include "quakedef.h" -#include "winquake.h" -#define bool int //we ain't c++ (grr microsoft stdbool.h gief!) - -#ifdef _WIN32 -#ifndef _WINDOWS -#define _WINDOWS //stupid GCC -#endif -#endif - -#include "npapi/npupp.h" -#include "sys_plugfte.h" - -#define Q_STRINGZ_TO_NPVARIANT(_val, _v) \ -NP_BEGIN_MACRO \ - NPString str = { _val, strlen(_val) }; \ - (_v).type = NPVariantType_String; \ - (_v).value.stringValue = str; \ -NP_END_MACRO -#undef STRINGZ_TO_NPVARIANT -#define STRINGZ_TO_NPVARIANT Q_STRINGZ_TO_NPVARIANT - -#define FIREFOX_BUGS_OVER_25MB - -//TODO: player name input (before allowing them to join) -//TODO: fix active gl context (per thread, and we hijacked the browser's thread) - - -NPNetscapeFuncs *browserfuncs; - - - - -#ifdef _WIN32 -#ifndef GetWindowLongPtr -#define GetWindowLongPtr GetWindowLong -#endif -#ifndef SetWindowLongPtr -#define SetWindowLongPtr SetWindowLong -#define LONG_PTR LONG -#endif -#endif - - - - - -qboolean NPFTE_BeginDownload(void *ctx, struct pipetype *ftype, char *url) -{ - return NPERR_NO_ERROR==browserfuncs->geturlnotify(ctx, url, NULL, ftype); -} - - -#ifdef _WIN32 -void DrawWndBack(struct context *ctx, HWND hWnd, HDC hdc, PAINTSTRUCT *p) -{ - int width, height; - HBITMAP bmp = Plug_GetSplashBack(ctx, hdc, &width, &height); - if (bmp) - { - HDC memDC; - - memDC = CreateCompatibleDC(hdc); - SelectObject(memDC, bmp); - StretchBlt(hdc, p->rcPaint.left, p->rcPaint.top, p->rcPaint.right-p->rcPaint.left,p->rcPaint.bottom-p->rcPaint.top, memDC, 0, 0, width, height, SRCCOPY); - SelectObject(memDC, NULL); - DeleteDC(memDC); - Plug_ReleaseSplashBack(ctx, bmp); - } - else - PatBlt(hdc, p->rcPaint.left, p->rcPaint.top, p->rcPaint.right-p->rcPaint.left,p->rcPaint.bottom-p->rcPaint.top,PATCOPY); -} - -LRESULT CALLBACK MyPluginWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - struct context *ctx; - struct contextpublic *pub; - ctx = (struct context *)GetWindowLongPtr(hWnd, GWL_USERDATA); - if (!ctx) - return DefWindowProc(hWnd, msg, wParam, lParam); - pub = (struct contextpublic*)ctx; - - switch(msg) - { - case WM_USER: - /*if the plugin is somewhere in video code, the plugin might depend upon us being able to respond to window messages*/ -/* while(ctx->queuedstreams) - { - struct qstream *strm; - strm = ctx->queuedstreams; - ctx->queuedstreams = strm->next; - - if (!browserfuncs->geturlnotify(ctx->nppinstance, strm->url, NULL, strm->type)) - { - VS_DebugLocation(__FILE__, __LINE__, "Starting Download %s", strm->url); - if (strm->type->wait == WAIT_YES) - ctx->waitingfordatafiles++; - } - free(strm); - } -*/ - return TRUE; - - case WM_PAINT: -/* if (ctx->waitingfordatafiles) - { - HDC hdc; - PAINTSTRUCT paint; - char *s; - unsigned int progress; - unsigned int total; - bool sizeknown = true; - struct qstream *strm; - - progress = 0; - total = 0; - if (Sys_TryLockMutex(ctx->mutex)) //this lock doesn't have to be here - { - for (strm = ctx->activestreams; strm; strm = strm->next) - { - progress += strm->offset; - total += strm->size; - if (!total && progress) - sizeknown = false; - } - Plug_LockPlugin(ctx, false); - } - - hdc = BeginPaint(hWnd, &paint); - DrawWndBack(ctx, hWnd, hdc, &paint); - SetBkMode(hdc, TRANSPARENT); - TextOutA(hdc, 0, 0, "Downloading Data, please wait", 16); - if (!progress && !total) - s = "connecting"; - else if (sizeknown) - s = va("%i bytes (%i%%)", progress, (int)((100.0f*progress)/total)); - else - s = va("%i bytes", progress); - TextOutA(hdc, 0, 32, s, strlen(s)); - EndPaint(hWnd, &paint); - return TRUE; - } - else -*/ { - HDC hdc; - PAINTSTRUCT paint; - char *s; - - hdc = BeginPaint(hWnd, &paint); - DrawWndBack(ctx, hWnd, hdc, &paint); - SetBkMode(hdc, TRANSPARENT); - if (!pub->running) - { - s = "Click to activate"; - TextOutA(hdc, 0, 0, s, strlen(s)); - - if (pub->availver) - { - s = va("Your plugin may be incompatible"); - TextOutA(hdc, 0, 32, s, strlen(s)); - s = va("Version %3.2f was requested, you are using version %3.2f", pub->availver, (float)version_number()); - TextOutA(hdc, 0, 48, s, strlen(s)); - } - } - EndPaint(hWnd, &paint); - return TRUE; - } - break; - - case WM_LBUTTONDOWN: - SetActiveWindow(hWnd); - if (!Plug_StartContext(ctx)) - Plug_StopContext(NULL); - break; - default: - break; - } - - //I would call the previous wndproc... but that crashes firefox - return DefWindowProc(hWnd, msg, wParam, lParam); -} - -#endif - -static const struct browserfuncs npqtv_browserfuncs = -{ - NPFTE_BeginDownload -}; - -NPError NP_LOADDS NPP_New(NPMIMEType pluginType, NPP instance, - uint16 mode, int16 argc, char* argn[], - char* argv[], NPSavedData* saved) -{ - int i; - struct context *ctx; - - if (!instance || instance->pdata) - { - return NPERR_INVALID_INSTANCE_ERROR; - } - if (mode != NP_EMBED && mode != NP_FULL) - { - return NPERR_INVALID_PLUGIN_ERROR; - } - - ctx = Plug_CreateContext(instance, &npqtv_browserfuncs); - instance->pdata = ctx; - if (!ctx) - { - return NPERR_OUT_OF_MEMORY_ERROR; - } - - //parse out the properties - for (i = 0; i < argc; i++) - { - Plug_SetString(ctx, Plug_FindProp(ctx, argn[i]), argv[i]); - } - - return NPERR_NO_ERROR; -} -NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save) -{ - struct context *ctx = instance->pdata; - struct contextpublic *pub = (struct contextpublic *)ctx; - - if (!ctx) - return NPERR_INVALID_INSTANCE_ERROR; - -#ifdef _WIN32 - if (pub->oldwnd) - { - if (pub->oldproc) - SetWindowLongPtr(pub->oldwnd, GWL_WNDPROC, (LONG_PTR)pub->oldproc); - SetWindowLongPtr(pub->oldwnd, GWL_USERDATA, (LONG_PTR)NULL); - } -#endif - - Plug_DestroyContext(ctx); - instance->pdata = NULL; - - return NPERR_NO_ERROR; -} -NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window) -{ - extern cvar_t vid_width; - struct context *ctx = instance->pdata; - struct contextpublic *pub = (struct contextpublic*)ctx; - -#ifdef _WIN32 - HWND oldwindow; - WNDPROC p; - - if (!ctx) - return NPERR_INVALID_INSTANCE_ERROR; - - //if the window changed - if (Plug_ChangeWindow(ctx, window->window, window->width, window->height)) - { - //we switched window? - if (pub->oldwnd && pub->oldproc) - { - SetWindowLongPtr(pub->oldwnd, GWL_WNDPROC, (LONG_PTR)pub->oldproc); - } - pub->oldproc = NULL; - - p = (WNDPROC)GetWindowLongPtr(window->window, GWL_WNDPROC); - if (p != MyPluginWndProc) - pub->oldproc = p; - pub->oldwnd = window->window; - - SetWindowLongPtr(window->window, GWL_WNDPROC, (LONG_PTR)MyPluginWndProc); - SetWindowLongPtr(window->window, GWL_USERDATA, (LONG_PTR)ctx); - } - - InvalidateRgn(window->window, NULL, FALSE); -#endif - return NPERR_NO_ERROR; -} - -NPError NP_LOADDS NPP_NewStream(NPP instance, NPMIMEType type, - NPStream* stream, NPBool seekable, - uint16* stype) -{ - return NPERR_NO_ERROR; -/* struct context *ctx = instance->pdata; - struct qstream *qstr; - - stream->pdata = qstr = malloc(sizeof(*qstr) + strlen(stream->url)); - memset(qstr, 0, sizeof(*qstr)); - strcpy(qstr->url, stream->url); - - Plug_LockPlugin(ctx, true); - qstr->next = ctx->activestreams; - if (qstr->next) - qstr->next->prev = qstr; - ctx->activestreams = qstr; - Plug_LockPlugin(ctx, false); - - if (!stream->notifyData) - { - //choose source type based on mime type - if (!strncmp(type, "text/x-quaketvident", 5)) - stream->notifyData = &QTVFileDescriptor; - else if (!strcmp(type, "application/x-multiviewdemo")) - stream->notifyData = &DemoFileDescriptor; - - //well that failed, try choosing based on extension - else if (!strcmp(COM_FileExtension(stream->url), "qtv")) - stream->notifyData = &QTVFileDescriptor; - - else - return NPERR_INVALID_PARAM; - } - qstr->type = stream->notifyData; - - if (qstr->type->needseeking) - { - *stype = NP_ASFILEONLY; //everything is a download - -#ifdef FIREFOX_BUGS_OVER_25MB - *stype = NP_NORMAL; - qstr->pipe = FS_OpenTemp(); -#endif - } - else - { - *stype = NP_NORMAL; - qstr->pipe = VFSPIPE_Open(); - } - - return NPERR_NO_ERROR;*/ -} -NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream* stream, - NPReason reason) -{ - return NPERR_NO_ERROR; -/* struct context *ctx = instance->pdata; - struct qstream *qstr = stream->pdata; - - if (!qstr) //urm, got canceled before it finished downloading? - return NPERR_NO_ERROR; - - if (qstr->type->wait == WAIT_YES) - { - ctx->waitingfordatafiles--; - } - - if (qstr->next) - qstr->next->prev = qstr->prev; - if (qstr->prev) - qstr->prev->next = qstr->next; - else - ctx->activestreams = qstr->next; - - if (qstr->type->wait == WAIT_NONACTIVE) - { - Plug_LockPlugin(ctx, true); - qstr->type->completionfunc(ctx, qstr->pipe, qstr->url); - Plug_LockPlugin(ctx, false); - } - else - { - qstr->next = ctx->donestreams; - ctx->donestreams = qstr; - } - - if (qstr && qstr->type && qstr->type->wait) - { - InvalidateRgn(ctx->window.window, NULL, FALSE); - } - return NPERR_NO_ERROR;*/ -} -int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream* stream) -{ - return 8192; - -/* struct qstream *qstr = stream->pdata; - vfsfile_t *pipe = qstr?qstr->pipe:NULL; - - if (pipe && pipe->seekingisabadplan) - return 1024*1024 - VFS_GETLEN(pipe); - else - return 8192;*/ -} -int32 NP_LOADDS NPP_Write(NPP instance, NPStream* stream, int32 offset, - int32 len, void* buffer) -{ - return NPERR_NO_ERROR; -/* int bytes = NPP_WriteReady(instance, stream); - struct context *ctx = instance->pdata; - struct qstream *qstr = stream->pdata; - - if (qstr && qstr->type && qstr->type->wait) - { - qstr->offset = offset; - qstr->size = stream->end; - InvalidateRgn(ctx->window.window, NULL, FALSE); - } - - if (!qstr || !qstr->pipe) - return bytes; - - //we're not meant to read more bytes than we said we could read. - if (len > bytes) - len = bytes; - - return VFS_WRITE(qstr->pipe, buffer, len);*/ -} -void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream* stream, - const char* fname) -{ - return; -/* struct qstream *qstr = stream->pdata; - - if (!qstr) - return; - - if (qstr->pipe) - VFS_CLOSE(qstr->pipe); - qstr->pipe = VFSOS_Open(fname, "rb"); -*/ -} - -void NP_LOADDS NPP_Print(NPP instance, NPPrint* platformPrint) -{ - //we don't support printing. - //paper and ink doesn't give a good frame rate. - return; -} -int16 NP_LOADDS NPP_HandleEvent(NPP instance, void* event) -{ -// MessageBox(NULL, "NPP_HandleEvent", "npapi", 0); - return NPERR_NO_ERROR; -} -void NP_LOADDS NPP_URLNotify(NPP instance, const char* url, - NPReason reason, void* notifyData) -{ -} - -struct npscript -{ - NPObject obj; - - struct context *ctx; -}; - -NPObject *npscript_allocate(NPP npp, NPClass *aClass) -{ - struct npscript_property *prop; - struct npscript *obj; - obj = malloc(sizeof(*obj)); - obj->obj._class = aClass; - obj->obj.referenceCount = 1; - obj->ctx = npp->pdata; - - return (NPObject*)obj; -} -void npscript_deallocate(NPObject *npobj) -{ - free(npobj); -} -void npscript_invalidate(NPObject *npobj) -{ - struct npscript *obj = (struct npscript *)npobj; - obj->ctx = NULL; -} -bool npscript_hasMethod(NPObject *npobj, NPIdentifier name) -{ - NPUTF8 *mname; - mname = browserfuncs->utf8fromidentifier(name); - return false; -} -bool npscript_invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32_t argCount, NPVariant *result) -{ - return false; -} -bool npscript_invokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) -{ - return false; -} -bool npscript_hasProperty(NPObject *npobj, NPIdentifier name) -{ - struct npscript *obj = (struct npscript *)npobj; - struct npscript_property *prop; - NPUTF8 *pname; - pname = browserfuncs->utf8fromidentifier(name); - - if (Plug_FindProp(obj->ctx, pname)) - return true; - return false; -} -bool npscript_getProperty(NPObject *npobj, NPIdentifier name, NPVariant *result) -{ - struct npscript *obj = (struct npscript *)npobj; - struct context *ctx = obj->ctx; - NPUTF8 *pname; - struct pscript_property *prop; - bool success = false; - char *strval; - int intval; - float floatval; - pname = browserfuncs->utf8fromidentifier(name); - - Plug_LockPlugin(ctx, true); - prop = Plug_FindProp(obj->ctx, pname); - if (prop) - { - if (Plug_GetString(ctx, prop, &strval)) - { - char *ns; - int len; - len = strlen(strval); - ns = browserfuncs->memalloc(len); - if (ns) - { - memcpy(ns, strval, len); - STRINGZ_TO_NPVARIANT(ns, *result); - success = true; - } - Plug_GotString(strval); - } - else if (Plug_GetInteger(ctx, prop, &intval)) - { - INT32_TO_NPVARIANT(intval, *result); - success = true; - } - else if (Plug_GetFloat(ctx, prop, &floatval)) - { - DOUBLE_TO_NPVARIANT(floatval, *result); - success = true; - } - } - Plug_LockPlugin(ctx, false); - return success; -} -bool npscript_setProperty(NPObject *npobj, NPIdentifier name, const NPVariant *value) -{ - struct npscript *obj = (struct npscript *)npobj; - struct context *ctx = obj->ctx; - NPUTF8 *pname; - NPString str; - struct pscript_property *prop; - bool success = false; - pname = browserfuncs->utf8fromidentifier(name); - - Plug_LockPlugin(ctx, true); - prop = Plug_FindProp(obj->ctx, pname); - if (prop) - { - success = true; - if (NPVARIANT_IS_STRING(*value)) - { - char *t = NULL; - - str = NPVARIANT_TO_STRING(*value); - if (str.utf8characters[str.utf8length] != 0) - { - t = malloc(str.utf8length+1); - memcpy(t, str.utf8characters, str.utf8length); - t[str.utf8length] = 0; - str.utf8characters = t; - } - Plug_SetString(ctx, prop, str.utf8characters); - if (t) - free(t); - } - else if (NPVARIANT_IS_INT32(*value)) - Plug_SetInteger(ctx, prop, NPVARIANT_TO_INT32(*value)); - else if (NPVARIANT_IS_BOOLEAN(*value)) - Plug_SetInteger(ctx, prop, NPVARIANT_TO_BOOLEAN(*value)); - else if (NPVARIANT_IS_DOUBLE(*value)) - Plug_SetFloat(ctx, prop, NPVARIANT_TO_DOUBLE(*value)); - else - success = false; - } - Plug_LockPlugin(ctx, false); - return success; -} -bool npscript_removeProperty(NPObject *npobj, NPIdentifier name) -{ - return false; -} -bool npscript_enumerate(NPObject *npobj, NPIdentifier **value, uint32_t *count) -{ - return false; -} -bool npscript_construct(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) -{ - return false; -} - -NPClass npscript_class = -{ - NP_CLASS_STRUCT_VERSION, - - npscript_allocate, - npscript_deallocate, - npscript_invalidate, - npscript_hasMethod, - npscript_invoke, - npscript_invokeDefault, - npscript_hasProperty, - npscript_getProperty, - npscript_setProperty, - npscript_removeProperty, - npscript_enumerate, - npscript_construct -}; - -NPError NP_LOADDS NPP_GetValue(NPP instance, NPPVariable variable, void *value) -{ - switch(variable) - { - case NPPVpluginScriptableNPObject: - *(void**)value = browserfuncs->createobject(instance, &npscript_class); - return NPERR_NO_ERROR; - default: - return NPERR_INVALID_PARAM; - } - - return NPERR_NO_ERROR; -} -NPError NP_LOADDS NPP_SetValue(NPP instance, NPNVariable variable, void *value) -{ - switch(variable) - { - default: - return NPERR_INVALID_PARAM; - } - return NPERR_NO_ERROR; -} - -NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs) -{ - browserfuncs = pFuncs; - return NPERR_NO_ERROR; -} - -NPError OSCALL NP_Shutdown(void) -{ -/* if (contextlist) - { //the browser isn't meant to call this when there's still instances left... - return NPERR_GENERIC_ERROR; - } -*/ - return NPERR_NO_ERROR; -} - -NPError OSCALL NP_GetValue(void *instance, NPPVariable variable, void *value) -{ - if (value == NULL) - return NPERR_INVALID_PARAM; - - switch(variable) - { - case NPPVpluginNameString: - *(char**)value = "QTV Viewer"; - break; - case NPPVpluginDescriptionString: - *(char**)value = "QTV Viewer"; - break; - default: - return NPERR_INVALID_PARAM; - } - return NPERR_NO_ERROR; -} - -NPError OSCALL NP_GetEntryPoints (NPPluginFuncs* pFuncs) -{ - if (pFuncs->size < sizeof(NPPluginFuncs)) - return NPERR_INVALID_FUNCTABLE_ERROR; - pFuncs->size = sizeof(NPPluginFuncs); - - pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; - - pFuncs->newp = NPP_New; - pFuncs->destroy = NPP_Destroy; - pFuncs->setwindow = NPP_SetWindow; - pFuncs->newstream = NPP_NewStream; - pFuncs->destroystream = NPP_DestroyStream; - pFuncs->asfile = NPP_StreamAsFile; - pFuncs->writeready = NPP_WriteReady; - pFuncs->write = NPP_Write; - pFuncs->print = NPP_Print; - pFuncs->event = NPP_HandleEvent; - pFuncs->urlnotify = NPP_URLNotify; - pFuncs->javaClass = NULL; - pFuncs->getvalue = NPP_GetValue; - pFuncs->setvalue = NPP_SetValue; - - return NPERR_NO_ERROR; -} - -char *NP_GetMIMEDescription(void) -{ - return "test/x-qtv:qtv:QTV Stream Description"; -} diff --git a/engine/client/sys_plugfte.c b/engine/client/sys_plugfte.c index 06fa7292..6b493880 100644 --- a/engine/client/sys_plugfte.c +++ b/engine/client/sys_plugfte.c @@ -105,6 +105,8 @@ struct context struct contextpublic pub; void *windowhnd; + int windowleft; + int windowtop; int windowwidth; int windowheight; @@ -117,7 +119,7 @@ struct context char *onend; char *ondemoend; - void *nppinstance; + void *hostinstance; int read; int written; @@ -299,7 +301,6 @@ int Plug_PluginThread(void *ctxptr) } Con_Printf("Attempting to download %s\n", c); - VS_DebugLocation(__FILE__, __LINE__, "Queuing Download %s", c); dl = DL_Create(c); dl->user_ctx = ctx; @@ -327,7 +328,7 @@ int Plug_PluginThread(void *ctxptr) ctx->pub.dlsize = total; ctx->pub.dldone = done; if (ctx->bfuncs.StatusChanged) - ctx->bfuncs.StatusChanged(&ctx->pub); + ctx->bfuncs.StatusChanged(ctx->hostinstance); } if (!dl->file) ctx->packagelist = dl->next; @@ -347,28 +348,29 @@ int Plug_PluginThread(void *ctxptr) Sys_LockMutex(ctx->mutex); ctx->resetvideo = false; sys_parentwindow = ctx->windowhnd; + sys_parentleft = ctx->windowleft; + sys_parenttop = ctx->windowtop; sys_parentwidth = ctx->windowwidth; sys_parentheight = ctx->windowheight; - VS_DebugLocation(__FILE__, __LINE__, "Host_FinishInit"); Host_FinishInit(); Sys_UnlockMutex(ctx->mutex); } if (ctx->bfuncs.StatusChanged) - ctx->bfuncs.StatusChanged(&ctx->pub); + ctx->bfuncs.StatusChanged(ctx->hostinstance); - VS_DebugLocation(__FILE__, __LINE__, "main loop"); while(host_initialized) { Sys_LockMutex(ctx->mutex); if (ctx->shutdown) { ctx->shutdown = false; - VS_DebugLocation(__FILE__, __LINE__, "Sys_Shutdown"); Host_Shutdown(); /*will shut down the host*/ } else if (ctx->resetvideo) { sys_parentwindow = ctx->windowhnd; + sys_parentleft = ctx->windowleft; + sys_parenttop = ctx->windowtop; sys_parentwidth = ctx->windowwidth; sys_parentheight = ctx->windowheight; if (ctx->resetvideo == 2) @@ -410,7 +412,7 @@ int Plug_PluginThread(void *ctxptr) ctx->pub.running = false; Sys_UnlockMutex(ctx->mutex); if (ctx->bfuncs.StatusChanged) - ctx->bfuncs.StatusChanged(&ctx->pub); + ctx->bfuncs.StatusChanged(ctx->hostinstance); while(argc-- > 0) free(argv[argc]); @@ -470,7 +472,7 @@ struct context *Plug_CreateContext(void *sysctx, const struct browserfuncs *func memcpy(&ctx->bfuncs, funcs, sizeof(ctx->bfuncs)); //link the instance to the context and the context to the instance - ctx->nppinstance = sysctx; + ctx->hostinstance = sysctx; ctx->gamename = strdup("q1"); @@ -484,7 +486,7 @@ struct context *Plug_CreateContext(void *sysctx, const struct browserfuncs *func } //change the plugin's parent window, width, and height, returns true if the window handle actually changed, false otherwise -qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int width, int height) +qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int left, int top, int width, int height) { qboolean result = false; @@ -497,11 +499,12 @@ qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int width, int heigh ctx->windowhnd = whnd; ctx->resetvideo = 2; } - if (ctx->windowwidth != width || ctx->windowheight != height) - { - ctx->windowwidth = width; - ctx->windowheight = height; - } + + ctx->windowleft = left; + ctx->windowtop = top; + ctx->windowwidth = width; + ctx->windowheight = height; + if (ctx->pub.running && !ctx->resetvideo) ctx->resetvideo = true; Plug_LockPlugin(ctx, false); @@ -659,7 +662,7 @@ void LoadSplashImage(struct dl_download *dl) if (!f) { if (ctx->bfuncs.StatusChanged) - ctx->bfuncs.StatusChanged(&ctx->pub); + ctx->bfuncs.StatusChanged(ctx->hostinstance); return; } @@ -695,7 +698,7 @@ void LoadSplashImage(struct dl_download *dl) BZ_Free(image); if (ctx->bfuncs.StatusChanged) - ctx->bfuncs.StatusChanged(&ctx->pub); + ctx->bfuncs.StatusChanged(ctx->hostinstance); } } @@ -887,9 +890,10 @@ char *pscript_property_build_gets(struct context *ctx) extern cvar_t skin, team, topcolor, bottomcolor, vid_fullscreen, cl_download_mapsrc; static struct pscript_property pscript_properties[] = { + {"", false, NULL, pscript_property_curserver_gets, pscript_property_curserver_sets}, + {"server", false, NULL, pscript_property_curserver_gets, pscript_property_curserver_sets}, {"running", false, NULL, NULL, NULL, pscript_property_running_getb, pscript_property_running_setb}, {"startserver", false, NULL, pscript_property_startserver_gets, pscript_property_startserver_sets}, - {"server", false, NULL, pscript_property_curserver_gets, pscript_property_curserver_sets}, {"join", false, NULL, NULL, pscript_property_curserver_sets}, {"playername", true, &name}, {NULL, true, &skin}, @@ -913,68 +917,11 @@ static struct pscript_property pscript_properties[] = {"map", false, NULL, NULL, pscript_property_map_sets}, {"build", false, NULL, pscript_property_build_gets}, -/* - else if (!stricmp(argn[i], "connType")) - { - if (ctx->qtvf.connectiontype) - continue; - if (!stricmp(argn[i], "join")) - ctx->qtvf.connectiontype = QTVCT_JOIN; - else if (!stricmp(argn[i], "qtv")) - ctx->qtvf.connectiontype = QTVCT_STREAM; - else if (!stricmp(argn[i], "connect")) - ctx->qtvf.connectiontype = QTVCT_CONNECT; - else if (!stricmp(argn[i], "map")) - ctx->qtvf.connectiontype = QTVCT_MAP; - else if (!stricmp(argn[i], "join")) - ctx->qtvf.connectiontype = QTVCT_JOIN; - else if (!stricmp(argn[i], "observe")) - ctx->qtvf.connectiontype = QTVCT_OBSERVE; - else - ctx->qtvf.connectiontype = QTVCT_NONE; - } - else if (!stricmp(argn[i], "map")) - { - if (ctx->qtvf.connectiontype) - continue; - ctx->qtvf.connectiontype = QTVCT_MAP; - Q_strncpyz(ctx->qtvf.server, argv[i], sizeof(ctx->qtvf.server)); - } - else if (!stricmp(argn[i], "join")) - { - if (ctx->qtvf.connectiontype) - continue; - ctx->qtvf.connectiontype = QTVCT_JOIN; - Q_strncpyz(ctx->qtvf.server, argv[i], sizeof(ctx->qtvf.server)); - } - else if (!stricmp(argn[i], "observe")) - { - if (ctx->qtvf.connectiontype) - continue; - ctx->qtvf.connectiontype = QTVCT_OBSERVE; - Q_strncpyz(ctx->qtvf.server, argv[i], sizeof(ctx->qtvf.server)); - } - else if (!stricmp(argn[i], "password")) - { - ctx->password = strdup(argv[i]); - } - else if (!stricmp(argn[i], "onStart")) - { - ctx->onstart = strdup(argv[i]); - } - else if (!stricmp(argn[i], "onEnd")) - { - ctx->onend = strdup(argv[i]); - } - else if (!stricmp(argn[i], "onDemoEnd")) - { - ctx->ondemoend = strdup(argv[i]); - } -*/ + {NULL} }; -struct pscript_property *Plug_FindProp(struct context *ctx, const char *field) +int Plug_FindProp(struct context *ctx, const char *field) { struct pscript_property *prop; for (prop = pscript_properties; prop->name||prop->cvar; prop++) @@ -984,17 +931,18 @@ struct pscript_property *Plug_FindProp(struct context *ctx, const char *field) if (prop->onlyifactive) { if (!ctx->pub.running) - return NULL; + return -1; } - return prop; + return prop - pscript_properties; } } - return NULL; + return -1; } -qboolean Plug_SetString(struct context *ctx, struct pscript_property *field, const char *value) +qboolean Plug_SetString(struct context *ctx, int fieldidx, const char *value) { - if (!ctx || !field || !value) + struct pscript_property *field = pscript_properties + fieldidx; + if (!ctx || fieldidx < 0 || fieldidx >= sizeof(pscript_properties)/sizeof(pscript_properties[0]) || !value) return false; if (field->setstring) { @@ -1024,9 +972,16 @@ qboolean Plug_SetString(struct context *ctx, struct pscript_property *field, con return false; return true; } -qboolean Plug_SetInteger(struct context *ctx, struct pscript_property *field, int value) +qboolean Plug_SetWString(struct context *ctx, int fieldidx, const wchar_t *value) { - if (!ctx || !field) + char tmp[1024]; + wcstombs(tmp, value, sizeof(tmp)); + return Plug_SetString(ctx, fieldidx, tmp); +} +qboolean Plug_SetInteger(struct context *ctx, int fieldidx, int value) +{ + struct pscript_property *field = pscript_properties + fieldidx; + if (!ctx || fieldidx < 0 || fieldidx >= sizeof(pscript_properties)/sizeof(pscript_properties[0])) return false; if (field->setint) { @@ -1050,9 +1005,10 @@ qboolean Plug_SetInteger(struct context *ctx, struct pscript_property *field, in return false; return true; } -qboolean Plug_SetFloat(struct context *ctx, struct pscript_property *field, float value) +qboolean Plug_SetFloat(struct context *ctx, int fieldidx, float value) { - if (!ctx || !field) + struct pscript_property *field = pscript_properties + fieldidx; + if (!ctx || fieldidx < 0 || fieldidx >= sizeof(pscript_properties)/sizeof(pscript_properties[0])) return false; if (field->setfloat) { @@ -1077,8 +1033,12 @@ qboolean Plug_SetFloat(struct context *ctx, struct pscript_property *field, floa return true; } -qboolean Plug_GetString(struct context *ctx, struct pscript_property *field, const char **value) +qboolean Plug_GetString(struct context *ctx, int fieldidx, const char **value) { + struct pscript_property *field = pscript_properties + fieldidx; + if (!ctx || fieldidx < 0 || fieldidx >= sizeof(pscript_properties)/sizeof(pscript_properties[0])) + return false; + if (field->getstring) { *value = field->getstring(ctx); @@ -1090,8 +1050,12 @@ void Plug_GotString(const char *value) { free((char*)value); } -qboolean Plug_GetInteger(struct context *ctx, struct pscript_property *field, int *value) +qboolean Plug_GetInteger(struct context *ctx, int fieldidx, int *value) { + struct pscript_property *field = pscript_properties + fieldidx; + if (!ctx || fieldidx < 0 || fieldidx >= sizeof(pscript_properties)/sizeof(pscript_properties[0])) + return false; + if (field->getint) { *value = field->getint(ctx); @@ -1099,8 +1063,12 @@ qboolean Plug_GetInteger(struct context *ctx, struct pscript_property *field, in } return false; } -qboolean Plug_GetFloat(struct context *ctx, struct pscript_property *field, float *value) +qboolean Plug_GetFloat(struct context *ctx, int fieldidx, float *value) { + struct pscript_property *field = pscript_properties + fieldidx; + if (!ctx || fieldidx < 0 || fieldidx >= sizeof(pscript_properties)/sizeof(pscript_properties[0])) + return false; + if (field->getfloat) { *value = field->getfloat(ctx); @@ -1161,7 +1129,9 @@ static const struct plugfuncs exportedplugfuncs_1 = Plug_GetFloat, Plug_GetSplashBack, - Plug_ReleaseSplashBack + Plug_ReleaseSplashBack, + + Plug_SetWString }; const struct plugfuncs *Plug_GetFuncs(int ver) diff --git a/engine/client/sys_plugfte.h b/engine/client/sys_plugfte.h index 03eaf5c2..776edb5a 100644 --- a/engine/client/sys_plugfte.h +++ b/engine/client/sys_plugfte.h @@ -26,6 +26,7 @@ struct contextpublic void *user; }; +/* #include static void VS_DebugLocation(char *fname, int line, char *fmt, ...) { @@ -41,7 +42,7 @@ static void VS_DebugLocation(char *fname, int line, char *fmt, ...) OutputDebugStringA(buffer); OutputDebugStringA("\n"); } - +*/ @@ -58,16 +59,16 @@ void Plug_DestroyContext(struct context *ctx); void Plug_LockPlugin(struct context *ctx, qboolean lockstate); qboolean Plug_StartContext(struct context *ctx); void Plug_StopContext(struct context *ctx); -qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int width, int height); +qboolean Plug_ChangeWindow(struct context *ctx, void *whnd, int left, int top, int width, int height); -struct pscript_property *Plug_FindProp(struct context *ctx, const char *field); -qboolean Plug_SetString(struct context *ctx, struct pscript_property *field, const char *value); -qboolean Plug_GetString(struct context *ctx, struct pscript_property *field, const char **value); +int Plug_FindProp(struct context *ctx, const char *field); +qboolean Plug_SetString(struct context *ctx, int field, const char *value); +qboolean Plug_GetString(struct context *ctx, int field, const char **value); void Plug_GotString(const char *value); -qboolean Plug_SetInteger(struct context *ctx, struct pscript_property *field, int value); -qboolean Plug_GetInteger(struct context *ctx, struct pscript_property *field, int *value); -qboolean Plug_SetFloat(struct context *ctx, struct pscript_property *field, float value); -qboolean Plug_GetFloat(struct context *ctx, struct pscript_property *field, float *value); +qboolean Plug_SetInteger(struct context *ctx, int field, int value); +qboolean Plug_GetInteger(struct context *ctx, int field, int *value); +qboolean Plug_SetFloat(struct context *ctx, int field, float value); +qboolean Plug_GetFloat(struct context *ctx, int field, float *value); #ifdef _WIN32 void *Plug_GetSplashBack(struct context *ctx, void *hdc, int *width, int *height);/*returns an HBITMAP*/ @@ -81,22 +82,27 @@ struct plugfuncs void (*LockPlugin)(struct context *ctx, qboolean lockstate); qboolean (*StartContext)(struct context *ctx); void (*StopContext)(struct context *ctx); - qboolean (*ChangeWindow)(struct context *ctx, void *whnd, int width, int height); + qboolean (*ChangeWindow)(struct context *ctx, void *whnd, int left, int top, int width, int height); - struct pscript_property *(*FindProp)(struct context *ctx, const char *field); - qboolean (*SetString)(struct context *ctx, struct pscript_property *field, const char *value); - qboolean (*GetString)(struct context *ctx, struct pscript_property *field, const char **value); + int (*FindProp)(struct context *ctx, const char *field); + qboolean (*SetString)(struct context *ctx, int field, const char *value); + qboolean (*GetString)(struct context *ctx, int field, const char **value); void (*GotString)(const char *value); - qboolean (*SetInteger)(struct context *ctx, struct pscript_property *field, int value); - qboolean (*GetInteger)(struct context *ctx, struct pscript_property *field, int *value); - qboolean (*SetFloat)(struct context *ctx, struct pscript_property *field, float value); - qboolean (*GetFloat)(struct context *ctx, struct pscript_property *field, float *value); + qboolean (*SetInteger)(struct context *ctx, int field, int value); + qboolean (*GetInteger)(struct context *ctx, int field, int *value); + qboolean (*SetFloat)(struct context *ctx, int field, float value); + qboolean (*GetFloat)(struct context *ctx, int field, float *value); #ifdef _WIN32 void *(*GetSplashBack)(struct context *ctx, void *hdc, int *width, int *height);/*returns an HBITMAP*/ void (*ReleaseSplashBack)(struct context *ctx, void *bmp); #endif + + qboolean (*SetWString)(struct context *ctx, int field, const wchar_t *value); }; #define PLUG_APIVER 1 +#ifdef __cplusplus +extern "C" +#endif const struct plugfuncs *Plug_GetFuncs(int ver); diff --git a/engine/client/sys_win.c b/engine/client/sys_win.c index 37b72d3e..f0e994d9 100644 --- a/engine/client/sys_win.c +++ b/engine/client/sys_win.c @@ -46,6 +46,8 @@ qboolean isDedicated = false; qboolean debugout; HWND sys_parentwindow; +unsigned int sys_parentleft; //valid if sys_parentwindow is set +unsigned int sys_parenttop; unsigned int sys_parentwidth; //valid if sys_parentwindow is set unsigned int sys_parentheight; @@ -1866,8 +1868,10 @@ qboolean Sys_LockMutex(void *mutex) return true; OutputDebugString("Warning: Suspected mutex deadlock\n"); DebugBreak(); -#endif + return false; +#else return WaitForSingleObject(mutex, INFINITE) == WAIT_OBJECT_0; +#endif } qboolean Sys_UnlockMutex(void *mutex) diff --git a/engine/client/textedit.c b/engine/client/textedit.c index 2f3e7d3f..21c2a772 100644 --- a/engine/client/textedit.c +++ b/engine/client/textedit.c @@ -526,7 +526,7 @@ void Editor_Key(int key, int unicode) case K_F4: EditorSaveFile(OpenEditorFile); break; - case K_F5: + case K_F5: /*stop debugging*/ editormodal = false; if (editprogfuncs) *editprogfuncs->pr_trace = false; @@ -535,16 +535,16 @@ void Editor_Key(int key, int unicode) if (editprogfuncs) PR_StackTrace(editprogfuncs); break; - case K_F7: + case K_F7: /*save+recompile*/ EditorSaveFile(OpenEditorFile); if (editprogfuncs) Cbuf_AddText("compile\n", RESTRICT_LOCAL); break; - case K_F8: + case K_F8: /*move execution point to here - I hope you move to the same function!*/ executionlinenum = cursorlinenum; executionblock = cursorblock; break; - case K_F9: + case K_F9: /*set breakpoint*/ { int f = 0; if (editprogfuncs) @@ -570,11 +570,11 @@ void Editor_Key(int key, int unicode) cursorblock->flags &= ~FB_BREAK; } break; - case K_F10: + case K_F10: //save+apply changes, supposedly EditorSaveFile(OpenEditorFile); Cbuf_AddText("applycompile\n", RESTRICT_LOCAL); break; - case K_F11: + case K_F11: //single step editormodal = false; break; // case K_STOP: diff --git a/engine/client/valid.c b/engine/client/valid.c index c002dc56..151ea186 100644 --- a/engine/client/valid.c +++ b/engine/client/valid.c @@ -295,8 +295,8 @@ static void Validation_Server(void) { char adr[MAX_ADR_SIZE]; -#ifndef _MSC_VER - #warning is allowing the user to turn this off practical?.. +#ifdef warningmsg +#pragma warningmsg("is allowing the user to turn this off practical?..") #endif if (!allow_f_server.ival) return; @@ -391,6 +391,8 @@ rulesetrule_t rulesetrules_strict[] = { {"ruleset_allow_localvolume", "0"}, {"tp_disputablemacros", "0"}, {"cl_instantrotate", "0"}, + {"v_projectionmode", "0"}, /*no extended fovs*/ + {"r_shadow_realtime_world", "0"}, /*static lighting can be used to cast shadows around corners*/ {NULL} }; @@ -404,6 +406,7 @@ rulesetrule_t rulesetrules_nqr[] = { {"ruleset_allow_sensative_texture_replacements", "0"}, {"ruleset_allow_localvolume", "0"}, {"ruleset_allow_shaders", "0"}, + {"v_projectionmode", "0"}, {NULL} }; @@ -435,11 +438,11 @@ qboolean Validation_GetCurrentRulesetName(char *rsnames, int resultbuflen, qbool rs = rulesets; *rsnames = '\0'; -#ifndef _MSC_VER -#warning "here's a question... Should we latch the ruleset unconditionally, or only when someone actually cares?" -#warning if we do it only when someone checks, we have a lot more checking, otherwise we have a freer tournament if the users choose to play that way -#warning "I'm going to do it the old-fashioned way" -#warning (yes, this is one for molgrum to resolve!) +#ifdef warningmsg +#pragma warningmsg("here's a question... Should we latch the ruleset unconditionally, or only when someone actually cares?") +#pragma warningmsg("if we do it only when someone checks, we have a lot more checking, otherwise we have a freer tournament if the users choose to play that way") +#pragma warningmsg("I'm going to do it the old-fashioned way") +#pragma warningmsg("(yes, this is one for molgrum to resolve!)") #endif for (rs = rulesets; rs->rulesetname; rs++) { @@ -537,8 +540,8 @@ void Validation_Apply_Ruleset(void) cvar_t *var; int i; -#ifndef _MSC_VER - #warning fixme: the following line should not be needed. ensure this is the case +#ifdef warningmsg +#pragma warningmsg("fixme: the following line should not be needed. ensure this is the case") #endif Validation_DelatchRulesets(); //make sure there's no old one diff --git a/engine/client/vid.h b/engine/client/vid.h index 6707b22f..2d5878bd 100644 --- a/engine/client/vid.h +++ b/engine/client/vid.h @@ -45,7 +45,7 @@ extern rendererstate_t currentrendererstate; typedef struct vrect_s { int x,y,width,height; - struct vrect_s *pnext; +// struct vrect_s *pnext; } vrect_t; typedef struct diff --git a/engine/client/view.c b/engine/client/view.c index 129f9840..d1c3387b 100644 --- a/engine/client/view.c +++ b/engine/client/view.c @@ -25,11 +25,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include // for isdigit(); -#ifdef FISH -void R_RenderView_fisheye(void); cvar_t ffov = SCVAR("ffov", "0"); -cvar_t fviews = SCVAR("fviews", "6"); -#endif /* @@ -96,6 +92,7 @@ cvar_t v_gunkick = SCVAR("v_gunkick", "0"); cvar_t v_gunkick_q2 = SCVAR("v_gunkick_q2", "1"); cvar_t v_viewheight = SCVAR("v_viewheight", "0"); +cvar_t v_projectionmode = SCVAR("v_projectionmode", "0"); cvar_t scr_autoid = SCVAR("scr_autoid", "1"); @@ -1201,11 +1198,9 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) case 3: #ifdef GLQUAKE if (qrenderer == QR_OPENGL && vid.rotpixelwidth > vid.rotpixelheight * 2 -#ifdef FISH - && ffov.value >= 0 -#endif + && ffov.value >= 0 /*panoramic view always stacks player views*/ ) - { //over twice as wide as high, assume duel moniter, horizontal. + { //over twice as wide as high, assume dual moniter, horizontal. vrect->width = vid.width/cl.splitclients; vrect->height = vid.height; vrect->x = 0 + vrect->width*pnum; @@ -1214,6 +1209,7 @@ void SCR_VRectForPlayer(vrect_t *vrect, int pnum) else #endif { + //stack them vertically vrect->width = vid.width; vrect->height = vid.height/cl.splitclients; vrect->x = 0; @@ -1341,7 +1337,7 @@ void V_RenderPlayerViews(int plnum) r_secondaryview = 2; VectorSubtract(r_refdef.vieworg, desired_position[plnum], dir); - vectoangles(dir, r_refdef.viewangles); + VectorAngles(dir, NULL, r_refdef.viewangles); r_refdef.viewangles[0] = -r_refdef.viewangles[0]; //flip the pitch. :( @@ -1579,10 +1575,7 @@ void V_Init (void) } #endif -#ifdef FISH Cvar_Register (&ffov, VIEWVARS); - Cvar_Register (&fviews, VIEWVARS); -#endif BuildGammaTable (1.0, 1.0); // no gamma yet Cvar_Register (&v_gamma, VIEWVARS); diff --git a/engine/client/winquake.h b/engine/client/winquake.h index e117b3b1..cef9cbbb 100644 --- a/engine/client/winquake.h +++ b/engine/client/winquake.h @@ -51,6 +51,8 @@ extern HINSTANCE global_hInstance; extern int global_nCmdShow; extern HWND sys_parentwindow; +extern unsigned int sys_parentleft; +extern unsigned int sys_parenttop; extern unsigned int sys_parentwidth; extern unsigned int sys_parentheight;