MakeFootsteps
(development version 12d1afc only)
virtual void MakeFootsteps ()
Usage
Note: This function requires the player pawn in question to have the MAKEFOOTSTEPS flag set to run. |
Handles the playing of player footstep sounds. By default, this function works on terrains with the WalkStepTics, RunStepTics, the (Left/Right)StepSounds, and StepVolume properties set. Essentially just giving a built-in use for all those terrain properties. It also spawns the terrains' splash if splashes are assigned, such as for walking on a liquid.
If a terrain uses the StepDistance and, optionally, the StepDistanceMinVel properties instead, they will take precedence over the above properties, allowing for a distance-based interval for terrains instead.
However, being a virtual method, the function can also be overridden, such as to be extended or entirely replaced with a different footstep system, such as one that only uses a terrain's StepSounds, and scales the frequency and volume of the sound based on the player's velocity, regardless of terrain properties.
ZScript definition
Note: The ZScript definition below is for reference and may be different in the current version of GZDoom.The most up-to-date version of this code can be found on GZDoom GitHub. |
This is the ZScript code of the default footstep system, including the DoFootstep function, the built-in system uses.
//---------------------------------------------------------------------------
//
// Handle player footstep sounds.
// Default footstep handling.
//
//---------------------------------------------------------------------------
int footstepCounter;
double footstepLength;
bool footstepFoot;
void DoFootstep(TerrainDef Ground)
{
Sound Step = Ground.StepSound;
//Generic foot-agnostic sound takes precedence.
if(!Step)
{
//Apparently most people walk with their right foot first, so assume that here.
if (!footstepFoot)
{
Step = Ground.LeftStepSound;
}
else
{
Step = Ground.RightStepSound;
}
footstepFoot = !footstepFoot;
}
if(Step)
{
A_StartSound(Step, flags: CHANF_OVERLAP, volume: Ground.StepVolume * snd_footstepvolume);
}
//Steps make splashes regardless.
bool Heavy = (Mass >= 200) ? 0 : THW_SMALL; //Big player makes big splash.
HitWater(CurSector, (Pos.XY, CurSector.FloorPlane.ZatPoint(Pos.XY)), true, false, flags: Heavy | THW_NOVEL);
}
virtual void MakeFootsteps()
{
if(pos.z > floorz) return;
let Ground = GetFloorTerrain();
if(Ground && (player.cmd.forwardMove != 0 || player.cmd.sideMove != 0))
{
int Delay = (player.cmd.buttons & BT_RUN) ? Ground.RunStepTics : Ground.WalkStepTics;
if((player.cmd.buttons ^ player.oldbuttons) & BT_RUN)
{ // zero out counters when starting/stopping a run
footstepCounter = 0;
footstepLength = Ground.StepDistance;
}
if(Ground.StepDistance > 0)
{ // distance-based terrain
footstepCounter = 0;
double moveVel = vel.xy.length();
if(moveVel > Ground.StepDistanceMinVel)
{
footstepLength += moveVel;
while(footstepLength > Ground.StepDistance)
{
footstepLength -= Ground.StepDistance;
DoFootstep(Ground);
}
}
else
{
footstepLength = Ground.StepDistance;
}
}
else if(Delay > 0)
{ // delay-based terrain
footstepLength = 0;
if(footstepCounter % Delay == 0)
{
DoFootstep(Ground);
}
footstepCounter = (footstepCounter + 1) % Delay;
}
}
else
{
footstepCounter = 0;
footstepLength = Ground.StepDistance;
footstepFoot = false;
}
}