diff --git a/engine/client/cl_cg.c b/engine/client/cl_cg.c index 059066b88..847d67712 100644 --- a/engine/client/cl_cg.c +++ b/engine/client/cl_cg.c @@ -566,7 +566,7 @@ static qintptr_t CG_SystemCallsEx(void *offset, quintptr_t mask, qintptr_t fn, c if (!mod) mod = cl.worldmodel; if (mod) - pc = cl.worldmodel->funcs.NativeContents(mod, 0, 0, VM_POINTER(arg[0]), vec3_origin, vec3_origin); + pc = cl.worldmodel->funcs.NativeContents(mod, 0, 0, NULL, VM_POINTER(arg[0]), vec3_origin, vec3_origin); else pc = 1;//FTECONTENTS_SOLID; VM_LONG(ret) = pc;//Contents_To_Q3(pc); @@ -584,10 +584,10 @@ static qintptr_t CG_SystemCallsEx(void *offset, quintptr_t mask, qintptr_t fn, c if (!mod) mod = cl.worldmodel; + if (mod) { vec3_t p_l; - vec3_t temp; - vec3_t forward, right, up; + vec3_t axis[3]; // subtract origin offset VectorSubtract (p, origin, p_l); @@ -595,20 +595,16 @@ static qintptr_t CG_SystemCallsEx(void *offset, quintptr_t mask, qintptr_t fn, c // rotate start and end into the models frame of reference if (angles[0] || angles[1] || angles[2]) { - AngleVectors (angles, forward, right, up); - - VectorCopy (p_l, temp); - p_l[0] = DotProduct (temp, forward); - p_l[1] = -DotProduct (temp, right); - p_l[2] = DotProduct (temp, up); + AngleVectors (angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); + pc = mod->funcs.NativeContents(mod, 0, 0, axis, p_l, vec3_origin, vec3_origin); } - - if (mod) - pc = mod->funcs.NativeContents(mod, 0, 0, VM_POINTER(arg[0]), vec3_origin, vec3_origin); else - pc = 1;//FTECONTENTS_SOLID; + pc = mod->funcs.NativeContents(mod, 0, 0, NULL, p_l, vec3_origin, vec3_origin); } - VM_LONG(ret) = pc;//Contents_To_Q3(pc); + else + pc = Q3CONTENTS_SOLID; + VM_LONG(ret) = pc; } break; @@ -687,7 +683,7 @@ static qintptr_t CG_SystemCallsEx(void *offset, quintptr_t mask, qintptr_t fn, c maxs = vec3_origin; if (mod) { - mod->funcs.NativeTrace(mod, 0, 0, start, end, mins, maxs, brushmask, &tr); + mod->funcs.NativeTrace(mod, 0, 0, NULL, start, end, mins, maxs, brushmask, &tr); } else { diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index b8d6ba920..198f632a8 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -1794,7 +1794,7 @@ void CL_LinkPacketEntities (void) //bots or powerup glows. items always glow, bots can be disabled if (state->modelindex != cl_playerindex || r_powerupglow.ival) - if (state->effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT) || state->light[3]) + if (state->effects & (EF_BLUE | EF_RED | EF_BRIGHTLIGHT | EF_DIMLIGHT)) { vec3_t colour; float radius; @@ -1831,13 +1831,6 @@ void CL_LinkPacketEntities (void) colour[1] += 0.05; colour[2] += 0.05; } - if (state->light[3]) - { - radius = max(radius,state->light[3]); - colour[0] += state->light[0]/1024.0f; - colour[1] += state->light[1]/1024.0f; - colour[2] += state->light[2]/1024.0f; - } if (radius) { @@ -1845,6 +1838,21 @@ void CL_LinkPacketEntities (void) CL_NewDlightRGB(state->number, state->origin, radius, 0.1, colour[0], colour[1], colour[2]); } } + if (state->lightpflags & PFLAGS_FULLDYNAMIC) + { + vec3_t colour; + if (!colour[0] && !colour[1] && !colour[2]) + { + colour[0] = colour[1] = colour[2] = 1; + } + else + { + colour[0] = state->light[0]/1024.0f; + colour[1] = state->light[1]/1024.0f; + colour[2] = state->light[2]/1024.0f; + } + CL_NewDlightRGB(state->number, state->origin, state->light[3]?state->light[3]:350, 0.1, colour[0], colour[1], colour[2]); + } // if set to invisible, skip if (state->modelindex<1) @@ -1953,7 +1961,7 @@ void CL_LinkPacketEntities (void) angles[2] = 0; if (cl_item_bobbing.value) - ent->origin[2] += 5+sin(cl.time*3)*5; //don't let it into the ground + ent->origin[2] += 5+sin(cl.time*3+(state->origin[0]+state->origin[1]+state->origin[2]))*5.5; //don't let it into the ground } else { @@ -2755,8 +2763,8 @@ void CL_LinkPlayers (void) VectorCopy(cl.simorg[pnum], org); if (model) { - org[2] -= model->mins[2]; - org[2] += 24; + org[2] += model->mins[2]; + org[2] += 32; } radius += r_lightflicker.value?(rand()&31):0; CL_NewDlightRGB(j+1, org, radius, 0.1, colour[0], colour[1], colour[2])->flags &= ~LFLAG_ALLOW_FLASH; @@ -2787,10 +2795,10 @@ void CL_LinkPlayers (void) CL_UpdateNetFrameLerpState(false, state->frame, &cl.lerpplayers[j]); CL_LerpNetFrameState(FS_REG, &ent->framestate, &cl.lerpplayers[j]); - if (state->modelindex == cl_playerindex) +// if (state->modelindex == cl_playerindex) ent->scoreboard = info; // use custom skin - else - ent->scoreboard = NULL; +// else +// ent->scoreboard = NULL; #ifdef PEXT_SCALE ent->scale = state->scale; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 4acac0c9a..06dffb65f 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -229,6 +229,7 @@ int host_hunklevel; qbyte *host_basepal; qbyte *host_colormap; +qbyte *h2playertranslations; cvar_t host_speeds = SCVAR("host_speeds","0"); // set for running times #ifdef CRAZYDEBUGGING diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 8fc10a254..74ff69657 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -1172,6 +1172,7 @@ void CL_RequestNextDownload (void) if (cl.downloadlist) { downloadlist_t *dl; + unsigned int fl; //download required downloads first for (dl = cl.downloadlist; dl; dl = dl->next) @@ -1181,21 +1182,22 @@ void CL_RequestNextDownload (void) } if (!dl) dl = cl.downloadlist; - - if ((dl->flags & DLLF_OVERWRITE) || !COM_FCheckExists (dl->localname)) - CL_SendDownloadStartRequest(dl->rname, dl->localname); - else + fl = dl->flags; + + if (cls.state == ca_active || requiredownloads.value || (fl & DLLF_REQUIRED)) { - Con_Printf("Already have %s\n", dl->localname); - CL_DisenqueDownload(dl->rname); + if ((fl & DLLF_OVERWRITE) || !COM_FCheckExists (dl->localname)) + CL_SendDownloadStartRequest(dl->rname, dl->localname); + else + { + Con_Printf("Already have %s\n", dl->localname); + CL_DisenqueDownload(dl->rname); - //recurse a bit. - CL_RequestNextDownload(); - return; + //recurse a bit. + CL_RequestNextDownload(); + return; + } } - - if (requiredownloads.value || (dl->flags & DLLF_REQUIRED)) - return; } if (cl.sendprespawn) @@ -3648,6 +3650,13 @@ void CL_ProcessUserInfo (int slot, player_info_t *player) */ player->model = NULL; + /*if we're running hexen2, they have to be some class...*/ + player->h2playerclass = atoi(Info_ValueForKey (player->userinfo, "cl_playerclass")); + if (player->h2playerclass > 5) + player->h2playerclass = 5; + if (player->h2playerclass < 1) + player->h2playerclass = 1; + player->colourised = TP_FindColours(player->name); // If it's us diff --git a/engine/client/cl_pred.c b/engine/client/cl_pred.c index 24d170ccb..40beac7e2 100644 --- a/engine/client/cl_pred.c +++ b/engine/client/cl_pred.c @@ -334,7 +334,7 @@ void CL_NudgePosition (void) vec3_t base; int x, y; - if (cl.worldmodel->funcs.PointContents (cl.worldmodel, pmove.origin) == FTECONTENTS_EMPTY) + if (cl.worldmodel->funcs.PointContents (cl.worldmodel, NULL, pmove.origin) == FTECONTENTS_EMPTY) return; VectorCopy (pmove.origin, base); @@ -344,7 +344,7 @@ void CL_NudgePosition (void) { pmove.origin[0] = base[0] + x * 1.0/8; pmove.origin[1] = base[1] + y * 1.0/8; - if (cl.worldmodel->funcs.PointContents (cl.worldmodel, pmove.origin) == FTECONTENTS_EMPTY) + if (cl.worldmodel->funcs.PointContents (cl.worldmodel, NULL, pmove.origin) == FTECONTENTS_EMPTY) return; } } diff --git a/engine/client/cl_screen.c b/engine/client/cl_screen.c index 316f50abc..c58b2721b 100644 --- a/engine/client/cl_screen.c +++ b/engine/client/cl_screen.c @@ -530,6 +530,9 @@ extern qboolean sb_showscores; { p = &scr_centerprint[pnum]; + if (p->time_off <= 0 && !cl.intermission && !(p->flags & CPRINT_PERSIST)) + continue; //'/P' prefix doesn't time out + p->time_off -= host_frametime; if (key_dest != key_game) //don't let progs guis/centerprints interfere with the game menu @@ -538,9 +541,6 @@ extern qboolean sb_showscores; if (sb_showscores) //this was annoying continue; - if (p->time_off <= 0 && !cl.intermission && !(p->flags & CPRINT_PERSIST)) - continue; //'/P' prefix doesn't time out - SCR_VRectForPlayer(&rect, pnum); SCR_DrawCenterString(&rect, p); } @@ -689,7 +689,10 @@ void SCR_ShowPic_Clear(void) int pnum; for (pnum = 0; pnum < MAX_SPLITS; pnum++) + { + scr_centerprint[pnum].flags = 0; scr_centerprint[pnum].charcount = 0; + } while((sp = showpics)) { @@ -994,8 +997,8 @@ void SCR_CalcRefdef (void) if (cl.stats[0][STAT_VIEWZOOM]) r_refdef.fov_x *= cl.stats[0][STAT_VIEWZOOM]/255.0f; - if (r_refdef.fov_x < 10) - r_refdef.fov_x = 10; + if (r_refdef.fov_x < 1) + r_refdef.fov_x = 1; else if (r_refdef.fov_x > 170) r_refdef.fov_x = 170; @@ -1033,7 +1036,7 @@ void SCR_CrosshairPosition(int pnum, int *x, int *y) memset(&tr, 0, sizeof(tr)); tr.fraction = 1; - cl.worldmodel->funcs.Trace(cl.worldmodel, 0, 0, start, end, vec3_origin, vec3_origin, &tr); + cl.worldmodel->funcs.Trace(cl.worldmodel, 0, 0, NULL, start, end, vec3_origin, vec3_origin, &tr); start[2]-=16; if (tr.fraction == 1) { diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index dded58390..21c307346 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -189,11 +189,12 @@ typedef struct beam_t cl_beams[MAX_BEAMS]; -#define MAX_EXPLOSIONS 32 +#define MAX_EXPLOSIONS 256 typedef struct { vec3_t origin; vec3_t oldorigin; + vec3_t velocity; int firstframe; int numframes; @@ -631,6 +632,7 @@ void CL_ParseStream (int type) b->model = NULL; b->endtime = cl.time + duration; b->alpha = 1; + b->skin = skin; VectorCopy (start, b->start); VectorCopy (end, b->end); @@ -671,8 +673,12 @@ void CL_ParseStream (int type) b->particleeffect = P_FindParticleType("te_stream_sunstaff2"); R_AddStain(end, -10, -10, -10, 20); break; + case TEH2_STREAM_COLORBEAM: + b->model = Mod_ForName("models/stclrbm.mdl", true); + b->particleeffect = P_FindParticleType("te_stream_colorbeam"); + break; default: - Con_Printf("Oh noes! type %i\n", type); + Con_Printf("CL_ParseStream: type %i\n", type); break; } } @@ -1420,6 +1426,7 @@ void CL_ParseTEnt (void) void MSG_ReadPos (vec3_t pos); void MSG_ReadDir (vec3_t dir); typedef struct { + char name[64]; int netstyle; int particleeffecttype; char stain[3]; @@ -1447,6 +1454,7 @@ void CL_ParseCustomTEnt(void) char *str; clcustomtents_t *t; int type = MSG_ReadByte(); + qboolean failed; if (type == 255) //255 is register { @@ -1457,6 +1465,7 @@ void CL_ParseCustomTEnt(void) t->netstyle = MSG_ReadByte(); str = MSG_ReadString(); + Q_strncpyz(t->name, str, sizeof(t->name)); t->particleeffecttype = P_ParticleTypeForName(str); if (t->netstyle & CTE_STAINS) @@ -1495,7 +1504,7 @@ void CL_ParseCustomTEnt(void) { MSG_ReadPos (pos); MSG_ReadPos (pos2); - P_ParticleTrail(pos, pos2, t->particleeffecttype, NULL); + failed = P_ParticleTrail(pos, pos2, t->particleeffecttype, NULL); } else { @@ -1507,14 +1516,24 @@ void CL_ParseCustomTEnt(void) MSG_ReadPos (pos); VectorCopy(pos, pos2); - if (t->netstyle & CTE_CUSTOMDIRECTION) + if (t->netstyle & CTE_CUSTOMVELOCITY) + { + dir[0] = MSG_ReadCoord(); + dir[1] = MSG_ReadCoord(); + dir[2] = MSG_ReadCoord(); + failed = P_RunParticleEffectType(pos, dir, count, t->particleeffecttype); + } + else if (t->netstyle & CTE_CUSTOMDIRECTION) { MSG_ReadDir (dir); - P_RunParticleEffectType(pos, dir, 1, t->particleeffecttype); + failed = P_RunParticleEffectType(pos, dir, count, t->particleeffecttype); } - else P_RunParticleEffectType(pos, NULL, 1, t->particleeffecttype); + else failed = P_RunParticleEffectType(pos, NULL, count, t->particleeffecttype); } + if (failed) + Con_Printf("Failed to create effect %s\n", t->name); + if (t->netstyle & CTE_STAINS) { //added at pos2 - end of trail R_AddStain(pos2, t->stain[0], t->stain[1], t->stain[2], 40); @@ -1685,7 +1704,7 @@ void CL_ParseParticleEffect4 (void) P_RunParticleEffect4 (org, radius, color, effect, msgcount); } -void CL_SpawnSpriteEffect(vec3_t org, model_t *model, int startframe, int framecount, int framerate) +void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, model_t *model, int startframe, int framecount, int framerate, float alpha) { explosion_t *ex; @@ -1696,10 +1715,16 @@ void CL_SpawnSpriteEffect(vec3_t org, model_t *model, int startframe, int framec ex->firstframe = startframe; ex->numframes = framecount; ex->framerate = framerate; + ex->alpha = alpha; ex->angles[0] = 0; ex->angles[1] = 0; ex->angles[2] = 0; + + if (dir) + VectorCopy(dir, ex->velocity); + else + VectorClear(ex->velocity); } // [vector] org [byte] modelindex [byte] startframe [byte] framecount [byte] framerate @@ -1730,7 +1755,7 @@ void CL_ParseEffect (qboolean effect2) framerate = MSG_ReadByte(); - CL_SpawnSpriteEffect(org, cl.model_precache[modelindex], startframe, framecount, framerate); + CL_SpawnSpriteEffect(org, vec3_origin, cl.model_precache[modelindex], startframe, framecount, framerate, 1); } #ifdef Q2CLIENT @@ -2854,7 +2879,7 @@ void CL_UpdateExplosions (void) ent = CL_NewTempEntity (); if (!ent) return; - VectorCopy (ex->origin, ent->origin); + VectorMA (ex->origin, f, ex->velocity, ent->origin); VectorCopy (ex->oldorigin, ent->oldorigin); VectorCopy (ex->angles, ent->angles); ent->skinnum = ex->skinnum; @@ -2866,9 +2891,9 @@ void CL_UpdateExplosions (void) ent->framestate.g[FS_REG].frame[0] = of+firstframe; ent->framestate.g[FS_REG].lerpfrac = (f - (int)f); if (ent->model->type == mod_sprite) - ent->shaderRGBAf[3] = 1; + ent->shaderRGBAf[3] = ex->alpha; /*sprites don't fade over time, the animation should do it*/ else - ent->shaderRGBAf[3] = 1.0 - f/(numframes); + ent->shaderRGBAf[3] = (1.0 - f/(numframes))*ex->alpha; ent->flags = ex->flags; } diff --git a/engine/client/client.h b/engine/client/client.h index 03a3b94d4..f493bf583 100644 --- a/engine/client/client.h +++ b/engine/client/client.h @@ -172,6 +172,7 @@ typedef struct player_info_s struct model_s *model; unsigned short vweapindex; + unsigned char h2playerclass; int prevcount; @@ -968,6 +969,7 @@ void CL_ParseParticleEffect4 (void); void CLDP_ParseTrailParticles(void); void CLDP_ParsePointParticles(qboolean compact); +void CL_SpawnSpriteEffect(vec3_t org, vec3_t dir, struct model_s *model, int startframe, int framecount, int framerate, float alpha); /*called from the particlesystem*/ // // cl_ents.c diff --git a/engine/client/m_items.c b/engine/client/m_items.c index 666cc3aed..a17b116b6 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -1144,8 +1144,8 @@ menubutton_t *MC_AddConsoleCommandHexen2BigFont(menu_t *menu, int x, int y, cons n->common.iszone = true; n->common.posx = x; n->common.posy = y; - n->common.height = 8; - n->common.width = strlen(text)*8; + n->common.height = 20; + n->common.width = strlen(text)*20; n->text = (char *)(n+1); strcpy((char *)(n+1), text); n->command = n->text + strlen(n->text)+1; diff --git a/engine/client/m_multi.c b/engine/client/m_multi.c index 6ec75091f..430addb8f 100644 --- a/engine/client/m_multi.c +++ b/engine/client/m_multi.c @@ -316,7 +316,7 @@ void MSetup_TransDraw (int x, int y, menucustom_t *option, menu_t *menu) if (p) Draw_ScalePic (x-12, y-8, 72, 72, p); - M_BuildTranslationTable(info->topcolour*16, info->lowercolour*16); + M_BuildTranslationTable(info->topcolour, info->lowercolour); Draw_TransPicTranslate (x, y, info->tiwidth, info->tiheight, info->translationimage, translationTable); } diff --git a/engine/client/m_options.c b/engine/client/m_options.c index 100c0555a..37e81460f 100644 --- a/engine/client/m_options.c +++ b/engine/client/m_options.c @@ -1091,7 +1091,7 @@ void M_Menu_Shadow_Lighting_f (void) #ifndef MINIMAL extern cvar_t r_vertexlight; #endif - extern cvar_t r_noaliasshadows, r_shadows, r_shadow_realtime_world, r_loadlits, gl_maxshadowlights, r_lightmap_saturation, r_dynamic, r_vertexdlights, r_lightstylesmooth, r_lightstylespeed, r_nolightdir, r_shadow_realtime_world_lightmaps, r_shadow_glsl_offsetmapping, r_shadow_glsl_offsetmapping_bias, r_shadow_glsl_offsetmapping_scale, r_shadow_bumpscale_basetexture, r_shadow_bumpscale_bumpmap, r_fb_bmodels, r_fb_models, gl_overbright, r_rocketlight, r_powerupglow, v_powerupshell, r_lightflicker, r_explosionlight; + extern cvar_t r_noaliasshadows, r_shadows, r_shadow_realtime_world, r_loadlits, gl_maxshadowlights, r_lightmap_saturation, r_dynamic, r_vertexdlights, r_lightstylesmooth, r_lightstylespeed, r_nolightdir, r_shadow_realtime_world_lightmaps, r_glsl_offsetmapping, r_glsl_offsetmapping_scale, r_shadow_bumpscale_basetexture, r_shadow_bumpscale_bumpmap, r_fb_bmodels, r_fb_models, gl_overbright, r_rocketlight, r_powerupglow, v_powerupshell, r_lightflicker, r_explosionlight; static const char *loadlitoptions[] = { @@ -1139,9 +1139,8 @@ void M_Menu_Shadow_Lighting_f (void) MC_AddCheckBox(menu, 16, y, " Realtime World Lightmaps", &r_shadow_realtime_world_lightmaps,0); y+=8; MC_AddCheckBox(menu, 16, y, " Realtime Dynamic Lights", &r_shadow_realtime_dlight,0); y+=8; MC_AddCheckBox(menu, 16, y, " Realtime Dynamic Light Shadows", &r_shadow_realtime_dlight_shadows,0); y+=8; - MC_AddCheckBox(menu, 16, y, " GLSL Shadow Offsetmapping", &r_shadow_glsl_offsetmapping,0); y+=8; - MC_AddSlider(menu, 16, y, " GLSL Shadow Offsetmapping Bias", &r_shadow_glsl_offsetmapping_bias,0,1,0.01); y+=8; - MC_AddSlider(menu, 16, y, " GLSL Shadow Offsetmapping Scale", &r_shadow_glsl_offsetmapping_scale,0,-1,0.01); y+=8; + MC_AddCheckBox(menu, 16, y, " GLSL Offsetmapping", &r_glsl_offsetmapping,0); y+=8; + MC_AddSlider(menu, 16, y, " GLSL Offsetmapping Scale", &r_glsl_offsetmapping_scale,0,-1,0.01); y+=8; MC_AddSlider(menu, 16, y, " Shadow Bumpscale Basetexture", &r_shadow_bumpscale_basetexture,0,10,1); y+=8; MC_AddSlider(menu, 16, y, " Shadow Bumpscale Bumpmap", &r_shadow_bumpscale_bumpmap,0,50,1); y+=8; info->loadlitcombo = MC_AddCombo(menu,16, y, " LIT Loading", loadlitoptions, currentloadlit); y+=8; diff --git a/engine/client/menu.c b/engine/client/menu.c index f1ed14e3c..e1759719d 100644 --- a/engine/client/menu.c +++ b/engine/client/menu.c @@ -69,23 +69,48 @@ void M_BuildTranslationTable(int top, int bottom) int j; qbyte *dest, *source; - for (j = 0; j < 256; j++) - identityTable[j] = j; - dest = translationTable; - source = identityTable; - memcpy (dest, source, 256); - - if (top < 128) // the artists made some backwards ranges. sigh. - memcpy (dest + TOP_RANGE, source + top, 16); + int pc = Cvar_Get("cl_playerclass", "1", 0, "foo")->value; + if (h2playertranslations && pc) + { + int i; + unsigned int color_offsets[5] = {2*14*256,0,1*14*256,2*14*256,2*14*256}; + unsigned char *colorA, *colorB, *sourceA, *sourceB; + colorA = h2playertranslations + 256 + color_offsets[pc-1]; + colorB = colorA + 256; + sourceA = colorB + (top * 256); + sourceB = colorB + (bottom * 256); + for(i=0;i<256;i++) + { + if (bottom > 0 && (colorB[i] != 255)) + translationTable[i] = sourceB[i]; + else if (top > 0 && (colorA[i] != 255)) + translationTable[i] = sourceA[i]; + else + translationTable[i] = i; + } + } else - for (j=0 ; j<16 ; j++) - dest[TOP_RANGE+j] = source[top+15-j]; + { + top *= 16; + bottom *= 16; + for (j = 0; j < 256; j++) + identityTable[j] = j; + dest = translationTable; + source = identityTable; + memcpy (dest, source, 256); - if (bottom < 128) - memcpy (dest + BOTTOM_RANGE, source + bottom, 16); - else - for (j=0 ; j<16 ; j++) - dest[BOTTOM_RANGE+j] = source[bottom+15-j]; + if (top < 128) // the artists made some backwards ranges. sigh. + memcpy (dest + TOP_RANGE, source + top, 16); + else + for (j=0 ; j<16 ; j++) + dest[TOP_RANGE+j] = source[top+15-j]; + + if (bottom < 128) + memcpy (dest + BOTTOM_RANGE, source + bottom, 16); + else + for (j=0 ; j<16 ; j++) + dest[BOTTOM_RANGE+j] = source[bottom+15-j]; + } } /* diff --git a/engine/client/p_script.c b/engine/client/p_script.c index aa2252304..34ba691e4 100644 --- a/engine/client/p_script.c +++ b/engine/client/p_script.c @@ -45,6 +45,17 @@ extern void *d3dballtexture; #include "r_partset.h" +struct +{ + char *name; + char **data; +} partset_list[] = +{ + {"none", NULL}, + R_PARTSET_BUILTINS + {NULL} +}; + extern qbyte *host_basepal; static int pt_pointfile = P_INVALID; @@ -148,6 +159,14 @@ typedef struct { typedef struct part_type_s { char name[MAX_QPATH]; char texname[MAX_QPATH]; + char modelname[MAX_QPATH]; + + model_t *model; + float modelframestart; + float modelframeend; + float modelframerate; + float modelalpha; + vec3_t rgb; //initial colour float alpha; vec3_t rgbchange; //colour delta (per second) @@ -218,7 +237,14 @@ typedef struct part_type_s { float gravity; vec3_t friction; float clipbounce; - int stains; + int stainonimpact; + + vec3_t dl_rgb; + float dl_radius; + float dl_time; + vec3_t dl_decay; + vec3_t stain_rgb; + float stain_radius; enum {RAMP_NONE, RAMP_DELTA, RAMP_ABSOLUTE} rampmode; int rampindexes; @@ -472,6 +498,8 @@ static void P_LoadTexture(part_type_t *ptype, qboolean warn) if (qrenderer == QR_NONE) return; + ptype->model = NULL; + if (*ptype->texname) { /*try and load the shader, fail if we would need to generate one*/ @@ -867,6 +895,14 @@ static void P_ParticleEffect_f(void) ptype = &part_type[pnum]; ptype->inwater = assoc; } + else if (!strcmp(var, "model")) + { + Q_strncpyz(ptype->modelname, Cmd_Argv(1), sizeof(ptype->modelname)); + ptype->modelframestart = atof(Cmd_Argv(2)); + ptype->modelframeend = atof(Cmd_Argv(3)); + ptype->modelframerate = atof(Cmd_Argv(4)); + ptype->modelalpha = atof(Cmd_Argv(5)); + } else if (!strcmp(var, "colorindex")) { if (Cmd_Argc()>2) @@ -959,7 +995,7 @@ static void P_ParticleEffect_f(void) ptype->rgbrandsync[2] = atof(value); else if (!strcmp(var, "stains")) - ptype->stains = atoi(value); + ptype->stainonimpact = atoi(value); else if (!strcmp(var, "blend")) { if (!strcmp(value, "add")) @@ -1864,77 +1900,73 @@ static void PScript_ClearParticles (void) static void P_ExportBuiltinSet_f(void) { char *efname = Cmd_Argv(1); - char *file; + char *file = NULL; + int i; if (!*efname) { Con_Printf("Please name the built in effect (faithful, spikeset, tsshaft, minimal or highfps)\n"); return; } - else if (!stricmp(efname, "faithful")) - file = particle_set_faithful; - else if (!stricmp(efname, "spikeset")) - file = particle_set_spikeset; - else if (!stricmp(efname, "highfps")) - file = particle_set_highfps; - else if (!stricmp(efname, "minimal")) - file = particle_set_minimal; - else if (!stricmp(efname, "tsshaft")) - file = particle_set_tsshaft; - else + + for (i = 0; partset_list[i].name; i++) { - if (!stricmp(efname, "none")) + if (!stricmp(efname, partset_list[i].name)) { - Con_Printf("nothing to export\n"); + file = *partset_list[i].data; + if (file) + { + COM_WriteFile(va("particles/%s.cfg", efname), file, strlen(file)); + Con_Printf("Written particles/%s.cfg\n", efname); + } + else + Con_Printf("nothing to export\n"); return; } - Con_Printf("'%s' is not a built in particle set\n", efname); - return; } - COM_WriteFile(va("particles/%s.cfg", efname), file, strlen(file)); - Con_Printf("Written particles/%s.cfg\n", efname); + Con_Printf("'%s' is not a built in particle set\n", efname); } static void P_LoadParticleSet(char *name, qboolean first) { + char *file; + int i; int restrictlevel = Cmd_FromGamecode() ? RESTRICT_SERVER : RESTRICT_LOCAL; - //particle descriptions submitted by the server are deemed to not be cheats but game configs. - if (!stricmp(name, "none")) - return; - else if (!stricmp(name, "effectinfo")) - Cbuf_AddText("r_importeffectinfo\n", RESTRICT_LOCAL); - else if (!stricmp(name, "faithful") || (first && !*name)) - Cbuf_AddText(particle_set_faithful, RESTRICT_LOCAL); - else if (!stricmp(name, "spikeset")) - Cbuf_AddText(particle_set_spikeset, RESTRICT_LOCAL); - else if (!stricmp(name, "highfps")) - Cbuf_AddText(particle_set_highfps, RESTRICT_LOCAL); - else if (!stricmp(name, "minimal")) - Cbuf_AddText(particle_set_minimal, RESTRICT_LOCAL); - else if (!stricmp(name, "tsshaft")) - Cbuf_AddText(particle_set_tsshaft, RESTRICT_LOCAL); - else + /*set up a default*/ + if (first && !*name) + name = "faithful"; + + for (i = 0; partset_list[i].name; i++) { - char *file; - FS_LoadFile(va("particles/%s.cfg", name), (void**)&file); - if (!file) - FS_LoadFile(va("%s.cfg", name), (void**)&file); - if (file) + if (!stricmp(name, partset_list[i].name)) { - Cbuf_AddText(file, restrictlevel); - Cbuf_AddText("\n", restrictlevel); - FS_FreeFile(file); + if (partset_list[i].data) + { + Cbuf_AddText(*partset_list[i].data, RESTRICT_LOCAL); + } + return; } - else if (first) - { - Con_Printf(CON_WARNING "Couldn't find particle description %s, using spikeset\n", name); - Cbuf_AddText(particle_set_spikeset, RESTRICT_LOCAL); - } - else - Con_Printf(CON_WARNING "Couldn't find particle description %s\n", name); } + + + FS_LoadFile(va("particles/%s.cfg", name), (void**)&file); + if (!file) + FS_LoadFile(va("%s.cfg", name), (void**)&file); + if (file) + { + Cbuf_AddText(file, restrictlevel); + Cbuf_AddText("\n", restrictlevel); + FS_FreeFile(file); + } + else if (first) + { + Con_Printf(CON_WARNING "Couldn't find particle description %s, using spikeset\n", name); + Cbuf_AddText(particle_set_spikeset, RESTRICT_LOCAL); + } + else + Con_Printf(CON_WARNING "Couldn't find particle description %s\n", name); } static void R_Particles_KillAllEffects(void) @@ -2120,7 +2152,7 @@ static void P_AddRainParticles(void) else VectorMA(org, 0.5, st->face->plane->normal, org); - if (!(cl.worldmodel->funcs.PointContents(cl.worldmodel, org) & FTECONTENTS_SOLID)) + if (!(cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, org) & FTECONTENTS_SOLID)) { if (st->face->flags & SURF_PLANEBACK) { @@ -2293,6 +2325,27 @@ static vec2_t avelocities[NUMVERTEXNORMALS]; // float partstep = 0.01; // float timescale = 0.01; + +static void PScript_EffectSpawned(part_type_t *ptype, vec3_t org, vec3_t dir) +{ + if (*ptype->modelname) + { + if (!ptype->model) + ptype->model = Mod_ForName(ptype->modelname, false); + if (ptype->model && !ptype->model->needload) + CL_SpawnSpriteEffect(org, dir, ptype->model, ptype->modelframestart, (ptype->modelframeend?ptype->modelframeend:(ptype->model->numframes - ptype->modelframestart)), ptype->modelframerate?ptype->modelframerate:10, ptype->modelalpha?ptype->modelalpha:1); + } + if (ptype->dl_radius) + { + dlight_t *dl = CL_NewDlightRGB(0, org, ptype->dl_radius, ptype->dl_time, ptype->dl_rgb[0], ptype->dl_rgb[1], ptype->dl_rgb[2]); + dl->channelfade[0] = ptype->dl_decay[0]; + dl->channelfade[1] = ptype->dl_decay[1]; + dl->channelfade[2] = ptype->dl_decay[2]; + } + if (ptype->stain_radius) + R_AddStain(org, ptype->stain_rgb[0], ptype->stain_rgb[1], ptype->stain_rgb[2], ptype->stain_radius); +} + int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent, vec3_t tangent2, float size, float **out); static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, int typenum, trailstate_t **tsk) { @@ -2314,7 +2367,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, if (r_part_contentswitch.ival && ptype->inwater >= 0 && cl.worldmodel) { int cont; - cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, org); + cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, org); if (cont & FTECONTENTS_WATER) ptype = &part_type[ptype->inwater]; @@ -2353,6 +2406,8 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, while(ptype) { + PScript_EffectSpawned(ptype, org, dir); + if (ptype->looks.type == PT_DECAL) { clippeddecal_t *d; @@ -2393,7 +2448,7 @@ static int PScript_RunParticleEffectState (vec3_t org, vec3_t dir, float count, VectorSubtract(org, t2, tangent); VectorAdd(org, t2, t2); - if (cl.worldmodel->funcs.Trace (cl.worldmodel, 0, 0,tangent, t2, vec3_origin, vec3_origin, &tr)) + if (cl.worldmodel->funcs.Trace (cl.worldmodel, 0, 0, NULL, tangent, t2, vec3_origin, vec3_origin, &tr)) { if (tr.fraction < dist) { @@ -3159,6 +3214,8 @@ static void P_ParticleTrailDraw (vec3_t startpos, vec3_t end, part_type_t *ptype else ts = NULL; + PScript_EffectSpawned(ptype, start, vec3_origin); + if (ptype->assoc>=0) { if (ts) @@ -3592,7 +3649,7 @@ static int PScript_ParticleTrail (vec3_t startpos, vec3_t end, int type, trailst if (r_part_contentswitch.ival && ptype->inwater >= 0) { int cont; - cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, startpos); + cont = cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, startpos); if (cont & FTECONTENTS_WATER) ptype = &part_type[ptype->inwater]; @@ -4116,14 +4173,14 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part P_RunParticleEffectType(p->org, p->vel, 1, type->emit); // make sure stain effect runs - if (type->stains && r_bloodstains.ival) + if (type->stainonimpact && r_bloodstains.ival) { if (traces-->0&&tr(oldorg, p->org, stop, normal)) { R_AddStain(stop, (p->rgba[1]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[1]*-10), - 30*p->rgba[3]*type->stains); + 30*p->rgba[3]*type->stainonimpact); } } @@ -4331,7 +4388,7 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part { if (traces-->0&&tr(oldorg, p->org, stop, normal)) { - if (type->stains && r_bloodstains.ival) + if (type->stainonimpact && r_bloodstains.ival) R_AddStain(stop, p->rgba[1]*-10+p->rgba[2]*-10, p->rgba[0]*-10+p->rgba[2]*-10, p->rgba[0]*-10+p->rgba[1]*-10, @@ -4360,14 +4417,14 @@ static void PScript_DrawParticleTypes (void (*texturedparticles)(int count, part continue; } } - else if (type->stains && r_bloodstains.ival) + else if (type->stainonimpact && r_bloodstains.ival) { if (traces-->0&&tr(oldorg, p->org, stop, normal)) { R_AddStain(stop, (p->rgba[1]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[2]*-10), (p->rgba[0]*-10+p->rgba[1]*-10), - 30*p->rgba[3]*type->stains); + 30*p->rgba[3]*type->stainonimpact); p->die = -1; continue; } diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 90471e7a7..30862b3cb 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -701,6 +701,9 @@ static qboolean CopyCSQCEdictToEntity(csqcedict_t *in, entity_t *out) else rflags = 0; + if ((int)in->v->effects & EF_NODEPTHTEST) + out->flags |= RF_NODEPTHTEST; + cs_getframestate(in, rflags, &out->framestate); VectorCopy(in->v->origin, out->origin); @@ -804,11 +807,23 @@ static void PF_R_DynamicLight_Set(progfuncs_t *prinst, struct globalvars_s *pr_g switch (field) { case 0: - VectorCopy(G_VECTOR(OFS_PARM1), l->origin); + VectorCopy(G_VECTOR(OFS_PARM2), l->origin); + l->rebuildcache = true; break; case 1: VectorCopy(G_VECTOR(OFS_PARM2), l->color); break; + case 2: + l->radius = G_FLOAT(OFS_PARM2); + l->rebuildcache = true; + break; + case 3: + l->flags = G_FLOAT(OFS_PARM2); + l->rebuildcache = true; + break; + case 4: + l->style = G_FLOAT(OFS_PARM2); + break; default: break; } @@ -818,10 +833,10 @@ static void PF_R_DynamicLight_Get(progfuncs_t *prinst, struct globalvars_s *pr_g dlight_t *l; unsigned int lno = G_FLOAT(OFS_PARM0); int field = G_FLOAT(OFS_PARM1); - if (lno >= cl_maxdlights) + if (lno >= rtlights_max) { if (field == -1) - G_FLOAT(OFS_RETURN) = cl_maxdlights; + G_FLOAT(OFS_RETURN) = rtlights_max; else G_INT(OFS_RETURN) = 0; return; @@ -835,6 +850,15 @@ static void PF_R_DynamicLight_Get(progfuncs_t *prinst, struct globalvars_s *pr_g case 1: VectorCopy(l->color, G_VECTOR(OFS_RETURN)); break; + case 2: + G_FLOAT(OFS_RETURN) = l->radius; + break; + case 3: + G_FLOAT(OFS_RETURN) = l->flags; + break; + case 4: + G_FLOAT(OFS_RETURN) = l->style; + break; default: G_INT(OFS_RETURN) = 0; break; @@ -1625,7 +1649,7 @@ static int CS_PointContents(vec3_t org) { if (!cl.worldmodel) return FTECONTENTS_EMPTY; - return cl.worldmodel->funcs.PointContents(cl.worldmodel, org); + return cl.worldmodel->funcs.PointContents(cl.worldmodel, NULL, org); } static void PF_cs_pointcontents(progfuncs_t *prinst, struct globalvars_s *pr_globals) { @@ -2494,7 +2518,6 @@ static void PF_cs_particle4(progfuncs_t *prinst, struct globalvars_s *pr_globals } -void CL_SpawnSpriteEffect(vec3_t org, model_t *model, int startframe, int framecount, int framerate); void PF_cl_effect(progfuncs_t *prinst, struct globalvars_s *pr_globals) { float *org = G_VECTOR(OFS_PARM0); @@ -2506,7 +2529,7 @@ void PF_cl_effect(progfuncs_t *prinst, struct globalvars_s *pr_globals) mdl = Mod_ForName(name, false); if (mdl) - CL_SpawnSpriteEffect(org, mdl, startframe, endframe, framerate); + CL_SpawnSpriteEffect(org, NULL, mdl, startframe, endframe, framerate, 1); else Con_Printf("PF_cl_effect: Couldn't load model %s\n", name); } diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index b201d2adb..ee63fcc44 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -557,6 +557,8 @@ void PF_CL_drawrawstring (progfuncs_t *prinst, struct globalvars_s *pr_globals) } Font_BeginScaledString(font_conchar, pos[0], pos[1], &x, &y); + x = pos[0]; + y = pos[1]; Font_ForceColour(rgb[0], rgb[1], rgb[2], alpha); while(*text) { diff --git a/engine/client/quakedef.h b/engine/client/quakedef.h index 6d7bb3e5b..2483a401f 100644 --- a/engine/client/quakedef.h +++ b/engine/client/quakedef.h @@ -242,6 +242,7 @@ extern qboolean host_initialized; // true if into command execution extern double host_frametime; extern qbyte *host_basepal; extern qbyte *host_colormap; +extern qbyte *h2playertranslations; extern int host_framecount; // incremented every frame, never reset extern double realtime; // not bounded in any way, changed at // start of every frame, never reset diff --git a/engine/client/r_part.c b/engine/client/r_part.c index f11f1965e..301e48923 100644 --- a/engine/client/r_part.c +++ b/engine/client/r_part.c @@ -187,6 +187,7 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) vec3_t delta, ts, te; physent_t *pe; qboolean clipped=false; + vec3_t axis[3]; memset (&trace, 0, sizeof(trace)); @@ -204,7 +205,14 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal) { VectorSubtract(start, pe->origin, ts); VectorSubtract(end, pe->origin, te); - pe->model->funcs.Trace(pe->model, 0, 0, ts, te, vec3_origin, vec3_origin, &trace); + if (pe->angles[0] || pe->angles[1] || pe->angles[2]) + { + AngleVectors(pe->angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); + pe->model->funcs.Trace(pe->model, 0, 0, axis, ts, te, vec3_origin, vec3_origin, &trace); + } + else + pe->model->funcs.Trace(pe->model, 0, 0, NULL, ts, te, vec3_origin, vec3_origin, &trace); if (trace.fraction<1) { VectorSubtract(trace.endpos, ts, delta); diff --git a/engine/client/r_partset.c b/engine/client/r_partset.c index ac1bd40a1..9e25a2241 100644 --- a/engine/client/r_partset.c +++ b/engine/client/r_partset.c @@ -1,5 +1,11 @@ +/* +WARNING: THIS FILE IS GENERATED BY 'generatebuiltin.c'. +YOU SHOULD NOT EDIT THIS FILE BY HAND +*/ + #include "r_partset.h" + char *particle_set_spikeset = // spikeset, originally by Spike // with contributions from TimeServ, purplehaze, Jedilamma @@ -8,7 +14,7 @@ char *particle_set_spikeset = //rocket trails (derived from purplehaze's, with only minor tweeks) "r_part rocketsmoke\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "step 8\n" @@ -21,10 +27,10 @@ char *particle_set_spikeset = "spawnmode spiral\n" "scalefactor 1\n" "spawnvel 5\n" -"}\n" +"}\n" "r_part rockettrail\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "step 4\n" @@ -39,10 +45,10 @@ char *particle_set_spikeset = "scalefactor 1\n" "assoc rocketsmoke\n" "spawnvel 10\n" -"}\n" +"}\n" "r_part t_rocket\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "step 2\n" @@ -55,10 +61,10 @@ char *particle_set_spikeset = "assoc rockettrail\n" "scalefactor 0.8\n" "scaledelta -10\n" -"}\n" +"}\n" "r_part rockettail\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "step 7\n" @@ -70,10 +76,10 @@ char *particle_set_spikeset = "rgb 192 192 192\n" "gravity 100\n" "cliptype rockettail\n" -"}\n" +"}\n" "r_part t_altrocket\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "step 4\n" @@ -87,12 +93,12 @@ char *particle_set_spikeset = "gravity -100\n" "blend add\n" "assoc rockettail\n" -"}\n" +"}\n" // te_railtrail, used with Quake 2 railgun and also used with // TeamFortress engineer railgun "r_part railtrailinner\n" -"{\n" +"{\n" "step 30\n" "scale 5\n" "die 1\n" @@ -101,10 +107,10 @@ char *particle_set_spikeset = "blend add\n" "type beam\n" "spawnvel 2 2\n" -"}\n" +"}\n" "r_part railtrail240\n" -"{\n" +"{\n" "step 15\n" "scale 3\n" "die 1\n" @@ -123,10 +129,10 @@ char *particle_set_spikeset = "spawnparam2 240\n" "spawnvel 12\n" "assoc railtrailinner\n" -"}\n" +"}\n" "r_part railtrail120\n" -"{\n" +"{\n" "step 15\n" "scale 3\n" "die 1\n" @@ -145,10 +151,10 @@ char *particle_set_spikeset = "spawnparam2 120\n" "spawnvel 12\n" "assoc railtrail240\n" -"}\n" +"}\n" "r_part te_railtrail\n" -"{\n" +"{\n" "step 15\n" "scale 3\n" "die 1\n" @@ -166,10 +172,10 @@ char *particle_set_spikeset = "spawnparam1 256\n" "spawnvel 12\n" "assoc railtrail120\n" -"}\n" +"}\n" "r_part shortfume\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "scale 15\n" @@ -180,10 +186,10 @@ char *particle_set_spikeset = "randomvel 12\n" "scaledelta 0.81\n" "rgb 150 150 150\n" -"}\n" +"}\n" "r_part t_grenade\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "step 24\n" @@ -198,11 +204,11 @@ char *particle_set_spikeset = "gravity -50\n" "scalefactor 0.0\n" "assoc shortfume\n" -"}\n" +"}\n" //cool's blood trails (cos they're cooler) "r_part t_gib\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 1 63 63 256 2 64\n" "step 32\n" @@ -218,10 +224,10 @@ char *particle_set_spikeset = "scalefactor 0.8\n" "scaledelta -10\n" "stains 5\n" -"}\n" +"}\n" "r_part t_zomgib\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 1 63 63 256 2 64\n" "step 64\n" @@ -237,10 +243,10 @@ char *particle_set_spikeset = "scalefactor 0.8\n" "scaledelta -10\n" "stains 5\n" -"}\n" +"}\n" "r_part t_tracer\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "scale 15\n" @@ -252,10 +258,10 @@ char *particle_set_spikeset = "randomvel 50\n" "friction 4\n" "scalefactor 0.825\n" -"}\n" +"}\n" "r_part t_tracer2\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "scale 15\n" @@ -267,10 +273,10 @@ char *particle_set_spikeset = "randomvel 50\n" "friction 4\n" "scalefactor 0.825\n" -"}\n" +"}\n" "r_part t_tracer3\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "scale 10\n" @@ -285,11 +291,11 @@ char *particle_set_spikeset = "spawnvel 60 0\n" "friction 4\n" "scalefactor 0.825\n" -"}\n" +"}\n" //qw blood "r_part te_lightningblood\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 97 255 159 256\n" "count 3\n" @@ -304,11 +310,11 @@ char *particle_set_spikeset = "friction 1\n" "stains 1\n" "blend add\n" -"}\n" +"}\n" //qw blood "r_part te_blood\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 97 255 159 256\n" "count 10\n" @@ -322,11 +328,11 @@ char *particle_set_spikeset = "stains 2\n" "scalefactor 0.9\n" "rotationstart 0 360\n" -"}\n" +"}\n" //nq blood "r_part pe_73\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 97 255 159 256\n" "count 1\n" @@ -340,12 +346,12 @@ char *particle_set_spikeset = "stains 2\n" "scalefactor 0.9\n" "rotationstart 0 360\n" -"}\n" +"}\n" ///////////////////////////////////////////////// //rocket explosions "r_part ember\n" -"{\n" +"{\n" "count 1\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" @@ -359,18 +365,18 @@ char *particle_set_spikeset = "blend add\n" "randomvel 5\n" "veladd 1\n" -"rampmode delta\n" //fade it in then out. +"rampmode delta\n" "ramp 0 0 0 -0.5 0\n" "ramp 0 0 0 0.1 0\n" "ramp 0 0 0 0.1 0\n" "ramp 0 0 0 0.1 0\n" "ramp 0 0 0 0.1 0\n" "ramp 0 0 0 0.1 0\n" -"}\n" +"}\n" //the bits that fly off "r_part expgib\n" -"{\n" +"{\n" "cliptype expgib\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" @@ -383,11 +389,11 @@ char *particle_set_spikeset = "emit ember\n" "emitinterval 0.01\n" "spawnmode circle\n" -"}\n" +"}\n" //the heart of the explosion "r_part te_explosion\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "count 1\n" @@ -399,10 +405,10 @@ char *particle_set_spikeset = "friction 1\n" "blend add\n" "assoc expgib\n" -"}\n" +"}\n" "r_part gunshotsmoke\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 65 31 95 256 8 32\n" "count 3\n" @@ -416,10 +422,10 @@ char *particle_set_spikeset = "spawnorg 2\n" "spawnvel 20\n" "veladd -20\n" -"}\n" +"}\n" "r_part te_gunshot\n" -"{\n" +"{\n" "type texturedspark\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 65 31 95 256 8 32\n" @@ -437,10 +443,10 @@ char *particle_set_spikeset = "friction 0.3\n" "gravity 400\n" "assoc gunshotsmoke\n" -"}\n" +"}\n" "r_part spikecore\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "count 1\n" @@ -452,10 +458,10 @@ char *particle_set_spikeset = "rgb 255 128 0\n" "blend add\n" "assoc gunshotsmoke\n" -"}\n" +"}\n" "r_part te_spike\n" -"{\n" +"{\n" "type sparkfan\n" "count 10\n" "scale 1\n" @@ -468,10 +474,10 @@ char *particle_set_spikeset = "spawnorg 12\n" "spawnvel 300\n" "assoc spikecore\n" -"}\n" +"}\n" "r_part te_lavasplash\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 129 1 191 63 256\n" "count 654\n" @@ -484,14 +490,14 @@ char *particle_set_spikeset = "blend add\n" "spawnorg 192 64\n" "up 48\n" -"}\n" +"}\n" ////////////////////////////////////////////////// //Teleport splash //two rings moving upwards, costs less "r_part teleportsplashdown\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 1 255 63 256\n" "count 32\n" @@ -504,9 +510,9 @@ char *particle_set_spikeset = "friction 1\n" "spawnorg 32 0\n" "spawnmode uniformcircle\n" -"}\n" +"}\n" "r_part te_teleportsplash\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 1 255 63 256\n" "count 32\n" @@ -520,11 +526,11 @@ char *particle_set_spikeset = "spawnorg 32 0\n" "spawnmode uniformcircle\n" "assoc teleportsplashdown\n" -"}\n" +"}\n" //flame effect "r_part cu_flame\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 129 1 191 63 256\n" "count 1024\n" @@ -540,11 +546,11 @@ char *particle_set_spikeset = "up -8\n" "spawnorg 6 0\n" "spawnvel -15 0\n" -"}\n" +"}\n" //flame effect "r_part cu_torch\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 129 1 191 63 256\n" "count 256\n" @@ -559,10 +565,10 @@ char *particle_set_spikeset = "spawnmode circle\n" "spawnorg 4 1\n" "spawnvel -12 -8\n" -"}\n" +"}\n" "r_part explodesprite\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 97 97 191 191 256\n" "count 180\n" @@ -578,11 +584,11 @@ char *particle_set_spikeset = "spawnorg 4 1\n" "spawnvel -8 -2\n" "up -8\n" -"}\n" +"}\n" //you'll probably never see this one "r_part ef_entityparticles\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "count 1\n" @@ -592,11 +598,11 @@ char *particle_set_spikeset = "veladd 16\n" "rgb 255 128 128\n" "blend add\n" -"}\n" +"}\n" // emp effect, based off of purplehaze's idea "r_part empshocktrail\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 1 255 63 256\n" "step 3.2\n" @@ -607,10 +613,10 @@ char *particle_set_spikeset = "blend add\n" "scalefactor 1\n" "spawnorg 12 0\n" -"}\n" +"}\n" "r_part empcore\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 1 255 63 256\n" "count 90\n" @@ -625,11 +631,11 @@ char *particle_set_spikeset = "scalefactor 0.8\n" "emit empshocktrail\n" "emitinterval -1\n" -"}\n" +"}\n" "r_part empflash\n" -"{\n" +"{\n" "die 0.1\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 193 1 255 63 256\n" @@ -642,10 +648,10 @@ char *particle_set_spikeset = "blend add\n" "scalefactor 1\n" "assoc empcore\n" -"}\n" +"}\n" "r_part te_tarexplosion\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "count 120\n" @@ -666,10 +672,10 @@ char *particle_set_spikeset = "emit empshocktrail\n" "emitinterval -1\n" "assoc empflash\n" -"}\n" +"}\n" "r_part pe_default\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "count 1\n" @@ -680,10 +686,10 @@ char *particle_set_spikeset = "diesubrand 0.4\n" "gravity 40\n" "spawnorg 8\n" -"}\n" +"}\n" "r_part pe_defaulttrail\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "step 12\n" @@ -693,10 +699,10 @@ char *particle_set_spikeset = "veladd 15\n" "spawnorg 1\n" "scalefactor 0.8\n" -"}\n" +"}\n" "r_part pe_pointfile\n" -"{\n" +"{\n" "texture \"particles/fteparticlefont.tga\"\n" "tcoords 1 97 95 191 256\n" "count 1\n" @@ -704,23 +710,25 @@ char *particle_set_spikeset = "die 30\n" "alphadelta 0\n" "rgb 255 255 0\n" -"}\n" +"}\n" "r_effect \"progs/s_explod.spr\" explodesprite 1\n" "r_effect \"progs/flame.spr\" explodesprite 1\n" "r_effect \"progs/flame2.mdl\" cu_flame 1\n" "r_effect \"progs/flame.mdl\" cu_torch\n" -"r_trail \"progs/e_spike1.mdl\" te_railtrail\n"; +"r_trail \"progs/e_spike1.mdl\" te_railtrail\n" +; -/////////////////////////////////////////////////////// +////////////////////////////////////////////////////// + char *particle_set_faithful = // faithful, by TimeServ "r_part t_gib\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -732,10 +740,10 @@ char *particle_set_faithful = "gravity 40\n" "spawnorg 3\n" "stains 1\n" -"}\n" +"}\n" "r_part t_zomgib\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 6\n" "scale 4\n" @@ -747,10 +755,10 @@ char *particle_set_faithful = "gravity 40\n" "spawnorg 3\n" "stains 1\n" -"}\n" +"}\n" "r_part t_tracer3\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -758,10 +766,10 @@ char *particle_set_faithful = "alphadelta 0\n" "colorindex 152 4\n" "spawnorg 8\n" -"}\n" +"}\n" "r_part t_tracer\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -771,10 +779,10 @@ char *particle_set_faithful = "citracer\n" "spawnvel 30 0\n" "spawnmode tracer\n" -"}\n" +"}\n" "r_part t_tracer2\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -784,10 +792,10 @@ char *particle_set_faithful = "citracer\n" "spawnvel 30 0\n" "spawnmode tracer\n" -"}\n" +"}\n" "r_part t_rocket\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -802,10 +810,10 @@ char *particle_set_faithful = "rampindex 3 0.167\n" "spawnorg 3\n" "gravity -40\n" -"}\n" +"}\n" "r_part t_altrocket\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -815,10 +823,10 @@ char *particle_set_faithful = "rampindexlist 109 107 6 5 4 3\n" "spawnorg 3\n" "gravity -40\n" -"}\n" +"}\n" "r_part t_grenade\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -831,10 +839,10 @@ char *particle_set_faithful = "rampindex 3 0.167\n" "spawnorg 3\n" "gravity -40\n" -"}\n" +"}\n" "r_part pe_size3\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "scale 4\n" @@ -844,10 +852,10 @@ char *particle_set_faithful = "diesubrand 0.4\n" "gravity 40\n" "spawnorg 24\n" -"}\n" +"}\n" "r_part pe_size2\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "scale 4\n" @@ -857,10 +865,10 @@ char *particle_set_faithful = "diesubrand 0.4\n" "gravity 40\n" "spawnorg 16\n" -"}\n" +"}\n" "r_part pe_default\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "scale 4\n" @@ -870,10 +878,10 @@ char *particle_set_faithful = "diesubrand 0.4\n" "gravity 40\n" "spawnorg 8\n" -"}\n" +"}\n" "r_part explode2\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 512\n" "scale 4\n" @@ -881,15 +889,15 @@ char *particle_set_faithful = "die 0.5333\n" "diesubrand 0.2667\n" "rampmode absolute\n" -"rampindexlist 111 110 109 108 107 106 104 102\n" +"rampindexlist 111 110 109 108 107 106 104 102 \n" "randomvel 256\n" "gravity 40\n" "friction 1\n" "spawnorg 16\n" -"}\n" +"}\n" "r_part te_explosion\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 512\n" "scale 4\n" @@ -897,15 +905,15 @@ char *particle_set_faithful = "diesubrand 0.4\n" "randomvel 256\n" "rampmode absolute\n" -"rampindexlist 111 109 107 105 103 101 99 97\n" +"rampindexlist 111 109 107 105 103 101 99 97 \n" "gravity 40\n" "friction -4\n" "spawnorg 16\n" "assoc explode2\n" -"}\n" +"}\n" "r_part blobexp2b\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 256\n" "scale 4\n" @@ -916,9 +924,9 @@ char *particle_set_faithful = "friction 4 0\n" "spawnorg 16\n" "randomvel 256\n" -"}\n" +"}\n" "r_part blobexp1b\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 256\n" "scale 4\n" @@ -930,10 +938,10 @@ char *particle_set_faithful = "spawnorg 16\n" "randomvel 256\n" "assoc blobexp2b\n" -"}\n" +"}\n" "r_part blobexp2\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 256\n" "scale 4\n" @@ -945,9 +953,9 @@ char *particle_set_faithful = "spawnorg 16\n" "randomvel 256\n" "assoc blobexp1b\n" -"}\n" +"}\n" "r_part te_tarexplosion\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 256\n" "scale 4\n" @@ -959,10 +967,10 @@ char *particle_set_faithful = "randomvel 256\n" "spawnorg 16\n" "assoc blobexp2\n" -"}\n" +"}\n" "r_part te_teleportsplash\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 896\n" "scale 4\n" @@ -975,10 +983,10 @@ char *particle_set_faithful = "spawnmode telebox\n" "spawnorg 16 28\n" "spawnvel 113\n" -"}\n" +"}\n" "r_part te_lavasplash\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1024\n" "scale 4\n" @@ -990,10 +998,10 @@ char *particle_set_faithful = "spawnorg 128 63\n" "spawnvel 113\n" "spawnmode lavasplash\n" -"}\n" +"}\n" "r_part pe_defaulttrail\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 3\n" "scale 4\n" @@ -1001,23 +1009,30 @@ char *particle_set_faithful = "diesubrand 0.6\n" "spawnorg 3\n" "gravity -40\n" -"}\n" +"}\n" "r_part pe_pointfile\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "scale 4\n" "die 30\n" "alphadelta 0\n" "rgb 255 255 0\n" -"}\n"; +"}\n" + +; + + + +////////////////////////////////////////////////////// + char *particle_set_highfps = // highfps, originally submitted by 'ShadowWalker' // rehashed by TimeServ "r_part t_gib\n" -"{\n" +"{\n" "texture \"particles/bloodtrail\"\n" "step 12\n" "scale 10\n" @@ -1026,9 +1041,9 @@ char *particle_set_highfps = "veladd 32\n" "rgb 64 0 0\n" "rgbdelta -128 0 0\n" -"}\n" +"}\n" "r_part t_zomgib\n" -"{\n" +"{\n" "texture \"particles/bloodtrail\"\n" "step 16\n" "scale 8\n" @@ -1037,37 +1052,37 @@ char *particle_set_highfps = "veladd 32\n" "rgb 192 0 0\n" "rgbdelta -128 0 0\n" -"}\n" +"}\n" "r_part t_tracer\n" -"{\n" +"{\n" "texture \"particles/tracer\"\n" "scale 23\n" "step 18\n" "rgb 192 192 0\n" "die 0.5\n" -"}\n" +"}\n" "r_part t_tracer2\n" -"{\n" +"{\n" "texture \"particles/tracer\"\n" "scale 23\n" "step 18\n" "die 0.5\n" "rgb 192 96 0\n" -"}\n" +"}\n" "r_part t_tracer3\n" -"{\n" +"{\n" "texture \"particles/tracer\"\n" "scale 23\n" "step 18\n" "die 0.5\n" "rgb 192 0 192\n" -"}\n" +"}\n" "r_part te_lightningblood\n" -"{\n" +"{\n" "texture \"particles/bloodtrail\"\n" "count 1\n" "scale 10\n" @@ -1076,10 +1091,10 @@ char *particle_set_highfps = "veladd 128\n" "rgb 192 0 0\n" "blend add\n" -"}\n" +"}\n" "r_part te_blood\n" -"{\n" +"{\n" "texture \"particles/bloodtrail\"\n" "count 1\n" "scale 12\n" @@ -1088,10 +1103,10 @@ char *particle_set_highfps = "veladd 64\n" "spawnvel 0 10\n" "rgb 64 0 0\n" -"}\n" +"}\n" "r_part sparks\n" -"{\n" +"{\n" "texture \"particles/spark\"\n" "count 32\n" "scale 3\n" @@ -1103,10 +1118,10 @@ char *particle_set_highfps = "blend add\n" "cliptype sparks\n" "clipcount 1\n" -"}\n" +"}\n" "r_part explosioncore\n" -"{\n" +"{\n" "texture \"particles/explosion\"\n" "count 1\n" "scale 200\n" @@ -1115,10 +1130,10 @@ char *particle_set_highfps = "rgb 255 128 76\n" "blend add\n" "assoc sparks\n" -"}\n" +"}\n" "r_part te_explosion\n" -"{\n" +"{\n" "texture \"particles/explosion\"\n" "count 8\n" "scale 60\n" @@ -1129,10 +1144,10 @@ char *particle_set_highfps = "assoc explosioncore\n" "spawnmode ball\n" "spawnorg 64\n" -"}\n" +"}\n" "r_part te_railtrail\n" -"{\n" +"{\n" "step 1000000\n" "scale 5\n" "die 1.2\n" @@ -1141,11 +1156,11 @@ char *particle_set_highfps = "blend add\n" "type beam\n" "averageout\n" -"}\n" +"}\n" //the blob tempent is used quite a bit with teamfortress emp grenades. "r_part te_tarexplosion\n" -"{\n" +"{\n" "texture \"particles/blob\"\n" "count 64\n" "scale 30\n" @@ -1156,10 +1171,10 @@ char *particle_set_highfps = "rgb 255 0 196\n" "spawnorg 8 56\n" "spawnvel 48 8\n" -"}\n" +"}\n" "r_part te_gunshot\n" -"{\n" +"{\n" "texture \"particles/spark\"\n" "count 2\n" "scale 3\n" @@ -1168,10 +1183,10 @@ char *particle_set_highfps = "randomvel 64\n" "rgb 255 128 0\n" "blend add\n" -"}\n" +"}\n" "r_part te_lavasplash\n" -"{\n" +"{\n" "texture \"particles/lava\"\n" "count 180\n" "scale 60\n" @@ -1181,10 +1196,10 @@ char *particle_set_highfps = "spawnorg 178 64\n" "up 56\n" "scalefactor 1\n" -"}\n" +"}\n" "r_part te_teleportsplash\n" -"{\n" +"{\n" "texture \"particles/teleport\"\n" "count 48\n" "scale 30\n" @@ -1195,20 +1210,20 @@ char *particle_set_highfps = "rgb 255 255 255\n" "spawnorg 4 32\n" "spawnvel 25 4\n" -"}\n" +"}\n" "r_part t_grenade\n" -"{\n" +"{\n" "texture \"particles/smoke\"\n" "step 20\n" "scale 21\n" "die 0.5\n" "randvel 16\n" "rgb 128 128 128\n" -"}\n" +"}\n" "r_part t_rocket\n" -"{\n" +"{\n" "texture \"particles/rocket\"\n" "step 15\n" "scale 30\n" @@ -1216,10 +1231,10 @@ char *particle_set_highfps = "rgb 192 48 0\n" "blend add\n" "assoc t_grenade\n" -"}\n" +"}\n" "r_part t_altrocket\n" -"{\n" +"{\n" "texture \"particles/rocket\"\n" "step 15\n" "scale 25\n" @@ -1228,11 +1243,11 @@ char *particle_set_highfps = "die 0.5\n" "rgb 192 48 0\n" "blend add\n" -"}\n" +"}\n" //you'll probably never see this one "r_part ef_entityparticles\n" -"{\n" +"{\n" "texture \"j\"\n" "count 1\n" "scale 10\n" @@ -1240,42 +1255,49 @@ char *particle_set_highfps = "die 0\n" "veladd 16\n" "rgb 128 128 0\n" -"}\n" +"}\n" "r_part pe_default\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "scale 4\n" "veladd 15\n" "die 0.5\n" "spawnorg 8\n" -"}\n" +"}\n" "r_part pe_defaulttrail\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 15\n" "die 0.5\n" "scale 8\n" "veladd 15\n" "spawnorg 1\n" -"}\n" +"}\n" "r_part pe_pointfile\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "scale 50\n" "die 30\n" "alphadelta 0\n" "rgb 255 255 0\n" -"}\n"; +"}\n" + +; + + + +////////////////////////////////////////////////////// + char *particle_set_minimal = // minimal, by TimeServ "r_part pe_size3\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "die 1\n" @@ -1285,10 +1307,10 @@ char *particle_set_minimal = "spawnorg 38\n" "spawnvel 38\n" "scalefactor 0.8\n" -"}\n" +"}\n" "r_part pe_size2\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "die 1\n" @@ -1298,10 +1320,10 @@ char *particle_set_minimal = "spawnorg 16\n" "spawnvel 16\n" "scalefactor 0.8\n" -"}\n" +"}\n" "r_part pe_default\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "count 1\n" "die 1\n" @@ -1311,10 +1333,10 @@ char *particle_set_minimal = "spawnorg 10\n" "spawnvel 10\n" "scalefactor 0.8\n" -"}\n" +"}\n" "r_part pe_defaulttrail\n" -"{\n" +"{\n" "texture \"particles/quake\"\n" "step 10\n" "die 1\n" @@ -1324,16 +1346,256 @@ char *particle_set_minimal = "spawnorg 2\n" "spawnvel 2\n" "scalefactor 0.8\n" -"}\n"; +"}\n" +; + + + +////////////////////////////////////////////////////// + + +char *particle_set_h2part = +"r_part ce_white_smoke_05\n" +"{\n" +"model models/whtsmk1.spr 0 0 20 0.5\n" +"}\n" +"r_part ce_white_smoke_10\n" +"{\n" +"model models/whtsmk1.spr 0 0 10 0.5\n" +"}\n" +"r_part ce_white_smoke_15\n" +"{\n" +"model models/whtsmk1.spr 0 0 6.666 0.5\n" +"}\n" +"r_part ce_white_smoke_20\n" +"{\n" +"model models/whtsmk1.spr 0 0 5 0.5\n" +"}\n" +"r_part ce_white_smoke_50\n" +"{\n" +"model models/whtsmk1.spr 0 0 2 0.5\n" +"}\n" + +"r_part ce_bluespark\n" +"{\n" +"model models/bspark.spr 0 0 20 1\n" +"}\n" +"r_part ce_yellowspark\n" +"{\n" +"model models/spark.spr 0 0 20 1\n" +"}\n" +"r_part ce_sm_circle_exp\n" +"{\n" +"model models/fcircle.spr 0 0 20 1\n" +"}\n" +"r_part ce_bg_circle_exp\n" +"{\n" +"model models/xplod29.spr 0 0 20 1\n" +"}\n" +"r_part ce_sm_white_flash\n" +"{\n" +"model models/sm_white.spr 0 0 20 1\n" +"}\n" +"r_part ce_white_flash\n" +"{\n" +"model models/gryspt.spr 0 0 20 0.4\n" +"}\n" +"r_part ce_yellowred_flash\n" +"{\n" +"model models/yr_flsh.spr 0 0 20 0.4\n" +"}\n" +"r_part ce_blue_flash\n" +"{\n" +"model models/bluflash.spr 0 0 20 0.4\n" +"}\n" +"r_part ce_sm_blue_flash\n" +"{\n" +"model models/sm_blue.spr 0 0 20 0.4\n" +"}\n" +"r_part ce_red_flash\n" +"{\n" +"model models/redspt.spr 0 0 20 0.4\n" +"}\n" +"r_part ce_sm_explosion\n" +"{\n" +"model models/sm_expld.spr 0 0 20 1\n" +"}\n" +"r_part ce_lg_explosion\n" +"{\n" +"model models/bg_expld.spr 0 0 20 1\n" +"}\n" +"r_part ce_floor_explosion\n" +"{\n" +"model models/fl_expld.spr 0 0 20 1\n" +"}\n" +"r_part ce_rider_death\n" +"{\n" +"}\n" +"r_part ce_blue_explosion\n" +"{\n" +"model models/xpspblue.spr 0 0 20 1\n" +"}\n" +"r_part ce_green_smoke_05\n" +"{\n" +"model models/grnsmk1.spr 0 0 20 0.5\n" +"}\n" +"r_part ce_green_smoke_10\n" +"{\n" +"model models/grnsmk1.spr 0 0 10 0.5\n" +"}\n" +"r_part ce_green_smoke_15\n" +"{\n" +"model models/grnsmk1.spr 0 0 6.666 0.5\n" +"}\n" +"r_part ce_green_smoke_20\n" +"{\n" +"model models/grnsmk1.spr 0 0 5 0.5\n" +"}\n" +// ce_grey_smoke +"r_part ce_grey_smoke_15\n" +"{\n" +"model models/grysmk1.spr 0 0 6.666 0.5\n" +"}\n" +"r_part ce_red_smoke\n" +"{\n" +"model models/redsmk1.spr 0 0 6.666 0.5\n" +"}\n" +"r_part ce_slow_white_smoke\n" +"{\n" +"model models/whtsmk1.spr 0 0 20 0.5\n" +"}\n" +"r_part ce_redspark\n" +"{\n" +"model models/rspark.spr 0 0 20 1\n" +"}\n" +"r_part ce_greenspark\n" +"{\n" +"model models/gspark.spr 0 0 20 1\n" +"}\n" +"r_part ce_telesmk1\n" +"{\n" +"model models/telesmk1.spr 0 0 15 1\n" +"}\n" +"r_part ce_telesmk2\n" +"{\n" +"model models/telesmk2.spr 0 0 15 1\n" +"}\n" +"r_part ce_icehit\n" +"{\n" +"model models/icehit.spr 0 0 20 0.5\n" +"}\n" +"r_part ce_medusa_hit\n" +"{\n" +"model models/medhit.spr 0 0 20 1\n" +"}\n" +"r_part ce_mezzo_reflect\n" +"{\n" +"model models/mezzoref.spr 0 0 20 1\n" +"}\n" +"r_part ce_floor_explosion2\n" +"{\n" +"model models/flrexpl2.spr 0 0 20 1\n" +"}\n" +"r_part ce_xbow_explosion\n" +"{\n" +"model models/xbowexpl.spr 0 0 20 1\n" +"}\n" +"r_part ce_new_explosion\n" +"{\n" +"model models/gen_expl.spr 0 0 20 1\n" +"}\n" +"r_part ce_magic_missile_explosion\n" +"{\n" +"model models/mm_explod.spr 0 0 20 1\n" +"}\n" +// ce_ghost +"r_part ce_bone_explosion\n" +"{\n" +"model models/bonexpld.spr 0 0 20 1\n" +"}\n" +// ce_redcloud +"r_part ce_teleporterpuffs\n" +"{\n" +// model models/telesmk2.spr 0 0 20 1 +"}\n" +// ce_teleporterbody +// ce_boneshard +// ce_boneshrapnel +"r_part ce_flamestream\n" +"{\n" +"model models/flamestr.spr 0 0 20 1\n" +"}\n" +// ce_snow, +// ce_gravitywell +"r_part ce_bldrn_expl\n" +"{\n" +"model models/xplsn_1.spr 0 0 20 1\n" +"}\n" +// ce_acid_muzzfl +"r_part ce_acid_hit\n" +"{\n" +"model models/axplsn_2.spr 0 0 20 1\n" +"}\n" +"r_part ce_firewall_small\n" +"{\n" +"model models/firewal1.spr 0 0 20 1\n" +"}\n" +"r_part ce_firewall_medium\n" +"{\n" +"model models/firewal5.spr 0 0 20 1\n" +"}\n" +"r_part ce_firewall_large\n" +"{\n" +"model models/firewal4.spr 0 0 20 1\n" +"}\n" +"r_part ce_lball_expl\n" +"{\n" +"model models/Bluexp3.spr 0 0 20 1\n" +"}\n" +"r_part ce_acid_splat\n" +"{\n" +"model models/axplsn_1.spr 0 0 20 1\n" +"}\n" +"r_part ce_acid_expl\n" +"{\n" +"model models/axplsn_5.spr 0 0 20 1\n" +"}\n" +"r_part ce_fboom\n" +"{\n" +"model models/fboom.spr 0 0 20 1\n" +"}\n" +// ce_chunk +"r_part ce_bomb\n" +"{\n" +"model models/pow.spr 0 0 20 1\n" +"}\n" +"r_part ce_brn_bounce\n" +"{\n" +"model models/spark.spr 0 0 20 1\n" +"}\n" +"r_part ce_lshock\n" +"{\n" +"model models/vorpshok.mdl 0 0 20 1\n" +"}\n" +// ce_flamewall +// ce_flamewall2 +"r_part ce_floor_explosion3\n" +"{\n" +"model models/biggy.spr 0 0 20 1\n" +"}\n" +; + + + +////////////////////////////////////////////////////// -// --- addon scripts will start here char *particle_set_tsshaft = // TE_LIGHTNING2 replacement, (c) 2005 TimeServ // If you steal this GPLed code you will be violating several international laws // as well as several laws of physics. "r_part tlightningflash\n" -"{\n" +"{\n" "spawntime 0.1\n" "spawnchance 0.1\n" "die 0.25\n" @@ -1349,10 +1611,10 @@ char *particle_set_tsshaft = "averageout\n" "nospreadfirst\n" "blend add\n" -"}\n" +"}\n" "r_part tlightningglow\n" -"{\n" +"{\n" "step 50\n" "scale 35\n" "scalefactor 1\n" @@ -1361,10 +1623,10 @@ char *particle_set_tsshaft = "rgb 1 1 8\n" "blend add\n" "assoc tlightningflash\n" -"}\n" +"}\n" "r_part tlightningfade\n" -"{\n" +"{\n" "spawntime 0.05\n" "die 0.2\n" "type beam\n" @@ -1379,10 +1641,10 @@ char *particle_set_tsshaft = "averageout\n" "nospreadfirst\n" "assoc tlightningglow\n" -"}\n" +"}\n" "r_part te_lightning2\n" -"{\n" +"{\n" "die 0\n" "type beam\n" "alpha 2\n" @@ -1396,10 +1658,10 @@ char *particle_set_tsshaft = "averageout\n" "nospreadfirst\n" "assoc tlightningfade\n" -"}\n" +"}\n" "r_part lbolttrail\n" -"{\n" +"{\n" "die 0.5\n" "type beam\n" "alpha 2\n" @@ -1412,10 +1674,10 @@ char *particle_set_tsshaft = "spawnvel 4\n" "spawnparam1 0.5\n" "blend add\n" -"}\n" +"}\n" "r_part lbolt\n" -"{\n" +"{\n" "die 0.5\n" "count 1\n" "spawnmode circle\n" @@ -1423,10 +1685,10 @@ char *particle_set_tsshaft = "spawnorg 1\n" "emit lbolttrail\n" "emitinterval -1\n" -"}\n" +"}\n" "r_part lemit\n" -"{\n" +"{\n" "die 0.1\n" "count 1\n" "spawnchance 1\n" @@ -1436,10 +1698,10 @@ char *particle_set_tsshaft = "cliptype lemit\n" "clipcount 1\n" "clipbounce 0\n" -"}\n" +"}\n" "r_part lflash\n" -"{\n" +"{\n" "die 0.1\n" "texture \"particles/lflash\"\n" "count 1\n" @@ -1450,10 +1712,10 @@ char *particle_set_tsshaft = "rgb 255 255 255\n" "blend add\n" "assoc lemit\n" -"}\n" +"}\n" "r_part te_lightning2_end\n" -"{\n" +"{\n" "die 0.3\n" "alpha 1\n" "count 8\n" @@ -1465,4 +1727,5 @@ char *particle_set_tsshaft = "spawnorg 5\n" "blend add\n" "assoc lflash\n" -"}\n"; +"}\n" +; diff --git a/engine/client/r_partset.h b/engine/client/r_partset.h index 5547f630a..1f3528bcd 100644 --- a/engine/client/r_partset.h +++ b/engine/client/r_partset.h @@ -1,6 +1,7 @@ extern char *particle_set_spikeset; -extern char *particle_set_highfps; extern char *particle_set_faithful; +extern char *particle_set_highfps; extern char *particle_set_minimal; +extern char *particle_set_h2part; extern char *particle_set_tsshaft; - +#define R_PARTSET_BUILTINS {"spikeset", &particle_set_spikeset},{"faithful", &particle_set_faithful},{"highfps", &particle_set_highfps},{"minimal", &particle_set_minimal},{"h2part", &particle_set_h2part},{"tsshaft", &particle_set_tsshaft}, diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 33c1d2955..2aa6d2943 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -467,6 +467,7 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf) // float temp; float r, g, b; unsigned *bl; + vec3_t lightofs; smax = (surf->extents[0]>>4)+1; tmax = (surf->extents[1]>>4)+1; @@ -478,7 +479,8 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf) continue; // not lit by this light rad = cl_dlights[lnum].radius; - dist = DotProduct (cl_dlights[lnum].origin, surf->plane->normal) - + VectorSubtract(cl_dlights[lnum].origin, currententity->origin, lightofs); + dist = DotProduct (lightofs, surf->plane->normal) - surf->plane->dist; rad -= fabs(dist); minlight = cl_dlights[lnum].minlight; @@ -488,7 +490,7 @@ static void Surf_AddDynamicLightsColours (msurface_t *surf) for (i=0 ; i<3 ; i++) { - impact[i] = cl_dlights[lnum].origin[i] - + impact[i] = lightofs[i] - surf->plane->normal[i]*dist; } @@ -1250,8 +1252,8 @@ void Surf_RenderDynamicLightmaps (msurface_t *fa, int shift) // check for lightmap modification if (!fa->samples) { - if (d_lightstylevalue[0] != fa->cached_light[0] - || cl_lightstyle[0].colour != fa->cached_colour[0]) + if (fa->cached_light[0] != 0 + || fa->cached_colour[0] != 0) goto dynamic; } else @@ -1793,17 +1795,20 @@ static void Surf_CleanChains(void) { model_t *model = cl.worldmodel; batch_t *batch; + int i; if (r_refdef.recurse) { - for (batch = model->batches; batch; batch = batch->next) + for (i = 0; i < SHADER_SORT_COUNT; i++) + for (batch = model->batches[i]; batch; batch = batch->next) { batch->meshes = batch->firstmesh; } } else { - for (batch = model->batches; batch; batch = batch->next) + for (i = 0; i < SHADER_SORT_COUNT; i++) + for (batch = model->batches[i]; batch; batch = batch->next) { batch->meshes = batch->firstmesh; } @@ -2336,12 +2341,16 @@ void Surf_DeInit(void) void Surf_Clear(model_t *mod) { batch_t *b; - while ((b = mod->batches)) + int i; + for (i = 0; i < SHADER_SORT_COUNT; i++) { - mod->batches = b->next; + while ((b = mod->batches[i])) + { + mod->batches[i] = b->next; - BZ_Free(b->mesh); - Z_Free(b); + BZ_Free(b->mesh); + Z_Free(b); + } } } @@ -2362,6 +2371,7 @@ void Surf_BuildLightmaps (void) msurface_t *surf; batch_t *batch, *bstop; vec3_t sn; + int sortid; r_framecount = 1; // no dlightcache @@ -2412,7 +2422,8 @@ void Surf_BuildLightmaps (void) { m->textures[t]->wtexno = t; - bstop = m->batches; + sortid = m->textures[t]->shader->sort; + bstop = m->batches[sortid]; batch = NULL; for (i=0 ; inumsurfaces ; i++) {//extra texture loop so we get slightly less texture switches @@ -2423,7 +2434,7 @@ void Surf_BuildLightmaps (void) Surf_CreateSurfaceLightmap (surf, shift); /*the excessive logic is to give portals separate batches for separate planes*/ - if (m->textures[t]->shader->sort == SHADER_SORT_PORTAL) + if (sortid == SHADER_SORT_PORTAL) { if (surf->flags & SURF_PLANEBACK) VectorNegate(surf->plane->normal, sn); @@ -2432,11 +2443,11 @@ void Surf_BuildLightmaps (void) } else VectorClear(sn); - if (!batch || batch->lightmap != surf->lightmaptexturenum || (m->textures[t]->shader->sort == SHADER_SORT_PORTAL && !VectorCompare(sn, batch->normal))) + if (!batch || batch->lightmap != surf->lightmaptexturenum || (sortid == SHADER_SORT_PORTAL && !VectorCompare(sn, batch->normal))) { - if (m->textures[t]->shader->sort == SHADER_SORT_PORTAL) + if (sortid == SHADER_SORT_PORTAL) { - for (batch = m->batches; batch != bstop; batch = batch->next) + for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) { if (batch->lightmap == surf->lightmaptexturenum && VectorCompare(sn, batch->normal)) break; @@ -2444,7 +2455,7 @@ void Surf_BuildLightmaps (void) } else { - for (batch = m->batches; batch != bstop; batch = batch->next) + for (batch = m->batches[sortid]; batch != bstop; batch = batch->next) { if (batch->lightmap == surf->lightmaptexturenum) break; @@ -2455,9 +2466,10 @@ void Surf_BuildLightmaps (void) batch = Z_Malloc(sizeof(*batch)); batch->lightmap = surf->lightmaptexturenum; batch->texture = m->textures[t]; - batch->next = m->batches; + batch->next = m->batches[sortid]; + batch->ent = &r_worldentity; VectorCopy(sn, batch->normal); - m->batches = batch; + m->batches[sortid] = batch; } } surf->sbatch = batch; @@ -2469,7 +2481,8 @@ void Surf_BuildLightmaps (void) } } } - for (batch = m->batches; batch != NULL; batch = batch->next) + for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++) + for (batch = m->batches[sortid]; batch != NULL; batch = batch->next) { batch->mesh = BZ_Malloc(sizeof(*batch->mesh)*batch->maxmeshes*2); } diff --git a/engine/client/render.h b/engine/client/render.h index 8ef8a147b..2426d5cb1 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -163,7 +163,8 @@ extern entity_t r_worldentity; //gl_alias.c -void R_DrawGAliasModel (entity_t *e, unsigned int rmode); +void R_GAlias_DrawBatch(struct batch_s *batch); +void R_GAlias_GenerateBatches(entity_t *e, struct batch_s **batches); //r_surf.c struct model_s; @@ -389,7 +390,7 @@ qbyte *R_MarkLeaves_Q3 (void); void R_SetFrustum (float projmat[16], float viewmat[16]); void R_SetRenderer(rendererinfo_t *ri); void R_AnimateLight (void); -struct texture_s *R_TextureAnimation (struct texture_s *base); +struct texture_s *R_TextureAnimation (int frame, struct texture_s *base); void RQ_Init(void); void CLQ2_EntityEvent(entity_state_t *es); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 45f17de0e..8e9283425 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -317,9 +317,8 @@ cvar_t r_noaliasshadows = SCVARF ("r_noaliasshadows", "0", cvar_t r_shadow_bumpscale_basetexture = SCVAR ("r_shadow_bumpscale_basetexture", "4"); cvar_t r_shadow_bumpscale_bumpmap = SCVAR ("r_shadow_bumpscale_bumpmap", "10"); -cvar_t r_shadow_glsl_offsetmapping = SCVAR ("r_shadow_glsl_offsetmapping", "0"); -cvar_t r_shadow_glsl_offsetmapping_bias = SCVAR ("r_shadow_glsl_offsetmapping_bias", "0.04"); -cvar_t r_shadow_glsl_offsetmapping_scale = SCVAR ("r_shadow_glsl_offsetmapping_scale", "-0.04"); +cvar_t r_glsl_offsetmapping = SCVAR ("r_glsl_offsetmapping", "0"); +cvar_t r_glsl_offsetmapping_scale = SCVAR ("r_glsl_offsetmapping_scale", "0.04"); cvar_t r_shadow_realtime_world = SCVARF ("r_shadow_realtime_world", "0", CVAR_ARCHIVE); cvar_t r_shadow_realtime_world_shadows = SCVARF ("r_shadow_realtime_world_shadows", "1", CVAR_ARCHIVE); @@ -407,9 +406,8 @@ void GLRenderer_Init(void) Cvar_Register (&gl_smoothcrosshair, GRAPHICALNICETIES); Cvar_Register (&gl_bump, GRAPHICALNICETIES); - Cvar_Register (&r_shadow_glsl_offsetmapping, GRAPHICALNICETIES); - Cvar_Register (&r_shadow_glsl_offsetmapping_scale, GRAPHICALNICETIES); - Cvar_Register (&r_shadow_glsl_offsetmapping_bias, GRAPHICALNICETIES); + Cvar_Register (&r_glsl_offsetmapping, GRAPHICALNICETIES); + Cvar_Register (&r_glsl_offsetmapping_scale, GRAPHICALNICETIES); Cvar_Register (&gl_contrast, GLRENDEREROPTIONS); #ifdef R_XFLIP @@ -1490,6 +1488,10 @@ qboolean R_ApplyRenderer_Load (rendererstate_t *newr) } } + if (h2playertranslations) + BZ_Free(h2playertranslations); + h2playertranslations = FS_LoadMallocFile ("gfx/player.lmp"); + if (vid.fullbright < 2) vid.fullbright = 0; //transparent colour doesn't count. @@ -2140,13 +2142,12 @@ R_TextureAnimation Returns the proper texture for a given time and base texture =============== */ -extern entity_t *currententity; -texture_t *R_TextureAnimation (texture_t *base) +texture_t *R_TextureAnimation (int frame, texture_t *base) { int reletive; int count; - if (currententity->framestate.g[FS_REG].frame[0]) + if (frame) { if (base->alternate_anims) base = base->alternate_anims; diff --git a/engine/client/sbar.c b/engine/client/sbar.c index 27722ba31..8e4b52fc1 100644 --- a/engine/client/sbar.c +++ b/engine/client/sbar.c @@ -78,10 +78,10 @@ cvar_t sbar_teamstatus = SCVAR("sbar_teamstatus", "1"); int sb_updates; // if >= vid.numpages, no update needed -int sb_hexen2_cur_item;//hexen2 hud -qboolean sb_hexen2_extra_info;//show the extra stuff -qboolean sb_hexen2_infoplaque; -float sb_hexen2_item_time; +int sb_hexen2_cur_item[MAX_SPLITS];//hexen2 hud +qboolean sb_hexen2_extra_info[MAX_SPLITS];//show the extra stuff +qboolean sb_hexen2_infoplaque[MAX_SPLITS]; +float sb_hexen2_item_time[MAX_SPLITS]; qboolean sbar_parsingteamstatuses; //so we don't eat it if its not displayed @@ -673,37 +673,58 @@ void Sbar_ShowScores (void) void Sbar_Hexen2InvLeft_f(void) { - sb_hexen2_item_time = realtime; - sb_hexen2_cur_item--; - if (sb_hexen2_cur_item < 0) - sb_hexen2_cur_item = 14; + int tries = 15; + int pnum = CL_TargettedSplit(false); + sb_hexen2_item_time[pnum] = realtime; + while (tries-- > 0) + { + sb_hexen2_cur_item[pnum]--; + if (sb_hexen2_cur_item[pnum] < 0) + sb_hexen2_cur_item[pnum] = 14; + + if (cl.stats[pnum][STAT_H2_CNT_TORCH+sb_hexen2_cur_item[pnum]] > 0) + break; + } } void Sbar_Hexen2InvRight_f(void) { - sb_hexen2_item_time = realtime; - sb_hexen2_cur_item++; - if (sb_hexen2_cur_item > 14) - sb_hexen2_cur_item = 0; + int tries = 15; + int pnum = CL_TargettedSplit(false); + sb_hexen2_item_time[pnum] = realtime; + while (tries-- > 0) + { + sb_hexen2_cur_item[pnum]++; + if (sb_hexen2_cur_item[pnum] > 14) + sb_hexen2_cur_item[pnum] = 0; + + if (cl.stats[pnum][STAT_H2_CNT_TORCH+sb_hexen2_cur_item[pnum]] > 0) + break; + } } void Sbar_Hexen2InvUse_f(void) { - Cbuf_AddText(va("impulse %d\n", 100+sb_hexen2_cur_item), Cmd_ExecLevel); + int pnum = CL_TargettedSplit(false); + Cmd_ExecuteString(va("impulse %d\n", 100+sb_hexen2_cur_item[pnum]), Cmd_ExecLevel); } void Sbar_Hexen2ShowInfo_f(void) { - sb_hexen2_extra_info = true; + int pnum = CL_TargettedSplit(false); + sb_hexen2_extra_info[pnum] = true; } void Sbar_Hexen2DontShowInfo_f(void) { - sb_hexen2_extra_info = false; + int pnum = CL_TargettedSplit(false); + sb_hexen2_extra_info[pnum] = false; } void Sbar_Hexen2PInfoPlaque_f(void) { - sb_hexen2_infoplaque = true; + int pnum = CL_TargettedSplit(false); + sb_hexen2_infoplaque[pnum] = true; } void Sbar_Hexen2MInfoPlaque_f(void) { - sb_hexen2_infoplaque = false; + int pnum = CL_TargettedSplit(false); + sb_hexen2_infoplaque[pnum] = false; } /* @@ -976,6 +997,11 @@ void Sbar_DrawString (int x, int y, char *str) Draw_FunString (sbar_rect.x + x /*+ ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y+ sbar_rect.height-SBAR_HEIGHT, str); } +void Sbar_DrawExpandedString (int x, int y, conchar_t *str) +{ + Draw_ExpandedString (sbar_rect.x + x /*+ ((sbar_rect.width - 320)>>1) */, sbar_rect.y + y+ sbar_rect.height-SBAR_HEIGHT, str); +} + void Draw_TinyString (int x, int y, const qbyte *str) { float xstart; @@ -1354,7 +1380,8 @@ Sbar_DrawInventory void Sbar_DrawInventory (int pnum) { int i; - char num[6]; + char num[6]; + conchar_t numc[6]; float time; int flashon; qboolean headsup; @@ -1368,9 +1395,9 @@ void Sbar_DrawInventory (int pnum) if (sbar_rogue) { if ( cl.stats[pnum][STAT_ACTIVEWEAPON] >= RIT_LAVA_NAILGUN ) - Sbar_DrawPic (0, -24, FINDOUT, FINDOUT, rsb_invbar[0]); + Sbar_DrawPic (0, -24, 320, 24, rsb_invbar[0]); else - Sbar_DrawPic (0, -24, FINDOUT, FINDOUT, rsb_invbar[1]); + Sbar_DrawPic (0, -24, 320, 24, rsb_invbar[1]); } else Sbar_DrawPic (0, -24, 320, 24, sb_ibar); @@ -1401,7 +1428,7 @@ void Sbar_DrawInventory (int pnum) } else { - Sbar_DrawPic (i*24, -16, 24, 16, sb_weapons[flashon][i]); + Sbar_DrawPic (i*24, -16, (i==6)?48:24, 16, sb_weapons[flashon][i]); } if (flashon > 1) @@ -1421,11 +1448,11 @@ void Sbar_DrawInventory (int pnum) if (headsup) { if (sbar_rect.height>200) - Sbar_DrawSubPic ((hudswap) ? 0 : (sbar_rect.width-24),-68-(5-i)*16, FINDOUT, FINDOUT, rsb_weapons[i],0,0,FINDOUT,FINDOUT); + Sbar_DrawSubPic ((hudswap) ? 0 : (sbar_rect.width-24),-68-(5-i)*16, 24, 16, rsb_weapons[i],0,0,((i==4)?48:24),16); } else - Sbar_DrawPic ((i+2)*24, -16, 24, 16, rsb_weapons[i]); + Sbar_DrawPic ((i+2)*24, -16, (i==4)?48:24, 16, rsb_weapons[i]); } } } @@ -1435,34 +1462,18 @@ void Sbar_DrawInventory (int pnum) for (i=0 ; i<4 ; i++) { snprintf (num, sizeof(num), "%3i",cl.stats[pnum][STAT_SHELLS+i] ); - if (num[0] != ' ') - num[0] += 18-'0'; - if (num[1] != ' ') - num[1] += 18-'0'; - if (num[2] != ' ') - num[2] += 18-'0'; + numc[0] = CON_WHITEMASK|0xe000|((num[0]!=' ')?(num[0] + 18-'0'):' '); + numc[1] = CON_WHITEMASK|0xe000|((num[1]!=' ')?(num[1] + 18-'0'):' '); + numc[2] = CON_WHITEMASK|0xe000|((num[2]!=' ')?(num[2] + 18-'0'):' '); + numc[3] = 0; if (headsup) { -// Sbar_DrawSubPic(3, -24, sb_ibar, 3, 0, 42,11); Sbar_DrawSubPic((hudswap) ? 0 : (sbar_rect.width-42), -24 - (4-i)*11, 42, 11, sb_ibar, 3+(i*48), 0, 320, 24); -/* - if (num[0] != ' ') - Sbar_DrawCharacter ( (hudswap) ? 3 : (sbar_rect.width-39), -24 - (4-i)*11, 18 + num[0] - '0'); - if (num[1] != ' ') - Sbar_DrawCharacter ( (hudswap) ? 11 : (sbar_rect.width-31), -24 - (4-i)*11, 18 + num[1] - '0'); - if (num[2] != ' ') - Sbar_DrawCharacter ( (hudswap) ? 19 : (sbar_rect.width-23), -24 - (4-i)*11, 18 + num[2] - '0'); -*/ - Sbar_DrawString((hudswap) ? 3 : (sbar_rect.width-39), -24 - (4-i)*11, num); + Sbar_DrawExpandedString((hudswap) ? 3 : (sbar_rect.width-39), -24 - (4-i)*11, numc); } else { - if (num[0] != ' ') - Sbar_DrawCharacter ( (6*i+1)*8 - 2, -24, 18 + num[0] - '0'); - if (num[1] != ' ') - Sbar_DrawCharacter ( (6*i+2)*8 - 2, -24, 18 + num[1] - '0'); - if (num[2] != ' ') - Sbar_DrawCharacter ( (6*i+3)*8 - 2, -24, 18 + num[2] - '0'); + Sbar_DrawExpandedString((6*i+1)*8 - 2, -24, numc); } } @@ -1818,25 +1829,69 @@ void Sbar_Hexen2DrawInventory(int pnum) { int i; int x, y=-37; + int activeleft = 0; + int activeright = 0; - if (sb_hexen2_item_time+3 < realtime) + /*always select an artifact that we actually have whether we are drawing the full bar or not.*/ + for (i = 0; i < 15; i++) + { + if (cl.stats[pnum][STAT_H2_CNT_TORCH+(i+sb_hexen2_cur_item[pnum])%15]) + { + sb_hexen2_cur_item[pnum] = (sb_hexen2_cur_item[pnum] + i)%15; + break; + } + } + + if (sb_hexen2_item_time[pnum]+3 < realtime) return; #if 1 + for (i = sb_hexen2_cur_item[pnum]; i < 15; i++) + if (sb_hexen2_cur_item[pnum] == i || cl.stats[pnum][STAT_H2_CNT_TORCH+i] > 0) + activeright++; + for (i = sb_hexen2_cur_item[pnum]-1; i >= 0; i--) + if (sb_hexen2_cur_item[pnum] == i || cl.stats[pnum][STAT_H2_CNT_TORCH+i] > 0) + activeleft++; + + if (activeleft > 3 + (activeright<=3?(4-activeright):0)) + activeleft = 3 + (activeright<=3?(4-activeright):0); + x=320/2-114 + (activeleft-1)*33; + for (i = sb_hexen2_cur_item[pnum]-1; x>=320/2-114; i--) + { + if (!cl.stats[pnum][STAT_H2_CNT_TORCH+i]) + continue; + + if (i == sb_hexen2_cur_item[pnum]) + Sbar_DrawPic(x+9, y-12, 11, 11, Draw_SafeCachePic("gfx/artisel.lmp")); + Sbar_Hexen2DrawItem(pnum, x, y, i); + x -= 33; + } + + x=320/2-114 + activeleft*33; + for (i = sb_hexen2_cur_item[pnum]; i < 15 && x < 320/2-114+7*33; i++) + { + if (i != sb_hexen2_cur_item[pnum] && !cl.stats[pnum][STAT_H2_CNT_TORCH+i]) + continue; + if (i == sb_hexen2_cur_item[pnum]) + Sbar_DrawPic(x+9, y-12, 11, 11, Draw_SafeCachePic("gfx/artisel.lmp")); + Sbar_Hexen2DrawItem(pnum, x, y, i); + x+=33; + } +#elif 1 for (i = 0, x=320/2-114; i < 7; i++, x+=33) { - if ((sb_hexen2_cur_item-3+i+30)%15 == sb_hexen2_cur_item) + if ((sb_hexen2_cur_item[pnum]-3+i+30)%15 == sb_hexen2_cur_item[pnum]) Sbar_DrawPic(x+9, y-12, 11, 11, Draw_SafeCachePic("gfx/artisel.lmp")); - Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item-3+i+30)%15); + Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item[pnum]-3+i+30)%15); } #else for (i = 0, x=320/2; i < 3; i++, x+=33) { - Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item+1+i)%15); + Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item[pnum]+1+i)%15); } for (i = 0, x=320/2-33; i < 3; i++, x-=33) { - Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item-1-i+45)%15); + Sbar_Hexen2DrawItem(pnum, x, y, (sb_hexen2_cur_item[pnum]-1-i+45)%15); } #endif } @@ -1857,7 +1912,7 @@ void Sbar_Hexen2DrawExtra (int pnum) "Demoness" }; - if (sb_hexen2_infoplaque) + if (sb_hexen2_infoplaque[pnum]) { int i; Con_Printf("Objectives:\n"); @@ -1866,16 +1921,16 @@ void Sbar_Hexen2DrawExtra (int pnum) if (cl.stats[pnum][STAT_H2_OBJECTIVE1 + i/32] & (1<<(i&31))) Con_Printf("%s\n", T_GetInfoString(i)); } - sb_hexen2_infoplaque = false; + sb_hexen2_infoplaque[pnum] = false; } - if (!sb_hexen2_extra_info) + if (!sb_hexen2_extra_info[pnum]) { sbar_rect.y -= 46-SBAR_HEIGHT; return; } - pclass = cl.stats[pnum][STAT_H2_PLAYERCLASS]; + pclass = cl.players[cl.playernum[pnum]].h2playerclass; if (pclass >= sizeof(pclassname)/sizeof(pclassname[0])) pclass = sizeof(pclassname)/sizeof(pclassname[0]) - 1; @@ -1967,7 +2022,7 @@ int Sbar_Hexen2ArmourValue(int pnum) }; int classno; - classno = cl.stats[pnum][STAT_H2_PLAYERCLASS]; + classno = cl.players[cl.playernum[pnum]].h2playerclass; if (classno >= 1 && classno <= 5) { classno--; @@ -2036,9 +2091,21 @@ void Sbar_Hexen2DrawBasic(int pnum) Sbar_DrawPic(267, 36, 10, 10, Draw_SafeCachePic("gfx/chnrcov.lmp")); - Sbar_Hexen2DrawItem(pnum, 144, 3, sb_hexen2_cur_item); + Sbar_Hexen2DrawItem(pnum, 144, 3, sb_hexen2_cur_item[pnum]); } +void Sbar_Hexen2DrawMinimal(int pnum) +{ + int y; + y = -16; + Sbar_DrawPic(3, y, 31, 17, Draw_SafeCachePic("gfx/bmmana.lmp")); + Sbar_DrawPic(3, y+18, 31, 17, Draw_SafeCachePic("gfx/gmmana.lmp")); + + Sbar_DrawTinyString(10, y+6, va("%03d", cl.stats[pnum][STAT_H2_BLUEMANA])); + Sbar_DrawTinyString(10, y+18+6, va("%03d", cl.stats[pnum][STAT_H2_GREENMANA])); + + Sbar_Hexen2DrawNum(38, y+18, cl.stats[pnum][STAT_HEALTH], 3); +} void Sbar_DrawTeamStatus(void) @@ -2223,9 +2290,14 @@ void Sbar_Draw (void) if (sbar_hexen2) { - Sbar_Hexen2DrawExtra(pnum); - Sbar_Hexen2DrawBasic(pnum); - Sbar_Hexen2DrawInventory(pnum); + if (sb_lines > 0) + { + Sbar_Hexen2DrawExtra(pnum); + Sbar_Hexen2DrawBasic(pnum); + Sbar_Hexen2DrawInventory(pnum); + } + else + Sbar_Hexen2DrawMinimal(pnum); if (cl.deathmatch) Sbar_MiniDeathmatchOverlay (); diff --git a/engine/client/snd_sdl.c b/engine/client/snd_sdl.c index 28bdd8dd2..76b3e7605 100644 --- a/engine/client/snd_sdl.c +++ b/engine/client/snd_sdl.c @@ -97,7 +97,7 @@ static int SDL_InitCard(soundcardinfo_t *sc, int cardnum) desired.channels = sc->sn.numchannels; //fixme! desired.samples = 0x0100; desired.format = AUDIO_S16SYS; - desired.callback = SSDL_Paint; + desired.callback = (void*)SSDL_Paint; desired.userdata = sc; memcpy(&obtained, &desired, sizeof(obtained)); diff --git a/engine/common/bspfile.h b/engine/common/bspfile.h index 76c778bb8..d3925776c 100644 --- a/engine/common/bspfile.h +++ b/engine/common/bspfile.h @@ -469,27 +469,30 @@ typedef struct // remaining contents are non-visible, and don't eat brushes -#define Q2CONTENTS_AREAPORTAL 0x8000 +#define Q2CONTENTS_AREAPORTAL 0x8000 -#define Q2CONTENTS_PLAYERCLIP 0x10000 +#define Q2CONTENTS_PLAYERCLIP 0x10000 #define Q2CONTENTS_MONSTERCLIP 0x20000 // currents can be added to any other contents, and may be mixed -#define Q2CONTENTS_CURRENT_0 0x40000 -#define Q2CONTENTS_CURRENT_90 0x80000 +#define Q2CONTENTS_CURRENT_0 0x40000 +#define Q2CONTENTS_CURRENT_90 0x80000 #define Q2CONTENTS_CURRENT_180 0x100000 #define Q2CONTENTS_CURRENT_270 0x200000 -#define Q2CONTENTS_CURRENT_UP 0x400000 +#define Q2CONTENTS_CURRENT_UP 0x400000 #define Q2CONTENTS_CURRENT_DOWN 0x800000 -#define Q2CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity +#define Q2CONTENTS_ORIGIN 0x1000000 // removed before bsping an entity #define Q2CONTENTS_MONSTER 0x2000000 // should never be on a brush, only in game #define Q2CONTENTS_DEADMONSTER 0x4000000 -#define Q2CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs +#define Q2CONTENTS_DETAIL 0x8000000 // brushes to be added after vis leafs #define Q2CONTENTS_TRANSLUCENT 0x10000000 // auto set if any surface has trans +#define Q2CONTENTS_LADDER 0x20000000 + +#define Q3CONTENTS_SOLID Q2CONTENTS_SOLID // should never be on a brush, only in game +#define Q3CONTENTS_BODY 0x2000000 // should never be on a brush, only in game #define Q3CONTENTS_TRANSLUCENT 0x20000000 -#define Q2CONTENTS_LADDER 0x20000000 //Texinfo flags - warning: these mix with q3 surface flags diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 75af83e7f..bb140e0fe 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -1131,7 +1131,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, R_LerpFrames(mesh, (galiaspose_t *)((char *)g1 + g1->poseofs + sizeof(galiaspose_t)*frame1), (galiaspose_t *)((char *)g2 + g2->poseofs + sizeof(galiaspose_t)*frame2), - 1-lerp, (qbyte)(alpha*255), currententity->fatness, nolightdir); + 1-lerp, (qbyte)(alpha*255), e->fatness, nolightdir); return true; //to allow the mesh to be dlighted. } @@ -1149,7 +1149,7 @@ qboolean Alias_GAliasBuildMesh(mesh_t *mesh, galiasinfo_t *inf, //The whole reason why model loading is supported in the server. -qboolean Mod_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +qboolean Mod_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) { galiasinfo_t *mod = Mod_Extradata(model); galiasgroup_t *group; diff --git a/engine/common/com_mesh.h b/engine/common/com_mesh.h index ef0b1b0f3..01306259a 100644 --- a/engine/common/com_mesh.h +++ b/engine/common/com_mesh.h @@ -110,6 +110,7 @@ typedef struct { texnums_t texnum; unsigned int tcolour; unsigned int bcolour; + unsigned int pclass; int skinnum; unsigned int subframe; bucket_t bucket; diff --git a/engine/common/fs.c b/engine/common/fs.c index 5ef25f423..90008eeb7 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -1801,9 +1801,9 @@ void COM_Gamedir (const char *dir) } #define DPCOMPAT "set dpcompat_set 1\nset dpcompat_trailparticles 1\n" -#define NEXCFG DPCOMPAT "set sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\nset r_particlesdesc effectinfo\n" +#define NEXCFG DPCOMPAT "set r_particlesdesc effectinfo\nset sv_maxairspeed \"400\"\nset sv_jumpvelocity 270\nset sv_mintic \"0.01\"\ncl_nolerp 0\nset r_particlesdesc effectinfo\n" #define DMFCFG "set com_parseutf8 1\npm_airstep 1\n" -#define HEX2CFG "set sv_maxspeed 640\nset watervis 1\nset r_wateralpha 0.5\nset sv_pupglow 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\n" typedef struct { const char *protocolname; //sent to the master server when this is the current gamemode. diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 6302f9263..e8e7af8e5 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -33,10 +33,10 @@ qboolean RMod_LoadSurfedges (lump_t *l); void RMod_LoadLighting (lump_t *l); -qboolean CM_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace); -qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contents, trace_t *trace); -unsigned int CM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t p, vec3_t mins, vec3_t maxs); -unsigned int Q2BSP_PointContents(model_t *mod, vec3_t p); +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); +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); +unsigned int CM_NativeContents(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs); +unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p); @@ -3691,6 +3691,13 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned else noerrors = noerrors && CModQ3_LoadRFaces (&header.lumps[Q3LUMP_SURFACES]); noerrors = noerrors && CModQ3_LoadMarksurfaces (&header.lumps[Q3LUMP_LEAFSURFACES]); //fixme: duplicated loading. + + /*make sure all textures have a shader*/ + for (i=0; inumtextures; i++) + { + if (!loadmodel->textures[i]->shader) + loadmodel->textures[i]->shader = R_RegisterShader_Lightmap(loadmodel->textures[i]->name); + } } #endif noerrors = noerrors && CModQ3_LoadLeafFaces (&header.lumps[Q3LUMP_LEAFSURFACES]); @@ -3929,7 +3936,7 @@ q2cmodel_t *CM_LoadMap (char *name, char *filein, qboolean clientload, unsigned mod->hulls[0].firstclipnode = bm->headnode; - mod->hulls[j].available = true; + mod->hulls[0].available = true; mod->nummodelsurfaces = bm->numsurfaces; mod->firstmodelsurface = bm->firstsurface; for (j=1 ; jfraction != 1; } -qboolean CM_NativeTrace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int contents, trace_t *trace) +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) { *trace = CM_BoxTrace(model, start, end, mins, maxs, contents); return trace->fraction != 1; @@ -5668,7 +5675,7 @@ qboolean Q2BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, return true; return false; }*/ -unsigned int Q2BSP_PointContents(model_t *mod, vec3_t p) +unsigned int Q2BSP_PointContents(model_t *mod, vec3_t axis[3], vec3_t p) { int pc, ret = FTECONTENTS_EMPTY; pc = CM_PointContents (mod, p); diff --git a/engine/common/mathlib.c b/engine/common/mathlib.c index 27eb9cd60..0ba9b76f2 100644 --- a/engine/common/mathlib.c +++ b/engine/common/mathlib.c @@ -1449,6 +1449,37 @@ qboolean Matrix4_Invert(const float *m, float *out) #undef SWAP_ROWS } +void Matrix3_Invert_Simple (const vec3_t in1[3], vec3_t out[3]) +{ + // we only support uniform scaling, so assume the first row is enough + // (note the lack of sqrt here, because we're trying to undo the scaling, + // this means multiplying by the inverse scale twice - squaring it, which + // makes the sqrt a waste of time) +#if 1 + double scale = 1.0 / (in1[0][0] * in1[0][0] + in1[0][1] * in1[0][1] + in1[0][2] * in1[0][2]); +#else + double scale = 3.0 / sqrt + (in1->m[0][0] * in1->m[0][0] + in1->m[0][1] * in1->m[0][1] + in1->m[0][2] * in1->m[0][2] + + in1->m[1][0] * in1->m[1][0] + in1->m[1][1] * in1->m[1][1] + in1->m[1][2] * in1->m[1][2] + + in1->m[2][0] * in1->m[2][0] + in1->m[2][1] * in1->m[2][1] + in1->m[2][2] * in1->m[2][2]); + scale *= scale; +#endif + + // invert the rotation by transposing and multiplying by the squared + // recipricol of the input matrix scale as described above + out[0][0] = in1[0][0] * scale; + out[0][1] = in1[1][0] * scale; + out[0][2] = in1[2][0] * scale; + + out[1][0] = in1[0][1] * scale; + out[1][1] = in1[1][1] * scale; + out[1][2] = in1[2][1] * scale; + + out[2][0] = in1[0][2] * scale; + out[2][1] = in1[1][2] * scale; + out[2][2] = in1[2][2] * scale; +} + void Matrix4Q_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 ca3240029..4d3c60d83 100644 --- a/engine/common/mathlib.h +++ b/engine/common/mathlib.h @@ -134,6 +134,7 @@ void Matrix3_Multiply (vec3_t *in1, vec3_t *in2, vec3_t *out); void Matrix4_Identity(float *outm); qboolean Matrix4_Invert(const float *m, float *out); void Matrix4Q_Invert_Simple (const float *in1, float *out); +void Matrix3_Invert_Simple(const vec3_t in[3], vec3_t out[3]); void Matrix4_CreateTranslate (float *out, float x, float y, float z); void Matrix4Q_CreateTranslate (float *out, float x, float y, float z); void Matrix4_ModelMatrixFromAxis (float *modelview, const vec3_t pn, const vec3_t right, const vec3_t up, const vec3_t vieworg); diff --git a/engine/common/pmovetst.c b/engine/common/pmovetst.c index 52b678fea..a107f9a28 100644 --- a/engine/common/pmovetst.c +++ b/engine/common/pmovetst.c @@ -88,21 +88,18 @@ hull_t *PM_HullForBox (vec3_t mins, vec3_t maxs) int PM_TransformedModelPointContents (model_t *mod, vec3_t p, vec3_t origin, vec3_t angles) { - vec3_t p_l, forward, up, right, temp; + vec3_t p_l, axis[3]; VectorSubtract (p, origin, p_l); // rotate start and end into the models frame of reference if (angles[0] || angles[1] || angles[2]) { - AngleVectors (angles, forward, right, up); - - VectorCopy (p_l, temp); - p_l[0] = DotProduct (temp, forward); - p_l[1] = -DotProduct (temp, right); - p_l[2] = DotProduct (temp, up); + AngleVectors (angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); + return mod->funcs.PointContents(mod, axis, p_l); } - return mod->funcs.PointContents(mod, p_l); + return mod->funcs.PointContents(mod, NULL, p_l); } @@ -123,7 +120,7 @@ int PM_PointContents (vec3_t p) pm = pmove.physents[0].model; if (!pm) return FTECONTENTS_EMPTY; - pc = pm->funcs.PointContents(pm, p); + pc = pm->funcs.PointContents(pm, NULL, p); //we need this for e2m2 - waterjumping on to plats wouldn't work otherwise. for (num = 1; num < pmove.numphysent; num++) { @@ -206,50 +203,24 @@ static vec3_t trace_extents; static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t end, trace_t *trace, vec3_t origin, vec3_t angles) { vec3_t start_l, end_l; - vec3_t a; - vec3_t forward, right, up; - vec3_t temp; - qboolean rotated; int i; + vec3_t axis[3]; // subtract origin offset VectorSubtract (start, origin, start_l); VectorSubtract (end, origin, end_l); - // rotate start and end into the models frame of reference - if (model && - (angles[0] || angles[1] || angles[2]) ) - rotated = true; - else - rotated = false; - - if (rotated) - { - AngleVectors (angles, forward, right, up); - - VectorCopy (start_l, temp); - start_l[0] = DotProduct (temp, forward); - start_l[1] = -DotProduct (temp, right); - start_l[2] = DotProduct (temp, up); - - VectorCopy (end_l, temp); - end_l[0] = DotProduct (temp, forward); - end_l[1] = -DotProduct (temp, right); - end_l[2] = DotProduct (temp, up); - } // sweep the box through the model - if (model) { - for (i = 0; i < 3; i++) + if (angles[0] || angles[1] || angles[2]) { - if (start_l[i]+player_mins[i] > model->maxs[i] && end_l[i] + player_mins[i] > model->maxs[i]) - return false; - if (start_l[i]+player_maxs[i] < model->mins[i] && end_l[i] + player_maxs[i] < model->mins[i]) - return false; + AngleVectors (angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); + model->funcs.Trace(model, 0, 0, axis, start_l, end_l, player_mins, player_maxs, trace); } - - model->funcs.Trace(model, 0, 0, start_l, end_l, player_mins, player_maxs, trace); + else + model->funcs.Trace(model, 0, 0, NULL, start_l, end_l, player_mins, player_maxs, trace); } else { @@ -264,33 +235,9 @@ static qboolean PM_TransformedHullCheck (model_t *model, vec3_t start, vec3_t en Q1BSP_RecursiveHullCheck (&box_hull, box_hull.firstclipnode, 0, 1, start_l, end_l, trace); } - if (rotated) - { - // FIXME: figure out how to do this with existing angles -// VectorNegate (angles, a); - - if (trace->fraction != 1.0) - { - a[0] = -angles[0]; - a[1] = -angles[1]; - a[2] = -angles[2]; - AngleVectors (a, forward, right, up); - - VectorCopy (trace->plane.normal, temp); - trace->plane.normal[0] = DotProduct (temp, forward); - trace->plane.normal[1] = -DotProduct (temp, right); - trace->plane.normal[2] = DotProduct (temp, up); - } - trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]); - trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]); - trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]); - } - else - { - trace->endpos[0] += origin[0]; - trace->endpos[1] += origin[1]; - trace->endpos[2] += origin[2]; - } + trace->endpos[0] += origin[0]; + trace->endpos[1] += origin[1]; + trace->endpos[2] += origin[2]; return true; } diff --git a/engine/common/q1bsp.c b/engine/common/q1bsp.c index 5c154c839..1cfe50fd7 100644 --- a/engine/common/q1bsp.c +++ b/engine/common/q1bsp.c @@ -367,12 +367,20 @@ int Q1BSP_HullPointContents(hull_t *hull, vec3_t p) } } -unsigned int Q1BSP_PointContents(model_t *model, vec3_t point) +unsigned int Q1BSP_PointContents(model_t *model, vec3_t axis[3], vec3_t point) { + if (axis) + { + vec3_t transformed; + transformed[0] = DotProduct(point, axis[0]); + transformed[1] = DotProduct(point, axis[1]); + transformed[2] = DotProduct(point, axis[2]); + return Q1BSP_HullPointContents(&model->hulls[0], transformed); + } return Q1BSP_HullPointContents(&model->hulls[0], point); } -qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +qboolean Q1BSP_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) { hull_t *hull; vec3_t size; @@ -420,16 +428,51 @@ qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, // calculate an offset value to center the origin VectorSubtract (hull->clip_mins, mins, offset); - VectorSubtract(start, offset, start_l); - VectorSubtract(end, offset, end_l); - Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); - if (trace->fraction == 1) + if (axis) { - VectorCopy (end, trace->endpos); + vec3_t tmp; + VectorSubtract(start, offset, tmp); + start_l[0] = DotProduct(tmp, axis[0]); + start_l[1] = DotProduct(tmp, axis[1]); + start_l[2] = DotProduct(tmp, axis[2]); + VectorSubtract(end, offset, tmp); + end_l[0] = DotProduct(tmp, axis[0]); + end_l[1] = DotProduct(tmp, axis[1]); + end_l[2] = DotProduct(tmp, axis[2]); + Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + + if (trace->fraction == 1) + { + VectorCopy (end, trace->endpos); + } + else + { + vec3_t iaxis[3]; + vec3_t norm; + Matrix3_Invert_Simple(axis, iaxis); + VectorCopy(trace->plane.normal, norm); + trace->plane.normal[0] = DotProduct(norm, iaxis[0]); + trace->plane.normal[1] = DotProduct(norm, iaxis[1]); + trace->plane.normal[2] = DotProduct(norm, iaxis[2]); + + /*just interpolate it, its easier than inverse matrix rotations*/ + VectorInterpolate(start, trace->fraction, end, trace->endpos); + } } else { - VectorAdd (trace->endpos, offset, trace->endpos); + VectorSubtract(start, offset, start_l); + VectorSubtract(end, offset, end_l); + Q1BSP_RecursiveHullCheck(hull, hull->firstclipnode, 0, 1, start_l, end_l, trace); + + if (trace->fraction == 1) + { + VectorCopy (end, trace->endpos); + } + else + { + VectorAdd (trace->endpos, offset, trace->endpos); + } } return trace->fraction != 1; diff --git a/engine/common/q3common.c b/engine/common/q3common.c index 9376d0dbc..bb9dfbf36 100644 --- a/engine/common/q3common.c +++ b/engine/common/q3common.c @@ -358,7 +358,7 @@ int VMQ3_Cvar_Update(vmcvar_t *v) if (!c) return 0; //that slot isn't active yet - v->integer = c->value; + v->integer = c->ival; v->value = c->value; v->modificationCount = c->modified; Q_strncpyz(v->string, c->string, sizeof(v->string)); diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 78f02408d..5883e5e41 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -40,31 +40,6 @@ typedef struct -// entity_state_t->renderfx flags -#define Q2RF_MINLIGHT 1 // always have some light (viewmodel) -#define Q2RF_VIEWERMODEL 2 // don't draw through eyes, only mirrors -#define Q2RF_WEAPONMODEL 4 // only draw through eyes -#define Q2RF_FULLBRIGHT 8 // always draw full intensity -#define Q2RF_DEPTHHACK 16 // for view weapon Z crunching -#define Q2RF_TRANSLUCENT 32 -#define Q2RF_FRAMELERP 64 -#define Q2RF_BEAM 128 -#define Q2RF_CUSTOMSKIN 256 // skin is an index in image_precache -#define Q2RF_GLOW 512 // pulse lighting for bonus items -#define Q2RF_SHELL_RED 1024 -#define Q2RF_SHELL_GREEN 2048 -#define Q2RF_SHELL_BLUE 4096 - -//ROGUE -#define Q2RF_IR_VISIBLE 0x00008000 // 32768 -#define Q2RF_SHELL_DOUBLE 0x00010000 // 65536 -#define Q2RF_SHELL_HALF_DAM 0x00020000 -#define Q2RF_USE_DISGUISE 0x00040000 -//ROGUE - - - - extern cvar_t gl_part_flame, r_fullbrightSkins, r_fb_models; extern cvar_t r_noaliasshadows; void R_TorchEffect (vec3_t pos, int type); @@ -218,7 +193,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, int frame; unsigned int subframe; - unsigned int tc, bc; + unsigned int tc, bc, pc; qboolean forced; if (e->skinnum >= 100 && e->skinnum < 110) @@ -245,11 +220,13 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, Skin_Find(e->scoreboard); tc = e->scoreboard->ttopcolor; bc = e->scoreboard->tbottomcolor; + pc = e->scoreboard->h2playerclass; } else { tc = 1; bc = 1; + pc = 0; } if (forced || tc != 1 || bc != 1 || (e->scoreboard && e->scoreboard->skin)) @@ -323,7 +300,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, for (cm = Hash_Get(&skincolourmapped, skinname); cm; cm = Hash_GetNext(&skincolourmapped, skinname, cm)) { - if (cm->tcolour == tc && cm->bcolour == bc && cm->skinnum == e->skinnum && cm->subframe == subframe) + if (cm->tcolour == tc && cm->bcolour == bc && cm->skinnum == e->skinnum && cm->subframe == subframe && cm->pclass == pc) { return &cm->texnum; } @@ -335,6 +312,7 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, Hash_Add(&skincolourmapped, cm->name, cm, &cm->bucket); cm->tcolour = tc; cm->bcolour = bc; + cm->pclass = pc; cm->skinnum = e->skinnum; cm->subframe = subframe; cm->texnum.fullbright = r_nulltex; @@ -469,6 +447,25 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, if (scaled_height > gl_max_size.value) scaled_height = gl_max_size.value; //whoops, we made it too big + if (h2playertranslations && pc) + { + unsigned int color_offsets[5] = {2*14*256,0,1*14*256,2*14*256,2*14*256}; + unsigned char *colorA, *colorB, *sourceA, *sourceB; + colorA = h2playertranslations + 256 + color_offsets[pc-1]; + colorB = colorA + 256; + sourceA = colorB + (tc * 256); + sourceB = colorB + (bc * 256); + for(i=0;i<256;i++) + { + translate32[i] = d_8to24rgbtable[i]; + if (tc > 0 && (colorA[i] != 255)) + translate32[i] = d_8to24rgbtable[sourceA[i]]; + if (bc > 0 && (colorB[i] != 255)) + translate32[i] = d_8to24rgbtable[sourceB[i]]; + } + translate32[0] = 0; + } + else { for (i=0 ; i<256 ; i++) translate32[i] = d_8to24rgbtable[i]; @@ -526,24 +523,27 @@ static texnums_t *GL_ChooseSkin(galiasinfo_t *inf, char *modelname, int surfnum, } } texnums->base = R_AllocNewTexture(scaled_width, scaled_height); - R_Upload(texnums->base, "", TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); + R_Upload(texnums->base, "", h2playertranslations?TF_RGBA32:TF_RGBX32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); - //now do the fullbrights. - out = pixels; - fracstep = tinwidth*0x10000/scaled_width; - for (i=0 ; i> 1; - for (j=0 ; j>16] < 255-vid.fullbright) - ((char *) (&out[j]))[3] = 0; //alpha 0 - frac += fracstep; + inrow = original + inwidth*(i*inheight/scaled_height); + frac = fracstep >> 1; + for (j=0 ; j>16] < 255-vid.fullbright) + ((char *) (&out[j]))[3] = 0; //alpha 0 + frac += fracstep; + } } + texnums->fullbright = R_AllocNewTexture(scaled_width, scaled_height); + R_Upload(texnums->fullbright, "", TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } - texnums->fullbright = R_AllocNewTexture(scaled_width, scaled_height); - R_Upload(texnums->fullbright, "", TF_RGBA32, pixels, NULL, scaled_width, scaled_height, IF_NOMIPMAP); } else { @@ -708,7 +708,7 @@ static void R_DrawShadowVolume(mesh_t *mesh) #endif //true if no shading is to be used. -static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int rmode) +static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel) { vec3_t lightdir; int i; @@ -728,14 +728,6 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int return true; } - //shortcut here, no need to test bsp lights or world lights when there's realtime lighting going on. - if (rmode == BEM_DEPTHDARK || rmode == BEM_DEPTHONLY) - { - shadelight[0] = shadelight[1] = shadelight[2] = 0; - ambientlight[0] = ambientlight[1] = ambientlight[2] = 0; - return true; - } - if (!(r_refdef.flags & Q2RDF_NOWORLDMODEL)) { if (e->flags & Q2RF_WEAPONMODEL) @@ -895,46 +887,63 @@ static qboolean R_CalcModelLighting(entity_t *e, model_t *clmodel, unsigned int return false; } -static shader_t reskinnedmodelshader; -void R_DrawGAliasModel (entity_t *e, unsigned int rmode) +void R_GAlias_DrawBatch(batch_t *batch) { - model_t *clmodel; - galiasinfo_t *inf; - mesh_t mesh; - texnums_t *skin; + entity_t *e; - vec3_t saveorg; + galiasinfo_t *inf; + model_t *clmodel; int surfnum; - int bef; + + static mesh_t mesh; + static mesh_t *meshl = &mesh; qboolean needrecolour; qboolean nolightdir; - shader_t *shader; + e = batch->ent; + clmodel = e->model; -// if (e->flags & Q2RF_VIEWERMODEL && e->keynum == cl.playernum[r_refdef.currentplayernum]+1) -// return; + currententity = e; + nolightdir = R_CalcModelLighting(e, clmodel); + + inf = RMod_Extradata (clmodel); + memset(&mesh, 0, sizeof(mesh)); + for(surfnum=0; inf; ((inf->nextsurf)?(inf = (galiasinfo_t*)((char *)inf + inf->nextsurf)):(inf=NULL)), surfnum++) + { + if (batch->lightmap == surfnum) + { + needrecolour = Alias_GAliasBuildMesh(&mesh, inf, e, e->shaderRGBAf[3], nolightdir); + batch->mesh = &meshl; + } + } +} + +void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) +{ + galiasinfo_t *inf; + model_t *clmodel; + shader_t *shader; + batch_t *b; + int surfnum; + + texnums_t *skin; if (r_refdef.externalview && e->flags & Q2RF_WEAPONMODEL) return; + /*switch model if we're the player model, and the player skin says a new model*/ { extern int cl_playerindex; if (e->scoreboard && e->model == cl.model_precache[cl_playerindex]) { clmodel = e->scoreboard->model; - if (!clmodel || clmodel->type != mod_alias) - clmodel = e->model; + if (clmodel && clmodel->type == mod_alias) + e->model = clmodel; } - else - clmodel = e->model; } - if (clmodel->tainted) - { - if (!ruleset_allow_modified_eyes.ival && !strcmp(clmodel->name, "progs/eyes.mdl")) - return; - } + clmodel = e->model; if (!(e->flags & Q2RF_WEAPONMODEL)) { @@ -951,116 +960,37 @@ void R_DrawGAliasModel (entity_t *e, unsigned int rmode) #endif } - nolightdir = R_CalcModelLighting(e, clmodel, rmode); - - if (gl_affinemodels.ival) - qglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); - - if (e->flags & Q2RF_DEPTHHACK) - qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); - - bef = BEF_FORCEDEPTHTEST; - if (e->flags & Q2RF_ADDITIVE) + if (clmodel->tainted) { - bef |= BEF_FORCEADDITIVE; + if (!ruleset_allow_modified_eyes.ival && !strcmp(clmodel->name, "progs/eyes.mdl")) + return; } - else if (e->drawflags & DRF_TRANSLUCENT) //hexen2 - { - bef |= BEF_FORCETRANSPARENT; - e->shaderRGBAf[3] = r_wateralpha.value; - } - else if ((e->model->flags & EFH2_SPECIAL_TRANS)) //hexen2 flags. - { - //BEFIXME: this needs to generate the right sort of default instead - //(alpha blend+disable cull) - } - else if ((e->model->flags & EFH2_TRANSPARENT)) - { - //BEFIXME: make sure the shader generator works - } - else if ((e->model->flags & EFH2_HOLEY)) - { - //BEFIXME: this needs to generate the right sort of default instead - //(alpha test) - } - else if (e->shaderRGBAf[3] < 1 && cls.protocol != CP_QUAKE3) - bef |= BEF_FORCETRANSPARENT; - BE_SelectMode(rmode, bef); - - - qglPushMatrix(); - R_RotateForEntity(e, clmodel); inf = RMod_Extradata (clmodel); - if (qglPNTrianglesfATI && gl_ati_truform.ival) - qglEnable(GL_PN_TRIANGLES_ATI); - if (clmodel == cl.model_precache_vwep[0]) - { - extern int cl_playerindex; - clmodel = cl.model_precache[cl_playerindex]; - } - - if (e->flags & Q2RF_WEAPONMODEL) - { - VectorCopy(currententity->origin, saveorg); - VectorCopy(r_refdef.vieworg, currententity->origin); - } - - memset(&mesh, 0, sizeof(mesh)); for(surfnum=0; inf; ((inf->nextsurf)?(inf = (galiasinfo_t*)((char *)inf + inf->nextsurf)):(inf=NULL)), surfnum++) { - needrecolour = Alias_GAliasBuildMesh(&mesh, inf, e, e->shaderRGBAf[3], nolightdir); - - shader = currententity->forcedshader; skin = GL_ChooseSkin(inf, clmodel->name, surfnum, e); - - if (!shader) + shader = e->forcedshader?e->forcedshader:skin->shader; + if (shader) { - if (skin && skin->shader) - shader = skin->shader; - else - { - shader = &reskinnedmodelshader; - skin = &shader->defaulttextures; - reskinnedmodelshader.numpasses = 1; - reskinnedmodelshader.passes[0].flags = 0; - reskinnedmodelshader.passes[0].numMergedPasses = 1; - reskinnedmodelshader.passes[0].anim_frames[0] = skin->base; - if (nolightdir || !mesh.normals_array || !mesh.colors4f_array) - { - reskinnedmodelshader.passes[0].rgbgen = RGB_GEN_IDENTITY_LIGHTING; - reskinnedmodelshader.passes[0].flags |= SHADER_PASS_NOCOLORARRAY; - } - else - reskinnedmodelshader.passes[0].rgbgen = RGB_GEN_LIGHTING_DIFFUSE; - reskinnedmodelshader.passes[0].alphagen = (e->shaderRGBAf[3]<1)?ALPHA_GEN_ENTITY:ALPHA_GEN_IDENTITY; - reskinnedmodelshader.passes[0].shaderbits |= SBITS_MISC_DEPTHWRITE; - reskinnedmodelshader.passes[0].blendmode = GL_MODULATE; - reskinnedmodelshader.passes[0].texgen = T_GEN_DIFFUSE; + b = BE_GetTempBatch(); + if (!b) + break; - reskinnedmodelshader.flags = SHADER_CULL_FRONT; - } + b->buildmeshes = R_GAlias_DrawBatch; + b->ent = e; + b->mesh = NULL; + b->firstmesh = 0; + b->meshes = 1; + b->skin = skin; + b->texture = NULL; + b->shader = shader; + b->lightmap = surfnum; + b->next = batches[shader->sort]; + batches[shader->sort] = b; } - - BE_DrawMesh_Single(shader, &mesh, NULL, skin); } - - if (e->flags & Q2RF_WEAPONMODEL) - VectorCopy(saveorg, currententity->origin); - - if (qglPNTrianglesfATI && gl_ati_truform.ival) - qglDisable(GL_PN_TRIANGLES_ATI); - - qglPopMatrix(); - - if (gl_affinemodels.value) - qglHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - - if (e->flags & Q2RF_DEPTHHACK) - qglDepthRange (gldepthmin, gldepthmax); - - BE_SelectMode(rmode, 0); } //returns the rotated offset of the two points in result @@ -1275,9 +1205,7 @@ void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius) if (Length(lightorg) > radius + clmodel->radius) return; - qglPushMatrix(); - R_RotateForEntity(e, clmodel); - + BE_SelectEntity(e); inf = RMod_Extradata (clmodel); while(inf) @@ -1295,8 +1223,6 @@ void R_DrawGAliasShadowVolume(entity_t *e, vec3_t lightpos, float radius) else inf = NULL; } - - qglPopMatrix(); } #endif diff --git a/engine/gl/gl_backend.c b/engine/gl/gl_backend.c index 64e8e34a3..d4c649ffd 100644 --- a/engine/gl/gl_backend.c +++ b/engine/gl/gl_backend.c @@ -2,7 +2,6 @@ //#define FORCESTATE - #ifdef GLQUAKE #include "glquake.h" @@ -43,7 +42,7 @@ void main (void)\n\ #if defined(SPECULAR)||defined(USEOFFSETMAPPING)\n\ vec3 eyeminusvertex = eyeposition - gl_Vertex.xyz;\n\ eyevector.x = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);\n\ - eyevector.y = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n\ + eyevector.y = -dot(eyeminusvertex, gl_MultiTexCoord3.xyz);\n\ eyevector.z = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);\n\ #endif\n\ #if defined(PCF) || defined(SPOT) || defined(PROJECTION)\n\ @@ -146,19 +145,20 @@ uniform vec3 lightcolour;\n\ \ #ifdef USEOFFSETMAPPING\n\ uniform float offsetmapping_scale;\n\ -uniform float offsetmapping_bias;\n\ #endif\n\ \ \ void main (void)\n\ {\n\ #ifdef USEOFFSETMAPPING\n\ - // this is 3 sample because of ATI Radeon 9500-9800/X300 limits\n\ - vec2 OffsetVector = normalize(eyevector).xy * vec2(-0.333, 0.333);\n\ - vec2 TexCoordOffset = tcbase + OffsetVector * (offsetmapping_bias + offsetmapping_scale * texture2D(bumpt, tcbase).w);\n\ - TexCoordOffset += OffsetVector * (offsetmapping_bias + offsetmapping_scale * texture2D(bumpt, TexCoordOffset).w);\n\ - TexCoordOffset += OffsetVector * (offsetmapping_bias + offsetmapping_scale * texture2D(bumpt, TexCoordOffset).w);\n\ -#define tcbase TexCoordOffset\n\ + vec2 OffsetVector = normalize(eyevector).xy * offsetmapping_scale * vec2(1, -1);\n\ + vec2 foo = tcbase;\n\ +#define tcbase foo\n\ + tcbase += OffsetVector;\n\ + OffsetVector *= 0.333;\n\ + tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ + tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ + tcbase -= OffsetVector * texture2D(bumpt, tcbase).w;\n\ #endif\n\ \ \ @@ -219,11 +219,17 @@ vec2 spot = ((shadowcoord.st)/shadowcoord.w - 0.5)*2.0;colorscale*=1.0-(dot(spot \ #endif\n\ " + +char *defaultglsl2program = + LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT + ; + static const char LIGHTPASS_SHADER[] = "\ {\n\ program\n\ {\n\ - %s%s\n\ + #define LIGHTPASS\n\ + %s\n\ }\n\ \ //incoming fragment\n\ @@ -236,11 +242,11 @@ static const char LIGHTPASS_SHADER[] = "\ param lightradius lightradius\n\ param lightcolour lightcolour\n\ \ - param opt cvarf r_shadow_glsl_offsetmapping_bias offsetmapping_bias\n\ - param opt cvarf r_shadow_glsl_offsetmapping_scale offsetmapping_scale\n\ + param opt cvarf r_glsl_offsetmapping_bias offsetmapping_bias\n\ + param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ \ //eye pos\n\ - param opt eyepos EyePosition\n\ + param opt eyepos eyeposition\n\ \ {\n\ map $diffuse\n\ @@ -263,9 +269,10 @@ static const char PCFPASS_SHADER[] = "\ {\n\ program\n\ {\n\ + #define LIGHTPASS\n\ //#define CUBE\n\ #define PCF\n\ - %s%s%s\n\ + %s%s\n\ }\n\ \ //incoming fragment\n\ @@ -279,8 +286,7 @@ static const char PCFPASS_SHADER[] = "\ param lightradius lightradius\n\ param lightcolour lightcolour\n\ \ - param opt cvarf r_shadow_glsl_offsetmapping_bias offsetmapping_bias\n\ - param opt cvarf r_shadow_glsl_offsetmapping_scale offsetmapping_scale\n\ + param opt cvarf r_glsl_offsetmapping_scale offsetmapping_scale\n\ \ //eye pos\n\ param opt eyepos EyePosition\n\ @@ -306,7 +312,8 @@ static const char PCFPASS_SHADER[] = "\ }"; -extern cvar_t r_shadow_glsl_offsetmapping, r_noportals; + +extern cvar_t r_glsl_offsetmapping, r_noportals; #if 0//def _DEBUG #define checkerror() if (qglGetError()) Con_Printf("Error detected at line %s:%i\n", __FILE__, __LINE__) @@ -317,65 +324,6 @@ extern cvar_t r_shadow_glsl_offsetmapping, r_noportals; static void BE_SendPassBlendAndDepth(unsigned int sbits); static void BE_SubmitBatch(batch_t *batch); -void PPL_CreateShaderObjects(void){} -void PPL_BaseBModelTextures(entity_t *e){} - -enum{ -PERMUTATION_GENERIC = 0, -PERMUTATION_BUMPMAP = 1, -PERMUTATION_SPECULAR = 2, -PERMUTATION_BUMP_SPEC, -PERMUTATION_OFFSET = 4, -PERMUTATION_OFFSET_BUMP, -PERMUTATION_OFFSET_SPEC, -PERMUTATION_OFFSET_BUMP_SPEC, - -PERMUTATIONS -}; -static char *lightpassname[PERMUTATIONS] = -{ - "lightpass_flat", - "lightpass_bump", - "lightpass_spec", - "lightpass_bump_spec", - "lightpass_offset", - "lightpass_offset_bump", - "lightpass_offset_spec", - "lightpass_offset_bump_spec" -}; -static char *pcfpassname[PERMUTATIONS] = -{ - "lightpass_pcf", - "lightpass_pcf_bump", - "lightpass_pcf_spec", - "lightpass_pcf_bump_spec", - "lightpass_pcf_offset", - "lightpass_pcf_offset_bump", - "lightpass_pcf_offset_spec", - "lightpass_pcf_offset_bump_spec" -}; -static char *spotpassname[PERMUTATIONS] = -{ - "lightpass_spot", - "lightpass_spot_bump", - "lightpass_spot_spec", - "lightpass_spot_bump_spec", - "lightpass_spot_offset", - "lightpass_spot_offset_bump", - "lightpass_spot_offset_spec", - "lightpass_spot_offset_bump_spec" -}; -static char *permutationdefines[PERMUTATIONS] = { - "", - "#define BUMP\n", - "#define SPECULAR\n", - "#define SPECULAR\n#define BUMP\n", - "#define USEOFFSETMAPPING\n", - "#define USEOFFSETMAPPING\n#define BUMP\n", - "#define USEOFFSETMAPPING\n#define SPECULAR\n", - "#define USEOFFSETMAPPING\n#define SPECULAR\n#define BUMP\n" -}; - struct { //internal state struct { @@ -385,11 +333,11 @@ struct { int vbo_deforms; //holds verticies... in case you didn't realise. qboolean initedlightpasses; - const shader_t *lightpassshader[PERMUTATIONS]; + const shader_t *lightpassshader; qboolean initedpcfpasses; - const shader_t *pcfpassshader[PERMUTATIONS]; + const shader_t *pcfpassshader; qboolean initedspotpasses; - const shader_t *spotpassshader[PERMUTATIONS]; + const shader_t *spotpassshader; qboolean force2d; int currenttmu; @@ -432,12 +380,20 @@ struct { texid_t curdeluxmap; float curtime; + float updatetime; vec3_t lightorg; vec3_t lightcolours; float lightradius; texid_t lighttexture; }; + + int wmesh; + int maxwmesh; + int wbatch; + int maxwbatches; + batch_t *wbatches; + mesh_t **wmeshes; } shaderstate; struct { @@ -468,6 +424,7 @@ void GL_ForceDepthWritable(void) void GL_SetShaderState2D(qboolean is2d) { + shaderstate.updatetime = realtime; shaderstate.force2d = is2d; BE_SelectMode(BEM_STANDARD, 0); } @@ -582,9 +539,9 @@ void R_FetchTopColour(int *retred, int *retgreen, int *retblue) { int i; - if (currententity->scoreboard) + if (shaderstate.curentity->scoreboard) { - i = currententity->scoreboard->ttopcolor; + i = shaderstate.curentity->scoreboard->ttopcolor; } else i = TOP_RANGE>>4; @@ -612,9 +569,9 @@ void R_FetchBottomColour(int *retred, int *retgreen, int *retblue) { int i; - if (currententity->scoreboard) + if (shaderstate.curentity->scoreboard) { - i = currententity->scoreboard->tbottomcolor; + i = shaderstate.curentity->scoreboard->tbottomcolor; } else i = BOTTOM_RANGE>>4; @@ -861,19 +818,20 @@ static float *FTableForFunc ( unsigned int func ) void Shader_LightPass_Std(char *shortname, shader_t *s, const void *args) { char shadertext[8192*2]; - sprintf(shadertext, LIGHTPASS_SHADER, (char*)args, LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT); + sprintf(shadertext, LIGHTPASS_SHADER, defaultglsl2program); + FS_WriteFile("shader/lightpass.shader.builtin", shadertext, strlen(shadertext), FS_GAMEONLY); Shader_DefaultScript(shortname, s, shadertext); } void Shader_LightPass_PCF(char *shortname, shader_t *s, const void *args) { char shadertext[8192*2]; - sprintf(shadertext, PCFPASS_SHADER, (char*)args, "", LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT); + sprintf(shadertext, PCFPASS_SHADER, "", defaultglsl2program); Shader_DefaultScript(shortname, s, shadertext); } void Shader_LightPass_Spot(char *shortname, shader_t *s, const void *args) { char shadertext[8192*2]; - sprintf(shadertext, PCFPASS_SHADER, (char*)args, "#define SPOT\n", LIGHTPASS_GLSL_SHARED LIGHTPASS_GLSL_VERTEX LIGHTPASS_GLSL_FRAGMENT); + sprintf(shadertext, PCFPASS_SHADER, "#define SPOT\n", defaultglsl2program); Shader_DefaultScript(shortname, s, shadertext); } @@ -911,12 +869,8 @@ void BE_Init(void) /*normally we load these lazily, but if they're probably going to be used anyway, load them now to avoid stalls.*/ if (r_shadow_realtime_dlight.ival && !shaderstate.initedlightpasses && gl_config.arb_shader_objects) { - int i; shaderstate.initedlightpasses = true; - for (i = 0; i < PERMUTATIONS; i++) - { - shaderstate.lightpassshader[i] = R_RegisterCustom(lightpassname[i], Shader_LightPass_Std, permutationdefines[i]); - } + shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL); } shaderstate.shaderbits = ~0; @@ -1688,17 +1642,40 @@ static void GenerateColourMods(const shaderpass_t *pass) else { extern cvar_t r_nolightdir; - if (pass->rgbgen == RGB_GEN_LIGHTING_DIFFUSE && r_nolightdir.ival) + if (pass->rgbgen == RGB_GEN_LIGHTING_DIFFUSE) { - extern avec3_t ambientlight, shadelight; - qglDisableClientState(GL_COLOR_ARRAY); - qglColor4f( ambientlight[0]*0.5+shadelight[0], - ambientlight[1]*0.5+shadelight[1], - ambientlight[2]*0.5+shadelight[2], - shaderstate.curentity->shaderRGBAf[3]); - qglShadeModel(GL_FLAT); - checkerror(); - return; + if (shaderstate.mode == BEM_DEPTHDARK || shaderstate.mode == BEM_DEPTHONLY) + { + avec4_t scol; + scol[0] = scol[1] = scol[2] = 0; + alphagen(pass, 1, meshlist->colors4f_array, &scol, meshlist); + qglDisableClientState(GL_COLOR_ARRAY); + qglColor4fv(scol); + qglShadeModel(GL_FLAT); + return; + } + if (shaderstate.mode == BEM_LIGHT) + { + avec4_t scol; + scol[0] = scol[1] = scol[2] = 1; + alphagen(pass, 1, meshlist->colors4f_array, &scol, meshlist); + qglDisableClientState(GL_COLOR_ARRAY); + qglColor4fv(scol); + qglShadeModel(GL_FLAT); + return; + } + if (r_nolightdir.ival) + { + extern avec3_t ambientlight, shadelight; + qglDisableClientState(GL_COLOR_ARRAY); + qglColor4f( ambientlight[0]*0.5+shadelight[0], + ambientlight[1]*0.5+shadelight[1], + ambientlight[2]*0.5+shadelight[2], + shaderstate.curentity->shaderRGBAf[3]); + qglShadeModel(GL_FLAT); + checkerror(); + return; + } } qglShadeModel(GL_SMOOTH); @@ -2055,6 +2032,18 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas float m16[16]; int r, g, b; + int perm; + + perm = 0; + if (TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_BUMPMAP].glsl) + perm |= PERMUTATION_BUMPMAP; + if (TEXVALID(shaderstate.curtexnums->specular) && s->programhandle[perm|PERMUTATION_SPECULAR].glsl) + perm |= PERMUTATION_SPECULAR; + if (r_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && s->programhandle[perm|PERMUTATION_OFFSET].glsl) + perm |= PERMUTATION_OFFSET; + + GLSlang_UseProgram(s->programhandle[perm].glsl); + BE_SendPassBlendAndDepth(pass->shaderbits); GenerateColourMods(pass); @@ -2076,43 +2065,45 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas } shaderstate.lastpasstmus = pass->numMergedPasses; - GLSlang_UseProgram(s->programhandle.glsl); for (i = 0; i < s->numprogparams; i++) { + if (s->progparm[i].handle[perm] == -1) + continue; /*not in this permutation*/ + switch(s->progparm[i].type) { case SP_TIME: - qglUniform1fARB(s->progparm[i].handle, shaderstate.curtime); + qglUniform1fARB(s->progparm[i].handle[perm], shaderstate.curtime); break; case SP_ENTMATRIX: - Matrix4_ModelMatrixFromAxis(m16, currententity->axis[0], currententity->axis[1], currententity->axis[2], currententity->origin); -/* VectorCopy(currententity->axis[0], m16+0); + Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); +/* VectorCopy(shaderstate.curentity->axis[0], m16+0); m16[3] = 0; - VectorCopy(currententity->axis[1], m16+1); + VectorCopy(shaderstate.curentity->axis[1], m16+1); m16[7] = 0; - VectorCopy(currententity->axis[2], m16+2); + VectorCopy(shaderstate.curentity->axis[2], m16+2); m16[11] = 0; - VectorCopy(currententity->origin, m16+3); + VectorCopy(shaderstate.curentity->origin, m16+3); m16[15] = 1; */ - qglUniformMatrix4fvARB(s->progparm[i].handle, 1, false, m16); + qglUniformMatrix4fvARB(s->progparm[i].handle[perm], 1, false, m16); break; case SP_ENTCOLOURS: - qglUniform4fvARB(s->progparm[i].handle, 1, currententity->shaderRGBAf); + qglUniform4fvARB(s->progparm[i].handle[perm], 1, (GLfloat*)shaderstate.curentity->shaderRGBAf); break; case SP_TOPCOLOURS: R_FetchTopColour(&r, &g, &b); param3[0] = r/255.0f; param3[1] = g/255.0f; param3[2] = b/255.0f; - qglUniform3fvARB(s->progparm[i].handle, 1, param3); + qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3); break; case SP_BOTTOMCOLOURS: R_FetchBottomColour(&r, &g, &b); param3[0] = r/255.0f; param3[1] = g/255.0f; param3[2] = b/255.0f; - qglUniform3fvARB(s->progparm[i].handle, 1, param3); + qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3); break; case SP_RENDERTEXTURESCALE: @@ -2133,25 +2124,25 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas param3[1] = vid.pixelheight/(float)g; } param3[2] = 1; - qglUniform3fvARB(s->progparm[i].handle, 1, param3); + qglUniform3fvARB(s->progparm[i].handle[perm], 1, param3); break; case SP_LIGHTRADIUS: - qglUniform1fARB(s->progparm[i].handle, shaderstate.lightradius); + qglUniform1fARB(s->progparm[i].handle[perm], shaderstate.lightradius); break; case SP_LIGHTCOLOUR: - qglUniform3fvARB(s->progparm[i].handle, 1, shaderstate.lightcolours); + qglUniform3fvARB(s->progparm[i].handle[perm], 1, shaderstate.lightcolours); break; case SP_EYEPOS: { #pragma message("is this correct?") // vec3_t t1; vec3_t t2; - Matrix4_ModelMatrixFromAxis(m16, currententity->axis[0], currententity->axis[1], currententity->axis[2], currententity->origin); + Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); Matrix4_Transform3(m16, r_origin, t2); -// VectorSubtract(r_origin, currententity->origin, t1); -// Matrix3_Multiply_Vec3(currententity->axis, t1, t2); - qglUniform3fvARB(s->progparm[i].handle, 1, t2); +// VectorSubtract(r_origin, shaderstate.curentity->origin, t1); +// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2); + qglUniform3fvARB(s->progparm[i].handle[perm], 1, t2); } break; case SP_LIGHTPOSITION: @@ -2162,15 +2153,28 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas vec3_t t2; qboolean Matrix4_Invert(const float *m, float *out); - Matrix4_ModelMatrixFromAxis(m16, currententity->axis[0], currententity->axis[1], currententity->axis[2], currententity->origin); + Matrix4_ModelMatrixFromAxis(m16, shaderstate.curentity->axis[0], shaderstate.curentity->axis[1], shaderstate.curentity->axis[2], shaderstate.curentity->origin); Matrix4_Invert(m16, inv); Matrix4_Transform3(inv, shaderstate.lightorg, t2); -// VectorSubtract(shaderstate.lightorg, currententity->origin, t1); -// Matrix3_Multiply_Vec3(currententity->axis, t1, t2); - qglUniform3fvARB(s->progparm[i].handle, 1, t2); +// VectorSubtract(shaderstate.lightorg, shaderstate.curentity->origin, t1); +// Matrix3_Multiply_Vec3(shaderstate.curentity->axis, t1, t2); + qglUniform3fvARB(s->progparm[i].handle[perm], 1, t2); } break; + case SP_TEXTURE: + qglUniform1iARB(s->progparm[i].handle[perm], s->progparm[i].ival); + break; + case SP_CVARI: + qglUniform1iARB(s->progparm[i].handle[perm], ((cvar_t*)s->progparm[i].pval)->ival); + break; + case SP_CVARF: + qglUniform1fARB(s->progparm[i].handle[perm], ((cvar_t*)s->progparm[i].pval)->value); + break; + case SP_CVAR3F: +// qglUniform3fvARB(uniformloc, 1, specialvec); + break; + default: Host_EndGame("Bad shader program parameter type (%i)", s->progparm[i].type); break; @@ -2184,7 +2188,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas #ifdef RTLIGHTS qboolean BE_LightCullModel(vec3_t org, model_t *model) { - if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_STENCIL) + if ((shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_STENCIL)) { float dist; vec3_t disp; @@ -2273,36 +2277,24 @@ void BE_SelectMode(backendmode_t mode, unsigned int flags) { if (!shaderstate.initedpcfpasses) { - int i; shaderstate.initedpcfpasses = true; - for (i = 0; i < PERMUTATIONS; i++) - { - shaderstate.pcfpassshader[i] = R_RegisterCustom(pcfpassname[i], Shader_LightPass_PCF, permutationdefines[i]); - } + shaderstate.pcfpassshader = R_RegisterCustom("lightpass_pcf", Shader_LightPass_PCF, NULL); } } if (mode == BEM_SMAPLIGHTSPOT) { if (!shaderstate.initedspotpasses) { - int i; shaderstate.initedspotpasses = true; - for (i = 0; i < PERMUTATIONS; i++) - { - shaderstate.spotpassshader[i] = R_RegisterCustom(spotpassname[i], Shader_LightPass_Spot, permutationdefines[i]); - } + shaderstate.spotpassshader = R_RegisterCustom("lightpass_spot", Shader_LightPass_Spot, NULL); } } if (mode == BEM_LIGHT) { if (!shaderstate.initedlightpasses) { - int i; shaderstate.initedlightpasses = true; - for (i = 0; i < PERMUTATIONS; i++) - { - shaderstate.lightpassshader[i] = R_RegisterCustom(lightpassname[i], Shader_LightPass_Std, permutationdefines[i]); - } + shaderstate.lightpassshader = R_RegisterCustom("lightpass", Shader_LightPass_Std, NULL); } } #endif @@ -2311,6 +2303,17 @@ void BE_SelectMode(backendmode_t mode, unsigned int flags) shaderstate.flags = flags; } +void BE_SelectEntity(entity_t *ent) +{ + if (shaderstate.curentity && shaderstate.curentity->flags & Q2RF_DEPTHHACK) + qglDepthRange (gldepthmin, gldepthmax); + shaderstate.curentity = ent; + currententity = ent; + R_RotateForEntity(shaderstate.curentity, shaderstate.curentity->model); + if (shaderstate.curentity->flags & Q2RF_DEPTHHACK) + qglDepthRange (gldepthmin, gldepthmin + 0.3*(gldepthmax-gldepthmin)); +} + #ifdef RTLIGHTS void BE_SelectDLight(dlight_t *dl, vec3_t colour) { @@ -2411,9 +2414,6 @@ static void DrawMeshes(void) { const shaderpass_t *p; int passno; -#ifdef RTLIGHTS - int perm; -#endif passno = 0; GL_SelectEBO(shaderstate.sourcevbo->vboe); @@ -2456,34 +2456,13 @@ static void DrawMeshes(void) break; #ifdef RTLIGHTS case BEM_SMAPLIGHTSPOT: - perm = 0; - if (TEXVALID(shaderstate.curtexnums->bump) && shaderstate.spotpassshader[perm|PERMUTATION_BUMPMAP]) - perm |= PERMUTATION_BUMPMAP; - if (TEXVALID(shaderstate.curtexnums->specular) && shaderstate.spotpassshader[perm|PERMUTATION_SPECULAR]) - perm |= PERMUTATION_SPECULAR; - if (r_shadow_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.spotpassshader[perm|PERMUTATION_OFFSET]) - perm |= PERMUTATION_OFFSET; - BE_RenderMeshProgram(shaderstate.spotpassshader[perm], shaderstate.spotpassshader[perm]->passes); + BE_RenderMeshProgram(shaderstate.spotpassshader, shaderstate.spotpassshader->passes); break; case BEM_SMAPLIGHT: - perm = 0; - if (TEXVALID(shaderstate.curtexnums->bump) && shaderstate.pcfpassshader[perm|PERMUTATION_BUMPMAP]) - perm |= PERMUTATION_BUMPMAP; - if (TEXVALID(shaderstate.curtexnums->specular) && shaderstate.pcfpassshader[perm|PERMUTATION_SPECULAR]) - perm |= PERMUTATION_SPECULAR; - if (r_shadow_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.pcfpassshader[perm|PERMUTATION_OFFSET]) - perm |= PERMUTATION_OFFSET; - BE_RenderMeshProgram(shaderstate.pcfpassshader[perm], shaderstate.pcfpassshader[perm]->passes); + BE_RenderMeshProgram(shaderstate.pcfpassshader, shaderstate.pcfpassshader->passes); break; case BEM_LIGHT: - perm = 0; - if (TEXVALID(shaderstate.curtexnums->bump) && shaderstate.lightpassshader[perm|PERMUTATION_BUMPMAP]) - perm |= PERMUTATION_BUMPMAP; - if (TEXVALID(shaderstate.curtexnums->specular) && shaderstate.lightpassshader[perm|PERMUTATION_SPECULAR]) - perm |= PERMUTATION_SPECULAR; - if (r_shadow_glsl_offsetmapping.ival && TEXVALID(shaderstate.curtexnums->bump) && shaderstate.lightpassshader[perm|PERMUTATION_OFFSET]) - perm |= PERMUTATION_OFFSET; - BE_RenderMeshProgram(shaderstate.lightpassshader[perm], shaderstate.lightpassshader[perm]->passes); + BE_RenderMeshProgram(shaderstate.lightpassshader, shaderstate.lightpassshader->passes); break; #endif case BEM_DEPTHONLY: @@ -2513,7 +2492,7 @@ static void DrawMeshes(void) //fallthrough case BEM_STANDARD: default: - if (shaderstate.curshader->programhandle.glsl) + if (shaderstate.curshader->programhandle[0].glsl) BE_RenderMeshProgram(shaderstate.curshader, shaderstate.curshader->passes); else { @@ -2538,11 +2517,12 @@ void BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t mesh_t *m; shaderstate.sourcevbo = &shaderstate.dummyvbo; shaderstate.curshader = shader; - shaderstate.curentity = currententity; + if (shaderstate.curentity != &r_worldentity) + BE_SelectEntity(&r_worldentity); shaderstate.curtexnums = texnums; shaderstate.curlightmap = r_nulltex; shaderstate.curdeluxmap = r_nulltex; - shaderstate.curtime = cl.servertime - currententity->shaderTime; + shaderstate.curtime = shaderstate.updatetime - shaderstate.curentity->shaderTime; while (nummeshes--) { @@ -2565,7 +2545,8 @@ void BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **meshlist, vbo_t { shaderstate.sourcevbo = vbo; shaderstate.curshader = shader; - shaderstate.curentity = currententity; + if (shaderstate.curentity != &r_worldentity) + BE_SelectEntity(&r_worldentity); shaderstate.curtexnums = texnums; shaderstate.curlightmap = r_nulltex; shaderstate.curdeluxmap = r_nulltex; @@ -2582,6 +2563,7 @@ void BE_DrawMesh_Single(shader_t *shader, mesh_t *mesh, vbo_t *vbo, texnums_t *t BE_DrawMesh_List(shader, 1, &mesh, NULL, texnums); } +#if 0 static void BaseBrushTextures(entity_t *ent) { int i; @@ -2653,6 +2635,7 @@ static void BaseBrushTextures(entity_t *ent) batch.mesh = batchmeshes; batch.lightmap = -1; batch.texture = NULL; + batch.ent = ent; for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) { if (batch.meshes == batch.maxmeshes || batch.lightmap != s->lightmaptexturenum || batch.texture != s->texinfo->texture) @@ -2672,10 +2655,10 @@ static void BaseBrushTextures(entity_t *ent) qglPopMatrix(); } -#ifdef RTLIGHTS void BE_BaseEntShadowDepth(void) { int i; + entity_t *ent; if (!r_drawentities.value) return; @@ -2683,27 +2666,26 @@ void BE_BaseEntShadowDepth(void) // draw sprites seperately, because of alpha blending for (i=0 ; imodel) + ent = &cl_visedicts[i]; + if (!ent->model) continue; - if (currententity->model->needload) + if (ent->model->needload) continue; - if (currententity->flags & Q2RF_WEAPONMODEL) + if (ent->flags & Q2RF_WEAPONMODEL) continue; - switch(currententity->model->type) + switch(ent->model->type) { case mod_brush: - BaseBrushTextures(currententity); + BaseBrushTextures(ent); break; case mod_alias: - R_DrawGAliasModel (currententity, BEM_DEPTHONLY); + R_DrawGAliasModel (ent, BEM_DEPTHONLY); break; } } } -#endif -void BE_BaseEntTextures(void) +/*void BE_BaseEntTextures(void) { int i; unsigned int bef; @@ -2748,7 +2730,8 @@ void BE_BaseEntTextures(void) break; } } -} +}*/ +#endif void BE_DrawPolys(qboolean decalsset) { @@ -2778,7 +2761,24 @@ static void BE_SubmitBatch(batch_t *batch) model_t *model = cl.worldmodel; int lm; - lm = batch->lightmap; + if (batch->texture) + { + shaderstate.sourcevbo = &batch->texture->vbo; + lm = batch->lightmap; + } + else + { + shaderstate.dummyvbo.coord = batch->mesh[0]->xyz_array; + shaderstate.dummyvbo.texcoord = batch->mesh[0]->st_array; + shaderstate.dummyvbo.indicies = batch->mesh[0]->indexes; + shaderstate.dummyvbo.normals = batch->mesh[0]->normals_array; + shaderstate.dummyvbo.svector = batch->mesh[0]->snormals_array; + shaderstate.dummyvbo.tvector = batch->mesh[0]->tnormals_array; + shaderstate.dummyvbo.colours4f = batch->mesh[0]->colors4f_array; + shaderstate.sourcevbo = &shaderstate.dummyvbo; + lm = -1; + } + if (lm < 0) { shaderstate.curlightmap = r_nulltex; @@ -2790,12 +2790,15 @@ static void BE_SubmitBatch(batch_t *batch) shaderstate.curdeluxmap = deluxmap_textures[lm]; } - shaderstate.sourcevbo = &batch->texture->vbo; shaderstate.curshader = batch->shader; - shaderstate.curentity = currententity; + if (shaderstate.curentity != batch->ent) + BE_SelectEntity(batch->ent); + shaderstate.flags = batch->flags; shaderstate.curtime = realtime; - - shaderstate.curtexnums = &shaderstate.curshader->defaulttextures; + if (batch->skin) + shaderstate.curtexnums = batch->skin; + else + shaderstate.curtexnums = &shaderstate.curshader->defaulttextures; if (0) { @@ -2815,37 +2818,42 @@ static void BE_SubmitBatch(batch_t *batch) } } -void BE_SubmitMeshes (void) +static void BE_SubmitMeshesPortals(batch_t *worldlist, batch_t *dynamiclist) { - model_t *model = cl.worldmodel; batch_t *batch, *old; - currententity = &r_worldentity; - - /*find all the portal shaders and try to draw them*/ - if (!r_noportals.ival && !r_refdef.recurse) + int i; + /*attempt to draw portal shaders*/ + if (shaderstate.mode == BEM_STANDARD) { - if (shaderstate.mode == BEM_STANDARD) + for (i = 0; i < 2; i++) { - for (batch = model->batches; batch; batch = batch->next) + for (batch = i?dynamiclist:worldlist; batch; batch = batch->next) { - batch->shader = R_TextureAnimation (batch->texture)->shader; - if (batch->shader->sort > SHADER_SORT_PORTAL) - break; - if (batch->meshes == batch->firstmesh) continue; + /*draw already-drawn portals as depth-only, to ensure that their contents are not harmed*/ BE_SelectMode(BEM_DEPTHONLY, 0); - for (old = model->batches; old != batch; old = old->next) + for (old = worldlist; old && old != batch; old = old->next) { if (old->meshes == old->firstmesh) continue; BE_SubmitBatch(old); } + if (!old) + { + for (old = dynamiclist; old != batch; old = old->next) + { + if (old->meshes == old->firstmesh) + continue; + BE_SubmitBatch(old); + } + } BE_SelectMode(BEM_STANDARD, 0); - + #if 0 R_DrawPortal(batch); + #endif /*clear depth again*/ GL_ForceDepthWritable(); @@ -2854,19 +2862,20 @@ void BE_SubmitMeshes (void) } } } +} - for (batch = model->batches; batch; batch = batch->next) +static void BE_SubmitMeshesSortList(batch_t *sortlist) +{ + batch_t *batch; + for (batch = sortlist; batch; batch = batch->next) { if (batch->meshes == batch->firstmesh) continue; - batch->shader = R_TextureAnimation (batch->texture)->shader; - - if (batch->shader->sort == SHADER_SORT_PORTAL) - { - if (shaderstate.mode != BEM_STANDARD) - continue; - } + if (batch->buildmeshes) + batch->buildmeshes(batch); + else + batch->shader = R_TextureAnimation(batch->ent->framestate.g[FS_REG].frame[0], batch->texture)->shader; if (batch->shader->flags & SHADER_NODLIGHT) if (shaderstate.mode == BEM_LIGHT || shaderstate.mode == BEM_SMAPLIGHT) @@ -2881,14 +2890,26 @@ void BE_SubmitMeshes (void) BE_SubmitBatch(batch); } +} - if (shaderstate.mode == BEM_STANDARD) - BE_DrawPolys(true); +void BE_SubmitMeshes (qboolean drawworld, batch_t **blist) +{ + model_t *model = cl.worldmodel; + int i; + + for (i = SHADER_SORT_PORTAL; i < SHADER_SORT_COUNT; i++) + { + if (drawworld) + { + if (i == SHADER_SORT_PORTAL && !r_noportals.ival && !r_refdef.recurse) + BE_SubmitMeshesPortals(model->batches[i], blist[i]); + + BE_SubmitMeshesSortList(model->batches[i]); + } + BE_SubmitMeshesSortList(blist[i]); + } checkerror(); - BE_BaseEntTextures(); - checkerror(); - currententity = &r_worldentity; } static void BE_UpdateLightmaps(void) @@ -2947,12 +2968,221 @@ static void BE_UpdateLightmaps(void) } } +static void BE_GenBrushBatches(batch_t **batches, entity_t *ent) +{ + int i; + msurface_t *s; + model_t *model; + batch_t *b; + unsigned int bef; + + model = ent->model; + + if (R_CullEntityBox (ent, model->mins, model->maxs)) + return; + +#ifdef RTLIGHTS + if (BE_LightCullModel(ent->origin, model)) + return; +#endif + +// calculate dynamic lighting for bmodel if it's not an +// instanced model + if (model->fromgame != fg_quake3) + { + int k; + int shift; + + currententity = ent; + currentmodel = ent->model; + if (model->nummodelsurfaces != 0 && r_dynamic.value) + { + for (k=rtlights_first; kfuncs.MarkLights (&cl_dlights[k], 1<nodes + model->hulls[0].firstclipnode); + } + } + + shift = Surf_LightmapShift(model); + if ((ent->drawflags & MLS_MASKIN) == MLS_ABSLIGHT) + { + //update lightmaps. + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + Surf_RenderAmbientLightmaps (s, shift, ent->abslight); + } + else if (ent->drawflags & DRF_TRANSLUCENT) + { + //update lightmaps. + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + Surf_RenderAmbientLightmaps (s, shift, 255); + } + else + { + //update lightmaps. + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + Surf_RenderDynamicLightmaps (s, shift); + } + currententity = NULL; + } + + bef = BEF_PUSHDEPTH; + if (ent->flags & Q2RF_ADDITIVE) + bef |= BEF_FORCEADDITIVE; + else if (ent->drawflags & DRF_TRANSLUCENT && r_wateralpha.value != 1) + { + bef |= BEF_FORCETRANSPARENT; + ent->shaderRGBAf[3] = r_wateralpha.value; + } + else if (ent->shaderRGBAf[3] < 1 && cls.protocol != CP_QUAKE3) + bef |= BEF_FORCETRANSPARENT; + if (ent->flags & RF_NODEPTHTEST) + bef |= BEF_FORCENODEPTH; + + b = NULL; + for (s = model->surfaces+model->firstmodelsurface,i = 0; i < model->nummodelsurfaces; i++, s++) + { + if (!b || b->lightmap != s->lightmaptexturenum || b->texture != s->texinfo->texture) + { + if (shaderstate.wbatch >= shaderstate.maxwbatches) + { + shaderstate.wbatch++; + break; /*can't allocate any new ones!*/ + } + b = &shaderstate.wbatches[shaderstate.wbatch++]; + b->buildmeshes = NULL; + b->ent = ent; + b->texture = s->texinfo->texture; + b->shader = R_TextureAnimation(ent->framestate.g[FS_REG].frame[0], b->texture)->shader; + b->skin = &b->shader->defaulttextures; + b->flags = bef; + if (bef & BEF_FORCEADDITIVE) + { + b->next = batches[SHADER_SORT_ADDITIVE]; + batches[SHADER_SORT_ADDITIVE] = b; + } + else if (bef & BEF_FORCETRANSPARENT) + { + b->next = batches[SHADER_SORT_BLEND]; + batches[SHADER_SORT_BLEND] = b; + } + else + { + b->next = batches[b->shader->sort]; + batches[b->shader->sort] = b; + } + b->mesh = shaderstate.wmeshes+shaderstate.wmesh; + b->meshes = 0; + b->lightmap = s->lightmaptexturenum; + } + + shaderstate.wmesh++; + if (shaderstate.wmesh >= shaderstate.maxwmesh) + continue; + b->mesh[b->meshes++] = s->mesh; + } +} + +batch_t *BE_GetTempBatch(void) +{ + if (shaderstate.wbatch >= shaderstate.maxwbatches) + { + shaderstate.wbatch++; + return NULL; + } + return &shaderstate.wbatches[shaderstate.wbatch++]; +} + +void BE_GenModelBatches(batch_t **batches) +{ + int i; + entity_t *ent; + + /*clear the batch list*/ + for (i = 0; i < SHADER_SORT_COUNT; i++) + batches[i] = NULL; + + if (!r_drawentities.ival) + return; + + // draw sprites seperately, because of alpha blending + for (i=0 ; imodel) + continue; + if (ent->model->needload) + continue; + if (!R_ShouldDraw(ent)) + continue; + switch(ent->model->type) + { + case mod_brush: + if (r_drawentities.ival == 2) + continue; + BE_GenBrushBatches(batches, ent); + break; + case mod_alias: + if (r_drawentities.ival == 3) + continue; + R_GAlias_GenerateBatches(ent, batches); + break; + } + } +} + +/*called from shadowmapping code*/ +#ifdef RTLIGHTS +void BE_BaseEntTextures(void) +{ + batch_t *batches[SHADER_SORT_COUNT]; + BE_GenModelBatches(batches); + BE_SubmitMeshes(false, batches); + BE_SelectEntity(&r_worldentity); +} +#endif + void BE_DrawWorld (qbyte *vis) { extern cvar_t r_shadow_realtime_world, r_shadow_realtime_world_lightmaps; + batch_t *batches[SHADER_SORT_COUNT]; RSpeedLocals(); GL_DoSwap(); + if (shaderstate.wmesh > shaderstate.maxwmesh) + { + int newm = shaderstate.wmesh; + shaderstate.wmeshes = BZ_Realloc(shaderstate.wmeshes, newm * sizeof(*shaderstate.wmeshes)); + memset(shaderstate.wmeshes + shaderstate.maxwmesh, 0, (newm - shaderstate.maxwmesh) * sizeof(*shaderstate.wmeshes)); + shaderstate.maxwmesh = newm; + } + if (shaderstate.wbatch > 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.wmesh = 0; + shaderstate.wbatch = 0; + BE_GenModelBatches(batches); + + shaderstate.curentity = NULL; + shaderstate.updatetime = cl.servertime; + +#if 0 + {int i; + for (i = 0; i < SHADER_SORT_COUNT; i++) + batches[i] = NULL; + } +#endif + BE_UpdateLightmaps(); //make sure the world draws correctly @@ -2979,16 +3209,52 @@ void BE_DrawWorld (qbyte *vis) checkerror(); RSpeedRemark(); - BE_SubmitMeshes(); + BE_SubmitMeshes(true, batches); RSpeedEnd(RSPEED_WORLD); #ifdef RTLIGHTS RSpeedRemark(); + BE_SelectEntity(&r_worldentity); Sh_DrawLights(vis); RSpeedEnd(RSPEED_STENCILSHADOWS); #endif checkerror(); BE_DrawPolys(false); + + BE_SelectEntity(&r_worldentity); + shaderstate.updatetime = realtime; } + +void BE_DrawNonWorld (void) +{ + batch_t *batches[SHADER_SORT_COUNT]; + if (shaderstate.wmesh > shaderstate.maxwmesh) + { + int newm = shaderstate.wmesh; + shaderstate.wmeshes = BZ_Realloc(shaderstate.wmeshes, newm * sizeof(*shaderstate.wmeshes)); + memset(shaderstate.wmeshes + shaderstate.maxwmesh, 0, (newm - shaderstate.maxwmesh) * sizeof(*shaderstate.wmeshes)); + shaderstate.maxwmesh = newm; + } + if (shaderstate.wbatch > 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.wmesh = 0; + shaderstate.wbatch = 0; + BE_GenModelBatches(batches); + + shaderstate.curentity = NULL; + shaderstate.updatetime = cl.servertime; + + BE_SubmitMeshes(false, batches); + + BE_SelectEntity(&r_worldentity); + shaderstate.updatetime = realtime; +} + #endif diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 1ce7dabbb..d4be12400 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -412,7 +412,6 @@ TRACE(("dbg: GLDraw_ReInit: Allocating upload buffers\n")); qglClearColor (1,0,0,0); TRACE(("dbg: GLDraw_ReInit: PPL_LoadSpecularFragmentProgram\n")); - PPL_CreateShaderObjects(); GL_InitSceneProcessingShaders(); #ifdef PLUGINS diff --git a/engine/gl/gl_font.c b/engine/gl/gl_font.c index 6cb7ef56b..0aa6ca5c9 100644 --- a/engine/gl/gl_font.c +++ b/engine/gl/gl_font.c @@ -1251,10 +1251,10 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch if (c->texplane >= DEFAULTPLANE) { - sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; - sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; - sw = ((curfont->charheight*cw)*vid.width) / (float)vid.pixelwidth; - sh = ((curfont->charheight*ch)*vid.height) / (float)vid.pixelheight; + sx = ((px+c->left));//*(int)vid.width) / (float)vid.pixelwidth; + sy = ((py+c->top));//*(int)vid.height) / (float)vid.pixelheight; + sw = ((curfont->charheight*cw));//*vid.width) / (float)vid.pixelwidth; + sh = ((curfont->charheight*ch));//*vid.height) / (float)vid.pixelheight; if (c->texplane == DEFAULTPLANE) v = Font_BeginChar(fontplanes.defaultfont); @@ -1263,10 +1263,10 @@ float Font_DrawScaleChar(float px, float py, float cw, float ch, unsigned int ch } else { - sx = ((px+c->left)*(int)vid.width) / (float)vid.pixelwidth; - sy = ((py+c->top)*(int)vid.height) / (float)vid.pixelheight; - sw = ((c->bmw*cw)*vid.width) / (float)vid.pixelwidth; - sh = ((c->bmh*ch)*vid.height) / (float)vid.pixelheight; + sx = ((px+c->left));//*(int)vid.width) / (float)vid.pixelwidth; + sy = ((py+c->top));//*(int)vid.height) / (float)vid.pixelheight; + sw = ((c->bmw*cw));//*vid.width) / (float)vid.pixelwidth; + sh = ((c->bmh*ch));//*vid.height) / (float)vid.pixelheight; v = Font_BeginChar(fontplanes.texnum[c->texplane]); } diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index 50163f1de..d55c6e6fa 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -270,12 +270,12 @@ unsigned int Heightmap_PointContentsHM(heightmap_t *hm, float clipmipsz, vec3_t return FTECONTENTS_EMPTY; } -unsigned int Heightmap_PointContents(model_t *model, vec3_t org) +unsigned int Heightmap_PointContents(model_t *model, vec3_t axis[3], vec3_t org) { heightmap_t *hm = model->terrain; return Heightmap_PointContentsHM(hm, 0, org); } -unsigned int Heightmap_NativeBoxContents(model_t *model, int hulloverride, int frame, vec3_t org, vec3_t mins, vec3_t maxs) +unsigned int Heightmap_NativeBoxContents(model_t *model, int hulloverride, int frame, vec3_t axis[3], vec3_t org, vec3_t mins, vec3_t maxs) { heightmap_t *hm = model->terrain; return Heightmap_PointContentsHM(hm, mins[2], org); @@ -514,7 +514,7 @@ Heightmap_Trace Traces a line through a heightmap, sampling the terrain at various different positions. This is inprecise, only supports points (or vertical lines), and can often travel though sticky out bits of terrain. */ -qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace) +qboolean Heightmap_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) { vec3_t org; vec3_t dir; @@ -575,9 +575,9 @@ qboolean Heightmap_Trace(model_t *model, int forcehullnum, int frame, vec3_t sta return trace->fraction != 1; } -qboolean Heightmap_NativeTrace(struct model_s *model, int hulloverride, int frame, vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace) +qboolean Heightmap_NativeTrace(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace) { - return Heightmap_Trace(model, hulloverride, frame, p1, p2, mins, maxs, trace); + return Heightmap_Trace(model, hulloverride, frame, axis, p1, p2, mins, maxs, trace); } #endif diff --git a/engine/gl/gl_model.c b/engine/gl/gl_model.c index 506e4a227..35ee2e202 100644 --- a/engine/gl/gl_model.c +++ b/engine/gl/gl_model.c @@ -497,7 +497,10 @@ model_t *RMod_LoadModel (model_t *mod, qboolean crash) if (!strcmp(mod->name, "progs/player.mdl")) mod->engineflags |= MDLF_PLAYER | MDLF_DOCRC; else if (!strcmp(mod->name, "progs/flame.mdl") || - !strcmp(mod->name, "progs/flame2.mdl")) + !strcmp(mod->name, "progs/flame2.mdl") || + !strcmp(mod->name, "models/flame1.mdl") || //hexen2 small standing flame + !strcmp(mod->name, "models/flame2.mdl") || //hexen2 large standing flame + !strcmp(mod->name, "models/cflmtrch.mdl")) //hexen2 wall torch mod->engineflags |= MDLF_FLAME; else if (!strcmp(mod->name, "progs/bolt.mdl") || !strcmp(mod->name, "progs/bolt2.mdl") || @@ -1114,9 +1117,9 @@ TRACE(("dbg: RMod_LoadTextures: inittexturedescs\n")); if (gl_bump.ival<2) //set to 2 to have faster loading. { snprintf(altname, sizeof(altname)-1, "%s_norm", mt->name); - tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOALPHA|IF_NOGAMMA|IF_SUBDIRONLY); + tn.bump = R_LoadReplacementTexture(altname, loadname, IF_NOGAMMA|IF_SUBDIRONLY); if (!TEXVALID(tn.bump)) - tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOALPHA|IF_NOGAMMA); + tn.bump = R_LoadReplacementTexture(altname, "bmodels", IF_NOGAMMA); } if (!TEXVALID(tn.bump)) { @@ -2685,12 +2688,6 @@ static void Q1BSP_StainNode (mnode_t *node, float *parms) #endif } - -void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); -qboolean Q1BSP_Trace(model_t *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, trace_t *trace); -void GLQ1BSP_LightPointValues(model_t *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); - - void RMod_FixupNodeMinsMaxs (mnode_t *node, mnode_t *parent) { if (!node) @@ -3191,17 +3188,17 @@ void * RMod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, { size *= 4; if (!TEXVALID(texnum)) - texnum = R_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), IF_NOGAMMA); + texnum = R_LoadTexture32 (name, width, height, (unsigned *)(pinframe + 1), IF_NOGAMMA|IF_CLAMP); } else if (version == SPRITEHL_VERSION) { if (!TEXVALID(texnum)) - texnum = R_LoadTexture8Pal32 (name, width, height, (qbyte *)(pinframe + 1), (qbyte*)palette, IF_NOGAMMA); + texnum = R_LoadTexture8Pal32 (name, width, height, (qbyte *)(pinframe + 1), (qbyte*)palette, IF_NOGAMMA|IF_CLAMP); } else { if (!TEXVALID(texnum)) - texnum = R_LoadTexture8 (name, width, height, (qbyte *)(pinframe + 1), IF_NOMIPMAP|IF_NOGAMMA, 1); + texnum = R_LoadTexture8 (name, width, height, (qbyte *)(pinframe + 1), IF_NOMIPMAP|IF_NOGAMMA|IF_CLAMP, 1); } Q_strncpyz(name, loadmodel->name, sizeof(name)); diff --git a/engine/gl/gl_model.h b/engine/gl/gl_model.h index 7dfc70b98..a27766391 100644 --- a/engine/gl/gl_model.h +++ b/engine/gl/gl_model.h @@ -30,29 +30,22 @@ struct wedict_s; struct model_s; struct world_s; -typedef struct { - //deals with FTECONTENTS (assumes against solid) - void (*PurgeModel) (struct model_s *mod); +typedef enum { + SHADER_SORT_NONE, + SHADER_SORT_PORTAL, + SHADER_SORT_SKY, + SHADER_SORT_OPAQUE, + SHADER_SORT_DECAL, + SHADER_SORT_SEETHROUGH, + SHADER_SORT_BANNER, + SHADER_SORT_UNDERWATER, + SHADER_SORT_BLEND, + SHADER_SORT_ADDITIVE, + SHADER_SORT_NEAREST, - qboolean (*Trace) (struct model_s *model, int hulloverride, int frame, vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, struct trace_s *trace); - unsigned int (*PointContents) (struct model_s *model, vec3_t p); - unsigned int (*BoxContents) (struct model_s *model, int hulloverride, int frame, vec3_t p, vec3_t mins, vec3_t maxs); - //deals with whatever is native for the bsp (gamecode is expected to distinguish this). - qboolean (*NativeTrace) (struct model_s *model, int hulloverride, int frame, vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace); - unsigned int (*NativeContents)(struct model_s *model, int hulloverride, int frame, vec3_t p, vec3_t mins, vec3_t maxs); - - unsigned int (*FatPVS) (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge); - qboolean (*EdictInFatPVS) (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer); - void (*FindTouchedLeafs) (struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs); //edict system as opposed to q2 game dll system. - - void (*LightPointValues) (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); - void (*StainNode) (struct mnode_s *node, float *parms); - void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node); - - qbyte *(*LeafPVS) (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize); - int (*LeafnumForPoint) (struct model_s *model, vec3_t point); -} modelfuncs_t; + SHADER_SORT_COUNT +} shadersort_t; typedef struct mesh_s { @@ -93,11 +86,17 @@ typedef struct batch_s struct batch_s *next; shader_t *shader; - struct texture_s *texture; struct vbo_s *vbo; int lightmap; + entity_t *ent; + + struct texture_s *texture; + struct texnums_s *skin; unsigned int maxmeshes; - vec3_t normal; + unsigned int flags; + + void (*buildmeshes)(struct batch_s *b); + vec3_t normal; /*used only at load (for portal surfaces, so multiple planes are not part of the same batch)*/ } batch_t; /* @@ -131,6 +130,32 @@ BRUSH MODELS ============================================================================== */ +typedef struct { + //deals with FTECONTENTS (assumes against solid) + void (*PurgeModel) (struct model_s *mod); + + qboolean (*Trace) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, struct trace_s *trace); + unsigned int (*PointContents) (struct model_s *model, vec3_t axis[3], vec3_t p); + unsigned int (*BoxContents) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs); + + //deals with whatever is native for the bsp (gamecode is expected to distinguish this). + qboolean (*NativeTrace) (struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p1, vec3_t p2, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace); + unsigned int (*NativeContents)(struct model_s *model, int hulloverride, int frame, vec3_t axis[3], vec3_t p, vec3_t mins, vec3_t maxs); + + unsigned int (*FatPVS) (struct model_s *model, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean merge); + qboolean (*EdictInFatPVS) (struct model_s *model, struct pvscache_s *edict, qbyte *pvsbuffer); + void (*FindTouchedLeafs) (struct model_s *model, struct pvscache_s *ent, vec3_t cullmins, vec3_t cullmaxs); //edict system as opposed to q2 game dll system. + + void (*LightPointValues) (struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); + void (*StainNode) (struct mnode_s *node, float *parms); + void (*MarkLights) (struct dlight_s *light, int bit, struct mnode_s *node); + + qbyte *(*LeafPVS) (struct model_s *model, int num, qbyte *buffer, unsigned int buffersize); + int (*LeafnumForPoint) (struct model_s *model, vec3_t point); +} modelfuncs_t; + + + // // in memory representation @@ -157,7 +182,7 @@ typedef struct mplane_s qbyte pad[2]; } mplane_t; -typedef struct { +typedef struct texnums_s { texid_t base; texid_t bump; texid_t upperoverlay; @@ -423,7 +448,9 @@ void Q1BSP_Init(void); int Q1BSP_ClipDecal(vec3_t center, vec3_t normal, vec3_t tangent1, vec3_t tangent2, float size, float **out); -qboolean Q1BSP_Trace(struct model_s *model, int forcehullnum, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace); +void Q1BSP_MarkLights (dlight_t *light, int bit, mnode_t *node); +void GLQ1BSP_LightPointValues(struct model_s *model, vec3_t point, vec3_t res_diffuse, vec3_t res_ambient, vec3_t res_dir); +qboolean Q1BSP_Trace(struct model_s *model, int forcehullnum, int frame, vec3_t axis[3], vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace); qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, struct trace_s *trace); unsigned int Q1BSP_FatPVS (struct model_s *mod, vec3_t org, qbyte *pvsbuffer, unsigned int buffersize, qboolean add); qboolean Q1BSP_EdictInFatPVS(struct model_s *mod, struct pvscache_s *ent, qbyte *pvs); @@ -826,7 +853,7 @@ typedef struct model_s char *entities; void *terrain; - batch_t *batches; + batch_t *batches[SHADER_SORT_COUNT]; unsigned checksum; unsigned checksum2; diff --git a/engine/gl/gl_rmain.c b/engine/gl/gl_rmain.c index 0f8f225a1..37aea41a3 100644 --- a/engine/gl/gl_rmain.c +++ b/engine/gl/gl_rmain.c @@ -37,9 +37,6 @@ extern int gl_canstencil; FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB; FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB; -#define Q2RF_WEAPONMODEL 4 // only draw through eyes -#define Q2RF_DEPTHHACK 16 - entity_t r_worldentity; vec3_t modelorg, r_entorigin; @@ -437,33 +434,10 @@ void GL_SetupSceneProcessingTextures (void) qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, PP_WARP_TEX_SIZE, PP_WARP_TEX_SIZE, 0, GL_RGB, GL_UNSIGNED_BYTE, pp_edge_tex); } -void R_RotateForEntity (entity_t *e, model_t *mod) +void R_RotateForEntity (const entity_t *e, const model_t *mod) { + float mv[16]; float m[16]; - if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0) - { //rotate to view first - m[0] = cl.viewent[r_refdef.currentplayernum].axis[0][0]; - m[1] = cl.viewent[r_refdef.currentplayernum].axis[0][1]; - m[2] = cl.viewent[r_refdef.currentplayernum].axis[0][2]; - m[3] = 0; - - m[4] = cl.viewent[r_refdef.currentplayernum].axis[1][0]; - m[5] = cl.viewent[r_refdef.currentplayernum].axis[1][1]; - m[6] = cl.viewent[r_refdef.currentplayernum].axis[1][2]; - m[7] = 0; - - m[8] = cl.viewent[r_refdef.currentplayernum].axis[2][0]; - m[9] = cl.viewent[r_refdef.currentplayernum].axis[2][1]; - m[10] = cl.viewent[r_refdef.currentplayernum].axis[2][2]; - m[11] = 0; - - m[12] = cl.viewent[r_refdef.currentplayernum].origin[0]; - m[13] = cl.viewent[r_refdef.currentplayernum].origin[1]; - m[14] = cl.viewent[r_refdef.currentplayernum].origin[2]; - m[15] = 1; - - qglMultMatrixf(m); - } m[0] = e->axis[0][0]; m[1] = e->axis[0][1]; @@ -485,101 +459,72 @@ void R_RotateForEntity (entity_t *e, model_t *mod) m[14] = e->origin[2]; m[15] = 1; - qglMultMatrixf(m); - - if (!mod) - return; - if (e->scale != 1 && e->scale != 0) //hexen 2 stuff { - float tmatrix[3][4]; - vec3_t scale; - vec3_t scale_origin; - float xyfact, zfact, entScale; - scale[0] = (mod->maxs[0]-mod->mins[0])/255; - scale[1] = (mod->maxs[1]-mod->mins[1])/255; - scale[2] = (mod->maxs[2]-mod->mins[2])/255; - scale_origin[0] = mod->mins[0]; - scale_origin[1] = mod->mins[1]; - scale_origin[2] = mod->mins[2]; - - - entScale = (float)e->scale; + float z; + float escale; + escale = e->scale; switch(e->drawflags&SCALE_TYPE_MASKIN) { default: case SCALE_TYPE_UNIFORM: - tmatrix[0][0] = scale[0]*entScale; - tmatrix[1][1] = scale[1]*entScale; - tmatrix[2][2] = scale[2]*entScale; - xyfact = zfact = (entScale-1.0)*127.95; + VectorScale((m+0), escale, (m+0)); + VectorScale((m+4), escale, (m+4)); + VectorScale((m+8), escale, (m+8)); break; case SCALE_TYPE_XYONLY: - tmatrix[0][0] = scale[0]*entScale; - tmatrix[1][1] = scale[1]*entScale; - tmatrix[2][2] = scale[2]; - xyfact = (entScale-1.0)*127.95; - zfact = 1.0; + VectorScale((m+0), escale, (m+0)); + VectorScale((m+4), escale, (m+4)); break; case SCALE_TYPE_ZONLY: - tmatrix[0][0] = scale[0]; - tmatrix[1][1] = scale[1]; - tmatrix[2][2] = scale[2]*entScale; - xyfact = 1.0; - zfact = (entScale-1.0)*127.95; + VectorScale((m+8), escale, (m+8)); break; } - switch(currententity->drawflags&SCALE_ORIGIN_MASKIN) + if (mod && (e->drawflags&SCALE_TYPE_MASKIN) != SCALE_TYPE_XYONLY) { - default: - case SCALE_ORIGIN_CENTER: - tmatrix[0][3] = scale_origin[0]-scale[0]*xyfact; - tmatrix[1][3] = scale_origin[1]-scale[1]*xyfact; - tmatrix[2][3] = scale_origin[2]-scale[2]*zfact; - break; - case SCALE_ORIGIN_BOTTOM: - tmatrix[0][3] = scale_origin[0]-scale[0]*xyfact; - tmatrix[1][3] = scale_origin[1]-scale[1]*xyfact; - tmatrix[2][3] = scale_origin[2]; - break; - case SCALE_ORIGIN_TOP: - tmatrix[0][3] = scale_origin[0]-scale[0]*xyfact; - tmatrix[1][3] = scale_origin[1]-scale[1]*xyfact; - tmatrix[2][3] = scale_origin[2]-scale[2]*zfact*2.0; - break; + switch(e->drawflags&SCALE_ORIGIN_MASKIN) + { + case SCALE_ORIGIN_CENTER: + z = ((mod->maxs[2] + mod->mins[2]) * (1-escale))/2; + VectorMA((m+12), z, e->axis[2], (m+12)); + break; + case SCALE_ORIGIN_BOTTOM: + VectorMA((m+12), mod->mins[2]*(1-escale), e->axis[2], (m+12)); + break; + case SCALE_ORIGIN_TOP: + VectorMA((m+12), -mod->maxs[2], e->axis[2], (m+12)); + break; + } } - /* - { - tmatrix[0][0] = scale[0]; - tmatrix[1][1] = scale[1]; - tmatrix[2][2] = scale[2]; - tmatrix[0][3] = scale_origin[0]; - tmatrix[1][3] = scale_origin[1]; - tmatrix[2][3] = scale_origin[2]; - } - */ - - qglTranslatef (tmatrix[0][3],tmatrix[1][3],tmatrix[2][3]); - qglScalef (tmatrix[0][0],tmatrix[1][1],tmatrix[2][2]); - - qglScalef( 1/scale[0], - 1/scale[1], - 1/scale[2]); - qglTranslatef ( -scale_origin[0], - -scale_origin[1], - -scale_origin[2]); } - else if (!strcmp(mod->name, "progs/eyes.mdl")) + else if (mod && !strcmp(mod->name, "progs/eyes.mdl")) { - // double size of eyes, since they are really hard to see in gl - qglTranslatef (0, 0, 0 - (22 + 8)); - qglScalef (2, 2, 2); + /*resize eyes, to make them easier to see*/ + m[14] -= (22 + 8); + VectorScale((m+0), 2, (m+0)); + VectorScale((m+4), 2, (m+4)); + VectorScale((m+8), 2, (m+8)); } - - if (!ruleset_allow_larger_models.ival && mod->clampscale != 1) + if (mod && !ruleset_allow_larger_models.ival && mod->clampscale != 1) { //possibly this should be on a per-frame basis, but that's a real pain to do Con_DPrintf("Rescaling %s by %f\n", mod->name, mod->clampscale); - qglScalef(mod->clampscale, mod->clampscale, mod->clampscale); + VectorScale((m+0), mod->clampscale, (m+0)); + VectorScale((m+4), mod->clampscale, (m+4)); + VectorScale((m+8), mod->clampscale, (m+8)); + } + + if (e->flags & Q2RF_WEAPONMODEL && r_refdef.currentplayernum>=0) + { + /*FIXME: no bob*/ + float simpleview[16]; + Matrix4_ModelViewMatrix(simpleview, vec3_origin, vec3_origin); + Matrix4_Multiply(simpleview, m, mv); + qglLoadMatrixf(mv); + } + else + { + Matrix4_Multiply(r_refdef.m_view, m, mv); + qglLoadMatrixf(mv); } } @@ -1027,8 +972,6 @@ void GLR_DrawEntitiesOnList (void) switch (currententity->model->type) { case mod_alias: - if (r_refdef.flags & Q2RDF_NOWORLDMODEL || !cl.worldmodel || cl.worldmodel->type != mod_brush || cl.worldmodel->fromgame == fg_doom) - R_DrawGAliasModel (currententity, BEM_STANDARD); break; #ifdef HALFLIFEMODELS @@ -1038,8 +981,6 @@ void GLR_DrawEntitiesOnList (void) #endif case mod_brush: - if (!cl.worldmodel || cl.worldmodel->type != mod_brush || cl.worldmodel->fromgame == fg_doom) - PPL_BaseBModelTextures (currententity); break; case mod_sprite: @@ -1081,7 +1022,7 @@ void R_SetupGL (void) x = r_refdef.vrect.x * vid.pixelwidth/(int)vid.width; x2 = (r_refdef.vrect.x + r_refdef.vrect.width) * vid.pixelwidth/(int)vid.width; y = (vid.height-r_refdef.vrect.y) * vid.pixelheight/(int)vid.height; - y2 = ((int)vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * vid.pixelheight/(int)vid.height; + y2 = ((int)vid.height - (r_refdef.vrect.y + r_refdef.vrect.height)) * (int)vid.pixelheight/(int)vid.height; // fudge around because of frac screen scale if (x > 0) @@ -1186,6 +1127,8 @@ void R_RenderScene (void) TRACE(("dbg: calling R_DrawWorld\n")); Surf_DrawWorld (); // adds static entities to the list } + else + BE_DrawNonWorld(); S_ExtraUpdate (); // don't let sound get messed up if going slow @@ -1333,7 +1276,7 @@ static void TransformDir(vec3_t in, vec3_t planea[3], vec3_t viewa[3], vec3_t re VectorMA(result, d, viewa[i], result); } } -void R_DrawPortal(batch_t *batch) +void R_DrawPortal(batch_t *batch, batch_t *blist) { entity_t *view; GLdouble glplane[4]; @@ -1409,7 +1352,7 @@ void R_DrawPortal(batch_t *batch) /*FIXME: the batch stuff should be done in renderscene*/ /*fixup the first mesh index*/ - for (batch = cl.worldmodel->batches; batch; batch = batch->next) + for (batch = blist; batch; batch = batch->next) { batch->firstmesh = batch->meshes; } @@ -1427,7 +1370,7 @@ void R_DrawPortal(batch_t *batch) R_RenderScene(); qglDisable(GL_CLIP_PLANE0); - for (batch = cl.worldmodel->batches; batch; batch = batch->next) + for (batch = blist; batch; batch = batch->next) { batch->firstmesh = 0; } diff --git a/engine/gl/gl_rmisc.c b/engine/gl/gl_rmisc.c index 77e379d69..c1da94045 100644 --- a/engine/gl/gl_rmisc.c +++ b/engine/gl/gl_rmisc.c @@ -864,11 +864,11 @@ static void R_LoadRTLights(void) VectorCopy(rgb, dl->color); dl->die = 0; dl->flags = flags|LFLAG_ALLOW_PPL; - if (*cubename) + /*if (*cubename) { dl->fov = 90; dl->flags |= LFLAG_SHADOWMAP; - } + }*/ AngleVectors(angles, dl->axis[0], dl->axis[1], dl->axis[2]); dl->style = style+1; diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index d1a3c045c..9f5dbd949 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -671,6 +671,35 @@ static void Shader_EntityMergable ( shader_t *shader, shaderpass_t *pass, char * shader->flags |= SHADER_ENTITY_MERGABLE; } +static void Shader_LoadProgram(shader_t *shader, char *vert, char *frag, int qrtype) +{ + static char *permutationdefines[PERMUTATIONS] = { + "", + "#define BUMP\n", + "#define SPECULAR\n", + "#define SPECULAR\n#define BUMP\n", + "#define USEOFFSETMAPPING\n", + "#define USEOFFSETMAPPING\n#define BUMP\n", + "#define USEOFFSETMAPPING\n#define SPECULAR\n", + "#define USEOFFSETMAPPING\n#define SPECULAR\n#define BUMP\n" + }; + int p; + + if (!frag) + frag = vert; + + for (p = 0; p < PERMUTATIONS; p++) + { + if (qrenderer != qrtype) + { + } + #ifdef GLQUAKE + else if (qrenderer == QR_OPENGL) + shader->programhandle[p].glsl = GLSlang_CreateProgram(permutationdefines[p], (char *)vert, (char *)frag); + #endif + } +} + static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **ptr, int qrtype) { /*accepts: @@ -685,13 +714,6 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p */ void *vert, *frag; char *token; - if (shader->programhandle.glsl) - { //this allows fallbacks - token = Shader_ParseString ( ptr ); - token = Shader_ParseString ( ptr ); - return; - } - token = *ptr; while (*token == ' ' || *token == '\t' || *token == '\r') @@ -709,7 +731,7 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p else { token++; - vert = frag = token; + frag = token; for (count = 1; *token; token++) { if (*token == '}') @@ -721,47 +743,39 @@ static void Shader_SLProgramName (shader_t *shader, shaderpass_t *pass, char **p else if (*token == '{') count++; } - frag = BZ_Malloc(token - (char*)vert + 1); - memcpy(frag, vert, token-(char*)vert); - ((char*)frag)[token-(char*)vert] = 0; - vert = frag; + vert = BZ_Malloc(token - (char*)frag + 1); + memcpy(vert, frag, token-(char*)frag); + ((char*)vert)[token-(char*)frag] = 0; + frag = NULL; *ptr = token+1; - if (qrenderer != qrtype) - { - } -#ifdef GLQUAKE - else if (qrenderer == QR_OPENGL) - shader->programhandle.glsl = GLSlang_CreateProgram("", (char *)vert, (char *)frag); -#endif + Shader_LoadProgram(shader, vert, frag, qrtype); + BZ_Free(vert); - frag = NULL; - vert = NULL; return; } } - token = Shader_ParseString ( ptr ); - FS_LoadFile(token, &vert); - token = Shader_ParseString ( ptr ); - if (!*token) - frag = vert; - else - FS_LoadFile(token, &frag); - if (qrenderer != qrtype) + vert = Shader_ParseString(ptr); + if (!strcmp(vert, "default")) { + extern char *defaultglsl2program; + frag = Shader_ParseString(ptr); + Shader_LoadProgram(shader, defaultglsl2program, defaultglsl2program, qrtype); + return; } -#ifdef GLQUAKE - else if (vert && frag) - shader->programhandle.glsl = GLSlang_CreateProgram("", (char *)vert, (char *)frag); -#endif + FS_LoadFile(vert, &vert); + + frag = Shader_ParseString(ptr); + if (!frag) + frag = NULL; + else + FS_LoadFile(frag, &frag); + + Shader_LoadProgram(shader, vert, frag, qrtype); if (vert) - { - if (frag == vert) - frag = NULL; FS_FreeFile(vert); - } if (frag) FS_FreeFile(frag); } @@ -777,13 +791,15 @@ static void Shader_HLSLProgramName (shader_t *shader, shaderpass_t *pass, char * static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **ptr ) { - cvar_t *cv; + cvar_t *cv = NULL; int specialint = 0; float specialfloat = 0; vec3_t specialvec = {0}; enum shaderprogparmtype_e parmtype = SP_BAD; char *token; qboolean silent = false; + int p; + qboolean foundone; token = Shader_ParseString(ptr); if (!Q_stricmp(token, "opt")) @@ -801,32 +817,24 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p { token = Shader_ParseSensString(ptr); cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); - if (cv) - { //Cvar_Get returns null if the cvar is the name of a command - specialint = cv->ival; - specialfloat = cv->value; - } + if (!cv) + return; parmtype = SP_CVARI; } else if (!Q_stricmp(token, "cvarf")) { token = Shader_ParseSensString(ptr); cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); - if (cv) - { //Cvar_Get returns null if the cvar is the name of a command - specialint = cv->ival; - specialfloat = cv->value; - } + if (!cv) + return; parmtype = SP_CVARF; } else if (!Q_stricmp(token, "cvar3f")) { token = Shader_ParseSensString(ptr); cv = Cvar_Get(token, "", 0, "GLSL Shader parameters"); - if (cv) - { - SCR_StringToRGB(cv->string, specialvec, 1); - } + if (!cv) + return; parmtype = SP_CVAR3F; } else if (!Q_stricmp(token, "time")) @@ -858,42 +866,52 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p if (qrenderer == QR_OPENGL) { unsigned int uniformloc; - if (!shader->programhandle.glsl) + if (!shader->programhandle[0].glsl) { Con_Printf("shader %s: param without program set\n", shader->name); } + else if (shader->numprogparams == SHADER_PROGPARMS_MAX) + Con_Printf("shader %s: too many parms\n", shader->name); else { - GLSlang_UseProgram(shader->programhandle.glsl); - uniformloc = qglGetUniformLocationARB(shader->programhandle.glsl, token); - if (uniformloc == -1) + foundone = false; + shader->progparm[shader->numprogparams].type = parmtype; + for (p = 0; p < PERMUTATIONS; p++) { - if (!silent) - Con_Printf("shader %s: param without uniform \"%s\"\n", shader->name, token); - } - else - { - switch(parmtype) + if (!shader->programhandle[p].glsl) + continue; + GLSlang_UseProgram(shader->programhandle[p].glsl); + uniformloc = qglGetUniformLocationARB(shader->programhandle[p].glsl, token); + shader->progparm[shader->numprogparams].handle[p] = uniformloc; + if (uniformloc != -1) { - case SP_BAD: - break; - case SP_TEXTURE: - case SP_CVARI: - qglUniform1iARB(uniformloc, specialint); - break; - case SP_CVARF: - qglUniform1fARB(uniformloc, specialfloat); - break; - case SP_CVAR3F: - qglUniform3fvARB(uniformloc, 1, specialvec); - break; - default: - shader->progparm[shader->numprogparams].type = parmtype; - shader->progparm[shader->numprogparams].handle = uniformloc; - shader->numprogparams++; - break; + foundone = true; + switch(parmtype) + { + case SP_BAD: + foundone = false; + break; + case SP_TEXTURE: + shader->progparm[shader->numprogparams].ival = specialint; + break; + case SP_CVARF: + case SP_CVARI: + shader->progparm[shader->numprogparams].pval = cv; + break; + case SP_CVAR3F: + shader->progparm[shader->numprogparams].pval = cv; + qglUniform3fvARB(uniformloc, 1, specialvec); + break; + default: + break; + } } } + if (!foundone && !silent) + Con_Printf("shader %s: param without uniform \"%s\"\n", shader->name, token); + else + shader->numprogparams++; + GLSlang_UseProgram(0); } } @@ -1689,8 +1707,14 @@ void Shader_Free (shader_t *shader) #ifdef GLQUAKE if (qrenderer == QR_OPENGL) - if (shader->programhandle.glsl) - qglDeleteObjectARB(shader->programhandle.glsl); + { + int p; + for (p = 0; p < PERMUTATIONS; p++) + { + if (shader->programhandle[p].glsl) + GLSlang_DeleteObject(shader->programhandle[p].glsl); + } + } #endif memset(&shader->programhandle, 0, sizeof(shader->programhandle)); @@ -2153,7 +2177,7 @@ void Shader_Finish (shader_t *s) s->sort = SHADER_SORT_DECAL; } - if (r_vertexlight.value && !s->programhandle.glsl) + if (r_vertexlight.value && !s->programhandle[0].glsl) { // do we have a lightmap pass? pass = s->passes; @@ -2337,7 +2361,7 @@ done:; s->flags &= ~SHADER_DEPTHWRITE; } - if (s->programhandle.glsl) + if (s->programhandle[0].glsl) { if (!s->numpasses) s->numpasses = 1; @@ -2452,6 +2476,37 @@ void Shader_DefaultBSPLM(char *shortname, shader_t *s, const void *args) "}\n" ); + if (0&&!builtin && gl_config.arb_shader_objects) + { + builtin = ( + "{\n" + "program default\n" + "param texture 0 tex_diffuse\n" + "param texture 1 tex_lightmap\n" + "param texture 2 tex_normalmap\n" + "param texture 3 tex_deluxmap\n" + "param texture 4 tex_fullbright\n" + "{\n" + "map $diffuse\n" + "tcgen base\n" + "}\n" + "{\n" + "map $lightmap\n" + "tcgen lightmap\n" + "}\n" + "{\n" + "map $normalmap\n" + "}\n" + "{\n" + "map $deluxmap\n" + "}\n" + "{\n" + "map $fullbright\n" + "}\n" + "}\n" + ); + } + if (!builtin) builtin = ( "{\n" diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 84a6fffd3..4d9e9791b 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -1347,7 +1347,8 @@ checkerror(); BE_DrawMesh_List(tex->shader, smesh->litsurfs[tno].count, smesh->litsurfs[tno].s, &tex->vbo, &tex->shader->defaulttextures); } - BE_BaseEntShadowDepth(); + BE_SelectMode(BEM_DEPTHONLY, 0); + BE_BaseEntTextures(); if (0) { @@ -1621,7 +1622,6 @@ static void Sh_DrawEntLighting(dlight_t *light, vec3_t colour) texture_t *tex; shadowmesh_t *sm; - currententity = &r_worldentity; sm = light->worldshadowmesh; if (light->rebuildcache) sm = &sh_tempshmesh; @@ -1659,8 +1659,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) RotateLightVector(e->axis, e->origin, dl->origin, lightorg); - qglPushMatrix(); - R_RotateForEntity(e, e->model); + BE_SelectEntity(e); GL_SelectVBO(0); GL_SelectEBO(0); @@ -1736,7 +1735,6 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) } qglEnd(); } - qglPopMatrix(); BE_PushOffsetShadow(false); } @@ -1750,6 +1748,7 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q extern cvar_t gl_part_flame; int i; struct shadowmesh_s *sm; + entity_t *ent; BE_PushOffsetShadow(false); @@ -1758,8 +1757,6 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q Sh_DrawBrushModelShadow(dl, &r_worldentity); else { - currententity = &r_worldentity; - //qglEnable(GL_POLYGON_OFFSET_FILL); //qglPolygonOffset(shaderstate.curpolyoffset.factor, shaderstate.curpolyoffset.unit); @@ -1780,41 +1777,42 @@ static void Sh_DrawStencilLightShadows(dlight_t *dl, qbyte *lvis, qbyte *vvis, q // draw sprites seperately, because of alpha blending for (i=0 ; iflags & (RF_NOSHADOW|Q2RF_BEAM)) + if (ent->flags & (RF_NOSHADOW|Q2RF_BEAM)) continue; { - if (currententity->keynum == dl->key && currententity->keynum) + if (ent->keynum == dl->key && ent->keynum) continue; } - if (!currententity->model) + if (!ent->model) continue; - if (cls.allow_anyparticles || currententity->visframe) //allowed or static + if (cls.allow_anyparticles || ent->visframe) //allowed or static { - if (currententity->model->engineflags & MDLF_ENGULPHS) + if (ent->model->engineflags & MDLF_ENGULPHS) { if (gl_part_flame.value) continue; } } - switch (currententity->model->type) + switch (ent->model->type) { case mod_alias: - R_DrawGAliasShadowVolume (currententity, dl->origin, dl->radius); + R_DrawGAliasShadowVolume (ent, dl->origin, dl->radius); break; case mod_brush: - Sh_DrawBrushModelShadow (dl, currententity); + Sh_DrawBrushModelShadow (dl, ent); break; default: break; } } + BE_SelectEntity(&r_worldentity); } //draws a light using stencil shadows. @@ -1881,7 +1879,7 @@ static qboolean Sh_DrawStencilLight(dlight_t *dl, vec3_t colour, qbyte *vvis) BE_SelectMode(BEM_STENCIL, 0); //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); diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index 3966bf424..91b3f55fa 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -579,7 +579,6 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) #endif } - // glslang helper api function definitions // type should be GL_FRAGMENT_SHADER_ARB or GL_VERTEX_SHADER_ARB GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource, GLenum shadertype) @@ -588,34 +587,33 @@ GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource GLint compiled; char str[1024]; int loglen; + char *prstrings[4]; - char *prstrings[3]; - if (!precompilerconstants) - precompilerconstants = ""; + prstrings[0] = "#define ENGINE_"DISTRIBUTION"\n"; switch (shadertype) { case GL_FRAGMENT_SHADER_ARB: - prstrings[0] = "#define FRAGMENT_SHADER\n"; + prstrings[1] = "#define FRAGMENT_SHADER\n"; break; case GL_VERTEX_SHADER_ARB: - prstrings[0] = "#define VERTEX_SHADER\n"; + prstrings[1] = "#define VERTEX_SHADER\n"; break; default: - prstrings[0] = "#define UNKNOWN_SHADER\n"; + prstrings[1] = "#define UNKNOWN_SHADER\n"; break; } - prstrings[1] = precompilerconstants; - prstrings[2] = shadersource; + prstrings[2] = precompilerconstants; + prstrings[3] = shadersource; shader = qglCreateShaderObjectARB(shadertype); - qglShaderSourceARB(shader, 3, (const GLcharARB**)prstrings, NULL); + qglShaderSourceARB(shader, 4, (const GLcharARB**)prstrings, NULL); qglCompileShaderARB(shader); qglGetObjectParameterivARB(shader, GL_OBJECT_COMPILE_STATUS_ARB, &compiled); if(!compiled) { - Con_DPrintf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2]); + Con_DPrintf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2], prstrings[3]); qglGetInfoLogARB(shader, sizeof(str), NULL, str); qglDeleteObjectARB(shader); switch (shadertype) @@ -641,7 +639,7 @@ GLhandleARB GLSlang_CreateShader (char *precompilerconstants, char *shadersource qglGetInfoLogARB(shader, sizeof(str), NULL, str); if (strstr(str, "WARNING")) { - Con_Printf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2]); + Con_Printf("Shader source:\n%s%s%s\n", prstrings[0], prstrings[1], prstrings[2], prstrings[3]); Con_Printf("%s\n", str); } } @@ -678,24 +676,78 @@ GLhandleARB GLSlang_CreateProgramObject (GLhandleARB vert, GLhandleARB frag) return program; } +#if HASHPROGRAMS +struct compiledshaders_s +{ + int uses; + char *consts; + char *vert; + char *frag; + GLhandleARB handle; + bucket_t buck; +}; + +bucket_t *compiledshadersbuckets[64]; +static hashtable_t compiledshaderstable; +#endif + GLhandleARB GLSlang_CreateProgram(char *precompilerconstants, char *vert, char *frag) { + GLhandleARB handle; GLhandleARB vs; GLhandleARB fs; +#if HASHPROGRAMS + unsigned int hashkey; + struct compiledshaders_s *cs; +#endif if (!gl_config.arb_shader_objects) return 0; + if (!precompilerconstants) + precompilerconstants = ""; + +#if HASHPROGRAMS + hashkey = Hash_Key(precompilerconstants, ~0) ^ Hash_Key(frag, ~0); + + cs = Hash_GetKey(&compiledshaderstable, hashkey); + while(cs) + { + if (!strcmp(cs->consts, precompilerconstants)) + if (!strcmp(cs->vert, vert)) + if (!strcmp(cs->frag, frag)) + { + cs->uses++; + return cs->handle; + } + cs = Hash_GetNextKey(&compiledshaderstable, hashkey, cs); + } +#endif + vs = GLSlang_CreateShader(precompilerconstants, vert, GL_VERTEX_SHADER_ARB); fs = GLSlang_CreateShader(precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB); if (!vs || !fs) - { - //delete ignores 0s. - qglDeleteObjectARB(vs); - qglDeleteObjectARB(fs); - return 0; - } - return GLSlang_CreateProgramObject(vs, fs); + handle = 0; + else + handle = GLSlang_CreateProgramObject(vs, fs); + //delete ignores 0s. + qglDeleteObjectARB(vs); + qglDeleteObjectARB(fs); + +#if HASHPROGRAMS + cs = Z_Malloc(sizeof(*cs) + strlen(precompilerconstants)+1+strlen(vert)+1+strlen(frag)+1); + cs->consts = (char*)(cs + 1); + cs->vert = cs->consts + strlen(precompilerconstants)+1; + cs->frag = cs->vert + strlen(vert)+1; + cs->handle = handle; + cs->uses = 1; + strcpy(cs->consts, precompilerconstants); + strcpy(cs->vert, vert); + strcpy(cs->frag, frag); + Hash_AddKey(&compiledshaderstable, hashkey, cs, &cs->buck); +#endif + + return handle; } GLint GLSlang_GetUniformLocation (int prog, char *name) @@ -890,6 +942,10 @@ void GL_Init(void *(*getglfunction) (char *name)) if (qglDebugMessageCallbackAMD) qglDebugMessageCallbackAMD(myGLDEBUGPROCAMD, NULL); #endif + +#if HASHPROGRAMS + Hash_InitTable(&compiledshaderstable, sizeof(compiledshadersbuckets)/Hash_BytesForBuckets(1), compiledshadersbuckets); +#endif } unsigned int d_8to24rgbtable[256]; diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index c516595ea..da3e83942 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -467,6 +467,7 @@ static void GL_DrawSkySphere (batch_t *batch, shader_t *shader) skydist=gl_skyboxdist.value; skydist/=16; + BE_SelectEntity(&r_worldentity); //scale sky sphere and place around view origin. qglPushMatrix(); qglTranslatef(r_refdef.vieworg[0], r_refdef.vieworg[1], r_refdef.vieworg[2]); diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index f72a6f6b7..9cccf8938 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -62,9 +62,6 @@ void GLR_FrameTimeGraph (int frametime); void GL_FlushSkinCache(void); void GL_GAliasFlushSkinCache(void); -void PPL_CreateShaderObjects(void); -void PPL_BaseBModelTextures(entity_t *e); - // Function prototypes for the Texture Object Extension routines typedef GLboolean (APIENTRY *ARETEXRESFUNCPTR)(GLsizei, const GLuint *, const GLboolean *); @@ -314,7 +311,7 @@ qboolean R_CullBox (vec3_t mins, vec3_t maxs); #ifdef GLQUAKE qboolean R_CullSphere (vec3_t origin, float radius); qboolean R_CullEntityBox(entity_t *e, vec3_t modmins, vec3_t modmaxs); -void R_RotateForEntity (entity_t *e, model_t *mod); +void R_RotateForEntity (const entity_t *e, const model_t *mod); void GL_InitSceneProcessingShaders (void); void GL_SetupSceneProcessingTextures (void); diff --git a/engine/gl/ltface.c b/engine/gl/ltface.c index 09d184a22..159e60ac3 100644 --- a/engine/gl/ltface.c +++ b/engine/gl/ltface.c @@ -61,7 +61,7 @@ vec_t CastRay (vec3_t p1, vec3_t p2) trace_t trace; vec3_t move; - lightmodel->funcs.Trace (lightmodel, 0, 0, p1, p2, vec3_origin, vec3_origin, &trace); + lightmodel->funcs.Trace (lightmodel, 0, 0, NULL, p1, p2, vec3_origin, vec3_origin, &trace); if (trace.fraction < 1) return -1; @@ -158,7 +158,7 @@ void LightLoadEntities(char *entstring) for (i = 0; i < 256; i+=16) { v[2] = mapent->origin[2]-i; - cont = lightmodel->funcs.PointContents (lightmodel, v); + cont = lightmodel->funcs.PointContents (lightmodel, NULL, v); if (cont & (FTECONTENTS_LAVA | FTECONTENTS_SLIME | FTECONTENTS_SOLID)) break; } diff --git a/engine/gl/shader.h b/engine/gl/shader.h index d446411ae..8fddd8135 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -18,20 +18,6 @@ typedef enum { SHADER_2D } shadertype_t; -typedef enum { - SHADER_SORT_NONE, - SHADER_SORT_PORTAL, - SHADER_SORT_SKY, - SHADER_SORT_OPAQUE, - SHADER_SORT_DECAL, - SHADER_SORT_SEETHROUGH, - SHADER_SORT_BANNER, - SHADER_SORT_UNDERWATER, - SHADER_SORT_BLEND, - SHADER_SORT_ADDITIVE, - SHADER_SORT_NEAREST -} shadersort_t; - typedef enum { MF_NONE = 1<<0, MF_NORMALS = 1<<1, @@ -243,6 +229,19 @@ typedef struct texid_t nearbox_textures[6]; } skydome_t; +enum{ + PERMUTATION_GENERIC = 0, + PERMUTATION_BUMPMAP = 1, + PERMUTATION_SPECULAR = 2, + PERMUTATION_BUMP_SPEC, + PERMUTATION_OFFSET = 4, + PERMUTATION_OFFSET_BUMP, + PERMUTATION_OFFSET_SPEC, + PERMUTATION_OFFSET_BUMP_SPEC, + + PERMUTATIONS +}; + typedef struct { enum shaderprogparmtype_e { SP_BAD, @@ -267,9 +266,15 @@ typedef struct { SP_CVAR3F, SP_TEXTURE } type; - unsigned int handle; + unsigned int handle[PERMUTATIONS]; + union + { + int ival; + void *pval; + }; } shaderprogparm_t; + typedef struct { float factor; float unit; @@ -318,7 +323,7 @@ struct shader_s union { int glsl; - } programhandle; + } programhandle[PERMUTATIONS]; int numprogparams; shaderprogparm_t progparm[SHADER_PROGPARMS_MAX]; @@ -393,9 +398,11 @@ void BE_SelectMode(backendmode_t mode, unsigned int flags); Rules for using a list: Every mesh must be part of the same VBO, shader, lightmap, and must have the same pointers set*/ void BE_DrawMesh_List(shader_t *shader, int nummeshes, mesh_t **mesh, vbo_t *vbo, texnums_t *texnums); void BE_DrawMesh_Single(shader_t *shader, mesh_t *meshchain, vbo_t *vbo, texnums_t *texnums); +batch_t *BE_GetTempBatch(void); //Asks the backend to invoke DrawMeshChain for each surface, and to upload lightmaps as required void BE_DrawWorld (qbyte *vis); +void BE_DrawNonWorld (void); //called at init, force the display to the right defaults etc void BE_Init(void); @@ -411,8 +418,6 @@ void BE_GenerateProgram(shader_t *shader); #ifdef RTLIGHTS void BE_PushOffsetShadow(qboolean foobar); -//submits the world and ents... used only by gl_shadows.c -void BE_SubmitMeshes (void); //sets up gl for depth-only FIXME void BE_SetupForShadowMap(void); //Called from shadowmapping code into backend @@ -424,6 +429,8 @@ void Sh_Shutdown(void); 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); + +void BE_SelectEntity(entity_t *ent); //Returns true if the mesh is not lit by the current light qboolean BE_LightCullModel(vec3_t org, model_t *model); #endif diff --git a/engine/partcfgs/generatebuiltin.c b/engine/partcfgs/generatebuiltin.c new file mode 100644 index 000000000..25f7fe2cf --- /dev/null +++ b/engine/partcfgs/generatebuiltin.c @@ -0,0 +1,77 @@ +#include +#include + +char *effects[] = +{ + "spikeset.cfg", + "faithful.cfg", + "highfps.cfg", + "minimal.cfg", + "h2part.cfg", + "tsshaft.cfg", + NULL +}; + +int main(void) +{ + FILE *c, *h, *s; + char line[1024]; + int i, j; + c = fopen("../client/r_partset.c", "wt"); + h = fopen("../client/r_partset.h", "wt"); + + fprintf(c, "/*\nWARNING: THIS FILE IS GENERATED BY '"__FILE__"'.\nYOU SHOULD NOT EDIT THIS FILE BY HAND\n*/\n\n"); + fprintf(c, "#include \"r_partset.h\"\n\n\n"); + + for (i = 0; effects[i]; i++) + { + s = fopen(effects[i], "rt"); + *strchr(effects[i], '.') = 0; + fprintf(h, "extern char *particle_set_%s;\n", effects[i]); + + if (i) + fprintf(c, "\n\n\n//////////////////////////////////////////////////////\n\n\n"); + fprintf(c, "char *particle_set_%s =\n", effects[i]); + while(fgets(line, sizeof(line), s)) + { + j = 0; + while (line[j] == ' ' || line[j] == '\t') + j++; + if ((line[j] == '/' && line[j] == '/') || line[j] == '\r' || line[j] == '\n') + { + while (line[j]) + fputc(line[j++], c); + } + else + { + fputc('\"', c); + while (line[j] && line[j] != '\r' && line[j] != '\n') + { + if (line[j] == '\t') + fputc(' ', c); + else if (line[j] == '\"') + { + fputc('\\', c); + fputc(line[j], c); + } + else + fputc(line[j], c); + j++; + } + fputs("\\n\"\n", c); + } + } + fputs(";\n", c); + fclose(s); + } + + fputs("#define R_PARTSET_BUILTINS ", h); + for (i = 0; effects[i]; i++) + { + fprintf(h, "{\"%s\", &particle_set_%s},", effects[i], effects[i]); + } + fputs("\n", h); + + fclose(h); + fclose(c); +} diff --git a/engine/partcfgs/h2part.cfg b/engine/partcfgs/h2part.cfg new file mode 100644 index 000000000..28ef14570 --- /dev/null +++ b/engine/partcfgs/h2part.cfg @@ -0,0 +1,228 @@ +r_part ce_white_smoke_05 +{ + model models/whtsmk1.spr 0 0 20 0.5 +} +r_part ce_white_smoke_10 +{ + model models/whtsmk1.spr 0 0 10 0.5 +} +r_part ce_white_smoke_15 +{ + model models/whtsmk1.spr 0 0 6.666 0.5 +} +r_part ce_white_smoke_20 +{ + model models/whtsmk1.spr 0 0 5 0.5 +} +r_part ce_white_smoke_50 +{ + model models/whtsmk1.spr 0 0 2 0.5 +} + +r_part ce_bluespark +{ + model models/bspark.spr 0 0 20 1 +} +r_part ce_yellowspark +{ + model models/spark.spr 0 0 20 1 +} +r_part ce_sm_circle_exp +{ + model models/fcircle.spr 0 0 20 1 +} +r_part ce_bg_circle_exp +{ + model models/xplod29.spr 0 0 20 1 +} +r_part ce_sm_white_flash +{ + model models/sm_white.spr 0 0 20 1 +} +r_part ce_white_flash +{ + model models/gryspt.spr 0 0 20 0.4 +} +r_part ce_yellowred_flash +{ + model models/yr_flsh.spr 0 0 20 0.4 +} +r_part ce_blue_flash +{ + model models/bluflash.spr 0 0 20 0.4 +} +r_part ce_sm_blue_flash +{ + model models/sm_blue.spr 0 0 20 0.4 +} +r_part ce_red_flash +{ + model models/redspt.spr 0 0 20 0.4 +} +r_part ce_sm_explosion +{ + model models/sm_expld.spr 0 0 20 1 +} +r_part ce_lg_explosion +{ + model models/bg_expld.spr 0 0 20 1 +} +r_part ce_floor_explosion +{ + model models/fl_expld.spr 0 0 20 1 +} +r_part ce_rider_death +{ +} +r_part ce_blue_explosion +{ + model models/xpspblue.spr 0 0 20 1 +} +r_part ce_green_smoke_05 +{ + model models/grnsmk1.spr 0 0 20 0.5 +} +r_part ce_green_smoke_10 +{ + model models/grnsmk1.spr 0 0 10 0.5 +} +r_part ce_green_smoke_15 +{ + model models/grnsmk1.spr 0 0 6.666 0.5 +} +r_part ce_green_smoke_20 +{ + model models/grnsmk1.spr 0 0 5 0.5 +} +// ce_grey_smoke +r_part ce_grey_smoke_15 +{ + model models/grysmk1.spr 0 0 6.666 0.5 +} +r_part ce_red_smoke +{ + model models/redsmk1.spr 0 0 6.666 0.5 +} +r_part ce_slow_white_smoke +{ + model models/whtsmk1.spr 0 0 20 0.5 +} +r_part ce_redspark +{ + model models/rspark.spr 0 0 20 1 +} +r_part ce_greenspark +{ + model models/gspark.spr 0 0 20 1 +} +r_part ce_telesmk1 +{ + model models/telesmk1.spr 0 0 15 1 +} +r_part ce_telesmk2 +{ + model models/telesmk2.spr 0 0 15 1 +} +r_part ce_icehit +{ + model models/icehit.spr 0 0 20 0.5 +} +r_part ce_medusa_hit +{ + model models/medhit.spr 0 0 20 1 +} +r_part ce_mezzo_reflect +{ + model models/mezzoref.spr 0 0 20 1 +} +r_part ce_floor_explosion2 +{ + model models/flrexpl2.spr 0 0 20 1 +} +r_part ce_xbow_explosion +{ + model models/xbowexpl.spr 0 0 20 1 +} +r_part ce_new_explosion +{ + model models/gen_expl.spr 0 0 20 1 +} +r_part ce_magic_missile_explosion +{ + model models/mm_explod.spr 0 0 20 1 +} +// ce_ghost +r_part ce_bone_explosion +{ + model models/bonexpld.spr 0 0 20 1 +} +// ce_redcloud +r_part ce_teleporterpuffs +{ +// model models/telesmk2.spr 0 0 20 1 +} +// ce_teleporterbody +// ce_boneshard +// ce_boneshrapnel +r_part ce_flamestream +{ + model models/flamestr.spr 0 0 20 1 +} +// ce_snow, +// ce_gravitywell +r_part ce_bldrn_expl +{ + model models/xplsn_1.spr 0 0 20 1 +} +// ce_acid_muzzfl +r_part ce_acid_hit +{ + model models/axplsn_2.spr 0 0 20 1 +} +r_part ce_firewall_small +{ + model models/firewal1.spr 0 0 20 1 +} +r_part ce_firewall_medium +{ + model models/firewal5.spr 0 0 20 1 +} +r_part ce_firewall_large +{ + model models/firewal4.spr 0 0 20 1 +} +r_part ce_lball_expl +{ + model models/Bluexp3.spr 0 0 20 1 +} +r_part ce_acid_splat +{ + model models/axplsn_1.spr 0 0 20 1 +} +r_part ce_acid_expl +{ + model models/axplsn_5.spr 0 0 20 1 +} +r_part ce_fboom +{ + model models/fboom.spr 0 0 20 1 +} +// ce_chunk +r_part ce_bomb +{ + model models/pow.spr 0 0 20 1 +} +r_part ce_brn_bounce +{ + model models/spark.spr 0 0 20 1 +} +r_part ce_lshock +{ + model models/vorpshok.mdl 0 0 20 1 +} +// ce_flamewall +// ce_flamewall2 +r_part ce_floor_explosion3 +{ + model models/biggy.spr 0 0 20 1 +} diff --git a/engine/partcfgs/spikeset.cfg b/engine/partcfgs/spikeset.cfg index cba452520..a1ac530e7 100644 --- a/engine/partcfgs/spikeset.cfg +++ b/engine/partcfgs/spikeset.cfg @@ -3,9 +3,27 @@ // and some others I probably forgot to mention ///////////////////////////////////////////////// //rocket trails (derived from purplehaze's, with only minor tweeks) + +r_part rocketsmoke +{ + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 + step 8 + scale 7.5 + alpha 0.8 + die 2 + randomvel 3 + rgb 10 10 10 + blend modulate + spawnmode spiral + scalefactor 1 + spawnvel 5 +} + r_part rockettrail { - texture "particles/smoke.tga" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 step 4 scale 30 alpha 0.3 @@ -17,11 +35,13 @@ r_part rockettrail gravity -25 scalefactor 1 assoc rocketsmoke + spawnvel 10 } r_part t_rocket { - texture "particles/rfire" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 step 2 scale 10 alpha 0.6 @@ -34,24 +54,10 @@ r_part t_rocket scaledelta -10 } -r_part rocketsmoke -{ - texture "particles/rtrail" - step 8 - scale 7.5 - alpha 0.8 - die 2 - randomvel 3 - rgb 10 10 10 - blend modulate - spawnmode spiral - scalefactor 1 - spawnvel 10 -} - r_part rockettail { - texture "particles/rtrail" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 step 7 scale 10 alpha 0.3 @@ -65,7 +71,8 @@ r_part rockettail r_part t_altrocket { - texture "particles/rtrail" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 step 4 scale 10 alpha 0.3 @@ -160,7 +167,8 @@ r_part te_railtrail r_part shortfume { - texture "particles/smoke" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 scale 15 scaledelta 20 alpha 0.5 @@ -173,7 +181,8 @@ r_part shortfume r_part t_grenade { - texture "particles/smoke" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 step 24 scale 16 scaledelta 4 @@ -191,7 +200,8 @@ r_part t_grenade //cool's blood trails (cos they're cooler) r_part t_gib { - texture "particles/blood" + texture "particles/fteparticlefont.tga" + tcoords 1 1 63 63 256 2 64 step 32 scale 64 alpha 0.6 @@ -209,7 +219,8 @@ r_part t_gib r_part t_zomgib { - texture "particles/blood" + texture "particles/fteparticlefont.tga" + tcoords 1 1 63 63 256 2 64 step 64 scale 64 alpha 0.6 @@ -227,7 +238,8 @@ r_part t_zomgib r_part t_tracer { - texture "particles/tracer" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 scale 15 step 5 alpha 0.6 @@ -241,7 +253,8 @@ r_part t_tracer r_part t_tracer2 { - texture "particles/tracer" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 scale 15 step 5 alpha 0.6 @@ -255,7 +268,8 @@ r_part t_tracer2 r_part t_tracer3 { - texture "particles/tracer" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 scale 10 scaledelta -10 step 5 @@ -273,7 +287,8 @@ r_part t_tracer3 //qw blood r_part te_lightningblood { - texture "particles/bloodtrail" + texture "particles/fteparticlefont.tga" + tcoords 193 97 255 159 256 count 3 scale 20 alpha 0.4 @@ -291,7 +306,8 @@ r_part te_lightningblood //qw blood r_part te_blood { - texture "particles/blood" + texture "particles/fteparticlefont.tga" + tcoords 193 97 255 159 256 count 10 scale 10 alpha 0.3 @@ -308,7 +324,8 @@ r_part te_blood //nq blood r_part pe_73 { - texture "particles/blood" + texture "particles/fteparticlefont.tga" + tcoords 193 97 255 159 256 count 1 scale 20 alpha 0.3 @@ -327,7 +344,8 @@ r_part pe_73 r_part ember { count 1 - texture "particles/explosion" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 rgb 255 128 76 alpha 0 scale 15 @@ -338,20 +356,21 @@ r_part ember blend add randomvel 5 veladd 1 - rampmode delta //fade it in then out. - ramp 0 0 0 -0.5 0 - ramp 0 0 0 0.1 0 - ramp 0 0 0 0.1 0 - ramp 0 0 0 0.1 0 - ramp 0 0 0 0.1 0 - ramp 0 0 0 0.1 0 + rampmode delta + ramp 0 0 0 -0.5 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 + ramp 0 0 0 0.1 0 } //the bits that fly off r_part expgib { cliptype expgib - texture "particles/explosion" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 alpha 0 count 16 die 1 @@ -366,7 +385,8 @@ r_part expgib //the heart of the explosion r_part te_explosion { - texture "particles/explosion" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 count 1 scale 200 scalefactor 1 @@ -380,7 +400,8 @@ r_part te_explosion r_part gunshotsmoke { - texture "particles/smoke" + texture "particles/fteparticlefont.tga" + tcoords 1 65 31 95 256 8 32 count 3 scale 25 scalefactor 1 @@ -397,7 +418,8 @@ r_part gunshotsmoke r_part te_gunshot { type texturedspark - texture "ball" + texture "particles/fteparticlefont.tga" + tcoords 1 65 31 95 256 8 32 count 3 scale 2 scalefactor 1 @@ -416,7 +438,8 @@ r_part te_gunshot r_part spikecore { - texture "ball" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 count 1 scale 1 scalefactor 1 @@ -446,7 +469,8 @@ r_part te_spike r_part te_lavasplash { - texture "default" + texture "particles/fteparticlefont.tga" + tcoords 129 1 191 63 256 count 654 scale 15 alpha 0.7 @@ -465,7 +489,8 @@ r_part te_lavasplash //two rings moving upwards, costs less r_part teleportsplashdown { - texture "textures/smoke" + texture "particles/fteparticlefont.tga" + tcoords 193 1 255 63 256 count 32 scale 32 scalefactor 1 @@ -479,7 +504,8 @@ r_part teleportsplashdown } r_part te_teleportsplash { - texture "textures/smoke" + texture "particles/fteparticlefont.tga" + tcoords 193 1 255 63 256 count 32 scale 32 scalefactor 1 @@ -496,7 +522,8 @@ r_part te_teleportsplash //flame effect r_part cu_flame { - texture "particles/flame" + texture "particles/fteparticlefont.tga" + tcoords 129 1 191 63 256 count 1024 scale 0.4 scalerand 6 @@ -515,7 +542,8 @@ r_part cu_flame //flame effect r_part cu_torch { - texture "particles/flame" + texture "particles/fteparticlefont.tga" + tcoords 129 1 191 63 256 count 256 scale 3 scalefactor 1 @@ -532,7 +560,8 @@ r_part cu_torch r_part explodesprite { - texture "particles/flame" + texture "particles/fteparticlefont.tga" + tcoords 97 97 191 191 256 count 180 scale 70 scaledelta -140 @@ -551,7 +580,8 @@ r_part explodesprite //you'll probably never see this one r_part ef_entityparticles { - texture "j" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 count 1 scale 15 alpha 0.2 @@ -564,7 +594,8 @@ r_part ef_entityparticles // emp effect, based off of purplehaze's idea r_part empshocktrail { - texture "particles/spark" + texture "particles/fteparticlefont.tga" + tcoords 193 1 255 63 256 step 3.2 scale 3 alpha 0.7 @@ -577,7 +608,8 @@ r_part empshocktrail r_part empcore { - texture "particles/flame" + texture "particles/fteparticlefont.tga" + tcoords 193 1 255 63 256 count 90 scale 55 scaledelta -110 @@ -596,7 +628,8 @@ r_part empcore r_part empflash { die 0.1 - texture "particles/flash" + texture "particles/fteparticlefont.tga" + tcoords 193 1 255 63 256 alpha 1 count 1 scale 400 @@ -610,7 +643,8 @@ r_part empflash r_part te_tarexplosion { - texture "particles/emp" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 count 120 scale 35 die 0.75 @@ -619,11 +653,11 @@ r_part te_tarexplosion rampmode delta ramp -32 0 0 0 ramp -32 0 0 0 - ramp -32 0 0 2 + ramp -32 0 0 2 friction -0.9 blend add spawnmode uniformcircle - spawnorg 24 0 + spawnorg 24 0 spawnvel 280 0 scalefactor 1 emit empshocktrail @@ -633,7 +667,8 @@ r_part te_tarexplosion r_part pe_default { - texture "particles/quake" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 count 1 scale 4 veladd 15 @@ -646,7 +681,8 @@ r_part pe_default r_part pe_defaulttrail { - texture "particles/quake" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 step 12 die 1 scale 10 @@ -658,7 +694,8 @@ r_part pe_defaulttrail r_part pe_pointfile { - texture "particles/quake" + texture "particles/fteparticlefont.tga" + tcoords 1 97 95 191 256 count 1 scale 50 die 30 diff --git a/engine/qclib/hash.c b/engine/qclib/hash.c index dff0dc19a..44ac211d3 100644 --- a/engine/qclib/hash.c +++ b/engine/qclib/hash.c @@ -85,6 +85,34 @@ void *Hash_GetKey(hashtable_t *table, unsigned int key) } return NULL; } +/*Does _NOT_ support items that are added with two names*/ +void *Hash_GetNextKey(hashtable_t *table, unsigned int key, void *old) +{ + unsigned int bucknum = key%table->numbuckets; + bucket_t *buck; + + buck = table->bucket[bucknum]; + + while(buck) + { + if (buck->data == old) //found the old one + break; + buck = buck->next; + } + if (!buck) + return NULL; + + buck = buck->next;//don't return old + while(buck) + { + if (buck->key.value == key) + return buck->data; + + buck = buck->next; + } + return NULL; +} +/*Does _NOT_ support items that are added with two names*/ void *Hash_GetNext(hashtable_t *table, const char *name, void *old) { unsigned int bucknum = Hash_Key(name, table->numbuckets); @@ -94,12 +122,9 @@ void *Hash_GetNext(hashtable_t *table, const char *name, void *old) while(buck) { - if (!STRCMP(name, buck->key.string)) - { - if (buck->data == old) //found the old one + if (buck->data == old) //found the old one +// if (!STRCMP(name, buck->key.string)) break; - } - buck = buck->next; } if (!buck) @@ -115,6 +140,7 @@ void *Hash_GetNext(hashtable_t *table, const char *name, void *old) } return NULL; } +/*Does _NOT_ support items that are added with two names*/ void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old) { unsigned int bucknum = Hash_KeyInsensative(name, table->numbuckets); @@ -124,9 +150,9 @@ void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old) while(buck) { - if (!STRCMP(name, buck->key.string)) + if (buck->data == old) //found the old one { - if (buck->data == old) //found the old one +// if (!stricmp(name, buck->key.string)) break; } @@ -138,7 +164,7 @@ void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old) buck = buck->next;//don't return old while(buck) { - if (!STRCMP(name, buck->key.string)) + if (!stricmp(name, buck->key.string)) return buck->data; buck = buck->next; diff --git a/engine/qclib/hash.h b/engine/qclib/hash.h index 951399629..e07c17d22 100644 --- a/engine/qclib/hash.h +++ b/engine/qclib/hash.h @@ -28,6 +28,7 @@ void *Hash_GetInsensative(hashtable_t *table, const char *name); void *Hash_GetKey(hashtable_t *table, unsigned int key); void *Hash_GetNext(hashtable_t *table, const char *name, void *old); void *Hash_GetNextInsensative(hashtable_t *table, const char *name, void *old); +void *Hash_GetNextKey(hashtable_t *table, unsigned int key, void *old); void *Hash_Add(hashtable_t *table, const char *name, void *data, bucket_t *buck); void *Hash_AddInsensative(hashtable_t *table, const char *name, void *data, bucket_t *buck); void Hash_Remove(hashtable_t *table, const char *name); diff --git a/engine/server/net_preparse.c b/engine/server/net_preparse.c index d7c23655e..30acdb3b4 100644 --- a/engine/server/net_preparse.c +++ b/engine/server/net_preparse.c @@ -562,6 +562,7 @@ qboolean pp_root_decide(enum protocol_type *pt, union protocol_data *pd) static sizebuf_t *writedest; static client_t *cldest; +struct netprim_s *destprim; static int majortype; static int minortype; static int protocollen; @@ -752,12 +753,12 @@ void NPP_NQFlush(void) vec3_t org; coorddata cd; - memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*0], writedest->prim.coordsize); - org[0] = MSG_FromCoord(cd, writedest->prim.coordsize); - memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*1], writedest->prim.coordsize); - org[1] = MSG_FromCoord(cd, writedest->prim.coordsize); - memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*2], writedest->prim.coordsize); - org[2] = MSG_FromCoord(cd, writedest->prim.coordsize); + memcpy(&cd, &buffer[multicastpos+destprim->coordsize*0], destprim->coordsize); + org[0] = MSG_FromCoord(cd, destprim->coordsize); + memcpy(&cd, &buffer[multicastpos+destprim->coordsize*1], destprim->coordsize); + org[1] = MSG_FromCoord(cd, destprim->coordsize); + memcpy(&cd, &buffer[multicastpos+destprim->coordsize*2], destprim->coordsize); + org[2] = MSG_FromCoord(cd, destprim->coordsize); SV_MulticastProtExt(org, multicasttype, pr_global_struct->dimension_send, requireextension, 0); } @@ -791,7 +792,7 @@ void NPP_NQCheckDest(int dest) NPP_NQFlush(); } cldest = cl; - + destprim = &cldest->netchan.message.prim; } else { @@ -802,6 +803,7 @@ void NPP_NQCheckDest(int dest) NPP_NQFlush(); } writedest = ndest; + destprim = &writedest->prim; } } void NPP_AddData(void *data, int len) @@ -852,7 +854,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case svc_temp_entity: break; case svc_setangle: - protocollen = sizeof(qbyte)*4; + protocollen = sizeof(qbyte) + destprim->anglesize*3; break; case svc_setview: protocollen = sizeof(qbyte)*1 + sizeof(short); @@ -907,7 +909,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) ignoreprotocol = true; break; case 51: - protocollen = 2; + protocollen = 3; ignoreprotocol = true; break; default: @@ -922,7 +924,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) switch(majortype) { case svc_sound: - protocollen = 5+writedest->prim.coordsize*3; + protocollen = 5+destprim->coordsize*3; if (data & NQSND_VOLUME) protocollen++; if (data & NQSND_ATTENUATION) @@ -945,7 +947,7 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_LIGHTNING3: multicastpos=4; multicasttype=MULTICAST_PHS; - protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*2; + protocollen = destprim->coordsize*6+sizeof(short)+sizeof(qbyte)*2; break; case TE_GUNSHOT: multicastpos=3; @@ -954,14 +956,14 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) //emit it here and we don't need to remember to play with temp_entity later NPP_AddData(&data, sizeof(qbyte)); data = 1; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*3; + protocollen = destprim->coordsize*3+sizeof(qbyte)*3; break; case TE_EXPLOSION: case TE_SPIKE: case TE_SUPERSPIKE: multicastpos=2; multicasttype=MULTICAST_PHS_R; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; + protocollen = destprim->coordsize*3+sizeof(qbyte)*2; break; case TE_TAREXPLOSION: case TE_WIZSPIKE: @@ -970,25 +972,25 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_TELEPORT: multicastpos=2; multicasttype=MULTICAST_PVS; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; + protocollen = destprim->coordsize*3+sizeof(qbyte)*2; break; case TE_EXPLOSION3_NEH: - protocollen = sizeof(qbyte) + writedest->prim.coordsize*6; + protocollen = sizeof(qbyte) + destprim->coordsize*6; ignoreprotocol = true; break; case TENQ_EXPLOSION2: - protocollen = sizeof(qbyte)*4 + writedest->prim.coordsize*3; + protocollen = sizeof(qbyte)*4 + destprim->coordsize*3; multicastpos=2; multicasttype=MULTICAST_PHS_R; break; case TE_EXPLOSIONSMALL2: data = TE_EXPLOSION; - protocollen = sizeof(qbyte)*2 + writedest->prim.coordsize*3; + protocollen = sizeof(qbyte)*2 + destprim->coordsize*3; multicastpos=2; multicasttype=MULTICAST_PHS; break; case TE_RAILTRAIL: - protocollen = writedest->prim.coordsize*6+sizeof(qbyte)*1; + protocollen = destprim->coordsize*6+sizeof(qbyte)*1; multicastpos=2; multicasttype=MULTICAST_PHS; break; @@ -1000,42 +1002,42 @@ void NPP_NQWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TEH2_STREAM_ICECHUNKS: case TEH2_STREAM_GAZE: case TEH2_STREAM_FAMINE: - protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*(2+2); + protocollen = destprim->coordsize*6+sizeof(short)+sizeof(qbyte)*(2+2); multicastpos = 8; multicasttype=MULTICAST_PHS; break; case TEH2_STREAM_COLORBEAM: - protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*(3+2); + protocollen = destprim->coordsize*6+sizeof(short)+sizeof(qbyte)*(3+2); multicastpos = 8; multicasttype=MULTICAST_PHS; break; case TEDP_FLAMEJET: //TE_FLAMEJET - protocollen = writedest->prim.coordsize*6 +sizeof(qbyte)*3; + protocollen = destprim->coordsize*6 +sizeof(qbyte)*3; multicastpos = 2; multicasttype=MULTICAST_PVS; break; case TEDP_TEI_G3: - protocollen = writedest->prim.coordsize*9+sizeof(qbyte)*2; + protocollen = destprim->coordsize*9+sizeof(qbyte)*2; multicastpos = 2; multicasttype=MULTICAST_PHS; break; case TEDP_SMOKE: - protocollen = writedest->prim.coordsize*6+sizeof(qbyte)*3; + protocollen = destprim->coordsize*6+sizeof(qbyte)*3; multicastpos = 2; multicasttype=MULTICAST_PHS; break; case TEDP_TEI_BIGEXPLOSION: - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; + protocollen = destprim->coordsize*3+sizeof(qbyte)*2; multicastpos = 2; multicasttype=MULTICAST_PHS; break; case TEDP_TEI_PLASMAHIT: - protocollen = writedest->prim.coordsize*6+sizeof(qbyte)*3; + protocollen = destprim->coordsize*6+sizeof(qbyte)*3; multicastpos = 2; multicasttype=MULTICAST_PHS; break; @@ -1150,31 +1152,28 @@ void NPP_NQWriteAngle(int dest, float in) //replacement write func (nq to qw) Con_Printf("NQWriteAngle: Messages should start with WriteByte\n"); #ifdef NQPROT - if (dest == MSG_ONE) + if (cldest) { - client_t *cl = Write_GetClient(); - if (!cl) - { - Con_Printf("msg_entity: not a client\n"); + if (cldest->protocol == SCP_BAD) return; - } - else + else if (!ISQWCLIENT(cldest)) { - if (cl->protocol == SCP_BAD) - return; - else if (!ISQWCLIENT(cl)) - { - ClientReliableCheckBlock(cl, sizeof(char)); - ClientReliableWrite_Angle(cl, in); - return; - } + ClientReliableCheckBlock(cldest, sizeof(char)); + ClientReliableWrite_Angle(cldest, in); + return; } } else MSG_WriteAngle (NQWriteDest(dest), in); #endif - NPP_AddData(&data, sizeof(char)); + if (destprim->anglesize==2) + { + coorddata cd = MSG_ToAngle(in, destprim->anglesize); + NPP_AddData(&cd.b2, sizeof(cd.b2)); + } + else + NPP_AddData(&data, sizeof(char)); NPP_NQCheckFlush(); } void NPP_NQWriteCoord(int dest, float in) //replacement write func (nq to qw) @@ -1210,7 +1209,7 @@ void NPP_NQWriteCoord(int dest, float in) //replacement write func (nq to qw) MSG_WriteCoord (NQWriteDest(dest), in); #endif - if (writedest->prim.coordsize==4) + if (destprim->coordsize==4) { dataf = LittleFloat(dataf); NPP_AddData(&dataf, sizeof(float)); @@ -1496,7 +1495,7 @@ void NPP_QWFlush(void) NPP_AddData(&svc, sizeof(qbyte)); for (i = 0; i < 3; i++) { - if (writedest->prim.coordsize == 4) + if (destprim->coordsize == 4) NPP_AddData(&org[i], sizeof(float)); else { @@ -1554,12 +1553,12 @@ void NPP_QWFlush(void) vec3_t org; coorddata cd; - memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*0], writedest->prim.coordsize); - org[0] = MSG_FromCoord(cd, writedest->prim.coordsize); - memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*1], writedest->prim.coordsize); - org[1] = MSG_FromCoord(cd, writedest->prim.coordsize); - memcpy(&cd, &buffer[multicastpos+writedest->prim.coordsize*2], writedest->prim.coordsize); - org[2] = MSG_FromCoord(cd, writedest->prim.coordsize); + memcpy(&cd, &buffer[multicastpos+destprim->coordsize*0], destprim->coordsize); + org[0] = MSG_FromCoord(cd, destprim->coordsize); + memcpy(&cd, &buffer[multicastpos+destprim->coordsize*1], destprim->coordsize); + org[1] = MSG_FromCoord(cd, destprim->coordsize); + memcpy(&cd, &buffer[multicastpos+destprim->coordsize*2], destprim->coordsize); + org[2] = MSG_FromCoord(cd, destprim->coordsize); qwsize = sv.multicast.cursize; sv.multicast.cursize = 0; @@ -1608,6 +1607,7 @@ void NPP_QWCheckDest(int dest) NPP_QWFlush(); } writedest = ndest; + destprim = &writedest->prim; } } @@ -1649,7 +1649,7 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case svc_temp_entity: break; case svc_setangle: - protocollen = sizeof(qbyte)*4; + protocollen = sizeof(qbyte) + destprim->anglesize*3; break; case svc_setview: protocollen = sizeof(qbyte)*1 + sizeof(short); @@ -1730,13 +1730,13 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_LIGHTNING3: multicastpos=4; multicasttype=MULTICAST_PHS; - protocollen = writedest->prim.coordsize*6+sizeof(short)+sizeof(qbyte)*2; + protocollen = destprim->coordsize*6+sizeof(short)+sizeof(qbyte)*2; break; case TEQW_BLOOD: //needs to be converted to a particle case TE_GUNSHOT: //needs qbyte 2 removed multicastpos=3; multicasttype=MULTICAST_PVS; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*3; + protocollen = destprim->coordsize*3+sizeof(qbyte)*3; break; case TEQW_LIGHTNINGBLOOD: case TE_EXPLOSION: @@ -1744,7 +1744,7 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_SUPERSPIKE: multicastpos=2; multicasttype=MULTICAST_PHS_R; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; + protocollen = destprim->coordsize*3+sizeof(qbyte)*2; break; case TE_TAREXPLOSION: case TE_WIZSPIKE: @@ -1753,12 +1753,12 @@ void NPP_QWWriteByte(int dest, qbyte data) //replacement write func (nq to qw) case TE_TELEPORT: multicastpos=2; multicasttype=MULTICAST_PVS; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*2; + protocollen = destprim->coordsize*3+sizeof(qbyte)*2; break; case TE_RAILTRAIL: multicastpos=1; multicasttype=MULTICAST_PVS; - protocollen = writedest->prim.coordsize*3+sizeof(qbyte)*1; + protocollen = destprim->coordsize*3+sizeof(qbyte)*1; break; default: protocollen = sizeof(buffer); @@ -1823,7 +1823,7 @@ void NPP_QWWriteLong(int dest, long data) //replacement write func (nq to qw) } void NPP_QWWriteAngle(int dest, float in) //replacement write func (nq to qw) { - if (writedest->prim.anglesize==1) + if (destprim->anglesize==1) { char data = (int)(in*256/360) & 255; NPP_QWWriteChar(dest, data); @@ -1836,7 +1836,7 @@ void NPP_QWWriteAngle(int dest, float in) //replacement write func (nq to qw) } void NPP_QWWriteCoord(int dest, float in) //replacement write func (nq to qw) { - if (writedest->prim.coordsize==4) + if (destprim->coordsize==4) { NPP_QWWriteFloat(dest, in); } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 6155c144a..9b235a2ab 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -674,8 +674,8 @@ void PR_LoadGlabalStruct(void) SV_QCStatName(ev_float, "cnt_invincibility", STAT_H2_CNT_INVINCIBILITY); SV_QCStatName(ev_float, "artifact_active", STAT_H2_ARTIFACT_ACTIVE); SV_QCStatName(ev_float, "artifact_low", STAT_H2_ARTIFACT_LOW); - SV_QCStatName(ev_float, "movetype", STAT_H2_MOVETYPE); - SV_QCStatName(ev_entity, "cameramode", STAT_H2_CAMERAMODE); + SV_QCStatName(ev_float, "movetype", STAT_H2_MOVETYPE); /*normally used to change the roll when flying*/ + SV_QCStatName(ev_entity, "cameramode", STAT_H2_CAMERAMODE); /*locks view in place when set*/ SV_QCStatName(ev_float, "hasted", STAT_H2_HASTED); SV_QCStatName(ev_float, "inventory", STAT_H2_INVENTORY); SV_QCStatName(ev_float, "rings_active", STAT_H2_RINGS_ACTIVE); @@ -699,8 +699,7 @@ void PR_LoadGlabalStruct(void) SV_QCStatName(ev_string, "puzzle_inv8", STAT_H2_PUZZLE8); SV_QCStatName(ev_float, "max_health", STAT_H2_MAXHEALTH); SV_QCStatName(ev_float, "max_mana", STAT_H2_MAXMANA); - SV_QCStatName(ev_float, "flags", STAT_H2_FLAGS); - SV_QCStatName(ev_float, "playerclass", STAT_H2_PLAYERCLASS); + SV_QCStatName(ev_float, "flags", STAT_H2_FLAGS); /*to show the special abilities on the sbar*/ SV_QCStatPtr(ev_integer, &h2infoplaque[0], STAT_H2_OBJECTIVE1); SV_QCStatPtr(ev_integer, &h2infoplaque[1], STAT_H2_OBJECTIVE2); @@ -1073,6 +1072,7 @@ void PR_Init(void) #endif } +void SV_RegisterH2CustomTents(void); void Q_InitProgs(void) { int i, i2; @@ -1430,6 +1430,8 @@ void Q_InitProgs(void) sv.world.edict_size = PR_InitEnts(svprogfuncs, sv.world.max_edicts); + SV_RegisterH2CustomTents(); + #ifdef USEODE World_Physics_Start(&sv.world); #endif @@ -1780,6 +1782,92 @@ static void SV_Effect(vec3_t org, int mdlidx, int startframe, int endframe, int } +static int SV_CustomTEnt_Register(char *effectname, int nettype, float *stain_rgb, float stain_radius, float *dl_rgb, float dl_radius, float dl_time, float *dl_fade) +{ + int i; + for (i = 0; i < 255; i++) + { + if (!*sv.customtents[i].particleeffecttype) + break; + if (!strcmp(effectname, sv.customtents[i].particleeffecttype)) + break; + } + if (i == 255) + { + Con_Printf("Too many custom effects\n"); + return -1; + } + + Q_strncpyz(sv.customtents[i].particleeffecttype, effectname, sizeof(sv.customtents[i].particleeffecttype)); + sv.customtents[i].netstyle = nettype; + + if (nettype & CTE_STAINS) + { + VectorCopy(stain_rgb, sv.customtents[i].stain); + sv.customtents[i].radius = stain_radius; + } + if (nettype & CTE_GLOWS) + { + sv.customtents[i].dlightrgb[0] = dl_rgb[0]*255; + sv.customtents[i].dlightrgb[1] = dl_rgb[1]*255; + sv.customtents[i].dlightrgb[2] = dl_rgb[2]*255; + sv.customtents[i].dlightradius = dl_radius/4; + sv.customtents[i].dlighttime = dl_time*16; + if (nettype & CTE_CHANNELFADE) + { + sv.customtents[i].dlightcfade[0] = dl_fade[0]*64; + sv.customtents[i].dlightcfade[1] = dl_fade[1]*64; + sv.customtents[i].dlightcfade[2] = dl_fade[2]*64; + } + } + + return i; +} + +static void SV_CustomTEnt_Spawn(int index, float *org, float *org2, int count, float *dir) +{ + int type; + if (index < 0 || index >= 255) + return; + + MSG_WriteByte(&sv.multicast, svcfte_customtempent); + MSG_WriteByte(&sv.multicast, index); + MSG_WriteCoord(&sv.multicast, org[0]); + MSG_WriteCoord(&sv.multicast, org[1]); + MSG_WriteCoord(&sv.multicast, org[2]); + + type = sv.customtents[index].netstyle; + if (type & CTE_ISBEAM) + { + MSG_WriteCoord(&sv.multicast, org2[0]); + MSG_WriteCoord(&sv.multicast, org2[1]); + MSG_WriteCoord(&sv.multicast, org2[2]); + } + else + { + if (type & CTE_CUSTOMCOUNT) + { + MSG_WriteByte(&sv.multicast, count); + } + if (type & CTE_CUSTOMVELOCITY) + { + MSG_WriteCoord(&sv.multicast, dir[0]); + MSG_WriteCoord(&sv.multicast, dir[1]); + MSG_WriteCoord(&sv.multicast, dir[2]); + } + else if (type & CTE_CUSTOMDIRECTION) + { + vec3_t norm; + VectorNormalize2(dir, norm); + MSG_WriteDir(&sv.multicast, norm); + } + } + + SV_MulticastProtExt (org, MULTICAST_PVS, pr_global_struct->dimension_send, PEXT_CUSTOMTEMPEFFECTS, 0); //now send the new multicast to all that will. +} + + + int externcallsdepth; void PR_MoveParms(int progs1, int progs2); //from 2 to 1 @@ -2258,7 +2346,7 @@ centerprint(clientent, value) */ void PF_centerprint_Internal (int entnum, qboolean plaque, char *s) { - client_t *cl, *sp; + client_t *cl; int slen; #ifdef SERVER_DEMO_PLAYBACK @@ -7142,8 +7230,414 @@ void PF_h2updateinfoplaque(progfuncs_t *prinst, struct globalvars_s *pr_globals) else h2infoplaque[idx/32] ^= 1<<(idx&31); } + +enum +{ + ce_none, + ce_rain, + ce_fountain, + ce_quake, + ce_white_smoke, + ce_bluespark, + ce_yellowspark, + ce_sm_circle_exp, + ce_bg_circle_exp, + ce_sm_white_flash, + ce_white_flash = 10, + ce_yellowred_flash, + ce_blue_flash, + ce_sm_blue_flash, + ce_red_flash, + ce_sm_explosion, + ce_lg_explosion, + ce_floor_explosion, + ce_rider_death, + ce_blue_explosion, + ce_green_smoke = 20, + ce_grey_smoke, + ce_red_smoke, + ce_slow_white_smoke, + ce_redspark, + ce_greenspark, + ce_telesmk1, + ce_telesmk2, + ce_icehit, + ce_medusa_hit, + ce_mezzo_reflect = 30, + ce_floor_explosion2, + ce_xbow_explosion, + ce_new_explosion, + ce_magic_missile_explosion, + ce_ghost, + ce_bone_explosion, + ce_redcloud, + ce_teleporterpuffs, + ce_teleporterbody, + ce_boneshard = 40, + ce_boneshrapnel, + ce_flamestream, + ce_snow, + ce_gravitywell, + ce_bldrn_expl, + ce_acid_muzzfl, + ce_acid_hit, + ce_firewall_small, + ce_firewall_medium, + ce_firewall_large = 50, + ce_lball_expl, + ce_acid_splat, + ce_acid_expl, + ce_fboom, + ce_chunk, + ce_bomb, + ce_brn_bounce, + ce_lshock, + ce_flamewall, + ce_flamewall2 = 60, + ce_floor_explosion3, + ce_onfire, + + + /*internal effects, here for indexes*/ + + ce_teleporterbody_1, /*de-sheeped*/ + ce_white_smoke_05, + ce_white_smoke_10, + ce_white_smoke_15, + ce_white_smoke_20, + ce_white_smoke_50, + ce_green_smoke_05, + ce_green_smoke_10, + ce_green_smoke_15, + ce_green_smoke_20, + ce_grey_smoke_15, + ce_grey_smoke_100, + + ce_max +}; +int h2customtents[ce_max]; +void SV_RegisterH2CustomTents(void) +{ + int i; + for (i = 0; i < ce_max; i++) + h2customtents[i] = -1; + + if (progstype == PROG_H2) + { + +// ce_rain +// ce_fountain + h2customtents[ce_quake] = SV_CustomTEnt_Register("ce_quake", 0, NULL, 0, NULL, 0, 0, NULL); +// ce_white_smoke + h2customtents[ce_bluespark] = SV_CustomTEnt_Register("ce_bluespark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_yellowspark] = SV_CustomTEnt_Register("ce_yellowspark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_circle_exp] = SV_CustomTEnt_Register("ce_sm_circle_exp", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bg_circle_exp] = SV_CustomTEnt_Register("ce_bg_circle_exp", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_white_flash] = SV_CustomTEnt_Register("ce_sm_white_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_flash] = SV_CustomTEnt_Register("ce_white_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_yellowred_flash] = SV_CustomTEnt_Register("ce_yellowred_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_blue_flash] = SV_CustomTEnt_Register("ce_blue_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_blue_flash] = SV_CustomTEnt_Register("ce_sm_blue_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_red_flash] = SV_CustomTEnt_Register("ce_red_flash", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_sm_explosion] = SV_CustomTEnt_Register("ce_sm_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_lg_explosion] = SV_CustomTEnt_Register("ce_lg_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_floor_explosion] = SV_CustomTEnt_Register("ce_floor_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_rider_death] = SV_CustomTEnt_Register("ce_rider_death", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_blue_explosion] = SV_CustomTEnt_Register("ce_blue_explosion", 0, NULL, 0, NULL, 0, 0, NULL); +// ce_green_smoke +// ce_grey_smoke + h2customtents[ce_red_smoke] = SV_CustomTEnt_Register("ce_red_smoke", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_slow_white_smoke] = SV_CustomTEnt_Register("ce_slow_white_smoke", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_redspark] = SV_CustomTEnt_Register("ce_redspark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_greenspark] = SV_CustomTEnt_Register("ce_greenspark", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_telesmk1] = SV_CustomTEnt_Register("ce_telesmk1", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_telesmk2] = SV_CustomTEnt_Register("ce_telesmk2", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_icehit] = SV_CustomTEnt_Register("ce_icehit", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_medusa_hit] = SV_CustomTEnt_Register("ce_medusa_hit", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_mezzo_reflect] = SV_CustomTEnt_Register("ce_mezzo_reflect", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_floor_explosion2] = SV_CustomTEnt_Register("ce_floor_explosion2", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_xbow_explosion] = SV_CustomTEnt_Register("ce_xbow_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_new_explosion] = SV_CustomTEnt_Register("ce_new_explosion", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_magic_missile_explosion] = SV_CustomTEnt_Register("ce_magic_missile_explosion", 0, NULL, 0, NULL, 0, 0, NULL); +// ce_ghost + h2customtents[ce_bone_explosion] = SV_CustomTEnt_Register("ce_bone_explosion", 0, NULL, 0, NULL, 0, 0, NULL); +// ce_redcloud + h2customtents[ce_teleporterpuffs] = SV_CustomTEnt_Register("ce_teleporterpuffs", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_teleporterbody] = SV_CustomTEnt_Register("ce_teleporterbody", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); +// ce_boneshard +// ce_boneshrapnel + h2customtents[ce_flamestream] = SV_CustomTEnt_Register("ce_flamestream", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); +// ce_snow, + h2customtents[ce_gravitywell] = SV_CustomTEnt_Register("ce_gravitywell", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_bldrn_expl] = SV_CustomTEnt_Register("ce_bldrn_expl", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_muzzfl] = SV_CustomTEnt_Register("ce_acid_muzzfl", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_hit] = SV_CustomTEnt_Register("ce_acid_hit", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_firewall_small] = SV_CustomTEnt_Register("ce_firewall_small", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_firewall_medium] = SV_CustomTEnt_Register("ce_firewall_medium", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_firewall_large] = SV_CustomTEnt_Register("ce_firewall_large", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_lball_expl] = SV_CustomTEnt_Register("ce_lball_expl", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_splat] = SV_CustomTEnt_Register("ce_acid_splat", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_acid_expl] = SV_CustomTEnt_Register("ce_acid_expl", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_fboom] = SV_CustomTEnt_Register("ce_fboom", 0, NULL, 0, NULL, 0, 0, NULL); +// ce_chunk + h2customtents[ce_bomb] = SV_CustomTEnt_Register("ce_bomb", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_brn_bounce] = SV_CustomTEnt_Register("ce_brn_bounce", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_lshock] = SV_CustomTEnt_Register("ce_lshock", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_flamewall] = SV_CustomTEnt_Register("ce_flamewall", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_flamewall2] = SV_CustomTEnt_Register("ce_flamewall2", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_floor_explosion3] = SV_CustomTEnt_Register("ce_floor_explosion3", 0, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_onfire] = SV_CustomTEnt_Register("ce_onfire", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + + + + h2customtents[ce_teleporterbody_1] = SV_CustomTEnt_Register("ce_teleporterbody_1", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_05] = SV_CustomTEnt_Register("ce_white_smoke_05", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_10] = SV_CustomTEnt_Register("ce_white_smoke_10", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_15] = SV_CustomTEnt_Register("ce_white_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_20] = SV_CustomTEnt_Register("ce_white_smoke_20", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_white_smoke_50] = SV_CustomTEnt_Register("ce_white_smoke_50", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_05] = SV_CustomTEnt_Register("ce_green_smoke_05", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_10] = SV_CustomTEnt_Register("ce_green_smoke_10", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_15] = SV_CustomTEnt_Register("ce_green_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_green_smoke_20] = SV_CustomTEnt_Register("ce_green_smoke_20", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_grey_smoke_15] = SV_CustomTEnt_Register("ce_grey_smoke_15", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + h2customtents[ce_grey_smoke_100] = SV_CustomTEnt_Register("ce_grey_smoke_100", CTE_CUSTOMVELOCITY, NULL, 0, NULL, 0, 0, NULL); + } +} void PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) { +// float *min, *max, *angle, *size; +// float colour, wait, radius, frame, framelength, duration; +// int flags, type, skin; + float *org, *dir; + int count; + + int efnum = G_FLOAT(OFS_PARM0); + G_FLOAT(OFS_RETURN) = 0; + switch(efnum) + { + case ce_rain: + //min = G_VECTOR(OFS_PARM1); + //max = G_VECTOR(OFS_PARM2); + //size = G_VECTOR(OFS_PARM3); + //dir = G_VECTOR(OFS_PARM4); + //colour = G_FLOAT(OFS_PARM5); + //count = G_FLOAT(OFS_PARM6); + //wait = G_FLOAT(OFS_PARM7); + /*FIXME: not spawned - this persistant effect is created by a map object, all attributes are custom.*/ + + Con_Printf("FTE-H2 FIXME: ce_rain not supported!\n", efnum); + return; + break; + case ce_snow: + //min = G_VECTOR(OFS_PARM1); + //max = G_VECTOR(OFS_PARM2); + //flags = G_FLOAT(OFS_PARM3); + //dir = G_VECTOR(OFS_PARM4); + //count = G_FLOAT(OFS_PARM5); + /*FIXME: not spawned - this persistant effect is created by a map object (might be delay-spawned), all attributes are custom.*/ + Con_Printf("FTE-H2 FIXME: ce_snow not supported!\n", efnum); + return; + break; + case ce_fountain: + //org = G_VECTOR(OFS_PARM1); + //angle = G_VECTOR(OFS_PARM2); + //dir = G_VECTOR(OFS_PARM3); + //colour = G_FLOAT(OFS_PARM4); + //count = G_FLOAT(OFS_PARM5); + /*FIXME: not spawned - this persistant effect is created by a map object, all attributes are custom.*/ + Con_Printf("FTE-H2 FIXME: ce_fountain not supported!\n", efnum); + return; + break; + case ce_quake: + org = G_VECTOR(OFS_PARM1); + //radius = G_FLOAT(OFS_PARM2); /*discard: always 500/3 */ + + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, NULL); + return; + } + break; + case ce_white_smoke: //(1,2,3,4,10)*0.05 + case ce_green_smoke: //(1,2,3,4)*0.05 + case ce_grey_smoke: //(3,20)*0.05 + /*transform them to the correct durations*/ + if (efnum == ce_white_smoke) + { + int ifl = G_FLOAT(OFS_PARM3) * 100; + if (ifl == 5) + efnum = ce_white_smoke_05; + else if (ifl == 10) + efnum = ce_white_smoke_10; + else if (ifl == 15) + efnum = ce_white_smoke_15; + else if (ifl == 20) + efnum = ce_white_smoke_20; + else if (ifl == 50) + efnum = ce_white_smoke_50; + } + else if (efnum == ce_green_smoke) + { + int ifl = G_FLOAT(OFS_PARM3) * 100; + if (ifl == 05) + efnum = ce_green_smoke_05; + else if (ifl == 10) + efnum = ce_green_smoke_10; + else if (ifl == 15) + efnum = ce_green_smoke_15; + else if (ifl == 20) + efnum = ce_green_smoke_20; + } + else + { + int ifl = G_FLOAT(OFS_PARM3) * 100; + if (ifl == 15) + efnum = ce_grey_smoke_15; + if (ifl == 100) + efnum = ce_grey_smoke_100; + } + /*fallthrough*/ + case ce_red_smoke: //0.15 + case ce_slow_white_smoke: //0 + case ce_telesmk1: //0.15 + case ce_telesmk2: //not used + case ce_ghost: //0.1 + case ce_redcloud: //0.05 + org = G_VECTOR(OFS_PARM1); + dir = G_VECTOR(OFS_PARM2); + //framelength = G_FLOAT(OFS_PARM3); /*FIXME: validate for the other effects?*/ + + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir); + return; + } + break; + case ce_acid_muzzfl: + case ce_flamestream: + case ce_flamewall: + case ce_flamewall2: + case ce_onfire: + org = G_VECTOR(OFS_PARM1); + dir = G_VECTOR(OFS_PARM2); + //frame = G_FLOAT(OFS_PARM3); /*discard: h2 uses a fixed value for each effect (0, except for acid_muzzfl which is 0.05)*/ + + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir); + return; + } + break; + case ce_sm_white_flash: + case ce_yellowred_flash: + case ce_bluespark: + case ce_yellowspark: + case ce_sm_circle_exp: + case ce_bg_circle_exp: + case ce_sm_explosion: + case ce_lg_explosion: + case ce_floor_explosion: + case ce_floor_explosion3: + case ce_blue_explosion: + case ce_redspark: + case ce_greenspark: + case ce_icehit: + case ce_medusa_hit: + case ce_mezzo_reflect: + case ce_floor_explosion2: + case ce_xbow_explosion: + case ce_new_explosion: + case ce_magic_missile_explosion: + case ce_bone_explosion: + case ce_bldrn_expl: + case ce_acid_hit: + case ce_acid_splat: + case ce_acid_expl: + case ce_lball_expl: + case ce_firewall_small: + case ce_firewall_medium: + case ce_firewall_large: + case ce_fboom: + case ce_bomb: + case ce_brn_bounce: + case ce_lshock: + case ce_white_flash: + case ce_blue_flash: + case ce_sm_blue_flash: + case ce_red_flash: + case ce_rider_death: + case ce_teleporterpuffs: + org = G_VECTOR(OFS_PARM1); + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, NULL); + return; + } + break; + case ce_gravitywell: + org = G_VECTOR(OFS_PARM1); + //colour = G_FLOAT(OFS_PARM2); /*discard: h2 uses a fixed random range*/ + //duration = G_FLOAT(OFS_PARM3); /*discard: h2 uses a fixed time limit*/ + + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, NULL); + return; + } + break; + case ce_teleporterbody: + org = G_VECTOR(OFS_PARM1); + dir = G_VECTOR(OFS_PARM2); + if (G_FLOAT(OFS_PARM3)) /*alternate*/ + efnum = ce_teleporterbody_1; + + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir); + return; + } + break; + case ce_boneshard: + case ce_boneshrapnel: + org = G_VECTOR(OFS_PARM1); + dir = G_VECTOR(OFS_PARM2); + //angle = G_VECTOR(OFS_PARM3); /*discard: angle is a function of the dir*/ + //avelocity = G_VECTOR(OFS_PARM4);/*discard: avelocity is a function of the dir*/ + + /*FIXME: persistant until removed*/ + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, 1, dir); + return; + } + break; + case ce_chunk: + org = G_VECTOR(OFS_PARM1); + //type = G_FLOAT(OFS_PARM2); /*FIXME: discarded*/ + dir = G_VECTOR(OFS_PARM3); + count = G_FLOAT(OFS_PARM4); + + if (h2customtents[efnum] != -1) + { + SV_CustomTEnt_Spawn(h2customtents[efnum], org, NULL, count, dir); + return; + } + + Con_Printf("FTE-H2 FIXME: ce_chunk not supported!\n", efnum); + return; + + + break; + default: + PR_BIError (prinst, "PF_h2starteffect: bad effect"); + break; + } + + Con_Printf("FTE-H2 FIXME: Effect %i doesn't have an effect registered\nTell Spike!\n", efnum); + +#if 0 + switch((int)G_FLOAT(OFS_PARM0)) { case 4: //white_smoke @@ -7250,6 +7744,7 @@ void PF_h2starteffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) Con_Printf("Start effect %i\n", (int)G_FLOAT(OFS_PARM0)); break; } +#endif } void PF_h2endeffect(progfuncs_t *prinst, struct globalvars_s *pr_globals) @@ -7397,9 +7892,19 @@ void PF_CustomTEnt(progfuncs_t *prinst, struct globalvars_s *pr_globals) MSG_WriteByte(&sv.multicast, G_FLOAT(OFS_PARM0+arg*3)); arg++; } - if (type & CTE_CUSTOMDIRECTION) + if (type & CTE_CUSTOMVELOCITY) { - MSG_WriteDir(&sv.multicast, G_VECTOR(OFS_PARM0+arg*3)); + float *vel = G_VECTOR(OFS_PARM0+arg*3); + MSG_WriteCoord(&sv.multicast, vel[0]); + MSG_WriteCoord(&sv.multicast, vel[1]); + MSG_WriteCoord(&sv.multicast, vel[2]); + arg++; + } + else if (type & CTE_CUSTOMDIRECTION) + { + vec3_t norm; + VectorNormalize2(G_VECTOR(OFS_PARM0+arg*3), norm); + MSG_WriteDir(&sv.multicast, norm); arg++; } } @@ -8390,71 +8895,8 @@ void PF_ChangePic(progfuncs_t *prinst, struct globalvars_s *pr_globals) -#if 0 -typedef struct { - int ident; - int version; - - char name[MAX_QPATH]; - - int flags; //Does anyone know what these are? - - int numFrames; - int numTags; - int numSurfaces; - - int numSkins; - - int ofsFrames; - int ofsTags; - int ofsSurfaces; - int ofsEnd; -} md3Header_t; -typedef struct { - char name[MAX_QPATH]; - vec3_t org; - float ang[3][3]; -} md3tag_t; - -typedef struct zymlump_s -{ - int start; - int length; -} zymlump_t; -typedef struct zymtype1header_s -{ - char id[12]; // "ZYMOTICMODEL", length 12, no termination - int type; // 0 (vertex morph) 1 (skeletal pose) or 2 (skeletal scripted) - int filesize; // size of entire model file - float mins[3], maxs[3], radius; // for clipping uses - int numverts; - int numtris; - int numsurfaces; - int numbones; // this may be zero in the vertex morph format (undecided) - int numscenes; // 0 in skeletal scripted models - -// skeletal pose header - // lump offsets are relative to the file - zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct) - zymlump_t lump_poses; // float pose[numposes][numbones][6]; // animation data - zymlump_t lump_bones; // zymbone_t bone[numbones]; - zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better) - zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct - zymlump_t lump_texcoords; // float texcoords[numvertices][2]; - zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices) - zymlump_t lump_surfnames; // char shadername[numsurfaces][32]; // shaders used on this model - zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation -} zymtype1header_t; -typedef struct zymbone_s -{ - char name[32]; - int flags; - int parent; // parent bone number -} zymbone_t; -#endif int SV_TagForName(int modelindex, char *tagname) { -#if 1 model_t *model = sv.models[modelindex]; if (!model) model = Mod_ForName(sv.strings.model_precache[modelindex], false); @@ -8462,51 +8904,6 @@ int SV_TagForName(int modelindex, char *tagname) return 0; return Mod_TagNumForName(model, tagname); -#else - int i; - unsigned int *file; - - file = (void*)COM_LoadTempFile(sv.model_precache[modelindex]); - if (!file) - { - Con_Printf("setattachment: \"%s\" is missing\n", sv.model_precache[modelindex]); - return 0; - } - - if (*file == MD3_IDENT) - { - md3Header_t *md3 = (md3Header_t*)file; - md3tag_t *tag; - - tag = (md3tag_t*)((char*)md3 + md3->ofsTags); - - for (i = 0;i < md3->numTags;i++) - { - if (!strcmp(tagname, tag[i].name)) - { - return i + 1; - } - } - } - else if (!strncmp((char*)file, "ZYMOTICMODEL", 12) && BigLong(file[3]) == 1) - { - zymtype1header_t *zym = (zymtype1header_t*)file; - zymbone_t *tag; - - tag = (zymbone_t*)((char*)zym + BigLong(zym->lump_bones.start)); - - for (i = BigLong(zym->numbones)-1;i >=0;i--) - { - if (!strcmp(tagname, tag[i].name)) - { - return i + 1; - } - } - } - else - Con_DPrintf("setattachment: %s not supported\n", sv.model_precache[modelindex]); - return 0; -#endif } void PF_setattachment(progfuncs_t *prinst, struct globalvars_s *pr_globals) diff --git a/engine/server/pr_q1qvm.c b/engine/server/pr_q1qvm.c index f2ff0d6ff..60a055fbd 100755 --- a/engine/server/pr_q1qvm.c +++ b/engine/server/pr_q1qvm.c @@ -775,7 +775,7 @@ static qintptr_t syscallhandle (void *offset, quintptr_t mask, qintptr_t fn, con v[0] = VM_FLOAT(arg[0]); v[1] = VM_FLOAT(arg[1]); v[2] = VM_FLOAT(arg[2]); - return sv.world.worldmodel->funcs.PointContents(sv.world.worldmodel, v); + return sv.world.worldmodel->funcs.PointContents(sv.world.worldmodel, NULL, v); } break; diff --git a/engine/server/progdefs.h b/engine/server/progdefs.h index c2ec14a86..43e1d1264 100644 --- a/engine/server/progdefs.h +++ b/engine/server/progdefs.h @@ -127,7 +127,7 @@ and the extension fields are added on the end and can have extra vm-specific stu comfieldstring(model,model,model);\ comfieldfloat(frame,frame,frame);\ comfieldfloat(skin,skin,skin);\ - comfieldfloat(effects,_effects,_effects);\ + comfieldfloat(effects,effects,effects);\ comfieldvector(mins,mins,mins);\ comfieldvector(maxs,maxs,maxs);\ comfieldvector(size,size,size);\ diff --git a/engine/server/server.h b/engine/server/server.h index cbc67d1a5..6251cc18f 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -78,6 +78,8 @@ typedef struct { #define CTE_STAINS 4 #define CTE_GLOWS 8 #define CTE_CHANNELFADE 16 +#define CTE_CUSTOMVELOCITY 32 +#define CTE_UNUSED2 64 #define CTE_ISBEAM 128 typedef struct laggedpacket_s diff --git a/engine/server/sv_ents.c b/engine/server/sv_ents.c index 21154ad37..6783055ba 100644 --- a/engine/server/sv_ents.c +++ b/engine/server/sv_ents.c @@ -1401,7 +1401,7 @@ qboolean Cull_Traceline(edict_t *viewer, edict_t *seen) //stage 1: check against their origin VectorAdd(viewer->v->origin, viewer->v->view_ofs, start); tr.fraction = 1; - if (!sv.world.worldmodel->funcs.Trace (sv.world.worldmodel, 1, 0, start, seen->v->origin, vec3_origin, vec3_origin, &tr)) + if (!sv.world.worldmodel->funcs.Trace (sv.world.worldmodel, 1, 0, NULL, start, seen->v->origin, vec3_origin, vec3_origin, &tr)) return false; //wasn't blocked //stage 2: check against their bbox @@ -1412,7 +1412,7 @@ qboolean Cull_Traceline(edict_t *viewer, edict_t *seen) end[2] = seen->v->origin[2] + ((i&4)?seen->v->mins[2]+0.1:seen->v->maxs[2]); tr.fraction = 1; - if (!sv.world.worldmodel->funcs.Trace (sv.world.worldmodel, 1, 0, start, end, vec3_origin, vec3_origin, &tr)) + if (!sv.world.worldmodel->funcs.Trace (sv.world.worldmodel, 1, 0, NULL, start, end, vec3_origin, vec3_origin, &tr)) return false; //this trace went through, so don't cull } @@ -2228,6 +2228,7 @@ void SV_Snapshot_BuildStateQ1(entity_state_t *state, edict_t *ent, client_t *cli state->light[2] = ent->xv->color[2]*255; state->light[3] = ent->xv->light_lev; state->lightstyle = ent->xv->style; + state->lightstyle = ent->xv->style; state->lightpflags = ent->xv->pflags; if ((int)ent->v->flags & FL_CLASS_DEPENDENT && client->playerclass) //hexen2 wierdness. diff --git a/engine/server/sv_init.c b/engine/server/sv_init.c index 2a9330efe..791d537d3 100644 --- a/engine/server/sv_init.c +++ b/engine/server/sv_init.c @@ -1269,8 +1269,21 @@ void SV_SpawnServer (char *server, char *startspot, qboolean noents, qboolean us else if (coop.value) spawnflagmask |= SPAWNFLAG_NOT_H2COOP; else + { + cvar_t *cl_playerclass = Cvar_Get("cl_playerclass", "0", CVAR_USERINFO, 0); spawnflagmask |= SPAWNFLAG_NOT_H2SINGLE; + if (cl_playerclass && cl_playerclass->ival == 1) + spawnflagmask |= SPAWNFLAG_NOT_H2PALADIN; + else if (cl_playerclass && cl_playerclass->ival == 2) + spawnflagmask |= SPAWNFLAG_NOT_H2CLERIC; + else if (cl_playerclass && cl_playerclass->ival == 3) + spawnflagmask |= SPAWNFLAG_NOT_H2NECROMANCER; + else if (cl_playerclass && cl_playerclass->ival == 4) + spawnflagmask |= SPAWNFLAG_NOT_H2THEIF; + else if (cl_playerclass && cl_playerclass->ival == 5) + spawnflagmask |= SPAWNFLAG_NOT_H2NECROMANCER; /*yes, I know.,. makes no sense*/ + } if (skill.value < 0.5) spawnflagmask |= SPAWNFLAG_NOT_H2EASY; else if (skill.value > 1.5) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index dac13f65f..0c1f5bfbd 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -4684,7 +4684,9 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node ) continue; // player's own missile if (check->v->solid == SOLID_BSP || check->v->solid == SOLID_BBOX - || check->v->solid == SOLID_SLIDEBOX) + || check->v->solid == SOLID_SLIDEBOX + //|| (check->v->solid == SOLID_PHASEH2 && progstype == PROG_H2) //logically matches hexen2, but I hate it + ) { if (check == player) continue; @@ -4744,9 +4746,14 @@ void AddLinksToPmove ( edict_t *player, areanode_t *node ) model = sv.models[(int)check->v->modelindex]; if (model) + { + vec3_t axis[3]; + AngleVectors(check->v->angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); // test the point - if (model->funcs.PointContents (model, player->v->origin) == FTECONTENTS_SOLID) - player->xv->pmove_flags = (int)player->xv->pmove_flags | PMF_LADDER; //touch that ladder! + if (model->funcs.PointContents (model, axis, player->v->origin) == FTECONTENTS_SOLID) + player->xv->pmove_flags = (int)player->xv->pmove_flags | PMF_LADDER; //touch that ladder! + } } } diff --git a/engine/server/svq3_game.c b/engine/server/svq3_game.c index 22bd3310c..f7b8a9ddb 100644 --- a/engine/server/svq3_game.c +++ b/engine/server/svq3_game.c @@ -86,9 +86,6 @@ char *mapentspointer; #define Q3SOLID_BMODEL 0xffffff -#define Q3CONTENTS_SOLID Q2CONTENTS_SOLID // should never be on a brush, only in game -#define Q3CONTENTS_BODY 0x2000000 // should never be on a brush, only in game - #define PS_FOR_NUM(n) ((q3playerState_t *)((qbyte *)q3playerstates + sizeofGameClient*(n))) #define clamp(v,min,max) v = (v>max)?max:((v < min)?min:v) @@ -402,7 +399,7 @@ static void SVQ3_Trace(q3trace_t *result, vec3_t start, vec3_t mins, vec3_t maxs if (!maxs) maxs = vec3_origin; - sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, start, end, mins, maxs, contentmask, &tr); + sv.world.worldmodel->funcs.NativeTrace(sv.world.worldmodel, 0, 0, NULL, start, end, mins, maxs, contentmask, &tr); result->allsolid = tr.allsolid; result->contents = tr.contents; VectorCopy(tr.endpos, result->endpos); @@ -504,7 +501,7 @@ static int SVQ3_PointContents(vec3_t pos, int entnum) // sv.worldmodel->funcs.Trace(sv.worldmodel, 0, 0, pos, pos, vec3_origin, vec3_origin, &tr); // tr = CM_BoxTrace(sv.worldmodel, pos, pos, vec3_origin, vec3_origin, 0); - cont = sv.world.worldmodel->funcs.NativeContents (sv.world.worldmodel, 0, 0, pos, vec3_origin, vec3_origin); + cont = sv.world.worldmodel->funcs.NativeContents (sv.world.worldmodel, 0, 0, NULL, pos, vec3_origin, vec3_origin); if ((unsigned)entnum >= MAX_GENTITIES) ourowner = -1; @@ -566,7 +563,7 @@ static int SVQ3_Contact(vec3_t mins, vec3_t maxs, q3sharedEntity_t *ent) if (mod->needload || !mod->funcs.Trace) return false; - mod->funcs.Trace(mod, 0, 0, vec3_origin, vec3_origin, mins, maxs, &tr); + mod->funcs.Trace(mod, 0, 0, NULL, vec3_origin, vec3_origin, mins, maxs, &tr); if (tr.startsolid) return true; @@ -2822,7 +2819,6 @@ void SVQ3_ParseUsercmd(client_t *client, qboolean delta) { if(to->servertime <= client->lastcmd.servertime) { - Con_Printf("%i vs %i\n", to->servertime, client->lastcmd.servertime); continue; } if (to->servertime-10 > sv.time*1000) //10 ms allows some server latency... diff --git a/engine/server/world.c b/engine/server/world.c index 343e0d1ad..1425ae729 100644 --- a/engine/server/world.c +++ b/engine/server/world.c @@ -886,7 +886,7 @@ SV_PointContents */ int World_PointContents (world_t *w, vec3_t p) { - return w->worldmodel->funcs.PointContents(w->worldmodel, p); + return w->worldmodel->funcs.PointContents(w->worldmodel, NULL, p); } //=========================================================================== @@ -917,11 +917,8 @@ qboolean Q1BSP_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, //qboolean TransformedHullCheck (hull_t *hull, vec3_t start, vec3_t end, trace_t *trace, vec3_t angles) qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, struct trace_s *trace, vec3_t origin, vec3_t angles) { - qboolean rotated; vec3_t start_l, end_l; - vec3_t a; - vec3_t forward, right, up; - vec3_t temp; + vec3_t axis[3]; qboolean result; memset (trace, 0, sizeof(trace_t)); @@ -934,53 +931,21 @@ qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, v // don't rotate non bsp ents. Too small to bother. if (model) { - rotated = (angles[0] || angles[1] || angles[2]); - if (rotated) + VectorSubtract (start, origin, start_l); + VectorSubtract (end, origin, end_l); + + if (angles[0] || angles[1] || angles[2]) { - AngleVectors (angles, forward, right, up); - - VectorSubtract (start, origin, temp); - start_l[0] = DotProduct (temp, forward); - start_l[1] = -DotProduct (temp, right); - start_l[2] = DotProduct (temp, up); - - VectorSubtract (end, origin, temp); - end_l[0] = DotProduct (temp, forward); - end_l[1] = -DotProduct (temp, right); - end_l[2] = DotProduct (temp, up); + AngleVectors (angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); + result = model->funcs.Trace (model, hulloverride, frame, axis, start_l, end_l, mins, maxs, trace); } else { - VectorSubtract (start, origin, start_l); - VectorSubtract (end, origin, end_l); + result = model->funcs.Trace (model, hulloverride, frame, NULL, start_l, end_l, mins, maxs, trace); } - result = model->funcs.Trace (model, hulloverride, frame, start_l, end_l, mins, maxs, trace); - if (rotated) - { - // FIXME: figure out how to do this with existing angles - if (trace->fraction != 1) - { - VectorNegate (angles, a); - AngleVectors (a, forward, right, up); - - VectorCopy (trace->plane.normal, temp); - trace->plane.normal[0] = DotProduct (temp, forward); - trace->plane.normal[1] = -DotProduct (temp, right); - trace->plane.normal[2] = DotProduct (temp, up); - - - trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]); - trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]); - trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]); - } - else - { - VectorCopy (end, trace->endpos); - } - } - else - VectorAdd (trace->endpos, origin, trace->endpos); + VectorAdd (trace->endpos, origin, trace->endpos); } else { @@ -1002,11 +967,8 @@ qboolean TransformedTrace (struct model_s *model, int hulloverride, int frame, v qboolean TransformedNativeTrace (struct model_s *model, int hulloverride, int frame, vec3_t start, vec3_t end, vec3_t mins, vec3_t maxs, unsigned int against, struct trace_s *trace, vec3_t origin, vec3_t angles) { - qboolean rotated; vec3_t start_l, end_l; - vec3_t a; - vec3_t forward, right, up; - vec3_t temp; + vec3_t axis[3]; qboolean result; memset (trace, 0, sizeof(trace_t)); @@ -1019,44 +981,17 @@ qboolean TransformedNativeTrace (struct model_s *model, int hulloverride, int fr // don't rotate non bsp ents. Too small to bother. if (model) { - rotated = (angles[0] || angles[1] || angles[2]); - if (rotated) + VectorSubtract (start, origin, start_l); + VectorSubtract (end, origin, end_l); + if (angles[0] || angles[1] || angles[2]) { - AngleVectors (angles, forward, right, up); - - VectorSubtract (start, origin, temp); - start_l[0] = DotProduct (temp, forward); - start_l[1] = -DotProduct (temp, right); - start_l[2] = DotProduct (temp, up); - - VectorSubtract (end, origin, temp); - end_l[0] = DotProduct (temp, forward); - end_l[1] = -DotProduct (temp, right); - end_l[2] = DotProduct (temp, up); + AngleVectors (angles, axis[0], axis[1], axis[2]); + VectorNegate(axis[1], axis[1]); + result = model->funcs.NativeTrace (model, hulloverride, frame, axis, start_l, end_l, mins, maxs, against, trace); } else { - VectorSubtract (start, origin, start_l); - VectorSubtract (end, origin, end_l); - } - result = model->funcs.NativeTrace (model, hulloverride, frame, start_l, end_l, mins, maxs, against, trace); - if (rotated) - { - // FIXME: figure out how to do this with existing angles - // VectorNegate (angles, a); - a[0] = -angles[0]; - a[1] = -angles[1]; - a[2] = -angles[2]; - AngleVectors (a, forward, right, up); - - VectorCopy (trace->plane.normal, temp); - trace->plane.normal[0] = DotProduct (temp, forward); - trace->plane.normal[1] = -DotProduct (temp, right); - trace->plane.normal[2] = DotProduct (temp, up); - - trace->endpos[0] = start[0] + trace->fraction * (end[0] - start[0]); - trace->endpos[1] = start[1] + trace->fraction * (end[1] - start[1]); - trace->endpos[2] = start[2] + trace->fraction * (end[2] - start[2]); + result = model->funcs.NativeTrace (model, hulloverride, frame, NULL, start_l, end_l, mins, maxs, against, trace); } VectorAdd (trace->endpos, origin, trace->endpos); }