DIFF

FlashGrenade.c

class FlashGrenade extends Grenade_Base
{
	const float FX_RANGE_MAX_MULT = 1.0;
	
	override void OnExplosionEffects(Object source, Object directHit, int componentIndex, string surface, vector pos, vector surfNormal, float energyFactor, float explosionFactor, bool isWater, string ammoType)
	{
		super.OnExplosionEffects(source, directHit, componentIndex, surface, pos, surfNormal, energyFactor, explosionFactor, isWater, ammoType);

		PlayerBase player = PlayerBase.Cast(g_Game.GetPlayer());

		if (player)
		{
			vector headPos 			= player.GetDamageZonePos("Head"); // animated position in the middle of the zone
			float ammoRangeKill	 	= g_Game.ConfigGetFloat(string.Format("CfgAmmo %1 indirectHitRange", ammoType));
			float ammoRangeMaxMult 	= 4.0;
			
			string indirectHitRangeMultiplier = string.Format("CfgAmmo %1 indirectHitRangeMultiplier", ammoType);
			if (g_Game.ConfigIsExisting(indirectHitRangeMultiplier))
			{
				//! values less than 1.0 make no sense
				ammoRangeMaxMult = Math.Clamp(g_Game.ConfigGetFloat(indirectHitRangeMultiplier), 1.0, float.MAX);
			}

			float ammoRangeMax = ammoRangeKill * ammoRangeMaxMult;
			ammoRangeMax = Math.Clamp(ammoRangeMax * FX_RANGE_MAX_MULT, ammoRangeKill, ammoRangeMax);
			
			float dist			= vector.Distance(headPos, pos);
			float distSq 		= vector.DistanceSq(headPos, pos);
			float radiusMaxSq = Math.SqrFloat(ammoRangeMax);
			
			if (distSq <= radiusMaxSq)
			{
				// ignore collisions with parent if fireplace
				InventoryItem invItem = InventoryItem.Cast(source);
				EntityAI parent = invItem.GetHierarchyParent();
				array<Object> excluded = new array<Object>;
				
				if (!parent || !parent.IsFireplace())
					parent = null;
				else if (parent)
					excluded.Insert(parent);
				
				array<ref RaycastRVResult> results = new array<ref RaycastRVResult>;
				excluded.Insert(this); //Ignore self for visibility check
				
				//There shouldn't be cases justifying we go further than first entry (if in fireplace, self does not impact)
				RaycastRVParams rayParams	= new RaycastRVParams(pos, headPos, excluded[0]);
				rayParams.flags				= CollisionFlags.ALLOBJECTS;
				DayZPhysics.RaycastRVProxy(rayParams, results, excluded);

				//! removes possible obstacles made by items around the grenade(or on the same position)
				array<Object> hitObjects = new array<Object>;
				for (int i = 0; i < results.Count(); i++)
				{
					if (results[i].obj && !results[i].obj.IsInherited(ItemBase))
					{
						hitObjects.Insert(results[i].obj);
					}
				}

				//If player is not first index, object is between player and grenade
				if (hitObjects.Count() && PlayerBase.Cast(hitObjects[0]))
				{
					float effectCoef;
					if (ammoRangeMax == ammoRangeKill)
					{
						effectCoef = 1.0; //edge case, landed right on the edge
					}
					effectCoef = 1 - ((dist - ammoRangeKill) / (ammoRangeMax - ammoRangeKill));
					effectCoef = Math.Clamp(effectCoef, 0.1, 100.0);

					player.OnPlayerReceiveFlashbangHitStart(MiscGameplayFunctions.IsPlayerOrientedTowardPos(player, pos, 60));
					player.GetFlashbangEffect().SetupFlashbangValues(effectCoef, effectCoef, effectCoef);
				}
			}
		}
	}

	void FlashGrenade()
	{
		SetAmmoType("FlashGrenade_Ammo");
		SetFuseDelay(2);
		SetGrenadeType(EGrenadeType.ILLUMINATING);
		SetParticleExplosion(ParticleList.GRENADE_M84);
	}
	
	protected override void CreateLight()
	{
		m_Light = ExplosiveLight.Cast(ScriptedLightBase.CreateLight(FlashGrenadeLight, GetPosition()));
	}

	void ~FlashGrenade() {}
}