From e8c1f669cc561c91642f1e9786105ca66a0cbf8e Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 3 Sep 2011 03:49:43 +0000 Subject: [PATCH] Couple of changes. D3D now supports hlsl shaders. Much functionality is still missing, but sky and water surfaces are in. IQM models now supported. Engine physics code is now potentially callable from csqc, but there are some issues which need to be resolved before its enabled. FTEQCC has had some pointer/struct/array functionality improved. Complex trees can now be navigated properly. added r_dumpshaders command to dump internal glsl scripts for editing. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@3896 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 2 +- engine/client/cl_ents.c | 6 +- engine/client/cl_main.c | 5 +- engine/client/cl_parse.c | 34 +- engine/client/cl_pred.c | 5 +- engine/client/cl_ui.c | 2 - engine/client/client.h | 9 +- engine/client/clq2_ents.c | 3 - engine/client/in_win.c | 11 +- engine/client/merged.h | 1 + engine/client/p_classic.c | 11 +- engine/client/p_script.c | 24 +- engine/client/pr_csqc.c | 85 ++- engine/client/pr_menu.c | 33 +- engine/client/r_surf.c | 3 + engine/client/render.h | 12 +- engine/client/renderer.c | 8 + engine/client/snd_dma.c | 10 +- engine/common/com_mesh.c | 132 +++-- engine/common/com_phys_ode.c | 42 +- engine/common/common.c | 40 -- engine/common/fs.c | 27 +- engine/common/gl_q2bsp.c | 7 +- engine/common/mathlib.c | 37 ++ engine/common/mathlib.h | 3 + engine/common/pr_common.h | 18 +- engine/common/world.h | 29 +- engine/d3d/d3d_backend.c | 288 ++++++++-- engine/d3d/d3d_shader.c | 153 ++++- engine/d3d/vid_d3d.c | 5 +- engine/dotnet2005/ftequake.vcproj | 377 ++++++------ engine/gl/gl_alias.c | 4 +- engine/gl/gl_backend.c | 399 +++++++++---- engine/gl/gl_model.h | 1 + engine/gl/gl_rlight.c | 124 +++- engine/gl/gl_rmain.c | 4 +- engine/gl/gl_shader.c | 550 +++++++++++++++--- engine/gl/gl_shadow.c | 8 +- engine/gl/gl_vidcommon.c | 30 +- engine/gl/glquake.h | 3 + engine/gl/shader.h | 46 +- engine/http/iwebiface.c | 2 +- engine/qclib/execloop.h | 51 +- engine/qclib/pr_edict.c | 6 + engine/qclib/pr_multi.c | 4 +- engine/qclib/qcc.h | 5 +- engine/qclib/qcc_pr_comp.c | 918 ++++++++++++++++++++---------- engine/qclib/qcc_pr_lex.c | 55 +- engine/qclib/qccmain.c | 9 +- engine/server/pr_cmds.c | 88 ++- engine/server/pr_q1qvm.c | 38 +- engine/server/progdefs.h | 30 +- engine/server/progs.h | 2 - engine/server/server.h | 18 +- engine/server/sv_ccmds.c | 21 +- engine/server/sv_ents.c | 10 +- engine/server/sv_init.c | 10 +- engine/server/sv_main.c | 24 +- engine/server/sv_mvd.c | 15 +- engine/server/sv_phys.c | 511 ++++++++--------- engine/server/sv_rankin.c | 27 +- engine/server/sv_send.c | 7 +- engine/server/sv_user.c | 46 +- engine/server/world.c | 42 +- fteqtv/dotnet2005/qtvprox.vcproj | 14 +- 65 files changed, 3067 insertions(+), 1477 deletions(-) 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" > + + + +