MakeFootsteps

From ZDoom Wiki
Jump to navigation Jump to search

(development version 12d1afc only)

PlayerPawn

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

	}

See also