bulletimpactbase.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. class EffBulletImpactBase : EffectParticle
  2. {
  3. static const int SURVIVOR_HEAD = 0; // Head component
  4. static const int INFECTED_HEAD = 3; // Head component
  5. static float DEFAULT_PROJECTILE_WEIGHT = 0.015;
  6. float MIN_SCALING_PARAM = 0.1;
  7. Object m_DirectHit;
  8. float m_StoppingForce;
  9. float m_Weight; // projectile weight in kg
  10. int m_ImpactType;
  11. int m_ComponentIndex;
  12. vector m_Pos;
  13. vector m_SurfNormal;
  14. vector m_ExitPos;
  15. vector m_InSpeed;
  16. vector m_OutSpeed;
  17. string m_AmmoType;
  18. static vector INVALID = "0 0 0";
  19. // Particle Effects
  20. int m_ParticleEnter = -1;
  21. int m_ParticleExit = -1;
  22. int m_ParticleRicochet = -1;
  23. // Calculations
  24. float m_EnterSplashCoef = 0.003;
  25. float m_ExitSplashCoef = 0.002;
  26. float m_RicochetSplashCoef = 0.002;
  27. float m_EnterAngledSplashCoef = 0.01;
  28. float m_AngledEnter = 0.40;
  29. void EffBulletImpactBase()
  30. {
  31. }
  32. override void OnCheckUpdate()
  33. {
  34. //DbgUI.Text( m_ammoType );
  35. }
  36. void SetEnterParticle(int id)
  37. {
  38. m_ParticleEnter = id;
  39. }
  40. void SetExitParticle(int id)
  41. {
  42. m_ParticleExit = id;
  43. }
  44. void SetRicochetParticle(int id)
  45. {
  46. m_ParticleRicochet = id;
  47. }
  48. void SetSingleParticle(int id)
  49. {
  50. SetEnterParticle(id);
  51. SetExitParticle(id);
  52. SetRicochetParticle(id);
  53. }
  54. void SetAngledEnterValue(float f)
  55. {
  56. m_AngledEnter = f;
  57. }
  58. void EvaluateEffect(Object directHit, int componentIndex, vector pos, int impact_type, vector surfNormal, vector exitPos, vector inSpeed, vector outSpeed, string ammoType)
  59. {
  60. m_DirectHit = directHit;
  61. m_Pos = pos;
  62. m_ImpactType = impact_type;
  63. m_ComponentIndex = componentIndex;
  64. m_SurfNormal = surfNormal;
  65. m_ExitPos = exitPos;
  66. m_InSpeed = inSpeed;
  67. m_OutSpeed = outSpeed;
  68. m_AmmoType = ammoType;
  69. m_Weight = GetGame().ConfigGetFloat("CfgAmmo " + ammoType + " weight");
  70. m_StoppingForce = CalculateStoppingForce(m_InSpeed.Length(), m_OutSpeed.Length(), ammoType, m_Weight);
  71. }
  72. float CalculateStoppingForce(float in_speedf, float out_speedf, string ammoType, float weight)
  73. {
  74. if ( m_ImpactType == ImpactTypes.MELEE )
  75. {
  76. return Math.RandomFloat(50, 100);
  77. }
  78. float projectile_weight_coef = weight / DEFAULT_PROJECTILE_WEIGHT;
  79. float stopping_force = (in_speedf - out_speedf) * projectile_weight_coef;
  80. return stopping_force;
  81. }
  82. void OnEnterCalculations( Particle p )
  83. {
  84. // All values represent scale
  85. float velocity_min = (m_StoppingForce * m_EnterSplashCoef);
  86. float velocity_max = (m_StoppingForce * m_EnterSplashCoef);
  87. float size = (m_StoppingForce * m_EnterSplashCoef);
  88. float birth_rate = (m_StoppingForce * m_EnterSplashCoef);
  89. float air_resistance = velocity_min;
  90. float lifetime = (m_StoppingForce * m_EnterSplashCoef);
  91. float lifetime_rnd = (m_StoppingForce * m_EnterSplashCoef);
  92. if ( m_AmmoType == "Bullet_12GaugePellets" )
  93. {
  94. birth_rate *= 0.5;
  95. velocity_min *= 2;
  96. velocity_max *= 2;
  97. }
  98. if (velocity_min < 0.75)
  99. velocity_min = 0.75;
  100. if (size < 0.75)
  101. size = 0.75;
  102. if (lifetime < 0.5)
  103. lifetime = 0.5;
  104. if (lifetime_rnd < 0.5)
  105. lifetime_rnd = 0.5;
  106. if (velocity_max < 1)
  107. velocity_max = 1;
  108. /*Print("===============");
  109. Print(velocity_min);
  110. Print(velocity_max);
  111. Print(size);
  112. Print(birth_rate);
  113. Print(air_resistance);
  114. Print(lifetime);
  115. Print(lifetime_rnd);*/
  116. p.ScaleParticleParam(EmitorParam.VELOCITY, velocity_min);
  117. p.ScaleParticleParam(EmitorParam.VELOCITY_RND, velocity_max);
  118. p.ScaleParticleParam(EmitorParam.SIZE, size);
  119. p.ScaleParticleParam(EmitorParam.BIRTH_RATE, birth_rate);
  120. p.ScaleParticleParam(EmitorParam.AIR_RESISTANCE, air_resistance);
  121. p.ScaleParticleParam(EmitorParam.AIR_RESISTANCE_RND, air_resistance);
  122. p.ScaleParticleParam(EmitorParam.LIFETIME, lifetime);
  123. p.ScaleParticleParam(EmitorParam.LIFETIME_RND, lifetime_rnd);
  124. }
  125. void OnExitCalculations(Particle p, float outSpeedf)
  126. {
  127. float velocity_min = 1 + (outSpeedf * m_ExitSplashCoef);
  128. float velocity_max = 1 + (outSpeedf * m_ExitSplashCoef);
  129. float size = 1 + ( outSpeedf * m_ExitSplashCoef);
  130. float birth_rate = 1 + (outSpeedf * m_ExitSplashCoef);
  131. if (velocity_min < MIN_SCALING_PARAM)
  132. velocity_min = MIN_SCALING_PARAM;
  133. if (size < MIN_SCALING_PARAM)
  134. size = MIN_SCALING_PARAM;
  135. if (birth_rate < MIN_SCALING_PARAM)
  136. birth_rate = MIN_SCALING_PARAM;
  137. p.ScaleParticleParam(EmitorParam.VELOCITY, velocity_min);
  138. p.ScaleParticleParam(EmitorParam.VELOCITY_RND, velocity_max);
  139. p.ScaleParticleParam(EmitorParam.SIZE, size);
  140. p.ScaleParticleParam(EmitorParam.BIRTH_RATE, birth_rate);
  141. }
  142. void OnRicochetCalculations(Particle p, float outspeedf)
  143. {
  144. float velocity_min = MIN_SCALING_PARAM + (m_StoppingForce * m_RicochetSplashCoef);
  145. float velocity_max = MIN_SCALING_PARAM + (m_StoppingForce * m_RicochetSplashCoef);
  146. float size = MIN_SCALING_PARAM + ( m_StoppingForce * m_RicochetSplashCoef);
  147. float birth_rate = MIN_SCALING_PARAM + (m_StoppingForce * m_RicochetSplashCoef);
  148. if (velocity_min < MIN_SCALING_PARAM)
  149. velocity_min = MIN_SCALING_PARAM;
  150. if (size < MIN_SCALING_PARAM)
  151. size = MIN_SCALING_PARAM;
  152. if (birth_rate < MIN_SCALING_PARAM)
  153. birth_rate = MIN_SCALING_PARAM;
  154. p.ScaleParticleParam(EmitorParam.VELOCITY, velocity_min);
  155. p.ScaleParticleParam(EmitorParam.VELOCITY_RND, velocity_max);
  156. p.ScaleParticleParam(EmitorParam.SIZE, size);
  157. p.ScaleParticleParam(EmitorParam.BIRTH_RATE, birth_rate);
  158. }
  159. void OnEnterAngledCalculations(Particle p)
  160. {
  161. float velocity_min = MIN_SCALING_PARAM + (m_StoppingForce * m_EnterAngledSplashCoef);
  162. float velocity_max = MIN_SCALING_PARAM + (m_StoppingForce * m_EnterAngledSplashCoef);
  163. float size = MIN_SCALING_PARAM + (m_StoppingForce * m_EnterAngledSplashCoef);
  164. float birth_rate = MIN_SCALING_PARAM + (m_StoppingForce * m_EnterAngledSplashCoef);
  165. if (velocity_min < MIN_SCALING_PARAM)
  166. velocity_min = MIN_SCALING_PARAM;
  167. if (size < MIN_SCALING_PARAM)
  168. size = MIN_SCALING_PARAM;
  169. if (birth_rate < MIN_SCALING_PARAM)
  170. birth_rate = MIN_SCALING_PARAM;
  171. p.ScaleParticleParam(EmitorParam.VELOCITY, velocity_min);
  172. p.ScaleParticleParam(EmitorParam.VELOCITY_RND, velocity_max);
  173. p.ScaleParticleParam(EmitorParam.SIZE, size);
  174. p.ScaleParticleParam(EmitorParam.BIRTH_RATE, birth_rate);
  175. }
  176. override void Event_OnStarted()
  177. {
  178. Particle p;
  179. vector particle_orientation;
  180. float outSpeedf = m_OutSpeed.Length();
  181. ParticleManager gPM = ParticleManager.GetInstance();
  182. if ( m_ImpactType == ImpactTypes.RICOCHET )
  183. {
  184. p = gPM.PlayInWorld(m_ParticleRicochet, m_Pos);
  185. if (p)
  186. {
  187. particle_orientation = m_OutSpeed.VectorToAngles();
  188. particle_orientation = particle_orientation + "0 -90 0";
  189. p.SetOrientation(particle_orientation);
  190. OnRicochetCalculations(p, outSpeedf);
  191. }
  192. }
  193. else
  194. {
  195. p = gPM.PlayInWorld(m_ParticleEnter, m_Pos );
  196. if (p)
  197. {
  198. if (m_SurfNormal != INVALID)
  199. {
  200. particle_orientation = m_SurfNormal.VectorToAngles();
  201. particle_orientation = particle_orientation + "0 270 0";
  202. }
  203. else
  204. {
  205. particle_orientation = "0 0 0"; // This vector is in angles
  206. }
  207. p.SetOrientation(particle_orientation);
  208. OnEnterCalculations(p);
  209. }
  210. if (outSpeedf > 0 && m_SurfNormal != INVALID)
  211. {
  212. p = gPM.PlayInWorld(m_ParticleExit, m_ExitPos);
  213. if (p)
  214. {
  215. particle_orientation = m_OutSpeed.VectorToAngles();
  216. particle_orientation = particle_orientation + "0 -90 0";
  217. p.SetOrientation(particle_orientation);
  218. OnExitCalculations(p, outSpeedf);
  219. }
  220. }
  221. else
  222. {
  223. if (m_SurfNormal != INVALID)
  224. {
  225. vector surfNormalN = m_SurfNormal.Normalized();
  226. vector inSpeedN = m_InSpeed.Normalized();
  227. vector bounce_ori = surfNormalN + inSpeedN;
  228. float dot = vector.Dot(bounce_ori, surfNormalN);
  229. if ( dot > m_AngledEnter )
  230. {
  231. p = gPM.PlayInWorld(m_ParticleRicochet, m_Pos);
  232. if (p)
  233. {
  234. particle_orientation = bounce_ori.VectorToAngles();
  235. particle_orientation = particle_orientation + "0 -90 0";
  236. p.SetOrientation(particle_orientation);
  237. OnEnterAngledCalculations(p);
  238. }
  239. }
  240. }
  241. }
  242. }
  243. if (p)
  244. {
  245. SetParticle(p);
  246. }
  247. // Additional impact particle over long ranges. It shows players where their bullets land
  248. if ( Type() != Hit_MeatBones )
  249. {
  250. vector camera_pos = GetGame().GetCurrentCameraPosition();
  251. float distance = vector.Distance(camera_pos, m_Pos);
  252. // Additional size increase by distance from camera
  253. float scaling_by_distance = distance * 0.01;
  254. // Now scale down the above size increase by player's zoom-in value
  255. float current_FOV = Camera.GetCurrentFOV();
  256. float config_FOV = GetDayZGame().GetUserFOVFromConfig();
  257. float FOV_scale = current_FOV / config_FOV;
  258. scaling_by_distance = 1 + scaling_by_distance * FOV_scale;
  259. if (scaling_by_distance > 1.1)
  260. {
  261. Particle p_distant = gPM.PlayInWorld(ParticleList.IMPACT_DISTANT_DUST, m_Pos);
  262. particle_orientation = m_SurfNormal.VectorToAngles();
  263. particle_orientation[1] = particle_orientation[1] + 270;
  264. p_distant.SetOrientation(particle_orientation);
  265. p_distant.ScaleParticleParam(EmitorParam.SIZE, scaling_by_distance - 0.5);
  266. p_distant.ScaleParticleParam(EmitorParam.BIRTH_RATE, scaling_by_distance * 0.1);
  267. p_distant.ScaleParticleParam(EmitorParam.BIRTH_RATE_RND, scaling_by_distance * 0.1);
  268. p_distant.ScaleParticleParam(EmitorParam.LIFETIME, scaling_by_distance * 0.3);
  269. p_distant.ScaleParticleParam(EmitorParam.LIFETIME_RND, scaling_by_distance * 0.3);
  270. }
  271. }
  272. }
  273. }