Chainsaw negates projectile impact thrust


When an actor receives damage, it is also pushed back (or, occasionally, forward, if damage is less than 40 but was sufficient to kill the victim) but there is a hardcoded exception for if the damage was inflicted by a player wielding a chainsaw. The intent is to prevent the chainsaw from pushing away its victims.

However, it does not check if the damage is actually inflicted by the chainsaw, only if it is inflicted by the player and the player has the chainsaw as their current weapon. Therefore it is possible, when using projectile weapons, to shoot and then switch to the chainsaw before the projectile impacts, negating the damage thrust.


Excerpt from P_DamageMobj(), lines 804 to 833 of p_inter.c: the if check verifies that there is an inflictor, that the target is not noclipping, and that there isn't a source, or that this source isn't a player, or that this player does not have the chainsaw equipped. Note that source and inflictor are usually pointers to the same object, except for explosion damage where source is normally set to inflictor's own target pointer; which means that when firing a rocket, inflictor will be the rocket while source will be the player (or cyberdemon) that shot the rocket.

    // Some close combat weapons should not
    // inflict thrust and push the victim out of reach,
    // thus kick away unless using the chainsaw.
    if (inflictor
	&& !(target->flags & MF_NOCLIP)
	&& (!source
	    || !source->player
	    || source->player->readyweapon != wp_chainsaw))
	ang = R_PointToAngle2 ( inflictor->x,
	thrust = damage*(FRACUNIT>>3)*100/target->info->mass;

	// make fall forwards sometimes
	if ( damage < 40
	     && damage > target->health
	     && target->z - inflictor->z > 64*FRACUNIT
	     && (P_Random ()&1) )
	    ang += ANG180;
	    thrust *= 4;
	target->momx += FixedMul (thrust, finecosine[ang]);
	target->momy += FixedMul (thrust, finesine[ang]);