From 22bb395305b75be262cd94f5c3e566e8bc2fd2a2 Mon Sep 17 00:00:00 2001 From: Spoike Date: Sat, 28 Aug 2010 17:14:38 +0000 Subject: [PATCH] hexen2 client effects now go via the particle system, if they're supported at all. Added 'h2part' description to provide this. Fixed svc_setangles and sv_bigcoords. Model code is now responsible for transforming traces instead of it being generic. This fixes rotating things getting stuck in players in hexen2. The renderer now generates a list of surfaces to draw. Backend now performs rotations/scaling per entity. This fixes sorting order, at least when not using realtime lights. Hidden items in the hexen2 inventory that you do not have. Added colourmapping for hexen2. Should be easier to click on menu items for hexen2. git-svn-id: https://svn.code.sf.net/p/fteqw/code/branches/wip@3602 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_cg.c | 26 +- engine/client/cl_ents.c | 36 +- engine/client/cl_main.c | 1 + engine/client/cl_parse.c | 33 +- engine/client/cl_pred.c | 4 +- engine/client/cl_screen.c | 15 +- engine/client/cl_tent.c | 47 +- engine/client/client.h | 2 + engine/client/m_items.c | 4 +- engine/client/m_multi.c | 2 +- engine/client/m_options.c | 7 +- engine/client/menu.c | 55 ++- engine/client/p_script.c | 177 +++++--- engine/client/pr_csqc.c | 35 +- engine/client/pr_menu.c | 2 + engine/client/quakedef.h | 1 + engine/client/r_part.c | 10 +- engine/client/r_partset.c | 659 +++++++++++++++++++--------- engine/client/r_partset.h | 5 +- engine/client/r_surf.c | 51 ++- engine/client/render.h | 5 +- engine/client/renderer.c | 19 +- engine/client/sbar.c | 190 +++++--- engine/client/snd_sdl.c | 2 +- engine/common/bspfile.h | 19 +- engine/common/com_mesh.c | 4 +- engine/common/com_mesh.h | 1 + engine/common/fs.c | 4 +- engine/common/gl_q2bsp.c | 25 +- engine/common/mathlib.c | 31 ++ engine/common/mathlib.h | 1 + engine/common/pmovetst.c | 85 +--- engine/common/q1bsp.c | 59 ++- engine/common/q3common.c | 2 +- engine/gl/gl_alias.c | 270 +++++------- engine/gl/gl_backend.c | 694 +++++++++++++++++++++--------- engine/gl/gl_draw.c | 1 - engine/gl/gl_font.c | 16 +- engine/gl/gl_heightmap.c | 10 +- engine/gl/gl_model.c | 21 +- engine/gl/gl_model.h | 79 ++-- engine/gl/gl_rmain.c | 167 +++---- engine/gl/gl_rmisc.c | 4 +- engine/gl/gl_shader.c | 221 ++++++---- engine/gl/gl_shadow.c | 32 +- engine/gl/gl_vidcommon.c | 94 +++- engine/gl/gl_warp.c | 1 + engine/gl/glquake.h | 5 +- engine/gl/ltface.c | 4 +- engine/gl/shader.h | 43 +- engine/partcfgs/generatebuiltin.c | 77 ++++ engine/partcfgs/h2part.cfg | 228 ++++++++++ engine/partcfgs/spikeset.cfg | 153 ++++--- engine/qclib/hash.c | 42 +- engine/qclib/hash.h | 1 + engine/server/net_preparse.c | 114 ++--- engine/server/pr_cmds.c | 627 ++++++++++++++++++++++----- engine/server/pr_q1qvm.c | 2 +- engine/server/progdefs.h | 2 +- engine/server/server.h | 2 + engine/server/sv_ents.c | 5 +- engine/server/sv_init.c | 13 + engine/server/sv_user.c | 13 +- engine/server/svq3_game.c | 10 +- engine/server/world.c | 103 +---- 65 files changed, 3104 insertions(+), 1569 deletions(-) create mode 100644 engine/partcfgs/generatebuiltin.c create mode 100644 engine/partcfgs/h2part.cfg 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); }