diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index d9e9c9ed..86e0a3cc 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -208,7 +208,7 @@ int demo_preparsedemo(unsigned char *buffer, int bytes) net_message.cursize = length; memcpy(net_message.data, buffer+ofs, length); MSG_BeginReading(cls.netchan.netprim); - CL_ParseServerMessage(); + CLQW_ParseServerMessage(); } parsed += ofs+length; diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 8f3c936b..63db9854 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1334,7 +1334,7 @@ void V_AddAxisEntity(entity_t *in) if (cl_numvisedicts == MAX_VISEDICTS) { - Con_Printf("Visedict list is full!\n"); + Con_DPrintf("Visedict list is full!\n"); return; // object list is full } ent = &cl_visedicts[cl_numvisedicts]; @@ -1348,7 +1348,7 @@ entity_t *V_AddEntity(entity_t *in) if (cl_numvisedicts == MAX_VISEDICTS) { - Con_Printf("Visedict list is full!\n"); + Con_DPrintf("Visedict list is full!\n"); return NULL; // object list is full } ent = &cl_visedicts[cl_numvisedicts]; @@ -3447,8 +3447,6 @@ Made up of: clients, packet_entities, nails, and tents */ void CL_SwapEntityLists(void) { - cl_visedicts = cl_visedicts_list; - cl_numvisedicts = 0; cl_numstrisidx = 0; cl_numstrisvert = 0; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 13dbb12c..71823530 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -199,8 +199,7 @@ int rtlights_first, rtlights_max; // this is double buffered so the last frame // can be scanned for oldorigins of trailing objects int cl_numvisedicts; -entity_t *cl_visedicts; -entity_t cl_visedicts_list[MAX_VISEDICTS]; +entity_t cl_visedicts[MAX_VISEDICTS]; scenetris_t *cl_stris; vecV_t *cl_strisvertv; @@ -2719,7 +2718,7 @@ void CL_ReadPackets (void) cls.netchan.outgoing_sequence = cls.netchan.incoming_sequence; } MSG_ChangePrimitives(cls.netchan.netprim); - CL_ParseServerMessage (); + CLQW_ParseServerMessage (); break; case CP_UNKNOWN: break; diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 52a995ae..e5b69cd1 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -943,13 +943,8 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) if (anycsqc || *s || cls.demoplayback) //only allow csqc if the server says so, and the 'checksum' matches. { unsigned int chksum = anycsqc?0:strtoul(s, NULL, 0); - if (CSQC_Init(chksum)) + if (!CSQC_Init(chksum)) { - CL_SendClientCommand(true, "enablecsqc"); - } - else - { - CL_SendClientCommand(true, "disablecsqc"); Sbar_Start(); //try and start this before we're actually on the server, //this'll stop the mod from sending so much stuffed data at us, whilst we're frozen while trying to load. //hopefully this'll make it more robust. @@ -1092,6 +1087,19 @@ int CL_LoadModels(int stage, qboolean dontactuallyload) endstage(); } + if (atstage()) + { + if (CSQC_Inited()) + { + CL_SendClientCommand(true, "enablecsqc"); + } + else + { + CL_SendClientCommand(true, "disablecsqc"); + } + endstage(); + } + return stage; } @@ -1631,7 +1639,7 @@ int CL_RequestADownloadChunk(void) CL_SendClientCommand(true, "stopdownload"); CL_DownloadFinished(); - Con_Printf("Download took %i seconds (%i more)\n", (int)(Sys_DoubleTime() - downloadstarttime), CL_CountQueuedDownloads()); + Con_DPrintf("Download took %i seconds (%i more)\n", (int)(Sys_DoubleTime() - downloadstarttime), CL_CountQueuedDownloads()); *cls.downloadlocalname = '\0'; *cls.downloadremotename = '\0'; @@ -1776,7 +1784,7 @@ void CL_ParseDownload (void) cls.downloadqw = NULL; cls.downloadpercent = 0; - Con_Printf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime)); + Con_DPrintf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime)); // get another file if needed @@ -1916,7 +1924,7 @@ void CLDP_ParseDownloadFinished(char *s) cls.downloadqw = NULL; cls.downloadpercent = 0; - Con_Printf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime)); + Con_DPrintf("Download took %i seconds\n", (int)(Sys_DoubleTime() - downloadstarttime)); // get another file if needed @@ -2488,7 +2496,7 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. } else if (protover == H2_PROTOCOL_VERSION) { - Host_EndGame ("\nUnable to connect to Hexen2 servers.\n"); + Host_EndGame ("\nUnable to connect to standard Hexen2 servers. Host the game with "DISTRIBUTION"\n"); } else if (protover != NQ_PROTOCOL_VERSION) { @@ -2587,6 +2595,10 @@ void CLNQ_ParseServerData(void) //Doesn't change gamedir - use with caution. //allow some things by default that quakeworld bans by default Info_SetValueForStarKey(cl.serverinfo, "watervis", "1", sizeof(cl.serverinfo)); + Info_SetValueForStarKey(cl.serverinfo, "mirrors", "1", sizeof(cl.serverinfo)); + + //prohibit some things that QW/FTE has enabled by default + Info_SetValueForStarKey(cl.serverinfo, "fbskins", "0", sizeof(cl.serverinfo)); //pretend it came from the server, and update cheat/permissions/etc CL_CheckServerInfo(); @@ -4843,7 +4855,7 @@ CL_ParseServerMessage ===================== */ int received_framecount; -void CL_ParseServerMessage (void) +void CLQW_ParseServerMessage (void) { int cmd; char *s; diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 346c7787..2183c545 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -848,7 +848,10 @@ fixedorg: from = &cl.frames[cl.oldvalidsequence & UPDATE_MASK]; //figure out the lerp factor - f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime);//f = (cl.time-cl.lerpents[state->number].lerptime)/cl.lerpents[state->number].lerprate; + if (cl.gametime == cl.servertime) + f = 0; + else + f = (cl.gametime-cl.servertime)/(cl.gametime-cl.oldgametime);//f = (cl.time-cl.lerpents[state->number].lerptime)/cl.lerpents[state->number].lerprate; if (f<0) f=0; if (f>1) diff --git a/engine/client/cl_ui.c b/engine/client/cl_ui.c index c613fa85..1807bd77 100644 --- a/engine/client/cl_ui.c +++ b/engine/client/cl_ui.c @@ -377,8 +377,6 @@ int VMQ3_StringToHandle(char *str) void VQ3_AddEntity(const q3refEntity_t *q3) { entity_t ent; - if (!cl_visedicts) - cl_visedicts = cl_visedicts_list; memset(&ent, 0, sizeof(ent)); ent.model = VM_FROMMHANDLE(q3->hModel); ent.framestate.g[FS_REG].frame[0] = q3->frame; diff --git a/engine/client/client.h b/engine/client/client.h index d1bc2c8e..d5d8529f 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -787,10 +787,9 @@ void CL_SetInfo (int pnum, char *key, char *value); void CL_BeginServerConnect(int port); char *CL_TryingToConnect(void); -#define MAX_VISEDICTS 1024 +#define MAX_VISEDICTS 2048 extern int cl_numvisedicts; -extern entity_t *cl_visedicts; -extern entity_t cl_visedicts_list[MAX_VISEDICTS]; +extern entity_t cl_visedicts[]; /*these are for q3 really*/ typedef struct { @@ -924,7 +923,7 @@ int CL_CalcNet (void); void CL_ClearParseState(void); void CL_DumpPacket(void); void CL_ParseEstablished(void); -void CL_ParseServerMessage (void); +void CLQW_ParseServerMessage (void); void CLNQ_ParseServerMessage (void); #ifdef Q2CLIENT void CLQ2_ParseServerMessage (void); @@ -1031,6 +1030,7 @@ char *CG_GetConfigString(int num); //pr_csqc.c // #ifdef CSQC_DAT +qboolean CSQC_Inited(void); qboolean CSQC_Init (unsigned int checksum); void CSQC_RegisterCvarsAndThings(void); qboolean CSQC_DrawView(void); @@ -1046,6 +1046,7 @@ qboolean CSQC_ParseTempEntity(unsigned char firstbyte); qboolean CSQC_ConsoleCommand(char *cmd); qboolean CSQC_KeyPress(int key, int unicode, qboolean down); qboolean CSQC_MouseMove(float xdelta, float ydelta); +qboolean CSQC_MousePosition(float xabs, float yabs); int CSQC_StartSound(int entnum, int channel, char *soundname, vec3_t pos, float vol, float attenuation); void CSQC_ParseEntities(void); qboolean CSQC_SettingListener(void); diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 0a4b3f17..de898357 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1912,9 +1912,6 @@ void CLQ2_AddEntities (void) r_refdef.currentplayernum = 0; - - cl_visedicts = cl_visedicts_list; - cl_numvisedicts = 0; cl_numstrisidx = 0; cl_numstrisvert = 0; diff --git a/engine/client/in_win.c b/engine/client/in_win.c index 81babfb2..040a40b3 100644 --- a/engine/client/in_win.c +++ b/engine/client/in_win.c @@ -1328,16 +1328,23 @@ static void ProcessMouse(mouse_t *mouse, float *movements, int pnum) mousecursor_y = vid.height - 1; mx=my=0; } -#ifdef VM_UI else { +#ifdef VM_UI if (UI_MousePosition(mx, my)) { mx = 0; my = 0; } - } #endif +#ifdef PEXT_CSQC + if (CSQC_MousePosition(mx, my)) + { + mx = 0; + my = 0; + } +#endif + } #ifdef PEXT_CSQC if (mx || my) diff --git a/engine/client/merged.h b/engine/client/merged.h index 8bf106c1..431ff8cc 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -167,6 +167,7 @@ typedef enum backendmode_e BEM_DEPTHONLY, //just a quick depth pass. textures used only for alpha test (shadowmaps). BEM_STENCIL, //used for drawing shadow volumes to the stencil buffer. BEM_DEPTHDARK, //a quick depth pass. textures used only for alpha test. additive textures still shown as normal. + BEM_DEPTHNORM, //all opaque stuff drawn using 'depthnorm' shader BEM_LIGHT, //we have a valid light BEM_SMAPLIGHTSPOT, //we have a spot light using a shadowmap BEM_SMAPLIGHT, //we have a light using a shadowmap diff --git a/engine/client/p_classic.c b/engine/client/p_classic.c index 80f48882..e681c50c 100644 --- a/engine/client/p_classic.c +++ b/engine/client/p_classic.c @@ -634,6 +634,7 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef goto done; VectorScale(delta, 1 / len, dir); //unit vector in direction of trail + VectorMA(point, -leftover, dir, point); len += leftover; rlen = len; @@ -647,16 +648,12 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef scale = 3; break; } - leftover = scale - leftover; - VectorMA(point, leftover, delta, point); + VectorScale (dir, scale, dir); len /= scale; leftover = rlen - ((int)(len) * scale); - if (!(num_particles = (int) len)) - goto done; - - VectorScale (delta, scale, delta); + num_particles = (int) len; for (i = 0; i < num_particles && free_particles; i++) { @@ -735,7 +732,7 @@ static float Classic_ParticleTrail (vec3_t start, vec3_t end, float leftover, ef p->org[j] = point[j] + ((rand() % 6) - 3); break; } - VectorAdd (point, delta, point); + VectorAdd (point, dir, point); } done: return leftover; diff --git a/engine/client/p_script.c b/engine/client/p_script.c index 8cb2a55e..0e73744d 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -276,8 +276,6 @@ typedef struct part_type_s { #define PS_INRUNLIST 0x1 // particle type is currently in execution list } part_type_t; -static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, particle_t **,plooks_t*), void (*sparklineparticles)(int count, particle_t **,plooks_t*), void (*sparkfanparticles)(int count, particle_t **,plooks_t*), void (*sparktexturedparticles)(int count, particle_t **,plooks_t*), void (*beamparticles)(int count, beamseg_t**,plooks_t*), void (*drawdecalparticles)(int count, clippeddecal_t**,plooks_t*)); - #ifndef TYPESONLY //triangle fan sparks use these. // defined but not used @@ -3972,8 +3970,12 @@ static void GL_DrawClippedDecal(int count, clippeddecal_t **dlist, plooks_t *typ } } -static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, particle_t **,plooks_t*), void (*sparklineparticles)(int count, particle_t **,plooks_t*), void (*sparkfanparticles)(int count, particle_t **,plooks_t*), void (*sparktexturedparticles)(int count, particle_t **,plooks_t*), void (*beamparticles)(int count, beamseg_t**,plooks_t*), void (*drawdecalparticles)(int count, clippeddecal_t**,plooks_t*)) +static void PScript_DrawParticleTypes (void) { + void (*sparklineparticles)(int count, particle_t **,plooks_t*)=GL_DrawLineSparkParticle; + void (*sparkfanparticles)(int count, particle_t **,plooks_t*)=GL_DrawTrifanParticle; + void (*sparktexturedparticles)(int count, particle_t **,plooks_t*)=GL_DrawTexturedSparkParticle; + qboolean (*tr) (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal); void *pdraw, *bdraw; @@ -4031,11 +4033,6 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part kill_list = kill_first = NULL; - if (r_part_beams.ival < 0) - beamparticles = NULL; - else if (!r_part_beams.ival) - beamparticles = NULL; - if (r_part_sparks_textured.ival < 0) sparktexturedparticles = NULL; else if (!r_part_sparks_textured.ival) @@ -4113,7 +4110,7 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part d->rgba[3] += pframetime*type->alphachange; } - drawdecalparticles(1, &d, &type->looks); + GL_DrawClippedDecal(1, &d, &type->looks); } } @@ -4125,12 +4122,15 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part switch(type->looks.type) { case PT_BEAM: - bdraw = beamparticles; + if (r_part_beams.ival <= 0) + bdraw = NULL; + else + bdraw = GL_DrawParticleBeam; break; case PT_DECAL: break; case PT_NORMAL: - pdraw = texturedparticles; + pdraw = GL_DrawTexturedParticle; break; case PT_SPARK: pdraw = sparklineparticles; @@ -4532,7 +4532,7 @@ static void PScript_DrawParticles (void) { P_AddRainParticles(); - PScript_DrawParticleTypes(GL_DrawTexturedParticle, GL_DrawLineSparkParticle, GL_DrawTrifanParticle, GL_DrawTexturedSparkParticle, GL_DrawParticleBeam, GL_DrawClippedDecal); + PScript_DrawParticleTypes(); if (fallback) fallback->DrawParticles(); diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index f63ce895..53a1261f 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -53,7 +53,7 @@ static qboolean csqc_isdarkplaces; static char csqc_printbuffer[8192]; #define CSQCPROGSGROUP "CSQC progs control" -cvar_t pr_csqc_maxedicts = CVAR("pr_csqc_maxedicts", "3072"); //not tied to protocol nor server. +cvar_t pr_csqc_maxedicts = CVAR("pr_csqc_maxedicts", "8192"); //not tied to protocol nor server. cvar_t pr_csqc_memsize = CVAR("pr_csqc_memsize", "-1"); cvar_t cl_csqcdebug = CVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...) cvar_t cl_nocsqc = CVAR("cl_nocsqc", "0"); @@ -287,6 +287,13 @@ static void CSQC_FindGlobals(void) CSQC_ChangeLocalPlayer(0); + 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.frametime = csqcg.frametime; + csqc_world.g.newmis = (int*)PR_FindGlobal(csqcprogs, "newmis", 0, NULL); + csqc_world.g.time = csqcg.svtime; + if (csqcg.maxclients) *csqcg.maxclients = cl.allocated_client_slots; } @@ -333,6 +340,7 @@ static void QCBUILTIN PF_cs_gettime (progfuncs_t *prinst, struct globalvars_s *p \ comfieldfloat(drawmask); /*So that the qc can specify all rockets at once or all bannanas at once*/ \ comfieldfunction(predraw); /*If present, is called just before it's drawn.*/ \ + comfieldvector(glowmod); \ \ comfieldfloat(ideal_pitch);\ comfieldfloat(pitch_speed);\ @@ -696,15 +704,10 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) AngleVectors(out->angles, out->axis[0], out->axis[1], out->axis[2]); VectorInverse(out->axis[1]); - if (!in->xv->scale || in->xv->scale == 1.0f) + if (!in->xv->scale) out->scale = 1; else - { - VectorScale(out->axis[0], in->xv->scale, out->axis[0]); - VectorScale(out->axis[1], in->xv->scale, out->axis[1]); - VectorScale(out->axis[2], in->xv->scale, out->axis[2]); out->scale = in->xv->scale; - } } ival = in->v->colormap; @@ -714,9 +717,18 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) } // TODO: DP COLORMAP extension? - out->shaderRGBAf[0] = 1; - out->shaderRGBAf[1] = 1; - out->shaderRGBAf[2] = 1; + if (!in->xv->colormod[0] && !in->xv->colormod[1] && !in->xv->colormod[2]) + { + out->shaderRGBAf[0] = 1; + out->shaderRGBAf[1] = 1; + out->shaderRGBAf[2] = 1; + } + else + { + out->shaderRGBAf[0] = in->xv->colormod[0]; + out->shaderRGBAf[1] = in->xv->colormod[1]; + out->shaderRGBAf[2] = in->xv->colormod[2]; + } if (!in->xv->alpha || in->xv->alpha == 1) { out->shaderRGBAf[3] = 1.0f; @@ -727,6 +739,8 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) out->shaderRGBAf[3] = in->xv->alpha; } + VectorCopy(in->xv->glowmod, out->glowmod); + out->skinnum = in->v->skin; out->fatness = in->xv->fatness; ival = in->xv->forceshader; @@ -5116,14 +5130,17 @@ pbool CSQC_EntFree (struct edict_s *e) { struct csqcedict_s *ent = (csqcedict_t*)e; ent->v->solid = SOLID_NOT; - ent->xv->drawmask = 0; + ent->v->movetype = 0; ent->v->modelindex = 0; ent->v->think = 0; ent->v->nextthink = 0; + ent->xv->predraw = 0; + ent->xv->drawmask = 0; + ent->xv->renderflags = 0; #ifdef USEODE - World_Physics_RemoveFromEntity(&csqc_world, (wedict_t*)ent); - World_Physics_RemoveJointFromEntity(&csqc_world, (wedict_t*)ent); + World_ODE_RemoveFromEntity(&csqc_world, (wedict_t*)ent); + World_ODE_RemoveJointFromEntity(&csqc_world, (wedict_t*)ent); #endif return true; @@ -5143,6 +5160,14 @@ void CSQC_Event_Touch(world_t *w, wedict_t *s, wedict_t *o) *csqcg.other = oother; } +void CSQC_Event_Think(world_t *w, wedict_t *s) +{ + *csqcg.self = EDICT_TO_PROG(w->progs, (edict_t*)s); + *csqcg.other = EDICT_TO_PROG(w->progs, (edict_t*)w->edicts); + + PR_ExecuteProgram (w->progs, s->v->think); +} + model_t *CSQC_World_ModelForIndex(world_t *w, int modelindex) { return CSQC_GetModelForIndex(modelindex); @@ -5162,7 +5187,7 @@ void CSQC_Shutdown(void) csqcprogs = NULL; #ifdef USEODE - World_Physics_End(&csqc_world); + World_ODE_End(&csqc_world); #endif Z_Free(csqcdelta_pack_new.e); @@ -5291,6 +5316,13 @@ int CSQC_PRFileSize (const char *path) return COM_FileSize(path); } +qboolean CSQC_Inited(void) +{ + if (csqcprogs) + return true; + return false; +} + double csqctime; qboolean CSQC_Init (unsigned int checksum) { @@ -5373,6 +5405,7 @@ qboolean CSQC_Init (unsigned int checksum) PR_Configure(csqcprogs, pr_csqc_memsize.ival, 16); 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; World_ClearWorld(&csqc_world); CSQC_InitFields(); //let the qclib know the field order that the engine needs. @@ -5462,7 +5495,7 @@ void CSQC_WorldLoaded(void) csqc_world.worldmodel = cl.worldmodel; #ifdef USEODE - World_Physics_Start(&csqc_world); + World_ODE_Start(&csqc_world); #endif worldent = (csqcedict_t *)EDICT_NUM(csqcprogs, 0); @@ -5689,7 +5722,9 @@ qboolean CSQC_DrawView(void) ft = mintic; csqc_world.physicstime += ft; - World_Physics_Frame(&csqc_world, ft, 800); + World_ODE_Frame(&csqc_world, ft, 800); + + //World_Physics_Frame(&csqc_world); } #else csqc_world.physicstime = cl.servertime; @@ -5749,6 +5784,22 @@ qboolean CSQC_KeyPress(int key, int unicode, qboolean down) return G_FLOAT(OFS_RETURN); } +qboolean CSQC_MousePosition(float xabs, float yabs) +{ + void *pr_globals; + + if (!csqcprogs || !csqcg.input_event) + return false; + + pr_globals = PR_globals(csqcprogs, PR_CURRENT); + G_FLOAT(OFS_PARM0) = 3; + G_FLOAT(OFS_PARM1) = xabs; + G_FLOAT(OFS_PARM2) = yabs; + + PR_ExecuteProgram (csqcprogs, csqcg.input_event); + + return G_FLOAT(OFS_RETURN); +} qboolean CSQC_MouseMove(float xdelta, float ydelta) { void *pr_globals; @@ -6030,7 +6081,7 @@ void CSQC_ParseEntities(void) if (!csqcprogs) Host_EndGame("CSQC needs to be initialized for this server.\n"); - if (!csqcg.ent_update || !csqcg.self) + if (!csqcg.ent_update || !csqcg.self || !csqc_world.worldmodel || csqc_world.worldmodel->needload) Host_EndGame("CSQC is unable to parse entities\n"); pr_globals = PR_globals(csqcprogs, PR_CURRENT); diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index e7992db7..742a5fdd 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -395,35 +395,30 @@ void QCBUILTIN PF_CL_drawcolouredstring (progfuncs_t *prinst, struct globalvars_ void QCBUILTIN PF_CL_stringwidth(progfuncs_t *prinst, struct globalvars_s *pr_globals) { + conchar_t buffer[2048], *end; + float px, py; char *text = PR_GetStringOfs(prinst, OFS_PARM0); int usecolours = G_FLOAT(OFS_PARM1); float fontsize; if (*prinst->callargc > 2) - fontsize = G_FLOAT(OFS_PARM2); + fontsize = G_FLOAT(OFS_PARM2+1); else - fontsize = 1; + fontsize = 8; if (mp_globs.drawfontscale) fontsize *= mp_globs.drawfontscale[1]; - if (usecolours) - { - conchar_t buffer[2048], *end; - float px, py; - end = COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), false); - Font_BeginScaledString(font_conchar, 0, 0, &px, &py); - px = Font_LineWidth(buffer, end); - Font_EndString(font_conchar); + end = COM_ParseFunString(CON_WHITEMASK, text, buffer, sizeof(buffer), !usecolours); - if (mp_globs.drawfontscale) - px *= mp_globs.drawfontscale[1]; + Font_BeginScaledString(font_conchar, 0, 0, &px, &py); + fontsize /= Font_CharHeight(); + px = Font_LineWidth(buffer, end); + Font_EndString(font_conchar); - G_FLOAT(OFS_RETURN) = px; - } - else - { - G_FLOAT(OFS_RETURN) = strlen(text)*fontsize; - } + if (mp_globs.drawfontscale) + px *= mp_globs.drawfontscale[1]; + + G_FLOAT(OFS_RETURN) = px * fontsize; } #define DRAWFLAG_NORMAL 0 @@ -442,7 +437,7 @@ static unsigned int PF_SelectDPDrawFlag(int flag) if (flag == 1) return BEF_FORCEADDITIVE; else - return BEF_FORCETRANSPARENT; + return 0; } //float drawpic(vector position, string pic, vector size, vector rgb, float alpha, float flag) = #456; diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index aa4b01ec..9cecb515 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -2447,7 +2447,10 @@ static void Surf_CreateSurfaceLightmap (msurface_t *surf, int shift) } if (currentmodel->fromgame == fg_quake3) + { Surf_LM_FillBlock(surf->lightmaptexturenum, smax, tmax, surf->light_s, surf->light_t); + return; + } else surf->lightmaptexturenum = Surf_LM_AllocBlock (smax, tmax, &surf->light_s, &surf->light_t, surf->texinfo->texture->shader); base = lightmap[surf->lightmaptexturenum]->lightmaps; diff --git a/engine/client/render.h b/engine/client/render.h index a9ce0993..e33843b5 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -83,11 +83,12 @@ typedef struct entity_s vec3_t angles; vec3_t axis[3]; - vec4_t shaderRGBAf; - float shaderTime; + vec4_t shaderRGBAf; /*colormod+alpha, available for shaders to mix*/ + float shaderTime; /*timestamp, for syncing shader times to spawns*/ + vec3_t glowmod; /*meant to be a multiplier for the fullbrights*/ - int light_known; - vec3_t light_avg; /*midpoint level*/ + int light_known; /*bsp lighting has been caled*/ + vec3_t light_avg; /*midpoint level*/ vec3_t light_range; /*avg + this = max, avg - this = min*/ vec3_t light_dir; @@ -435,13 +436,14 @@ extern cvar_t r_netgraph; extern cvar_t r_xflip; #endif +extern cvar_t r_lightprepass; extern cvar_t gl_maxdist; extern cvar_t r_clear; extern cvar_t gl_poly; extern cvar_t gl_affinemodels; extern cvar_t gl_nohwblend; extern cvar_t gl_reporttjunctions; -extern cvar_t r_flashblend; +extern cvar_t r_flashblend, r_flashblendscale; extern cvar_t r_lightstylesmooth; extern cvar_t r_lightstylesmooth_limit; extern cvar_t r_lightstylespeed; diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 74634df6..28c9fa56 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -2,6 +2,7 @@ #include "winquake.h" #include "pr_common.h" #include "gl_draw.h" +#include "shader.h" #include @@ -89,6 +90,8 @@ cvar_t r_skin_overlays = SCVARF ("r_skin_overlays", "1", CVAR_SEMICHEAT|CVAR_RENDERERLATCH); cvar_t r_flashblend = SCVARF ("gl_flashblend", "0", CVAR_ARCHIVE); +cvar_t r_flashblendscale = SCVARF ("gl_flashblendscale", "0.35", + CVAR_ARCHIVE); cvar_t r_floorcolour = SCVARF ("r_floorcolour", "255 255 255", CVAR_RENDERERCALLBACK|CVAR_SHADERSYSTEM); cvar_t r_floortexture = SCVARF ("r_floortexture", "", @@ -295,6 +298,7 @@ cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", CVAR_ARCHIVE); cvar_t r_shadows = SCVARF ("r_shadows", "0", CVAR_ARCHIVE); +cvar_t r_lightprepass = CVARFD("r_lightprepass", "0", CVAR_SHADERSYSTEM, "Experimental. Attempt to use a different lighting mechanism."); cvar_t r_shadow_bumpscale_basetexture = SCVAR ("r_shadow_bumpscale_basetexture", "4"); cvar_t r_shadow_bumpscale_bumpmap = SCVAR ("r_shadow_bumpscale_bumpmap", "10"); @@ -352,6 +356,7 @@ 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); @@ -483,6 +488,8 @@ void Renderer_Init(void) Cmd_AddCommand("setrenderer", R_SetRenderer_f); Cmd_AddCommand("vid_restart", R_RestartRenderer_f); + Cmd_AddCommand("r_dumpshaders", Shader_WriteOutGenerics_f); + #if defined(GLQUAKE) || defined(D3DQUAKE) GLD3DRenderer_Init(); #endif @@ -531,6 +538,7 @@ void Renderer_Init(void) Cvar_Register(&r_stains, GRAPHICALNICETIES); Cvar_Register(&r_stainfadetime, GRAPHICALNICETIES); Cvar_Register(&r_stainfadeammount, GRAPHICALNICETIES); + Cvar_Register(&r_lightprepass, GRAPHICALNICETIES); Cvar_Register(&scr_viewsize, SCREENOPTIONS); Cvar_Register(&scr_fov, SCREENOPTIONS); diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index 9875fb67..6d45c2a9 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -639,7 +639,9 @@ static int SNDDMA_Init(soundcardinfo_t *sc, int *cardnum, int *drivernum) memset(sc, 0, sizeof(*sc)); // set requested rate - if (!snd_khz.ival) + if (snd_khz.ival >= 1000) + sc->sn.speed = snd_khz.ival; + else if (snd_khz.ival <= 0) sc->sn.speed = 22050; /* else if (snd_khz.ival >= 195) sc->sn.speed = 200000; @@ -1064,10 +1066,14 @@ void S_Init (void) } p = COM_CheckParm ("-soundspeed"); + if (!p) + p = COM_CheckParm ("-sspeed"); + if (!p) + p = COM_CheckParm ("-sndspeed"); if (p) { if (p < com_argc-1) - Cvar_SetValue(&snd_khz, atof(com_argv[p+1])/1000); + Cvar_SetValue(&snd_khz, atof(com_argv[p+1])); else Sys_Error ("S_Init: you must specify a speed in KB after -soundspeed"); } diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 26e51290..49397a6d 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -215,6 +215,7 @@ static void GenMatrixPosQuat4Scale(vec3_t pos, vec4_t quat, vec3_t scale, float { float xx, xy, xz, xw, yy, yz, yw, zz, zw; float x2, y2, z2; + float s; x2 = quat[0] + quat[0]; y2 = quat[1] + quat[1]; z2 = quat[2] + quat[2]; @@ -223,17 +224,20 @@ static void GenMatrixPosQuat4Scale(vec3_t pos, vec4_t quat, vec3_t scale, float yy = quat[1] * y2; yz = quat[1] * z2; zz = quat[2] * z2; xw = quat[3] * x2; yw = quat[3] * y2; zw = quat[3] * z2; - result[0*4+0] = 1.0f - (yy + zz); - result[1*4+0] = xy + zw; - result[2*4+0] = xz - yw; + s = scale[0]; + result[0*4+0] = s*(1.0f - (yy + zz)); + result[1*4+0] = s*(xy + zw); + result[2*4+0] = s*(xz - yw); - result[0*4+1] = xy - zw; - result[1*4+1] = 1.0f - (xx + zz); - result[2*4+1] = yz + xw; + s = scale[1]; + result[0*4+1] = s*(xy - zw); + result[1*4+1] = s*(1.0f - (xx + zz)); + result[2*4+1] = s*(yz + xw); - result[0*4+2] = xz + yw; - result[1*4+2] = yz - xw; - result[2*4+2] = 1.0f - (xx + yy); + s = scale[2]; + result[0*4+2] = s*(xz + yw); + result[1*4+2] = s*(yz - xw); + result[2*4+2] = s*(1.0f - (xx + yy)); result[0*4+3] = pos[0]; result[1*4+3] = pos[1]; @@ -727,6 +731,7 @@ static int Alias_BuildLerps(float plerp[4], float *pose[4], int numbones, galias frame1=(frame1>g1->numposes-1)?g1->numposes-1:frame1; frame2=(frame2>g1->numposes-1)?g1->numposes-1:frame2; } + if (frame1 == frame2) mlerp = 0; plerp[l] = (1-mlerp)*(1-lerpfrac); @@ -1468,7 +1473,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent { meshcache.usebonepose = Alias_GetBonePositions(inf, &e->framestate, meshcache.bonepose, MAX_BONES); - if (1)//e->fatness || !inf->ofs_skel_idx || !usebones) + if (e->fatness || !inf->ofs_skel_idx || !usebones) { Alias_BuildSkeletalMesh(mesh, meshcache.usebonepose, inf); @@ -1487,7 +1492,9 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, int surfnum, ent #ifdef GLQUAKE if (!inf->numswtransforms && qrenderer == QR_OPENGL) + { Alias_GLDrawSkeletalBones((galiasbone_t*)((char*)inf + inf->ofsbones), (float *)meshcache.usebonepose, inf->numbones); + } #endif meshcache.usebonepose = NULL; } @@ -3789,6 +3796,7 @@ qboolean Mod_LoadQ3Model(model_t *mod, void *buffer) galias->groups = LittleLong(header->numFrames); galias->numverts = LittleLong(surf->numVerts); galias->numindexes = LittleLong(surf->numTriangles)*3; + galias->shares_verts = s; if (parent) parent->nextsurf = (qbyte *)galias - (qbyte *)parent; else @@ -4931,7 +4939,7 @@ qboolean Mod_LoadPSKModel(model_t *mod, void *buffer) gmdl[i].numindexes = 0; for (j = 0; j < num_face; j++) { - if (face[j].mattindex == i) + if (face[j].mattindex%num_matt == i) { indexes[gmdl[i].numindexes+0] = face[j].vtxwindex[0]; indexes[gmdl[i].numindexes+1] = face[j].vtxwindex[1]; @@ -5525,6 +5533,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) vec4_t *oweight; byte_vec4_t *oindex; float *opose; + vec2_t *otcoords; galiasinfo_t *gai; @@ -5601,13 +5610,14 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) sizeof(*skin)*h->num_meshes + sizeof(*texnum)*h->num_meshes + #endif sizeof(*fgroup)*h->num_anims + sizeof(float)*12*h->num_poses*h->num_frames + sizeof(*bones)*h->num_joints + - (sizeof(*opos) + sizeof(*onorm) + sizeof(*oweight) + sizeof(*oindex)) * h->num_vertexes); + (sizeof(*opos) + sizeof(*onorm) + sizeof(*oweight) + sizeof(*otcoords) + sizeof(*oindex)) * h->num_vertexes); bones = (galiasbone_t*)(gai + h->num_meshes); opos = (vecV_t*)(bones + h->num_joints); onorm = (vec3_t*)(opos + h->num_vertexes); oindex = (byte_vec4_t*)(onorm + h->num_vertexes); oweight = (vec4_t*)(oindex + h->num_vertexes); - fgroup = (galiasgroup_t*)(oweight + h->num_vertexes); + otcoords = (vec2_t*)(oweight + h->num_vertexes); + fgroup = (galiasgroup_t*)(otcoords + h->num_vertexes); opose = (float*)(fgroup + h->num_anims); #ifndef SERVERONLY skin = (galiasskin_t*)(opose + 12*h->num_poses*h->num_frames); @@ -5625,6 +5635,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) vec3_t pos; vec4_t quat; vec3_t scale; + float mat[12], mat2[12]; for (i = 0; i < h->num_joints; i++) { @@ -5632,25 +5643,42 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) bones[i].parent = ijoint[i].parent; GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); + + Matrix3x4_Invert(&basepose[i*12], &invbasepose[12*i]); + if (ijoint[i].parent >= 0) + { + Matrix3x4_Multiply(&basepose[i*12], &basepose[ijoint[i].parent*12], mat); + memcpy(&basepose[i*12], mat, sizeof(mat)); + Matrix3x4_Multiply(&invbasepose[ijoint[i].parent*12], &invbasepose[i*12], mat); + memcpy(&invbasepose[i*12], mat, sizeof(mat)); + } } for (i = 0; i < h->num_frames; i++) { for (j = 0, p = ipose; j < h->num_poses; j++, p++) { - pos[0] = p->channeloffset[0]; if (p->mask & 1) pos[0] += *framedata++ + p->channelscale[0]; - pos[1] = p->channeloffset[1]; if (p->mask & 2) pos[1] += *framedata++ + p->channelscale[1]; - pos[2] = p->channeloffset[2]; if (p->mask & 4) pos[2] += *framedata++ + p->channelscale[2]; - quat[0] = p->channeloffset[3]; if (p->mask & 8) quat[0] += *framedata++ + p->channelscale[3]; - quat[1] = p->channeloffset[4]; if (p->mask & 16) quat[1] += *framedata++ + p->channelscale[4]; - quat[2] = p->channeloffset[5]; if (p->mask & 32) quat[2] += *framedata++ + p->channelscale[5]; - scale[0] = p->channeloffset[6]; if (p->mask & 64) scale[0] += *framedata++ + p->channelscale[6]; - scale[1] = p->channeloffset[7]; if (p->mask & 128) scale[1] += *framedata++ + p->channelscale[7]; - scale[2] = p->channeloffset[8]; if (p->mask & 256) scale[2] += *framedata++ + p->channelscale[8]; + pos[0] = p->channeloffset[0]; if (p->mask & 1) pos[0] += *framedata++ * p->channelscale[0]; + pos[1] = p->channeloffset[1]; if (p->mask & 2) pos[1] += *framedata++ * p->channelscale[1]; + pos[2] = p->channeloffset[2]; if (p->mask & 4) pos[2] += *framedata++ * p->channelscale[2]; + quat[0] = p->channeloffset[3]; if (p->mask & 8) quat[0] += *framedata++ * p->channelscale[3]; + quat[1] = p->channeloffset[4]; if (p->mask & 16) quat[1] += *framedata++ * p->channelscale[4]; + quat[2] = p->channeloffset[5]; if (p->mask & 32) quat[2] += *framedata++ * p->channelscale[5]; + scale[0] = p->channeloffset[6]; if (p->mask & 64) scale[0] += *framedata++ * p->channelscale[6]; + scale[1] = p->channeloffset[7]; if (p->mask & 128) scale[1] += *framedata++ * p->channelscale[7]; + scale[2] = p->channeloffset[8]; if (p->mask & 256) scale[2] += *framedata++ * p->channelscale[8]; quat[3] = -sqrt(max(1.0 - pow(VectorLength(quat),2), 0.0)); GenMatrixPosQuat4Scale(pos, quat, scale, opose + (i*h->num_poses+j)*12); + + if (ijoint[j].parent >= 0) + { + Matrix3x4_Multiply(mat, &basepose[ijoint[j].parent*12], mat2); + Matrix3x4_Multiply(&invbasepose[j*12], mat2, &opose[(i*h->num_poses+j)*12]); + } + else + Matrix3x4_Multiply(&invbasepose[j*12], mat, &opose[(i*h->num_poses+j)*12]); } } } @@ -5661,7 +5689,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) vec3_t pos; vec4_t quat; vec3_t scale; - float mat[12]; + float mat[12], mat2[12]; for (i = 0; i < h->num_joints; i++) { @@ -5670,31 +5698,44 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) GenMatrixPosQuat4Scale(ijoint[i].translate, ijoint[i].rotate, ijoint[i].scale, &basepose[i*12]); -// Mod_Skel_Invert(bones, basepose, h->num_joints, invbonepose); + Matrix3x4_Invert(&basepose[i*12], &invbasepose[12*i]); + if (ijoint[i].parent >= 0) + { + Matrix3x4_Multiply(&basepose[i*12], &basepose[ijoint[i].parent*12], mat); + memcpy(&basepose[i*12], mat, sizeof(mat)); + Matrix3x4_Multiply(&invbasepose[ijoint[i].parent*12], &invbasepose[i*12], mat); + memcpy(&invbasepose[i*12], mat, sizeof(mat)); + } } for (i = 0; i < h->num_frames; i++) { for (j = 0, p = ipose; j < h->num_poses; j++, p++) { - pos[0] = p->channeloffset[0]; if (p->mask & 1) pos[0] += *framedata++ + p->channelscale[0]; - pos[1] = p->channeloffset[1]; if (p->mask & 2) pos[1] += *framedata++ + p->channelscale[1]; - pos[2] = p->channeloffset[2]; if (p->mask & 4) pos[2] += *framedata++ + p->channelscale[2]; - quat[0] = p->channeloffset[3]; if (p->mask & 8) quat[0] += *framedata++ + p->channelscale[3]; - quat[1] = p->channeloffset[4]; if (p->mask & 16) quat[1] += *framedata++ + p->channelscale[4]; - quat[2] = p->channeloffset[5]; if (p->mask & 32) quat[2] += *framedata++ + p->channelscale[5]; - quat[3] = p->channeloffset[6]; if (p->mask & 64) quat[3] += *framedata++ + p->channelscale[6]; - scale[0] = p->channeloffset[7]; if (p->mask & 128) scale[0] += *framedata++ + p->channelscale[7]; - scale[1] = p->channeloffset[8]; if (p->mask & 256) scale[1] += *framedata++ + p->channelscale[8]; - scale[2] = p->channeloffset[9]; if (p->mask & 512) scale[2] += *framedata++ + p->channelscale[9]; + pos[0] = p->channeloffset[0]; if (p->mask & 1) pos[0] += *framedata++ * p->channelscale[0]; + pos[1] = p->channeloffset[1]; if (p->mask & 2) pos[1] += *framedata++ * p->channelscale[1]; + pos[2] = p->channeloffset[2]; if (p->mask & 4) pos[2] += *framedata++ * p->channelscale[2]; + quat[0] = p->channeloffset[3]; if (p->mask & 8) quat[0] += *framedata++ * p->channelscale[3]; + quat[1] = p->channeloffset[4]; if (p->mask & 16) quat[1] += *framedata++ * p->channelscale[4]; + quat[2] = p->channeloffset[5]; if (p->mask & 32) quat[2] += *framedata++ * p->channelscale[5]; + quat[3] = p->channeloffset[6]; if (p->mask & 64) quat[3] += *framedata++ * p->channelscale[6]; + scale[0] = p->channeloffset[7]; if (p->mask & 128) scale[0] += *framedata++ * p->channelscale[7]; + scale[1] = p->channeloffset[8]; if (p->mask & 256) scale[1] += *framedata++ * p->channelscale[8]; + scale[2] = p->channeloffset[9]; if (p->mask & 512) scale[2] += *framedata++ * p->channelscale[9]; - GenMatrixPosQuat4Scale(pos, quat, scale, &opose[(i*h->num_poses+j)*12]); + GenMatrixPosQuat4Scale(pos, quat, scale, mat); + + if (ijoint[j].parent >= 0) + { + Matrix3x4_Multiply(mat, &basepose[ijoint[j].parent*12], mat2); + Matrix3x4_Multiply(&invbasepose[j*12], mat2, &opose[(i*h->num_poses+j)*12]); + } + else + Matrix3x4_Multiply(&invbasepose[j*12], mat, &opose[(i*h->num_poses+j)*12]); } } } -// Mod_Skel_PreSkin(basepose, invbonepose - /*load the framegroup info*/ anim = (struct iqmanim*)(buffer + h->ofs_anims); for (i = 0; i < h->num_anims; i++) @@ -5715,7 +5756,7 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) gai[i].shares_bones = 0; gai[i].numbones = h->num_joints; gai[i].ofsbones = (char*)bones - (char*)&gai[i]; - gai[i].groups = h->num_frames; + gai[i].groups = h->num_anims; gai[i].groupofs = (char*)fgroup - (char*)&gai[i]; #ifndef SERVERONLY @@ -5730,6 +5771,9 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) skin[i].texnums = 1; skin[i].ofstexnums = (char*)&texnum[i] - (char*)&skin[i]; texnum[i].shader = R_RegisterSkin(skin[i].name, mod->name); + R_BuildDefaultTexnums(&texnum[i], texnum[i].shader); + if (texnum[i].shader->flags & SHADER_NOIMAGE) + Con_Printf("Unable to load texture for shader \"%s\" for model \"%s\"\n", texnum[i].shader->name, loadmodel->name); #endif offset = LittleLong(mesh[i].first_vertex); @@ -5742,11 +5786,12 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) gai[i].ofs_indexes = (char*)idx - (char*)&gai[i]; for (t = 0; t < nt; t++) { - *idx++ = LittleShort(tris[t].vertex[0]); - *idx++ = LittleShort(tris[t].vertex[1]); - *idx++ = LittleShort(tris[t].vertex[2]); + *idx++ = LittleShort(tris[t].vertex[0]) - offset; + *idx++ = LittleShort(tris[t].vertex[1]) - offset; + *idx++ = LittleShort(tris[t].vertex[2]) - offset; } + gai[i].ofs_st_array = (char*)(otcoords+offset) - (char*)&gai[i]; /*verts*/ gai[i].shares_verts = i; gai[i].numverts = LittleLong(mesh[i].num_vertexes); @@ -5759,10 +5804,11 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer) } for (i = 0; i < h->num_vertexes; i++) { + Vector2Copy(tcoord+i*2, otcoords[i]); VectorCopy(vpos+i*3, opos[i]); VectorCopy(vnorm+i*4, onorm[i]); - VectorCopy(vbone+i*4, oindex[i]); - VectorCopy(vweight+i*4, oweight[i]); + Vector4Copy(vbone+i*4, oindex[i]); + Vector4Scale(vweight+i*4, 1/255.0, oweight[i]); } return gai; } diff --git a/engine/common/com_phys_ode.c b/engine/common/com_phys_ode.c index 2af2301d..e6d1ded4 100644 --- a/engine/common/com_phys_ode.c +++ b/engine/common/com_phys_ode.c @@ -1162,7 +1162,7 @@ static dllfunction_t odefuncs[] = dllhandle_t ode_dll = NULL; #endif -void World_Physics_Init(void) +void World_ODE_Init(void) { #ifdef ODE_DYNAMIC const char* dllname = @@ -1230,7 +1230,7 @@ void World_Physics_Init(void) #endif } -void World_Physics_Shutdown(void) +void World_ODE_Shutdown(void) { #ifdef ODE_DYNAMIC if (ode_dll) @@ -1244,7 +1244,7 @@ void World_Physics_Shutdown(void) } } -static void World_Physics_EnableODE(world_t *world) +static void World_ODE_Enable(world_t *world) { dVector3 center, extents; if (world->ode.ode) @@ -1271,14 +1271,14 @@ static void World_Physics_EnableODE(world_t *world) // dWorldSetAutoDisableFlag (world->ode.ode_world, true); } -void World_Physics_Start(world_t *world) +void World_ODE_Start(world_t *world) { if (world->ode.ode) return; - World_Physics_EnableODE(world); + World_ODE_Enable(world); } -void World_Physics_End(world_t *world) +void World_ODE_End(world_t *world) { if (world->ode.ode) { @@ -1289,7 +1289,7 @@ void World_Physics_End(world_t *world) } } -void World_Physics_RemoveJointFromEntity(world_t *world, wedict_t *ed) +void World_ODE_RemoveJointFromEntity(world_t *world, wedict_t *ed) { ed->ode.ode_joint_type = 0; if(ed->ode.ode_joint) @@ -1297,7 +1297,7 @@ void World_Physics_RemoveJointFromEntity(world_t *world, wedict_t *ed) ed->ode.ode_joint = NULL; } -void World_Physics_RemoveFromEntity(world_t *world, wedict_t *ed) +void World_ODE_RemoveFromEntity(world_t *world, wedict_t *ed) { if (!ed->ode.ode_physics) return; @@ -1347,7 +1347,7 @@ void World_Physics_RemoveFromEntity(world_t *world, wedict_t *ed) ed->ode.ode_massbuf = NULL; } -static void World_Physics_Frame_BodyToEntity(world_t *world, wedict_t *ed) +static void World_ODE_Frame_BodyToEntity(world_t *world, wedict_t *ed) { model_t *model; const dReal *avel; @@ -1444,7 +1444,7 @@ static void World_Physics_Frame_BodyToEntity(world_t *world, wedict_t *ed) World_LinkEdict(world, ed, true); } -static void World_Physics_Frame_JointFromEntity(world_t *world, wedict_t *ed) +static void World_ODE_Frame_JointFromEntity(world_t *world, wedict_t *ed) { dJointID j = 0; dBodyID b1 = 0; @@ -1729,7 +1729,7 @@ static qboolean GenerateCollisionMesh(world_t *world, model_t *mod, wedict_t *ed return true; } -static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) +static void World_ODE_Frame_BodyFromEntity(world_t *world, wedict_t *ed) { dBodyID body = (dBodyID)ed->ode.ode_body; dMass mass; @@ -1803,7 +1803,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) break; default: if (ed->ode.ode_physics) - World_Physics_RemoveFromEntity(world, ed); + World_ODE_RemoveFromEntity(world, ed); return; } @@ -1812,7 +1812,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) { // we don't allow point-size physics objects... if (ed->ode.ode_physics) - World_Physics_RemoveFromEntity(world, ed); + World_ODE_RemoveFromEntity(world, ed); return; } @@ -1827,7 +1827,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) || ed->ode.ode_modelindex != modelindex) { modified = true; - World_Physics_RemoveFromEntity(world, ed); + World_ODE_RemoveFromEntity(world, ed); ed->ode.ode_physics = true; VectorCopy(entmins, ed->ode.ode_mins); VectorCopy(entmaxs, ed->ode.ode_maxs); @@ -1853,13 +1853,13 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) { Con_Printf("entity %i (classname %s) has no model\n", NUM_FOR_EDICT(world->progs, (edict_t*)ed), PR_GetString(world->progs, ed->v->classname)); if (ed->ode.ode_physics) - World_Physics_RemoveFromEntity(world, ed); + World_ODE_RemoveFromEntity(world, ed); return; } if (!GenerateCollisionMesh(world, model, ed, geomcenter)) { if (ed->ode.ode_physics) - World_Physics_RemoveFromEntity(world, ed); + World_ODE_RemoveFromEntity(world, ed); return; } @@ -1909,7 +1909,7 @@ static void World_Physics_Frame_BodyFromEntity(world_t *world, wedict_t *ed) dMassSetCapsuleTotal(&mass, massval, axisindex+1, radius, length); break; default: - Sys_Error("World_Physics_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); + Sys_Error("World_ODE_BodyFromEntity: unrecognized solid value %i was accepted by filter\n", solid); } Matrix3x4_InvertTo4x4_Simple(ed->ode.ode_offsetmatrix, ed->ode.ode_offsetimatrix); ed->ode.ode_massbuf = BZ_Malloc(sizeof(dMass)); @@ -2259,7 +2259,7 @@ static void VARGS nearCallback (void *data, dGeomID o1, dGeomID o2) } } -void World_Physics_Frame(world_t *world, double frametime, double gravity) +void World_ODE_Frame(world_t *world, double frametime, double gravity) { if (world->ode.ode) { @@ -2275,14 +2275,14 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity) { ed = (wedict_t*)EDICT_NUM(world->progs, i); if (!ed->isfree) - World_Physics_Frame_BodyFromEntity(world, ed); + World_ODE_Frame_BodyFromEntity(world, ed); } // oh, and it must be called after all bodies were created for (i = 0;i < world->num_edicts;i++) { ed = (wedict_t*)EDICT_NUM(world->progs, i); if (!ed->isfree) - World_Physics_Frame_JointFromEntity(world, ed); + World_ODE_Frame_JointFromEntity(world, ed); } for (i = 0;i < world->ode.ode_iterations;i++) @@ -2313,7 +2313,7 @@ void World_Physics_Frame(world_t *world, double frametime, double gravity) { ed = (wedict_t*)EDICT_NUM(world->progs, i); if (!ed->isfree) - World_Physics_Frame_BodyToEntity(world, ed); + World_ODE_Frame_BodyToEntity(world, ed); } } } diff --git a/engine/common/common.c b/engine/common/common.c index 1491ddbb..9f361fbb 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -114,27 +114,6 @@ void COM_Locate_f (void); qboolean standard_quake = true, rogue, hipnotic; -// this graphic needs to be in the pak file to use registered features -unsigned short pop[] = -{ - 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x6600,0x0000,0x0000,0x0000,0x6600,0x0000 -,0x0000,0x0066,0x0000,0x0000,0x0000,0x0000,0x0067,0x0000 -,0x0000,0x6665,0x0000,0x0000,0x0000,0x0000,0x0065,0x6600 -,0x0063,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6563 -,0x0064,0x6561,0x0000,0x0000,0x0000,0x0000,0x0061,0x6564 -,0x0064,0x6564,0x0000,0x6469,0x6969,0x6400,0x0064,0x6564 -,0x0063,0x6568,0x6200,0x0064,0x6864,0x0000,0x6268,0x6563 -,0x0000,0x6567,0x6963,0x0064,0x6764,0x0063,0x6967,0x6500 -,0x0000,0x6266,0x6769,0x6a68,0x6768,0x6a69,0x6766,0x6200 -,0x0000,0x0062,0x6566,0x6666,0x6666,0x6666,0x6562,0x0000 -,0x0000,0x0000,0x0062,0x6364,0x6664,0x6362,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0062,0x6662,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0061,0x6661,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0000,0x6500,0x0000,0x0000,0x0000 -,0x0000,0x0000,0x0000,0x0000,0x6400,0x0000,0x0000,0x0000 -}; - /* @@ -3003,33 +2982,14 @@ being registered. void COM_CheckRegistered (void) { vfsfile_t *h; - unsigned short check[128]; - int i; h = FS_OpenVFS("gfx/pop.lmp", "rb", FS_GAME); static_registered = false; if (!h) - { - Con_TPrintf (TL_SHAREWAREVERSION); -#if 0//ndef SERVERONLY -// FIXME DEBUG -- only temporary - if (com_modified) - Sys_Error ("You must have the registered version to play QuakeWorld"); -#endif return; - } - - VFS_READ(h, check, sizeof(check)); VFS_CLOSE(h); - for (i=0 ; i<128 ; i++) - if (pop[i] != (unsigned short)BigShort (check[i])) - { - Con_TPrintf (TL_SHAREWAREVERSION); - return; - } - static_registered = true; Con_TPrintf (TL_REGISTEREDVERSION); } diff --git a/engine/common/fs.c b/engine/common/fs.c index d9ae4296..ef23a7a7 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1639,7 +1639,7 @@ void COM_Gamedir (const char *dir) /*some modern non-compat settings*/ #define DMFCFG "set com_parseutf8 1\npm_airstep 1\nsv_demoExtensions 1\n" /*set some stuff so our regular qw client appears more like hexen2*/ -#define HEX2CFG "set r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\n" +#define HEX2CFG "set r_particlesdesc \"spikeset tsshaft h2part\"\nset sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 1\nset cl_model_bobbing 1\nsv_sound_land \"fx/thngland.wav\"\n" /*Q3's ui doesn't like empty model/headmodel/handicap cvars, even if the gamecode copes*/ #define Q3CFG "seta model sarge\nseta headmodel sarge\nseta handicap 100\n" @@ -2307,21 +2307,24 @@ void COM_InitFilesystem (void) fclose(f); break; } + if (autobasedir) + { #ifdef _WIN32 - if (Sys_FindGameData(gamemode_info[i].poshname, gamemode_info[i].exename, com_quakedir, sizeof(com_quakedir))) - { - if (com_quakedir[strlen(com_quakedir)-1] == '\\') - com_quakedir[strlen(com_quakedir)-1] = '/'; - else if (com_quakedir[strlen(com_quakedir)-1] != '/') + if (Sys_FindGameData(gamemode_info[i].poshname, gamemode_info[i].exename, com_quakedir, sizeof(com_quakedir))) { - com_quakedir[strlen(com_quakedir)+1] = '\0'; - com_quakedir[strlen(com_quakedir)] = '/'; + if (com_quakedir[strlen(com_quakedir)-1] == '\\') + com_quakedir[strlen(com_quakedir)-1] = '/'; + else if (com_quakedir[strlen(com_quakedir)-1] != '/') + { + com_quakedir[strlen(com_quakedir)+1] = '\0'; + com_quakedir[strlen(com_quakedir)] = '/'; + } } - } - else + else #endif - { - Con_Printf("Couldn't find the gamedata for this game mode!\n"); + { + Con_Printf("Couldn't find the gamedata for this game mode!\n"); + } } break; } diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index c7da4221..5949ac96 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -3444,7 +3444,7 @@ void CMQ3_CalcPHS (void) count++; } - Con_Printf ("Average clusters visible / hearable / total: %i / %i / %i\n" + Con_DPrintf ("Average clusters visible / hearable / total: %i / %i / %i\n" , vcount/numclusters, count/numclusters, numclusters); } #endif @@ -5186,7 +5186,10 @@ trace_t CM_BoxTrace (model_t *mod, vec3_t start, vec3_t end, qboolean CM_Trace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) { - *trace = CM_BoxTrace(model, start, end, mins, maxs, MASK_PLAYERSOLID); + if (maxs[0] - mins[0]) + *trace = CM_BoxTrace(model, start, end, mins, maxs, MASK_PLAYERSOLID); + else + *trace = CM_BoxTrace(model, start, end, mins, maxs, MASK_SOLID); return trace->fraction != 1; } qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contents, trace_t *trace) diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 0b03ceed..dd1b09b8 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -622,6 +622,24 @@ void R_ConcatTransforms (float in1[3][4], float in2[3][4], float out[3][4]) in1[2][2] * in2[2][3] + in1[2][3]; } +void Matrix3x4_Multiply(const float *a, const float *b, float *out) +{ + out[0] = a[0] * b[0] + a[4] * b[1] + a[8] * b[2]; + out[1] = a[1] * b[0] + a[5] * b[1] + a[9] * b[2]; + out[2] = a[2] * b[0] + a[6] * b[1] + a[10] * b[2]; + out[3] = a[3] * b[0] + a[7] * b[1] + a[11] * b[2] + b[3]; + + out[4] = a[0] * b[4] + a[4] * b[5] + a[8] * b[6]; + out[5] = a[1] * b[4] + a[5] * b[5] + a[9] * b[6]; + out[6] = a[2] * b[4] + a[6] * b[5] + a[10] * b[6]; + out[7] = a[3] * b[4] + a[7] * b[5] + a[11] * b[6] + b[7]; + + out[8] = a[0] * b[8] + a[4] * b[9] + a[8] * b[10]; + out[9] = a[1] * b[8] + a[5] * b[9] + a[9] * b[10]; + out[10] = a[2] * b[8] + a[6] * b[9] + a[10] * b[10]; + out[11] = a[3] * b[8] + a[7] * b[9] + a[11] * b[10] + b[11]; +} + void R_ConcatRotationsPad (float in1[3][4], float in2[3][4], float out[3][4]) { out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] + @@ -1537,6 +1555,25 @@ void Matrix3x3_RM_Invert_Simple (const vec3_t in1[3], vec3_t out[3]) out[2][2] = in1[2][2] * scale; } +void Matrix3x4_Invert (const float *in1, float *out) +{ + vec3_t a, b, c, trans; + + VectorSet (a, in1[0], in1[4], in1[8]); + VectorSet (b, in1[1], in1[5], in1[9]); + VectorSet (c, in1[2], in1[6], in1[10]); + + VectorScale (a, 1 / DotProduct (a, a), a); + VectorScale (b, 1 / DotProduct (b, b), b); + VectorScale (c, 1 / DotProduct (c, c), c); + + VectorSet (trans, in1[3], in1[7], in1[11]); + + Vector4Set (out+0, a[0], a[1], a[2], -DotProduct (a, trans)); + Vector4Set (out+4, b[0], b[1], b[2], -DotProduct (b, trans)); + Vector4Set (out+8, c[0], c[1], c[2], -DotProduct (c, trans)); +} + void Matrix3x4_Invert_Simple (const float *in1, float *out) { // we only support uniform scaling, so assume the first row is enough diff --git a/engine/common/mathlib.h b/engine/common/mathlib.h index d23ee711..593d71a8 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -82,6 +82,7 @@ extern vec3_t vec3_origin; #define Vector4Copy(a,b) do{(b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];(b)[3]=(a)[3];}while(0) #define Vector4Scale(in,scale,out) ((out)[0]=(in)[0]*scale,(out)[1]=(in)[1]*scale,(out)[2]=(in)[2]*scale,(out)[3]=(in)[3]*scale) #define Vector4Add(a,b,c) ((c)[0]=(((a[0])+(b[0]))),(c)[1]=(((a[1])+(b[1]))),(c)[2]=(((a[2])+(b[2]))),(c)[3]=(((a[3])+(b[3])))) +#define Vector4Set(r,x,y,z,w) {(r)[0] = x; (r)[1] = y;(r)[2] = z;(r)[3]=w;} typedef float matrix3x4[3][4]; typedef float matrix3x3[3][3]; @@ -140,6 +141,7 @@ mat3x4 is always row-major (and functions can accept many RM mat4x4) void Matrix3_Multiply (vec3_t *in1, vec3_t *in2, vec3_t *out); void Matrix4x4_Identity(float *outm); qboolean Matrix4_Invert(const float *m, float *out); +void Matrix3x4_Invert (const float *in1, float *out); void Matrix3x4_Invert_Simple (const float *in1, float *out); void Matrix3x4_InvertTo4x4_Simple (const float *in1, float *out); void Matrix3x3_RM_Invert_Simple(const vec3_t in[3], vec3_t out[3]); @@ -151,6 +153,7 @@ void Matrix4x4_CM_ModelViewMatrix (float *modelview, const vec3_t viewangles, c void Matrix4x4_CM_ModelViewMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); void Matrix4_CreateFromQuakeEntity (float *matrix, float x, float y, float z, float pitch, float yaw, float roll, float scale); void Matrix4_Multiply (const float *a, const float *b, float *out); +void Matrix3x4_Multiply(const float *a, const float *b, float *out); void Matrix4x4_CM_Project (const vec3_t in, vec3_t out, const vec3_t viewangles, const vec3_t vieworg, float fovx, float fovy); void Matrix4x4_CM_Transform3 (const float *matrix, const float *vector, float *product); void Matrix4x4_CM_Transform4 (const float *matrix, const float *vector, float *product); diff --git a/engine/common/pr_common.h b/engine/common/pr_common.h index f072abe0..e6bf1ae2 100644 --- a/engine/common/pr_common.h +++ b/engine/common/pr_common.h @@ -310,6 +310,20 @@ pbool ED_CanFree (edict_t *ed); #endif #define MOVETYPE_NONE 0 // never moves +#define MOVETYPE_ANGLENOCLIP 1 +#define MOVETYPE_ANGLECLIP 2 +#define MOVETYPE_WALK 3 // gravity +#define MOVETYPE_STEP 4 // gravity, special edge handling +#define MOVETYPE_FLY 5 +#define MOVETYPE_TOSS 6 // gravity +#define MOVETYPE_PUSH 7 // no clip to world, push and crush +#define MOVETYPE_NOCLIP 8 +#define MOVETYPE_FLYMISSILE 9 // extra size to monsters +#define MOVETYPE_BOUNCE 10 +#define MOVETYPE_BOUNCEMISSILE 11 // bounce w/o gravity +#define MOVETYPE_FOLLOW 12 // track movement of aiment +#define MOVETYPE_H2PUSHPULL 13 // pushable/pullable object +#define MOVETYPE_H2SWIM 14 // should keep the object in water #define MOVETYPE_PHYSICS 32 // edict->solid values @@ -318,8 +332,8 @@ pbool ED_CanFree (edict_t *ed); #define SOLID_BBOX 2 // touch on edge, block #define SOLID_SLIDEBOX 3 // touch on edge, but not an onground #define SOLID_BSP 4 // bsp clip, touch on edge, block -#define SOLID_PHASEH2 5 -#define SOLID_CORPSE 5 +#define SOLID_PHASEH2 5 // hexen2 flag - these ents can be freely walked through or something +#define SOLID_CORPSE 5 // non-solid to solid_slidebox entities and itself. #define SOLID_LADDER 20 //dmw. touch on edge, not blocking. Touching players have different physics. Otherwise a SOLID_TRIGGER #define SOLID_PHYSICS_BOX 32 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity) #define SOLID_PHYSICS_SPHERE 33 ///< physics object (mins, maxs, mass, origin, axis_forward, axis_left, axis_up, velocity, spinvelocity) diff --git a/engine/common/world.h b/engine/common/world.h index 7a84a047..730fcafc 100644 --- a/engine/common/world.h +++ b/engine/common/world.h @@ -93,6 +93,7 @@ typedef struct q2trace_s #define MOVE_TRIGGERS 16 //triggers must be marked with FINDABLE_NONSOLID (an alternative to solid-corpse) #define MOVE_EVERYTHING 32 //can return triggers and non-solid items if they're marked with FINDABLE_NONSOLID (works even if the items are not properly linked) #define MOVE_LAGGED 64 //trace touches current last-known-state, instead of actual ents (just affects players for now) +#define MOVE_ENTCHAIN 128 //chain of impacted ents, otherwise result shows only world typedef struct areanode_s { @@ -107,6 +108,8 @@ typedef struct areanode_s #define EDICT_FROM_AREA(l) STRUCT_FROM_LINK(l,wedict_t,area) typedef struct wedict_s wedict_t; +#define PROG_TO_WEDICT (wedict_t*)PROG_TO_EDICT +#define WEDICT_NUM (wedict_t *)EDICT_NUM typedef struct { @@ -117,9 +120,10 @@ typedef struct struct world_s { void (*Event_Touch)(struct world_s *w, wedict_t *s, wedict_t *o); + void (*Event_Think)(struct world_s *w, wedict_t *s); + void (*Event_Sound) (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj); model_t *(*GetCModel)(struct world_s *w, int modelindex); - int *global_self; unsigned int max_edicts; //limiting factor... 1024 fields*4*MAX_EDICTS == a heck of a lot. unsigned int num_edicts; // increases towards MAX_EDICTS /*FTE_DEPRECATED*/ unsigned int edict_size; //still used in copyentity @@ -138,6 +142,15 @@ struct world_s laggedentinfo_t *lagents; unsigned int maxlagents; + struct { + int *self; + int *other; + int *newmis; + float *time; + float *frametime; + float *force_retouch; + } g; + #ifdef USEODE worldode_t ode; #endif @@ -145,13 +158,13 @@ struct world_s typedef struct world_s world_t; #ifdef USEODE -void World_Physics_RemoveFromEntity(world_t *world, wedict_t *ed); -void World_Physics_RemoveJointFromEntity(world_t *world, wedict_t *ed); -void World_Physics_Frame(world_t *world, double frametime, double gravity); -void World_Physics_Init(void); -void World_Physics_Start(world_t *world); -void World_Physics_End(world_t *world); -void World_Physics_Shutdown(void); +void World_ODE_RemoveFromEntity(world_t *world, wedict_t *ed); +void World_ODE_RemoveJointFromEntity(world_t *world, wedict_t *ed); +void World_ODE_Frame(world_t *world, double frametime, double gravity); +void World_ODE_Init(void); +void World_ODE_Start(world_t *world); +void World_ODE_End(world_t *world); +void World_ODE_Shutdown(void); #endif void World_ClearWorld (world_t *w); diff --git a/engine/d3d/d3d_backend.c b/engine/d3d/d3d_backend.c index 3c62a3df..07ea1a74 100644 --- a/engine/d3d/d3d_backend.c +++ b/engine/d3d/d3d_backend.c @@ -15,6 +15,8 @@ extern LPDIRECT3DDEVICE9 pD3DDev9; #define MAX_TMUS 4 +extern float d3d_trueprojection[16]; + /*========================================== tables for deforms =====================================*/ #define frand() (rand()*(1.0/RAND_MAX)) #define FTABLE_SIZE 1024 @@ -126,6 +128,7 @@ typedef struct unsigned int curcull; float depthbias; float depthfactor; + float m_model[16]; unsigned int lastpasscount; texid_t curtex[MAX_TMUS]; @@ -169,13 +172,26 @@ extern int be_maxpasses; enum { D3D_VDEC_COL4B = 1<<0, - //D3D_VDEC_NORMS = 1<<1, D3D_VDEC_ST0 = 1<<1, D3D_VDEC_ST1 = 1<<2, D3D_VDEC_ST2 = 1<<3, D3D_VDEC_ST3 = 1<<4, - D3D_VDEC_MAX = 1<<5 + D3D_VDEC_NORM = 1<<5, + D3D_VDEC_SKEL = 1<<6, + D3D_VDEC_MAX = 1<<7 }; +#define STRM_VERT 0 +#define STRM_COL 1 +#define STRM_TC0 2 +#define STRM_TC1 3 +#define STRM_TC2 4 +#define STRM_TC3 5 +#define STRM_NORM 6 +#define STRM_NORMS 7 +#define STRM_NORMT 8 +#define STRM_BONENUM 9 +#define STRM_BONEWEIGHT 10 +#define STRM_MAX 11 IDirect3DVertexDeclaration9 *vertexdecls[D3D_VDEC_MAX]; static void BE_ApplyTMUState(unsigned int tu, unsigned int flags) @@ -355,7 +371,7 @@ void D3DBE_Reset(qboolean before) { IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, NULL); shaderstate.curvertdecl = 0; - for (i = 0; i < 5+MAX_TMUS; i++) + for (i = 0; i < STRM_MAX; i++) IDirect3DDevice9_SetStreamSource(pD3DDev9, i, NULL, 0, 0); IDirect3DDevice9_SetIndices(pD3DDev9, NULL); @@ -384,13 +400,13 @@ void D3DBE_Reset(qboolean before) } else { - D3DVERTEXELEMENT9 decl[8], declend=D3DDECL_END(); + D3DVERTEXELEMENT9 decl[13], declend=D3DDECL_END(); int elements; for (i = 0; i < D3D_VDEC_MAX; i++) { elements = 0; - decl[elements].Stream = 0; + decl[elements].Stream = STRM_VERT; decl[elements].Offset = 0; decl[elements].Type = D3DDECLTYPE_FLOAT3; decl[elements].Method = D3DDECLMETHOD_DEFAULT; @@ -400,7 +416,7 @@ void D3DBE_Reset(qboolean before) if (i & D3D_VDEC_COL4B) { - decl[elements].Stream = 1; + decl[elements].Stream = STRM_COL; decl[elements].Offset = 0; decl[elements].Type = D3DDECLTYPE_D3DCOLOR; decl[elements].Method = D3DDECLMETHOD_DEFAULT; @@ -409,38 +425,38 @@ void D3DBE_Reset(qboolean before) elements++; } -/* if (i & D3D_VDEC_NORMS) + if (i & D3D_VDEC_NORM) { - decl[elements].Stream = 2; + decl[elements].Stream = STRM_NORM; decl[elements].Offset = 0; - decl[elements].Type = D3DDECLTYPE_FLOAT2; + decl[elements].Type = D3DDECLTYPE_FLOAT3; decl[elements].Method = D3DDECLMETHOD_DEFAULT; - decl[elements].Usage = D3DDECLUSAGE_TEXCOORD; - decl[elements].UsageIndex = 1; + decl[elements].Usage = D3DDECLUSAGE_NORMAL; + decl[elements].UsageIndex = 0; elements++; - decl[elements].Stream = 3; + decl[elements].Stream = STRM_NORMS; decl[elements].Offset = 0; - decl[elements].Type = D3DDECLTYPE_FLOAT2; + decl[elements].Type = D3DDECLTYPE_FLOAT3; decl[elements].Method = D3DDECLMETHOD_DEFAULT; - decl[elements].Usage = D3DDECLUSAGE_TEXCOORD; - decl[elements].UsageIndex = 1; + decl[elements].Usage = D3DDECLUSAGE_TANGENT; + decl[elements].UsageIndex = 0; elements++; - decl[elements].Stream = 4; + decl[elements].Stream = STRM_NORMT; decl[elements].Offset = 0; - decl[elements].Type = D3DDECLTYPE_FLOAT2; + decl[elements].Type = D3DDECLTYPE_FLOAT3; decl[elements].Method = D3DDECLMETHOD_DEFAULT; - decl[elements].Usage = D3DDECLUSAGE_TEXCOORD; - decl[elements].UsageIndex = 1; + decl[elements].Usage = D3DDECLUSAGE_BINORMAL; + decl[elements].UsageIndex = 0; elements++; } -*/ + for (tmu = 0; tmu < MAX_TMUS; tmu++) { if (i & (D3D_VDEC_ST0<handle[permu].hlsl.vert); + IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->handle[permu].hlsl.frag); + for (i = 0; i < prog->numparams; i++) + { + switch (prog->parm[i].type) + { + case SP_M_PROJECTION: + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], d3d_trueprojection, 4); + break; + case SP_M_VIEW: + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], r_refdef.m_view, 4); + break; +// case SP_M_MODEL: +// IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], r_refdef.m_view, 4); +// break; + + case SP_V_EYEPOS: + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], r_origin, 1); + break; + case SP_E_EYEPOS: + { + vec4_t t2; + float m16[16]; + Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); + Matrix4x4_CM_Transform3(m16, r_origin, t2); + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], t2, 1); + } + break; + case SP_E_TIME: + { + vec4_t t1 = {shaderstate.curtime}; + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], t1, 1); + } + break; + case SP_M_MODELVIEWPROJECTION: + { + float mv[16], mvp[16]; + Matrix4_Multiply(r_refdef.m_view, shaderstate.m_model, mv); + Matrix4_Multiply(d3d_trueprojection, mv, mvp); + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, prog->parm[i].handle[permu], mvp, 4); + } + break; + case SP_E_COLOURS: + case SP_E_COLOURSIDENT: + case SP_E_TOPCOLOURS: + case SP_E_BOTTOMCOLOURS: + case SP_E_L_DIR: + case SP_E_L_MUL: + case SP_E_L_AMBIENT: + + case SP_M_ENTBONES: + case SP_M_MODEL: + case SP_M_MODELVIEW: + + case SP_RENDERTEXTURESCALE: + + case SP_LIGHTRADIUS: + case SP_LIGHTCOLOUR: + case SP_LIGHTPOSITION: + + case SP_FIRSTIMMEDIATE: + case SP_CONSTI: + case SP_CONSTF: + case SP_CVARI: + case SP_CVARF: + case SP_CVAR3F: + case SP_TEXTURE: + Con_Printf("shader property %i not implemented\n", prog->parm[i].type); + break; + } + } +} + static void BE_RenderMeshProgram(unsigned int vertcount, unsigned int idxfirst, unsigned int idxcount) { + int vdec = D3D_VDEC_ST0; + int passno; shader_t *s = shaderstate.curshader; //shaderpass_t *pass = s->passes; //unused variable - IDirect3DDevice9_SetVertexShader(pD3DDev9, s->prog->handle[0].hlsl.vert); - IDirect3DDevice9_SetPixelShader(pD3DDev9, s->prog->handle[0].hlsl.frag); + D3DBE_ApplyShaderBits(shaderstate.curshader->passes->shaderbits); + + BE_ApplyUniforms(s->prog, 0); + + + + /*activate tmus*/ + for (passno = 0; passno < s->numpasses; passno++) + { + SelectPassTexture(passno, s->passes+passno); + } + /*deactivate any extras*/ + for (; passno < shaderstate.lastpasscount; passno++) + { + BindTexture(passno, NULL); + d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_COLOROP, D3DTOP_DISABLE)); + } + shaderstate.lastpasscount = passno; + + /*colours*/ + if (vdec & D3D_VDEC_COL4B) + { + int mno,v; + void *map; + mesh_t *m; + allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(byte_vec4_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + byte_vec4_t *dest = (byte_vec4_t*)((char*)map+vertcount*sizeof(byte_vec4_t)); + m = shaderstate.meshlist[mno]; + if (m->colors4f_array) + { + for (v = 0; v < m->numvertexes; v++) + { + dest[v][0] = bound(0, m->colors4f_array[v][0] * 255, 255); + dest[v][1] = bound(0, m->colors4f_array[v][1] * 255, 255); + dest[v][2] = bound(0, m->colors4f_array[v][2] * 255, 255); + dest[v][3] = bound(0, m->colors4f_array[v][3] * 255, 255); + } + } + else if (m->colors4b_array) + memcpy(dest, m->colors4b_array, m->numvertexes*sizeof(byte_vec4_t)); + else + memset(dest, 0, m->numvertexes*sizeof(byte_vec4_t)); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(byte_vec4_t), sizeof(byte_vec4_t))); + } + + /*texture coords*/ + if (vdec & D3D_VDEC_ST0) + { + int mno; + void *map; + mesh_t *m; + allocvertexbuffer(shaderstate.dynst_buff[0], shaderstate.dynst_size, &shaderstate.dynst_offs[0], &map, vertcount*sizeof(vec2_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + vec2_t *dest = (vec2_t*)((char*)map+vertcount*sizeof(vec2_t)); + m = shaderstate.meshlist[mno]; + memcpy(dest, m->st_array, m->numvertexes*sizeof(vec2_t)); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[0])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[0], shaderstate.dynst_offs[0] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); + } + /*lm coords*/ + if (vdec & D3D_VDEC_ST1) + { + int mno; + void *map; + mesh_t *m; + allocvertexbuffer(shaderstate.dynst_buff[1], shaderstate.dynst_size, &shaderstate.dynst_offs[1], &map, vertcount*sizeof(vec2_t)); + for (mno = 0, vertcount = 0; mno < shaderstate.nummeshes; mno++) + { + vec2_t *dest = (vec2_t*)((char*)map+vertcount*sizeof(vec2_t)); + m = shaderstate.meshlist[mno]; + memcpy(dest, m->lmst_array, m->numvertexes*sizeof(vec2_t)); + vertcount += m->numvertexes; + } + d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynst_buff[1])); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0, shaderstate.dynst_buff[1], shaderstate.dynst_offs[1] - vertcount*sizeof(vec2_t), sizeof(vec2_t))); + } + + /*normals/tangents/bitangents*/ + if (vdec & D3D_VDEC_NORM) + { + /*FIXME*/ + vdec &= ~D3D_VDEC_NORM; + } + + /*bone weights+indexes*/ + if (vdec & D3D_VDEC_SKEL) + { + /*FIXME*/ + vdec &= ~D3D_VDEC_NORM; + } + + if (vdec != shaderstate.curvertdecl) + { + shaderstate.curvertdecl = vdec; + d3dcheck(IDirect3DDevice9_SetVertexDeclaration(pD3DDev9, vertexdecls[shaderstate.curvertdecl])); + } // IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, d3dcheck(IDirect3DDevice9_DrawIndexedPrimitive(pD3DDev9, D3DPT_TRIANGLELIST, 0, 0, vertcount, idxfirst, idxcount/3)); @@ -1597,7 +1812,7 @@ static void BE_DrawMeshChain_Internal(void) vertcount += m->numvertexes; } d3dcheck(IDirect3DVertexBuffer9_Unlock(shaderstate.dynxyz_buff)); - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, 0, shaderstate.dynxyz_buff, shaderstate.dynxyz_offs - vertcount*sizeof(vecV_t), sizeof(vecV_t))); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_VERT, shaderstate.dynxyz_buff, shaderstate.dynxyz_offs - vertcount*sizeof(vecV_t), sizeof(vecV_t))); /*so are index buffers*/ idxfirst = allocindexbuffer(&map, idxcount); @@ -1626,7 +1841,7 @@ static void BE_DrawMeshChain_Internal(void) /*deactivate any extras*/ for (passno = 0; passno < shaderstate.lastpasscount; ) { - d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, 5+passno, NULL, 0, 0)); + d3dcheck(IDirect3DDevice9_SetStreamSource(pD3DDev9, STRM_TC0+passno, NULL, 0, 0)); BindTexture(passno, NULL); d3dcheck(IDirect3DDevice9_SetTextureStageState(pD3DDev9, passno, D3DTSS_COLOROP, D3DTOP_DISABLE)); passno++; @@ -1900,7 +2115,7 @@ batch_t *D3DBE_GetTempBatch(void) static void BE_RotateForEntity (const entity_t *e, const model_t *mod) { float mv[16]; - float m[16]; + float *m = shaderstate.m_model; shaderstate.curentity = e; @@ -2072,9 +2287,12 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) if (batch->shader->flags & SHADER_SKY) { - if (shaderstate.mode == BEM_STANDARD) - R_DrawSkyChain (batch); - continue; + if (!batch->shader->prog) + { + if (shaderstate.mode == BEM_STANDARD) + R_DrawSkyChain (batch); + continue; + } } BE_SubmitBatch(batch); @@ -2209,7 +2427,7 @@ static void TransformDir(vec3_t in, vec3_t planea[3], vec3_t viewa[3], vec3_t re } static void R_RenderScene(void) { - IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)r_refdef.m_projection); + IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection); IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); Surf_DrawWorld(); @@ -2320,7 +2538,7 @@ static void R_DrawPortal(batch_t *batch, batch_t **blist) AngleVectors (r_refdef.viewangles, vpn, vright, vup); VectorCopy (r_refdef.vieworg, r_origin); - IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)r_refdef.m_projection); + IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection); IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view); R_SetFrustum (r_refdef.m_projection, r_refdef.m_view); } diff --git a/engine/d3d/d3d_shader.c b/engine/d3d/d3d_shader.c index cf2978d9..82756257 100644 --- a/engine/d3d/d3d_shader.c +++ b/engine/d3d/d3d_shader.c @@ -15,8 +15,8 @@ typedef struct { LPCSTR Definition; } D3DXMACRO; +#define D3DXHANDLE void * #define LPD3DXINCLUDE void * -#define LPD3DXCONSTANTTABLE void * #undef INTERFACE #define INTERFACE d3dxbuffer @@ -31,6 +31,96 @@ DECLARE_INTERFACE_(d3dxbuffer,IUnknown) }; typedef struct d3dxbuffer *LPD3DXBUFFER; +typedef enum _D3DXREGISTER_SET +{ + D3DXRS_BOOL, + D3DXRS_INT4, + D3DXRS_FLOAT4, + D3DXRS_SAMPLER, + D3DXRS_FORCE_DWORD = 0x7fffffff +} D3DXREGISTER_SET, *LPD3DXREGISTER_SET; +typedef enum _D3DXPARAMETER_CLASS +{ + D3DXPC_SCALAR, + D3DXPC_VECTOR, + D3DXPC_MATRIX_ROWS, + D3DXPC_MATRIX_COLUMNS, + D3DXPC_OBJECT, + D3DXPC_STRUCT, + D3DXPC_FORCE_DWORD = 0x7fffffff +} D3DXPARAMETER_CLASS, *LPD3DXPARAMETER_CLASS; +typedef enum _D3DXPARAMETER_TYPE +{ + D3DXPT_VOID, + D3DXPT_BOOL, + D3DXPT_INT, + D3DXPT_FLOAT, + D3DXPT_STRING, + D3DXPT_TEXTURE, + D3DXPT_TEXTURE1D, + D3DXPT_TEXTURE2D, + D3DXPT_TEXTURE3D, + D3DXPT_TEXTURECUBE, + D3DXPT_SAMPLER, + D3DXPT_SAMPLER1D, + D3DXPT_SAMPLER2D, + D3DXPT_SAMPLER3D, + D3DXPT_SAMPLERCUBE, + D3DXPT_PIXELSHADER, + D3DXPT_VERTEXSHADER, + D3DXPT_PIXELFRAGMENT, + D3DXPT_VERTEXFRAGMENT, +} D3DXPARAMETER_TYPE, *LPD3DXPARAMETER_TYPE; +typedef struct _D3DXCONSTANT_DESC +{ + LPCSTR Name; // Constant name + + D3DXREGISTER_SET RegisterSet; // Register set + UINT RegisterIndex; // Register index + UINT RegisterCount; // Number of registers occupied + + D3DXPARAMETER_CLASS Class; // Class + D3DXPARAMETER_TYPE Type; // Component type + + UINT Rows; // Number of rows + UINT Columns; // Number of columns + UINT Elements; // Number of array elements + UINT StructMembers; // Number of structure member sub-parameters + + UINT Bytes; // Data size, in bytes + LPCVOID DefaultValue; // Pointer to default value + +} D3DXCONSTANT_DESC, *LPD3DXCONSTANT_DESC; +typedef struct _D3DXCONSTANTTABLE_DESC +{ + LPCSTR Creator; // Creator string + DWORD Version; // Shader version + UINT Constants; // Number of constants + +} D3DXCONSTANTTABLE_DESC, *LPD3DXCONSTANTTABLE_DESC; + +#undef INTERFACE +#define INTERFACE d3dxconstanttable +DECLARE_INTERFACE_(d3dxconstanttable,IUnknown) +{ + STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE; + STDMETHOD_(ULONG,AddRef)(THIS) PURE; + STDMETHOD_(ULONG,Release)(THIS) PURE; + + STDMETHOD_(LPVOID,GetBufferPointer)(THIS) PURE; + STDMETHOD_(SIZE_T,GetBufferSize)(THIS) PURE; + + STDMETHOD(GetDesc)(THIS_ D3DXCONSTANTTABLE_DESC *pDesc) PURE; + STDMETHOD(GetConstantDesc)(THIS_ D3DXHANDLE hConstant, D3DXCONSTANT_DESC *pConstantDesc, UINT *pCount) PURE; + + STDMETHOD_(D3DXHANDLE, GetConstant)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantByName)(THIS_ D3DXHANDLE hConstant, LPCSTR pName) PURE; + STDMETHOD_(D3DXHANDLE, GetConstantElement)(THIS_ D3DXHANDLE hConstant, UINT Index) PURE; + + /*more stuff not included here cos I don't need it*/ +}; +typedef struct d3dxconstanttable *LPD3DXCONSTANTTABLE; + HRESULT (WINAPI *pD3DXCompileShader) ( LPCSTR pSrcData, @@ -58,29 +148,36 @@ void D3DShader_Init(void) if (!shaderlib) shaderlib = Sys_LoadLibrary("d3dx9_32", funcs); + if (!shaderlib) + shaderlib = Sys_LoadLibrary("d3dx9_34", funcs); if (!shaderlib) return; } -union programhandle_u D3DShader_CreateProgram (char **precompilerconstants, char *vert, char *frag) +void D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag) { - union programhandle_u ret; + int i, j, k; D3DXMACRO defines[64]; LPD3DXBUFFER code = NULL, errors = NULL; - memset(&ret, 0, sizeof(ret)); + D3DXCONSTANTTABLE_DESC ctd; + D3DXHANDLE ch; + D3DXCONSTANT_DESC d; + UINT dc; + + prog->handle[permu].hlsl.vert = NULL; + prog->handle[permu].hlsl.frag = NULL; if (pD3DXCompileShader) { int consts; for (consts = 2; precompilerconstants[consts]; consts++) - { - } + ; if (consts >= sizeof(defines) / sizeof(defines[0])) - return ret; + return; consts = 0; - defines[consts].Name = NULL; + defines[consts].Name = NULL; /*shader type*/ defines[consts].Definition = "1"; consts++; @@ -99,9 +196,9 @@ union programhandle_u D3DShader_CreateProgram (char **precompilerconstants, char defines[consts].Definition = NULL; defines[0].Name = "VERTEX_SHADER"; - if (!FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, NULL))) + if (!FAILED(pD3DXCompileShader(vert, strlen(vert), defines, NULL, "main", "vs_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->handle[permu].hlsl.ctabv))) { - IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&ret.hlsl.vert); + IDirect3DDevice9_CreateVertexShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DVertexShader9**)&prog->handle[permu].hlsl.vert); code->lpVtbl->Release(code); } if (errors) @@ -112,9 +209,9 @@ union programhandle_u D3DShader_CreateProgram (char **precompilerconstants, char } defines[0].Name = "FRAGMENT_SHADER"; - if (!FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, NULL))) + if (!FAILED(pD3DXCompileShader(frag, strlen(frag), defines, NULL, "main", "ps_2_0", 0, &code, &errors, (LPD3DXCONSTANTTABLE*)&prog->handle[permu].hlsl.ctabf))) { - IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&ret.hlsl.frag); + IDirect3DDevice9_CreatePixelShader(pD3DDev9, code->lpVtbl->GetBufferPointer(code), (IDirect3DPixelShader9**)&prog->handle[permu].hlsl.frag); code->lpVtbl->Release(code); } if (errors) @@ -124,7 +221,37 @@ union programhandle_u D3DShader_CreateProgram (char **precompilerconstants, char errors->lpVtbl->Release(errors); } } +} - return ret; +static int D3DShader_FindUniform_(LPD3DXCONSTANTTABLE ct, char *name) +{ + if (ct) + { + UINT dc = 1; + D3DXCONSTANT_DESC d; + if (!FAILED(ct->lpVtbl->GetConstantDesc(ct, name, &d, &dc))) + return d.RegisterIndex; + } + return -1; +} + +int D3DShader_FindUniform(union programhandle_u *h, int type, char *name) +{ + int offs; + + if (!type || type == 1) + { + offs = D3DShader_FindUniform_(h->hlsl.ctabv, name); + if (offs >= 0) + return offs; + } + if (!type || type == 2) + { + offs = D3DShader_FindUniform_(h->hlsl.ctabf, name); + if (offs >= 0) + return offs; + } + + return -1; } #endif \ No newline at end of file diff --git a/engine/d3d/vid_d3d.c b/engine/d3d/vid_d3d.c index 007549c2..e8434a1a 100644 --- a/engine/d3d/vid_d3d.c +++ b/engine/d3d/vid_d3d.c @@ -58,6 +58,7 @@ static void resetD3D9(void); static LPDIRECT3D9 pD3D; LPDIRECT3DDEVICE9 pD3DDev9; static D3DPRESENT_PARAMETERS d3dpp; +float d3d_trueprojection[16]; static qboolean vid_initializing; @@ -1180,8 +1181,8 @@ static void D3D9_SetupViewPort(void) d3d9error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_VIEW, (D3DMATRIX*)r_refdef.m_view)); /*d3d projection matricies scale depth to 0 to 1*/ - Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value/2); - d3d9error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)r_refdef.m_projection)); + Matrix4x4_CM_Projection_Inf(d3d_trueprojection, fov_x, fov_y, gl_mindist.value/2); + d3d9error(IDirect3DDevice9_SetTransform(pD3DDev9, D3DTS_PROJECTION, (D3DMATRIX*)d3d_trueprojection)); /*ogl projection matricies scale depth to -1 to 1, and I would rather my code used consistant culling*/ Matrix4x4_CM_Projection_Inf(r_refdef.m_projection, fov_x, fov_y, gl_mindist.value); } diff --git a/engine/dotnet2005/ftequake.vcproj b/engine/dotnet2005/ftequake.vcproj index ef7e12f7..a83c20cd 100644 --- a/engine/dotnet2005/ftequake.vcproj +++ b/engine/dotnet2005/ftequake.vcproj @@ -709,6 +709,7 @@ /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -28386,6 +28199,194 @@ RelativePath="..\client\r_surf.c" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 43000aef..bff151f9 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1027,7 +1027,7 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) if (e->flags & Q2RF_TRANSLUCENT) { b->flags |= BEF_FORCETRANSPARENT; - if (sort < SHADER_SORT_BLEND) + if (SHADER_SORT_PORTAL < sort && sort < SHADER_SORT_BLEND) sort = SHADER_SORT_BLEND; } if (e->flags & RF_NODEPTHTEST) @@ -1821,7 +1821,7 @@ static void R_Sprite_GenerateBatch(entity_t *e, batch_t **batches, void (*drawfu if (e->flags & Q2RF_TRANSLUCENT || (gl_blendsprites.ival && drawfunc == R_DB_Sprite)) { b->flags |= BEF_FORCETRANSPARENT; - if (sort < SHADER_SORT_BLEND) + if (SHADER_SORT_PORTAL < sort && sort < SHADER_SORT_BLEND) sort = SHADER_SORT_BLEND; } if (e->flags & RF_NODEPTHTEST) diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 4fcaaa77..e09da84b 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -30,7 +30,7 @@ uniform mat4 entmatrix;\n\ #define LIGHTPASS_GLSL_VERTEX "\ #ifdef VERTEX_SHADER\n\ \ -uniform vec3 lightposition;\n\ +uniform vec3 l_lightposition;\n\ \ #if defined(SPECULAR) || defined(OFFSETMAPPING)\n\ uniform vec3 eyeposition;\n\ @@ -47,7 +47,7 @@ void main (void)\n\ \ tcbase = v_texcoord; //pass the texture coords straight through\n\ \ - vec3 lightminusvertex = lightposition - v_position.xyz;\n\ + vec3 lightminusvertex = l_lightposition - v_position.xyz;\n\ lightvector.x = dot(lightminusvertex, v_svector.xyz);\n\ lightvector.y = dot(lightminusvertex, v_tvector.xyz);\n\ lightvector.z = dot(lightminusvertex, v_normal.xyz);\n\ @@ -59,7 +59,7 @@ void main (void)\n\ eyevector.z = dot(eyeminusvertex, v_normal.xyz);\n\ #endif\n\ #if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\ - vshadowcoord = gl_TextureMatrix[7] * (entmatrix*v_position);\n\ + vshadowcoord = gl_TextureMatrix[7] * (entmatrix*vec4(v_position.xyz, 1.0));\n\ #endif\n\ }\n\ #endif\n\ @@ -68,8 +68,8 @@ void main (void)\n\ /*this is full 4*4 PCF, with an added attempt at prenumbra*/ /*the offset consts are 1/(imagesize*2) */ #define PCF16P(f) "\ - float xPixelOffset = (1.0+shadowcoord.b/lightradius)/texx;\ - float yPixelOffset = (1.0+shadowcoord.b/lightradius)/texy;\ + float xPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texx;\ + float yPixelOffset = (1.0+shadowcoord.b/l_lightradius)/texy;\ float s = 0.0;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -1.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ s += "f"Proj(shadowmap, shadowcoord + vec4(-1.5 * xPixelOffset * shadowcoord.w, -0.5 * yPixelOffset * shadowcoord.w, 0.05, 0.0)).r;\n\ @@ -153,8 +153,8 @@ uniform sampler2DShadow shadowmap;\n\ #endif\n\ \ \ -uniform float lightradius;\n\ -uniform vec3 lightcolour;\n\ +uniform float l_lightradius;\n\ +uniform vec3 l_lightcolour;\n\ \ #ifdef OFFSETMAPPING\n\ uniform float offsetmapping_scale;\n\ @@ -188,7 +188,7 @@ void main (void)\n\ #endif\n\ \ vec3 nl = normalize(lightvector);\n\ - float colorscale = max(1.0 - dot(lightvector, lightvector)/(lightradius*lightradius), 0.0);\n\ + float colorscale = max(1.0 - dot(lightvector, lightvector)/(l_lightradius*l_lightradius), 0.0);\n\ \ #ifdef BUMP\n\ vec3 diff;\n\ @@ -224,10 +224,10 @@ if (shadowcoord.w < 0.0) discard;\n\ vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot,spot));\n\ #endif\n\ #if defined(PROJECTION)\n\ - lightcolour *= texture2d(projected, shadowcoord);\n\ + l_lightcolour *= texture2d(projected, shadowcoord);\n\ #endif\n\ \n\ - gl_FragColor.rgb = diff*colorscale*lightcolour;\n\ + gl_FragColor.rgb = diff*colorscale*l_lightcolour;\n\ }\n\ \ #endif\n\ @@ -257,11 +257,6 @@ static const char LIGHTPASS_SHADER[] = "\ param texture 0 baset\n\ param opt texture 1 bumpt\n\ param opt texture 2 speculart\n\ -\ - //light info\n\ - param lightpos lightposition\n\ - param lightradius lightradius\n\ - param lightcolour lightcolour\n\ \ param opt cvarf r_glsl_offsetmapping_bias offsetmapping_bias\n\ param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ @@ -301,11 +296,6 @@ static const char PCFPASS_SHADER[] = "\ param texture 1 baset\n\ param opt texture 2 bumpt\n\ param opt texture 3 speculart\n\ -\ - //light info\n\ - param lightpos lightposition\n\ - param lightradius lightradius\n\ - param lightcolour lightcolour\n\ \ param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ \ @@ -354,6 +344,14 @@ struct { qboolean initedspotpasses; const shader_t *spotpassshader; + qboolean initeddepthnorm; + const shader_t *depthnormshader; + texid_t tex_normals; + texid_t tex_diffuse; + int fbo_diffuse; + texid_t tex_sourcecol; /*this is used by $sourcecolour tgen*/ + texid_t tex_sourcedepth; + qboolean force2d; int currenttmu; int blendmode[SHADER_PASS_MAX]; @@ -923,6 +921,13 @@ static void Shader_BindTextureForPass(int tmu, const shaderpass_t *pass, qboolea case T_GEN_CURRENTRENDER: T_Gen_CurrentRender(tmu); return; + + case T_GEN_SOURCECOLOUR: + t = shaderstate.tex_sourcecol; + break; + case T_GEN_SOURCEDEPTH: + t = shaderstate.tex_sourcedepth; + break; } GL_LazyBind(tmu, GL_TEXTURE_2D, t, useclientarray); } @@ -1100,6 +1105,16 @@ void GLBE_Init(void) shaderstate.fogtexture = r_nulltex; + + + //make sure the world draws correctly + r_worldentity.shaderRGBAf[0] = 1; + r_worldentity.shaderRGBAf[1] = 1; + r_worldentity.shaderRGBAf[2] = 1; + r_worldentity.shaderRGBAf[3] = 1; + r_worldentity.axis[0][0] = 1; + r_worldentity.axis[1][1] = 1; + r_worldentity.axis[2][2] = 1; } //end tables @@ -2358,14 +2373,20 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglVertexAttribPointer(p->handle[perm], 2, GL_FLOAT, GL_FALSE, sizeof(vec2_t), shaderstate.sourcevbo->lmcoord); return 1u<handle[perm]; case SP_ATTR_NORMALS: + if (!shaderstate.sourcevbo->normals) + return 0; GL_SelectVBO(shaderstate.sourcevbo->vbonormals); qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->normals); return 1u<handle[perm]; case SP_ATTR_SNORMALS: + if (!shaderstate.sourcevbo->normals) + return 0; GL_SelectVBO(shaderstate.sourcevbo->vbosvector); qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->svector); return 1u<handle[perm]; case SP_ATTR_TNORMALS: + if (!shaderstate.sourcevbo->normals) + return 0; GL_SelectVBO(shaderstate.sourcevbo->vbotvector); qglVertexAttribPointer(p->handle[perm], 3, GL_FLOAT, GL_FALSE, sizeof(vec3_t), shaderstate.sourcevbo->tvector); return 1u<handle[perm]; @@ -2378,20 +2399,31 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglVertexAttribPointer(p->handle[perm], 4, GL_FLOAT, GL_FALSE, sizeof(vec4_t), shaderstate.sourcevbo->boneweights); return 1u<handle[perm]; - case SP_VIEWMATRIX: + case SP_M_VIEW: qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.m_view); break; - case SP_PROJECTIONMATRIX: + case SP_M_PROJECTION: qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.m_projection); break; - case SP_MODELVIEWMATRIX: + case SP_M_MODELVIEW: qglUniformMatrix4fvARB(p->handle[perm], 1, false, shaderstate.modelviewmatrix); break; - case SP_MODELVIEWPROJECTIONMATRIX: -// qglUniformMatrix4fvARB(p->handle[perm], 1, false, r_refdef.); + case SP_M_MODELVIEWPROJECTION: + { + float m16[16]; + Matrix4_Multiply(r_refdef.m_projection, shaderstate.modelviewmatrix, m16); + qglUniformMatrix4fvARB(p->handle[perm], 1, false, m16); + } break; - case SP_MODELMATRIX: - case SP_ENTMATRIX: + case SP_M_INVMODELVIEWPROJECTION: + { + float m16[16], inv[16]; + Matrix4_Multiply(r_refdef.m_projection, shaderstate.modelviewmatrix, m16); + Matrix4_Invert(m16, inv); + qglUniformMatrix4fvARB(p->handle[perm], 1, false, inv); + } + break; + case SP_M_MODEL: { float m16[16]; Matrix4x4_CM_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); @@ -2407,29 +2439,43 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglUniformMatrix4fvARB(p->handle[perm], 1, false, m16); } break; - case SP_ENTBONEMATRICIES: + case SP_M_ENTBONES: { qglUniformMatrix3x4fv(p->handle[perm], shaderstate.sourcevbo->numbones, false, shaderstate.sourcevbo->bones); } break; + case SP_M_INVVIEWPROJECTION: + { + float m16[16], inv[16]; + Matrix4_Multiply(r_refdef.m_projection, r_refdef.m_view, m16); + Matrix4_Invert(m16, inv); + qglUniformMatrix4fvARB(p->handle[perm], 1, false, inv); + } + break; - case SP_ENTCOLOURS: + case SP_E_GLOWMOD: + qglUniform3fvARB(p->handle[perm], 1, (GLfloat*)shaderstate.curentity->glowmod); + break; + case SP_E_ORIGIN: + qglUniform3fvARB(p->handle[perm], 1, (GLfloat*)shaderstate.curentity->origin); + break; + case SP_E_COLOURS: qglUniform4fvARB(p->handle[perm], 1, (GLfloat*)shaderstate.curentity->shaderRGBAf); break; - case SP_ENTCOLOURSIDENT: + case SP_E_COLOURSIDENT: if (shaderstate.flags & BEF_FORCECOLOURMOD) qglUniform4fvARB(p->handle[perm], 1, (GLfloat*)shaderstate.curentity->shaderRGBAf); else qglUniform4fARB(p->handle[perm], 1, 1, 1, shaderstate.curentity->shaderRGBAf[3]); break; - case SP_TOPCOLOURS: + case SP_E_TOPCOLOURS: R_FetchTopColour(&r, &g, &b); param3[0] = r/255.0f; param3[1] = g/255.0f; param3[2] = b/255.0f; qglUniform3fvARB(p->handle[perm], 1, param3); break; - case SP_BOTTOMCOLOURS: + case SP_E_BOTTOMCOLOURS: R_FetchBottomColour(&r, &g, &b); param3[0] = r/255.0f; param3[1] = g/255.0f; @@ -2464,7 +2510,10 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned case SP_LIGHTCOLOUR: qglUniform3fvARB(p->handle[perm], 1, shaderstate.lightcolours); break; - case SP_EYEPOS: + case SP_V_EYEPOS: + qglUniform3fvARB(p->handle[perm], 1, r_origin); + break; + case SP_E_EYEPOS: { float m16[16]; #ifdef _MSC_VER @@ -2498,7 +2547,17 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglUniform3fvARB(p->handle[perm], 1, t2); } break; - case SP_TIME: + case SP_E_L_DIR: + qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_dir); + break; + case SP_E_L_MUL: + qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_range); + break; + case SP_E_L_AMBIENT: + qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_avg); + break; + + case SP_E_TIME: qglUniform1fARB(p->handle[perm], shaderstate.curtime); break; case SP_CONSTI: @@ -2527,15 +2586,6 @@ static unsigned int BE_Program_Set_Attribute(const shaderprogparm_t *p, unsigned qglUniform3fvARB(p->handle[perm], 1, param3); } break; - case SP_E_L_DIR: - qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_dir); - break; - case SP_E_L_MUL: - qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_range); - break; - case SP_E_L_AMBIENT: - qglUniform3fvARB(p->handle[perm], 1, (float*)shaderstate.curentity->light_avg); - break; default: Host_EndGame("Bad shader program parameter type (%i)", p->type); @@ -2934,6 +2984,9 @@ static void DrawMeshes(void) case BEM_LIGHT: BE_RenderMeshProgram(shaderstate.lightpassshader, shaderstate.lightpassshader->passes); break; + case BEM_DEPTHNORM: + BE_RenderMeshProgram(shaderstate.depthnormshader, shaderstate.depthnormshader->passes); + break; #endif case BEM_DEPTHONLY: GL_DeSelectProgram(); @@ -3219,12 +3272,12 @@ static void BE_SubmitMeshesSortList(batch_t *sortlist) } } -void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist) +static void GLBE_SubmitMeshes (qboolean drawworld, batch_t **blist, int start, int stop) { model_t *model = cl.worldmodel; int i; - for (i = SHADER_SORT_PORTAL; i < SHADER_SORT_COUNT; i++) + for (i = start; i <= stop; i++) { if (drawworld) { @@ -3311,11 +3364,135 @@ void BE_BaseEntTextures(void) { batch_t *batches[SHADER_SORT_COUNT]; BE_GenModelBatches(batches); - GLBE_SubmitMeshes(false, batches); + GLBE_SubmitMeshes(false, batches, SHADER_SORT_PORTAL, SHADER_SORT_NEAREST); BE_SelectEntity(&r_worldentity); } #endif +void GLBE_DrawLightPrePass(qbyte *vis, batch_t **batches) +{ + extern cvar_t temp1; + if (!shaderstate.initeddepthnorm) + { + shaderstate.initeddepthnorm = true; + shaderstate.depthnormshader = R_RegisterShader("lpp_depthnorm", + "{\n" + "program lpp_depthnorm\n" + "{\n" + "map $normalmap\n" + "tcgen base\n" + "}\n" + "}\n" + ); + } + if (!shaderstate.depthnormshader) + { + Con_Printf("%s requires content support\n", r_lightprepass.name); + r_lightprepass.ival = 0; + return; + } + /*do portals*/ + BE_SelectMode(BEM_STANDARD); + GLBE_SubmitMeshes(true, batches, SHADER_SORT_PORTAL, SHADER_SORT_PORTAL); + + BE_SelectMode(BEM_DEPTHNORM); + if (!shaderstate.depthnormshader) + { + BE_SelectMode(BEM_STANDARD); + return; + } + +#define GL_RGBA16F_ARB 0x881A +#define GL_RGBA32F_ARB 0x8814 + if (!TEXVALID(shaderstate.tex_normals)) + { + shaderstate.tex_normals = GL_AllocNewTexture(vid.pixelwidth, vid.pixelheight); + r_lightprepass.modified = true; + } + if (r_lightprepass.modified) + { + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_normals); + qglTexImage2D(GL_TEXTURE_2D, 0, (r_lightprepass.ival==2)?GL_RGBA32F_ARB:GL_RGBA16F_ARB, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + r_lightprepass.modified = false; + } + + if (!TEXVALID(shaderstate.tex_diffuse)) + { + int drb; + + shaderstate.tex_diffuse = GL_AllocNewTexture(vid.pixelwidth, vid.pixelheight); + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_diffuse); + qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + GL_MTBind(0, GL_TEXTURE_2D, shaderstate.tex_normals); + qglTexImage2D(GL_TEXTURE_2D, 0, (r_lightprepass.ival==2)?GL_RGBA32F_ARB:GL_RGBA16F_ARB, vid.pixelwidth, vid.pixelheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + r_lightprepass.modified = false; + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + + qglGenFramebuffersEXT(1, &shaderstate.fbo_diffuse); + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_diffuse); + + qglGenRenderbuffersEXT(1, &drb); + qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, drb); + qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24_ARB, vid.pixelwidth, vid.pixelheight); + qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, drb); + + + qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); +// qglReadBuffer(GL_NONE); + } + else + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shaderstate.fbo_diffuse); + + /*set the FB up to draw surface info*/ + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, shaderstate.tex_normals.num, 0); + qglClear(GL_DEPTH_BUFFER_BIT); + + if (GL_FRAMEBUFFER_COMPLETE_EXT != qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)) + { + Con_Printf("Bad framebuffer\n"); + return; + } + + /*draw surfaces that can be drawn this way*/ + GLBE_SubmitMeshes(true, batches, SHADER_SORT_OPAQUE, SHADER_SORT_OPAQUE); + + /*reconfigure - now drawing diffuse light info using the previous fb image as a source image*/ + shaderstate.tex_sourcecol = shaderstate.tex_normals; + qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, shaderstate.tex_diffuse.num, 0); + + BE_SelectMode(BEM_STANDARD); + qglClearColor (0,0,0,0); + qglClear(GL_COLOR_BUFFER_BIT); + + BE_SelectEntity(&r_worldentity); + /*now draw the prelights*/ + GLBE_SubmitMeshes(true, batches, SHADER_SORT_PRELIGHT, SHADER_SORT_PRELIGHT); + + /*final reconfigure - now drawing final surface data onto true framebuffer*/ + qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + shaderstate.tex_sourcecol = shaderstate.tex_diffuse; + qglDrawBuffer(GL_BACK); + + /*now draw the postlight passes (this includes blended stuff which will NOT be lit)*/ + BE_SelectEntity(&r_worldentity); + GLBE_SubmitMeshes(true, batches, SHADER_SORT_SKY, SHADER_SORT_NEAREST); + + /*regular lighting now*/ + Sh_DrawLights(vis); + + shaderstate.tex_sourcecol = r_nulltex; + shaderstate.tex_sourcedepth = r_nulltex; + + qglClearColor (1,0,0,1); +} + void GLBE_DrawWorld (qbyte *vis) { extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; @@ -3328,9 +3505,9 @@ void GLBE_DrawWorld (qbyte *vis) if (!r_refdef.recurse) { - if (shaderstate.wbatch > shaderstate.maxwbatches) + if (shaderstate.wbatch + 50 > shaderstate.maxwbatches) { - int newm = shaderstate.wbatch; + int newm = shaderstate.wbatch + 100; shaderstate.wbatches = BZ_Realloc(shaderstate.wbatches, newm * sizeof(*shaderstate.wbatches)); memset(shaderstate.wbatches + shaderstate.maxwbatches, 0, (newm - shaderstate.maxwbatches) * sizeof(*shaderstate.wbatches)); shaderstate.maxwbatches = newm; @@ -3339,101 +3516,75 @@ void GLBE_DrawWorld (qbyte *vis) shaderstate.wbatch = 0; } BE_GenModelBatches(batches); + R_GenDlightBatches(batches); shaderstate.curentity = &r_worldentity; shaderstate.updatetime = cl.servertime; BE_SelectEntity(&r_worldentity); -#if 0 - {int i; - for (i = 0; i < SHADER_SORT_COUNT; i++) - batches[i] = NULL; - } -#endif - - BE_UpdateLightmaps(); - //make sure the world draws correctly - r_worldentity.shaderRGBAf[0] = 1; - r_worldentity.shaderRGBAf[1] = 1; - r_worldentity.shaderRGBAf[2] = 1; - r_worldentity.shaderRGBAf[3] = 1; - r_worldentity.axis[0][0] = 1; - r_worldentity.axis[1][1] = 1; - r_worldentity.axis[2][2] = 1; - - if (gl_overbright.modified) + if (vis) { - int i; - gl_overbright.modified = false; - if (gl_overbright.ival > 2) - gl_overbright.ival = 2; + BE_UpdateLightmaps(); - for (i = 0; i < SHADER_PASS_MAX; i++) - shaderstate.blendmode[i] = -1; - } + if (gl_overbright.modified) + { + int i; + gl_overbright.modified = false; + if (gl_overbright.ival > 2) + gl_overbright.ival = 2; + + for (i = 0; i < SHADER_PASS_MAX; i++) + shaderstate.blendmode[i] = -1; + } #ifdef RTLIGHTS - if (r_shadow_realtime_world.value && gl_config.arb_shader_objects) - shaderstate.identitylighting = r_shadow_realtime_world_lightmaps.value; - else + if (r_shadow_realtime_world.value && gl_config.arb_shader_objects) + shaderstate.identitylighting = r_shadow_realtime_world_lightmaps.value; + else #endif - shaderstate.identitylighting = 1; -// shaderstate.identitylighting /= 1< shaderstate.maxwbatches) - { - int newm = shaderstate.wbatch; - shaderstate.wbatches = BZ_Realloc(shaderstate.wbatches, newm * sizeof(*shaderstate.wbatches)); - memset(shaderstate.wbatches + shaderstate.maxwbatches, 0, (newm - shaderstate.maxwbatches) * sizeof(*shaderstate.wbatches)); - shaderstate.maxwbatches = newm; - } - - shaderstate.wbatch = 0; - BE_GenModelBatches(batches); - - shaderstate.updatetime = cl.servertime; - - GLBE_SubmitMeshes(false, batches); - - BE_SelectEntity(&r_worldentity); - shaderstate.updatetime = realtime; - - checkglerror(); -} - #endif diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index a82e123c..804e6c26 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -32,6 +32,7 @@ struct world_s; typedef enum { SHADER_SORT_NONE, + SHADER_SORT_PRELIGHT, SHADER_SORT_PORTAL, SHADER_SORT_SKY, SHADER_SORT_OPAQUE, diff --git a/engine/gl/gl_rlight.c b/engine/gl/gl_rlight.c index 0f162ea2..7d5e313e 100644 --- a/engine/gl/gl_rlight.c +++ b/engine/gl/gl_rlight.c @@ -121,8 +121,11 @@ avec4_t flashblend_colours[FLASHBLEND_VERTS+1]; vecV_t flashblend_vcoords[FLASHBLEND_VERTS+1]; vec2_t flashblend_tccoords[FLASHBLEND_VERTS+1]; index_t flashblend_indexes[FLASHBLEND_VERTS*3]; +index_t flashblend_fsindexes[6] = {0, 1, 2, 0, 2, 3}; mesh_t flashblend_mesh; +mesh_t flashblend_fsmesh; shader_t *flashblend_shader; +shader_t *lpplight_shader; void R_InitFlashblends(void) { int i; @@ -143,6 +146,14 @@ void R_InitFlashblends(void) flashblend_mesh.numindexes = FLASHBLEND_VERTS*3; flashblend_mesh.istrifan = true; + flashblend_fsmesh.numvertexes = 4; + flashblend_fsmesh.xyz_array = flashblend_vcoords; + flashblend_fsmesh.st_array = flashblend_tccoords; + flashblend_fsmesh.colors4f_array = flashblend_colours; + flashblend_fsmesh.indexes = flashblend_fsindexes; + flashblend_fsmesh.numindexes = 6; + flashblend_fsmesh.istrifan = true; + flashblend_shader = R_RegisterShader("flashblend", "{\n" "{\n" @@ -153,9 +164,10 @@ void R_InitFlashblends(void) "}\n" "}\n" ); + lpplight_shader = NULL; } -void R_RenderDlight (dlight_t *light, unsigned int beflags) +static qboolean R_BuildDlightMesh(dlight_t *light, float radscale, qboolean expand) { int i, j; // float a; @@ -163,11 +175,11 @@ void R_RenderDlight (dlight_t *light, unsigned int beflags) float rad; float *bub_sin, *bub_cos; vec3_t colour; + extern cvar_t gl_mindist; bub_sin = bubble_sintable; bub_cos = bubble_costable; - rad = light->radius * 0.35; - rad = 16; + rad = light->radius * radscale; VectorCopy(light->color, colour); @@ -182,19 +194,17 @@ void R_RenderDlight (dlight_t *light, unsigned int beflags) } VectorSubtract (light->origin, r_origin, v); - if (Length (v) < rad) + if (Length (v) < rad + gl_mindist.value*2) { // view is inside the dlight - AddLightBlend (colour[0]*5, colour[1]*5, colour[2]*5, light->radius * 0.0003); - return; + return false; } flashblend_colours[0][0] = colour[0]*2; flashblend_colours[0][1] = colour[1]*2; flashblend_colours[0][2] = colour[2]*2; flashblend_colours[0][3] = 1; - - for (i=0 ; i<3 ; i++) - flashblend_vcoords[0][i] = light->origin[i] - vpn[i]*rad/1.5; + + VectorCopy(light->origin, flashblend_vcoords[0]); for (i=16 ; i>0 ; i--) { for (j=0 ; j<3 ; j++) @@ -203,8 +213,17 @@ void R_RenderDlight (dlight_t *light, unsigned int beflags) bub_sin++; bub_cos++; } - - BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, beflags); + if (!expand) + VectorMA(flashblend_vcoords[0], -rad/1.5, vpn, flashblend_vcoords[0]); + else + { + vec3_t diff; + VectorSubtract(r_origin, light->origin, diff); + VectorNormalize(diff); + for (i=0 ; i<=16 ; i++) + VectorMA(flashblend_vcoords[i], rad, diff, flashblend_vcoords[i]); + } + return true; } /* @@ -251,7 +270,88 @@ void GLR_RenderDlights (void) if (TraceLineN(r_refdef.vieworg, l->origin, waste1, waste2)) continue; } - R_RenderDlight (l, beflags); + if (!R_BuildDlightMesh (l, r_flashblendscale.value, false)) + AddLightBlend (l->color[0]*5, l->color[1]*5, l->color[2]*5, l->radius * 0.0003); + else + BE_DrawMesh_Single(flashblend_shader, &flashblend_mesh, NULL, &flashblend_shader->defaulttextures, beflags); + } +} + + +void R_GenDlightMesh(struct batch_s *batch) +{ + static mesh_t *meshptr; + dlight_t *l = cl_dlights + batch->surf_first; + + BE_SelectDLight(l, l->color); + + if (!R_BuildDlightMesh (l, 1, true)) + { + int i; + static vec2_t s[4] = {{1, -1}, {-1, -1}, {-1, 1}, {1, 1}}; + batch->flags |= BEF_FORCENODEPTH; + for (i = 0; i < 4; i++) + { + VectorMA(r_origin, 32, vpn, flashblend_vcoords[i]); + VectorMA(flashblend_vcoords[i], s[i][0]*320, vright, flashblend_vcoords[i]); + VectorMA(flashblend_vcoords[i], s[i][1]*320, vup, flashblend_vcoords[i]); + } + + meshptr = &flashblend_fsmesh; + } + else + { + meshptr = &flashblend_mesh; + } + batch->mesh = &meshptr; +} +void R_GenDlightBatches(batch_t *batches[]) +{ + int i, sort; + dlight_t *l; + batch_t *b; + if (!lpplight_shader) + lpplight_shader = R_RegisterShader("lpp_light", + "{\n" + "program lpp_light\n" + "{\n" + "map $sourcecolour\n" + "blendfunc gl_one gl_one\n" + "}\n" + "surfaceparm nodlight\n" + "lpp_light\n" + "}\n" + ); + + l = cl_dlights+rtlights_first; + for (i=rtlights_first; iradius) + continue; + + if (R_CullSphere(l->origin, l->radius)) + continue; + + b = BE_GetTempBatch(); + if (!b) + return; + + b->flags = 0; + sort = lpplight_shader->sort; + b->buildmeshes = R_GenDlightMesh; + b->ent = &r_worldentity; + b->mesh = NULL; + b->firstmesh = 0; + b->meshes = 1; + b->skin = &lpplight_shader->defaulttextures; + b->texture = NULL; + b->shader = lpplight_shader; + b->lightmap = -1; + b->surf_first = i; + b->flags |= BEF_NOSHADOWS; + b->vbo = 0; + b->next = batches[sort]; + batches[sort] = b; } } diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 13e51918..725fd6a6 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -208,7 +208,7 @@ void GL_InitFisheyeFov(void) void main(void)\ {\ texcoord = gl_MultiTexCoord0.xy;\ - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\ + gl_Position = ftetransform();\ }"; char *fisheyefshader = "\ uniform samplerCube source;\ @@ -600,7 +600,7 @@ void R_RenderScene (void) Surf_DrawWorld (); // adds static entities to the list } else - BE_DrawNonWorld(); + BE_DrawWorld(NULL); S_ExtraUpdate (); // don't let sound get messed up if going slow diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index d08da943..8d556184 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -31,6 +31,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include +#ifdef D3DQUAKE +#include +extern LPDIRECT3DDEVICE9 pD3DDev9; +#endif + extern texid_t missing_texture; static qboolean shader_reload_needed; static qboolean shader_rescan_needed; @@ -218,7 +223,9 @@ static qboolean Shader_EvaluateCondition(char **ptr) { extern cvar_t gl_bump; token++; - if (!Q_stricmp(token, "lightmap")) + if (!Q_stricmp(token, "lpp")) + conditiontrue = conditiontrue == !r_lightprepass.ival; + else if (!Q_stricmp(token, "lightmap")) conditiontrue = conditiontrue == !r_fullbright.value; else if (!Q_stricmp(token, "deluxmap") ) conditiontrue = conditiontrue == (r_deluxemapping.value && gl_bump.value); @@ -697,34 +704,41 @@ static void Shader_Sort ( shader_t *shader, shaderpass_t *pass, char **ptr ) { char *token; - token = Shader_ParseString ( ptr ); - if ( !Q_stricmp( token, "portal" ) ) { + if ( !Q_stricmp( token, "portal" ) ) shader->sort = SHADER_SORT_PORTAL; - } else if( !Q_stricmp( token, "sky" ) ) { + else if( !Q_stricmp( token, "sky" ) ) shader->sort = SHADER_SORT_SKY; - } else if( !Q_stricmp( token, "opaque" ) ) { + else if( !Q_stricmp( token, "opaque" ) ) shader->sort = SHADER_SORT_OPAQUE; - } else if( !Q_stricmp( token, "decal" ) ) { + else if( !Q_stricmp( token, "decal" ) ) shader->sort = SHADER_SORT_DECAL; - } else if( !Q_stricmp( token, "seethrough" ) ) { + else if( !Q_stricmp( token, "seethrough" ) ) shader->sort = SHADER_SORT_SEETHROUGH; - } else if( !Q_stricmp( token, "banner" ) ) { + else if( !Q_stricmp( token, "banner" ) ) shader->sort = SHADER_SORT_BANNER; - } else if( !Q_stricmp( token, "additive" ) ) { + else if( !Q_stricmp( token, "additive" ) ) shader->sort = SHADER_SORT_ADDITIVE; - } else if( !Q_stricmp( token, "underwater" ) ) { + else if( !Q_stricmp( token, "underwater" ) ) shader->sort = SHADER_SORT_UNDERWATER; - } else if( !Q_stricmp( token, "nearest" ) ) { + else if( !Q_stricmp( token, "nearest" ) ) shader->sort = SHADER_SORT_NEAREST; - } else if( !Q_stricmp( token, "blend" ) ) { + else if( !Q_stricmp( token, "blend" ) ) shader->sort = SHADER_SORT_BLEND; - } else { + else if ( !Q_stricmp( token, "lpp_light" ) ) + shader->sort = SHADER_SORT_PRELIGHT; + else + { shader->sort = atoi ( token ); clamp ( shader->sort, SHADER_SORT_NONE, SHADER_SORT_NEAREST ); } } +static void Shader_Prelight ( shader_t *shader, shaderpass_t *pass, char **ptr ) +{ + shader->sort = SHADER_SORT_PRELIGHT; +} + static void Shader_Portal ( shader_t *shader, shaderpass_t *pass, char **ptr ) { shader->sort = SHADER_SORT_PORTAL; @@ -856,7 +870,7 @@ static void Shader_LoadPermutations(char *name, program_t *prog, char *script, i permutationdefines[pn++] = permutationname[n]; } permutationdefines[pn++] = NULL; - prog->handle[p] = D3DShader_CreateProgram(permutationdefines, script, script); + D3DShader_CreateProgram(prog, p, permutationdefines, script, script); } #endif } @@ -1123,7 +1137,7 @@ struct sbuiltin_s "}\n" "#endif\n" }, -/* {QR_OPENGL, 110, "defaultsky", + {QR_OPENGL, 110, "defaultsky", "#ifdef VERTEX_SHADER\n" "varying vec3 pos;\n" @@ -1160,7 +1174,6 @@ struct sbuiltin_s "}\n" "#endif\n" }, -*/ /*draws a model. there's lots of extra stuff for light shading calcs and upper/lower textures*/ {QR_OPENGL/*ES*/, 100, "defaultskin", "!!permu FULLBRIGHT\n" @@ -1284,26 +1297,180 @@ struct sbuiltin_s "}\n" "#endif\n" }, + {QR_OPENGL, 110, "lpp_depthnorm", + "!!permu BUMP\n" + "varying vec2 pos;\n" + "varying vec3 norm, tang, bitang;\n" + "#if defined(BUMP)\n" + "varying vec2 tc;\n" + "#endif\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "attribute vec3 v_normal;\n" + "attribute vec3 v_svector;\n" + "attribute vec3 v_tvector;\n" + "uniform mat4 m_modelviewprojection;\n" + "void main(void)\n" + "{\n" + "gl_Position = ftetransform();\n" + "pos = gl_Position.zw;\n" + "norm = v_normal;\n" + "#if defined(BUMP)\n" + "tang = v_svector;\n" + "bitang = v_tvector;\n" + "tc = v_texcoord;\n" + "#endif\n" + "}\n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "#if defined(BUMP)\n" + "uniform sampler2D s_t0;\n" + "#endif\n" + "void main(void)\n" + "{\n" + "vec3 onorm;\n" + "#if defined(BUMP)\n" + /*transform by the normalmap*/ + "vec3 bm = 2.0*texture2D(s_t0, tc).xyz - 1.0;\n" + "onorm = normalize(bm.x * tang + bm.y * bitang + bm.z * norm);\n" + "#else\n" + "onorm = norm;\n" + "#endif\n" + "gl_FragColor = vec4(onorm.xyz, pos.x/pos.y);\n" + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "lpp_light", + "varying vec4 tf;\n" + "#ifdef VERTEX_SHADER\n" + "void main(void)\n" + "{\n" + "gl_Position = tf = ftetransform();\n" + "}\n" + "#endif\n" + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" + "uniform vec3 l_lightposition;\n" + "uniform mat4 m_invviewprojection;\n" + + "uniform vec3 l_lightcolour;\n" + "uniform float l_lightradius;\n" + + "vec3 calcLightWorldPos(vec2 screenPos, float depth)\n" + "{\n" + "vec4 pos;\n" + + "pos.x = screenPos.x;\n" + "pos.y = screenPos.y;\n" + "pos.z = depth;\n" + "pos.w = 1.0;\n" + "pos = m_invviewprojection * pos;\n" + "return pos.xyz / pos.w;\n" + "}\n" + + "void main (void)\n" + "{\n" + "vec3 lightColour = l_lightcolour.rgb;\n" + "float lightIntensity = 1.0;\n" + "float lightAttenuation = l_lightradius;\n" // fixme: just use the light radius for now, use better near/far att math separately once working + "float radiusFar = l_lightradius;\n" + "float radiusNear = l_lightradius*0.5;\n" + + "vec2 fc;\n" + "fc = tf.xy / tf.w;\n" + "vec4 data = texture2D(s_t0, (1.0 + fc) / 2.0);\n" + "float depth = data.a;\n" + "vec3 norm = data.xyz;\n" + + /* calc where the wall that generated this sample came from */ + "vec3 worldPos = calcLightWorldPos(fc, depth);\n" + + /*calc diffuse lighting term*/ + "vec3 lightDir = l_lightposition - worldPos;\n" + "float zdiff = 1.0 - saturate( length(lightDir) / lightAttenuation );\n" + "float atten = (radiusFar * zdiff) / (radiusFar - radiusNear);\n" + "atten = pow(atten, 2.0);\n" + "lightDir = normalize(lightDir);\n" + + "float nDotL = dot(norm, lightDir) * atten;\n" + + "float lightDiffuse = max(0.0, nDotL);\n" + + /*calc specular term*/ + // todo: specular term in its own buffer for full coloured specular + + "gl_FragColor = vec4(lightDiffuse * (lightColour * lightIntensity), 1.0);\n" +// gl_FragColor = vec4(normalize(lightDir), 0.0); + "}\n" + "#endif\n" + }, + {QR_OPENGL, 110, "lpp_wall", + "!!cvarf gl_overbright\n" + "varying vec2 tc, lm;\n" + "varying vec4 tf;\n" + "#ifdef VERTEX_SHADER\n" + "attribute vec2 v_texcoord;\n" + "attribute vec2 v_lmcoord;\n" + + "void main (void)\n" + "{\n" + "tc = v_texcoord;\n" + "lm = v_lmcoord;\n" + "gl_Position = tf = ftetransform();\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "uniform sampler2D s_t0;\n" /*lpp lighting*/ + "uniform sampler2D s_t1;\n" /*tex_diffuse*/ + "uniform sampler2D s_t2;\n" /*tex_lightmap*/ + //"uniform sampler2D s_t3;\n" /*tex_normalmap*/ + //"uniform sampler2D s_t4;\n" /*tex_deluxmap*/ + //"uniform sampler2D s_t5;\n" /*tex_fullbright*/ + "uniform float cvar_gl_overbright;\n" + + "void main (void)\n" + "{\n" + "float lmscale = exp2(floor(clamp(cvar_gl_overbright, 0.0, 2.0)));\n" + //"gl_FragColor = texture2D(s_t0, tc) * texture2D(s_t1, lm) * vec4(scale, scale, scale, 1.0);\n" + + "vec2 nst;\n" + "nst = tf.xy / tf.w;\n" + "nst = (1.0 + nst) / 2.0;\n" + "vec4 l = texture2D(s_t0, nst)*5.0;\n" + "vec4 c = texture2D(s_t1, tc);\n" + "vec3 lmsamp = texture2D(s_t2, lm).rgb*lmscale;\n" + "vec3 diff = l.rgb;\n" + "vec3 chrom = diff / (0.001 + dot(diff, vec3(0.3, 0.59, 0.11)));\n" + "vec3 spec = chrom * l.a;\n" + + "gl_FragColor = vec4((diff + lmsamp) * c.xyz, 1.0);\n" // + 0.6 * spec, 1.0); + "}\n" + "#endif\n" + }, + + + #endif -#if 0//def D3DQUAKE - {QR_DIRECT3D, 9, "defaultsky", +#ifdef D3DQUAKE + {QR_DIRECT3D, 9, "defaultsky", "struct a2v {\n" "float4 pos: POSITION;\n" "};\n" "struct v2f {\n" - "#ifdef VERTEX_SHADER\n" + "#ifndef FRAGMENT_SHADER\n" "float4 pos: POSITION;\n" - "#endif\n" - "float3 vpos: COLOR;\n" + "#endif\n" + "float3 vpos: TEXCOORD0;\n" "};\n" "#ifdef VERTEX_SHADER\n" - "float4x4 ModelViewProj;\n" + "float4x4 m_modelviewprojection;\n" "v2f main (a2v inp)\n" "{\n" " v2f outp;\n" - " outp.pos = mul(inp.pos, ModelViewProj);\n" + " outp.pos = mul(m_modelviewprojection, inp.pos);\n" " outp.vpos = inp.pos;\n" " return outp;\n" "}\n" @@ -1312,8 +1479,8 @@ struct sbuiltin_s "#ifdef FRAGMENT_SHADER\n" "float e_time;\n" "float3 e_eyepos;\n" - "sampler2D s_t0;\n" - "sampler2D s_t1;\n" + "sampler s_t0;\n" + "sampler s_t1;\n" "float4 main (v2f inp) : COLOR0\n" "{\n" " float2 tccoord;\n" @@ -1330,7 +1497,46 @@ struct sbuiltin_s " float4 clouds = tex2D(s_t1, tccoord);\n" " return float4((solid.rgb*(1.0-clouds.a)) + (clouds.a*clouds.rgb), 1);\n" -// " return solid.rgb;/*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n" +// " return float4(solid.rgb, 1);"///*gl_FragColor.g = clouds.r;*/gl_FragColor.b = clouds.a;\n" + "}\n" + "#endif\n" + }, + + {QR_DIRECT3D, 9, "defaultwarp", + "!!cvarf r_wateralpha\n" + "struct a2v {\n" + "float4 pos: POSITION;\n" + "float2 tc: TEXCOORD0;\n" + "};\n" + "struct v2f {\n" + "#ifndef FRAGMENT_SHADER\n" + "float4 pos: POSITION;\n" + "#endif\n" + "float2 tc: TEXCOORD0;\n" + "};\n" + "#ifdef VERTEX_SHADER\n" + "float4x4 m_modelviewprojection;\n" + "v2f main (a2v inp)\n" + "{\n" + " v2f outp;\n" + " outp.pos = mul(m_modelviewprojection, inp.pos);\n" + " outp.tc = inp.tc;\n" + " return outp;\n" + "}\n" + "#endif\n" + + "#ifdef FRAGMENT_SHADER\n" + "float cvar_r_wateralpha;\n" + "float e_time;\n" + "sampler s_t0;\n" + "float4 main (v2f inp) : COLOR0\n" + "{\n" + " float2 ntc;\n" + " ntc.x = inp.tc.x + sin(inp.tc.y+e_time)*0.125;\n" + " ntc.y = inp.tc.y + sin(inp.tc.x+e_time)*0.125;\n" + " float3 ts = tex2D(s_t0, ntc).xyz;\n" + + " return float4(ts, cvar_r_wateralpha);\n" "}\n" "#endif\n" }, @@ -1399,9 +1605,24 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) g->prog.refs = 1; - FS_LoadFile(name, &file); + if (strchr(name, '/') || strchr(name, '.')) + FS_LoadFile(name, &file); + else if (qrenderer == QR_DIRECT3D) + FS_LoadFile(va("hlsl/%s.hlsl", name), &file); + else if (qrenderer == QR_OPENGL) + { +#ifdef GLQUAKE + if (gl_config.gles) + FS_LoadFile(va("gles/%s.glsl", name), &file); + else +#endif + FS_LoadFile(va("glsl/%s.glsl", name), &file); + } + else + file = NULL; if (file) { + Con_DPrintf("Loaded %s from disk\n", name); Shader_LoadPermutations(name, &g->prog, file, qrtype, 0); FS_FreeFile(file); @@ -1437,6 +1658,92 @@ static program_t *Shader_LoadGeneric(char *name, int qrtype) return NULL; } +void Shader_WriteOutGenerics_f(void) +{ + int i; + char *name; + for (i = 0; *sbuiltins[i].name; i++) + { + name = NULL; + if (sbuiltins[i].qrtype == QR_OPENGL) + { + if (sbuiltins[i].apiver == 100) + name = va("gles/%s.glsl", sbuiltins[i].name); + else + name = va("glsl/%s.glsl", sbuiltins[i].name); + } + else if (sbuiltins[i].qrtype == QR_DIRECT3D) + name = va("hlsl/%s.hlsl", sbuiltins[i].name); + + if (name) + { + vfsfile_t *f = FS_OpenVFS(name, "rb", FS_GAMEONLY); + if (f) + { + int len = VFS_GETLEN(f); + char *buf = Hunk_TempAlloc(len); + VFS_READ(f, buf, len); + if (len != strlen(sbuiltins[i].body) || memcmp(buf, sbuiltins[i].body, len)) + Con_Printf("Not writing %s - modified version in the way\n", name); + else + Con_Printf("%s is unmodified\n", name); + VFS_CLOSE(f); + } + else + { + Con_Printf("Writing %s\n", name); + FS_WriteFile(name, sbuiltins[i].body, strlen(sbuiltins[i].body), FS_GAMEONLY); + } + } + } +} + +struct shader_field_names_s shader_field_names[] = +{ + /*vertex attributes*/ + {"v_position", SP_ATTR_VERTEX}, + {"v_colour", SP_ATTR_COLOUR}, + {"v_texcoord", SP_ATTR_TEXCOORD}, + {"v_lmcoord", SP_ATTR_LMCOORD}, + {"v_normal", SP_ATTR_NORMALS}, + {"v_svector", SP_ATTR_SNORMALS}, + {"v_tvector", SP_ATTR_TNORMALS}, + {"v_bone", SP_ATTR_BONENUMS}, + {"v_weight", SP_ATTR_BONEWEIGHTS}, + + /*matricies*/ + {"m_model", SP_M_MODEL}, + {"m_view", SP_M_VIEW}, + {"m_modelview", SP_M_MODELVIEW}, + {"m_projection", SP_M_PROJECTION}, + {"m_modelviewprojection", SP_M_MODELVIEWPROJECTION}, + {"m_bones", SP_M_ENTBONES}, + {"m_invviewprojection", SP_M_INVVIEWPROJECTION}, + {"m_invmodelviewprojection",SP_M_INVMODELVIEWPROJECTION}, + + /*viewer properties*/ + {"v_eyepos", SP_V_EYEPOS}, + + /*ent properties*/ + {"e_origin", SP_E_ORIGIN}, + {"e_time", SP_E_TIME}, + {"e_eyepos", SP_E_EYEPOS}, + {"e_colour", SP_E_COLOURS}, + {"e_colourident", SP_E_COLOURSIDENT}, + {"e_glowmod", SP_E_GLOWMOD}, + {"e_topcolour", SP_E_TOPCOLOURS}, + {"e_bottomcolour", SP_E_BOTTOMCOLOURS}, + {"e_light_dir", SP_E_L_DIR}, + {"e_light_mul", SP_E_L_MUL}, + {"e_light_ambient", SP_E_L_AMBIENT}, + + /*rtlight properties, use with caution*/ + {"l_lightradius", SP_LIGHTRADIUS}, + {"l_lightcolour", SP_LIGHTCOLOUR}, + {"l_lightposition", SP_LIGHTPOSITION}, + {NULL} +}; + static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) { unsigned int i, p; @@ -1444,43 +1751,7 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) int uniformloc; char tmpname[128]; cvar_t *cvar; - static struct - { - char *name; - enum shaderprogparmtype_e ptype; - } u[] = - { - /*vertex attributes*/ - {"v_position", SP_ATTR_VERTEX}, - {"v_colour", SP_ATTR_COLOUR}, - {"v_texcoord", SP_ATTR_TEXCOORD}, - {"v_lmcoord", SP_ATTR_LMCOORD}, - {"v_normal", SP_ATTR_NORMALS}, - {"v_svector", SP_ATTR_SNORMALS}, - {"v_tvector", SP_ATTR_TNORMALS}, - {"v_bone", SP_ATTR_BONENUMS}, - {"v_weight", SP_ATTR_BONEWEIGHTS}, - /*matricies*/ - {"m_model", SP_MODELMATRIX}, - {"m_view", SP_VIEWMATRIX}, - {"m_modelview", SP_MODELVIEWMATRIX}, - {"m_projection", SP_PROJECTIONMATRIX}, - {"m_modelviewprojection", SP_MODELVIEWPROJECTIONMATRIX}, - {"m_bones", SP_ENTBONEMATRICIES}, - - /*ent properties*/ - {"e_time", SP_TIME}, - {"e_eyepos", SP_EYEPOS}, - {"e_colour", SP_ENTCOLOURS}, - {"e_colourident", SP_ENTCOLOURSIDENT}, - {"e_topcolour", SP_TOPCOLOURS}, - {"e_bottomcolour", SP_BOTTOMCOLOURS}, - {"e_light_dir", SP_E_L_DIR}, - {"e_light_mul", SP_E_L_MUL}, - {"e_light_ambient", SP_E_L_AMBIENT}, - {NULL} - }; prog->numparams = 0; #ifdef GLQUAKE if (qrenderer == QR_OPENGL) @@ -1502,13 +1773,13 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) { if (!prog->handle[p].glsl) continue; - GLSlang_UseProgram(prog->handle[p].glsl); + GL_SelectProgram(prog->handle[p].glsl); uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, va("cvar_%s", tmpname)); if (uniformloc != -1) qglUniform1fARB(uniformloc, cvar->value); } } - for (i = 0; u[i].name; i++) + for (i = 0; shader_field_names[i].name; i++) { found = false; for (p = 0; p < PERMUTATIONS; p++) @@ -1516,20 +1787,20 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) if (!prog->handle[p].glsl) continue; GLSlang_UseProgram(prog->handle[p].glsl); - if (u[i].ptype >= SP_FIRSTUNIFORM) - uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, u[i].name); + if (shader_field_names[i].ptype >= SP_FIRSTUNIFORM) + uniformloc = qglGetUniformLocationARB(prog->handle[p].glsl, shader_field_names[i].name); else - uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, u[i].name); + uniformloc = qglGetAttribLocationARB(prog->handle[p].glsl, shader_field_names[i].name); if (uniformloc != -1) found = true; prog->parm[prog->numparams].handle[p] = uniformloc; } if (found) { - prog->parm[prog->numparams].type = u[i].ptype; + prog->parm[prog->numparams].type = shader_field_names[i].ptype; prog->numparams++; - if (u[i].ptype < SP_FIRSTUNIFORM) + if (shader_field_names[i].ptype < SP_FIRSTUNIFORM) prog->nofixedcompat = true; } } @@ -1546,7 +1817,84 @@ static void Shader_ProgAutoFields(program_t *prog, char **cvarfnames) qglUniform1iARB(uniformloc, i); } } - GLSlang_UseProgram(0); + return; + } +#endif +#ifdef D3DQUAKE + if (qrenderer == QR_DIRECT3D) + { + prog->nofixedcompat = true; + + /*set cvar uniforms*/ + for (i = 0; cvarfnames[i]; i++) + { + for (p = 0; cvarfnames[i][p] && (unsigned char)cvarfnames[i][p] > 32 && p < sizeof(tmpname)-1; p++) + tmpname[p] = cvarfnames[i][p]; + tmpname[p] = 0; + cvar = Cvar_FindVar(tmpname); + if (!cvar) + continue; + cvar->flags |= CVAR_SHADERSYSTEM; + for (p = 0; p < PERMUTATIONS; p++) + { + if (!prog->handle[p].glsl) + continue; + uniformloc = D3DShader_FindUniform(&prog->handle[p], 1, va("cvar_%s", tmpname)); + if (uniformloc != -1) + { + vec4_t v = {cvar->value, 0, 0, 0}; + IDirect3DDevice9_SetVertexShader(pD3DDev9, prog->handle[0].hlsl.vert); + IDirect3DDevice9_SetVertexShaderConstantF(pD3DDev9, 0, v, 1); + } + uniformloc = D3DShader_FindUniform(&prog->handle[p], 2, va("cvar_%s", tmpname)); + if (uniformloc != -1) + { + vec4_t v = {cvar->value, 0, 0, 0}; + IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->handle[0].hlsl.vert); + IDirect3DDevice9_SetPixelShaderConstantF(pD3DDev9, 0, v, 1); + } + } + } + for (i = 0; shader_field_names[i].name; i++) + { + found = false; + for (p = 0; p < PERMUTATIONS; p++) + { + if (shader_field_names[i].ptype >= SP_FIRSTUNIFORM) + { + uniformloc = D3DShader_FindUniform(&prog->handle[p], 0, shader_field_names[i].name); + } + else + uniformloc = -1; + if (uniformloc != -1) + found = true; + prog->parm[prog->numparams].handle[p] = uniformloc; + } + if (found) + { + prog->parm[prog->numparams].type = shader_field_names[i].ptype; + prog->numparams++; + + if (shader_field_names[i].ptype < SP_FIRSTUNIFORM) + prog->nofixedcompat = true; + } + } + /*set texture uniforms*/ + for (p = 0; p < PERMUTATIONS; p++) + { + for (i = 0; i < 8; i++) + { + uniformloc = D3DShader_FindUniform(&prog->handle[p], 2, va("s_t%i", i)); + if (uniformloc != -1) + { + int v[4] = {i}; + IDirect3DDevice9_SetPixelShader(pD3DDev9, prog->handle[0].hlsl.vert); + IDirect3DDevice9_SetPixelShaderConstantI(pD3DDev9, 0, v, 1); + } + } + } + IDirect3DDevice9_SetVertexShader(pD3DDev9, NULL); + IDirect3DDevice9_SetPixelShader(pD3DDev9, NULL); } #endif } @@ -1685,17 +2033,17 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p parmtype = SP_CVAR3F; } else if (!Q_stricmp(token, "time")) - parmtype = SP_TIME; + parmtype = SP_E_TIME; else if (!Q_stricmp(token, "eyepos")) - parmtype = SP_EYEPOS; + parmtype = SP_E_EYEPOS; else if (!Q_stricmp(token, "entmatrix")) - parmtype = SP_ENTMATRIX; + parmtype = SP_M_MODEL; else if (!Q_stricmp(token, "colours") || !Q_stricmp(token, "colors")) - parmtype = SP_ENTCOLOURS; + parmtype = SP_E_COLOURS; else if (!Q_stricmp(token, "upper")) - parmtype = SP_TOPCOLOURS; + parmtype = SP_E_TOPCOLOURS; else if (!Q_stricmp(token, "lower")) - parmtype = SP_BOTTOMCOLOURS; + parmtype = SP_E_BOTTOMCOLOURS; else if (!Q_stricmp(token, "lightradius")) parmtype = SP_LIGHTRADIUS; else if (!Q_stricmp(token, "lightcolour")) @@ -1805,6 +2153,7 @@ static shaderkey_t shaderkeys[] = {"sort", Shader_Sort}, {"deformvertexes", Shader_DeformVertexes}, {"portal", Shader_Portal}, + {"lpp_light", Shader_Prelight}, {"entitymergable", Shader_EntityMergable}, {"glslprogram", Shader_GLSLProgramName}, @@ -1886,6 +2235,16 @@ static qboolean ShaderPass_MapGen (shader_t *shader, shaderpass_t *pass, char *t pass->texgen = T_GEN_CURRENTRENDER; pass->tcgen = TC_GEN_BASE; //FIXME: moo! } + else if (!Q_stricmp (tname, "$sourcecolour")) + { + pass->texgen = T_GEN_SOURCECOLOUR; + pass->tcgen = TC_GEN_BASE; //FIXME: moo! + } + else if (!Q_stricmp (tname, "$sourcedepth")) + { + pass->texgen = T_GEN_SOURCEDEPTH; + pass->tcgen = TC_GEN_BASE; //FIXME: moo! + } else return false; return true; @@ -2253,7 +2612,7 @@ static void Shaderpass_TcMod (shader_t *shader, shaderpass_t *pass, char **ptr) tcmod_t *tcmod; char *token; - if (pass->numtcmods >= SHADER_TCMOD_MAX) + if (pass->numtcmods >= SHADER_MAX_TC_MODS) { return; } @@ -3504,6 +3863,32 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "}\n" ); #ifdef GLQUAKE + if (!builtin && r_lightprepass.ival) + { + builtin = ( + "{\n" + "program lpp_wall\n" + "{\n" + "map $sourcecolour\n" + "}\n" + "{\n" + "map $diffuse\n" + "}\n" + "{\n" + "map $lightmap\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $deluxmap\n" + "}\n" + "{\n" + "map $fullbright\n" + "}\n" + "}\n" + ); + } if (!builtin && gl_config.arb_shader_objects && gl_config.nofixedfunc) { builtin = ( @@ -3934,7 +4319,14 @@ void Shader_DefaultSkin(char *shortname, shader_t *s, const void *args) { Shader_DefaultScript(shortname, s, "{\n" - "program defaultskin\n" + "if $lpp\n" + "[\n" + "program defaultskin\n" + "]\n" + "else\n" + "[\n" + "program lpp_skin\n" + "]\n" "{\n" "map $diffuse\n" "rgbgen lightingDiffuse\n" diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index b4d51685..7cff501d 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1218,7 +1218,7 @@ static qboolean Sh_ScissorForBox(vec3_t mins, vec3_t maxs) return true; // set up the scissor rectangle qglScissor(ix1, iy1, ix2 - ix1, iy2 - iy1); - //qglEnable(GL_SCISSOR_TEST); +// qglEnable(GL_SCISSOR_TEST); return false; } @@ -1229,7 +1229,7 @@ void GL_BeginRenderBuffer_DepthOnly(texid_t depthtexture) { if (!shadow_fbo_id) { - qglGenRenderbuffersEXT(1, &shadow_fbo_id); + qglGenFramebuffersEXT(1, &shadow_fbo_id); qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, shadow_fbo_id); qglDrawBuffer(GL_NONE); qglReadBuffer(GL_NONE); @@ -1855,7 +1855,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) BE_SelectMode(BEM_STENCIL); //The backend doesn't maintain scissor state. -// qglEnable(GL_SCISSOR_TEST); + //qglEnable(GL_SCISSOR_TEST); //The backend doesn't maintain stencil test state either - it needs to be active for more than just stencils, or disabled. its awkward. qglEnable(GL_STENCIL_TEST); @@ -2065,7 +2065,9 @@ void Sh_DrawLights(qbyte *vis) extern cvar_t r_shadow_realtime_world_shadows, r_shadow_realtime_dlight_shadows; if (!r_shadow_realtime_world.ival && !r_shadow_realtime_dlight.ival) + { return; + } /*no stencil?*/ if (gl_config.nofixedfunc) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 67f6d7fa..a4c5f73a 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -122,6 +122,8 @@ void (APIENTRY *qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint* ids); void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id); void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId, GLint level); +void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); +GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); /* PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB; @@ -647,14 +649,16 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name), float ver) if (GL_CheckExtension("GL_EXT_framebuffer_object")) { gl_config.ext_framebuffer_objects = true; - qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffersEXT"); - qglDeleteFramebuffersEXT = (void *)getglext("glDeleteFramebuffersEXT"); - qglBindFramebufferEXT = (void *)getglext("glBindFramebufferEXT"); - qglGenRenderbuffersEXT = (void *)getglext("glGenRenderbuffersEXT"); - qglDeleteRenderbuffersEXT = (void *)getglext("glDeleteRenderbuffersEXT"); - qglBindRenderbufferEXT = (void *)getglext("glBindRenderbufferEXT"); - qglRenderbufferStorageEXT = (void *)getglext("glRenderbufferStorageEXT"); - qglFramebufferTexture2DEXT = (void *)getglext("glFramebufferTexture2DEXT"); + qglGenFramebuffersEXT = (void *)getglext("glGenFramebuffersEXT"); + qglDeleteFramebuffersEXT = (void *)getglext("glDeleteFramebuffersEXT"); + qglBindFramebufferEXT = (void *)getglext("glBindFramebufferEXT"); + qglGenRenderbuffersEXT = (void *)getglext("glGenRenderbuffersEXT"); + qglDeleteRenderbuffersEXT = (void *)getglext("glDeleteRenderbuffersEXT"); + qglBindRenderbufferEXT = (void *)getglext("glBindRenderbufferEXT"); + qglRenderbufferStorageEXT = (void *)getglext("glRenderbufferStorageEXT"); + qglFramebufferTexture2DEXT = (void *)getglext("glFramebufferTexture2DEXT"); + qglFramebufferRenderbufferEXT = (void *)getglext("glFramebufferRenderbufferEXT"); + qglCheckFramebufferStatusEXT = (void *)getglext("glCheckFramebufferStatusEXT"); } #ifdef DEBUG @@ -716,8 +720,8 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi if (gl_config.nofixedfunc) { prstrings[strings++] = - "#define ftetransform() (m_projection * m_modelview * vec4(v_position, 1.0))\n" - "uniform mat4 m_modelview, m_projection;\n" + "#define ftetransform() (m_modelviewprojection * vec4(v_position, 1.0))\n" + "uniform mat4 m_modelviewprojection;\n" "attribute vec3 v_position;\n"; } else @@ -726,9 +730,9 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi "#ifdef SKELETAL\n" "attribute vec4 v_bone;\n" "attribute vec4 v_weight;\n" - "uniform mat4 m_modelview, m_projection;\n" + "uniform mat4 m_modelviewprojection;\n" "uniform mat3x4 m_bones["STRINGIFY(MAX_BONES)"];\n" - "#define v_position gl_Vertex\n" + "attribute vec3 v_position;\n" "vec4 skeletaltransform()\n" "{" @@ -737,7 +741,7 @@ GLhandleARB GLSlang_CreateShader (char *name, char *versionline, char **precompi " wmat += m_bones[int(v_bone.y)] * v_weight.y;\n" " wmat += m_bones[int(v_bone.z)] * v_weight.z;\n" " wmat += m_bones[int(v_bone.w)] * v_weight.w;\n" - " return m_projection * m_modelview * vec4(v_position * wmat, v_position.w);\n" + " return m_modelviewprojection * vec4(vec4(v_position.xyz, 1.0) * wmat, 1.0);\n" "}\n" "#define ftetransform() skeletaltransform()\n" "#else\n" diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index ad33cb29..bb14af8d 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -333,6 +333,7 @@ void R_DrawHLModel(entity_t *curent); // gl_rlight.c // void GLR_RenderDlights (void); +void R_GenDlightBatches(batch_t *batches[]); #ifdef GLQUAKE void GLR_MarkQ2Lights (dlight_t *light, int bit, mnode_t *node); void R_InitFlashblends (void); @@ -750,6 +751,8 @@ extern void (APIENTRY *qglDeleteRenderbuffersEXT)(GLsizei n, const GLuint* ids); extern void (APIENTRY *qglBindRenderbufferEXT)(GLenum target, GLuint id); extern void (APIENTRY *qglRenderbufferStorageEXT)(GLenum target, GLenum internalFormat, GLsizei width, GLsizei height); extern void (APIENTRY *qglFramebufferTexture2DEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId, GLint level); +extern void (APIENTRY *qglFramebufferRenderbufferEXT)(GLenum target, GLenum attachmentPoint, GLenum textureTarget, GLuint textureId); +extern GLenum (APIENTRY *qglCheckFramebufferStatusEXT)(GLenum target); /* extern qboolean gl_arb_fragment_program; diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 4218038e..58d3b7ed 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -53,7 +53,6 @@ typedef struct SHADER_TCMOD_SCROLL, //boring moving texcoords with time SHADER_TCMOD_STRETCH, //constant factor SHADER_TCMOD_ROTATE, - SHADER_TCMOD_MAX, SHADER_TCMOD_TRANSFORM, SHADER_TCMOD_TURB } type; @@ -221,6 +220,9 @@ typedef struct shaderpass_s { T_GEN_CURRENTRENDER,//copy the current screen to a texture, and draw that + T_GEN_SOURCECOLOUR, //used for render-to-texture targets + T_GEN_SOURCEDEPTH, //used for render-to-texture targets + T_GEN_VIDEOMAP, //use the media playback as an image source, updating each frame for which it is visible T_GEN_SKYBOX, //use a skybox instead, otherwise T_GEN_SINGLEMAP } texgen; @@ -275,23 +277,27 @@ typedef struct { SP_FIRSTUNIFORM, //never set /*entity properties*/ - SP_ENTCOLOURS, - SP_ENTCOLOURSIDENT, - SP_TOPCOLOURS, - SP_BOTTOMCOLOURS, - SP_TIME, + SP_E_ORIGIN, + SP_E_COLOURS, + SP_E_COLOURSIDENT, + SP_E_GLOWMOD, + SP_E_TOPCOLOURS, + SP_E_BOTTOMCOLOURS, + SP_E_TIME, SP_E_L_DIR, /*these light values are non-dynamic light as in classic quake*/ SP_E_L_MUL, SP_E_L_AMBIENT, + SP_E_EYEPOS, /*viewer's eyepos, in model space*/ + SP_V_EYEPOS, /*viewer's eyepos, in world space*/ - SP_ENTBONEMATRICIES, - SP_EYEPOS, - SP_ENTMATRIX, - SP_VIEWMATRIX, - SP_MODELMATRIX, - SP_MODELVIEWMATRIX, - SP_PROJECTIONMATRIX, - SP_MODELVIEWPROJECTIONMATRIX, + SP_M_ENTBONES, + SP_M_VIEW, + SP_M_MODEL, + SP_M_MODELVIEW, + SP_M_PROJECTION, + SP_M_MODELVIEWPROJECTION, + SP_M_INVVIEWPROJECTION, + SP_M_INVMODELVIEWPROJECTION, SP_RENDERTEXTURESCALE, /*multiplier for currentrender->texcoord*/ @@ -325,6 +331,8 @@ union programhandle_u { void *vert; void *frag; + void *ctabf; + void *ctabv; } hlsl; #endif }; @@ -429,6 +437,7 @@ void R_BackendInit (void); void Shader_Shutdown (void); qboolean Shader_Init (void); void Shader_NeedReload(void); +void Shader_WriteOutGenerics_f(void); mfog_t *CM_FogForOrigin(vec3_t org); @@ -470,7 +479,8 @@ void D3DBE_DrawWorld (qbyte *vis); qboolean D3DBE_LightCullModel(vec3_t org, model_t *model); void D3DBE_SelectEntity(entity_t *ent); -union programhandle_u D3DShader_CreateProgram (char **precompilerconstants, char *vert, char *frag); +void D3DShader_CreateProgram (program_t *prog, int permu, char **precompilerconstants, char *vert, char *frag); +int D3DShader_FindUniform(union programhandle_u *h, int type, char *name); void D3DShader_Init(void); #endif @@ -496,4 +506,10 @@ void BE_BaseEntShadowDepth(void); //Sets the given light+colour to be the current one that everything is to be lit/culled by. void BE_SelectDLight(dlight_t *dl, vec3_t colour); #endif + +struct shader_field_names_s +{ + char *name; + enum shaderprogparmtype_e ptype; +} shader_field_names[]; #endif diff --git a/engine/http/iwebiface.c b/engine/http/iwebiface.c index 2cbe398d..167838d7 100644 --- a/engine/http/iwebiface.c +++ b/engine/http/iwebiface.c @@ -463,7 +463,7 @@ int IWebAuthorize(char *name, char *password) return IWEBACC_READ; #else #ifndef CLIENTONLY - int id = Rank_GetPlayerID(name, atoi(password), false, true); + int id = Rank_GetPlayerID(NULL, name, atoi(password), false, true); rankinfo_t info; if (!id) { diff --git a/engine/qclib/execloop.h b/engine/qclib/execloop.h index 8fe1db91..f095d1b4 100644 --- a/engine/qclib/execloop.h +++ b/engine/qclib/execloop.h @@ -35,6 +35,12 @@ #error Bad cont size #endif +#ifdef DEBUGABLE +#define OPCODE (st->op & ~0x8000) +#else +#define OPCODE (st->op) +#endif + #define ENGINEPOINTER(p) ((char*)(p) - progfuncs->stringtable) #define QCPOINTER(p) (eval_t *)(p->_int+progfuncs->stringtable) #define QCPOINTERM(p) (eval_t *)((p)+progfuncs->stringtable) @@ -49,11 +55,10 @@ cont: //last statement may have been a breakpoint st = pr_statements + s; reeval: - switch (st->op & ~0x8000) #else st++; - switch (st->op) #endif + switch (OPCODE) { case OP_ADD_F: OPC->_float = OPA->_float + OPB->_float; @@ -567,11 +572,10 @@ reeval: RUNAWAYCHECK(); pr_xstatement = st-pr_statements; - - if (st->op > OP_CALL8) - pr_argc = st->op - (OP_CALL1H-1); + if (OPCODE > OP_CALL8) + pr_argc = OPCODE - (OP_CALL1H-1); else - pr_argc = st->op - OP_CALL0; + pr_argc = OPCODE - OP_CALL0; fnum = OPA->function; if ((fnum & ~0xff000000)==0) { @@ -743,7 +747,7 @@ if (pr_typecurrent != 0) //array/structure reading/writing. case OP_GLOBALADDRESS: - OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); + OPC->_int = ENGINEPOINTER(&OPA->_int + OPB->_int); /*pointer arithmatic*/ break; case OP_POINTER_ADD: //pointer to 32 bit (remember to *3 for vectors) OPC->_int = OPA->_int + OPB->_int*4; @@ -755,7 +759,7 @@ if (pr_typecurrent != 0) case OP_LOADA_ENT: case OP_LOADA_S: case OP_LOADA_FNC: - ptr = (eval_t *)(&OPA->_int + OPB->_int); + ptr = (eval_t *)(&OPA->_int + OPB->_int); /*pointer arithmatic*/ OPC->_int = ptr->_int; break; @@ -784,7 +788,7 @@ if (pr_typecurrent != 0) case OP_LOADP_ENT: case OP_LOADP_S: case OP_LOADP_FNC: - ptr = QCPOINTERM(OPA->_int + OPB->_int); + ptr = QCPOINTERM(OPA->_int + OPB->_int*p); OPC->_int = ptr->_int; break; @@ -859,44 +863,44 @@ if (pr_typecurrent != 0) break; case OP_RAND0: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff); + OPC->_float = (rand()&0x7fff)/((float)0x7fff); break; case OP_RAND1: - G_FLOAT(OFS_RETURN) = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; + OPC->_float = (rand()&0x7fff)/((float)0x7fff)*OPA->_float; break; case OP_RAND2: if(OPA->_float < OPB->_float) { - G_FLOAT(OFS_RETURN) = OPA->_float+((rand()&0x7fff)/((float)0x7fff) + OPC->_float = OPA->_float+((rand()&0x7fff)/((float)0x7fff) *(OPB->_float-OPA->_float)); } else { - G_FLOAT(OFS_RETURN) = OPB->_float+((rand()&0x7fff)/((float)0x7fff) + OPC->_float = OPB->_float+((rand()&0x7fff)/((float)0x7fff) *(OPA->_float-OPB->_float)); } break; case OP_RANDV0: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff); - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff); + OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff); + OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff); + OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff); break; case OP_RANDV1: - G_FLOAT(OFS_RETURN+0) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; - G_FLOAT(OFS_RETURN+1) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; - G_FLOAT(OFS_RETURN+2) = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; + OPC->_vector[0] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[0]; + OPC->_vector[1] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[1]; + OPC->_vector[2] = (rand()&0x7fff)/((float)0x7fff)*OPA->_vector[2]; break; case OP_RANDV2: for(i = 0; i < 3; i++) { if(OPA->_vector[i] < OPB->_vector[i]) { - G_FLOAT(OFS_RETURN+i) = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) + OPC->_vector[i] = OPA->_vector[i]+((rand()&0x7fff)/((float)0x7fff) *(OPB->_vector[i]-OPA->_vector[i])); } else { - G_FLOAT(OFS_RETURN+i) = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) + OPC->_vector[i] = OPB->_vector[i]+(rand()*(1.0f/RAND_MAX) *(OPA->_vector[i]-OPB->_vector[i])); } } @@ -909,7 +913,7 @@ if (pr_typecurrent != 0) case OP_SWITCH_E: case OP_SWITCH_FNC: swtch = OPA; - swtchtype = st->op; + swtchtype = OPCODE; RUNAWAYCHECK(); st += (sofs)st->b - 1; // offset the st++ break; @@ -1072,7 +1076,7 @@ if (pr_typecurrent != 0) if ((unsigned int)OPA->_int < (unsigned int)st->c || (unsigned int)OPA->_int >= (unsigned int)st->b) { pr_xstatement = st-pr_statements; - PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i.", OPA->_int); + PR_RunError(progfuncs, "Progs boundcheck failed. Value is %i. Must be between %u and %u", OPA->_int, st->c, st->b); } break; /* case OP_PUSH: @@ -1124,6 +1128,7 @@ if (pr_typecurrent != 0) #undef dstatement_t #undef sofs #undef uofs +#undef OPCODE #undef ENGINEPOINTER #undef QCPOINTER diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index a67b3685..1f854f05 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -2922,6 +2922,9 @@ retry: break; } } + if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2) + if (!st16[i].c) + st16[i].c = OFS_RETURN; } if (hexencalling) { @@ -2951,6 +2954,9 @@ retry: break; } } + if (st16[i].op >= OP_RAND0 && st16[i].op <= OP_RANDV2) + if (!st16[i].c) + st16[i].c = OFS_RETURN; } if (hexencalling) { diff --git a/engine/qclib/pr_multi.c b/engine/qclib/pr_multi.c index a375e889..e9505254 100644 --- a/engine/qclib/pr_multi.c +++ b/engine/qclib/pr_multi.c @@ -45,9 +45,9 @@ void PR_MoveParms(progfuncs_t *progfuncs, progsnum_t progs1, progsnum_t progs2) p2 = &pr_progstate[(int)progs2]; if ((unsigned)progs1 >= maxprogs || !p1->globals) - Sys_Error("QCLIB: Bad prog type - %i", progs1); + PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", progs1); if ((unsigned)progs2 >= maxprogs || !p2->globals) - Sys_Error("QCLIB: Bad prog type - %i", progs2); + PR_RunError(progfuncs, "QCLIB: Bad prog type - %i", progs2); //copy parms. for (a = 0; a < MAX_PARMS;a++) diff --git a/engine/qclib/qcc.h b/engine/qclib/qcc.h index 13d85a60..cdb79468 100644 --- a/engine/qclib/qcc.h +++ b/engine/qclib/qcc.h @@ -533,7 +533,8 @@ void QCC_PR_Lex (void); // reads the next token into pr_token and classifies its type QCC_type_t *QCC_PR_NewType (char *name, int basictype); -QCC_type_t *QCC_PR_ParseType (int newtype); extern pbool type_inlinefunction; +QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail); +extern pbool type_inlinefunction; QCC_type_t *QCC_TypeForName(char *name); QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype); QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype); @@ -542,6 +543,8 @@ CompilerConstant_t *QCC_PR_DefineName(char *name); void QCC_RemapOffsets(unsigned int firststatement, unsigned int laststatement, unsigned int min, unsigned int max, unsigned int newmin); +int QCC_PR_IntConstExpr(void); + #ifndef COMMONINLINES pbool QCC_PR_CheckImmediate (char *string); pbool QCC_PR_CheckToken (char *string); diff --git a/engine/qclib/qcc_pr_comp.c b/engine/qclib/qcc_pr_comp.c index daafed1e..ff76d22a 100644 --- a/engine/qclib/qcc_pr_comp.c +++ b/engine/qclib/qcc_pr_comp.c @@ -355,8 +355,8 @@ QCC_opcode_t pr_opcodes[] = {7, "", "CALL8H", -1, ASSOC_LEFT, &type_function, &type_vector, &type_vector}, {7, "=", "STORE_I", 6, ASSOC_RIGHT, &type_integer, &type_integer, &type_integer}, - {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_integer}, - {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_float}, + {7, "=", "STORE_IF", 6, ASSOC_RIGHT, &type_float, &type_integer, &type_integer}, + {7, "=", "STORE_FI", 6, ASSOC_RIGHT, &type_integer, &type_float, &type_float}, {7, "+", "ADD_I", 4, ASSOC_LEFT, &type_integer, &type_integer, &type_integer}, {7, "+", "ADD_FI", 4, ASSOC_LEFT, &type_float, &type_integer, &type_float}, @@ -592,6 +592,7 @@ pbool OpAssignsToB(unsigned int op) #undef ASSOC_RIGHT_RESULT #define TOP_PRIORITY 7 +#define FUNC_PRIORITY 1 #define UNARY_PRIORITY 1 #define NOT_PRIORITY 5 //conditional and/or @@ -1094,8 +1095,14 @@ Emits a primitive statement, returning the var it places it's value in QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement); static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted) { + /*no conversion needed*/ + if (var->type->type == wanted) + return 0; if (var->type->type == ev_integer && wanted == ev_function) return 0; + if (var->type->type == ev_integer && wanted == ev_pointer) + return 0; + /*stuff needs converting*/ if (var->type->type == ev_pointer && var->type->aux_type) { if (var->type->aux_type->type == ev_float && wanted == ev_integer) @@ -1113,10 +1120,12 @@ static int QCC_ShouldConvert(QCC_def_t *var, etype_t wanted) return OP_CONV_ITOF; } + /*impossible*/ return -1; } -QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted) +QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted, pbool fatal) { + extern char *basictypenames[]; int o; if (pr_classtype && var->type->type == ev_field && wanted != ev_field) @@ -1145,9 +1154,15 @@ QCC_def_t *QCC_SupplyConversion(QCC_def_t *var, etype_t wanted) o = QCC_ShouldConvert(var, wanted); - if (o <= 0) //no conversion + if (o == 0) //type already matches return var; - + if (o < 0) + { + if (fatal) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, var, "Implicit type mismatch. Needed %s, got %s.", basictypenames[wanted], var->type->name); + else + return var; + } return QCC_PR_Statement(&pr_opcodes[o], var, NULL, NULL); //conversion return value } @@ -1498,7 +1513,10 @@ static void QCC_fprintfLocals(FILE *f, gofs_t paramstart, gofs_t paramend) { if (var->ofs >= paramstart && var->ofs < paramend) continue; - fprintf(f, "local %s %s;\n", TypeName(var->type), var->name); + if (var->arraysize != 1) + fprintf(f, "local %s %s[%i];\n", TypeName(var->type), var->name, var->arraysize); + else + fprintf(f, "local %s %s;\n", TypeName(var->type), var->name); } for (t = functemps, i = 0; t; t = t->next, i++) @@ -1612,6 +1630,8 @@ static const char *QCC_VarAtOffset(unsigned int ofs, unsigned int size) } #endif +QCC_dstatement_t *QCC_PR_SimpleStatement( int op, int var_a, int var_b, int var_c, int force); + QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var_b, QCC_dstatement_t **outstatement) { QCC_dstatement_t *statement; @@ -1619,29 +1639,19 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var if (outstatement == (QCC_dstatement_t **)0xffffffff) outstatement = NULL; - else if (op->priority != -1) + else if (op->priority != -1 && op->priority != CONDITION_PRIORITY) { if (op->associative!=ASSOC_LEFT) { - if (op->type_a == &type_pointer) - var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type); - else - var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type); + if (op->type_a != &type_pointer) + var_b = QCC_SupplyConversion(var_b, (*op->type_a)->type, false); } else { if (var_a) - var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type); + var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type, false); if (var_b) - var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type); -// if (op->type_a == &def_pointer) -// var_a = QCC_SupplyConversion(var_a, (*op->type_b)->type); -// else -// var_a = QCC_SupplyConversion(var_a, (*op->type_a)->type); -// } -// //can't convert the left componant of an assignment operation -// if (var_b && var_b->type && var_b->type != op->type_b->type) -// var_b = QCC_SupplyConversion(var_b, op->type_b->type->type); + var_b = QCC_SupplyConversion(var_b, (*op->type_b)->type, false); } } @@ -1750,9 +1760,11 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var //a is const, b is not switch (op - pr_opcodes) { + case OP_STORE_FI: case OP_CONV_FTOI: optres_constantarithmatic++; return QCC_MakeIntDef(G_FLOAT(var_a->ofs)); + case OP_STORE_IF: case OP_CONV_ITOF: optres_constantarithmatic++; return QCC_MakeFloatDef(G_INT(var_a->ofs)); @@ -1877,7 +1889,7 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var return var_a; } case OP_AND_I: - if (G_INT(var_b->ofs) != 0) + if (G_INT(var_b->ofs) == 0) { optres_constantarithmatic++; QCC_UnFreeTemp(var_a); @@ -1890,6 +1902,15 @@ QCC_def_t *QCC_PR_Statement ( QCC_opcode_t *op, QCC_def_t *var_a, QCC_def_t *var switch (op - pr_opcodes) { + case OP_LOADA_F: + case OP_LOADA_V: + case OP_LOADA_S: + case OP_LOADA_ENT: + case OP_LOADA_FLD: + case OP_LOADA_FNC: + case OP_LOADA_I: + QCC_PR_SimpleStatement (OP_BOUNDCHECK, var_b->ofs, var_a->arraysize, 0, false);//annoy the programmer. :p + break; case OP_AND_F: if (var_a->ofs == var_b->ofs) QCC_PR_ParseWarning(WARN_CONSTANTCOMPARISON, "Parameter offsets for && are the same"); @@ -3082,6 +3103,15 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could if (!t->num_parms&&t->type != ev_variant) //intrinsics. These base functions have variable arguments. I would check for (...) args too, but that might be used for extended builtin functionality. (this code wouldn't compile otherwise) { + if (!strcmp(func->name, "sizeof")) + { + QCC_type_t *t; + func->initialized = 1; + func->references++; + t = QCC_PR_ParseType(false, false); + QCC_PR_Expect(")"); + return QCC_MakeIntDef(t->size * 4); + } if (!strcmp(func->name, "random")) { old = NULL; @@ -3108,12 +3138,24 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could d = NULL; } + out = &def_ret; if (QCC_OPCodeValid(&pr_opcodes[OP_RAND0])) { - if(def_ret.temp->used) + if(qcc_targetformat != QCF_HEXEN2) out = QCC_GetTemp(type_float); + else if (out->temp->used) + { + old = QCC_GetTemp(out->type); + if (def_ret.type->size == 3) + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL)); + else + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL)); + QCC_UnFreeTemp(old); + QCC_UnFreeTemp(out); + QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); + } else - out = &def_ret; + old = NULL; if (e) { @@ -3127,15 +3169,15 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could } else { - if (def_ret.temp->used) + if (out->temp->used) { - old = QCC_GetTemp(def_ret.type); + old = QCC_GetTemp(out->type); if (def_ret.type->size == 3) - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], &def_ret, old, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], out, old, NULL)); else - QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], &def_ret, old, NULL)); + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], out, old, NULL)); QCC_UnFreeTemp(old); - QCC_UnFreeTemp(&def_ret); + QCC_UnFreeTemp(out); QCC_PR_ParseWarning(WARN_FIXEDRETURNVALUECONFLICT, "Return value conflict - output is inefficient"); } else @@ -3205,16 +3247,20 @@ QCC_def_t *QCC_PR_ParseFunctionCall (QCC_def_t *func) //warning, the func could return d; } - if (def_ret.temp->used) - QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid"); - def_ret.temp->used = true; - def_ret.type = type_float; - return &def_ret; + if (out == &def_ret) + { + if (out->temp->used) + QCC_PR_ParseWarning(0, "Return value conflict - output is likly to be invalid"); + out->temp->used = true; + out->type = type_float; + } + return out; } if (!strcmp(func->name, "randomv")) { out = NULL; + func->initialized = 1; func->references++; if (!QCC_PR_CheckToken(")")) { @@ -3859,7 +3905,7 @@ QCC_type_t *QCC_PR_NewType (char *name, int basictype); QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type) { QCC_type_t *newtype; - newtype = QCC_PR_NewType("POINTER TYPE", ev_pointer); + newtype = QCC_PR_NewType("ptr", ev_pointer); newtype->aux_type = type; return newtype; } @@ -4100,11 +4146,10 @@ Returns the global ofs for the current token */ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) { - QCC_def_t *ao=NULL; //arrayoffset - QCC_def_t *d, *nd, *od; + QCC_def_t *d, *od, *tmp, *idx; + QCC_type_t *t; char *name; QCC_dstatement_t *st; - int i; char membername[2048]; @@ -4139,43 +4184,44 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) while(type != type_entity && type) { sprintf(membername, "%s::"MEMBERFIELDNAME, type->name, name); - od = d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); + d = QCC_PR_GetDef (NULL, membername, pr_scope, false, 0, false); if (d) break; type = type->parentclass; } if (!d) - od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); + d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); } else // look through the defs - od = d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); + d = QCC_PR_GetDef (NULL, name, pr_scope, false, 0, false); if (!d) { if ( (!strcmp(name, "random" )) || (!strcmp(name, "randomv")) || + (!strcmp(name, "sizeof")) || (!strcmp(name, "entnum")) ) //intrinsics, any old function with no args will do. - od = d = QCC_PR_GetDef (type_function, name, NULL, true, 1, false); + d = QCC_PR_GetDef (type_function, name, NULL, true, 1, false); else if (keyword_class && !strcmp(name, "this")) { if (!pr_classtype) QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'this' outside of an OO function\n"); od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false); - od = d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 1, od->ofs, true, false); + d = QCC_PR_DummyDef(pr_classtype, "this", pr_scope, 1, od->ofs, true, false); } else if (keyword_class && !strcmp(name, "super")) { if (!pr_classtype) QCC_PR_ParseError(ERR_NOTANAME, "Cannot use 'super' outside of an OO function\n"); od = QCC_PR_GetDef(NULL, "self", NULL, true, 1, false); - od = d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 1, od->ofs, true, false); + d = QCC_PR_DummyDef(pr_classtype, "super", pr_scope, 1, od->ofs, true, false); } else { - od = d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 1, false); + d = QCC_PR_GetDef (type_variant, name, pr_scope, true, 1, false); if (!d) QCC_PR_ParseError (ERR_UNKNOWNVALUE, "Unknown value \"%s\"", name); else @@ -4185,6 +4231,280 @@ QCC_def_t *QCC_PR_ParseValue (QCC_type_t *assumeclass, pbool allowarrayassign) } } +#if 0 + if (keyword_class) + { + if (d->type->parentclass||d->type->type == ev_entity) //class + { + if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")) + { + QCC_def_t *field; + if (QCC_PR_CheckToken("(")) + { + field = QCC_PR_Expression(TOP_PRIORITY, 0); + QCC_PR_Expect(")"); + } + else + field = QCC_PR_ParseValue(d->type, false); + if (field->type->type == ev_field) + { + if (!field->type->aux_type) + { + QCC_PR_ParseWarning(ERR_INTERNAL, "Field with null aux_type"); + return QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL); + } + else + { + switch(field->type->aux_type->type) + { + default: + QCC_PR_ParseError(ERR_INTERNAL, "Bad field type"); + return d; + case ev_integer: + return QCC_PR_Statement(&pr_opcodes[OP_LOAD_I], d, field, NULL); + case ev_field: + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FLD], d, field, NULL); + nd = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (nd, 0, sizeof(QCC_def_t)); + nd->type = field->type->aux_type; + nd->ofs = d->ofs; + nd->temp = d->temp; + nd->constant = false; + nd->name = d->name; + return nd; + case ev_float: + return QCC_PR_Statement(&pr_opcodes[OP_LOAD_F], d, field, NULL); + case ev_string: + return QCC_PR_Statement(&pr_opcodes[OP_LOAD_S], d, field, NULL); + case ev_vector: + return QCC_PR_Statement(&pr_opcodes[OP_LOAD_V], d, field, NULL); + case ev_function: + { //complicated for a typecast + d = QCC_PR_Statement(&pr_opcodes[OP_LOAD_FNC], d, field, NULL); + nd = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (nd, 0, sizeof(QCC_def_t)); + nd->type = field->type->aux_type; + nd->ofs = d->ofs; + nd->temp = d->temp; + nd->constant = false; + nd->name = d->name; + return nd; + + } + case ev_entity: + return QCC_PR_Statement(&pr_opcodes[OP_LOAD_ENT], d, field, NULL); + } + } + } + else + QCC_PR_IncludeChunk(".", false, NULL); + } + } + } +#endif + + t = d->type; + idx = NULL; + while(1) + { + if (QCC_PR_CheckToken("[")) + { + tmp = QCC_PR_Expression (TOP_PRIORITY, 0); + QCC_PR_Expect("]"); + if (tmp->constant) + { + int i; + if (tmp->type->type == ev_integer) + i = G_INT(tmp->ofs); + else if (tmp->type->type == ev_float) + i = G_FLOAT(tmp->ofs); +// if (i < 0 || i >= ???) +// QCC_PR_ParseWarning(0, "(constant) array index out of bounds"); + } + else + { + //QCC_PR_SimpleStatement (OP_BOUNDCHECK, tmp->ofs, ???, 0, false); + } + if (!idx && t->type == ev_pointer && d->arraysize == 1) + t = t->aux_type; + if (idx) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL); + else + idx = tmp; + } + else if ((t->type == ev_pointer || t->type == ev_struct || t->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))) + { + if (!idx && t->type == ev_pointer) + t = t->aux_type; + for (t = t->param; t; t = t->next) + { + if (QCC_PR_CheckName(t->name)) + { + break; + } + + } + if (!t) + QCC_PR_ParseError(0, "%s is not a member", pr_token); + + tmp = QCC_MakeIntDef(t->ofs); + if (idx) + idx = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], idx, tmp, NULL); + else + idx = tmp; + } + else + break; + } + + if (idx) + { + if (d->type->type == ev_pointer) + { + switch (t->type) + { + case ev_pointer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_float: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_integer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_string: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_vector: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_entity: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_field: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_function: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_struct: + case ev_union: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + + default: + QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); + } + d->type = t; + } + else + /*if (idx->constant) + { + /* if the index is known, we can just directly read/write the actual value * / + writeme + } + else*/ + if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) + { + /*don't care about assignments. the code can convert an OP_LOADA_F to an OP_ADDRESS on assign*/ + /*source type is a struct, or its an array, or something that can otherwise be directly accessed*/ + switch(t->type) + { + case ev_pointer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_float: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_integer: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_string: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_vector: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_entity: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_field: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + case ev_function: + d = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(idx, ev_integer, true), NULL); + break; + default: + QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); + } + d->type = t; + } + else if (allowarrayassign && QCC_PR_CheckToken("=")) + { + /*if its assigned to, generate a functioncall to do the store*/ + QCC_def_t *args[2], *funcretr, *rhs; + + funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); + + rhs = QCC_PR_Expression(TOP_PRIORITY, 0); + if (rhs->type->type != d->type->type) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); + + args[0] = QCC_SupplyConversion(idx, ev_float, true); + args[1] = rhs; + qcc_usefulstatement=true; + d = QCC_PR_GenerateFunctionCall(funcretr, args, 2); + d->type = t; + } + else if (QCC_OPCodeValid(&pr_opcodes[OP_FETCH_GBL_F])) + { +QCC_PR_ParseWarning(0, "untested"); + /*hexen2 format has opcodes to read arrays (but has no way to write)*/ + switch(t->type) + { + case ev_float: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; + break; + case ev_vector: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; + break; + case ev_string: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; + break; + case ev_entity: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; + break; + case ev_function: + d = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, QCC_SupplyConversion(idx, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; + break; + default: + QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); + d = NULL; + break; + } + d->type = t; + } + else + { + /*emulate the array access using a function call to do the read for us*/ + QCC_def_t *args[1], *funcretr; + + /*make sure the function type that we're calling exists*/ + def_parms[0].type = type_float; + funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false); + + args[0] = QCC_SupplyConversion(idx, ev_float, true); + d = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + d->type = t; + } + } + +#if 0 reloop: @@ -4240,7 +4560,7 @@ reloop: ao = QCC_PR_Expression (TOP_PRIORITY, 0); QCC_PR_Expect("]"); - if (QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F]) && d->type->size != 1) //we need to multiply it to find the offset. + if (d->type->size != 1 && QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) //we need to multiply it to find the offset. { if (ao->type->type == ev_integer) ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], ao, QCC_MakeIntDef(d->type->size), NULL); //get add part @@ -4255,260 +4575,175 @@ reloop: newtype = d->type; } - if (ao->type->type == ev_integer) - { + + if (qcc_targetformat == QCF_HEXEN2) + { //hexen2 style retrieval, mixed with q1 style assignments... + if (QCC_PR_CheckToken("=")) //(hideous concept) + { + QCC_def_t *funcretr; + QCC_def_t *args[2]; + if (d->scope) + QCC_PR_ParseError(0, "Scoped array without specific engine support"); + + funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); + nd = QCC_PR_Expression(TOP_PRIORITY, 0); + if (nd->type->type != d->type->type) + QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); + + args[0] = QCC_SupplyConversion(ao, ev_float, true); + args[1] = nd; + return QCC_PR_GenerateFunctionCall(funcretr, args, 2); + } + switch(newtype->type) { case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, ao, NULL); //get pointer to precise def. - break; - case ev_string: - if (d->arraysize <= 1) - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], ao, 0, NULL), NULL); //get pointer to precise def. - newtype = nd->type;//don't be fooled - } - else - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, ao, NULL); //get pointer to precise def. - } + nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, QCC_SupplyConversion(ao, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; break; case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, ao, NULL); //get pointer to precise def. + nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, QCC_SupplyConversion(ao, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; + break; + case ev_string: + nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, QCC_SupplyConversion(ao, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; break; case ev_entity: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, ao, NULL); //get pointer to precise def. - break; - case ev_field: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, ao, NULL); //get pointer to precise def. + nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, QCC_SupplyConversion(ao, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; break; case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, ao, NULL); //get pointer to precise def. - nd->type = d->type; - break; - case ev_pointer: - if (ao->constant && !G_INT(ao->ofs)) - ao->ofs = 0; - if (d->arraysize>1) //use the array - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. - newtype = d->type->aux_type; - } - else - { //dereference the pointer. - ao = QCC_PR_Statement(&pr_opcodes[OP_MUL_I], ao, QCC_MakeIntDef(4), NULL); - switch(newtype->aux_type->type) - { - case ev_pointer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, ao, NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, ao, NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, ao, NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - } - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. - break; - case ev_struct: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, ao, NULL); //get pointer to precise def. - nd->type = d->type; + nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, QCC_SupplyConversion(ao, ev_float, true), &st); //get pointer to precise def. + st->a = d->ofs; break; default: QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); nd = NULL; break; } + QCC_FreeTemp(d); + QCC_FreeTemp(ao); + d=nd; + d->type = newtype; + return d; } - else if (ao->type->type == ev_float) + else { - if (qcc_targetformat == QCF_HEXEN2) - { //hexen2 style retrieval, mixed with q1 style assignments... - if (QCC_PR_CheckToken("=")) //(hideous concept) + if (!QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) //q1 compatible. + { //you didn't see this, okay? + QCC_def_t *funcretr; + if (d->scope) + QCC_PR_ParseError(0, "Scoped array without specific engine support"); + + if (allowarrayassign && QCC_PR_CheckToken("=")) { - QCC_def_t *funcretr; QCC_def_t *args[2]; - if (d->scope) - QCC_PR_ParseError(0, "Scoped array without specific engine support"); funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); + nd = QCC_PR_Expression(TOP_PRIORITY, 0); if (nd->type->type != d->type->type) QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - args[0] = ao; + args[0] = QCC_SupplyConversion(ao, ev_float, true); args[1] = nd; - return QCC_PR_GenerateFunctionCall(funcretr, args, 2); + qcc_usefulstatement=true; + nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2); + nd->type = d->type->aux_type; } + else + { + QCC_def_t *args[1]; + def_parms[0].type = type_float; + funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false); + + args[0] = QCC_SupplyConversion(ao, ev_float, true); + nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1); + nd->type = d->type->aux_type; + } + } + else + { switch(newtype->type) { - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_F], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; + case ev_pointer: + if (d->arraysize>1) //use the array + { + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + nd->type = d->type->aux_type; + } + else + { //dereference the pointer. + switch(newtype->aux_type->type) + { + case ev_pointer: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + newtype = d->type->aux_type; + break; + case ev_float: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + newtype = d->type->aux_type; + break; + case ev_vector: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + newtype = d->type->aux_type; + break; + case ev_integer: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + newtype = d->type->aux_type; + break; + default: + QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); + nd = NULL; + break; + } + } break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_V], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; + + case ev_float: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. break; case ev_string: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_S], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; + if (d->arraysize <= 1) + { + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, QCC_SupplyConversion(ao, ev_float, true), NULL); //get pointer to precise def. + newtype = nd->type;//don't be fooled + } + else + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + break; + case ev_vector: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. break; case ev_entity: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_E], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + break; + case ev_field: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. break; case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_FETCH_GBL_FNC], d, ao, &st); //get pointer to precise def. - st->a = d->ofs; + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + nd->type = d->type; + break; + case ev_integer: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + break; + + case ev_struct: + nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_SupplyConversion(ao, ev_integer, true), NULL); //get pointer to precise def. + nd->type = d->type; break; default: QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); nd = NULL; break; } - QCC_FreeTemp(d); - QCC_FreeTemp(ao); - - d=nd; - d->type = newtype; - return d; } - else - { - if (!QCC_OPCodeValid(&pr_opcodes[OP_LOADA_F])) //q1 compatible. - { //you didn't see this, okay? - QCC_def_t *funcretr; - if (d->scope) - QCC_PR_ParseError(0, "Scoped array without specific engine support"); - - if (allowarrayassign && QCC_PR_CheckToken("=")) - { - QCC_def_t *args[2]; - - funcretr = QCC_PR_GetDef(type_function, qcva("ArraySet*%s", d->name), NULL, true, 1, false); - - nd = QCC_PR_Expression(TOP_PRIORITY, 0); - if (nd->type->type != d->type->type) - QCC_PR_ParseErrorPrintDef(ERR_TYPEMISMATCH, d, "Type Mismatch on array assignment"); - - args[0] = ao; - args[1] = nd; - qcc_usefulstatement=true; - nd = QCC_PR_GenerateFunctionCall(funcretr, args, 2); - nd->type = d->type->aux_type; - } - else - { - QCC_def_t *args[1]; - - def_parms[0].type = type_float; - funcretr = QCC_PR_GetDef(type_function, qcva("ArrayGet*%s", d->name), NULL, true, 1, false); - - args[0] = ao; - nd = QCC_PR_GenerateFunctionCall(funcretr, args, 1); - nd->type = d->type->aux_type; - } - } - else - { - switch(newtype->type) - { - case ev_pointer: - if (d->arraysize>1) //use the array - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type->aux_type; - } - else - { //dereference the pointer. - switch(newtype->aux_type->type) - { - case ev_pointer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - newtype = d->type->aux_type; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - } - break; - - case ev_float: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_F], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_string: - if (d->arraysize <= 1) - { - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADP_C], d, ao, NULL); //get pointer to precise def. - newtype = nd->type;//don't be fooled - } - else - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_S], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_vector: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_V], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_entity: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_ENT], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_field: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FLD], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - case ev_function: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_FNC], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type; - break; - case ev_integer: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - break; - - case ev_struct: - nd = QCC_PR_Statement(&pr_opcodes[OP_LOADA_I], d, QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], ao, 0, NULL), NULL); //get pointer to precise def. - nd->type = d->type; - break; - default: - QCC_PR_ParseError(ERR_NOVALIDOPCODES, "No op available. Try assembler"); - nd = NULL; - break; - } - } - } - d=nd; } - else - QCC_PR_ParseError(ERR_BADARRAYINDEXTYPE, "Array offset is not of integer or float type"); + d=nd; d->type = newtype; goto reloop; @@ -4519,10 +4754,10 @@ reloop: if (i == ev_pointer) { int j; - QCC_type_t *type; - if (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->")) + QCC_type_t *type = d->type->aux_type; + if ((type->type == ev_struct || type->type == ev_union) && (QCC_PR_CheckToken(".") || QCC_PR_CheckToken("->"))) { - for (i = d->type->num_parms, type = d->type+1; i; i--, type++) + for (type = type->param;type;type = type->next) { if (QCC_PR_CheckName(type->name)) { @@ -4578,11 +4813,6 @@ reloop: d=nd; break; } - if (type->num_parms) - { - for (j = type->num_parms; j;j--) - type++; - } } if (!i) QCC_PR_ParseError (ERR_MEMBERNOTVALID, "\"%s\" is not a member of \"%s\"", pr_token, od->type->name); @@ -4747,7 +4977,7 @@ reloop: QCC_PR_IncludeChunk(".", false, NULL); } } - +#endif return d; } @@ -4837,18 +5067,30 @@ QCC_def_t *QCC_PR_Term (void) else if (QCC_PR_CheckToken ("&")) { int st = numstatements; - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); t = e->type->type; if (st != numstatements) //woo, something like ent.field? { - if ((unsigned)(statements[numstatements-1].op - OP_LOAD_F) < 6 || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P) + if ((OP_LOAD_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOAD_FNC) || statements[numstatements-1].op == OP_LOAD_I || statements[numstatements-1].op == OP_LOAD_P) { statements[numstatements-1].op = OP_ADDRESS; e->type = QCC_PR_PointerType(e->type); return e; } + else if (OP_LOADA_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADA_I) + { + statements[numstatements-1].op = OP_GLOBALADDRESS; + e->type = QCC_PR_PointerType(e->type); + return e; + } + else if (OP_LOADP_F <= statements[numstatements-1].op && statements[numstatements-1].op <= OP_LOADP_I) + { + statements[numstatements-1].op = OP_POINTER_ADD; + e->type = QCC_PR_PointerType(e->type); + return e; + } else //this is a restriction that could be lifted, I just want to make sure that I got all the bits first. { QCC_PR_ParseError (ERR_BADNOTTYPE, "type mismatch for '&' Must be singular expression or field reference"); @@ -4866,7 +5108,7 @@ QCC_def_t *QCC_PR_Term (void) } else if (QCC_PR_CheckToken ("*")) { - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); t = e->type->type; if (t != ev_pointer) @@ -4912,7 +5154,7 @@ QCC_def_t *QCC_PR_Term (void) } else if (QCC_PR_CheckToken ("-")) { - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); switch(e->type->type) { @@ -4934,7 +5176,7 @@ QCC_def_t *QCC_PR_Term (void) } else if (QCC_PR_CheckToken ("+")) { - e = QCC_PR_Expression (UNARY_PRIORITY, 0); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); switch(e->type->type) { @@ -4957,7 +5199,40 @@ QCC_def_t *QCC_PR_Term (void) if (QCC_PR_CheckToken ("(")) { - if (QCC_PR_CheckToken("*")) + QCC_type_t *newtype; + newtype = QCC_PR_ParseType(false, true); + if (newtype) + { + QCC_PR_Expect (")"); + e = QCC_PR_Expression (UNARY_PRIORITY, EXPR_DISALLOW_COMMA); + + /*you may cast from const 0 to any type of same size for free (from either int or float for simplicity)*/ + if (newtype->size == e->type->size && (e->type->type == ev_integer || e->type->type == ev_float) && e->constant && !G_INT(e->ofs)) + { + } + /*cast from int->float will convert*/ + else if (newtype->type == ev_float && e->type->type == ev_integer) + return QCC_PR_Statement (&pr_opcodes[OP_CONV_ITOF], e, 0, NULL); + /*cast from float->int will convert*/ + else if (newtype->type == ev_integer && e->type->type == ev_float) + return QCC_PR_Statement (&pr_opcodes[OP_CONV_FTOI], e, 0, NULL); + /*you may freely cast between pointers (and ints, as this is explicit) (strings count as pointers - WARNING: some strings may not be expressable as pointers)*/ + else if ((newtype->type == ev_pointer || newtype->type == ev_string || newtype->type == ev_integer) && (e->type->type == ev_pointer || e->type->type == ev_string || e->type->type == ev_integer)) + { + /*pointer cast*/ + e2 = (void *)qccHunkAlloc (sizeof(QCC_def_t)); + memset (e2, 0, sizeof(QCC_def_t)); + + e2->type = newtype; + e2->ofs = e->ofs; + e2->constant = true; + e2->temp = e->temp; + return e2; + } + else + QCC_PR_ParseError(0, "Bad type cast\n"); + } +/* else if (QCC_PR_CheckToken("*")) { QCC_PR_Expect (")"); e = QCC_PR_Term(); @@ -5030,7 +5305,7 @@ QCC_def_t *QCC_PR_Term (void) else QCC_PR_ParseError (ERR_BADTYPECAST, "invalid typecast"); } - else +*/ else { pbool oldcond = conditional; conditional = conditional?2:0; @@ -5099,7 +5374,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) while (1) { - if (priority == 1) + if (priority == FUNC_PRIORITY) { if (QCC_PR_CheckToken ("(") ) { @@ -5192,7 +5467,7 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) } else { - statements[numstatements-1].op = OP_ADD_I; + statements[numstatements-1].op = OP_POINTER_ADD; if (e->type->type != ev_pointer) { type_pointer->aux_type->type = e->type->type; @@ -5513,13 +5788,26 @@ QCC_def_t *QCC_PR_Expression (int priority, int exprflags) if (!(exprflags&EXPR_DISALLOW_COMMA) && priority == TOP_PRIORITY && QCC_PR_CheckToken (",")) { + if (!qcc_usefulstatement) + QCC_PR_ParseWarning(WARN_POINTLESSSTATEMENT, "Effectless statement"); + QCC_FreeTemp(e); - return QCC_PR_Expression(TOP_PRIORITY, exprflags); + qcc_usefulstatement = false; + e = QCC_PR_Expression(TOP_PRIORITY, exprflags); } return e; } +int QCC_PR_IntConstExpr(void) +{ + QCC_def_t *def = QCC_PR_Expression(7, 0); + if (!def->constant) + QCC_PR_ParseError(ERR_BADARRAYSIZE, "Array size is not a constant value"); + def = QCC_SupplyConversion(def, ev_integer, true); + return G_INT(def->ofs); +} + void QCC_PR_GotoStatement (QCC_dstatement_t *patch2, char *labelname) { if (num_gotos >= max_gotos) @@ -5614,7 +5902,7 @@ void QCC_PR_ParseStatement (void) return; } e = QCC_PR_Expression (TOP_PRIORITY, 0); - e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type); + e2 = QCC_SupplyConversion(e, pr_scope->type->aux_type->type, true); if (e != e2) { QCC_PR_ParseWarning(WARN_CORRECTEDRETURNTYPE, "\'%s\' returned %s, expected %s, conversion supplied", pr_scope->name, e->type->name, pr_scope->type->aux_type->name); @@ -7244,7 +7532,7 @@ void QCC_WriteAsmFunction(QCC_def_t *sc, unsigned int firststatement, gofs_t fir } } } - fprintf(asmfile, ";\n"); + fprintf(asmfile, "; /*%i*/\n", statement_linenums[i]); } fprintf(asmfile, "}\n\n"); @@ -7398,7 +7686,7 @@ QCC_function_t *QCC_PR_ParseImmediateStatements (QCC_type_t *type) do { name = QCC_PR_ParseName(); QCC_PR_Expect(":"); - e2 = QCC_PR_GetDef(QCC_PR_ParseType(false), name, pr_scope, true, 1, false); + e2 = QCC_PR_GetDef(QCC_PR_ParseType(false, false), name, pr_scope, true, 1, false); QCC_PR_Expect(";"); } while(!QCC_PR_CheckToken("{")); } @@ -8391,10 +8679,12 @@ void QCC_PR_ParseDefs (char *classname) pbool nosave = false; pbool allocatenew = true; pbool inlinefunction = false; - int ispointer; gofs_t oldglobals; int arraysize; + while (QCC_PR_CheckToken(";")) + ; + if (QCC_PR_CheckKeyword(keyword_enum, "enum")) { if (QCC_PR_CheckKeyword(keyword_integer, "integer") || QCC_PR_CheckKeyword(keyword_int, "int")) @@ -8610,7 +8900,7 @@ void QCC_PR_ParseDefs (char *classname) if (QCC_PR_CheckKeyword (keyword_typedef, "typedef")) { - type = QCC_PR_ParseType(true); + type = QCC_PR_ParseType(true, false); if (!type) { QCC_PR_ParseError(ERR_NOTANAME, "typedef found unexpected tokens"); @@ -8781,7 +9071,7 @@ void QCC_PR_ParseDefs (char *classname) break; } - type = QCC_PR_ParseType (false); + type = QCC_PR_ParseType (false, false); if (type == NULL) //ignore return; @@ -8884,15 +9174,8 @@ void QCC_PR_ParseDefs (char *classname) // QCC_PR_ParseError ("Fields must be global"); do - { - if (QCC_PR_CheckToken ("*")) - { - ispointer = 1; - while(QCC_PR_CheckToken ("*")) - ispointer++; - name = QCC_PR_ParseName (); - } - else if (QCC_PR_CheckToken (";")) + { + if (QCC_PR_CheckToken (";")) { if (type->type == ev_field && (type->aux_type->type == ev_union || type->aux_type->type == ev_struct)) { @@ -8905,12 +9188,10 @@ void QCC_PR_ParseDefs (char *classname) // } QCC_PR_ParseError (ERR_TYPEWITHNONAME, "type with no name"); name = NULL; - ispointer = false; } else { name = QCC_PR_ParseName (); - ispointer = false; } if (QCC_PR_CheckToken("::") && !classname) @@ -9013,19 +9294,7 @@ void QCC_PR_ParseDefs (char *classname) oldglobals = numpr_globals; - if (ispointer) - { - parm = type; - while(ispointer) - { - ispointer--; - parm = QCC_PointerTypeTo(parm); - } - - def = QCC_PR_GetDef (parm, name, pr_scope, allocatenew, arraysize, !nosave); - } - else - def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave); + def = QCC_PR_GetDef (type, name, pr_scope, allocatenew, arraysize, !nosave); if (!def) QCC_PR_ParseError(ERR_NOTANAME, "%s is not part of class %s", name, classname); @@ -9138,20 +9407,59 @@ void QCC_PR_ParseDefs (char *classname) def->initialized = 1; continue; } - else if (def->type->size >= 3) + else if (def->type->type == ev_vector) { QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_V], d, def, NULL)); def->constant = false; def->initialized = false; continue; } - else + else if (def->type->type == ev_float) { QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_F], d, def, NULL)); def->constant = false; def->initialized = false; continue; } + else if (def->type->type == ev_integer) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_I], d, def, NULL)); + def->constant = false; + def->initialized = false; + continue; + } + else if (def->type->type == ev_pointer) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_P], d, def, NULL)); + def->constant = false; + def->initialized = false; + continue; + } + else if (def->type->type == ev_string) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_S], d, def, NULL)); + def->constant = false; + def->initialized = false; + continue; + } + else if (def->type->type == ev_entity) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_ENT], d, def, NULL)); + def->constant = false; + def->initialized = false; + continue; + } + else if (def->type->type == ev_function) + { + QCC_FreeTemp(QCC_PR_Statement(&pr_opcodes[OP_STORE_FNC], d, def, NULL)); + def->constant = false; + def->initialized = false; + continue; + } + else + { + QCC_PR_ParseErrorPrintDef (ERR_BADIMMEDIATETYPE, def, "initialiser is not constant", name); + } } else if (pr_token_type == tt_name) diff --git a/engine/qclib/qcc_pr_lex.c b/engine/qclib/qcc_pr_lex.c index e42afff7..ce743b5e 100644 --- a/engine/qclib/qcc_pr_lex.c +++ b/engine/qclib/qcc_pr_lex.c @@ -2828,7 +2828,12 @@ char *QCC_PR_ParseName (void) char *ret; if (pr_token_type != tt_name) - QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token); + { + if (pr_token_type == tt_eof) + QCC_PR_ParseError (ERR_EOF, "unexpected EOF", pr_token); + else + QCC_PR_ParseError (ERR_NOTANAME, "\"%s\" - not a name", pr_token); + } if (strlen(pr_token) >= MAX_NAME-1) QCC_PR_ParseError (ERR_NAMETOOLONG, "name too long"); strcpy (ident, pr_token); @@ -3105,7 +3110,7 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype) break; } - nptype = QCC_PR_ParseType(true); + nptype = QCC_PR_ParseType(true, false); if (nptype->type == ev_void) break; @@ -3188,7 +3193,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) { name = QCC_PR_ParseName(); QCC_PR_Expect(":"); - nptype = QCC_PR_ParseType(true); + nptype = QCC_PR_ParseType(true, false); } if (nptype->type == ev_void) @@ -3219,12 +3224,17 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype) } QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto) { - QCC_type_t *ptype; - char name[128]; - sprintf(name, "*%s", pointsto->name); - ptype = QCC_PR_NewType(name, ev_pointer); + QCC_type_t *ptype, *e; + ptype = QCC_PR_NewType("ptr", ev_pointer); ptype->aux_type = pointsto; - return QCC_PR_FindType (ptype); + e = QCC_PR_FindType (ptype); + if (e == ptype) + { + char name[128]; + sprintf(name, "ptr to %s", pointsto->name); + e->name = strdup(name); + } + return e; } QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto) { @@ -3238,7 +3248,10 @@ QCC_type_t *QCC_PR_FieldType (QCC_type_t *pointsto) } pbool type_inlinefunction; -QCC_type_t *QCC_PR_ParseType (int newtype) +/*newtype=true: creates a new type always + silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL +*/ +QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) { QCC_type_t *newparm; QCC_type_t *newt; @@ -3253,7 +3266,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges) { newt = QCC_PR_NewType("FIELD TYPE", ev_field); - newt->aux_type = QCC_PR_ParseType (false); + newt->aux_type = QCC_PR_ParseType (false, false); newt->size = newt->aux_type->size; @@ -3271,7 +3284,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) if (QCC_PR_CheckToken (".")) { newt = QCC_PR_NewType("FIELD TYPE", ev_field); - newt->aux_type = QCC_PR_ParseType (false); + newt->aux_type = QCC_PR_ParseType (false, false); newt->size = newt->aux_type->size; @@ -3345,7 +3358,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) // if (QCC_PR_CheckToken(",")) // type->next = QCC_PR_NewType(type->name, type->type); // else - newparm = QCC_PR_ParseType(true); + newparm = QCC_PR_ParseType(true, false); if (newparm->type == ev_struct || newparm->type == ev_union) //we wouldn't be able to handle it. QCC_PR_ParseError(ERR_INTERNAL, "Struct or union in class %s", classname); @@ -3407,7 +3420,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) newparm = QCC_PR_NewType(newparm->name, newparm->type); } else - newparm = QCC_PR_ParseType(true); + newparm = QCC_PR_ParseType(true, false); if (!QCC_PR_CheckToken(";")) { @@ -3415,8 +3428,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) QCC_PR_Lex(); if (QCC_PR_CheckToken("[")) { - newparm->size*=atoi(pr_token); - QCC_PR_Lex(); + newparm->size*=QCC_PR_IntConstExpr(); QCC_PR_Expect("]"); } QCC_PR_CheckToken(";"); @@ -3454,7 +3466,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype) newparm = QCC_PR_NewType(newparm->name, newparm->type); } else - newparm = QCC_PR_ParseType(true); + newparm = QCC_PR_ParseType(true, false); if (QCC_PR_CheckToken(";")) newparm->name = QCC_CopyString("")+strings; else @@ -3504,16 +3516,22 @@ QCC_type_t *QCC_PR_ParseType (int newtype) type = type_function; else { + if (silentfail) + return NULL; + QCC_PR_ParseError (ERR_NOTATYPE, "\"%s\" is not a type", name); type = type_float; // shut up compiler warning } } QCC_PR_Lex (); + while (QCC_PR_CheckToken("*")) + type = QCC_PointerTypeTo(type); + if (QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function. { type_inlinefunction = true; - return QCC_PR_ParseFunctionType(newtype, type); + type = QCC_PR_ParseFunctionType(newtype, type); } else { @@ -3521,9 +3539,8 @@ QCC_type_t *QCC_PR_ParseType (int newtype) { type = QCC_PR_DuplicateType(type); } - - return type; } + return type; } #endif diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index 1e22aadc..50ac2a64 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -238,7 +238,8 @@ compiler_flag_t compiler_flag[] = { {&flag_filetimes, 0, "filetimes", "Check Filetimes", "Recompiles the progs only if the file times are modified."}, {&flag_fasttrackarrays, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"fastarrays","fast arrays where possible", "Generates extra instructions inside array handling functions to detect engine and use extension opcodes only in supporting engines.\nAdds a global which is set by the engine if the engine supports the extra opcodes. Note that this applies to all arrays or none."}, {&flag_assume_integer, FLAG_MIDCOMPILE,"assumeint", "Assume Integers", "Numerical constants are assumed to be integers, instead of floats."}, - {&pr_subscopedlocals, FLAG_MIDCOMPILE, "subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."}, + {&pr_subscopedlocals, FLAG_MIDCOMPILE,"subscope", "Subscoped Locals", "Restrict the scope of locals to the block they are actually defined within, as in C."}, + {&verbose, FLAG_MIDCOMPILE,"verbose", "Verbose", "Lots of extra compiler messages."}, {NULL} }; @@ -2865,10 +2866,10 @@ void QCC_main (int argc, char **argv) //as part of the quake engine pHash_GetNext = &Hash_GetNext; pHash_Add = &Hash_Add; - MAX_REGS = 65536; + MAX_REGS = 1<<17; MAX_STRINGS = 1000000; - MAX_GLOBALS = 65535; - MAX_FIELDS = 2048; + MAX_GLOBALS = 1<<17; + MAX_FIELDS = 1<<12; MAX_STATEMENTS = 0x80000; MAX_FUNCTIONS = 16384; maxtypeinfos = 16384; diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index f5f299b8..8127701c 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -166,7 +166,7 @@ void ED_Spawned (struct edict_s *ent, int loading) ent->xv->dimension_solid = 255; ent->xv->dimension_hit = 255; - ent->xv->Version = sv.csqcentversion[ent->entnum]+1; + ent->xv->Version = sv.csqcentversion[ent->entnum]; ent->xv->uniquespawnid = sv.csqcentversion[ent->entnum]; } } @@ -202,6 +202,7 @@ pbool ED_CanFree (edict_t *ed) VectorClear (ed->v->angles); ed->v->nextthink = 0; ed->v->solid = 0; + ed->xv->pvsflags = 0; ed->v->classname = 0; @@ -216,12 +217,13 @@ pbool ED_CanFree (edict_t *ed) ed->v->think = 0; } + ed->xv->Version+=1; ed->xv->SendEntity = 0; - sv.csqcentversion[ed->entnum] = ed->xv->Version+1; + sv.csqcentversion[ed->entnum] += 1; #ifdef USEODE - World_Physics_RemoveFromEntity(&sv.world, (wedict_t*)ed); - World_Physics_RemoveJointFromEntity(&sv.world, (wedict_t*)ed); + World_ODE_RemoveFromEntity(&sv.world, (wedict_t*)ed); + World_ODE_RemoveJointFromEntity(&sv.world, (wedict_t*)ed); #endif @@ -413,17 +415,19 @@ void SVPR_Event_Touch(world_t *w, wedict_t *s, wedict_t *o) pr_global_struct->self = EDICT_TO_PROG(w->progs, s); pr_global_struct->other = EDICT_TO_PROG(w->progs, o); pr_global_struct->time = w->physicstime; -#ifdef VM_Q1 - if (w==&sv.world && svs.gametype == GT_Q1QVM) - Q1QVM_Touch(); - else -#endif - PR_ExecuteProgram (w->progs, s->v->touch); + PR_ExecuteProgram (w->progs, s->v->touch); pr_global_struct->self = oself; pr_global_struct->other = oother; } +void SVPR_Event_Think(world_t *w, wedict_t *s) +{ + pr_global_struct->self = EDICT_TO_PROG(w->progs, s); + pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); + PR_ExecuteProgram (w->progs, s->v->think); +} + void Q_SetProgsParms(qboolean forcompiler) { progstype = PROG_NONE; @@ -469,6 +473,8 @@ void Q_SetProgsParms(qboolean forcompiler) sv.world.progs = svprogfuncs = InitProgs(&svprogparms); } sv.world.Event_Touch = SVPR_Event_Touch; + sv.world.Event_Think = SVPR_Event_Think; + sv.world.Event_Sound = SVQ1_StartSound; sv.world.GetCModel = SVPR_GetCModel; PRSV_ClearThreads(); PR_fclose_progs(svprogfuncs); @@ -480,7 +486,7 @@ void Q_SetProgsParms(qboolean forcompiler) void PR_Deinit(void) { #ifdef USEODE - World_Physics_End(&sv.world); + World_ODE_End(&sv.world); #endif #ifdef SQL @@ -678,6 +684,14 @@ void PR_LoadGlabalStruct(void) SV_ClearQCStats(); + sv.world.g.self = pr_nqglobal_struct->self; + sv.world.g.other = pr_nqglobal_struct->other; + sv.world.g.force_retouch = pr_nqglobal_struct->force_retouch; + sv.world.g.frametime = pr_nqglobal_struct->frametime; + sv.world.g.newmis = pr_nqglobal_struct->newmis; + sv.world.g.time = pr_nqglobal_struct->time; + + /*Hexen2 has lots of extra stats, which I don't want special support for, so list them here and send them as for csqc*/ if (progstype == PROG_H2) { SV_QCStatName(ev_float, "level", STAT_H2_LEVEL); @@ -1476,7 +1490,7 @@ void Q_InitProgs(void) SV_RegisterH2CustomTents(); #ifdef USEODE - World_Physics_Start(&sv.world); + World_ODE_Start(&sv.world); #endif } @@ -2819,7 +2833,7 @@ static void QCBUILTIN PF_sound (progfuncs_t *prinst, struct globalvars_s *pr_glo if (volume > 255) volume = 255; - SVQ1_StartSound (entity, channel, sample, volume, attenuation, pitchadj); + SVQ1_StartSound ((wedict_t*)entity, channel, sample, volume, attenuation, pitchadj); } //an evil one from telejano. @@ -2960,7 +2974,6 @@ static void QCBUILTIN PF_traceboxdp (progfuncs_t *prinst, struct globalvars_s *p set_trace_globals(&trace, pr_globals); } -extern trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore); static void QCBUILTIN PF_TraceToss (progfuncs_t *prinst, struct globalvars_s *pr_globals) { trace_t trace; @@ -2972,7 +2985,7 @@ static void QCBUILTIN PF_TraceToss (progfuncs_t *prinst, struct globalvars_s *pr Con_DPrintf("tracetoss: can not use world entity\n"); ignore = G_EDICT(prinst, OFS_PARM1); - trace = SV_Trace_Toss (ent, ignore); + trace = WPhys_Trace_Toss (&sv.world, (wedict_t*)ent, (wedict_t*)ignore); set_trace_globals(&trace, pr_globals); } @@ -4458,6 +4471,17 @@ void QCBUILTIN PF_WriteCoord (progfuncs_t *prinst, struct globalvars_s *pr_globa #endif } +void QCBUILTIN PF_WriteFloat (progfuncs_t *prinst, struct globalvars_s *pr_globals) +{ + if (G_FLOAT(OFS_PARM0) == MSG_CSQC) + { //csqc buffers are always written. + MSG_WriteFloat(&csqcmsgbuffer, G_FLOAT(OFS_PARM1)); + return; + } + + return; +} + void PF_WriteString_Internal (int target, char *str) { if (target == MSG_CSQC) @@ -6981,7 +7005,7 @@ static void QCBUILTIN PF_h2StopSound(progfuncs_t *prinst, struct globalvars_s *p entity = G_EDICT(prinst, OFS_PARM0); channel = G_FLOAT(OFS_PARM1); - SVQ1_StartSound (entity, channel, "", 1, 0, 0); + SVQ1_StartSound ((wedict_t*)entity, channel, "", 1, 0, 0); } static void QCBUILTIN PF_h2updatesoundpos(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -8375,15 +8399,7 @@ static void QCBUILTIN PF_runclientphys(progfuncs_t *prinst, struct globalvars_s if (!touched->v->touch || (playertouch[n/8]&(1<<(n%8)))) continue; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, touched); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->time = sv.time; - #ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_Touch(); - else - #endif - PR_ExecuteProgram (svprogfuncs, touched->v->touch); + sv.world.Event_Touch(&sv.world, (wedict_t*)touched, (wedict_t*)ent); playertouch[n/8] |= 1 << (n%8); } } @@ -8439,7 +8455,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) sv_player->xv->movement[2] = ucmd->upmove; } - SV_CheckVelocity(sv_player); + WPhys_CheckVelocity(&sv.world, (wedict_t*)sv_player); // // angles @@ -8458,7 +8474,7 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) //prethink should be consistant with what the engine normally does pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, client->edict); PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPreThink); - SV_RunThink (client->edict); + WPhys_RunThink (&sv.world, (wedict_t*)client->edict); @@ -8472,9 +8488,18 @@ qboolean SV_RunFullQCMovement(client_t *client, usercmd_t *ucmd) pr_global_struct->input_timelength = ucmd->msec/1000.0f; //precision inaccuracies. :( #define ANGLE2SHORT(x) (x) * (65536/360.0) - (pr_global_struct->input_angles)[0] = SHORT2ANGLE(ucmd->angles[0]); - (pr_global_struct->input_angles)[1] = SHORT2ANGLE(ucmd->angles[1]); - (pr_global_struct->input_angles)[2] = SHORT2ANGLE(ucmd->angles[2]); + if (sv_player->v->fixangle) + { + (pr_global_struct->input_angles)[0] = sv_player->v->v_angle[0]; + (pr_global_struct->input_angles)[1] = sv_player->v->v_angle[1]; + (pr_global_struct->input_angles)[2] = sv_player->v->v_angle[2]; + } + else + { + (pr_global_struct->input_angles)[0] = SHORT2ANGLE(ucmd->angles[0]); + (pr_global_struct->input_angles)[1] = SHORT2ANGLE(ucmd->angles[1]); + (pr_global_struct->input_angles)[2] = SHORT2ANGLE(ucmd->angles[2]); + } (pr_global_struct->input_movevalues)[0] = ucmd->forwardmove; (pr_global_struct->input_movevalues)[1] = ucmd->sidemove; @@ -9117,6 +9142,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"terrain_edit", PF_sv_terrain_edit, 0, 0, 0, 278},//void(float action, vector pos, float radius, float quant) terrain_edit = #278 (??FTE_TERRAIN_EDIT?? {"touchtriggers", PF_sv_touchtriggers,0, 0, 0, 279},//void() touchtriggers = #279; + {"writefloat", PF_WriteFloat, 0, 0, 0, 280},//void(float buf, float fl) writefloat = #280; //EXT_CSQC // {"setmodelindex", PF_sv_SetModelIndex,0, 0, 0, 333}, // #333 void(entity e, float mdlindex) setmodelindex (EXT_CSQC) @@ -9198,7 +9224,7 @@ BuiltinList_t BuiltinList[] = { //nq qw h2 ebfs {"getsurfacenumpoints",PF_getsurfacenumpoints,0,0, 0, 434},// #434 float(entity e, float s) getsurfacenumpoints (DP_QC_GETSURFACE) {"getsurfacepoint",PF_getsurfacepoint, 0, 0, 0, 435},// #435 vector(entity e, float s, float n) getsurfacepoint (DP_QC_GETSURFACE) {"getsurfacenormal",PF_getsurfacenormal,0, 0, 0, 436},// #436 vector(entity e, float s) getsurfacenormal (DP_QC_GETSURFACE) -// {"getsurfacetexture",PF_getsurfacetexture,0, 0, 0, 437},// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) + {"getsurfacetexture",PF_getsurfacetexture,0, 0, 0, 437},// #437 string(entity e, float s) getsurfacetexture (DP_QC_GETSURFACE) {"getsurfacenearpoint",PF_getsurfacenearpoint,0,0, 0, 438},// #438 float(entity e, vector p) getsurfacenearpoint (DP_QC_GETSURFACE) {"getsurfaceclippedpoint",PF_getsurfaceclippedpoint,0,0,0, 439},// #439 vector(entity e, float s, vector p) getsurfaceclippedpoint (DP_QC_GETSURFACE) diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index 866d43cf..322b9ce4 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -639,7 +639,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con case G_SOUND: // ( int edn, int channel, char *samp, float vol, float att ) - SVQ1_StartSound (Q1QVMPF_EdictNum(svprogfuncs, VM_LONG(arg[0])), VM_LONG(arg[1]), VM_POINTER(arg[2]), VM_FLOAT(arg[3])*255, VM_FLOAT(arg[4]), 0); + SVQ1_StartSound ((wedict_t*)Q1QVMPF_EdictNum(svprogfuncs, VM_LONG(arg[0])), VM_LONG(arg[1]), VM_POINTER(arg[2]), VM_FLOAT(arg[3])*255, VM_FLOAT(arg[4]), 0); break; case G_TRACELINE: @@ -1302,6 +1302,29 @@ void Q1QVM_Shutdown(void) Z_FreeTags(VMFSID_Q1QVM); } +void Q1QVM_Event_Touch(world_t *w, wedict_t *s, wedict_t *o) +{ + int oself = pr_global_struct->self; + int oother = pr_global_struct->other; + + pr_global_struct->self = EDICT_TO_PROG(w->progs, s); + pr_global_struct->other = EDICT_TO_PROG(w->progs, o); + pr_global_struct->time = w->physicstime; + VM_Call(q1qvm, GAME_EDICT_TOUCH); + + pr_global_struct->self = oself; + pr_global_struct->other = oother; +} + +void Q1QVM_Event_Think(world_t *w, wedict_t *s) +{ + pr_global_struct->self = EDICT_TO_PROG(w->progs, s); + pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); + VM_Call(q1qvm, GAME_EDICT_THINK); + + PR_ExecuteProgram (w->progs, s->v->think); +} + qboolean PR_LoadQ1QVM(void) { static float writable; @@ -1343,7 +1366,8 @@ qboolean PR_LoadQ1QVM(void) q1qvmprogfuncs.StringToProgs = Q1QVMPF_StringToProgs; q1qvmprogfuncs.StringToNative = Q1QVMPF_StringToNative; - sv.world.Event_Touch = SVPR_Event_Touch; + sv.world.Event_Touch = Q1QVM_Event_Touch; + sv.world.Event_Think = Q1QVM_Event_Think; sv.world.GetCModel = SVPR_GetCModel; sv.world.num_edicts = 0; //we're not ready for most of the builtins yet @@ -1549,16 +1573,6 @@ void Q1QVM_StartFrame(void) VM_Call(q1qvm, GAME_START_FRAME, (qintptr_t)(sv.time*1000)); } -void Q1QVM_Touch(void) -{ - VM_Call(q1qvm, GAME_EDICT_TOUCH); -} - -void Q1QVM_Think(void) -{ - VM_Call(q1qvm, GAME_EDICT_THINK); -} - void Q1QVM_Blocked(void) { VM_Call(q1qvm, GAME_EDICT_BLOCKED); diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index 43e1d126..d14afbd7 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -109,17 +109,17 @@ if the middle has a valid name, both left+right must have valid names too. so the base fields are a fixed size and the extension fields are added on the end and can have extra vm-specific stuff added on the end */ -/*DO NOT ADD TO THIS STRUCTURE*/ +/*DO NOT ADD TO THIS STRUCTURE (base-qw-compat for q1qvm)*/ #define comqcfields \ comfieldfloat(modelindex,modelindex,modelindex);\ comfieldvector(absmin,absmin,absmin);\ comfieldvector(absmax,absmax,absmax);\ - comfieldfloat(ltime,_ltime,_ltime);\ - comfieldfloat(lastruntime,_lastruntime,_lastruntime); /*type doesn't match the qc, we use a hidden double instead. this is dead.*/ \ + comfieldfloat(ltime,ltime,_ltime);\ + comfieldfloat(_lastruntime,lastruntime,_lastruntime); /*type doesn't match the qc, we use a hidden double instead. this is dead.*/ \ comfieldfloat(movetype,movetype,movetype);\ comfieldfloat(solid,solid,solid);\ comfieldvector(origin,origin,origin);\ - comfieldvector(oldorigin,_oldorigin,_oldorigin);\ + comfieldvector(oldorigin,oldorigin,_oldorigin);\ comfieldvector(velocity,velocity,velocity);\ comfieldvector(angles,angles,angles);\ comfieldvector(avelocity,avelocity,avelocity);\ @@ -133,9 +133,9 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldvector(size,size,size);\ comfieldfunction(touch,touch,touch);\ comfieldfunction(_use,_use,_use);\ - comfieldfunction(think,_think,think);\ - comfieldfunction(blocked,_blocked,_blocked);\ - comfieldfloat(nextthink,_nextthink,nextthink);\ + comfieldfunction(think,think,think);\ + comfieldfunction(blocked,blocked,_blocked);\ + comfieldfloat(nextthink,nextthink,nextthink);\ comfieldentity(groundentity,groundentity,groundentity);\ comfieldfloat(health,_health,_health);\ comfieldfloat(frags,_frags,_frags);\ @@ -151,13 +151,13 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(takedamage,_takedamage,_takedamage);\ comfieldentity(chain,chain,chain);\ comfieldfloat(_deadflag,_deadflag,_deadflag);\ - comfieldvector(view_ofs,_view_ofs,_view_ofs);\ + comfieldvector(view_ofs,view_ofs,_view_ofs);\ comfieldfloat(button0,_button0,_button0);\ comfieldfloat(button1,_button1,_button1); /*dead field in nq mode*/ \ comfieldfloat(button2,_button2,_button2);\ comfieldfloat(impulse,_impulse,_impulse);\ comfieldfloat(fixangle,_fixangle,_fixangle);\ - comfieldvector(v_angle,_v_angle,_v_angle);\ + comfieldvector(v_angle,v_angle,_v_angle);\ comfieldstring(netname,_netname,_netname);\ comfieldentity(enemy,enemy,enemy);\ comfieldfloat(flags,flags,flags);\ @@ -167,8 +167,8 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(teleport_time,_teleport_time,_teleport_time);\ comfieldfloat(_armortype,_armortype,_armortype);\ comfieldfloat(armorvalue,_armorvalue,_armorvalue);\ - comfieldfloat(waterlevel,_waterlevel,_waterlevel);\ - comfieldfloat(watertype,_watertype,_watertype);\ + comfieldfloat(waterlevel,waterlevel,_waterlevel);\ + comfieldfloat(watertype,watertype,_watertype);\ comfieldfloat(ideal_yaw,ideal_yaw,ideal_yaw);\ comfieldfloat(yaw_speed,yaw_speed,yaw_speed);\ comfieldentity(aiment,aiment,aiment);\ @@ -190,13 +190,17 @@ and the extension fields are added on the end and can have extra vm-specific stu /*DO NOT ADD TO THE ABOVE STRUCTURE*/ #define comextqcfields \ + comfieldvector(punchangle); /*std in nq*/\ comfieldfloat(gravity); /*added in quake 1.09 (for hipnotic)*/\ comfieldfloat(hull);/*PEXT_HEXEN2*/\ + comfieldentity(movechain);/*hexen2*/\ + comfieldfunction(chainmoved);/*hexen2*/\ comfieldfloat(dimension_solid);/*EXT_DIMENSION_PHYSICS*/\ comfieldfloat(dimension_hit);/*EXT_DIMENSION_PHYSICS*/\ comfieldfloat(scale);/*DP_ENT_SCALE*/\ comfieldfloat(fatness);/*FTE_PEXT_FATNESS*/\ comfieldfloat(alpha);/*DP_ENT_ALPHA*/\ + comfieldvector(colormod);\ comfieldfloat(pmove_flags);/*EXT_CSQC_1*/\ comfieldfloat(jointtype);/*DP_...PHYSICS*/\ comfieldfloat(mass);/*DP_...PHYSICS*/\ @@ -206,7 +210,6 @@ and the extension fields are added on the end and can have extra vm-specific stu #define svextqcfields \ comfieldfloat(maxspeed);/*added in quake 1.09*/\ comfieldfloat(items2); /*added in quake 1.09 (for hipnotic)*/\ - comfieldvector(punchangle); /*std in nq*/\ comfieldentity(view2);/*FTE_PEXT_VIEW2*/\ comfieldvector(movement);\ comfieldfloat(vw_index);\ @@ -227,7 +230,6 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(glow_color);\ comfieldfloat(glow_trail);\ comfieldvector(color);\ - comfieldvector(colormod);\ comfieldfloat(light_lev);\ comfieldfloat(style);\ comfieldfloat(pflags);\ @@ -238,8 +240,6 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldfloat(dimension_ghost_alpha);/*EXT_DIMENSION_GHOST*/\ comfieldfloat(playerclass);/*hexen2 requirements*/\ comfieldfloat(drawflags);/*hexen2*/\ - comfieldentity(movechain);/*hexen2*/\ - comfieldfunction(chainmoved);/*hexen2*/\ comfieldfloat(hasted);/*hexen2 uses this AS WELL as maxspeed*/\ comfieldfloat(light_level);/*hexen2's grabbing light level from client*/\ comfieldfloat(abslight);/*hexen2's force a lightlevel*/\ diff --git a/engine/server/progs.h b/engine/server/progs.h index b6d4c030..06425e27 100644 --- a/engine/server/progs.h +++ b/engine/server/progs.h @@ -144,8 +144,6 @@ void Q1QVM_PlayerPreThink(void); void Q1QVM_RunPlayerThink(void); void Q1QVM_PostThink(void); void Q1QVM_StartFrame(void); -void Q1QVM_Touch(void); -void Q1QVM_Think(void); void Q1QVM_Blocked(void); void Q1QVM_SetNewParms(void); void Q1QVM_SetChangeParms(void); diff --git a/engine/server/server.h b/engine/server/server.h index a3c387fb..9c8f914c 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -370,7 +370,7 @@ typedef struct client_s char *name; char namebuf[32]; // for printing to other people // extracted from userinfo - char guid[32]; + char guid[32]; /*+2 for split+pad*/ int messagelevel; // for filtering printed messages // the datagram is written to after every frame, but only cleared @@ -1000,13 +1000,14 @@ qboolean SVQ3_Command(void); // sv_phys.c // void SV_SetMoveVars(void); -void SV_RunNewmis (void); +void WPhys_RunNewmis (world_t *w); qboolean SV_Physics (void); -void SV_CheckVelocity (edict_t *ent); -trace_t SV_Trace_Toss (edict_t *ent, edict_t *ignore); +void World_Physics_Frame(world_t *w); +void WPhys_CheckVelocity (world_t *w, wedict_t *ent); +trace_t WPhys_Trace_Toss (world_t *w, wedict_t *ent, wedict_t *ignore); void SV_ProgStartFrame (void); -void SV_RunEntity (edict_t *ent); -qboolean SV_RunThink (edict_t *ent); +void WPhys_RunEntity (world_t *w, wedict_t *ent); +qboolean WPhys_RunThink (world_t *w, wedict_t *ent); // // sv_send.c // @@ -1024,7 +1025,7 @@ void VARGS SV_Multicast (vec3_t origin, multicast_t to); void SV_MulticastProtExt(vec3_t origin, multicast_t to, int dimension_mask, int with, int without); void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sample, int volume, float attenuation, int pitchadj); -void SVQ1_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj); +void SVQ1_StartSound (wedict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj); void SV_PrintToClient(client_t *cl, int level, char *string); void VARGS SV_ClientPrintf (client_t *cl, int level, char *fmt, ...) LIKEPRINTF(3); void VARGS SV_ClientTPrintf (client_t *cl, int level, translation_t text, ...); @@ -1156,7 +1157,7 @@ typedef struct { rankstats_t s; } rankinfo_t; -int Rank_GetPlayerID(char *name, int pwd, qboolean allowcreate, qboolean requirepasswordtobeset); +int Rank_GetPlayerID(char *guid, char *name, int pwd, qboolean allowcreate, qboolean requirepasswordtobeset); void Rank_SetPlayerStats(int id, rankstats_t *stats); rankstats_t *Rank_GetPlayerStats(int id, rankstats_t *buffer); rankinfo_t *Rank_GetPlayerInfo(int id, rankinfo_t *buffer); @@ -1292,6 +1293,7 @@ extern cvar_t sv_demoUseCache; extern cvar_t sv_demoMaxSize; extern cvar_t sv_demoMaxDirSize; +char *SV_Demo_CurrentOutput(void); void SV_MVDInit(void); char *SV_MVDNum(char *buffer, int bufferlen, int num); void SV_SendMVDMessage(void); diff --git a/engine/server/sv_ccmds.c b/engine/server/sv_ccmds.c index f0472e81..884904ad 100644 --- a/engine/server/sv_ccmds.c +++ b/engine/server/sv_ccmds.c @@ -1151,7 +1151,7 @@ void SV_CripplePlayer_f (void) if (!cl->iscrippled) { SV_LogPlayer(cl, "crippled"); - if (persist) + if (persist && cl->rankid) { cl->iscrippled = 2; SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTISCRIPPLEDPERMANENTLY, cl->name); @@ -1186,7 +1186,7 @@ void SV_Mute_f (void) if (!cl->ismuted) { SV_LogPlayer(cl, "muted"); - if (persist) + if (persist && cl->rankid) { cl->ismuted = 2; SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTISMUTEDPERMANENTLY, cl->name); @@ -1221,7 +1221,7 @@ void SV_Cuff_f (void) if (!cl->iscuffed) { SV_LogPlayer(cl, "cuffed"); - if (persist) + if (persist && cl->rankid) { cl->iscuffed = 2; SV_BroadcastTPrintf (PRINT_HIGH, STL_CLIENTISCUFFEDPERMANENTLY, cl->name); @@ -1437,20 +1437,23 @@ void SV_Status_f (void) NET_PrintAddresses(svs.sockets); - Con_Printf ("cpu utilization : %3i%%\n",(int)cpu); - Con_Printf ("avg response time: %i ms\n",(int)avg); - Con_Printf ("packets/frame : %5.2f\n", pak); //not relevent as a limit. - + Con_Printf("cpu utilization : %3i%%\n",(int)cpu); + Con_Printf("avg response time: %i ms\n",(int)avg); + Con_Printf("packets/frame : %5.2f\n", pak); //not relevent as a limit. + Con_Printf("server uptime : %s\n", ShowTime(realtime)); + Con_Printf("map uptime : %s\n", ShowTime(sv.world.physicstime)); //show the current map+name (but hide name if its too long or would be ugly) if (columns >= 80 && *sv.mapname && strlen(sv.mapname) < 45 && !strchr(sv.mapname, '\n')) Con_Printf ("current map : %s (%s)\n", sv.name, sv.mapname); else Con_Printf ("current map : %s\n", sv.name); - Con_Printf("map uptime : %s\n", ShowTime(sv.world.physicstime)); - Con_Printf("server uptime : %s\n", ShowTime(realtime)); + Con_Printf("entities : %i/%i\n", sv.world.num_edicts, sv.world.max_edicts); + Con_Printf("gamedir : %s\n", FS_GetGamedir()); if (sv.csqcdebug) Con_Printf("csqc debug : true\n"); + if (sv.mvdrecording) + Con_Printf("recording : %s\n", SV_Demo_CurrentOutput()); Con_Printf("public : %s\n", sv_public.value?"yes":"no"); Con_Printf("client types :%s%s%s%s\n", sv_listen_qw.ival?" QW":"", sv_listen_nq.ival?" NQ":"", sv_listen_dp.ival?" DP":"", sv_listen_q3.ival?" Q3":""); diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index e13a098c..667622be 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -357,10 +357,10 @@ void SV_EmitCSQCUpdate(client_t *client, sizebuf_t *msg) for (en = 1; en < sv.world.num_edicts; en++) { ent = EDICT_NUM(svprogfuncs, en); - if (client->csqcentversions[en] > 0 && (client->csqcentversions[en] != sv.csqcentversion[en]) && !((int)ent->xv->pvsflags & PVSF_NOREMOVE)) + if (client->csqcentversions[en] > 0 && client->csqcentversions[en] != ent->xv->Version) { - // if (!ent->isfree) - // continue; + if (((int)ent->xv->pvsflags & PVSF_NOREMOVE)) + continue; if (msg->cursize + 5 >= msg->maxsize) //try removing next frame instead. { @@ -2542,10 +2542,8 @@ void SV_Snapshot_BuildQ1(client_t *client, packet_entities_t *pack, qbyte *pvs, { if (e >= client->max_net_ents) continue; -#ifdef PEXT_MODELDBL - if (ent->v->modelindex >= 256 && !(client->fteprotocolextensions & PEXT_MODELDBL)) + if (ent->v->modelindex >= client->maxmodels) continue; -#endif } #ifdef DEPTHOPTIMISE diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index bb82fb90..e9db572b 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -736,7 +736,7 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us } #ifdef USEODE - World_Physics_End(&sv.world); + World_ODE_End(&sv.world); #endif // wipe the entire per-level structure @@ -1256,10 +1256,6 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us pr_global_struct->deathmatch = deathmatch.value; } - if (progstype == PROG_QW) - // run the frame start qc function to let progs check cvars - SV_ProgStartFrame (); //prydon gate seems to fail because of this allowance - if (svs.gametype != GT_Q1QVM) //we cannot do this with qvm { for (i = 0; i < svs.numprogs; i++) //do this AFTER precaches have been played with... @@ -1271,6 +1267,10 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us } } } + if (progstype == PROG_QW) + // run the frame start qc function to let progs check cvars + SV_ProgStartFrame (); //prydon gate seems to fail because of this allowance + } // load and spawn all other entities diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index d7eb0cc0..3fc0f90c 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -256,7 +256,7 @@ void SV_Shutdown (void) PR_Deinit(); #ifdef USEODE - World_Physics_Shutdown(); + World_ODE_Shutdown(); #endif if (sv.mvdrecording) @@ -2344,10 +2344,14 @@ client_t *SVC_DirectConnect(void) } else { - for (i=0 ; ispawn_parms[i] = rs.parm[i]; - for (; i < NUM_SPAWN_PARMS; i++) - newcl->spawn_parms[i] = 0; + extern cvar_t rank_parms_first, rank_parms_last; + for (i=0 ; i= rank_parms_first.ival && i <= rank_parms_last.ival) + newcl->spawn_parms[i] = rs.parm[i]; + else + newcl->spawn_parms[i] = 0; + } } if (rs.timeonserver > 3*60) //woo. Ages. @@ -2435,6 +2439,7 @@ client_t *SVC_DirectConnect(void) temp.frameunion.frames = cl->frameunion.frames; //don't touch these. temp.edict = cl->edict; memcpy(cl, newcl, sizeof(client_t)); + Q_strncatz(cl->guid, va("%i", clients), sizeof(cl->guid)); cl->name = cl->namebuf; cl->team = cl->teambuf; @@ -2552,7 +2557,7 @@ void SVC_RemoteCommand (void) { *colon = '\0'; colon++; - rid = Rank_GetPlayerID(s, atoi(colon), false, true); + rid = Rank_GetPlayerID(NULL, s, atoi(colon), false, true); if (rid) { if (!Rank_GetPlayerStats(rid, &stats)) @@ -4342,9 +4347,9 @@ qboolean ReloadRanking(client_t *cl, char *newname) int newid; int j; rankstats_t rs; - newid = Rank_GetPlayerID(newname, atoi(Info_ValueForKey (cl->userinfo, "_pwd")), true, false); //'_' keys are always stripped. On any server. So try and use that so persistant data won't give out the password when connecting to a different server + newid = Rank_GetPlayerID(cl->guid, newname, atoi(Info_ValueForKey (cl->userinfo, "_pwd")), true, false); //'_' keys are always stripped. On any server. So try and use that so persistant data won't give out the password when connecting to a different server if (!newid) - newid = Rank_GetPlayerID(newname, atoi(Info_ValueForKey (cl->userinfo, "password")), true, false); + newid = Rank_GetPlayerID(cl->guid, newname, atoi(Info_ValueForKey (cl->userinfo, "password")), true, false); if (newid) { if (cl->rankid && cl->state >= cs_spawned)//apply current stats @@ -4372,6 +4377,7 @@ qboolean ReloadRanking(client_t *cl, char *newname) if (spawnparamglobals[j]) rs.parm[j] = *spawnparamglobals[j]; Rank_SetPlayerStats(cl->rankid, &rs); + cl->rankid = 0; } if (!Rank_GetPlayerStats(newid, &rs)) return false; @@ -4656,7 +4662,7 @@ void SV_Init (quakeparms_t *parms) #endif #ifdef USEODE - World_Physics_Init(); + World_ODE_Init(); #endif #ifdef SVRANKING diff --git a/engine/server/sv_mvd.c b/engine/server/sv_mvd.c index 855b7787..91f44ea6 100644 --- a/engine/server/sv_mvd.c +++ b/engine/server/sv_mvd.c @@ -1416,7 +1416,7 @@ mvddest_t *SV_InitRecordFile (char *name) Q_strncpyz(demo.path, ".", MAX_OSPATH); SV_BroadcastPrintf (PRINT_CHAT, "Server starts recording (%s):\n%s\n", (dst->desttype == DEST_BUFFEREDFILE) ? "memory" : "disk", name); - Cvar_ForceSet(Cvar_Get("serverdemo", "", CVAR_NOSET, ""), demo.name); + Cvar_ForceSet(Cvar_Get("serverdemo", "", CVAR_NOSET, ""), SV_Demo_CurrentOutput()); Q_strncpyz(path, name, MAX_OSPATH); Q_strncpyz(path + strlen(path) - 3, "txt", MAX_OSPATH - strlen(path) + 3); @@ -1447,6 +1447,17 @@ mvddest_t *SV_InitRecordFile (char *name) return dst; } +char *SV_Demo_CurrentOutput(void) +{ + mvddest_t *d; + for (d = demo.dest; d; d = d->nextdest) + { + if (d->desttype == DEST_FILE || d->desttype == DEST_BUFFEREDFILE) + return d->name; + } + return "QTV"; +} + mvddest_t *SV_InitStream(int socket) { mvddest_t *dst; @@ -2916,8 +2927,8 @@ void SV_MVDInit(void) #ifdef SERVERONLY //client command would conflict otherwise. Cmd_AddCommand ("record", SV_MVD_Record_f); Cmd_AddCommand ("stop", SV_MVDStop_f); - Cmd_AddCommand ("cancel", SV_MVD_Cancel_f); #endif + Cmd_AddCommand ("cancel", SV_MVD_Cancel_f); Cmd_AddCommand ("qtvreverse", SV_MVD_QTVReverse_f); Cmd_AddCommand ("mvdrecord", SV_MVD_Record_f); Cmd_AddCommand ("easyrecord", SV_MVDEasyRecord_f); diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index d3727e00..756d1f57 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -60,6 +60,7 @@ cvar_t sv_friction = SCVAR( "sv_friction", "4"); cvar_t sv_waterfriction = SCVAR( "sv_waterfriction", "4"); cvar_t sv_gameplayfix_noairborncorpse = SCVAR( "sv_gameplayfix_noairborncorpse", "0"); cvar_t sv_sound_watersplash = CVAR( "sv_sound_watersplash", "misc/h2ohit1.wav"); +cvar_t sv_sound_land = CVAR( "sv_sound_land", "demon/dland2.wav"); cvar_t pm_ktjump = SCVARF("pm_ktjump", "0", CVAR_SERVERINFO); cvar_t pm_bunnyspeedcap = SCVARF("pm_bunnyspeedcap", "0", CVAR_SERVERINFO); @@ -112,7 +113,7 @@ static void SV_CheckAllEnts (void) SV_CheckVelocity ================ */ -void SV_CheckVelocity (edict_t *ent) +void WPhys_CheckVelocity (world_t *w, wedict_t *ent) { int i; @@ -123,19 +124,19 @@ void SV_CheckVelocity (edict_t *ent) { if (IS_NAN(ent->v->velocity[i])) { - Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(svprogfuncs, ent->v->classname)); + Con_Printf ("Got a NaN velocity on %s\n", PR_GetString(w->progs, ent->v->classname)); ent->v->velocity[i] = 0; } if (IS_NAN(ent->v->origin[i])) { - Con_Printf ("Got a NaN origin on %s\n", PR_GetString(svprogfuncs, ent->v->classname)); + Con_Printf ("Got a NaN origin on %s\n", PR_GetString(w->progs, ent->v->classname)); ent->v->origin[i] = 0; } } if (Length(ent->v->velocity) > sv_maxvelocity.value) { -// Con_DPrintf("Slowing %s\n", PR_GetString(svprogfuncs, ent->v->classname)); +// Con_DPrintf("Slowing %s\n", PR_GetString(w->progs, ent->v->classname)); VectorScale (ent->v->velocity, sv_maxvelocity.value/Length(ent->v->velocity), ent->v->velocity); } } @@ -150,30 +151,35 @@ in a frame. Not used for pushmove objects, because they must be exact. Returns false if the entity removed itself. ============= */ -qboolean SV_RunThink (edict_t *ent) +qboolean WPhys_RunThink (world_t *w, wedict_t *ent) { float thinktime; if (sv_nomsec.ival>=2) //try and imitate nq as closeley as possible { thinktime = ent->v->nextthink; - if (thinktime <= 0 || thinktime > sv.world.physicstime + host_frametime) + if (thinktime <= 0 || thinktime > w->physicstime + host_frametime) return true; - if (thinktime < sv.world.physicstime) - thinktime = sv.world.physicstime; // don't let things stay in the past. + if (thinktime < w->physicstime) + thinktime = w->physicstime; // don't let things stay in the past. // it is possible to start that way // by a trigger with a local time. ent->v->nextthink = 0; +#if 1 + *w->g.time = thinktime; + w->Event_Think(w, ent); +#else pr_global_struct->time = thinktime; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.world.edicts); + pr_global_struct->self = EDICT_TO_PROG(w->progs, ent); + pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_Think(); else #endif PR_ExecuteProgram (svprogfuncs, ent->v->think); +#endif return !ent->isfree; } @@ -182,24 +188,29 @@ qboolean SV_RunThink (edict_t *ent) thinktime = ent->v->nextthink; if (thinktime <= 0) return true; - if (thinktime > sv.world.physicstime + host_frametime) + if (thinktime > w->physicstime + host_frametime) return true; - if (thinktime < sv.world.physicstime) - thinktime = sv.world.physicstime; // don't let things stay in the past. + if (thinktime < w->physicstime) + thinktime = w->physicstime; // don't let things stay in the past. // it is possible to start that way // by a trigger with a local time. ent->v->nextthink = 0; +#if 1 + *w->g.time = thinktime; + w->Event_Think(w, ent); +#else pr_global_struct->time = thinktime; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.world.edicts); + pr_global_struct->self = EDICT_TO_PROG(w->progs, ent); + pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_Think(); else #endif PR_ExecuteProgram (svprogfuncs, ent->v->think); +#endif if (ent->isfree) return false; @@ -218,40 +229,18 @@ SV_Impact Two entities have touched, so run their touch functions ================== */ -static void SV_Impact (edict_t *e1, edict_t *e2) +static void WPhys_Impact (world_t *w, wedict_t *e1, wedict_t *e2) { - int old_self, old_other; - - old_self = pr_global_struct->self; - old_other = pr_global_struct->other; - - pr_global_struct->time = sv.world.physicstime; + *w->g.time = w->physicstime; if (e1->v->touch && e1->v->solid != SOLID_NOT) { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, e1); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, e2); -#ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_Touch(); - else -#endif - PR_ExecuteProgram (svprogfuncs, e1->v->touch); + w->Event_Touch(w, e1, e2); } if (e2->v->touch && e2->v->solid != SOLID_NOT) { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, e2); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, e1); -#ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_Touch(); - else -#endif - PR_ExecuteProgram (svprogfuncs, e2->v->touch); + w->Event_Touch(w, e2, e1); } - - pr_global_struct->self = old_self; - pr_global_struct->other = old_other; } @@ -292,7 +281,7 @@ If steptrace is not NULL, the trace of any vertical wall hit will be stored ============ */ #define MAX_CLIP_PLANES 5 -static int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) +static int WPhys_FlyMove (world_t *w, wedict_t *ent, float time, trace_t *steptrace) { int bumpcount, numbumps; vec3_t dir; @@ -325,7 +314,7 @@ static int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) for (i=0 ; i<3 ; i++) end[i] = ent->v->origin[i] + time_left * ent->v->velocity[i]; - trace = World_Move (&sv.world, ent->v->origin, ent->v->mins, ent->v->maxs, end, false, (wedict_t*)ent); + trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, false, (wedict_t*)ent); if (trace.startsolid) { // entity is trapped in another solid @@ -352,7 +341,7 @@ static int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) if (((edict_t *)trace.ent)->v->solid == SOLID_BSP) { ent->v->flags = (int)ent->v->flags | FL_ONGROUND; - ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, trace.ent); + ent->v->groundentity = EDICT_TO_PROG(w->progs, trace.ent); } } if (!trace.plane.normal[2]) @@ -365,7 +354,7 @@ static int SV_FlyMove (edict_t *ent, float time, trace_t *steptrace) // // run the impact function // - SV_Impact (ent, trace.ent); + WPhys_Impact (w, ent, trace.ent); if (ent->isfree) break; // removed by the impact function @@ -460,7 +449,7 @@ SV_AddGravity ============ */ -static void SV_AddGravity (edict_t *ent, float scale) +static void WPhys_AddGravity (wedict_t *ent, float scale) { if (!scale && progstype != PROG_QW) scale = 1; @@ -482,7 +471,7 @@ SV_PushEntity Does not change the entities velocity at all ============ */ -static trace_t SV_PushEntity (edict_t *ent, vec3_t push, unsigned int traceflags) +static trace_t WPhys_PushEntity (world_t *w, wedict_t *ent, vec3_t push, unsigned int traceflags) { trace_t trace; vec3_t end; @@ -493,21 +482,21 @@ static trace_t SV_PushEntity (edict_t *ent, vec3_t push, unsigned int traceflags traceflags |= MOVE_LAGGED; if (ent->v->movetype == MOVETYPE_FLYMISSILE) - trace = World_Move (&sv.world, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_MISSILE|traceflags, (wedict_t*)ent); + trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_MISSILE|traceflags, (wedict_t*)ent); else if (ent->v->solid == SOLID_TRIGGER || ent->v->solid == SOLID_NOT) // only clip against bmodels - trace = World_Move (&sv.world, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS|traceflags, (wedict_t*)ent); + trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS|traceflags, (wedict_t*)ent); else - trace = World_Move (&sv.world, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL|traceflags, (wedict_t*)ent); + trace = World_Move (w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL|traceflags, (wedict_t*)ent); // if (trace.ent) // VectorMA(trace.endpos, sv_impactpush.value, trace.plane.normal, ent->v->origin); // else VectorCopy (trace.endpos, ent->v->origin); - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + World_LinkEdict (w, ent, true); if (trace.ent) - SV_Impact (ent, trace.ent); + WPhys_Impact (w, ent, trace.ent); return trace; } @@ -517,7 +506,7 @@ static trace_t SV_PushEntity (edict_t *ent, vec3_t push, unsigned int traceflags typedef struct { - edict_t *ent; + wedict_t *ent; vec3_t origin; vec3_t angles; // float deltayaw; @@ -532,10 +521,10 @@ Objects need to be moved back on a failed push, otherwise riders would continue to slide. ============ */ -static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) +static qboolean WPhys_PushAngles (world_t *w, wedict_t *pusher, vec3_t move, vec3_t amove) { int i, e; - edict_t *check, *block; + wedict_t *check, *block; vec3_t mins, maxs; float oldsolid; pushed_t *p; @@ -565,12 +554,12 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) // move the pusher to it's final position VectorAdd (pusher->v->origin, move, pusher->v->origin); VectorAdd (pusher->v->angles, amove, pusher->v->angles); - World_LinkEdict (&sv.world, (wedict_t*)pusher, false); + World_LinkEdict (w, pusher, false); // see if any solid entities are inside the final position - for (e = 1; e < sv.world.num_edicts; e++) + for (e = 1; e < w->num_edicts; e++) { - check = EDICT_NUM(svprogfuncs, e); + check = WEDICT_NUM(w->progs, e); if (check->isfree) continue; @@ -583,7 +572,7 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) #if 1 oldsolid = pusher->v->solid; pusher->v->solid = SOLID_NOT; - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + block = World_TestEntityPosition (w, check); pusher->v->solid = oldsolid; if (block) continue; @@ -594,7 +583,7 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) // if the entity is standing on the pusher, it will definitely be moved if ( ! ( ((int)check->v->flags & FL_ONGROUND) - && PROG_TO_EDICT(svprogfuncs, check->v->groundentity) == pusher) ) + && PROG_TO_WEDICT(w->progs, check->v->groundentity) == pusher) ) { // see if the ent needs to be tested if ( check->v->absmin[0] >= maxs[0] @@ -607,11 +596,11 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) // see if the ent's bbox is inside the pusher's final position - if (!World_TestEntityPosition (&sv.world, (wedict_t*)check)) + if (!World_TestEntityPosition (w, (wedict_t*)check)) continue; } - if ((pusher->v->movetype == MOVETYPE_PUSH) || (PROG_TO_EDICT(svprogfuncs, check->v->groundentity) == pusher)) + if ((pusher->v->movetype == MOVETYPE_PUSH) || (PROG_TO_WEDICT(w->progs, check->v->groundentity) == pusher)) { // move this entity pushed_p->ent = check; @@ -638,13 +627,13 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) check->v->flags = (int)check->v->flags & ~FL_ONGROUND; // may have pushed them off an edge - if (PROG_TO_EDICT(svprogfuncs, check->v->groundentity) != pusher) + if (PROG_TO_WEDICT(w->progs, check->v->groundentity) != pusher) check->v->groundentity = 0; - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + block = World_TestEntityPosition (w, check); if (!block) { // pushed ok - World_LinkEdict (&sv.world, (wedict_t*)check, false); + World_LinkEdict (w, check, false); // impact? continue; } @@ -655,7 +644,7 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) // this is only relevent for riding entities, not pushed // FIXME: this doesn't acount for rotation VectorSubtract (check->v->origin, move, check->v->origin); - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + block = World_TestEntityPosition (w, check); if (!block) { pushed_p--; @@ -666,21 +655,21 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) // if it is sitting on top. Do not block. if (check->v->mins[0] == check->v->maxs[0]) { - World_LinkEdict (&sv.world, (wedict_t*)check, false); + World_LinkEdict (w, check, false); continue; } -// Con_Printf("Pusher hit %s\n", PR_GetString(svprogfuncs, check->v->classname)); +// Con_Printf("Pusher hit %s\n", PR_GetString(w->progs, check->v->classname)); if (pusher->v->blocked) { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, pusher); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, check); + *w->g.self = EDICT_TO_PROG(w->progs, pusher); + *w->g.other = EDICT_TO_PROG(w->progs, check); #ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) + if (w==&sv.world && svs.gametype == GT_Q1QVM) Q1QVM_Blocked(); else #endif - PR_ExecuteProgram (svprogfuncs, pusher->v->blocked); + PR_ExecuteProgram (w->progs, pusher->v->blocked); } // move back any entities we already moved @@ -694,7 +683,7 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) // { // p->ent->client->ps.pmove.delta_angles[YAW] = p->deltayaw; // } - World_LinkEdict (&sv.world, (wedict_t*)p->ent, false); + World_LinkEdict (w, p->ent, false); } return false; } @@ -702,7 +691,7 @@ static qboolean SV_PushAngles (edict_t *pusher, vec3_t move, vec3_t amove) //FIXME: is there a better way to handle this? // see if anything we moved has touched a trigger for (p=pushed_p-1 ; p>=pushed ; p--) - World_TouchLinks (&sv.world, (wedict_t*)p->ent, sv.world.areanodes ); + World_TouchLinks (w, p->ent, w->areanodes); return true; } @@ -713,20 +702,20 @@ SV_Push ============ */ -static qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) +static qboolean WPhys_Push (world_t *w, wedict_t *pusher, vec3_t move, vec3_t amove) { int i, e; - edict_t *check, *block; + wedict_t *check, *block; vec3_t mins, maxs; vec3_t pushorig; int num_moved; - edict_t *moved_edict[MAX_EDICTS]; + wedict_t *moved_edict[MAX_EDICTS]; vec3_t moved_from[MAX_EDICTS]; float oldsolid; if (amove[0] || amove[1] || amove[2]) { - return SV_PushAngles(pusher, move, amove); + return WPhys_PushAngles(w, pusher, move, amove); } for (i=0 ; i<3 ; i++) @@ -740,13 +729,13 @@ static qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) // move the pusher to it's final position VectorAdd (pusher->v->origin, move, pusher->v->origin); - World_LinkEdict (&sv.world, (wedict_t*)pusher, false); + World_LinkEdict (w, pusher, false); // see if any solid entities are inside the final position num_moved = 0; - for (e=1 ; enum_edicts ; e++) { - check = EDICT_NUM(svprogfuncs, e); + check = WEDICT_NUM(w->progs, e); if (check->isfree) continue; if (check->v->movetype == MOVETYPE_PUSH @@ -759,7 +748,7 @@ static qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) // if the entity is standing on the pusher, it will definately be moved if ( ! ( ((int)check->v->flags & FL_ONGROUND) && - PROG_TO_EDICT(svprogfuncs, check->v->groundentity) == pusher) ) + PROG_TO_WEDICT(w->progs, check->v->groundentity) == pusher) ) { if ( check->v->absmin[0] >= maxs[0] || check->v->absmin[1] >= maxs[1] @@ -770,13 +759,13 @@ static qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) continue; // see if the ent's bbox is inside the pusher's final position - if (!World_TestEntityPosition (&sv.world, (wedict_t*)check)) + if (!World_TestEntityPosition (w, check)) continue; } oldsolid = pusher->v->solid; pusher->v->solid = SOLID_NOT; - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + block = World_TestEntityPosition (w, check); pusher->v->solid = oldsolid; if (block) continue; @@ -789,16 +778,16 @@ static qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) // try moving the contacted entity VectorAdd (check->v->origin, move, check->v->origin); - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + block = World_TestEntityPosition (w, check); if (!block) { // pushed ok - World_LinkEdict (&sv.world, (wedict_t*)check, false); + World_LinkEdict (w, check, false); continue; } // if it is ok to leave in the old position, do it VectorSubtract (check->v->origin, move, check->v->origin); - block = (edict_t*)World_TestEntityPosition (&sv.world, (wedict_t*)check); + block = World_TestEntityPosition (w, check); if (!block) { //if leaving it where it was, allow it to drop to the floor again (useful for plats that move downward) @@ -811,39 +800,39 @@ static qboolean SV_Push (edict_t *pusher, vec3_t move, vec3_t amove) // if it is still inside the pusher, block if (check->v->mins[0] == check->v->maxs[0]) { - World_LinkEdict (&sv.world, (wedict_t*)check, false); + World_LinkEdict (w, check, false); continue; } if (check->v->solid == SOLID_NOT || check->v->solid == SOLID_TRIGGER) { // corpse check->v->mins[0] = check->v->mins[1] = 0; VectorCopy (check->v->mins, check->v->maxs); - World_LinkEdict (&sv.world, (wedict_t*)check, false); + World_LinkEdict (w, check, false); continue; } VectorCopy (pushorig, pusher->v->origin); - World_LinkEdict (&sv.world, (wedict_t*)pusher, false); + World_LinkEdict (w, pusher, false); // if the pusher has a "blocked" function, call it // otherwise, just stay in place until the obstacle is gone if (pusher->v->blocked) { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, pusher); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, check); + *w->g.self = EDICT_TO_PROG(w->progs, pusher); + *w->g.other = EDICT_TO_PROG(w->progs, check); #ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) + if (w==&sv.world && svs.gametype == GT_Q1QVM) Q1QVM_Blocked(); else #endif - PR_ExecuteProgram (svprogfuncs, pusher->v->blocked); + PR_ExecuteProgram (w->progs, pusher->v->blocked); } // move back any entities we already moved for (i=0 ; iv->origin); - World_LinkEdict (&sv.world, (wedict_t*)moved_edict[i], false); + World_LinkEdict (w, moved_edict[i], false); } return false; } @@ -858,7 +847,7 @@ SV_PushMove ============ */ -static void SV_PushMove (edict_t *pusher, float movetime) +static void WPhys_PushMove (world_t *w, wedict_t *pusher, float movetime) { int i; vec3_t move; @@ -877,7 +866,7 @@ static void SV_PushMove (edict_t *pusher, float movetime) amove[i] = pusher->v->avelocity[i] * movetime; } - if (SV_Push (pusher, move, amove)) + if (WPhys_Push (w, pusher, move, amove)) pusher->v->ltime += movetime; } @@ -888,7 +877,7 @@ SV_Physics_Pusher ================ */ -static void SV_Physics_Pusher (edict_t *ent) +static void WPhys_Physics_Pusher (world_t *w, wedict_t *ent) { float thinktime; float oldltime; @@ -911,7 +900,7 @@ float l; if (movetime) { - SV_PushMove (ent, movetime); // advances ent->v->ltime if not blocked + WPhys_PushMove (w, ent, movetime); // advances ent->v->ltime if not blocked } if (thinktime > oldltime && thinktime <= ent->v->ltime) @@ -919,15 +908,20 @@ float l; VectorCopy (ent->v->origin, oldorg); VectorCopy (ent->v->angles, oldang); ent->v->nextthink = 0; +#if 1 + *w->g.time = w->physicstime; + w->Event_Think(w, ent); +#else pr_global_struct->time = sv.world.physicstime; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv.world.edicts); + pr_global_struct->self = EDICT_TO_PROG(w->progs, ent); + pr_global_struct->other = EDICT_TO_PROG(w->progs, w->edicts); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_Think(); else #endif PR_ExecuteProgram (svprogfuncs, ent->v->think); +#endif if (ent->isfree) return; VectorSubtract (ent->v->origin, oldorg, move); @@ -939,7 +933,7 @@ if (l > 1.0/64) // Con_Printf ("**** snap: %f\n", Length (l)); VectorCopy (oldorg, ent->v->origin); VectorCopy (oldang, ent->v->angles); - SV_Push (ent, move, amove); + WPhys_Push (w, ent, move, amove); } } @@ -954,17 +948,17 @@ SV_Physics_Follow Entities that are "stuck" to another entity ============= */ -static void SV_Physics_Follow (edict_t *ent) +static void WPhys_Physics_Follow (world_t *w, wedict_t *ent) { vec3_t vf, vr, vu, angles, v; - edict_t *e; + wedict_t *e; // regular thinking - if (!SV_RunThink (ent)) + if (!WPhys_RunThink (w, ent)) return; // LordHavoc: implemented rotation on MOVETYPE_FOLLOW objects - e = PROG_TO_EDICT(svprogfuncs, ent->v->aiment); + e = PROG_TO_WEDICT(w->progs, ent->v->aiment); if (e->v->angles[0] == ent->xv->punchangle[0] && e->v->angles[1] == ent->xv->punchangle[1] && e->v->angles[2] == ent->xv->punchangle[2]) { // quick case for no rotation @@ -988,7 +982,7 @@ static void SV_Physics_Follow (edict_t *ent) ent->v->origin[2] = v[0] * vu[0] + v[1] * vu[1] + v[2] * vu[2] + e->v->origin[2]; } VectorAdd (e->v->angles, ent->v->v_angle, ent->v->angles); - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + World_LinkEdict (w, ent, true); } /* @@ -998,16 +992,16 @@ SV_Physics_Noclip A moving object that doesn't obey physics ============= */ -static void SV_Physics_Noclip (edict_t *ent) +static void WPhys_Physics_Noclip (world_t *w, wedict_t *ent) { // regular thinking - if (!SV_RunThink (ent)) + if (!WPhys_RunThink (w, ent)) return; VectorMA (ent->v->angles, host_frametime, ent->v->avelocity, ent->v->angles); VectorMA (ent->v->origin, host_frametime, ent->v->velocity, ent->v->origin); - World_LinkEdict (&sv.world, (wedict_t*)ent, false); + World_LinkEdict (w, (wedict_t*)ent, false); } /* @@ -1024,11 +1018,11 @@ SV_CheckWaterTransition ============= */ -static void SV_CheckWaterTransition (edict_t *ent) +static void WPhys_CheckWaterTransition (world_t *w, wedict_t *ent) { int cont; - cont = World_PointContents (&sv.world, ent->v->origin); + cont = World_PointContents (w, ent->v->origin); //needs to be q1 progs compatible if (cont & FTECONTENTS_LAVA) @@ -1051,7 +1045,7 @@ static void SV_CheckWaterTransition (edict_t *ent) { if (ent->v->watertype == Q1CONTENTS_EMPTY && *sv_sound_watersplash.string) { // just crossed into water - SVQ1_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, 0); + w->Event_Sound(ent, 0, sv_sound_watersplash.string, 255, 1, 0); } ent->v->watertype = cont; ent->v->waterlevel = 1; @@ -1060,7 +1054,7 @@ static void SV_CheckWaterTransition (edict_t *ent) { if (ent->v->watertype != Q1CONTENTS_EMPTY && *sv_sound_watersplash.string) { // just crossed into open - SVQ1_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, 0); + w->Event_Sound(ent, 0, sv_sound_watersplash.string, 255, 1, 0); } ent->v->watertype = Q1CONTENTS_EMPTY; ent->v->waterlevel = cont; @@ -1074,7 +1068,7 @@ SV_Physics_Toss Toss, bounce, and fly movement. When onground, do nothing. ============= */ -static void SV_Physics_Toss (edict_t *ent) +static void WPhys_Physics_Toss (world_t *w, wedict_t *ent) { trace_t trace; vec3_t move; @@ -1082,10 +1076,10 @@ static void SV_Physics_Toss (edict_t *ent) vec3_t temporg; - SV_CheckVelocity (ent); + WPhys_CheckVelocity (w, ent); // regular thinking - if (!SV_RunThink (ent)) + if (!WPhys_RunThink (w, ent)) return; // if onground, return without moving @@ -1097,8 +1091,8 @@ static void SV_Physics_Toss (edict_t *ent) { if (sv_gameplayfix_noairborncorpse.value) { - edict_t *onent; - onent = PROG_TO_EDICT(svprogfuncs, ent->v->groundentity); + wedict_t *onent; + onent = PROG_TO_WEDICT(w->progs, ent->v->groundentity); if (!onent->isfree) return; //don't drop if our fround is still valid } @@ -1112,7 +1106,7 @@ static void SV_Physics_Toss (edict_t *ent) && ent->v->movetype != MOVETYPE_FLYMISSILE && ent->v->movetype != MOVETYPE_BOUNCEMISSILE && ent->v->movetype != MOVETYPE_H2SWIM) - SV_AddGravity (ent, 1.0); + WPhys_AddGravity (ent, 1.0); // move angles VectorMA (ent->v->angles, host_frametime, ent->v->avelocity, ent->v->angles); @@ -1122,7 +1116,7 @@ static void SV_Physics_Toss (edict_t *ent) VectorCopy(ent->v->origin, temporg); VectorCopy(temporg, ent->v->origin); - trace = SV_PushEntity (ent, move, (sv_antilag.ival==2)?MOVE_LAGGED:0); + trace = WPhys_PushEntity (w, ent, move, (sv_antilag.ival==2)?MOVE_LAGGED:0); if (trace.allsolid) trace.fraction = 0; @@ -1155,14 +1149,14 @@ static void SV_Physics_Toss (edict_t *ent) if (ent->v->velocity[2] < 60 || ent->v->movetype != MOVETYPE_BOUNCE ) { ent->v->flags = (int)ent->v->flags | FL_ONGROUND; - ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, trace.ent); + ent->v->groundentity = EDICT_TO_PROG(w->progs, trace.ent); VectorClear (ent->v->velocity); VectorClear (ent->v->avelocity); } } // check for in water - SV_CheckWaterTransition (ent); + WPhys_CheckWaterTransition (w, ent); } /* @@ -1185,7 +1179,7 @@ will fall if the floor is pulled out from under them. FIXME: is this true? ============= */ -static void SV_Physics_Step (edict_t *ent) +static void WPhys_Physics_Step (world_t *w, wedict_t *ent) { qboolean hitsound; qboolean freefall; @@ -1208,27 +1202,24 @@ static void SV_Physics_Step (edict_t *ent) { hitsound = ent->v->velocity[2] < movevars.gravity*-0.1; - SV_AddGravity (ent, 1.0); - SV_CheckVelocity (ent); - SV_FlyMove (ent, host_frametime, NULL); - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + WPhys_AddGravity (ent, 1.0); + WPhys_CheckVelocity (w, ent); + WPhys_FlyMove (w, ent, host_frametime, NULL); + World_LinkEdict (w, ent, true); if ( (int)ent->v->flags & FL_ONGROUND ) // just hit ground { if (hitsound) { - if (progstype == PROG_H2) - SVQ1_StartSound (ent, 0, "fx/thngland.wav", 255, 1, 0); - else - SVQ1_StartSound (ent, 0, "demon/dland2.wav", 255, 1, 0); + w->Event_Sound(ent, 0, sv_sound_land.string, 255, 1, 0); } } } // regular thinking - SV_RunThink (ent); + WPhys_RunThink (w, ent); - SV_CheckWaterTransition (ent); + WPhys_CheckWaterTransition (w, ent); } //============================================================================ @@ -1268,13 +1259,13 @@ This is a big hack to try and fix the rare case of getting stuck in the world clipping hull. ============= */ -static void SV_CheckStuck (edict_t *ent) +static void WPhys_CheckStuck (world_t *w, wedict_t *ent) { int i, j; int z; vec3_t org; //return; - if (!World_TestEntityPosition (&sv.world, (wedict_t*)ent)) + if (!World_TestEntityPosition (w, ent)) { VectorCopy (ent->v->origin, ent->v->oldorigin); return; @@ -1282,10 +1273,10 @@ static void SV_CheckStuck (edict_t *ent) VectorCopy (ent->v->origin, org); VectorCopy (ent->v->oldorigin, ent->v->origin); - if (!World_TestEntityPosition (&sv.world, (wedict_t*)ent)) + if (!World_TestEntityPosition (w, ent)) { Con_DPrintf ("Unstuck.\n"); - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + World_LinkEdict (w, ent, true); return; } @@ -1296,10 +1287,10 @@ static void SV_CheckStuck (edict_t *ent) ent->v->origin[0] = org[0] + i; ent->v->origin[1] = org[1] + j; ent->v->origin[2] = org[2] + z; - if (!World_TestEntityPosition (&sv.world, (wedict_t*)ent)) + if (!World_TestEntityPosition (w, ent)) { Con_DPrintf ("Unstuck.\n"); - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + World_LinkEdict (w, ent, true); return; } } @@ -1313,7 +1304,7 @@ static void SV_CheckStuck (edict_t *ent) SV_CheckWater ============= */ -static qboolean SV_CheckWater (edict_t *ent) +static qboolean WPhys_CheckWater (world_t *w, wedict_t *ent) { vec3_t point; int cont; @@ -1324,7 +1315,7 @@ static qboolean SV_CheckWater (edict_t *ent) ent->v->waterlevel = 0; ent->v->watertype = Q1CONTENTS_EMPTY; - cont = World_PointContents (&sv.world, point); + cont = World_PointContents (w, point); if (cont & FTECONTENTS_FLUID) { if (cont & FTECONTENTS_LAVA) @@ -1337,12 +1328,12 @@ static qboolean SV_CheckWater (edict_t *ent) ent->v->watertype = Q1CONTENTS_SKY; ent->v->waterlevel = 1; point[2] = ent->v->origin[2] + (ent->v->mins[2] + ent->v->maxs[2])*0.5; - cont = World_PointContents (&sv.world, point); + cont = World_PointContents (w, point); if (cont & FTECONTENTS_FLUID) { ent->v->waterlevel = 2; point[2] = ent->v->origin[2] + ent->v->view_ofs[2]; - cont = World_PointContents (&sv.world, point); + cont = World_PointContents (w, point); if (cont & FTECONTENTS_FLUID) ent->v->waterlevel = 3; } @@ -1358,7 +1349,7 @@ SV_WallFriction ============ */ -static void SV_WallFriction (edict_t *ent, trace_t *trace) +static void WPhys_WallFriction (wedict_t *ent, trace_t *trace) { vec3_t forward, right, up; float d, i; @@ -1611,7 +1602,7 @@ static void SV_WalkMove (edict_t *ent) // 1/32 epsilon to keep floating point happy #define DIST_EPSILON (0.03125) -static int SV_SetOnGround (edict_t *ent) +static int WPhys_SetOnGround (world_t *w, wedict_t *ent) { vec3_t end; trace_t trace; @@ -1620,22 +1611,22 @@ static int SV_SetOnGround (edict_t *ent) end[0] = ent->v->origin[0]; end[1] = ent->v->origin[1]; end[2] = ent->v->origin[2] - 1; - trace = World_Move(&sv.world, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, (wedict_t*)ent); + trace = World_Move(w, ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, (wedict_t*)ent); if (trace.fraction <= DIST_EPSILON && trace.plane.normal[2] >= 0.7) { ent->v->flags = (int)ent->v->flags | FL_ONGROUND; - ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, trace.ent); + ent->v->groundentity = EDICT_TO_PROG(w->progs, trace.ent); return 1; } return 0; } -static void SV_WalkMove (edict_t *ent) +static void WPhys_WalkMove (world_t *w, wedict_t *ent) { int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity; vec3_t upmove, downmove, start_origin, start_velocity, originalmove_origin, originalmove_velocity; trace_t downtrace, steptrace; - SV_CheckVelocity(ent); + WPhys_CheckVelocity(w, ent); // do a regular slide move unless it looks like you ran into a step oldonground = (int)ent->v->flags & FL_ONGROUND; @@ -1644,10 +1635,10 @@ static void SV_WalkMove (edict_t *ent) VectorCopy (ent->v->origin, start_origin); VectorCopy (ent->v->velocity, start_velocity); - clip = SV_FlyMove (ent, host_frametime, NULL); + clip = WPhys_FlyMove (w, ent, host_frametime, NULL); - SV_SetOnGround (ent); - SV_CheckVelocity(ent); + WPhys_SetOnGround (w, ent); + WPhys_CheckVelocity(w, ent); VectorCopy(ent->v->origin, originalmove_origin); VectorCopy(ent->v->velocity, originalmove_velocity); @@ -1689,14 +1680,14 @@ static void SV_WalkMove (edict_t *ent) VectorClear (upmove); upmove[2] = movevars.stepheight; // FIXME: don't link? - SV_PushEntity(ent, upmove, MOVE_NORMAL); + WPhys_PushEntity(w, ent, upmove, MOVE_NORMAL); // move forward ent->v->velocity[2] = 0; - clip = SV_FlyMove (ent, host_frametime, &steptrace); + clip = WPhys_FlyMove (w, ent, host_frametime, &steptrace); ent->v->velocity[2] += start_velocity[2]; - SV_CheckVelocity(ent); + WPhys_CheckVelocity(w, ent); // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls @@ -1722,7 +1713,7 @@ static void SV_WalkMove (edict_t *ent) if (clip & 2)// && sv_wallfriction.value) { // Con_Printf("wall\n"); - SV_WallFriction (ent, &steptrace); + WPhys_WallFriction (ent, &steptrace); } } else if (/*!sv_gameplayfix_stepdown.integer || */!oldonground || start_velocity[2] > 0 || ((int)ent->v->flags & FL_ONGROUND) || ent->v->waterlevel >= 2) @@ -1732,7 +1723,7 @@ static void SV_WalkMove (edict_t *ent) VectorClear (downmove); downmove[2] = -movevars.stepheight + start_velocity[2]*host_frametime; // FIXME: don't link? - downtrace = SV_PushEntity (ent, downmove, MOVE_NORMAL); + downtrace = WPhys_PushEntity (w, ent, downmove, MOVE_NORMAL); if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7) { @@ -1741,7 +1732,7 @@ static void SV_WalkMove (edict_t *ent) { //Con_Printf("onground\n"); ent->v->flags = (int)ent->v->flags | FL_ONGROUND; - ent->v->groundentity = EDICT_TO_PROG(svprogfuncs, downtrace.ent); + ent->v->groundentity = EDICT_TO_PROG(w->progs, downtrace.ent); } } else @@ -1757,12 +1748,12 @@ static void SV_WalkMove (edict_t *ent) ent->v->groundentity = originalmove_groundentity; } - SV_SetOnGround (ent); - SV_CheckVelocity(ent); + WPhys_SetOnGround (w, ent); + WPhys_CheckVelocity(w, ent); } #endif -static void SV_MoveChain(edict_t *ent, edict_t *movechain, float *initial_origin, float *initial_angle) +static void WPhys_MoveChain(world_t *w, wedict_t *ent, wedict_t *movechain, float *initial_origin, float *initial_angle) { qboolean callfunc; if ((callfunc=DotProduct(ent->v->origin, initial_origin)) || DotProduct(ent->v->angles, initial_angle)) @@ -1772,7 +1763,7 @@ static void SV_MoveChain(edict_t *ent, edict_t *movechain, float *initial_origin VectorSubtract(ent->v->angles, initial_angle, moveang); VectorSubtract(ent->v->origin, initial_origin, moveorg); - for(i=16;i && movechain != (edict_t*)sv.world.edicts && !movechain->isfree;i--, movechain = PROG_TO_EDICT(svprogfuncs, movechain->xv->movechain)) + for(i=16;i && movechain != w->edicts && !movechain->isfree;i--, movechain = PROG_TO_WEDICT(w->progs, movechain->xv->movechain)) { if ((int)movechain->v->flags & FL_MOVECHAIN_ANGLE) VectorAdd(movechain->v->angles, moveang, movechain->v->angles); @@ -1780,14 +1771,14 @@ static void SV_MoveChain(edict_t *ent, edict_t *movechain, float *initial_origin if (movechain->xv->chainmoved && callfunc) { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, movechain); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); + pr_global_struct->self = EDICT_TO_PROG(w->progs, movechain); + pr_global_struct->other = EDICT_TO_PROG(w->progs, ent); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_ChainMoved(); else #endif - PR_ExecuteProgram(svprogfuncs, movechain->xv->chainmoved); + PR_ExecuteProgram(w->progs, movechain->xv->chainmoved); } } } @@ -1800,12 +1791,13 @@ SV_RunEntity ================ */ -void SV_RunEntity (edict_t *ent) +void WPhys_RunEntity (world_t *w, wedict_t *ent) { - edict_t *movechain; + wedict_t *movechain; + edict_t *svent = (edict_t*)ent; vec3_t initial_origin = {0},initial_angle = {0}; // warning: ‘initial_?[?]’ may be used uninitialized in this function - if (ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots) + if (ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots && w == &sv.world) { //a client woo. qboolean readyforjump = false; @@ -1814,15 +1806,15 @@ void SV_RunEntity (edict_t *ent) if (svs.clients[ent->entnum-1].protocol == SCP_BAD) - svs.clients[ent->entnum-1].edict->v->fixangle = 0; //bots never get fixangle cleared otherwise + svent->v->fixangle = 0; //bots never get fixangle cleared otherwise host_client = &svs.clients[ent->entnum-1]; SV_ClientThink(); if (progstype == PROG_QW) //detect if the mod should do a jump - if (ent->v->button2) - if ((int)ent->v->flags & FL_JUMPRELEASED) + if (svent->v->button2) + if ((int)svent->v->flags & FL_JUMPRELEASED) readyforjump = true; // @@ -1840,8 +1832,8 @@ void SV_RunEntity (edict_t *ent) if (readyforjump) //qw progs can't jump for themselves... { - if (!ent->v->button2 && !((int)ent->v->flags & FL_JUMPRELEASED) && ent->v->velocity[2] <= 0) - ent->v->velocity[2] += 270; + if (!svent->v->button2 && !((int)ent->v->flags & FL_JUMPRELEASED) && ent->v->velocity[2] <= 0) + svent->v->velocity[2] += 270; } } else @@ -1849,12 +1841,13 @@ void SV_RunEntity (edict_t *ent) if ((unsigned int)ent->v->lastruntime == svs.framenum) return; ent->v->lastruntime = svs.framenum; + svent = NULL; } - movechain = PROG_TO_EDICT(svprogfuncs, ent->xv->movechain); - if (movechain != (edict_t*)sv.world.edicts) + movechain = PROG_TO_WEDICT(w->progs, ent->xv->movechain); + if (movechain != w->edicts) { VectorCopy(ent->v->origin,initial_origin); VectorCopy(ent->v->angles,initial_angle); @@ -1863,22 +1856,22 @@ void SV_RunEntity (edict_t *ent) switch ( (int)ent->v->movetype) { case MOVETYPE_PUSH: - SV_Physics_Pusher (ent); + WPhys_Physics_Pusher (w, ent); break; case MOVETYPE_NONE: - if (!SV_RunThink (ent)) + if (!WPhys_RunThink (w, ent)) return; break; case MOVETYPE_NOCLIP: case MOVETYPE_ANGLENOCLIP: - SV_Physics_Noclip (ent); + WPhys_Physics_Noclip (w, ent); break; case MOVETYPE_STEP: case MOVETYPE_H2PUSHPULL: - SV_Physics_Step (ent); + WPhys_Physics_Step (w, ent); break; case MOVETYPE_FOLLOW: - SV_Physics_Follow (ent); + WPhys_Physics_Follow (w, ent); break; case MOVETYPE_FLY: case MOVETYPE_H2SWIM: @@ -1886,40 +1879,40 @@ void SV_RunEntity (edict_t *ent) case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEMISSILE: case MOVETYPE_FLYMISSILE: - SV_Physics_Toss (ent); + WPhys_Physics_Toss (w, ent); break; case MOVETYPE_WALK: - if (!SV_RunThink (ent)) + if (!WPhys_RunThink (w, ent)) return; - if (!SV_CheckWater (ent) && ! ((int)ent->v->flags & FL_WATERJUMP) ) - SV_AddGravity (ent, ent->xv->gravity); - SV_CheckStuck (ent); + if (!WPhys_CheckWater (w, ent) && ! ((int)ent->v->flags & FL_WATERJUMP) ) + WPhys_AddGravity (ent, ent->xv->gravity); + WPhys_CheckStuck (w, ent); - SV_WalkMove (ent); + WPhys_WalkMove (w, ent); if (!(ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots)) - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + World_LinkEdict (w, ent, true); break; case MOVETYPE_PHYSICS: - if (SV_RunThink(ent)) - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + if (WPhys_RunThink(w, ent)) + World_LinkEdict (w, ent, true); break; default: - SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(svprogfuncs, ent->v->classname)); + SV_Error ("SV_Physics: bad movetype %i on %s", (int)ent->v->movetype, PR_GetString(w->progs, ent->v->classname)); } - if (movechain != (edict_t*)sv.world.edicts) + if (movechain != w->edicts) { - SV_MoveChain(ent, movechain, initial_origin, initial_angle); + WPhys_MoveChain(w, ent, movechain, initial_origin, initial_angle); } - if (ent->entnum > 0 && ent->entnum <= sv.allocated_client_slots) + if (svent) { - World_LinkEdict (&sv.world, (wedict_t*)ent, true); + World_LinkEdict (w, (wedict_t*)svent, true); - pr_global_struct->time = sv.world.physicstime; - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); + pr_global_struct->time = w->physicstime; + pr_global_struct->self = EDICT_TO_PROG(w->progs, ent); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) Q1QVM_PostThink(); @@ -1927,7 +1920,7 @@ void SV_RunEntity (edict_t *ent) #endif { if (pr_global_struct->PlayerPostThink) - PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPostThink); + PR_ExecuteProgram (w->progs, pr_global_struct->PlayerPostThink); } } } @@ -1938,28 +1931,28 @@ SV_RunNewmis ================ */ -void SV_RunNewmis (void) +void WPhys_RunNewmis (world_t *w) { - edict_t *ent; + wedict_t *ent; - if (!realpr_nqglobal_struct.newmis) //newmis variable is not exported. + if (!w->g.newmis) //newmis variable is not exported. return; if (sv_nomsec.ival >= 2) return; - if (!pr_global_struct->newmis) + if (!*w->g.newmis) return; - ent = PROG_TO_EDICT(svprogfuncs, pr_global_struct->newmis); + ent = PROG_TO_WEDICT(w->progs, *w->g.newmis); host_frametime = 0.05; - pr_global_struct->newmis = 0; + *w->g.newmis = 0; - SV_RunEntity (ent); + WPhys_RunEntity (w, ent); - host_frametime = pr_global_struct->frametime; + host_frametime = *w->g.frametime; } -trace_t SV_Trace_Toss (edict_t *tossent, edict_t *ignore) +trace_t WPhys_Trace_Toss (world_t *w, wedict_t *tossent, wedict_t *ignore) { int i; float gravity; @@ -1977,14 +1970,14 @@ trace_t SV_Trace_Toss (edict_t *tossent, edict_t *ignore) VectorCopy (tossent->v->origin, origin); VectorCopy (tossent->v->velocity, velocity); - SV_CheckVelocity (tossent); + WPhys_CheckVelocity (w, tossent); for (i = 0;i < 200;i++) // LordHavoc: sanity check; never trace more than 10 seconds { velocity[2] -= gravity; VectorScale (velocity, 0.05, move); VectorAdd (origin, move, end); - trace = World_Move (&sv.world, origin, tossent->v->mins, tossent->v->maxs, end, MOVE_NORMAL, (wedict_t*)tossent); + trace = World_Move (w, origin, tossent->v->mins, tossent->v->maxs, end, MOVE_NORMAL, tossent); VectorCopy (trace.endpos, origin); if (trace.fraction < 1 && trace.ent && trace.ent != ignore) @@ -1992,7 +1985,7 @@ trace_t SV_Trace_Toss (edict_t *tossent, edict_t *ignore) if (Length(velocity) > sv_maxvelocity.value) { -// Con_DPrintf("Slowing %s\n", PR_GetString(svprogfuncs, tossent->v->classname)); +// Con_DPrintf("Slowing %s\n", PR_GetString(w->progs, tossent->v->classname)); VectorScale (velocity, sv_maxvelocity.value/Length(velocity), velocity); } } @@ -2001,6 +1994,56 @@ trace_t SV_Trace_Toss (edict_t *tossent, edict_t *ignore) return trace; } +/* +Run an individual physics frame. This might be run multiple times in one frame if we're running slow, or not at all. +*/ +void World_Physics_Frame(world_t *w) +{ + int i; + qboolean retouch; + wedict_t *ent; + + retouch = (w->g.force_retouch && (*w->g.force_retouch >= 1)); + + // + // treat each object in turn + // even the world gets a chance to think + // + for (i=0 ; inum_edicts ; i++) + { + ent = (wedict_t*)EDICT_NUM(w->progs, i); + if (ent->isfree) + continue; + + if (retouch) + World_LinkEdict (w, ent, true); // force retouch even for stationary + + if (i > 0 && i <= sv.allocated_client_slots && w == &sv.world) + { + if (!svs.clients[i-1].isindependant) + { + WPhys_RunEntity (w, ent); + WPhys_RunNewmis (w); + } +// else +// World_LinkEdict(w, (wedict_t*)ent, true); + continue; // clients are run directly from packets + } + + WPhys_RunEntity (w, ent); + WPhys_RunNewmis (w); + + if (((!ent->solidtype) != (!(qbyte)ent->v->solid)) && !ent->isfree) + { + Con_DPrintf("Entity \"%s\" improperly changed solid type\n", PR_GetString(w->progs, ent->v->classname)); + World_LinkEdict (w, ent, true); // a change of solidity should always relink the edict. someone messed up. + } + } + + if (retouch) + w->g.force_retouch-=1; +} + /* ================ SV_Physics @@ -2010,8 +2053,6 @@ SV_Physics qboolean SV_Physics (void) { int i; - qboolean retouch; - edict_t *ent; qboolean moved = false; int maxtics; @@ -2147,52 +2188,14 @@ qboolean SV_Physics (void) SV_ProgStartFrame (); -#ifdef USEODE - World_Physics_Frame(&sv.world, host_frametime, sv_gravity.value); -#endif - PRSV_RunThreads(); +#ifdef USEODE + World_ODE_Frame(&sv.world, host_frametime, sv_gravity.value); +#endif - retouch = (pr_nqglobal_struct->force_retouch && *pr_nqglobal_struct->force_retouch); - // - // treat each object in turn - // even the world gets a chance to think - // - for (i=0 ; iisfree) - continue; - - if (retouch) - World_LinkEdict (&sv.world, (wedict_t*)ent, true); // force retouch even for stationary - - if (i > 0 && i <= sv.allocated_client_slots) - { - if (!svs.clients[i-1].isindependant) - { - SV_RunEntity(ent); - SV_RunNewmis (); - } -// else -// World_LinkEdict(&sv.world, (wedict_t*)ent, true); - continue; // clients are run directly from packets - } - - SV_RunEntity (ent); - SV_RunNewmis (); - - if (((!ent->solidtype) != (!(qbyte)ent->v->solid)) && !ent->isfree) - { - Con_DPrintf("Entity \"%s\" improperly changed solid type\n", PR_GetString(svprogfuncs, ent->v->classname)); - World_LinkEdict (&sv.world, (wedict_t*)ent, true); // a change of solidity should always relink the edict. someone messed up. - } - } - - if (retouch) - pr_global_struct->force_retouch-=1; + World_Physics_Frame(&sv.world); #ifdef VM_Q1 if (svs.gametype == GT_Q1QVM) diff --git a/engine/server/sv_rankin.c b/engine/server/sv_rankin.c index 41c0403e..4ea141c2 100644 --- a/engine/server/sv_rankin.c +++ b/engine/server/sv_rankin.c @@ -26,9 +26,11 @@ typedef struct { rankfileheader_t rankfileheader; FILE *rankfile; -cvar_t rank_autoadd = SCVAR("rank_autoadd", "1"); -cvar_t rank_needlogin = SCVAR("rank_needlogin", "0"); -cvar_t rank_filename = SCVAR("rank_filename", ""); +cvar_t rank_autoadd = CVARD("rank_autoadd", "1", "Automatically register players into the ranking system"); +cvar_t rank_needlogin = CVARD("rank_needlogin", "0", "If set to 1, prohibits players from joining if they're not already registered."); +cvar_t rank_filename = CVARD("rank_filename", "", "Specifies which file to use as a rankings database. Enables the ranking system if set."); +cvar_t rank_parms_first = CVARD("rank_parms_first", "0", "Mod setting: first parm saved"); +cvar_t rank_parms_last = CVARD("rank_parms_last", "31", "Mod setting: the index of the last parm to be saved. Clamped to 32."); char rank_cvargroup[] = "server rankings"; #define RANKFILE_VERSION ((NUM_RANK_SPAWN_PARMS==32)?0:0x00000001) @@ -40,7 +42,7 @@ void inline READ_PLAYERSTATS(int x, rankstats_t *os) size_t result; fseek(rankfile, sizeof(rankfileheader_t)+sizeof(rankheader_t)+((x-1)*sizeof(rankinfo_t)), SEEK_SET); - result = fread(os, sizeof(rankstats_t), 1, rankfile); + result = fread(os, 1, sizeof(rankstats_t), rankfile); if (result != sizeof(rankstats_t)) Con_Printf("READ_PLAYERSTATS() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankstats_t),(unsigned int)result,strerror(errno)); @@ -73,7 +75,7 @@ void inline WRITE_PLAYERSTATS(int x, rankstats_t *os) ns.pad2 = (os->pad2); ns.pad3 = (os->pad3); - fwrite(&ns, sizeof(rankstats_t), 1, rankfile); + fwrite(&ns, 1, sizeof(rankstats_t), rankfile); } void inline READ_PLAYERHEADER(int x, rankheader_t *oh) @@ -82,7 +84,7 @@ void inline READ_PLAYERHEADER(int x, rankheader_t *oh) fseek(rankfile, sizeof(rankfileheader_t)+((x-1)*sizeof(rankinfo_t)), SEEK_SET); - result = fread(oh, sizeof(rankheader_t), 1, rankfile); + result = fread(oh, 1, sizeof(rankheader_t), rankfile); if (result != sizeof(rankheader_t)) Con_Printf("READ_PLAYERHEADER() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankheader_t),(unsigned int)result,strerror(errno)); @@ -106,7 +108,7 @@ void inline WRITE_PLAYERHEADER(int x, rankheader_t *oh) nh.pwd = swaplong(oh->pwd); nh.score = swapfloat(oh->score); - fwrite(&nh, sizeof(rankheader_t), 1, rankfile); + fwrite(&nh, 1, sizeof(rankheader_t), rankfile); } void inline READ_PLAYERINFO(int x, rankinfo_t *inf) @@ -126,9 +128,9 @@ void inline WRITEHEADER(void) nh.freeslot = swaplong(rankfileheader.freeslot); fseek(rankfile, 0, SEEK_SET); - fwrite(&nh, sizeof(rankfileheader_t), 1, rankfile); + fwrite(&nh, 1, sizeof(rankfileheader_t), rankfile); } -//#define WRITEHEADER() {fseek(rankfile, 0, SEEK_SET);fwrite(&rankfileheader, sizeof(rankfileheader_t), 1, rankfile);} +//#define WRITEHEADER() {fseek(rankfile, 0, SEEK_SET);fwrite(&rankfileheader, 1, sizeof(rankfileheader_t), rankfile);} #define NAMECMP(saved, against) Q_strncasecmp(saved, against, 31) @@ -161,7 +163,7 @@ qboolean Rank_OpenRankings(void) memset(&rankfileheader, 0, sizeof(rankfileheader)); fseek(rankfile, 0, SEEK_SET); - result = fread(&rankfileheader, sizeof(rankfileheader_t), 1, rankfile); + result = fread(&rankfileheader, 1, sizeof(rankfileheader_t), rankfile); if (result != sizeof(rankfileheader_t)) Con_Printf("Rank_OpenRankings() fread: expected %lu, result was %u (%s)\n",(long unsigned int)sizeof(rankfileheader_t),(unsigned int)result,strerror(errno)); @@ -388,7 +390,7 @@ void Rank_SetPlayerStats(int id, rankstats_t *stats) } } -int Rank_GetPlayerID(char *name, int pwd, qboolean allowadd, qboolean requirepasswordtobeset) +int Rank_GetPlayerID(char *guid, char *name, int pwd, qboolean allowadd, qboolean requirepasswordtobeset) { rankstats_t rs; rankheader_t rh; @@ -902,6 +904,9 @@ void Rank_RegisterCommands(void) Cvar_Register(&rank_autoadd, rank_cvargroup); Cvar_Register(&rank_needlogin, rank_cvargroup); Cvar_Register(&rank_filename, rank_cvargroup); + + Cvar_Register(&rank_parms_first, rank_cvargroup); + Cvar_Register(&rank_parms_last, rank_cvargroup); } void Rank_Flush (void) //new game dir? { diff --git a/engine/server/sv_send.c b/engine/server/sv_send.c index fc053f26..1d17f4de 100644 --- a/engine/server/sv_send.c +++ b/engine/server/sv_send.c @@ -945,8 +945,9 @@ void SV_StartSound (int ent, vec3_t origin, int seenmask, int channel, char *sam SV_MulticastProtExt(origin, reliable ? MULTICAST_ALL_R : MULTICAST_ALL, seenmask, requiredextensions, 0); } -void SVQ1_StartSound (edict_t *entity, int channel, char *sample, int volume, float attenuation, int pitchadj) +void SVQ1_StartSound (wedict_t *wentity, int channel, char *sample, int volume, float attenuation, int pitchadj) { + edict_t *entity = (edict_t*)wentity; int i; vec3_t origin; if (entity->v->solid == SOLID_BSP) @@ -1561,7 +1562,7 @@ void SV_UpdateClientStats (client_t *client, int pnum) SV_CalcClientStats(client, statsi, statsf, statss); m = MAX_QW_STATS; - if (client->fteprotocolextensions & PEXT_HEXEN2) + if (client->fteprotocolextensions & (PEXT_HEXEN2|PEXT_CSQC)) m = MAX_CL_STATS; for (i=0 ; ixv->movement[2] = ucmd->upmove * host_frametime; } - SV_CheckVelocity(sv_player); + WPhys_CheckVelocity(&sv.world, (wedict_t*)sv_player); // // angles @@ -5442,7 +5439,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) { //csqc independant physics support pr_global_struct->frametime = host_frametime; pr_global_struct->time = sv.time; - SV_RunEntity(sv_player); + WPhys_RunEntity(&sv.world, (wedict_t*)sv_player); return; } @@ -5489,7 +5486,7 @@ void SV_RunCmd (usercmd_t *ucmd, qboolean recurse) sv_player->v->velocity[2] -= 270; } - SV_RunThink (sv_player); + WPhys_RunThink (&sv.world, (wedict_t*)sv_player); } // memset(&pmove, 0, sizeof(pmove)); @@ -5650,32 +5647,11 @@ if (sv_player->v->health > 0 && before && !after ) continue; if (ent->v->touch) - { - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, sv_player); - pr_global_struct->time = sv.time; -#ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_Touch(); - else -#endif - PR_ExecuteProgram (svprogfuncs, ent->v->touch); - } + sv.world.Event_Touch(&sv.world, (wedict_t*)ent, (wedict_t*)sv_player); playertouch[n/8] |= 1 << (n%8); if (sv_player->v->touch && !ent->isfree) - { - pr_global_struct->other = EDICT_TO_PROG(svprogfuncs, ent); - pr_global_struct->self = EDICT_TO_PROG(svprogfuncs, sv_player); - pr_global_struct->time = sv.time; -#ifdef VM_Q1 - if (svs.gametype == GT_Q1QVM) - Q1QVM_Touch(); - else -#endif - PR_ExecuteProgram (svprogfuncs, sv_player->v->touch); - } - + sv.world.Event_Touch(&sv.world, (wedict_t*)sv_player, (wedict_t*)ent); } } @@ -5716,7 +5692,7 @@ void SV_PostRunCmd(void) PR_ExecuteProgram (svprogfuncs, pr_global_struct->PlayerPostThink); - SV_RunNewmis (); + WPhys_RunNewmis (&sv.world); } else if (SpectatorThink) { @@ -6466,7 +6442,7 @@ void SVNQ_ReadClientMove (usercmd_t *move) if (host_client->last_sequence) { host_frametime = timesincelast; - SV_RunEntity(host_client->edict); + WPhys_RunEntity(&sv.world, (wedict_t*)host_client->edict); host_client->isindependant = true; } else diff --git a/engine/server/world.c b/engine/server/world.c index 5fa2590d..8c3c8048 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -469,10 +469,7 @@ void World_LinkEdict (world_t *w, wedict_t *ent, qboolean touch_triggers) // link to PVS leafs if (w->worldmodel) { - if (ent->v->modelindex) - w->worldmodel->funcs.FindTouchedLeafs(w->worldmodel, &ent->pvsinfo, ent->v->absmin, ent->v->absmax); - else - w->worldmodel->funcs.FindTouchedLeafs(w->worldmodel, &ent->pvsinfo, NULL, NULL); + w->worldmodel->funcs.FindTouchedLeafs(w->worldmodel, &ent->pvsinfo, ent->v->absmin, ent->v->absmax); } if (ent->v->solid == SOLID_NOT) @@ -1445,8 +1442,16 @@ static void World_ClipToEverything (world_t *w, moveclip_t *clip) if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { - trace.ent = touch; - clip->trace = trace; + if (clip->type & MOVE_ENTCHAIN) + { + touch->v->chain = EDICT_TO_PROG(w->progs, clip->trace.ent?clip->trace.ent:w->edicts); + clip->trace.ent = touch; + } + else + { + trace.ent = touch; + clip->trace = trace; + } } } } @@ -1535,11 +1540,20 @@ static void World_ClipToLinks (world_t *w, areanode_t *node, moveclip_t *clip) trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins2, clip->maxs2, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); else trace = World_ClipMoveToEntity (w, touch, touch->v->origin, clip->start, clip->mins, clip->maxs, clip->end, clip->hullnum, clip->type & MOVE_HITMODEL); + if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { - trace.ent = touch; - clip->trace = trace; + if (clip->type & MOVE_ENTCHAIN) + { + touch->v->chain = EDICT_TO_PROG(w->progs, clip->trace.ent?clip->trace.ent:w->edicts); + clip->trace.ent = touch; + } + else + { + trace.ent = touch; + clip->trace = trace; + } } } @@ -1822,8 +1836,16 @@ trace_t World_Move (world_t *w, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t e if (trace.allsolid || trace.startsolid || trace.fraction < clip.trace.fraction) { - trace.ent = touch; - clip.trace = trace; + if (clip.type & MOVE_ENTCHAIN) + { + touch->v->chain = EDICT_TO_PROG(w->progs, clip.trace.ent?clip.trace.ent:w->edicts); + clip.trace.ent = touch; + } + else + { + trace.ent = touch; + clip.trace = trace; + } } } } diff --git a/fteqtv/dotnet2005/qtvprox.vcproj b/fteqtv/dotnet2005/qtvprox.vcproj index b7e3377c..b3166d63 100644 --- a/fteqtv/dotnet2005/qtvprox.vcproj +++ b/fteqtv/dotnet2005/qtvprox.vcproj @@ -1,7 +1,7 @@ @@ -220,6 +220,10 @@ RelativePath="..\forward.c" > + + @@ -228,10 +232,18 @@ RelativePath="..\mdfour.c" > + + + +