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
@@ -5,9 +5,9 @@ using Barotrauma.Tutorials;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Xml.Linq;
using Barotrauma.Networking;
namespace Barotrauma
{
@@ -27,19 +27,29 @@ namespace Barotrauma
private readonly List<CharacterInfo> characterInfos = new List<CharacterInfo>();
private readonly List<Character> characters = new List<Character>();
private readonly List<CharacterInfo> reserveBench = new List<CharacterInfo>();
public IEnumerable<Character> GetCharacters()
{
return characters;
}
/// <summary>
/// Note: this only returns AI characters' infos in multiplayer. The infos are used to manage hiring/firing/renaming, which only applies to AI characters.
/// NOTE: When called from client code, this method will include players, but NOT when called from server code.
/// CrewManager is used for dealing with things relevant to AI characters, like hiring, firing, renaming, and the reserve bench.
/// In single player/client code, player CharacterInfos are still stored in it but only for displaying crew listings in the GUI correctly.
/// Use <see cref="GetSessionCrewCharacters"/> to get all the characters regardless if they're player or AI controlled.
/// </summary>
public IEnumerable<CharacterInfo> GetCharacterInfos()
/// <param name="includeReserveBench">Should characters on the reserve be included? Defaults to false.</param>
public IEnumerable<CharacterInfo> GetCharacterInfos(bool includeReserveBench = false)
{
if (includeReserveBench)
{
return characterInfos.Concat(reserveBench);
}
return characterInfos;
}
public IEnumerable<CharacterInfo> GetReserveBenchInfos()
{
return reserveBench;
}
private Character welcomeMessageNPC;
@@ -81,6 +91,7 @@ namespace Barotrauma
// Ignore orders work a bit differently since the "unignore" order counters the "ignore" order
var isUnignoreOrder = order.Identifier == Tags.UnignoreThis;
var isIgnoreOrder = order.Identifier == Tags.IgnoreThis;
var orderPrefab = !isUnignoreOrder ? order.Prefab : OrderPrefab.Prefabs[Tags.IgnoreThis];
ActiveOrder existingOrder = ActiveOrders.Find(o =>
o.Order.Prefab == orderPrefab && MatchesTarget(o.Order.TargetEntity, order.TargetEntity) &&
@@ -96,6 +107,14 @@ namespace Barotrauma
else
{
ActiveOrders.Remove(existingOrder);
if (isIgnoreOrder && order.TargetEntity is Item targetItem)
{
foreach (var stackedItem in targetItem.GetStackedItems())
{
ActiveOrders.RemoveAll(o => o.Order.Prefab == orderPrefab && o.Order.TargetEntity == stackedItem);
stackedItem.OrderedToBeIgnored = false;
}
}
return true;
}
}
@@ -124,7 +143,18 @@ namespace Barotrauma
}
}
}
ActiveOrders.Add(new ActiveOrder(order, fadeOutTime));
if (isIgnoreOrder && order.TargetEntity is Item targetItem)
{
foreach (var stackedItem in targetItem.GetStackedItems())
{
ActiveOrders.Add(new ActiveOrder(order.WithTargetEntity(stackedItem), fadeOutTime));
stackedItem.OrderedToBeIgnored = true;
}
}
else
{
ActiveOrders.Add(new ActiveOrder(order, fadeOutTime));
}
#if CLIENT
HintManager.OnActiveOrderAdded(order);
#endif
@@ -154,7 +184,14 @@ namespace Barotrauma
if (characterElement.GetAttributeBool("lastcontrolled", false)) { characterInfo.LastControlled = true; }
characterInfo.CrewListIndex = characterElement.GetAttributeInt("crewlistindex", -1);
#endif
characterInfos.Add(characterInfo);
if (characterElement.GetAttributeBool(nameof(CharacterInfo.IsOnReserveBench), false))
{
reserveBench.Add(characterInfo);
}
else
{
characterInfos.Add(characterInfo);
}
foreach (var subElement in characterElement.Elements())
{
switch (subElement.Name.ToString().ToLowerInvariant())
@@ -179,10 +216,17 @@ namespace Barotrauma
/// <param name="characterInfo"></param>
public void RemoveCharacterInfo(CharacterInfo characterInfo)
{
if (characterInfo is { IsOnReserveBench: true })
{
reserveBench.Remove(characterInfo);
}
characterInfos.Remove(characterInfo);
#if CLIENT
GameMain.GameSession?.DeathPrompt?.UpdateBotList();
#endif
}
public void AddCharacter(Character character, bool sortCrewList = true)
public void AddCharacter(Character character)
{
if (character.Removed)
{
@@ -216,10 +260,6 @@ namespace Barotrauma
}
#if CLIENT
var characterComponent = AddCharacterToCrewList(character);
if (sortCrewList)
{
SortCrewList();
}
if (character.CurrentOrders != null)
{
foreach (var order in character.CurrentOrders)
@@ -273,6 +313,15 @@ namespace Barotrauma
public void AddCharacterInfo(CharacterInfo characterInfo)
{
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign)
{
Debug.Assert(characterInfo.BotStatus == BotStatus.ActiveService);
if (characterInfo.BotStatus != BotStatus.ActiveService)
{
DebugConsole.ThrowError($"CrewManager.AddCharacterInfo called on a bot ({characterInfo.DisplayName}) with the wrong status ({characterInfo.BotStatus})");
}
}
if (characterInfos.Contains(characterInfo))
{
DebugConsole.ThrowError("Tried to add the same character info to CrewManager twice.\n" + Environment.StackTrace.CleanupStackTrace());
@@ -280,11 +329,15 @@ namespace Barotrauma
}
characterInfos.Add(characterInfo);
#if CLIENT
GameMain.GameSession?.DeathPrompt?.UpdateBotList();
#endif
}
public void ClearCharacterInfos()
{
characterInfos.Clear();
reserveBench.Clear();
}
public void InitRound()
@@ -297,7 +350,7 @@ namespace Barotrauma
List<WayPoint> spawnWaypoints = null;
List<WayPoint> mainSubWaypoints = WayPoint.SelectCrewSpawnPoints(characterInfos, Submarine.MainSub).ToList();
if (Level.Loaded != null && Level.Loaded.ShouldSpawnCrewInsideOutpost())
{
spawnWaypoints = GetOutpostSpawnpoints();
@@ -308,7 +361,7 @@ namespace Barotrauma
while (spawnWaypoints.Any() && spawnWaypoints.Count < characterInfos.Count)
{
spawnWaypoints.Add(spawnWaypoints[Rand.Int(spawnWaypoints.Count)]);
}
}
}
if (spawnWaypoints == null || !spawnWaypoints.Any())
{
@@ -324,7 +377,7 @@ namespace Barotrauma
Character character = Character.Create(info, spawnWaypoints[i].WorldPosition, info.Name);
InitializeCharacter(character, mainSubWaypoints[i], spawnWaypoints[i]);
AddCharacter(character, sortCrewList: false);
AddCharacter(character);
#if CLIENT
if (IsSinglePlayer && (Character.Controlled == null || character.Info.LastControlled)) { Character.Controlled = character; }
#endif
@@ -364,7 +417,7 @@ namespace Barotrauma
}
else if (!character.Info.StartItemsGiven)
{
character.GiveJobItems(mainSubWaypoint);
character.GiveJobItems(isPvPMode: GameMain.GameSession?.GameMode is PvPMode, mainSubWaypoint);
foreach (Item item in character.Inventory.AllItems)
{
//if the character is loaded from a human prefab with preconfigured items, its ID card gets assigned to the sub it spawns in
@@ -558,7 +611,7 @@ namespace Barotrauma
public static IEnumerable<Character> GetCharactersSortedForOrder(Order order, IEnumerable<Character> characters, Character controlledCharacter, bool includeSelf, IEnumerable<Character> extraCharacters = null)
{
var filteredCharacters = characters.Where(c => controlledCharacter == null || ((includeSelf || c != controlledCharacter) && c.TeamID == controlledCharacter.TeamID));
var filteredCharacters = characters.Where(c => c.Info != null && (controlledCharacter == null || ((includeSelf || c != controlledCharacter) && c.TeamID == controlledCharacter.TeamID)));
if (extraCharacters != null)
{
filteredCharacters = filteredCharacters.Union(extraCharacters);