Engine Side Footsteps

Post tutorials on how to do certain tasks within game or engine code here.
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post 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 ;)
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post 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?);
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Engine Side Footsteps

Post 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!)
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post 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...
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Engine Side Footsteps

Post 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 :(
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post 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)
Spike
Posts: 2914
Joined: Fri Nov 05, 2004 3:12 am
Location: UK
Contact:

Re: Engine Side Footsteps

Post by Spike »

snow-covered surfaces needs decals or something.
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Engine Side Footsteps

Post 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.
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post 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?
frag.machine
Posts: 2126
Joined: Sat Nov 25, 2006 1:49 pm

Re: Engine Side Footsteps

Post 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...
I know FrikaC made a cgi-bin version of the quakec interpreter once and wrote part of his website in QuakeC :) (LordHavoc)
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post by drm_wayne »

Thanks, i will try it. And yes in qc its easier. :mrgreen:
r00k
Posts: 1111
Joined: Sat Nov 13, 2004 10:39 pm

Re: Engine Side Footsteps

Post 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.
drm_wayne
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Post 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;
   }
}

Post Reply