From 81b7ba9e4b0ca768de8a7de3550fef38fac08ee7 Mon Sep 17 00:00:00 2001 From: Shpoike Date: Fri, 13 Sep 2019 18:51:16 +0100 Subject: [PATCH] Added FTE_ENT_SKIN_CONTENTS support. --- Quake/bspfile.h | 2 ++ Quake/gl_model.c | 2 +- Quake/gl_rmain.c | 24 ++++++++++++++++++--- Quake/pr_ext.c | 1 + Quake/progs.h | 1 + Quake/sv_phys.c | 54 +++++++++++++++++++++++++++++++++++++++++------- Quake/sv_user.c | 11 ++++++++-- Quake/world.c | 25 ++++++++++++++++++++-- Quake/world.h | 6 ++++++ 9 files changed, 110 insertions(+), 16 deletions(-) diff --git a/Quake/bspfile.h b/Quake/bspfile.h index 833f6aa8..5d708067 100644 --- a/Quake/bspfile.h +++ b/Quake/bspfile.h @@ -177,6 +177,8 @@ typedef struct #define CONTENTS_CURRENT_UP -13 #define CONTENTS_CURRENT_DOWN -14 +#define CONTENTS_LADDER -16 + // !!! if this is changed, it must be changed in asm_i386.h too !!! typedef struct diff --git a/Quake/gl_model.c b/Quake/gl_model.c index 71079565..d28f6b4d 100644 --- a/Quake/gl_model.c +++ b/Quake/gl_model.c @@ -111,7 +111,7 @@ mleaf_t *Mod_PointInLeaf (vec3_t p, qmodel_t *model) if (!model || !model->nodes) Sys_Error ("Mod_PointInLeaf: bad model"); - node = model->nodes; + node = model->nodes + model->hulls[0].firstclipnode; while (1) { if (node->contents < 0) diff --git a/Quake/gl_rmain.c b/Quake/gl_rmain.c index 8694d011..7c029425 100644 --- a/Quake/gl_rmain.c +++ b/Quake/gl_rmain.c @@ -555,6 +555,8 @@ R_SetupView -- johnfitz -- this is the stuff that needs to be done once per fram */ void R_SetupView (void) { + int viewcontents; //spike -- rewrote this a little + int i; Fog_SetupFrame (); //johnfitz // build the transformation matrix for the given view angles @@ -564,8 +566,25 @@ void R_SetupView (void) // current viewleaf r_oldviewleaf = r_viewleaf; r_viewleaf = Mod_PointInLeaf (r_origin, cl.worldmodel); + viewcontents = r_viewleaf->contents; - V_SetContentsColor (r_viewleaf->contents); + //spike -- added this loop for moving water volumes + for (i = 0; i < cl.num_entities && viewcontents == CONTENTS_EMPTY; i++) + { + mleaf_t *subleaf; + vec3_t relpos; + if (cl.entities[i].model && cl.entities[i].model->type==mod_brush) + { + VectorSubtract(r_origin, cl.entities[i].origin, relpos); + subleaf = Mod_PointInLeaf (relpos, cl.entities[i].model); + if ((char)cl.entities[i].skinnum < 0) + viewcontents = ((subleaf->contents == CONTENTS_SOLID)?(char)cl.entities[i].skinnum:CONTENTS_EMPTY); + else + viewcontents = subleaf->contents; + } + } + + V_SetContentsColor (viewcontents); V_CalcBlend (); r_cache_thrash = false; @@ -575,8 +594,7 @@ void R_SetupView (void) r_fovy = r_refdef.fov_y; if (r_waterwarp.value) { - int contents = Mod_PointInLeaf (r_origin, cl.worldmodel)->contents; - if (contents == CONTENTS_WATER || contents == CONTENTS_SLIME || contents == CONTENTS_LAVA) + if (viewcontents == CONTENTS_WATER || viewcontents == CONTENTS_SLIME || viewcontents == CONTENTS_LAVA) { //variance is a percentage of width, where width = 2 * tan(fov / 2) otherwise the effect is too dramatic at high FOV and too subtle at low FOV. what a mess! r_fovx = atan(tan(DEG2RAD(r_refdef.fov_x) / 2) * (0.97 + sin(cl.time * 1.5) * 0.03)) * 2 / M_PI_DIV_180; diff --git a/Quake/pr_ext.c b/Quake/pr_ext.c index f06bc46c..309e98cf 100644 --- a/Quake/pr_ext.c +++ b/Quake/pr_ext.c @@ -5706,6 +5706,7 @@ static const char *extnames[] = "DP_TE_STANDARDEFFECTBUILTINS", "EXT_BITSHIFT", "FRIK_FILE", //lacks the file part, but does have the strings part. + "FTE_ENT_SKIN_CONTENTS", //SOLID_BSP&&skin==CONTENTS_FOO changes CONTENTS_SOLID to CONTENTS_FOO, allowing you to swim in moving ents without qc hacks, as well as correcting view cshifts etc. #ifdef PSET_SCRIPT "FTE_PART_SCRIPT", "FTE_PART_NAMESPACES", diff --git a/Quake/progs.h b/Quake/progs.h index 39aba74a..0691b513 100644 --- a/Quake/progs.h +++ b/Quake/progs.h @@ -48,6 +48,7 @@ typedef struct edict_s entity_state_t baseline; unsigned char alpha; /* johnfitz -- hack to support alpha since it's not part of entvars_t */ qboolean sendinterval; /* johnfitz -- send time until nextthink to client for better lerp timing */ + qboolean onladder; /* spike -- content_ladder stuff */ float freetime; /* sv.time when the object was freed */ entvars_t v; /* C exported fields from progs */ diff --git a/Quake/sv_phys.c b/Quake/sv_phys.c index 293596e1..de73be71 100644 --- a/Quake/sv_phys.c +++ b/Quake/sv_phys.c @@ -508,8 +508,16 @@ void SV_PushMove (edict_t *pusher, float movetime) continue; // see if the ent's bbox is inside the pusher's final position - if (!SV_TestEntityPosition (check)) - continue; + if (pusher->v.skin < 0) + { //a more precise check... + if (!SV_ClipMoveToEntity (pusher, check->v.origin, check->v.mins, check->v.maxs, check->v.origin).startsolid) + continue; + } + else + { + if (!SV_TestEntityPosition (check)) + continue; + } } // remove the onground flag for non-players @@ -530,10 +538,18 @@ void SV_PushMove (edict_t *pusher, float movetime) // try moving the contacted entity pusher->v.solid = SOLID_NOT; SV_PushEntity (check, move); - pusher->v.solid = solid_backup; // if it is still inside the pusher, block - block = SV_TestEntityPosition (check); + if (pusher->v.skin < 0) + { //if it has forced contents then do things in a slightly different order, so water can push properly. + block = SV_TestEntityPosition (check); + pusher->v.solid = solid_backup; + } + else + { + pusher->v.solid = solid_backup; + block = SV_TestEntityPosition (check); + } } else block = NULL; @@ -689,6 +705,26 @@ qboolean SV_CheckWater (edict_t *ent) { vec3_t point; int cont; + trace_t tr; + + //Spike -- FTE_ENT_SKIN_CONTENTS -- check if we're on a ladder, and if so fire a trace forwards to ensure its a valid ladder instead of a random volume + tr = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, ent->v.origin, MOVE_HITALLCONTENTS, ent); + if (tr.contents == CONTENTS_LADDER) + { + vec3_t flatforward; + flatforward[0] = cos((M_PI/180)*ent->v.angles[1]); + flatforward[1] = sin((M_PI/180)*ent->v.angles[1]); + flatforward[2] = 0; + VectorMA (ent->v.origin, 24, flatforward, point); + + tr = SV_Move(ent->v.origin, ent->v.mins, ent->v.maxs, point, 0, ent); + if (tr.fraction < 1) + sv_player->onladder = true; + else + sv_player->onladder = false; + } + else + sv_player->onladder = false; point[0] = ent->v.origin[0]; point[1] = ent->v.origin[1]; @@ -696,18 +732,19 @@ qboolean SV_CheckWater (edict_t *ent) ent->v.waterlevel = 0; ent->v.watertype = CONTENTS_EMPTY; - cont = SV_PointContents (point); + //Spike -- FTE_ENT_SKIN_CONTENTS -- check submodels too, because we can. + cont = SV_PointContentsAllBsps (point, ent); if (cont <= CONTENTS_WATER) { ent->v.watertype = cont; ent->v.waterlevel = 1; point[2] = ent->v.origin[2] + (ent->v.mins[2] + ent->v.maxs[2])*0.5; - cont = SV_PointContents (point); + cont = SV_PointContentsAllBsps (point, ent); if (cont <= CONTENTS_WATER) { ent->v.waterlevel = 2; point[2] = ent->v.origin[2] + ent->v.view_ofs[2]; - cont = SV_PointContents (point); + cont = SV_PointContentsAllBsps (point, ent); if (cont <= CONTENTS_WATER) ent->v.waterlevel = 3; } @@ -948,7 +985,8 @@ void SV_Physics_Client (edict_t *ent, int num) if (!SV_RunThink (ent)) return; if (!SV_CheckWater (ent) && ! ((int)ent->v.flags & FL_WATERJUMP) ) - SV_AddGravity (ent); + if (!sv_player->onladder) + SV_AddGravity (ent); SV_CheckStuck (ent); SV_WalkMove (ent); break; diff --git a/Quake/sv_user.c b/Quake/sv_user.c index 8ea6d48f..26e45201 100644 --- a/Quake/sv_user.c +++ b/Quake/sv_user.c @@ -236,7 +236,14 @@ void SV_WaterMove (void) for (i=0 ; i<3 ; i++) wishvel[i] = forward[i]*cmd.forwardmove + right[i]*cmd.sidemove; - if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove) + if (sv_player->onladder) + { + wishvel[2] *= 1+fabs(wishvel[2]/200)*9; //exaggerate vertical movement. + if (sv_player->v.button2) + wishvel[2] += 400; //make jump climb (you can turn around and move off to fall) + } + + if (!cmd.forwardmove && !cmd.sidemove && !cmd.upmove && !sv_player->onladder) wishvel[2] -= 60; // drift towards bottom else wishvel[2] += cmd.upmove; @@ -422,7 +429,7 @@ void SV_ClientThink (void) //johnfitz -- alternate noclip if (sv_player->v.movetype == MOVETYPE_NOCLIP && sv_altnoclip.value) SV_NoclipMove (); - else if (sv_player->v.waterlevel >= 2 && sv_player->v.movetype != MOVETYPE_NOCLIP) + else if ((sv_player->v.waterlevel >= 2||sv_player->onladder) && sv_player->v.movetype != MOVETYPE_NOCLIP) SV_WaterMove (); else SV_AirMove (); diff --git a/Quake/world.c b/Quake/world.c index b9f75922..8b54f1d2 100644 --- a/Quake/world.c +++ b/Quake/world.c @@ -41,6 +41,7 @@ typedef struct float *start, *end; trace_t trace; int type; + unsigned int hitcontents; //content types to impact upon... (1<<-CONTENTS_FOO) bitmask edict_t *passedict; } moveclip_t; @@ -555,6 +556,14 @@ int SV_TruePointContents (vec3_t p) return SV_HullPointContents (&qcvm->worldmodel->hulls[0], 0, p); } +int SV_PointContentsAllBsps(vec3_t p, edict_t *forent) +{ + trace_t trace = SV_Move (p, vec3_origin, vec3_origin, p, MOVE_NOMONSTERS|MOVE_HITALLCONTENTS, forent); + if (trace.contents <= CONTENTS_CURRENT_0 && trace.contents >= CONTENTS_CURRENT_DOWN) + trace.contents = CONTENTS_WATER; + return trace.contents; +} + //=========================================================================== /* @@ -629,6 +638,7 @@ reenter: if (num < 0) { /*hit a leaf*/ + trace->contents = num; if (num == CONTENTS_SOLID) { if (trace->allsolid) @@ -741,7 +751,9 @@ qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec if (p1[0]==p2[0] && p1[1]==p2[1] && p1[2]==p2[2]) { /*points cannot cross planes, so do it faster*/ - switch(SV_HullPointContents(hull, num, p1)) + int c = SV_HullPointContents(hull, num, p1); + trace->contents = c; + switch(c) { case CONTENTS_SOLID: trace->startsolid = true; @@ -875,6 +887,11 @@ void SV_ClipToLinks ( areanode_t *node, moveclip_t *clip ) trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, clip->maxs2, clip->end); else trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, clip->maxs, clip->end); + if (trace.contents == CONTENTS_SOLID && touch->v.skin < 0) + trace.contents = touch->v.skin; + if (!((1<<(-trace.contents)) & clip->hitcontents)) + continue; + if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { @@ -951,8 +968,12 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e clip.end = end; clip.mins = mins; clip.maxs = maxs; - clip.type = type; + clip.type = type&3; clip.passedict = passedict; + if (type & MOVE_HITALLCONTENTS) + clip.hitcontents = ~0u; + else + clip.hitcontents = (1<<(-CONTENTS_SOLID)) | (1<<(-CONTENTS_CLIP)); if (type == MOVE_MISSILE) { diff --git a/Quake/world.h b/Quake/world.h index fed90b02..b409deba 100644 --- a/Quake/world.h +++ b/Quake/world.h @@ -38,6 +38,8 @@ typedef struct vec3_t endpos; // final position plane_t plane; // surface normal at impact edict_t *ent; // entity the surface is on + + int contents; // spike -- the content type(s) that we found. } trace_t; @@ -45,6 +47,8 @@ typedef struct #define MOVE_NOMONSTERS 1 #define MOVE_MISSILE 2 +#define MOVE_HITALLCONTENTS (1<<9) + void SV_ClearWorld (void); // called after the world model has been loaded, before linking any entities @@ -60,6 +64,7 @@ void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); // sets ent->v.absmin and ent->v.absmax // if touchtriggers, calls prog functions for the intersected triggers +int SV_PointContentsAllBsps(vec3_t p, edict_t *forent); //check all SOLID_BSP ents int SV_PointContents (vec3_t p); int SV_TruePointContents (vec3_t p); // returns the CONTENTS_* value from the world at the given point. @@ -68,6 +73,7 @@ int SV_TruePointContents (vec3_t p); edict_t *SV_TestEntityPosition (edict_t *ent); +trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end); trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); // mins and maxs are reletive