Build 0.18.0.0

This commit is contained in:
Markus Isberg
2022-05-13 00:55:52 +09:00
parent 15d18e6ff6
commit 7547a9b78a
218 changed files with 3881 additions and 2192 deletions
@@ -299,11 +299,41 @@ namespace Barotrauma
/// Random integers generated during the level generation. If these values differ between clients/server,
/// it means the levels aren't identical for some reason and there will most likely be major ID mismatches.
/// </summary>
public List<int> EqualityCheckValues
public enum LevelGenStage
{
get;
private set;
} = new List<int>();
GenStart,
TunnelGen,
VoronoiGen,
VoronoiGen2,
VoronoiGen3,
Ruins,
FloatingIce,
LevelBodies,
IceSpires,
TopAndBottom,
PlaceLevelObjects,
GenerateItems,
Finish
}
private readonly Dictionary<LevelGenStage, int> equalityCheckValues = Enum.GetValues(typeof(LevelGenStage))
.Cast<LevelGenStage>()
.Select(k => (k, 0))
.ToDictionary();
public IReadOnlyDictionary<LevelGenStage, int> EqualityCheckValues => equalityCheckValues;
private void GenerateEqualityCheckValue(LevelGenStage stage)
{
equalityCheckValues[stage] = Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient);
}
private void ClearEqualityCheckValues()
{
foreach (LevelGenStage stage in Enum.GetValues(typeof(LevelGenStage)))
{
equalityCheckValues[stage] = 0;
}
}
public List<Entity> EntitiesBeforeGenerate { get; private set; } = new List<Entity>();
public int EntityCountBeforeGenerate { get; private set; }
@@ -404,7 +434,7 @@ namespace Barotrauma
Loaded = this;
Generating = true;
EqualityCheckValues.Clear();
ClearEqualityCheckValues();
EntitiesBeforeGenerate = GetEntities().ToList();
EntityCountBeforeGenerate = EntitiesBeforeGenerate.Count();
@@ -414,7 +444,7 @@ namespace Barotrauma
EndLocation = GameMain.GameSession?.EndLocation;
}
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.GenStart);
LevelObjectManager = new LevelObjectManager();
@@ -477,7 +507,7 @@ namespace Barotrauma
(int)MathHelper.Lerp(borders.Bottom - Math.Max(minMainPathWidth, ExitDistance * 1.5f), borders.Y + minMainPathWidth, GenerationParams.EndPosition.Y));
endExitPosition = new Point(endPosition.X, borders.Bottom);
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.TunnelGen);
//----------------------------------------------------------------------------------
//generate the initial nodes for the main path and smaller tunnels
@@ -573,7 +603,7 @@ namespace Barotrauma
GenerateAbyssArea();
GenerateCaves(mainPath);
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.VoronoiGen);
//----------------------------------------------------------------------------------
//generate voronoi sites
@@ -678,7 +708,7 @@ namespace Barotrauma
}
}
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.VoronoiGen2);
//----------------------------------------------------------------------------------
// construct the voronoi graph and cells
@@ -796,7 +826,7 @@ namespace Barotrauma
startPosition.X = (int)pathCells[0].Site.Coord.X;
startExitPosition.X = startPosition.X;
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.VoronoiGen3);
//----------------------------------------------------------------------------------
// remove unnecessary cells and create some holes at the bottom of the level
@@ -1025,7 +1055,7 @@ namespace Barotrauma
}
}
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.Ruins);
//----------------------------------------------------------------------------------
// create some ruins
@@ -1038,7 +1068,7 @@ namespace Barotrauma
GenerateRuin(ruinPositions[i], mirror);
}
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.FloatingIce);
//----------------------------------------------------------------------------------
// create floating ice chunks
@@ -1070,7 +1100,7 @@ namespace Barotrauma
}
}
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.LevelBodies);
//----------------------------------------------------------------------------------
// generate the bodies and rendered triangles of the cells
@@ -1175,7 +1205,7 @@ namespace Barotrauma
}
#endif
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.IceSpires);
//----------------------------------------------------------------------------------
// create ice spires
@@ -1210,7 +1240,7 @@ namespace Barotrauma
CreateOutposts();
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.TopAndBottom);
//----------------------------------------------------------------------------------
// top barrier & sea floor
@@ -1252,15 +1282,15 @@ namespace Barotrauma
CreateWrecks();
CreateBeaconStation();
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.PlaceLevelObjects);
LevelObjectManager.PlaceObjects(this, GenerationParams.LevelObjectAmount);
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.GenerateItems);
GenerateItems();
EqualityCheckValues.Add(Rand.Int(int.MaxValue, Rand.RandSync.ServerAndClient));
GenerateEqualityCheckValue(LevelGenStage.Finish);
#if CLIENT
backgroundCreatureManager.SpawnCreatures(this, GenerationParams.BackgroundCreatureAmount);
@@ -2606,7 +2636,7 @@ namespace Barotrauma
#if DEBUG
DebugConsole.NewMessage("Level resources spawned: " + itemCount + "\n" +
" Spawn points containing resources: " + PathPoints.Where(p => p.ClusterLocations.Any()).Count() + "/" + PathPoints.Count + "\n" +
" Total value: "+ PathPoints.Sum(p => p.ClusterLocations.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0)))+" mk");
" Total value: " + PathPoints.Sum(p => p.ClusterLocations.Sum(c => c.Resources.Sum(r => r.Prefab.DefaultPrice?.Price ?? 0))) + " mk");
if (AbyssResources.Count > 0)
{
@@ -3688,6 +3718,7 @@ namespace Barotrauma
if (wreckFiles.None())
{
DebugConsole.ThrowError("No wreck files found in the selected content packages!");
Wrecks = new List<Submarine>();
return;
}
wreckFiles.Shuffle(Rand.RandSync.ServerAndClient);
@@ -4112,12 +4143,12 @@ namespace Barotrauma
int corpseCount = Rand.Range(Loaded.GenerationParams.MinCorpseCount, Loaded.GenerationParams.MaxCorpseCount + 1);
var allSpawnPoints = WayPoint.WayPointList.FindAll(wp => wp.Submarine == wreck && wp.CurrentHull != null);
var pathPoints = allSpawnPoints.FindAll(wp => wp.SpawnType == SpawnType.Path);
pathPoints.Shuffle(Rand.RandSync.Unsynced);
var corpsePoints = allSpawnPoints.FindAll(wp => wp.SpawnType == SpawnType.Corpse);
corpsePoints.Shuffle(Rand.RandSync.Unsynced);
if (!corpsePoints.Any() && !pathPoints.Any()) { continue; }
pathPoints.Shuffle(Rand.RandSync.Unsynced);
// Sort by job so that we first spawn those with a predefined job (might have special id cards)
corpsePoints = corpsePoints.OrderBy(p => p.AssignedJob == null).ThenBy(p => Rand.Value()).ToList();
var usedJobs = new HashSet<JobPrefab>();
int spawnCounter = 0;
for (int j = 0; j < corpseCount; j++)
{
@@ -4126,18 +4157,18 @@ namespace Barotrauma
CorpsePrefab selectedPrefab;
if (job == null)
{
selectedPrefab = GetCorpsePrefab(p => p.SpawnPosition == PositionType.Wreck);
selectedPrefab = GetCorpsePrefab(usedJobs);
}
else
{
selectedPrefab = GetCorpsePrefab(p => p.SpawnPosition == PositionType.Wreck && (p.Job == "any" || p.Job == job.Identifier));
selectedPrefab = GetCorpsePrefab(usedJobs, p => p.Job == "any" || p.Job == job.Identifier);
if (selectedPrefab == null)
{
corpsePoints.Remove(sp);
pathPoints.Remove(sp);
sp = corpsePoints.FirstOrDefault(sp => sp.AssignedJob == null) ?? pathPoints.FirstOrDefault(sp => sp.AssignedJob == null);
// Deduce the job from the selected prefab
selectedPrefab = GetCorpsePrefab(p => p.SpawnPosition == PositionType.Wreck);
selectedPrefab = GetCorpsePrefab(usedJobs);
}
}
if (selectedPrefab == null) { continue; }
@@ -4156,28 +4187,65 @@ namespace Barotrauma
pathPoints.Remove(sp);
}
job ??= selectedPrefab.GetJobPrefab();
job ??= selectedPrefab.GetJobPrefab(predicate: p => !usedJobs.Contains(p));
if (job == null) { continue; }
if (job.Identifier == "captain" || job.Identifier == "engineer" || job.Identifier == "medicaldoctor" || job.Identifier == "securityofficer")
{
// Only spawn one of these jobs per wreck
usedJobs.Add(job);
}
var characterInfo = new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: job, randSync: Rand.RandSync.ServerAndClient);
var corpse = Character.Create(CharacterPrefab.HumanSpeciesName, worldPos, ToolBox.RandomSeed(8), characterInfo, hasAi: true, createNetworkEvent: true);
corpse.AnimController.FindHull(worldPos, setSubmarine: true);
corpse.TeamID = CharacterTeamType.None;
corpse.EnableDespawn = false;
selectedPrefab.GiveItems(corpse, wreck);
corpse.CharacterHealth.ApplyAffliction(corpse.AnimController.MainLimb, AfflictionPrefab.OxygenLow.Instantiate(200));
bool applyBurns = Rand.Value() < 0.1f;
bool applyDamage = Rand.Value() < 0.3f;
foreach (var limb in corpse.AnimController.Limbs)
{
if (applyDamage && (limb.type == LimbType.Head || Rand.Value() < 0.5f))
{
var prefab = AfflictionPrefab.BiteWounds;
float max = prefab.MaxStrength / prefab.DamageOverlayAlpha;
corpse.CharacterHealth.ApplyAffliction(limb, prefab.Instantiate(GetStrength(limb, max)));
}
if (applyBurns)
{
var prefab = AfflictionPrefab.Burn;
float max = prefab.MaxStrength / prefab.BurnOverlayAlpha;
corpse.CharacterHealth.ApplyAffliction(limb, prefab.Instantiate(GetStrength(limb, max)));
}
static float GetStrength(Limb limb, float max)
{
float strength = Rand.Range(0, max);
if (limb.type != LimbType.Head)
{
strength = Math.Min(strength, Rand.Range(0, max));
}
return strength;
}
}
corpse.Kill(CauseOfDeathType.Unknown, causeOfDeathAffliction: null, log: false);
corpse.GiveIdCardTags(sp);
#if SERVER
if (selectedPrefab.MinMoney >= 0 && selectedPrefab.MaxMoney > 0)
bool isServerOrSingleplayer = GameMain.IsSingleplayer || GameMain.NetworkMember is { IsServer: true };
if (isServerOrSingleplayer && selectedPrefab.MinMoney >= 0 && selectedPrefab.MaxMoney > 0)
{
corpse.Wallet.Give(Rand.Range(selectedPrefab.MinMoney, selectedPrefab.MaxMoney, Rand.RandSync.Unsynced));
}
#endif
spawnCounter++;
static CorpsePrefab GetCorpsePrefab(Func<CorpsePrefab, bool> predicate)
static CorpsePrefab GetCorpsePrefab(HashSet<JobPrefab> usedJobs, Func<CorpsePrefab, bool> predicate = null)
{
IEnumerable<CorpsePrefab> filteredPrefabs = CorpsePrefab.Prefabs.Where(predicate);
IEnumerable<CorpsePrefab> filteredPrefabs = CorpsePrefab.Prefabs.Where(p =>
usedJobs.None(j => j.Identifier == p.Job.ToIdentifier()) &&
p.SpawnPosition == PositionType.Wreck &&
(predicate == null || predicate(p)));
return ToolBox.SelectWeightedRandom(filteredPrefabs.ToList(), filteredPrefabs.Select(p => p.Commonness).ToList(), Rand.RandSync.Unsynced);
}
}
@@ -4270,7 +4338,7 @@ namespace Barotrauma
blockedRects?.Clear();
EntitiesBeforeGenerate?.Clear();
EqualityCheckValues?.Clear();
ClearEqualityCheckValues();
if (Ruins != null)
{