impacteffects.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. enum ImpactTypes
  2. {
  3. UNKNOWN;
  4. STOP;
  5. PENETRATE;
  6. RICOCHET;
  7. MELEE;
  8. }
  9. class ImpactEffectsData
  10. {
  11. Object m_DirectHit;
  12. int m_ImpactType;
  13. int m_ComponentIndex;
  14. bool m_IsDeflected;
  15. bool m_IsWater;
  16. string m_Surface;
  17. string m_AmmoType;
  18. vector m_InSpeed;
  19. vector m_OutSpeed;
  20. vector m_Position;
  21. vector m_SurfaceNormal;
  22. vector m_ExitPosition;
  23. }
  24. class ImpactMaterials
  25. {
  26. ref static map<string, typename> m_ImpactEffect;
  27. static int m_LastRegisteredMaterial = 0;
  28. //! Map of ammo which will not spawn any impact effect
  29. ref static map<string, int> m_IgnoredAmmo;
  30. static int m_LastRegisteredIgnoredAmmo = 0;
  31. /** \name Surface effects
  32. * Register all hit materials here!
  33. * When modding, these can be unregistered with 'UnregisterSurface' if so desired
  34. */
  35. //@{
  36. static int PLASTIC = RegisterSurface("Hit_Plastic");
  37. static int SAND = RegisterSurface("Hit_Sand");
  38. static int TEXTILE = RegisterSurface("Hit_Textile");
  39. static int CONCRETE = RegisterSurface("Hit_Concrete");
  40. static int GRAVEL = RegisterSurface("Hit_Gravel");
  41. static int DIRT = RegisterSurface("Hit_Dirt");
  42. static int FOLIAGE = RegisterSurface("Hit_Foliage");
  43. static int GRASS = RegisterSurface("Hit_Grass");
  44. static int WOOD = RegisterSurface("Hit_Wood");
  45. static int METAL = RegisterSurface("Hit_Metal");
  46. static int GLASS = RegisterSurface("Hit_Glass");
  47. static int GLASS_THIN = RegisterSurface("Hit_Glass_Thin");
  48. static int WATER = RegisterSurface("Hit_Water");
  49. static int RUBBER = RegisterSurface("Hit_Rubber");
  50. static int PLASTER = RegisterSurface("Hit_Plaster");
  51. static int ICE = RegisterSurface("Hit_Ice");
  52. static int SNOW = RegisterSurface("Hit_Snow");
  53. static int MEATBONES = RegisterSurface("Hit_MeatBones");
  54. static int MEATBONES_SHOVEL = RegisterSurface("Hit_MeatBones_MeleeShovel");
  55. static int MEATBONES_PIPEWRENCH = RegisterSurface("Hit_MeatBones_MeleePipeWrench");
  56. static int MEATBONES_WRENCH = RegisterSurface("Hit_MeatBones_MeleeWrench");
  57. static int MEATBONES_FIST = RegisterSurface("Hit_MeatBones_MeleeFist");
  58. static int UNDEFINED = RegisterSurface("Hit_Undefined");
  59. static int ERROR_NO_MATERIAL = RegisterSurface("Hit_ErrorNoMaterial");
  60. //@}
  61. /** \name Ignored ammo
  62. * Register ammo which will not spawn impact effects here
  63. * When modding, these can be unregistered with 'UnregisterIgnoredAmmo' if so desired
  64. */
  65. //@{
  66. static int FIST = RegisterIgnoredAmmo("MeleeFist");
  67. static int FIST_HEAVY = RegisterIgnoredAmmo("MeleeFist_Heavy");
  68. static int SOFT = RegisterIgnoredAmmo("MeleeSoft");
  69. static int SOFT_HEAVY = RegisterIgnoredAmmo("MeleeSoft_Heavy");
  70. static int DUMMY = RegisterIgnoredAmmo("Dummy_Light");
  71. static int DUMMY_HEAVY = RegisterIgnoredAmmo("Dummy_Heavy");
  72. //@}
  73. static int RegisterSurface(string surface)
  74. {
  75. if (!m_ImpactEffect)
  76. m_ImpactEffect = new map<string, typename>;
  77. m_ImpactEffect.Insert(surface, surface.ToType());
  78. return ++m_LastRegisteredMaterial;
  79. }
  80. static bool UnregisterSurface(string surface)
  81. {
  82. if (m_ImpactEffect)
  83. {
  84. m_ImpactEffect.Remove(surface);
  85. return !m_ImpactEffect.Contains(surface);
  86. }
  87. return false;
  88. }
  89. static int RegisterIgnoredAmmo(string ammo)
  90. {
  91. if (!m_IgnoredAmmo)
  92. m_IgnoredAmmo = new map<string, int>;
  93. ++m_LastRegisteredIgnoredAmmo;
  94. m_IgnoredAmmo.Insert(ammo, m_LastRegisteredIgnoredAmmo);
  95. return m_LastRegisteredIgnoredAmmo;
  96. }
  97. static bool UnregisterIgnoredAmmo(string ammo)
  98. {
  99. if (m_IgnoredAmmo)
  100. {
  101. m_IgnoredAmmo.Remove(ammo);
  102. return !m_IgnoredAmmo.Contains(ammo);
  103. }
  104. return false;
  105. }
  106. static typename GetImpactEffect(string surface, string ammoType)
  107. {
  108. string key = string.Format("%1_%2", surface, ammoType);
  109. typename eff_type = m_ImpactEffect[key];
  110. if (eff_type)
  111. return eff_type;
  112. else
  113. return m_ImpactEffect[surface];
  114. }
  115. static void EvaluateImpactEffectEx(ImpactEffectsData pData)
  116. {
  117. EvaluateImpactEffect(pData.m_DirectHit, pData.m_ComponentIndex, pData.m_Surface, pData.m_Position, pData.m_ImpactType, pData.m_SurfaceNormal, pData.m_ExitPosition, pData.m_InSpeed, pData.m_OutSpeed, pData.m_IsDeflected, pData.m_AmmoType, pData.m_IsWater);
  118. }
  119. static void EvaluateImpactEffect(Object directHit, int componentIndex, string surface, vector pos, int impact_type, vector surfNormal, vector exitPos, vector inSpeed, vector outSpeed, bool deflected, string ammoType, bool isWater)
  120. {
  121. // No impact effects wanted for this ammo
  122. if (m_IgnoredAmmo.Contains(ammoType))
  123. return;
  124. if (impact_type == ImpactTypes.UNKNOWN)
  125. impact_type = ImpactTypes.STOP;
  126. if (deflected)
  127. impact_type = ImpactTypes.RICOCHET;
  128. else if (outSpeed)
  129. impact_type = ImpactTypes.PENETRATE;
  130. if (isWater)
  131. surface = "Hit_Water";
  132. EffBulletImpactBase eff = EffBulletImpactBase.Cast(GetImpactEffect(surface, ammoType).Spawn());
  133. if ( !eff && surface == "" ) // handle undefined surface
  134. {
  135. eff = EffBulletImpactBase.Cast( surface.ToType().Spawn() );
  136. if (eff)
  137. {
  138. RegisterSurface(surface);
  139. ErrorEx(string.Format("Unregistered surface for bullet impact effect (%1). Register this surface in ImpactMaterials (Script) for better performance.", surface), ErrorExSeverity.WARNING);
  140. }
  141. else
  142. {
  143. if (directHit)
  144. {
  145. string object_type = directHit.GetType();
  146. if ( object_type == "" )
  147. object_type = "OBJECT_WITHOUT_CONFIG_CLASS";
  148. ErrorEx(string.Format("Object '%1' with model file: %2 has undefined 'Hit_...' material! Cannot play impact effect.", object_type, directHit.GetShapeName()));
  149. eff = EffBulletImpactBase.Cast(GetImpactEffect("Hit_ErrorNoMaterial", ammoType).Spawn());
  150. }
  151. }
  152. }
  153. if ( !eff && surface != "" )
  154. {
  155. ErrorEx(string.Format("Unregistered surface impact material <%1>! Register this surface in ImpactMaterials (Script).", surface));
  156. eff = EffBulletImpactBase.Cast(GetImpactEffect("Hit_Undefined", ammoType).Spawn());
  157. }
  158. if (eff)
  159. {
  160. eff.EvaluateEffect(directHit, componentIndex, pos, impact_type, surfNormal, exitPos, inSpeed, outSpeed, ammoType);
  161. eff.SetAutodestroy(true);
  162. SEffectManager.PlayInWorld(eff, pos);
  163. }
  164. }
  165. }