Client LuaCsForBarotrauma
BarotraumaClient/ClientSource/Map/Explosion.cs
1 using Barotrauma.Lights;
3 using Microsoft.Xna.Framework;
4 using System;
5 using System.Collections.Generic;
6 
7 namespace Barotrauma
8 {
9  partial class Explosion
10  {
11  partial void ExplodeProjSpecific(Vector2 worldPosition, Hull hull)
12  {
13  if (GameMain.Client?.MidRoundSyncing ?? false) { return; }
14 
15  if (shockwave)
16  {
17  GameMain.ParticleManager.CreateParticle("shockwave", worldPosition,
18  Vector2.Zero, 0.0f, hull);
19  }
20 
21  hull ??= Hull.FindHull(worldPosition, useWorldCoordinates: true);
22  bool underwater = hull == null || worldPosition.Y < hull.WorldSurface;
23 
24  if (underwater && underwaterBubble)
25  {
26  var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition, Vector2.Zero, 0.0f, hull);
27  if (underwaterExplosion != null)
28  {
29  underwaterExplosion.Size *= MathHelper.Clamp(Attack.Range / 150.0f, 0.5f, 10.0f);
30  underwaterExplosion.StartDelay = 0.0f;
31  }
32  }
33  if (!underwater && (flames || smoke))
34  {
35  for (int i = 0; i < Attack.Range * 0.025f; i++)
36  {
37  float distFactor = 0.0f;
38 
39  if (i > 0 && Attack.Range > 100.0f)
40  {
41  distFactor = Rand.Range(0.0f, 1.0f);
42  //sqrt to make larger values more common (= more particles spawn further away from the origin)
43  distFactor = MathF.Sqrt(distFactor);
44  }
45  float sizeFactor = MathHelper.Clamp(Attack.Range / 1000.0f, 0.0f, 1.0f);
46  float minScale = MathHelper.Lerp(0.2f, 1.0f, sizeFactor);
47  float maxScale = MathUtils.InverseLerp(2.0f, 3.0f, sizeFactor);
48  //larger particles closer to the origin
49  float particleScale = MathHelper.Clamp(1.0f - distFactor, minScale, maxScale);
50 
51  var particlePrefab = ParticleManager.FindPrefab("explosionfire");
52  Vector2 pos = worldPosition;
53  if (i > 0)
54  {
55  pos = ClampParticlePos(worldPosition + Rand.Vector(Attack.Range * distFactor * 0.3f), hull, particlePrefab);
56  }
57 
58  if (flames)
59  {
60  var flameParticle = GameMain.ParticleManager.CreateParticle(particlePrefab,
61  pos,
62  velocity: Vector2.Zero, hullGuess: hull);
63  if (flameParticle != null)
64  {
65  //brief delay to particles futher from origin
66  flameParticle.StartDelay = distFactor * sizeFactor;
67  flameParticle.Size *= particleScale;
68  }
69  }
70  if (smoke)
71  {
72  GameMain.ParticleManager.CreateParticle(
73  ParticleManager.FindPrefab(Rand.Range(0.0f, 1.0f) < 0.5f ? "explosionsmoke" : "smoke"),
74  pos, velocity: Vector2.Zero, hullGuess: hull);
75  }
76  }
77  }
78 
79  for (int i = 0; i < Attack.Range * 0.1f; i++)
80  {
81  if (underwater && underwaterBubble)
82  {
83  Vector2 bubblePos = Rand.Vector(Rand.Range(0.0f, Attack.Range * 0.5f));
84 
85  GameMain.ParticleManager.CreateParticle("risingbubbles", worldPosition + bubblePos,
86  velocity: Vector2.Zero, hullGuess: hull);
87  if (i < Attack.Range * 0.02f)
88  {
89  var underwaterExplosion = GameMain.ParticleManager.CreateParticle("underwaterexplosion", worldPosition + bubblePos,
90  Vector2.Zero, 0.0f, hull);
91  if (underwaterExplosion != null)
92  {
93  underwaterExplosion.Size *= MathHelper.Clamp(Attack.Range / 300.0f, 0.5f, 2.0f) * Rand.Range(0.8f, 1.2f);
94  }
95  }
96  }
97  if (sparks)
98  {
99  GameMain.ParticleManager.CreateParticle("spark", worldPosition,
100  Rand.Vector(Rand.Range(800.0f, 1500.0f)), 0.0f, hull);
101  }
102  if (debris)
103  {
104  GameMain.ParticleManager.CreateParticle("explosiondebris", worldPosition,
105  Rand.Vector(Rand.Range(800.0f, 2000.0f)), 0.0f, hull);
106  }
107  }
108 
109  if (flash)
110  {
111  float displayRange = flashRange ?? (Attack.Range * 2);
112  if (displayRange < 0.1f) { return; }
113  var light = new LightSource(worldPosition, displayRange, flashColor, null);
114  CoroutineManager.StartCoroutine(DimLight(light));
115  }
116  }
117 
118  private static Vector2 ClampParticlePos(Vector2 particlePos, Hull hull, ParticlePrefab particlePrefab)
119  {
120  float minX = hull.WorldRect.X;
121  float maxX = hull.WorldRect.Right;
122  float minY = hull.WorldRect.Y - hull.WorldRect.Height;
123  float maxY = hull.WorldRect.Y;
124  if (particlePrefab != null)
125  {
126  minX = Math.Min(minX + particlePrefab.CollisionRadius, hull.WorldRect.Center.X);
127  maxX = Math.Max(maxX - particlePrefab.CollisionRadius, hull.WorldRect.Center.X);
128  minY = Math.Min(minY + particlePrefab.CollisionRadius, hull.WorldRect.Y - hull.WorldRect.Height / 2);
129  maxY = Math.Max(maxY - particlePrefab.CollisionRadius, hull.WorldRect.Y - hull.WorldRect.Height / 2);
130  }
131 
132  return new Vector2(
133  MathHelper.Clamp(particlePos.X, minX, maxX),
134  MathHelper.Clamp(particlePos.Y, minY, maxY));
135  }
136 
137  private IEnumerable<CoroutineStatus> DimLight(LightSource light)
138  {
139  float currBrightness = 1.0f;
140  while (light.Color.A > 0.0f && flashDuration > 0.0f && currBrightness > 0.0f)
141  {
142  if (!CoroutineManager.Paused)
143  {
144  light.Color = new Color(light.Color.R, light.Color.G, light.Color.B, (byte)(currBrightness * 255));
145  currBrightness -= 1.0f / flashDuration * CoroutineManager.DeltaTime;
146  }
147  yield return CoroutineStatus.Running;
148  }
149 
150  light.Remove();
151 
152  yield return CoroutineStatus.Success;
153  }
154 
155  static partial void PlayTinnitusProjSpecific(float volume) => SoundPlayer.PlaySound("tinnitus", volume: volume);
156  }
157 }
static ParticlePrefab FindPrefab(string prefabName)