public override void Update(float deltaTime, Camera cam) { UpdateProjSpecific(deltaTime, cam); Oxygen -= OxygenDetoriationSpeed * deltaTime; FireSource.UpdateAll(fireSources, deltaTime); aiTarget.SightRange = Submarine == null ? 0.0f : Math.Max(Submarine.Velocity.Length() * 500.0f, 500.0f); aiTarget.SoundRange -= deltaTime * 1000.0f; //update client hulls if the amount of water has changed by >10% //or if oxygen percentage has changed by 5% if (Math.Abs(lastSentVolume - waterVolume) > Volume * 0.1f || Math.Abs(lastSentOxygen - OxygenPercentage) > 5f) { if (GameMain.Server != null && !IdFreed) { sendUpdateTimer -= deltaTime; if (sendUpdateTimer < 0.0f) { GameMain.Server.CreateEntityEvent(this); lastSentVolume = waterVolume; lastSentOxygen = OxygenPercentage; sendUpdateTimer = NetworkUpdateInterval; } } } if (!update) { lethalPressure = 0.0f; return; } float surfaceY = rect.Y - rect.Height + WaterVolume / rect.Width; for (int i = 0; i < waveY.Length; i++) { waveY[i] = waveY[i] + waveVel[i]; if (surfaceY + waveY[i] > rect.Y) { waveY[i] -= (surfaceY + waveY[i]) - rect.Y; waveVel[i] = waveVel[i] * -0.5f; } else if (surfaceY + waveY[i] < rect.Y - rect.Height) { waveY[i] -= (surfaceY + waveY[i]) - (rect.Y - rect.Height); waveVel[i] = waveVel[i] * -0.5f; } //acceleration float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening; waveVel[i] = waveVel[i] + a; } for (int j = 0; j < 2; j++) { for (int i = 1; i < waveY.Length - 1; i++) { leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]); waveVel[i - 1] = waveVel[i - 1] + leftDelta[i]; rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]); waveVel[i + 1] = waveVel[i + 1] + rightDelta[i]; } for (int i = 1; i < waveY.Length - 1; i++) { waveY[i - 1] = waveY[i - 1] + leftDelta[i]; waveY[i + 1] = waveY[i + 1] + rightDelta[i]; } } //interpolate the position of the rendered surface towards the "target surface" surface = Math.Max(MathHelper.Lerp(surface, surfaceY, deltaTime * 10.0f), rect.Y - rect.Height); if (waterVolume < Volume) { LethalPressure -= 10.0f * deltaTime; if (WaterVolume <= 0.0f) { //wait for the surface to be lerped back to bottom and the waves to settle until disabling update if (surface > rect.Y - rect.Height + 1) { return; } for (int i = 1; i < waveY.Length - 1; i++) { if (waveY[i] > 0.1f) { return; } } update = false; } } }
public override void Update(Camera cam, float deltaTime) { Oxygen -= OxygenDetoriationSpeed * deltaTime; if (EditWater) { Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); if (Submarine.RectContains(WorldRect, position)) { if (PlayerInput.LeftButtonHeld()) { //waveY[GetWaveIndex(position.X - rect.X - Submarine.Position.X) / WaveWidth] = 100.0f; Volume = Volume + 1500.0f; } else if (PlayerInput.RightButtonHeld()) { Volume = Volume - 1500.0f; } } } else if (EditFire) { Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition); if (Submarine.RectContains(WorldRect, position)) { if (PlayerInput.LeftButtonClicked()) { new FireSource(position, this); } } } FireSource.UpdateAll(fireSources, deltaTime); aiTarget.SightRange = Submarine == null ? 0.0f : Math.Max(Submarine.Velocity.Length() * 500.0f, 500.0f); aiTarget.SoundRange -= deltaTime * 1000.0f; float strongestFlow = 0.0f; foreach (Gap gap in ConnectedGaps) { if (gap.IsRoomToRoom) { //only the first linked hull plays the flow sound if (gap.linkedTo[1] == this) { continue; } } float gapFlow = gap.LerpedFlowForce.Length(); if (gapFlow > strongestFlow) { strongestFlow = gapFlow; } } if (strongestFlow > 1.0f) { soundVolume = soundVolume + ((strongestFlow < 100.0f) ? -deltaTime * 0.5f : deltaTime * 0.5f); soundVolume = MathHelper.Clamp(soundVolume, 0.0f, 1.0f); int index = (int)Math.Floor(strongestFlow / 100.0f); index = Math.Min(index, 2); var flowSound = SoundPlayer.flowSounds[index]; if (flowSound != currentFlowSound && soundIndex > -1) { Sounds.SoundManager.Stop(soundIndex); currentFlowSound = null; soundIndex = -1; } currentFlowSound = flowSound; soundIndex = currentFlowSound.Loop(soundIndex, soundVolume, WorldPosition, Math.Min(strongestFlow * 5.0f, 2000.0f)); } else { if (soundIndex > -1) { Sounds.SoundManager.Stop(soundIndex); currentFlowSound = null; soundIndex = -1; } } //update client hulls if the amount of water has changed by >10% //or if oxygen percentage has changed by 5% if (Math.Abs(lastSentVolume - volume) > FullVolume * 0.1f || Math.Abs(lastSentOxygen - OxygenPercentage) > 5f) { if (GameMain.Server != null) { sendUpdateTimer -= deltaTime; if (sendUpdateTimer < 0.0f) { GameMain.Server.CreateEntityEvent(this); lastSentVolume = volume; lastSentOxygen = OxygenPercentage; sendUpdateTimer = NetworkUpdateInterval; } } } if (!update) { lethalPressure = 0.0f; return; } float surfaceY = rect.Y - rect.Height + Volume / rect.Width; for (int i = 0; i < waveY.Length; i++) { float maxDelta = Math.Max(Math.Abs(rightDelta[i]), Math.Abs(leftDelta[i])); if (maxDelta > Rand.Range(1.0f, 10.0f)) { var particlePos = new Vector2(rect.X + WaveWidth * i, surface + waveY[i]); if (Submarine != null) { particlePos += Submarine.Position; } GameMain.ParticleManager.CreateParticle("mist", particlePos, new Vector2(0.0f, -50.0f), 0.0f, this); } waveY[i] = waveY[i] + waveVel[i]; if (surfaceY + waveY[i] > rect.Y) { waveY[i] -= (surfaceY + waveY[i]) - rect.Y; waveVel[i] = waveVel[i] * -0.5f; } else if (surfaceY + waveY[i] < rect.Y - rect.Height) { waveY[i] -= (surfaceY + waveY[i]) - (rect.Y - rect.Height); waveVel[i] = waveVel[i] * -0.5f; } //acceleration float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening; waveVel[i] = waveVel[i] + a; } for (int j = 0; j < 2; j++) { for (int i = 1; i < waveY.Length - 1; i++) { leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]); waveVel[i - 1] = waveVel[i - 1] + leftDelta[i]; rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]); waveVel[i + 1] = waveVel[i + 1] + rightDelta[i]; } for (int i = 1; i < waveY.Length - 1; i++) { waveY[i - 1] = waveY[i - 1] + leftDelta[i]; waveY[i + 1] = waveY[i + 1] + rightDelta[i]; } } //interpolate the position of the rendered surface towards the "target surface" surface = Math.Max(MathHelper.Lerp(surface, surfaceY, deltaTime * 10.0f), rect.Y - rect.Height); if (volume < FullVolume) { LethalPressure -= 10.0f * deltaTime; if (Volume == 0.0f) { //wait for the surface to be lerped back to bottom and the waves to settle until disabling update if (surface > rect.Y - rect.Height + 1) { return; } for (int i = 1; i < waveY.Length - 1; i++) { if (waveY[i] > 0.1f) { return; } } update = false; } } }
public override void Update(float deltaTime, Camera cam) { UpdateProjSpecific(deltaTime, cam); Oxygen -= OxygenDeteriorationSpeed * deltaTime; FireSource.UpdateAll(FireSources, deltaTime); aiTarget.SightRange = Submarine == null ? 0.0f : Math.Max(Submarine.Velocity.Length() * 2000.0f, AITarget.StaticSightRange); aiTarget.SoundRange -= deltaTime * 1000.0f; if (!update) { lethalPressure = 0.0f; return; } surface = Math.Max(MathHelper.Lerp( surface, rect.Y - rect.Height + WaterVolume / rect.Width, deltaTime * 10.0f), rect.Y - rect.Height); //interpolate the position of the rendered surface towards the "target surface" drawSurface = Math.Max(MathHelper.Lerp( drawSurface, rect.Y - rect.Height + WaterVolume / rect.Width, deltaTime * 10.0f), rect.Y - rect.Height); for (int i = 0; i < waveY.Length; i++) { //apply velocity waveY[i] = waveY[i] + waveVel[i]; //if the wave attempts to go "through" the top of the hull, make it bounce back if (surface + waveY[i] > rect.Y) { float excess = (surface + waveY[i]) - rect.Y; waveY[i] -= excess; waveVel[i] = waveVel[i] * -0.5f; } //if the wave attempts to go "through" the bottom of the hull, make it bounce back else if (surface + waveY[i] < rect.Y - rect.Height) { float excess = (surface + waveY[i]) - (rect.Y - rect.Height); waveY[i] -= excess; waveVel[i] = waveVel[i] * -0.5f; } //acceleration float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening; waveVel[i] = waveVel[i] + a; } //apply spread (two iterations) for (int j = 0; j < 2; j++) { for (int i = 1; i < waveY.Length - 1; i++) { leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]); waveVel[i - 1] += leftDelta[i]; rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]); waveVel[i + 1] += rightDelta[i]; } for (int i = 1; i < waveY.Length - 1; i++) { waveY[i - 1] += leftDelta[i]; waveY[i + 1] += rightDelta[i]; } } //make waves propagate through horizontal gaps foreach (Gap gap in ConnectedGaps) { if (!gap.IsRoomToRoom || !gap.IsHorizontal || gap.Open <= 0.0f) { continue; } if (surface > gap.Rect.Y || surface < gap.Rect.Y - gap.Rect.Height) { continue; } Hull hull2 = this == gap.linkedTo[0] as Hull ? (Hull)gap.linkedTo[1] : (Hull)gap.linkedTo[0]; float otherSurfaceY = hull2.surface; if (otherSurfaceY > gap.Rect.Y || otherSurfaceY < gap.Rect.Y - gap.Rect.Height) { continue; } float surfaceDiff = (surface - otherSurfaceY) * gap.Open; if (this != gap.linkedTo[0] as Hull) { //the first hull linked to the gap handles the wave propagation, //the second just updates the surfaces to the same level if (surfaceDiff < 32.0f) { hull2.waveY[hull2.waveY.Length - 1] = surfaceDiff * 0.5f; waveY[0] = -surfaceDiff * 0.5f; } continue; } for (int j = 0; j < 2; j++) { int i = waveY.Length - 1; leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]); waveVel[i - 1] += leftDelta[i]; rightDelta[i] = WaveSpread * (waveY[i] - hull2.waveY[0] + surfaceDiff); hull2.waveVel[0] += rightDelta[i]; i = 0; hull2.leftDelta[i] = WaveSpread * (hull2.waveY[i] - waveY[waveY.Length - 1] - surfaceDiff); waveVel[waveVel.Length - 1] += hull2.leftDelta[i]; hull2.rightDelta[i] = WaveSpread * (hull2.waveY[i] - hull2.waveY[i + 1]); hull2.waveVel[i + 1] += hull2.rightDelta[i]; } if (surfaceDiff < 32.0f) { //update surfaces to the same level hull2.waveY[0] = surfaceDiff * 0.5f; waveY[waveY.Length - 1] = -surfaceDiff * 0.5f; } else { hull2.waveY[0] += rightDelta[waveY.Length - 1]; waveY[waveY.Length - 1] += hull2.leftDelta[0]; } } if (waterVolume < Volume) { LethalPressure -= 10.0f * deltaTime; if (WaterVolume <= 0.0f) { //wait for the surface to be lerped back to bottom and the waves to settle until disabling update if (drawSurface > rect.Y - rect.Height + 1) { return; } for (int i = 1; i < waveY.Length - 1; i++) { if (waveY[i] > 0.1f) { return; } } update = false; } } }
public override void Update(float deltaTime, Camera cam) { base.Update(deltaTime, cam); UpdateProjSpecific(deltaTime, cam); Oxygen -= OxygenDeteriorationSpeed * deltaTime; FireSource.UpdateAll(FireSources, deltaTime); if (aiTarget != null) { aiTarget.SightRange = Submarine == null ? aiTarget.MinSightRange : Submarine.Velocity.Length() / 2 * aiTarget.MaxSightRange; aiTarget.SoundRange -= deltaTime * 1000.0f; } if (!update) { lethalPressure = 0.0f; return; } float waterDepth = WaterVolume / rect.Width; if (waterDepth < 1.0f) { //if there's only a minuscule amount of water, consider the surface to be at the bottom of the hull //otherwise unnoticeable amounts of water can for example cause magnesium to explode waterDepth = 0.0f; } surface = Math.Max(MathHelper.Lerp( surface, rect.Y - rect.Height + waterDepth, deltaTime * 10.0f), rect.Y - rect.Height); //interpolate the position of the rendered surface towards the "target surface" drawSurface = Math.Max(MathHelper.Lerp( drawSurface, rect.Y - rect.Height + waterDepth, deltaTime * 10.0f), rect.Y - rect.Height); for (int i = 0; i < waveY.Length; i++) { //apply velocity waveY[i] = waveY[i] + waveVel[i]; //if the wave attempts to go "through" the top of the hull, make it bounce back if (surface + waveY[i] > rect.Y) { float excess = (surface + waveY[i]) - rect.Y; waveY[i] -= excess; waveVel[i] = waveVel[i] * -0.5f; } //if the wave attempts to go "through" the bottom of the hull, make it bounce back else if (surface + waveY[i] < rect.Y - rect.Height) { float excess = (surface + waveY[i]) - (rect.Y - rect.Height); waveY[i] -= excess; waveVel[i] = waveVel[i] * -0.5f; } //acceleration float a = -WaveStiffness * waveY[i] - waveVel[i] * WaveDampening; waveVel[i] = waveVel[i] + a; } //apply spread (two iterations) for (int j = 0; j < 2; j++) { for (int i = 1; i < waveY.Length - 1; i++) { leftDelta[i] = WaveSpread * (waveY[i] - waveY[i - 1]); waveVel[i - 1] += leftDelta[i]; rightDelta[i] = WaveSpread * (waveY[i] - waveY[i + 1]); waveVel[i + 1] += rightDelta[i]; } } //make waves propagate through horizontal gaps foreach (Gap gap in ConnectedGaps) { if (this != gap.linkedTo[0] as Hull) { //let the first linked hull handle the water propagation continue; } if (!gap.IsRoomToRoom || !gap.IsHorizontal || gap.Open <= 0.0f) { continue; } if (surface > gap.Rect.Y || surface < gap.Rect.Y - gap.Rect.Height) { continue; } // ReSharper refuses to compile this if it's using "as Hull" since "as" means it can be null and you can't compare null to true or false Hull hull2 = this == gap.linkedTo[0] ? (Hull)gap.linkedTo[1] : (Hull)gap.linkedTo[0]; float otherSurfaceY = hull2.surface; if (otherSurfaceY > gap.Rect.Y || otherSurfaceY < gap.Rect.Y - gap.Rect.Height) { continue; } float surfaceDiff = (surface - otherSurfaceY) * gap.Open; for (int j = 0; j < 2; j++) { rightDelta[waveY.Length - 1] = WaveSpread * (hull2.waveY[0] - waveY[waveY.Length - 1] - surfaceDiff) * 0.5f; waveVel[waveY.Length - 1] += rightDelta[waveY.Length - 1]; waveY[waveY.Length - 1] += rightDelta[waveY.Length - 1]; hull2.leftDelta[0] = WaveSpread * (waveY[waveY.Length - 1] - hull2.waveY[0] + surfaceDiff) * 0.5f; hull2.waveVel[0] += hull2.leftDelta[0]; hull2.waveY[0] += hull2.leftDelta[0]; } if (surfaceDiff < 32.0f) { //update surfaces to the same level hull2.waveY[0] = surfaceDiff * 0.5f; waveY[waveY.Length - 1] = -surfaceDiff * 0.5f; } } //apply spread (two iterations) for (int j = 0; j < 2; j++) { for (int i = 1; i < waveY.Length - 1; i++) { waveY[i - 1] += leftDelta[i]; waveY[i + 1] += rightDelta[i]; } } if (waterVolume < Volume) { LethalPressure -= 10.0f * deltaTime; if (WaterVolume <= 0.0f) { //wait for the surface to be lerped back to bottom and the waves to settle until disabling update if (drawSurface > rect.Y - rect.Height + 1) { return; } for (int i = 1; i < waveY.Length - 1; i++) { if (waveY[i] > 0.1f) { return; } } update = false; } } }