ApplyKickback

From ZDoom Wiki
Jump to navigation Jump to search

Actor

virtual void ApplyKickback(Actor inflictor, Actor source, int damage, double angle, Name mod, int flags)

Usage

Called by an actor when they're hit by an attack and must be pushed by it, in accordance with the ProjectileKickback or Weapon.KickBack property of the attack inflictor. This function can be overridden to make class-specific changes to the kickback behavior.

By default, the function tries to apply ProjectileKickback (if inflictor is present and is a projectile), or, if the attacker is a player, the Weapon.KickBack property of the player's current weapon. Otherwise, the defkickback MAPINFO property will be used. The function also accounts for the KickbackFactor value of the current skill.

Parameters

  • Actor inflictor
The actor dealing the damage. This is the missile for projectiles and the puff for hitscan attacks. For monster melee attacks this is the same as the source.
  • Actor source
The actor responsible for the inflictor.
  • int damage
The amount of damage to deal.
  • double angle
The absolute angle for thrusting enemies from the damage if DMG_USEANGLE is set.
  • Name mod
The damage type applied to the attack. Regular attacks use 'Normal', hitscan attacks use 'Hitscan'.
  • int flags - The damage flags to use in the attack:
  • DMG_NO_ARMOR - The attack won't call AbsorbDamage on any of the victim's inventory items.
  • DMG_NO_PAIN - The attack will not cause the victim to enter their Pain state sequence.
  • DMG_INFLICTOR_IS_PUFF - Used by ApplyKickback to determine whether the origin should be the source (if the flag is set) or the inflictor. Automatically set by hitscan attacks.
  • DMG_THRUSTLESS - The attack won't call ApplyKickback on the victim.
  • DMG_FORCED - The attack ignores all damage negation flags/properties the victim has, such as NODAMAGE, and doesn't call special damage functions e.g. TakeSpecialDamage. Players with the NODAMAGE flag, god2, or buddha2 cheats are immune due to potential abuse.
  • DMG_NO_FACTOR - The attack won't apply the victim's damage factors.
  • DMG_PLAYERATTACK - Set if the attack came from a hitscan weapon fired by a player.
  • DMG_FOILINVUL - The attack ignores the INVULNERABLE flag if the victim has it set.
  • DMG_FOILBUDDHA - The attack ignores the BUDDHA flag if the victim has it set.
  • DMG_NO_PROTECT - The attack won't call ModifyDamage or AbsorbDamage on any of the victim's inventory items.
  • DMG_NO_ENHANCE - The attack won't call ModifyDamage on any of the source's inventory items.
  • DMG_USEANGLE - The attack will use the angle parameter when applying kickback instead of having ApplyKickback calculate the angle from the origin of the attack.
  • DMG_EXPLOSION - The attack will be marked as splash damage from an explosion. This is set automatically if the damage came from an explosive projectile.
Note: The list of flags is the same as used by DamageMobj and other damage-related functions, but, naturally, this function will not be called if DMG_THRUSTLESS is used.

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.
virtual void ApplyKickback(Actor inflictor, Actor source, int damage, double angle, Name mod, int flags)
{
	double ang;
	int kickback;
	double thrust;

	if (inflictor && inflictor.projectileKickback)
		kickback = inflictor.projectileKickback;
	else if (!source || !source.player || !source.player.ReadyWeapon)
		kickback = gameinfo.defKickback;
	else
		kickback = source.player.ReadyWeapon.Kickback;

	kickback = int(kickback * G_SkillPropertyFloat(SKILLP_KickbackFactor));
	if (kickback)
	{
		Actor origin = (source && (flags & DMG_INFLICTOR_IS_PUFF)) ? source : inflictor;

		if (flags & DMG_USEANGLE)
		{
			ang = angle;
		}
		else if (origin.pos.xy == pos.xy)
		{
			// If the origin and target are in exactly the same spot, choose a random direction.
			// (Most likely cause is from telefragging somebody during spawning because they
			// haven't moved from their spawn spot at all.)
			ang = frandom[Kickback](0., 360.);
		}
		else
		{
			ang = origin.AngleTo(self);
		}

		thrust = mod == 'MDK' ? 10 : 32;
		if (Mass > 0)
		{
			thrust = clamp((damage * 0.125 * kickback) / Mass, 0., thrust);
		}

		// Don't apply ultra-small damage thrust
		if (thrust < 0.01) thrust = 0;

		// make fall forwards sometimes
		if ((damage < 40) && (damage > health)
			&& (pos.Z - origin.pos.Z > 64)
			&& random[Kickback](0, 1)
			// [RH] But only if not too fast and not flying
			&& thrust < 10
			&& !bNoGravity
			&& !bNoForwardFall
			&& (inflictor == NULL || !inflictor.bNoForwardFall)
			)
		{
			ang += 180.;
			thrust *= 4;
		}
		if (source && source.player && (flags & DMG_INFLICTOR_IS_PUFF)
			&& source.player.ReadyWeapon != NULL &&	(source.player.ReadyWeapon.bSTAFF2_KICKBACK))
		{
			// Staff power level 2
			Thrust(10, ang);
			if (!bNoGravity)
			{
				Vel.Z += 5.;
			}
		}
		else
		{
			Thrust(thrust, ang);
		}
	}
}

Examples

Nuvolachalk.png Note: This article lists no examples. If you make use of this feature in your own project(s) or know of any basic examples that could be shared, please add them. This will make it easier to understand for future authors seeking assistance. Your contributions are greatly appreciated.


See also