202 lines
8.0 KiB
C#
202 lines
8.0 KiB
C#
using Barotrauma.Extensions;
|
|
using Barotrauma.Items.Components;
|
|
using Microsoft.Xna.Framework;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
partial class AfflictionPsychosis : Affliction
|
|
{
|
|
const int MaxFakeFireSources = 10;
|
|
const float MinFakeFireSourceInterval = 30.0f, MaxFakeFireSourceInterval = 240.0f;
|
|
private float createFireSourceTimer;
|
|
private readonly List<DummyFireSource> fakeFireSources = new List<DummyFireSource>();
|
|
|
|
public enum FloodType
|
|
{
|
|
None,
|
|
Minor,
|
|
Major,
|
|
HideFlooding
|
|
}
|
|
|
|
const float MinSoundInterval = 60.0f, MaxSoundInterval = 240.0f;
|
|
private FloodType currentFloodType;
|
|
private float soundTimer;
|
|
|
|
const float MinFloodInterval = 60.0f, MaxFloodInterval = 240.0f;
|
|
private float createFloodTimer;
|
|
private float currentFloodState;
|
|
private float currentFloodDuration;
|
|
|
|
private float fakeBrokenInterval = 30.0f;
|
|
private float fakeBrokenTimer = 0.0f;
|
|
|
|
private float invisibleCharacterInterval = 30.0f;
|
|
private float invisibleCharacterTimer = 0.0f;
|
|
|
|
public FloodType CurrentFloodType
|
|
{
|
|
get { return currentFloodType; }
|
|
}
|
|
|
|
partial void UpdateProjSpecific(CharacterHealth characterHealth, Limb targetLimb, float deltaTime)
|
|
{
|
|
if (Character.Controlled != characterHealth.Character) return;
|
|
UpdateFloods(deltaTime);
|
|
UpdateSounds(characterHealth.Character, deltaTime);
|
|
UpdateFires(characterHealth.Character, deltaTime);
|
|
UpdateInvisibleCharacters(deltaTime);
|
|
UpdateFakeBroken(deltaTime);
|
|
}
|
|
|
|
private void UpdateSounds(Character character, float deltaTime)
|
|
{
|
|
if (soundTimer < MathHelper.Lerp(MaxSoundInterval, MinSoundInterval, Strength / 100.0f))
|
|
{
|
|
soundTimer += deltaTime;
|
|
return;
|
|
}
|
|
|
|
float impactStrength = MathHelper.Lerp(0.1f, 1.0f, Strength / 100.0f);
|
|
SoundPlayer.PlayDamageSound("StructureBlunt", Rand.Range(10.0f, 1000.0f), character.WorldPosition + Rand.Vector(500.0f));
|
|
GameMain.GameScreen.Cam.Shake = impactStrength * 10.0f;
|
|
GameMain.GameScreen.Cam.AngularVelocity = Rand.Range(-impactStrength, impactStrength);
|
|
soundTimer = 0.0f;
|
|
}
|
|
|
|
private void UpdateFloods(float deltaTime)
|
|
{
|
|
if (currentFloodDuration > 0.0f)
|
|
{
|
|
currentFloodDuration -= deltaTime;
|
|
switch (currentFloodType)
|
|
{
|
|
case FloodType.Minor:
|
|
currentFloodState += deltaTime;
|
|
//lerp the water surface in all hulls 15 units above the floor within 10 seconds
|
|
foreach (Hull hull in Hull.HullList)
|
|
{
|
|
for (int i = hull.FakeFireSources.Count - 1; i >= 0; i--)
|
|
{
|
|
hull.FakeFireSources[i].Extinguish(deltaTime, 50.0f);
|
|
}
|
|
hull.DrawSurface = hull.Rect.Y - hull.Rect.Height + MathHelper.Lerp(0.0f, 15.0f, currentFloodState / 10.0f);
|
|
}
|
|
break;
|
|
case FloodType.Major:
|
|
currentFloodState += deltaTime;
|
|
//create a full flood in 10 seconds
|
|
foreach (Hull hull in Hull.HullList)
|
|
{
|
|
for (int i = hull.FakeFireSources.Count - 1; i >= 0; i--)
|
|
{
|
|
hull.FakeFireSources[i].Extinguish(deltaTime, 200.0f);
|
|
}
|
|
hull.DrawSurface = hull.Rect.Y - MathHelper.Lerp(hull.Rect.Height, 0.0f, currentFloodState / 10.0f);
|
|
}
|
|
break;
|
|
case FloodType.HideFlooding:
|
|
//hide water inside hulls (the player can't see which hulls are flooded)
|
|
foreach (Hull hull in Hull.HullList)
|
|
{
|
|
hull.DrawSurface = hull.Rect.Y - hull.Rect.Height;
|
|
}
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (createFloodTimer < MathHelper.Lerp(MaxFloodInterval, MinFloodInterval, Strength / 100.0f))
|
|
{
|
|
currentFloodType = FloodType.None;
|
|
createFloodTimer += deltaTime;
|
|
return;
|
|
}
|
|
|
|
//probability of a fake flood goes from 0%-100%
|
|
if (Rand.Range(0.0f, 100.0f) < Strength)
|
|
{
|
|
if (Rand.Range(0.0f, 1.0f) < 0.5f)
|
|
{
|
|
currentFloodType = FloodType.HideFlooding;
|
|
currentFloodType = FloodType.Minor;
|
|
}
|
|
else
|
|
{
|
|
//disabled Major flooding because it's too easy to tell it's fake
|
|
currentFloodType = FloodType.Minor;// Strength < 50.0f ? FloodType.Minor : FloodType.Major;
|
|
}
|
|
currentFloodDuration = Rand.Range(20.0f, 100.0f);
|
|
}
|
|
createFloodTimer = 0.0f;
|
|
}
|
|
|
|
private void UpdateFires(Character character, float deltaTime)
|
|
{
|
|
createFireSourceTimer += deltaTime;
|
|
fakeFireSources.RemoveAll(fs => fs.Removed);
|
|
if (fakeFireSources.Count < MaxFakeFireSources &&
|
|
character.Submarine != null &&
|
|
createFireSourceTimer > MathHelper.Lerp(MaxFakeFireSourceInterval, MinFakeFireSourceInterval, Strength / 100.0f))
|
|
{
|
|
Hull fireHull = Hull.HullList.GetRandomUnsynced(h => h.Submarine == character.Submarine);
|
|
if (fireHull != null)
|
|
{
|
|
var fakeFire = new DummyFireSource(Vector2.One * 500.0f, new Vector2(Rand.Range(fireHull.WorldRect.X, fireHull.WorldRect.Right), fireHull.WorldPosition.Y + 1), fireHull, isNetworkMessage: true)
|
|
{
|
|
CausedByPsychosis = true,
|
|
DamagesItems = false,
|
|
DamagesCharacters = false
|
|
};
|
|
fakeFireSources.Add(fakeFire);
|
|
createFireSourceTimer = 0.0f;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateInvisibleCharacters(float deltaTime)
|
|
{
|
|
invisibleCharacterTimer -= deltaTime;
|
|
if (invisibleCharacterTimer > 0.0f) { return; }
|
|
|
|
foreach (Character c in Character.CharacterList)
|
|
{
|
|
if (c.IsDead || c == Character.Controlled) { continue; }
|
|
if (c.WorldPosition.X < GameMain.GameScreen.Cam.WorldView.X || c.WorldPosition.X > GameMain.GameScreen.Cam.WorldView.Right) { continue; }
|
|
if (c.WorldPosition.Y < GameMain.GameScreen.Cam.WorldView.Y - GameMain.GameScreen.Cam.WorldView.Height || c.WorldPosition.Y > GameMain.GameScreen.Cam.WorldView.Y) { continue; }
|
|
if (Rand.Range(0.0f, 500.0f) < Strength)
|
|
{
|
|
c.InvisibleTimer = 60.0f;
|
|
}
|
|
}
|
|
|
|
invisibleCharacterTimer = invisibleCharacterInterval;
|
|
}
|
|
|
|
|
|
private void UpdateFakeBroken(float deltaTime)
|
|
{
|
|
fakeBrokenTimer -= deltaTime;
|
|
if (fakeBrokenTimer > 0.0f) { return; }
|
|
|
|
foreach (Item item in Item.RepairableItems)
|
|
{
|
|
var repairable = item.GetComponent<Repairable>();
|
|
if (repairable == null) { continue; }
|
|
if (ShouldFakeBrokenItem(item))
|
|
{
|
|
repairable.FakeBrokenTimer = 60.0f;
|
|
}
|
|
}
|
|
|
|
fakeBrokenTimer = fakeBrokenInterval;
|
|
}
|
|
|
|
private bool ShouldFakeBrokenItem(Item item)
|
|
{
|
|
return Rand.Range(0.0f, 1000.0f) < Strength;
|
|
}
|
|
}
|
|
}
|