Client LuaCsForBarotrauma
BarotraumaClient/ClientSource/Map/SubmarineBody.cs
1 using FarseerPhysics;
2 using Microsoft.Xna.Framework;
3 using System;
4 using System.Collections.Generic;
5 using System.Linq;
6 using Voronoi2;
7 
8 namespace Barotrauma
9 {
10  partial class SubmarineBody
11  {
12 
13  partial void HandleLevelCollisionProjSpecific(Impact impact)
14  {
15  float wallImpact = Vector2.Dot(impact.Velocity, -impact.Normal);
16  int particleAmount = (int)Math.Min(wallImpact, 10);
17 
18  const float BurstParticleThreshold = 5.0f;
19 
20  float velocityFactor = MathHelper.Clamp(wallImpact / 10.0f, 0.0f, 1.0f);
21  for (int i = 0; i < particleAmount * 5; i++)
22  {
23  GameMain.ParticleManager.CreateParticle("iceshards",
24  ConvertUnits.ToDisplayUnits(impact.ImpactPos) + Rand.Vector(Rand.Range(1.0f, 50.0f)),
25  (Rand.Vector(0.9f) + impact.Normal) * Rand.Range(100.0f, 10000) * velocityFactor);
26  }
27  for (int i = 0; i < particleAmount; i++)
28  {
29  float particleVelocityMultiplier = Rand.Range(0.0f, 1);
30  var p = GameMain.ParticleManager.CreateParticle("iceexplosion",
31  ConvertUnits.ToDisplayUnits(impact.ImpactPos) + Rand.Vector(Rand.Range(1.0f, 50.0f)),
32  (Rand.Vector(0.5f) + impact.Normal) * particleVelocityMultiplier * 500 * velocityFactor);
33  if (p != null)
34  {
35  p.VelocityChangeMultiplier = particleVelocityMultiplier * Rand.Range(0.0f, 1.0f);
36  p.Size *= Math.Max(particleVelocityMultiplier, 0);
37  }
38  }
39  if (wallImpact > BurstParticleThreshold)
40  {
41  for (int i = 0; i < particleAmount; i++)
42  {
43  GameMain.ParticleManager.CreateParticle("iceburst",
44  ConvertUnits.ToDisplayUnits(impact.ImpactPos) + Rand.Vector(Rand.Range(1.0f, 50.0f)),
45  angle: MathUtils.VectorToAngle(impact.Normal.FlipY() + Rand.Vector(0.25f)), speed: 0.0f);
46  }
47  }
48  }
49 
50  partial void ClientUpdatePosition(float deltaTime)
51  {
52  if (GameMain.Client == null) { return; }
53 
54  Body.CorrectPosition(positionBuffer, out Vector2 newPosition, out Vector2 newVelocity, out _, out _);
55  Vector2 moveAmount = ConvertUnits.ToDisplayUnits(newPosition - Body.SimPosition);
56  newVelocity = newVelocity.ClampLength(100.0f);
57  if (!MathUtils.IsValid(newVelocity) || moveAmount.LengthSquared() < 0.0001f)
58  {
59  return;
60  }
61 
62  var subsToMove = submarine.GetConnectedSubs();
63  foreach (Submarine dockedSub in subsToMove)
64  {
65  if (dockedSub == submarine) { continue; }
66  //clear the position buffer of the docked subs to prevent unnecessary position corrections
67  dockedSub.SubBody.positionBuffer.Clear();
68  }
69 
70  Submarine closestSub;
71  if (Character.Controlled == null)
72  {
73  closestSub = Submarine.FindClosest(GameMain.GameScreen.Cam.Position);
74  }
75  else
76  {
77  closestSub = Character.Controlled.Submarine;
78  }
79 
80  bool displace = moveAmount.LengthSquared() > 100.0f * 100.0f;
81  foreach (Submarine sub in subsToMove)
82  {
83  sub.PhysicsBody.LinearVelocity = newVelocity;
84 
85  if (displace)
86  {
87  sub.PhysicsBody.SetTransform(sub.PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(moveAmount), 0.0f);
88  sub.SubBody.DisplaceCharacters(moveAmount);
89  }
90  else
91  {
92  sub.PhysicsBody.SetTransformIgnoreContacts(sub.PhysicsBody.SimPosition + ConvertUnits.ToSimUnits(moveAmount), 0.0f);
93  }
94  }
95  if (closestSub != null && subsToMove.Contains(closestSub))
96  {
97  GameMain.GameScreen.Cam.Position += moveAmount;
98  if (GameMain.GameScreen.Cam.TargetPos != Vector2.Zero) { GameMain.GameScreen.Cam.TargetPos += moveAmount; }
99 
100  if (Character.Controlled != null) { Character.Controlled.CursorPosition += moveAmount; }
101  }
102  }
103 
104  private void PlayDamageSounds(Dictionary<Structure, float> damagedStructures, Vector2 impactSimPos, float impact, string soundTag)
105  {
106  if (impact < MinCollisionImpact) { return; }
107 
108  //play a damage sound for the structure that took the most damage
109  float maxDamage = 0.0f;
110  Structure maxDamageStructure = null;
111  foreach (KeyValuePair<Structure, float> structureDamage in damagedStructures)
112  {
113  if (maxDamageStructure == null || structureDamage.Value > maxDamage)
114  {
115  maxDamage = structureDamage.Value;
116  maxDamageStructure = structureDamage.Key;
117  }
118  }
119 
120  if (maxDamageStructure != null)
121  {
122  PlayDamageSound(impactSimPos, impact, soundTag, maxDamageStructure);
123  }
124  }
125 
126  private void PlayDamageSound(Vector2 impactSimPos, float impact, string soundTag, Structure hitStructure = null)
127  {
128  if (impact < MinCollisionImpact) { return; }
129 
130  SoundPlayer.PlayDamageSound(
131  soundTag,
132  impact * 10.0f,
133  ConvertUnits.ToDisplayUnits(impactSimPos),
134  MathHelper.Lerp(2000.0f, 10000.0f, (impact - MinCollisionImpact) / 2.0f),
135  hitStructure?.Tags);
136  }
137 
138 
139  }
140 }
IEnumerable< Submarine > GetConnectedSubs()
Returns a list of all submarines that are connected to this one via docking ports,...
static Submarine FindClosest(Vector2 worldPosition, bool ignoreOutposts=false, bool ignoreOutsideLevel=true, bool ignoreRespawnShuttle=false, CharacterTeamType? teamType=null)
If has value, the sub must match the team type.