public static float WeaponDamageRevDistance(ICombatant attacker, ICombatant target, Weapon weapon, float damage, float rawDamage) { var damagePerShot = weapon.DamagePerShot; var adjustment = rawDamage / damagePerShot; float varianceMultiplier; var distance = Vector3.Distance(attacker.TargetPosition, target.TargetPosition); var distanceDifference = weapon.MaxRange - distance; var distanceRatio = distanceDifference / weapon.MinRange; var baseMultiplier = CustomAmmoCategories.getWeaponDistantVariance(weapon); var distanceBasedFunctionMultiplier = (float)Math.Atan(1f / (Pi2 * distanceRatio + baseMultiplier)); if (distance < weapon.MinRange) { varianceMultiplier = 0; } else if (distance <= weapon.MaxRange) { varianceMultiplier = Mathf.Max( baseMultiplier, Mathf.Min( 1.0f, distanceBasedFunctionMultiplier )); } else // out of range ¯\_(ツ)_/¯ { return(damage); } var computedDamage = damage * varianceMultiplier * adjustment; CustomAmmoCategoriesLog.Log.LogWrite($"reverseDistanceBasedFunctionMultiplier: {distanceBasedFunctionMultiplier}\n" + $"defId: {weapon.defId}\n" + $"varianceMultiplier: {varianceMultiplier}\n" + $"adjustment: {adjustment}\n" + $"damage: {damage}\n" + $"distance: {distance}\n" + $"max: {weapon.MaxRange}\n" + $"distanceDifference {distanceDifference}\n" + $"baseMultplier: {baseMultiplier}\n" + $"distanceRatio: {distanceRatio}\n" + $"computedDamage: {computedDamage}\n"); return(computedDamage); }