Page 2 of 2

Re: Engine Side Footsteps

Posted: Tue May 06, 2014 2:29 pm
by drm_wayne
i had footsteps in qc before with cheap triggers to simulate wood/metal/mud and snow, but i want to have it in the engine ;)
The Node stuff looks interesting ;)

Re: Engine Side Footsteps

Posted: Wed May 07, 2014 4:16 pm
by drm_wayne
I got the GetNodePoint stuff to work... well kinda... i dont get the texture under me, only above me which is weird..
How do you call the GetNodePoint?? GetNodePoint(ent->origin, ?whathere?);

Re: Engine Side Footsteps

Posted: Wed May 07, 2014 4:57 pm
by Spike
vec3_t end, downdir = {0, 0, -1};
VectorMA(ent->origin, 128, downdir, end);
GetNodePoint(ent->origin, end);
change the 128 for different distances.
will fail when you're in the air or standing over a ledge, also when standing on a steep-enough slope.
(although really, if your center of gravity is over the ledge, you ought to fall off anyway!)

Re: Engine Side Footsteps

Posted: Wed May 07, 2014 5:27 pm
by drm_wayne
ahh thx, im still not that good when it comes to the entire vec3_t stuff :wink:
at least it shows now the texturename under me... Now i need to find out how i adapt that to my frootsteps...

Re: Engine Side Footsteps

Posted: Thu May 08, 2014 2:32 am
by r00k
Ya what spike said... though if you are in air you shouldn't make a footstep sound! :)

After playing awhile locally hearing generic footsteps for all surfaces its kinda funny to jump online and play DM and hear nothing.. makes me feel like im sliding around on glass! :O

Quake Live's footsteps makes me want this more and more in online games, but the DM community just DOESNT want it :(

Re: Engine Side Footsteps

Posted: Thu May 08, 2014 5:28 am
by drm_wayne
Actually i dont play them local, i changed the code so they play with bots too :o
But im using "quiet" steps so you cant hear too much, also:
SNOW maps with snow footsteps makes the map feel so better :mrgreen:
You should update the tutorial 8)

Re: Engine Side Footsteps

Posted: Thu May 08, 2014 3:10 pm
by Spike
snow-covered surfaces needs decals or something.

Re: Engine Side Footsteps

Posted: Fri May 09, 2014 2:37 pm
by r00k
drm_wayne wrote:Actually i dont play them local, i changed the code so they play with bots too :o
But im using "quiet" steps so you cant hear too much, also:
SNOW maps with snow footsteps makes the map feel so better :mrgreen:
You should update the tutorial 8)
Ya you can enable them with bots by using

Code: Select all

	if (ent == &cl_entities[cl.viewentity])
		{
			e = (int)cl.viewentity;//play my own footsteps locally
		}
		else
		{
			for (i = 0, p = cl_entities ; i < cl.num_entities ; i++, p++)//FrikBots make footstep sounds too!
			{
				if (p == ent)
				{
					e = i;
				}			
			}
		}
I do have a check for

Code: Select all

if (!((ent->modelindex == cl_modelindex[mi_player])||(ent->modelindex == cl_modelindex[mi_md3_player])))//players or frikbots only
		return;
at the top of the function... so monsters are not included, though it would be cool to hear the stomp of a shambler or the clicky-clack of the vore!
Unfortunately, this will also make footstep sounds for multiplayers too! :O which is why the 1st if statement in the functions is compared to !sv.active to abort in online games.

Re: Engine Side Footsteps

Posted: Thu Aug 06, 2015 12:28 pm
by drm_wayne
Those footsteps are working fine for Quake, but i adapted the code to another mod which seems to use Halfllife
player hullsizes and the footsptes dont play (they only play if you crouch -.-), also this seems not to work with the shamber.
What do i need to change to make them play?

Re: Engine Side Footsteps

Posted: Thu Aug 06, 2015 9:31 pm
by frag.machine
You'll need to change the distance between the entity origin and the dest vector to fit the entity size in use.
This can be done here (change the -32 value to the new Z offset value):

Code: Select all

VectorMA (ent->origin, -32, up, dest);//trace down 
Also, since you're using a different model (with probably different number of frames in the walk/run animations), you'll need to change this part, too.

All these small changes makes clear to me this would be handled in a more elegant way in the QuakeC side, not hardcoded in the engine. Oh well...

Re: Engine Side Footsteps

Posted: Thu Aug 06, 2015 9:45 pm
by drm_wayne
Thanks, i will try it. And yes in qc its easier. :mrgreen:

Re: Engine Side Footsteps

Posted: Tue Aug 11, 2015 5:10 am
by r00k
Yes, originally it was to include sounds based on the material; which i have 99% added just newver made the sounds :(
Darkplaces can do it fine in quakeC, as you can get texture names.

Re: Engine Side Footsteps

Posted: Tue Aug 11, 2015 6:11 am
by drm_wayne
Heres what i have (supports 7 different surface types:)
Needs modified if you want to use the Quakeguy (this has been modified for custom player model)

Code: Select all

/*
==================
CL_Footsteps Stuff
==================
*/

#define		SURFACE_NORMAL 0 // Generic Stone
#define		SURFACE_CARPET 1 // Carpet
#define		SURFACE_GRAVEL 2 // Gravel
#define		SURFACE_METAL  3 // Metal
#define		SURFACE_SNOW   4 // Snow
#define		SURFACE_WOODEN 5 // Wood
#define		SURFACE_DIRT   6 // Dirt n mud

char *nodename = "                 "; // lel nothing xD

float plr_surfacetype;

int RecursiveNodePoint (mnode_t *node, vec3_t start, vec3_t end)
{
   float   front, back, frac;
   vec3_t   mid;
   
loc0:
   if (node->contents < 0)
      return false;      // didn't hit anything
   
// calculate mid point
   if (node->plane->type < 3)
   {
      front = start[node->plane->type] - node->plane->dist;
      back = end[node->plane->type] - node->plane->dist;
   }
   else
   {
      front = DotProduct(start, node->plane->normal) - node->plane->dist;
      back = DotProduct(end, node->plane->normal) - node->plane->dist;
   }

   // optimized recursion
   if ((back < 0) == (front < 0))
   {
      node = node->children[front < 0];
      goto loc0;
   }
   
   frac = front / (front-back);
   mid[0] = start[0] + (end[0] - start[0]) * frac;
   mid[1] = start[1] + (end[1] - start[1]) * frac;
   mid[2] = start[2] + (end[2] - start[2]) * frac;
   
// go down front side
   if (RecursiveNodePoint(node->children[front < 0], start, mid))
   {      
      return true;   // hit something
   }
   else
   {
      int      i, ds, dt;
      msurface_t   *surf;

      surf = cl.worldmodel->surfaces + node->firstsurface;
      for (i = 0 ; i < node->numsurfaces ; i++, surf++)
      {
         ds = (int)((float)DotProduct (mid, surf->texinfo->vecs[0]) + surf->texinfo->vecs[0][3]);
         dt = (int)((float)DotProduct (mid, surf->texinfo->vecs[1]) + surf->texinfo->vecs[1][3]);

         if (ds < surf->texturemins[0] || dt < surf->texturemins[1])
            continue;
         
         ds -= surf->texturemins[0];
         dt -= surf->texturemins[1];
         
         if (ds > surf->extents[0] || dt > surf->extents[1])
            continue;

         //nodename = (surf->texinfo->texture->name);
		if (!Q_strncmp(surf->texinfo->texture->name,"carpet",6))
		plr_surfacetype = SURFACE_CARPET;
		else if (!Q_strncmp(surf->texinfo->texture->name,"ground",6))
		plr_surfacetype = SURFACE_GRAVEL;
		else if (!Q_strncmp(surf->texinfo->texture->name,"metal",5))
		plr_surfacetype = SURFACE_METAL;
		else if (!Q_strncmp(surf->texinfo->texture->name,"snow",4))
		plr_surfacetype = SURFACE_SNOW;
		else if (!Q_strncmp(surf->texinfo->texture->name,"wood",4))
		plr_surfacetype = SURFACE_WOODEN;
		else if (!Q_strncmp(surf->texinfo->texture->name,"wet",3))
		plr_surfacetype = SURFACE_DIRT;		
		else
		plr_surfacetype = SURFACE_NORMAL;			
         return true;
      }   
      return RecursiveNodePoint (node->children[front >= 0], mid, end);
   }
}

void GetNodePoint (vec3_t p, vec3_t   end)
{
   RecursiveNodePoint (cl.worldmodel->nodes, p, end); 
	Con_DPrintf(nodename);
	Con_DPrintf("\n"); 	
}

extern sfx_t	*cl_sfx_st_carpet1;
extern sfx_t	*cl_sfx_st_carpet2;
extern sfx_t	*cl_sfx_st_dirt1;
extern sfx_t	*cl_sfx_st_dirt2;
extern sfx_t	*cl_sfx_st_gravel1;
extern sfx_t	*cl_sfx_st_gravel2;
extern sfx_t	*cl_sfx_st_metal1;
extern sfx_t	*cl_sfx_st_metal2;
extern sfx_t	*cl_sfx_st_snow1;
extern sfx_t	*cl_sfx_st_snow2;
extern sfx_t	*cl_sfx_st_stone1;
extern sfx_t	*cl_sfx_st_stone2;
extern sfx_t	*cl_sfx_st_wood1;
extern sfx_t	*cl_sfx_st_wood2;


/*
============
CL_Footsteps
============
*/

void CL_Footsteps(entity_t   *ent, int frame)
{ 
   if (ent->steptime > cl.time)
      return;
	  
   if (TruePointContents(ent->origin) != CONTENTS_EMPTY)// if in water etc.. no sound
		return;	
//TODO: Add support for the axis soldiers too plz!
	if (frame == 2 || frame == 5 ||	frame == 9|| frame == 15 || frame == 18 || frame == 21) 
   {
      vec3_t dest, forward, right,up;
	  vec3_t end, downdir = {0, 0, -1};
      trace_t   trace;
      float f;
      int   i,e;
      entity_t *p;

      AngleVectors (ent->angles, forward, right, up);

      VectorMA (ent->origin, -42, up, dest);//trace down (Halfllife Player Hulls)
     //VectorMA (ent->origin, -32, up, dest);//trace down (Quake Player Hulls)	  
      memset (&trace, 0, sizeof(trace_t));

      trace.fraction = 1;

      SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, ent->origin, dest, &trace);
	  VectorMA(ent->origin, 128, downdir, end); //change the 128 for different distances
	  GetNodePoint(ent->origin, end);

      if (trace.fraction == 1) //if we didnt hit anything solid  dont make a sound
      {         
        ent->steptime = cl.time + 0.1;//since the player model animates at 10 frames per sec, no need to come back here until time + 1/10...
		//Con_Printf ("trace.fraction == 1\n");	
		return;
      }
      
    e = (int)cl.viewentity;//emit the sound at our location
  
      f = (rand()%4)+1;

		if (plr_surfacetype == SURFACE_NORMAL)
		{
		    if (f == 1)
			S_StartSound(0, 0, cl_sfx_st_stone1, ent->origin, 0.60f, 1.0f);
			else
			S_StartSound(0, 0, cl_sfx_st_stone2, ent->origin, 0.60f, 1.0f);
		}
		if (plr_surfacetype == SURFACE_CARPET)
		{	
		 if (f == 1)		
         S_StartSound(0, 0, cl_sfx_st_carpet1, ent->origin, 0.60f, 1.0f);
		 else
         S_StartSound(0, 0, cl_sfx_st_carpet2, ent->origin, 0.60f, 1.0f);
		}		 
		if (plr_surfacetype == SURFACE_GRAVEL)
		{	
		 if (f == 1)		
         S_StartSound(0, 0, cl_sfx_st_gravel1, ent->origin, 0.60f, 1.0f);
		 else
		 S_StartSound(0, 0, cl_sfx_st_gravel2, ent->origin, 0.60f, 1.0f);
		}			 
		if (plr_surfacetype == SURFACE_METAL)
		{	
		 if (f == 1)		
         S_StartSound(0, 0, cl_sfx_st_metal1, ent->origin, 0.60f, 1.0f);
		 else
		 S_StartSound(0, 0, cl_sfx_st_metal2, ent->origin, 0.60f, 1.0f);
		}
		if (plr_surfacetype == SURFACE_SNOW)
		{	
		 if (f == 1)		
         S_StartSound(0, 0, cl_sfx_st_snow1, ent->origin, 0.60f, 1.0f);
		 else
		 S_StartSound(0, 0, cl_sfx_st_snow2, ent->origin, 0.60f, 1.0f);
		}
		if (plr_surfacetype == SURFACE_DIRT)
		{	
		 if (f == 1)		
         S_StartSound(0, 0, cl_sfx_st_dirt1, ent->origin, 0.60f, 1.0f);
		 else
		 S_StartSound(0, 0, cl_sfx_st_dirt2, ent->origin, 0.60f, 1.0f);
		}		
		if (plr_surfacetype == SURFACE_WOODEN)
		{	
		 if (f == 1)		
         S_StartSound(0, 0, cl_sfx_st_wood1, ent->origin, 0.60f, 1.0f);
		 else
		 S_StartSound(0, 0, cl_sfx_st_wood2, ent->origin, 0.60f, 1.0f);
		}
    ent->steptime = cl.time + 0.3;
   }
}