impacteffects.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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 FOLIAGE_GREEN = RegisterSurface("Hit_Foliage_Green");
  44. static int FOLIAGE_CONIFER = RegisterSurface("Hit_Foliage_Conifer");
  45. static int GRASS = RegisterSurface("Hit_Grass");
  46. static int WOOD = RegisterSurface("Hit_Wood");
  47. static int METAL = RegisterSurface("Hit_Metal");
  48. static int GLASS = RegisterSurface("Hit_Glass");
  49. static int GLASS_THIN = RegisterSurface("Hit_Glass_Thin");
  50. static int WATER = RegisterSurface("Hit_Water");
  51. static int RUBBER = RegisterSurface("Hit_Rubber");
  52. static int PLASTER = RegisterSurface("Hit_Plaster");
  53. static int ICE = RegisterSurface("Hit_Ice");
  54. static int SNOW = RegisterSurface("Hit_Snow");
  55. static int MEATBONES = RegisterSurface("Hit_MeatBones");
  56. static int MEATBONES_SHOVEL = RegisterSurface("Hit_MeatBones_MeleeShovel");
  57. static int MEATBONES_PIPEWRENCH = RegisterSurface("Hit_MeatBones_MeleePipeWrench");
  58. static int MEATBONES_WRENCH = RegisterSurface("Hit_MeatBones_MeleeWrench");
  59. static int MEATBONES_FIST = RegisterSurface("Hit_MeatBones_MeleeFist");
  60. static int UNDEFINED = RegisterSurface("Hit_Undefined");
  61. static int ERROR_NO_MATERIAL = RegisterSurface("Hit_ErrorNoMaterial");
  62. //@}
  63. /** \name Ignored ammo
  64. * Register ammo which will not spawn impact effects here
  65. * When modding, these can be unregistered with 'UnregisterIgnoredAmmo' if so desired
  66. */
  67. //@{
  68. static int FIST = RegisterIgnoredAmmo("MeleeFist");
  69. static int FIST_HEAVY = RegisterIgnoredAmmo("MeleeFist_Heavy");
  70. static int SOFT = RegisterIgnoredAmmo("MeleeSoft");
  71. static int SOFT_HEAVY = RegisterIgnoredAmmo("MeleeSoft_Heavy");
  72. static int DUMMY = RegisterIgnoredAmmo("Dummy_Light");
  73. static int DUMMY_HEAVY = RegisterIgnoredAmmo("Dummy_Heavy");
  74. //@}
  75. static int RegisterSurface(string surface)
  76. {
  77. if (!m_ImpactEffect)
  78. m_ImpactEffect = new map<string, typename>;
  79. m_ImpactEffect.Insert(surface, surface.ToType());
  80. return ++m_LastRegisteredMaterial;
  81. }
  82. static bool UnregisterSurface(string surface)
  83. {
  84. if (m_ImpactEffect)
  85. {
  86. m_ImpactEffect.Remove(surface);
  87. return !m_ImpactEffect.Contains(surface);
  88. }
  89. return false;
  90. }
  91. static int RegisterIgnoredAmmo(string ammo)
  92. {
  93. if (!m_IgnoredAmmo)
  94. m_IgnoredAmmo = new map<string, int>;
  95. ++m_LastRegisteredIgnoredAmmo;
  96. m_IgnoredAmmo.Insert(ammo, m_LastRegisteredIgnoredAmmo);
  97. return m_LastRegisteredIgnoredAmmo;
  98. }
  99. static bool UnregisterIgnoredAmmo(string ammo)
  100. {
  101. if (m_IgnoredAmmo)
  102. {
  103. m_IgnoredAmmo.Remove(ammo);
  104. return !m_IgnoredAmmo.Contains(ammo);
  105. }
  106. return false;
  107. }
  108. static typename GetImpactEffect(string surface, string ammoType)
  109. {
  110. string key = string.Format("%1_%2", surface, ammoType);
  111. typename eff_type = m_ImpactEffect[key];
  112. if (eff_type)
  113. return eff_type;
  114. else
  115. return m_ImpactEffect[surface];
  116. }
  117. static void EvaluateImpactEffectEx(ImpactEffectsData pData)
  118. {
  119. 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);
  120. }
  121. 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)
  122. {
  123. // No impact effects wanted for this ammo
  124. if (m_IgnoredAmmo.Contains(ammoType))
  125. return;
  126. if (impact_type == ImpactTypes.UNKNOWN)
  127. impact_type = ImpactTypes.STOP;
  128. if (deflected)
  129. impact_type = ImpactTypes.RICOCHET;
  130. else if (outSpeed)
  131. impact_type = ImpactTypes.PENETRATE;
  132. if (isWater)
  133. surface = "Hit_Water";
  134. EffBulletImpactBase eff = EffBulletImpactBase.Cast(GetImpactEffect(surface, ammoType).Spawn());
  135. if ( !eff && surface == "" ) // handle undefined surface
  136. {
  137. eff = EffBulletImpactBase.Cast( surface.ToType().Spawn() );
  138. if (eff)
  139. {
  140. RegisterSurface(surface);
  141. ErrorEx(string.Format("Unregistered surface for bullet impact effect (%1). Register this surface in ImpactMaterials (Script) for better performance.", surface), ErrorExSeverity.WARNING);
  142. }
  143. else
  144. {
  145. if (directHit)
  146. {
  147. string object_type = directHit.GetType();
  148. if ( object_type == "" )
  149. object_type = "OBJECT_WITHOUT_CONFIG_CLASS";
  150. ErrorEx(string.Format("Object '%1' with model file: %2 has undefined 'Hit_...' material! Cannot play impact effect.", object_type, directHit.GetShapeName()));
  151. eff = EffBulletImpactBase.Cast(GetImpactEffect("Hit_ErrorNoMaterial", ammoType).Spawn());
  152. }
  153. }
  154. }
  155. if ( !eff && surface != "" )
  156. {
  157. ErrorEx(string.Format("Unregistered surface impact material <%1>! Register this surface in ImpactMaterials (Script).", surface));
  158. eff = EffBulletImpactBase.Cast(GetImpactEffect("Hit_Undefined", ammoType).Spawn());
  159. }
  160. if (eff)
  161. {
  162. eff.EvaluateEffect(directHit, componentIndex, pos, impact_type, surfNormal, exitPos, inSpeed, outSpeed, ammoType);
  163. eff.SetAutodestroy(true);
  164. SEffectManager.PlayInWorld(eff, pos);
  165. }
  166. }
  167. }