contaminatedarea_dynamic.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // The parameters for the explosion light when creating dynamic area
  2. class ShellLight : PointLightBase
  3. {
  4. protected float m_DefaultBrightness = 10;
  5. protected float m_DefaultRadius = 100;
  6. void ShellLight()
  7. {
  8. SetVisibleDuringDaylight(false);
  9. SetRadiusTo(m_DefaultRadius);
  10. SetBrightnessTo(m_DefaultBrightness);
  11. SetFlareVisible(false);
  12. SetAmbientColor(1.0, 1.0, 0.3);
  13. SetDiffuseColor(1.0, 1.0, 0.3);
  14. SetLifetime(0.15);
  15. SetDisableShadowsWithinRadius(-1);
  16. SetCastShadow( false );
  17. }
  18. }
  19. // The dynamic Contaminated area, using it's own default settings
  20. class ContaminatedArea_Dynamic : ContaminatedArea_DynamicBase
  21. {
  22. protected vector m_OffsetPos; // This will be the position at which we spawn all future airborne FX
  23. protected ref Timer m_StartupTimer;
  24. protected ref Timer m_FXTimer;
  25. protected FlareLight m_FlareLight;
  26. protected ShellLight m_ShellLight; // Light used upon ariborne shell detonation
  27. // Constants used for startup events
  28. const int AIRBORNE_EXPLOSION_DELAY = 20;
  29. const int AREA_SETUP_DELAY = 10;
  30. const float AIRBORNE_FX_OFFSET = 50;
  31. const float ARTILLERY_SHELL_SPEED = 100; // Units per second
  32. // Item Spawning upon area creation, the 4 arrays bellow have to have the same amount of elements
  33. const ref array<string> SPAWN_ITEM_TYPE = {"Grenade_ChemGas"};//item classnames
  34. const ref array<int> SPAWN_ITEM_COUNT = {Math.RandomIntInclusive(2,5)};//how many of each type
  35. const ref array<float> SPAWN_ITEM_RAD_MIN = {5};//min distance the item will be spawned from the area position(epicenter)
  36. const ref array<float> SPAWN_ITEM_RAD_MAX = {15};//max distance the item will be spawned from the area position(epicenter)
  37. override void EEOnCECreate()
  38. {
  39. // We get the PPE index for future usage and synchronization ( we must do it here for dynamic as it is not read through file )
  40. m_PPERequesterIdx = GetRequesterIndex(m_PPERequesterType);
  41. // If this is the first initialization, we delay it in order to play cool effects
  42. if (m_DecayState == eAreaDecayStage.INIT)
  43. {
  44. vector areaPos = GetPosition();
  45. m_OffsetPos = areaPos;
  46. m_OffsetPos[1] = m_OffsetPos[1] + AIRBORNE_FX_OFFSET;
  47. vector closestPoint = areaPos;
  48. // play artillery sound, sent to be played for everyone on server
  49. array<vector> artilleryPoints = GetGame().GetMission().GetWorldData().GetArtyFiringPos();
  50. int index = 0;
  51. foreach (int i, vector artilleryPoint : artilleryPoints)
  52. {
  53. int dist = 0;
  54. int temp = vector.DistanceSq(artilleryPoint, areaPos);
  55. if (temp < dist || dist == 0)
  56. {
  57. dist = temp;
  58. index = i;
  59. }
  60. }
  61. closestPoint = artilleryPoints.Get(index);
  62. // We calculate the delay depending on distance from firing position to simulate shell travel time
  63. float delay = vector.Distance(closestPoint, areaPos);
  64. delay = delay / ARTILLERY_SHELL_SPEED;
  65. delay += AIRBORNE_EXPLOSION_DELAY; // We add the base, minimum time ( no area can start before this delay )
  66. Param3<vector, vector, float> pos = new Param3<vector, vector, float>(closestPoint, areaPos, delay);
  67. array<ref Param> params = new array<ref Param>();
  68. // We send the message with this set of coords
  69. params.Insert(pos);
  70. GetGame().RPC(null, ERPCs.RPC_SOUND_ARTILLERY_SINGLE, params, true);
  71. m_FXTimer = new Timer(CALL_CATEGORY_GAMEPLAY);
  72. m_FXTimer.Run(delay, this, "PlayFX");
  73. delay += AREA_SETUP_DELAY; // We have an additional delay between shell detonation and finalization of area creation
  74. // setup zone
  75. m_StartupTimer = new Timer(CALL_CATEGORY_GAMEPLAY);
  76. m_StartupTimer.Run(delay, this, "InitZone");
  77. }
  78. SetSynchDirty();
  79. }
  80. override void OnVariablesSynchronized()
  81. {
  82. super.OnVariablesSynchronized();
  83. switch (m_DecayState)
  84. {
  85. case eAreaDecayStage.START:
  86. PlayExplosionLight();
  87. break;
  88. }
  89. }
  90. override void Tick()
  91. {
  92. if ( GetRemainingTime() < GetFinishDecayLifetime() )
  93. {
  94. // The second state of decay, further reduction of particle density and size
  95. SetDecayState( eAreaDecayStage.DECAY_END );
  96. }
  97. else if ( GetRemainingTime() < GetStartDecayLifetime() )
  98. {
  99. // The first state of decay, slight reduction in particle density and size
  100. SetDecayState( eAreaDecayStage.DECAY_START );
  101. }
  102. }
  103. override void SetupZoneData(EffectAreaParams params)
  104. {
  105. params.m_ParamName = string.Format("Dynamic area (%1)", m_Position.ToString());
  106. params.m_ParamPartId = ParticleList.CONTAMINATED_AREA_GAS_BIGASS;
  107. params.m_ParamAroundPartId = ParticleList.CONTAMINATED_AREA_GAS_AROUND;
  108. params.m_ParamTinyPartId = ParticleList.CONTAMINATED_AREA_GAS_TINY;
  109. params.m_ParamPosHeight = 7;
  110. params.m_ParamNegHeight = 10;
  111. params.m_ParamRadius = 120;
  112. params.m_ParamInnerRings = 1;
  113. params.m_ParamInnerSpace = 40;
  114. params.m_ParamOuterSpace = 30;
  115. params.m_ParamOuterOffset = 0;
  116. params.m_ParamTriggerType = "ContaminatedTrigger_Dynamic";
  117. super.SetupZoneData(params);
  118. }
  119. override void DeferredInit()
  120. {
  121. super.DeferredInit();
  122. // We make sure we have the particle array
  123. if (!m_ToxicClouds)
  124. m_ToxicClouds = new array<Particle>();
  125. m_Position = GetPosition();
  126. m_OffsetPos = m_Position;
  127. m_OffsetPos[1] = m_OffsetPos[1] + AIRBORNE_FX_OFFSET;
  128. SetupZoneData(new EffectAreaParams);
  129. // If a player arrives slightly later during the creation process we check if playing the flare FX is relevant
  130. if (m_DecayState == eAreaDecayStage.INIT)
  131. PlayFlareVFX();
  132. if ( m_DecayState == eAreaDecayStage.LIVE )
  133. InitZone(); // If it has already been created, we simply do the normal setup, no cool effects, force the LIVE state
  134. super.DeferredInit();
  135. }
  136. override void InitZoneServer()
  137. {
  138. SpawnItems();
  139. super.InitZoneServer();
  140. }
  141. void SpawnItems()
  142. {
  143. //Print("---------============ Spawning items at pos:"+m_Position);
  144. foreach (int j, string type : SPAWN_ITEM_TYPE)
  145. {
  146. //Print("----------------------------------");
  147. for (int i = 0; i < SPAWN_ITEM_COUNT[j]; ++i)
  148. {
  149. vector randomDir2d = vector.RandomDir2D();
  150. float randomDist = Math.RandomFloatInclusive(SPAWN_ITEM_RAD_MIN[j],SPAWN_ITEM_RAD_MAX[j]);
  151. vector spawnPos = m_Position + (randomDir2d * randomDist);
  152. InventoryLocation il = new InventoryLocation();
  153. vector mat[4];
  154. Math3D.MatrixIdentity4(mat);
  155. mat[3] = spawnPos;
  156. il.SetGround(NULL, mat);
  157. //Print("Spawning item:"+ type + " at position:" + il.GetPos());
  158. GetGame().CreateObjectEx(type, il.GetPos(), ECE_PLACE_ON_SURFACE);
  159. }
  160. }
  161. }
  162. override void CreateTrigger(vector pos, int radius)
  163. {
  164. super.CreateTrigger(pos, radius);
  165. // This handles the specific case of dynamic triggers as some additionnal parameters are present
  166. ContaminatedTrigger_Dynamic dynaTrigger = ContaminatedTrigger_Dynamic.Cast( m_Trigger );
  167. if ( dynaTrigger )
  168. {
  169. dynaTrigger.SetLocalEffects( m_AroundParticleID, m_TinyParticleID, m_PPERequesterIdx );
  170. dynaTrigger.SetAreaState( m_DecayState );
  171. }
  172. }
  173. void PlayFX()
  174. {
  175. if (GetGame().IsServer())
  176. {
  177. Param1<vector> pos = new Param1<vector>(vector.Zero); // The value to be sent through RPC
  178. array<ref Param> params = new array<ref Param>(); // The RPC params
  179. // We send the message with this set of coords
  180. pos.param1 = m_OffsetPos;
  181. params.Insert(pos);
  182. GetGame().RPC(null, ERPCs.RPC_SOUND_CONTAMINATION, params, true);
  183. // We go to the next stage
  184. SetDecayState(eAreaDecayStage.START);
  185. SetSynchDirty();
  186. }
  187. }
  188. void PlayExplosionLight()
  189. {
  190. m_ShellLight = ShellLight.Cast( ScriptedLightBase.CreateLight( ShellLight, m_OffsetPos ) );
  191. }
  192. void PlayFlareVFX()
  193. {
  194. if ( GetGame().IsClient() || ( GetGame().IsServer() && !GetGame().IsMultiplayer() ) )
  195. {
  196. // We spawn locally the dummy object which will be used to move and manage the particle
  197. DynamicArea_Flare dummy = DynamicArea_Flare.Cast( GetGame().CreateObjectEx( "DynamicArea_Flare", m_OffsetPos, ECE_SETUP | ECE_LOCAL ) );
  198. // We add some light to reinforce the effect
  199. m_FlareLight = FlareLightContamination.Cast(ScriptedLightBase.CreateLight( FlareLightContamination, m_OffsetPos ));
  200. }
  201. }
  202. }