Added FTE_ENT_SKIN_CONTENTS support.

This commit is contained in:
Shpoike 2019-09-13 18:51:16 +01:00
parent ef5d841e80
commit 81b7ba9e4b
9 changed files with 110 additions and 16 deletions

View file

@ -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

View file

@ -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)

View file

@ -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;

View file

@ -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",

View file

@ -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 */

View file

@ -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;

View file

@ -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 ();

View file

@ -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)
{

View file

@ -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