Unstable 1.8.4.0

This commit is contained in:
Markus Isberg
2025-03-12 12:56:27 +00:00
parent a4c3e868e4
commit a4a3427e4e
627 changed files with 29860 additions and 10018 deletions
@@ -158,6 +158,7 @@ namespace Barotrauma
activeEvents.Clear();
#if SERVER
MissionAction.ResetMissionsUnlockedThisRound();
UnlockPathAction.ResetPathsUnlockedThisRound();
#endif
pathFinder = new PathFinder(WayPoint.WayPointList, false);
totalPathLength = 0.0f;
@@ -180,11 +181,46 @@ namespace Barotrauma
random = new MTRandom(RandomSeed);
bool playingCampaign = GameMain.GameSession?.GameMode is CampaignMode;
EventSet initialEventSet = SelectRandomEvents(
EventSet.Prefabs.ToList(),
requireCampaignSet: playingCampaign,
random: random);
//ensure that the sets that have been configured to be always selected get selected if there's any available
EventSet initialEventSet = null;
EventSet additiveSet = null;
var selectAlwaysEventSets = GetAllowedEventSets(EventSet.Prefabs.ToList(), requireCampaignSet: playingCampaign).Where(s => s.SelectAlways);
foreach (var eventSet in selectAlwaysEventSets)
{
if (eventSet.GetCommonness(level) <= 0.0f)
{
//you might be wondering why an event set would be configured to SelectAlways, but have a commonness of 0:
//the set might have a non-zero commonness in some other biome or level type, but not this one
continue;
}
if (eventSet.Additive)
{
additiveSet = eventSet;
}
else
{
if (initialEventSet == null)
{
initialEventSet = eventSet;
}
else //initial set already chosen, ignore this one
{
continue;
}
}
AddSet(eventSet);
}
if (initialEventSet == null)
{
initialEventSet = SelectRandomEvents(
EventSet.Prefabs.ToList(),
requireCampaignSet: playingCampaign,
random: random);
}
//we happened to choose an additive set as the initial one, choose an additive one too
if (initialEventSet != null && initialEventSet.Additive)
{
additiveSet = initialEventSet;
@@ -193,15 +229,15 @@ namespace Barotrauma
requireCampaignSet: playingCampaign,
random: random);
}
if (initialEventSet != null)
if (initialEventSet != null) { AddSet(initialEventSet); }
if (additiveSet != null) { AddSet(additiveSet); }
void AddSet(EventSet eventSet)
{
pendingEventSets.Add(initialEventSet);
CreateEvents(initialEventSet);
}
if (additiveSet != null)
{
pendingEventSets.Add(additiveSet);
CreateEvents(additiveSet);
if (pendingEventSets.Contains(eventSet)) { return; }
pendingEventSets.Add(eventSet);
CreateEvents(eventSet);
}
if (level?.LevelData != null)
@@ -223,6 +259,22 @@ namespace Barotrauma
level.StartLocation.Connections.ForEach(c => c.Locked = false);
}
}
if (GameMain.NetworkMember is not { IsClient: true } && level.StartOutpost != null)
{
foreach (var eventTag in level.StartOutpost.Info.TriggerOutpostMissionEvents)
{
EventPrefab eventPrefab = EventPrefab.FindEventPrefab(identifier: Identifier.Empty, tag: eventTag, level.StartOutpost.ContentPackage);
if (eventPrefab == null)
{
DebugConsole.ThrowError($"Outpost {level.StartOutpost.Info.DisplayName} failed to trigger an event (tag: {eventTag}).", contentPackage: level.StartOutpost.ContentPackage);
}
else
{
var newEvent = eventPrefab.CreateInstance(RandomSeed);
ActivateEvent(newEvent);
}
}
}
}
RegisterNonRepeatableChildEvents(initialEventSet);
void RegisterNonRepeatableChildEvents(EventSet eventSet)
@@ -244,7 +296,7 @@ namespace Barotrauma
while (QueuedEventsForNextRound.TryDequeue(out var id))
{
var eventPrefab = EventSet.GetEventPrefab(id);
var eventPrefab = EventSet.GetEventPrefab(id) ?? EventSet.GetAllEventPrefabs().Where(e => e.Tags.Contains(id)).GetRandomUnsynced();
if (eventPrefab == null)
{
DebugConsole.ThrowError($"Error in EventManager.StartRound - could not find an event with the identifier {id}.");
@@ -421,12 +473,10 @@ namespace Barotrauma
/// <summary>
/// Registers the exhaustible events in the level as exhausted, and adds the current events to the event history
/// </summary>
public void RegisterEventHistory(bool registerFinishedOnly = false)
public void StoreEventDataAtRoundEnd(bool registerFinishedOnly = false)
{
if (level?.LevelData == null) { return; }
level.LevelData.EventsExhausted = !registerFinishedOnly;
if (level.LevelData.Type == LevelData.LevelType.Outpost)
{
if (registerFinishedOnly)
@@ -437,7 +487,7 @@ namespace Barotrauma
if (parentSet == null) { continue; }
if (parentSet.Exhaustible)
{
level.LevelData.EventsExhausted = true;
level.LevelData.ExhaustEventSet(parentSet);
}
if (!level.LevelData.FinishedEvents.TryAdd(parentSet, 1))
{
@@ -484,7 +534,7 @@ namespace Barotrauma
selectedEvents.Remove(eventSet);
if (level == null) { return; }
if (level.LevelData.HasHuntingGrounds && eventSet.DisableInHuntingGrounds) { return; }
if (eventSet.Exhaustible && level.LevelData.EventsExhausted) { return; }
if (eventSet.Exhaustible && level.LevelData.IsEventSetExhausted(eventSet)) { return; }
DebugConsole.NewMessage($"Loading event set {eventSet.Identifier}", Color.LightBlue, debugOnly: true);
@@ -609,12 +659,11 @@ namespace Barotrauma
}
}
private EventSet SelectRandomEvents(IReadOnlyList<EventSet> eventSets, bool? requireCampaignSet = null, Random random = null)
private IEnumerable<EventSet> GetAllowedEventSets(IReadOnlyList<EventSet> eventSets, bool? requireCampaignSet = null)
{
if (level == null) { return null; }
Random rand = random ?? new MTRandom(ToolBox.StringToInt(level.Seed));
if (level == null) { return Enumerable.Empty<EventSet>(); }
var allowedEventSets =
var allowedEventSets =
eventSets.Where(set => IsValidForLevel(set, level));
if (requireCampaignSet.HasValue)
@@ -659,6 +708,12 @@ namespace Barotrauma
// When there are no forced sets, only allow sets that aren't forced at any specific location
allowedEventSets = allowedEventSets.Where(set => set.ForceAtDiscoveredNr < 0 && set.ForceAtVisitedNr < 0);
}
return allowedEventSets;
}
private EventSet SelectRandomEvents(IReadOnlyList<EventSet> eventSets, bool? requireCampaignSet = null, Random random = null)
{
var allowedEventSets = GetAllowedEventSets(eventSets, requireCampaignSet);
if (allowedEventSets.Count() == 1)
{
@@ -666,6 +721,7 @@ namespace Barotrauma
return allowedEventSets.First();
}
Random rand = random ?? new MTRandom(ToolBox.StringToInt(level.Seed));
float totalCommonness = allowedEventSets.Sum(e => e.GetCommonness(level));
float randomNumber = (float)rand.NextDouble();
randomNumber *= totalCommonness;
@@ -692,6 +748,7 @@ namespace Barotrauma
return
(e.BiomeIdentifier.IsEmpty || e.BiomeIdentifier == level.LevelData?.Biome?.Identifier) &&
(e.RequiredLayer.IsEmpty || Submarine.LayerExistsInAnySub(e.RequiredLayer)) &&
(e.RequiredSpawnPointTag.IsEmpty || WayPoint.WayPointList.Any(wp => wp.Tags.Contains(e.RequiredSpawnPointTag))) &&
!level.LevelData.NonRepeatableEvents.Contains(e.Identifier);
}
@@ -704,8 +761,9 @@ namespace Barotrauma
{
return
level.IsAllowedDifficulty(eventSet.MinLevelDifficulty, eventSet.MaxLevelDifficulty) &&
level.LevelData.Type == eventSet.LevelType &&
eventSet.LevelType.HasFlag(level.LevelData.Type) &&
(eventSet.RequiredLayer.IsEmpty || Submarine.LayerExistsInAnySub(eventSet.RequiredLayer)) &&
(eventSet.RequiredSpawnPointTag.IsEmpty || WayPoint.WayPointList.Any(wp => wp.Tags.Contains(eventSet.RequiredSpawnPointTag))) &&
(eventSet.BiomeIdentifier.IsEmpty || eventSet.BiomeIdentifier == level.LevelData.Biome.Identifier);
}
@@ -716,7 +774,7 @@ namespace Barotrauma
{
if (eventSet.Faction != location.Faction?.Prefab.Identifier && eventSet.Faction != location.SecondaryFaction?.Prefab.Identifier) { return false; }
}
var locationType = location.GetLocationType();
var locationType = location.Type;
bool includeGenericEvents = level.Type == LevelData.LevelType.LocationConnection || !locationType.IgnoreGenericEvents;
if (includeGenericEvents && eventSet.LocationTypeIdentifiers == null) { return true; }
return eventSet.LocationTypeIdentifiers != null && eventSet.LocationTypeIdentifiers.Any(identifier => identifier == locationType.Identifier);
@@ -965,9 +1023,9 @@ namespace Barotrauma
monsterStrength += enemyAI.CombatStrength;
}
if (character.CurrentHull?.Submarine?.Info != null &&
(character.CurrentHull.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(character.CurrentHull.Submarine)) &&
character.CurrentHull.Submarine.Info.Type == SubmarineType.Player)
if (Submarine.MainSub != null &&
character.CurrentHull?.Submarine.Info is { Type: SubmarineType.Player } &&
(character.CurrentHull.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(character.CurrentHull.Submarine)))
{
// Enemy onboard -> Crawler inside the sub adds 0.2 to enemy danger, Mudraptor 0.42
enemyDanger += enemyAI.CombatStrength / 500.0f;
@@ -981,8 +1039,8 @@ namespace Barotrauma
}
else if (character.AIController is HumanAIController humanAi && !character.IsOnFriendlyTeam(CharacterTeamType.Team1))
{
if (character.Submarine != null &&
character.Submarine.PhysicsBody is { BodyType: BodyType.Dynamic } &&
if (character.Submarine != null && Submarine.MainSub != null &&
character.Submarine.PhysicsBody is { BodyType: BodyType.Dynamic } &&
Vector2.DistanceSquared(character.Submarine.WorldPosition, Submarine.MainSub.WorldPosition) < Sonar.DefaultSonarRange * Sonar.DefaultSonarRange)
{
//we have no easy way to define the strength of a human enemy (depends more on the sub and it's state than the character),
@@ -1111,16 +1169,15 @@ namespace Barotrauma
/// Get the entity that should be used in determining how far the player has progressed in the level.
/// = The submarine or player character that has progressed the furthest.
/// </summary>
public static ISpatialEntity GetRefEntity()
public static ISpatialEntity GetRefEntity(bool acceptRemoteControlledSubs = false)
{
ISpatialEntity refEntity = Submarine.MainSub;
#if CLIENT
if (Character.Controlled != null)
{
if (Character.Controlled.Submarine != null &&
Character.Controlled.Submarine.Info.Type == SubmarineType.Player)
if (Character.Controlled.Submarine is { Info.Type: SubmarineType.Player } playerSub)
{
refEntity = Character.Controlled.Submarine;
GetRefSubForCharacter(Character.Controlled);
}
else
{
@@ -1128,22 +1185,44 @@ namespace Barotrauma
}
}
#else
if (refEntity == null) { return null; }
foreach (Barotrauma.Networking.Client client in GameMain.Server.ConnectedClients)
{
if (client.Character == null) { continue; }
//only take the players inside a player sub into account.
//Otherwise the system could be abused by for example making a respawned player wait
//close to the destination outpost
if (client.Character.Submarine != null &&
client.Character.Submarine.Info.Type == SubmarineType.Player)
GetRefSubForCharacter(client.Character);
}
#endif
void GetRefSubForCharacter(Character character)
{
if (character.Submarine is { Info.Type: SubmarineType.Player } playerSub)
{
if (client.Character.Submarine.WorldPosition.X > refEntity.WorldPosition.X)
if (playerSub.WorldPosition.X > refEntity.WorldPosition.X)
{
refEntity = client.Character.Submarine;
refEntity = playerSub;
}
}
if (acceptRemoteControlledSubs)
{
if (character.ViewTarget?.Submarine is { Info.Type: SubmarineType.Player } viewedSub)
{
if (viewedSub.WorldPosition.X > refEntity.WorldPosition.X)
{
refEntity = viewedSub;
}
}
if (character.SelectedItem?.GetComponent<Steering>()?.ControlledSub is { } controlledSub)
{
if (controlledSub.WorldPosition.X > refEntity.WorldPosition.X)
{
refEntity = controlledSub;
}
}
}
}
#endif
return refEntity;
}