Forum

Engine Side Footsteps

Post tutorials on how to do certain tasks within game or engine code here.

Moderator: InsideQC Admins

Engine Side Footsteps

Postby r00k » Mon Jan 04, 2010 8:18 pm

description: quick and dirty footstep sounds engine tutorial.
---------------------------------------------------------------------------------
purpose: adds footstep sounds to local gameplay.
---------------------------------------------------------------------------------
future expansion: different sounds for different surfaces and different speeds.
---------------------------------------------------------------------------------
First thing we need to do is precache the sound effects internally in the engine.

Open up cl_tent.c

near the top of the file look for the other sound effects precaches
and add these under sfx_t *cl_sfx_r_exp3,

Code: Select all
sfx_t      *cl_sfx_step1;
sfx_t      *cl_sfx_step2;
sfx_t      *cl_sfx_step3;
sfx_t      *cl_sfx_step4;


scroll down and find void CL_InitTEnts (void)
and add these precaches to be initialized.
Code: Select all
   cl_sfx_step1      = S_PrecacheSound ("misc/step1.wav");   
   cl_sfx_step2      = S_PrecacheSound ("misc/step2.wav");   
   cl_sfx_step3      = S_PrecacheSound ("misc/step3.wav");      
   cl_sfx_step4      = S_PrecacheSound ("misc/step4.wav");   


NOTE: you are going to have to find your own .wav files for the sounds and put them in quake/id1/sound/misc

okay now open up cl_main.c

near the top around all the other cvar_t definitions add,

Code: Select all
cvar_t   cl_footsteps      = {"cl_footsteps", "0", true};


now look for CL_Init and register the variable,

Code: Select all
     Cvar_RegisterVariable (&cl_footsteps);   


Scroll back to the top of the file in cl_main.c and add this code block prior to CL_RelinkEntities,

Code: Select all
void CL_Footsteps(entity_t   *ent, int frame)
{
   extern   sfx_t      *cl_sfx_step1;
   extern   sfx_t      *cl_sfx_step2;
   extern   sfx_t      *cl_sfx_step3;
   extern   sfx_t      *cl_sfx_step4;

   if (ent->steptime > cl.time)//Timer to sync with player animations
      return;

   if (ent != &cl_entities[cl.viewentity])//check if it's our player
      return; //only play our OWN footsteps! no multiplayer hax!
   
   if (TruePointContents(ent->origin) != CONTENTS_EMPTY)// if in water etc.. no sound
      return;

   if (frame == 2 || frame == 5 ||   frame == 7 || frame == 10)//check for run frames
   {
      vec3_t   dest, forward, right,up;
      trace_t   trace;
      float f;
      int   i,e;
      entity_t *p;

      AngleVectors (ent->angles, forward, right, up);
      
      VectorMA (ent->origin, -32, up, dest);//trace down
         
      memset (&trace, 0, sizeof(trace_t));

      trace.fraction = 1;

      SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, ent->origin, dest, &trace);

      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...
         return;
      }
      
      f = (rand()%4)+1;

      e = (int)cl.viewentity;//emit the sound at our location
      
      if (f == 1)
         S_StartSound(e, 0, cl_sfx_step1, ent->origin, 0.40f, 1.0f);
      else if (f == 2)
         S_StartSound(e, 0, cl_sfx_step2, ent->origin, 0.40f, 1.0f);
      else if (f == 3)
         S_StartSound(e, 0, cl_sfx_step3, ent->origin, 0.40f, 1.0f);
      else
         S_StartSound(e, 0, cl_sfx_step4, ent->origin, 0.40f, 1.0f);
      
      ent->steptime = cl.time + 0.3;
   }
}


now scroll down into CL_RelinkEntites and add this bit of code before ent->forcelink = true;

Code: Select all
      if (cl_footsteps.value)
         CL_Footsteps(ent,ent->frame);


one last thing we need to do is add a timer to make the sound, so open up render.h and find the entity_s definition and add
to the end, like this
Code: Select all
   double   steptime;
} entity_t;
r00k
 
Posts: 1108
Joined: Sat Nov 13, 2004 10:39 pm

Postby Team Xlink » Mon Jan 04, 2010 8:40 pm

This is a very good tutorial and has much use to avoid tricky qc code. It allows you to play have sounds for footsteps in all mods. Thank you.

I am still intrigued by your mention of the future expansion's different footsteps for different surfaces, this would be great.

For example your running in a shallow puddle of water so you want to hear the small splash sounds, then you come up to a middle surface it then plays the ting sounds, so on and so fourth.

EDIT: Does anyone have any good sound files for this? My sound files aren't that good.
Team Xlink
 
Posts: 368
Joined: Thu Jun 25, 2009 4:45 am
Location: Michigan

Postby Downsider » Mon Jan 04, 2010 9:56 pm

I'm pretty sure that when you trace against a face in the engine you can grab its texture name directly from the information returned, which could easily be your solution to getting surface-specific sounds.
User avatar
Downsider
 
Posts: 621
Joined: Tue Sep 16, 2008 1:35 am

Re: Engine Side Footsteps

Postby Baker » Mon Jan 04, 2010 9:58 pm

Is there a way to query what texture a player is walking on (Surface flags) like in Half-Life?

For instance, to play a different wav if the texture begins with "stone_" or "metal_".
User avatar
Baker
 
Posts: 3666
Joined: Tue Mar 14, 2006 5:15 am

Postby goldenboy » Mon Jan 04, 2010 10:23 pm

Some of the multiplayer types argue that footsteps are bad, or cheating.

Also, mods will want to use their own footstep sounds, plus monster footsteps, like RemakeQuake does.

It's not really hard to do in QC - I think this should be left to individual mods. See RMQ source.

I would get pissed if an engine "overwrote" my carefully selected and randomized footstep sounds.

Edit: It would be nice, however, if the engine provided surface detection which could then be used by the footstep QC code.
User avatar
goldenboy
 
Posts: 924
Joined: Fri Sep 05, 2008 11:04 pm
Location: Kiel

Postby r00k » Mon Jan 04, 2010 10:50 pm

Actually this doesnt provide a hack for multiplayer at all because it only plays your own footsteps. Also this shouldnt piss off modders cause it doesnt change monsters footsteps and the player footstep sounds can be copied to /sounds/misc. I think i would map out areas based on the origin, like how .locs are used. have an .fsm (footstep materail) file defined. That way at runtime im just comparing location to array not traceline collision detection.

It can be expanded to have custom monster sounds. The only real benefit of this is adding footsteps to mods that dont have them.

I think you are in your right that if your mod supports footsteps there should be a SVC_ trigger or ruleset or atleast you can stuffcmd to the client "cl_footstep 0\n", that way it will use your media/code instead.
Last edited by r00k on Mon Jan 04, 2010 11:02 pm, edited 2 times in total.
r00k
 
Posts: 1108
Joined: Sat Nov 13, 2004 10:39 pm

Re: Engine Side Footsteps

Postby mh » Mon Jan 04, 2010 10:54 pm

Baker wrote:Is there a way to query what texture a player is walking on (Surface flags) like in Half-Life?

For instance, to play a different wav if the texture begins with "stone_" or "metal_".

R_LightPoint will give you it. :D

I'm in two minds though about doing this via QC in preference to the engine. A part of me wants to agree bigtime, but another part of me says that the engine has access to so much more info than QC does, and that doing it via the engine gives players the option to switch footsteps off by a cvar if they find them annoying. And players are the most important thing at the end of the day, aren't they?

I reckon the engine wins this one so far as I'm concerned. Perhaps a good meet-in-the-middle option might be to make this footstep code extensible via QC (it would need to move to server-side for that, but shouldn't need a new protocol as the standard server-side sound spawning should work fine).

Say let QC control the volume, the sounds used, etc. Provide some new builtins and we're done.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2287
Joined: Sat Jan 12, 2008 1:38 am

Postby goldenboy » Tue Jan 05, 2010 1:41 am

Yes, QC / the mod needs to control the sounds used and how they are used. There can be default sounds that the engine would supply, but as soon as a mod brings its own sound files along, control should shift to the mod.

RMQ uses much more than 4 footstep sound files, too. So that would be a possible clash. Requiring mods to provide exactly n footstep sounds is problematic. The engine should only offer an interface to the mod.

An engine that played the crappy hipnotic footsteps instead of the RMQ ones would make me want to shoot somebody.

Finally, disabling footstep sounds should be done by the mod, too, possibly via an impulse.
User avatar
goldenboy
 
Posts: 924
Joined: Fri Sep 05, 2008 11:04 pm
Location: Kiel

Postby Teiman » Fri Jan 08, 2010 4:18 pm

Telejano has footsteps builtin, I even have different sounds for different mosters.

Is a nice feature, and really adds to the game.
Teiman
 
Posts: 309
Joined: Sun Jun 03, 2007 9:39 am

Postby mh » Fri Jan 08, 2010 4:20 pm

goldenboy wrote:Finally, disabling footstep sounds should be done by the mod, too, possibly via an impulse.
So long as it doesn't override what the player wants I'd agree.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2287
Joined: Sat Jan 12, 2008 1:38 am

Re: Engine Side Footsteps

Postby drm_wayne » Sun May 04, 2014 5:51 pm

mh wrote:
Baker wrote:Is there a way to query what texture a player is walking on (Surface flags) like in Half-Life?

For instance, to play a different wav if the texture begins with "stone_" or "metal_".

R_LightPoint will give you it. :D

Sorry for bumping this, but i adapted it to my engine and i wonder how exactly "R_LightPoint" will work gettign the texture name??
Can somebody explain it?
User avatar
drm_wayne
 
Posts: 232
Joined: Sat Feb 11, 2012 5:47 pm

Re: Engine Side Footsteps

Postby mh » Sun May 04, 2014 10:34 pm

drm_wayne wrote:
mh wrote:
Baker wrote:Is there a way to query what texture a player is walking on (Surface flags) like in Half-Life?

For instance, to play a different wav if the texture begins with "stone_" or "metal_".

R_LightPoint will give you it. :D

Sorry for bumping this, but i adapted it to my engine and i wonder how exactly "R_LightPoint" will work gettign the texture name??
Can somebody explain it?


R_LightPoint will get you the lighting for an object from the msurface_t under it. It also gets you the lightspot (a position in 3D space where the trace intersects the surface) and the plane, which are used for Quake's crap planar shadows. It's a small enough thing to also save out surf->texinfo->texture.

The object may not be in direct contact with the surface but for the player you can then use cl.onground to determine if it is (you may also need cl.inwater, it's been a while). If you want footsteps on monsters you could put something together from the object's bounding box and the distance between the entity origin and the saved-out lightspot (monsters don't send SU_ONGROUND or SU_INWATER). Beware of MDL bounding boxes here: they need to be fixed in the engine to make this work too (if you do it server-side you'll get access to a lot more info, of course, but you'll need to implement a server-side version of R_LightPoint too). You'd also need to hack something up for if the object is standing on a brush model, and again for BSP models. It's up to you to decide at what point this crosses the line between "a technically interesting challenge" and "a gigantic pain in the ass".

Quake doesn't have surface flags so you need to hack something from the texture name if you want different sounds for metal, wood, grass, etc. That will break down if one of those wacky modders decides to use texture names like "dkfgjbakshdv" (and then pulls a fit of passive-agressive whining and "I can't understand why we can't do it if HL2 can" on you when you try to point this out). There's nothing you can do about that, so it's better to just accept that your chosen technology can't do what you want to do and use a sound that's tweaked to sound not-particularly-dreadful with everything. Or else choose a different technology that can.
We had the power, we had the space, we had a sense of time and place
We knew the words, we knew the score, we knew what we were fighting for
User avatar
mh
 
Posts: 2287
Joined: Sat Jan 12, 2008 1:38 am

Re: Engine Side Footsteps

Postby goldenboy » Mon May 05, 2014 7:05 pm

Hi mh :)

My evil hacky modder idea how to do surface dependant footsteps in a Quake mod has to do with simply placing triggers on top of every walkable surface.

A hack? Sure! Workable? Totally! Next problem!
User avatar
goldenboy
 
Posts: 924
Joined: Fri Sep 05, 2008 11:04 pm
Location: Kiel

Re: Engine Side Footsteps

Postby r00k » Mon May 05, 2014 10:12 pm

i have already implemented this 90%...

Code: Select all

char *nodename = "                 ";

int RecursiveNodePoint (mnode_t *node, vec3_t start, vec3_t end)
{
   float   front, back, frac;
   vec3_t   mid;
   void DrawGLPolyHighlight(glpoly_t *p);
   
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;
   
         if (developer.value)
            DrawGLPolyHighlight(surf->polys);

         nodename = (surf->texinfo->texture->name);
         return true;
      }

   // go down back side      
      return RecursiveNodePoint (node->children[front >= 0], mid, end);
   }
}

void GetNodePoint (vec3_t p, vec3_t   end)
{
   RecursiveNodePoint (cl.worldmodel->nodes, p, end);   
   SCR_CenterPrint (nodename);   
}


and then i just call GetNodePoint in the footstep code to get the name of the texture im standing on. I havent completed this but it would just parse the texturename and point it to a precached sound file.
But as MH says, texturenames do not have any strict syntax. Then there is the issues with brush models.

BTW MH, compiling the Jan 2012 RMQ SDK renders missing polygons on world surfaces :(
r00k
 
Posts: 1108
Joined: Sat Nov 13, 2004 10:39 pm

Re: Engine Side Footsteps

Postby qbism » Tue May 06, 2014 12:07 am

goldenboy wrote:My evil hacky modder idea how to do surface dependant footsteps in a Quake mod has to do with simply placing triggers on top of every walkable surface.
Wasn't there a mod that used a brute-force texture list file (read with frikfile) to determine footstep sounds? If mostly new textures, could encode 'surface flags' in the texture names to be decoded by qc. However, much could be done with audio triggers... put them off ledges to play "whoosh" or "oh shizzle!!" when player falls.
User avatar
qbism
 
Posts: 1236
Joined: Thu Nov 04, 2004 5:51 am

Next

Return to Programming Tutorials

Who is online

Users browsing this forum: No registered users and 1 guest