Merge branch 'master' of https://github.com/Regalis11/Barotrauma into develop

This commit is contained in:
EvilFactory
2025-04-10 10:37:09 -03:00
296 changed files with 8420 additions and 2945 deletions
@@ -199,12 +199,12 @@ namespace Barotrauma
{
var itemPrefab = prefabsItemsCanSpawnIn[i];
if (itemPrefab == null) { continue; }
SpawnItems(itemPrefab);
SpawnItems(itemPrefab, skipItemProbability);
}
// Spawn items that nothing can spawn in last
singlePrefabs.Shuffle(Rand.RandSync.ServerAndClient);
singlePrefabs.ForEach(i => SpawnItems(i));
singlePrefabs.ForEach(i => SpawnItems(i, skipItemProbability));
if (OutputDebugInfo)
{
@@ -251,7 +251,7 @@ namespace Barotrauma
return itemsToSpawn;
void SpawnItems(ItemPrefab itemPrefab, float skipItemProbability = 0.0f)
void SpawnItems(ItemPrefab itemPrefab, float skipItemProbability)
{
if (Rand.Range(0.0f, 1.0f, Rand.RandSync.ServerAndClient) < skipItemProbability) { return; }
if (itemPrefab == null)
@@ -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;
@@ -174,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())
@@ -199,7 +216,14 @@ 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)
@@ -289,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());
@@ -296,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()
@@ -313,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();
@@ -324,7 +361,7 @@ namespace Barotrauma
while (spawnWaypoints.Any() && spawnWaypoints.Count < characterInfos.Count)
{
spawnWaypoints.Add(spawnWaypoints[Rand.Int(spawnWaypoints.Count)]);
}
}
}
if (spawnWaypoints == null || !spawnWaypoints.Any())
{
@@ -177,10 +177,28 @@ namespace Barotrauma
if (GameMain.NetworkMember.GameStarted)
{
//allow managing if no-one with permissions is alive and in-game
return GameMain.NetworkMember.ConnectedClients.None(c =>
c.InGame && c.Character is { IsIncapacitated: false, IsDead: false } &&
(IsOwner(c) || c.HasPermission(permissions)));
bool someOneHasPermissions = GameMain.NetworkMember.ConnectedClients.Any(c => IsOwner(c) || c.HasPermission(permissions));
if (someOneHasPermissions)
{
if (GameMain.GameSession != null && GameMain.GameSession.RoundDuration < 60.0f)
{
//round has been going on for less than a minute, don't allow anyone to manage just yet,
//the people with permissions might still be loading or doing something in the lobby
return false;
}
else
{
//allow managing if the round has been going on for a while, and no-one with permissions is alive and in-game
return GameMain.NetworkMember.ConnectedClients.None(c =>
c.InGame && c.Character is { IsIncapacitated: false, IsDead: false } &&
(IsOwner(c) || c.HasPermission(permissions)));
}
}
else
{
//no-one in the server with permissions, allow anyone to manage
return true;
}
}
else
{
@@ -963,7 +981,9 @@ namespace Barotrauma
{
UpdateStoreStock();
}
GameMain.GameSession.EventManager?.RegisterEventHistory(registerFinishedOnly: true);
GameMain.GameSession.EndMissions();
GameMain.GameSession.EventManager?.StoreEventDataAtRoundEnd(registerFinishedOnly: true);
}
/// <summary>
@@ -1089,13 +1109,24 @@ namespace Barotrauma
return false;
}
}
var price = buyingNewCharacter ? NewCharacterCost(characterInfo) : HireManager.GetSalaryFor(characterInfo);
int price = buyingNewCharacter ? NewCharacterCost(characterInfo) : HireManager.GetSalaryFor(characterInfo);
if (takeMoney && !TryPurchase(client, price)) { return false; }
characterInfo.IsNewHire = true;
characterInfo.Title = null;
location.RemoveHireableCharacter(characterInfo);
CrewManager.AddCharacterInfo(characterInfo);
if (GameMain.GameSession?.Campaign is MultiPlayerCampaign)
{
#if SERVER
CrewManager.ToggleReserveBenchStatus(characterInfo, client, pendingHire: true, confirmPendingHire: true, sendUpdate: false);
#endif
}
else
{
CrewManager.AddCharacterInfo(characterInfo);
}
GameAnalyticsManager.AddMoneySpentEvent(characterInfo.Salary, GameAnalyticsManager.MoneySink.Crew, characterInfo.Job?.Prefab.Identifier.Value ?? "unknown");
return true;
}
@@ -92,6 +92,11 @@ namespace Barotrauma
get; set;
}
public byte RoundID
{
get; set;
}
private MultiPlayerCampaign(CampaignSettings settings) : base(GameModePreset.MultiPlayerCampaign, settings)
{
currentCampaignID++;
@@ -38,7 +38,7 @@ namespace Barotrauma
}
}
if (Submarine.MainSubs[1] is not null)
if (Submarine.MainSubs[1] is not null && GameMain.GameSession.GameMode is PvPMode)
{
foreach (var team2Perk in Team2Perks)
{
@@ -703,70 +703,6 @@ namespace Barotrauma
casualties.Clear();
GameAnalyticsManager.AddProgressionEvent(
GameAnalyticsManager.ProgressionStatus.Start,
GameMode?.Preset?.Identifier.Value ?? "none");
string eventId = "StartRound:" + (GameMode?.Preset?.Identifier.Value ?? "none") + ":";
GameAnalyticsManager.AddDesignEvent(eventId + "Submarine:" + (Submarine.MainSub?.Info?.Name ?? "none"));
GameAnalyticsManager.AddDesignEvent(eventId + "GameMode:" + (GameMode?.Preset?.Identifier.Value ?? "none"));
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.GetCharacterInfos()?.Count() ?? 0));
foreach (Mission mission in missions)
{
GameAnalyticsManager.AddDesignEvent(eventId + "MissionType:" + (mission.Prefab.Type.ToString() ?? "none") + ":" + mission.Prefab.Identifier);
}
if (Level.Loaded != null)
{
Identifier levelId = (Level.Loaded.Type == LevelData.LevelType.Outpost ?
Level.Loaded.StartOutpost?.Info?.OutpostGenerationParams?.Identifier :
Level.Loaded.GenerationParams?.Identifier) ?? "null".ToIdentifier();
GameAnalyticsManager.AddDesignEvent(eventId + "LevelType:" + Level.Loaded.Type.ToString() + ":" + levelId);
}
GameAnalyticsManager.AddDesignEvent(eventId + "Biome:" + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none"));
#if CLIENT
if (GameMode is TutorialMode tutorialMode)
{
GameAnalyticsManager.AddDesignEvent(eventId + tutorialMode.Tutorial.Identifier);
if (GameMain.IsFirstLaunch)
{
GameAnalyticsManager.AddDesignEvent("FirstLaunch:" + eventId + tutorialMode.Tutorial.Identifier);
}
}
GameAnalyticsManager.AddDesignEvent($"{eventId}HintManager:{(HintManager.Enabled ? "Enabled" : "Disabled")}");
#endif
var campaignMode = GameMode as CampaignMode;
if (campaignMode != null)
{
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RadiationEnabled:" + campaignMode.Settings.RadiationEnabled);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:WorldHostility:" + campaignMode.Settings.WorldHostility);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShowHuskWarning:" + campaignMode.Settings.ShowHuskWarning);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:StartItemSet:" + campaignMode.Settings.StartItemSet);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:MaxMissionCount:" + campaignMode.Settings.MaxMissionCount);
//log the multipliers as integers to reduce the number of distinct values
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RepairFailMultiplier:" + (int)(campaignMode.Settings.RepairFailMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:FuelMultiplier:" + (int)(campaignMode.Settings.FuelMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:MissionRewardMultiplier:" + (int)(campaignMode.Settings.MissionRewardMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:CrewVitalityMultiplier:" + (int)(campaignMode.Settings.CrewVitalityMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:NonCrewVitalityMultiplier:" + (int)(campaignMode.Settings.NonCrewVitalityMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:OxygenMultiplier:" + (int)(campaignMode.Settings.OxygenMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RepairFailMultiplier:" + (int)(campaignMode.Settings.RepairFailMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShipyardPriceMultiplier:" + (int)(campaignMode.Settings.ShipyardPriceMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShopPriceMultiplier:" + (int)(campaignMode.Settings.ShopPriceMultiplier * 100));
bool firstTimeInBiome = Map != null && !Map.Connections.Any(c => c.Passed && c.Biome == LevelData!.Biome);
if (firstTimeInBiome)
{
GameAnalyticsManager.AddDesignEvent(eventId + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none") + "Discovered:Playtime", campaignMode.TotalPlayTime);
GameAnalyticsManager.AddDesignEvent(eventId + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none") + "Discovered:PassedLevels", campaignMode.TotalPassedLevels);
}
if (GameMain.NetworkMember?.ServerSettings is { } serverSettings)
{
GameAnalyticsManager.AddDesignEvent("ServerSettings:RespawnMode:" + serverSettings.RespawnMode);
GameAnalyticsManager.AddDesignEvent("ServerSettings:IronmanMode:" + serverSettings.IronmanModeActive);
GameAnalyticsManager.AddDesignEvent("ServerSettings:AllowBotTakeoverOnPermadeath:" + serverSettings.AllowBotTakeoverOnPermadeath);
}
}
#if DEBUG
double startDuration = (DateTime.Now - startTime).TotalSeconds;
if (startDuration < MinimumLoadingTime)
@@ -818,7 +754,11 @@ namespace Barotrauma
GameMain.LuaCs.Hook.Call("roundStart");
EnableEventLogNotificationIcon(enabled: false);
LogStartRoundStats();
#endif
var campaignMode = GameMode as CampaignMode;
if (campaignMode is { ItemsRelocatedToMainSub: true })
{
#if SERVER
@@ -1102,7 +1042,11 @@ namespace Barotrauma
#if SERVER
players = GameMain.Server.ConnectedClients.Select(c => c.Character).Where(c => c?.Info != null && !c.IsDead);
bots = crewManager.GetCharacters().Where(c => !c.IsRemotePlayer);
bots = crewManager.GetCharacterInfos()
//filter out players in case a player has been given control of a bot using console commands
.Where(characterInfo => GameMain.Server.ConnectedClients.None(c => c.CharacterInfo == characterInfo))
.Select(characterInfo => characterInfo.Character)
.NotNull();
#elif CLIENT
players = crewManager.GetCharacters().Where(static c => c.IsPlayer);
bots = crewManager.GetCharacters().Where(static c => c.IsBot);
@@ -1124,7 +1068,7 @@ namespace Barotrauma
private double LastEndRoundErrorMessageTime;
#endif
public void EndRound(string endMessage, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None, TraitorManager.TraitorResults? traitorResults = null)
public void EndRound(string endMessage, CampaignMode.TransitionType transitionType = CampaignMode.TransitionType.None, TraitorManager.TraitorResults? traitorResults = null, bool createRoundSummary = true)
{
RoundEnding = true;
@@ -1141,35 +1085,14 @@ namespace Barotrauma
ImmutableHashSet<Character> crewCharacters = GetSessionCrewCharacters(CharacterType.Both);
int prevMoney = GetAmountOfMoney(crewCharacters);
foreach (Mission mission in missions)
{
mission.End();
}
EndMissions();
foreach (Character character in crewCharacters)
{
character.CheckTalents(AbilityEffectType.OnRoundEnd);
}
if (missions.Any())
{
if (missions.Any(m => m.Completed))
{
foreach (Character character in crewCharacters)
{
character.CheckTalents(AbilityEffectType.OnAnyMissionCompleted);
}
}
if (missions.All(m => m.Completed))
{
foreach (Character character in crewCharacters)
{
character.CheckTalents(AbilityEffectType.OnAllMissionsCompleted);
}
}
}
GameMain.LuaCs.Hook.Call("missionsEnded", missions);
#if CLIENT
@@ -1186,7 +1109,10 @@ namespace Barotrauma
GUI.PreventPauseMenuToggle = true;
if (GameMode is not TestGameMode && Screen.Selected == GameMain.GameScreen && RoundSummary != null && transitionType != CampaignMode.TransitionType.End)
if (createRoundSummary &&
GameMode is not TestGameMode &&
Screen.Selected == GameMain.GameScreen && RoundSummary != null &&
transitionType != CampaignMode.TransitionType.End)
{
GUI.ClearMessages();
GUIMessageBox.MessageBoxes.RemoveAll(mb => mb.UserData is RoundSummary);
@@ -1265,6 +1191,34 @@ namespace Barotrauma
}
}
public void EndMissions()
{
ImmutableHashSet<Character> crewCharacters = GetSessionCrewCharacters(CharacterType.Both);
foreach (Mission mission in missions)
{
mission.End();
}
if (missions.Any())
{
if (missions.Any(m => m.Completed))
{
foreach (Character character in crewCharacters)
{
character.CheckTalents(AbilityEffectType.OnAnyMissionCompleted);
}
}
if (missions.All(m => m.Completed))
{
foreach (Character character in crewCharacters)
{
character.CheckTalents(AbilityEffectType.OnAllMissionsCompleted);
}
}
}
}
public static PerkCollection GetPerks()
{
if (GameMain.NetworkMember?.ServerSettings is not { } serverSettings)
@@ -1347,8 +1301,89 @@ namespace Barotrauma
return true;
}
private void LogStartRoundStats()
{
#if !UNSTABLE
if (!GameAnalyticsManager.ShouldLogRandomSample())
{
return;
}
#endif
GameAnalyticsManager.AddProgressionEvent(
GameAnalyticsManager.ProgressionStatus.Start,
GameMode?.Preset?.Identifier.Value ?? "none");
string eventId = "StartRound:" + (GameMode?.Preset?.Identifier.Value ?? "none") + ":";
GameAnalyticsManager.AddDesignEvent(eventId + "Submarine:" + (Submarine.MainSub?.Info?.Name ?? "none"));
GameAnalyticsManager.AddDesignEvent(eventId + "GameMode:" + (GameMode?.Preset?.Identifier.Value ?? "none"));
GameAnalyticsManager.AddDesignEvent(eventId + "CrewSize:" + (CrewManager?.GetCharacterInfos()?.Count() ?? 0));
foreach (Mission mission in missions)
{
GameAnalyticsManager.AddDesignEvent(eventId + "MissionType:" + (mission.Prefab.Type.ToString() ?? "none") + ":" + mission.Prefab.Identifier);
}
if (Level.Loaded != null)
{
Identifier levelId = (Level.Loaded.Type == LevelData.LevelType.Outpost ?
Level.Loaded.StartOutpost?.Info?.OutpostGenerationParams?.Identifier :
Level.Loaded.GenerationParams?.Identifier) ?? "null".ToIdentifier();
GameAnalyticsManager.AddDesignEvent(eventId + "LevelType:" + Level.Loaded.Type.ToString() + ":" + levelId);
}
GameAnalyticsManager.AddDesignEvent(eventId + "Biome:" + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none"));
#if CLIENT
if (GameMode is TutorialMode tutorialMode)
{
GameAnalyticsManager.AddDesignEvent(eventId + tutorialMode.Tutorial.Identifier);
if (GameMain.IsFirstLaunch)
{
GameAnalyticsManager.AddDesignEvent("FirstLaunch:" + eventId + tutorialMode.Tutorial.Identifier);
}
}
GameAnalyticsManager.AddDesignEvent($"{eventId}HintManager:{(HintManager.Enabled ? "Enabled" : "Disabled")}");
#endif
var campaignMode = GameMode as CampaignMode;
if (campaignMode != null)
{
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RadiationEnabled:" + campaignMode.Settings.RadiationEnabled);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:WorldHostility:" + campaignMode.Settings.WorldHostility);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShowHuskWarning:" + campaignMode.Settings.ShowHuskWarning);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:StartItemSet:" + campaignMode.Settings.StartItemSet);
GameAnalyticsManager.AddDesignEvent("CampaignSettings:MaxMissionCount:" + campaignMode.Settings.MaxMissionCount);
//log the multipliers as integers to reduce the number of distinct values
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RepairFailMultiplier:" + (int)(campaignMode.Settings.RepairFailMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:FuelMultiplier:" + (int)(campaignMode.Settings.FuelMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:MissionRewardMultiplier:" + (int)(campaignMode.Settings.MissionRewardMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:CrewVitalityMultiplier:" + (int)(campaignMode.Settings.CrewVitalityMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:NonCrewVitalityMultiplier:" + (int)(campaignMode.Settings.NonCrewVitalityMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:OxygenMultiplier:" + (int)(campaignMode.Settings.OxygenMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:RepairFailMultiplier:" + (int)(campaignMode.Settings.RepairFailMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShipyardPriceMultiplier:" + (int)(campaignMode.Settings.ShipyardPriceMultiplier * 100));
GameAnalyticsManager.AddDesignEvent("CampaignSettings:ShopPriceMultiplier:" + (int)(campaignMode.Settings.ShopPriceMultiplier * 100));
bool firstTimeInBiome = Map != null && !Map.Connections.Any(c => c.Passed && c.Biome == LevelData!.Biome);
if (firstTimeInBiome)
{
GameAnalyticsManager.AddDesignEvent(eventId + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none") + "Discovered:Playtime", campaignMode.TotalPlayTime);
GameAnalyticsManager.AddDesignEvent(eventId + (Level.Loaded?.LevelData?.Biome?.Identifier.Value ?? "none") + "Discovered:PassedLevels", campaignMode.TotalPassedLevels);
}
if (GameMain.NetworkMember?.ServerSettings is { } serverSettings)
{
GameAnalyticsManager.AddDesignEvent("ServerSettings:RespawnMode:" + serverSettings.RespawnMode);
GameAnalyticsManager.AddDesignEvent("ServerSettings:IronmanMode:" + serverSettings.IronmanModeActive);
GameAnalyticsManager.AddDesignEvent("ServerSettings:AllowBotTakeoverOnPermadeath:" + serverSettings.AllowBotTakeoverOnPermadeath);
}
}
}
public void LogEndRoundStats(string eventId, TraitorManager.TraitorResults? traitorResults = null)
{
#if !UNSTABLE
//only collect the stats from a random sample of round ends
if (!GameAnalyticsManager.ShouldLogRandomSample())
{
return;
}
#endif
if (Submarine.MainSub?.Info?.IsVanillaSubmarine() ?? false)
{
//don't log modded subs, that's a ton of extra data to collect
@@ -1405,7 +1440,8 @@ namespace Barotrauma
GameAnalyticsManager.AddDesignEvent($"TraitorEvent:{traitorResults.Value.TraitorEventIdentifier}:{(traitorResults.Value.VotedCorrectTraitor ? "TraitorIdentifier" : "TraitorUnidentified")}");
}
foreach (Character c in GetSessionCrewCharacters(CharacterType.Both))
//disabled to reduce the amount of data we collect through GA
/*foreach (Character c in GetSessionCrewCharacters(CharacterType.Both))
{
foreach (var itemSelectedDuration in c.ItemSelectedDurations)
{
@@ -1420,7 +1456,7 @@ namespace Barotrauma
}
GameAnalyticsManager.AddDesignEvent("TimeSpentOnDevices:" + (GameMode?.Preset?.Identifier.Value ?? "none") + ":" + characterType + ":" + (c.Info?.Job?.Prefab.Identifier.Value ?? "NoJob") + ":" + itemSelectedDuration.Key.Identifier, itemSelectedDuration.Value);
}
}
}*/
#if CLIENT
if (GameMode is TutorialMode tutorialMode)
{
@@ -1430,15 +1466,17 @@ namespace Barotrauma
GameAnalyticsManager.AddDesignEvent("FirstLaunch:" + eventId + tutorialMode.Tutorial.Identifier);
}
}
GameAnalyticsManager.AddDesignEvent(eventId + "TimeSpentCleaning", TimeSpentCleaning);
GameAnalyticsManager.AddDesignEvent(eventId + "TimeSpentPainting", TimeSpentPainting);
//disabled to reduce the amount of data we collect through GA
//GameAnalyticsManager.AddDesignEvent(eventId + "TimeSpentCleaning", TimeSpentCleaning);
//GameAnalyticsManager.AddDesignEvent(eventId + "TimeSpentPainting", TimeSpentPainting);
TimeSpentCleaning = TimeSpentPainting = 0.0;
#endif
}
public void KillCharacter(Character character)
{
if (CrewManager != null && CrewManager.GetCharacters().Contains(character))
if (CrewManager != null &&
CrewManager.GetCharacterInfos().Contains(character.Info))
{
casualties.Add(character);
}
@@ -1542,6 +1580,8 @@ namespace Barotrauma
rootElement.Add(new XAttribute("nextleveltype", campaign.NextLevel?.Type ?? LevelData?.Type ?? LevelData.LevelType.Outpost));
rootElement.Add(new XAttribute("ismultiplayer", campaign is MultiPlayerCampaign));
LastSaveVersion = GameMain.Version;
rootElement.Add(new XAttribute("version", GameMain.Version));
if (Submarine?.Info != null && !Submarine.Removed && Campaign != null)
@@ -58,7 +58,8 @@ namespace Barotrauma
void AddCharacter(JobPrefab job)
{
if (job == null) { return; }
int variant = Rand.Range(0, job.Variants, Rand.RandSync.ServerAndClient);
//no need for synced rand, these only generate ones and are then included in the campaign save
int variant = Rand.Range(0, job.Variants, Rand.RandSync.Unsynced);
AvailableCharacters.Add(new CharacterInfo(CharacterPrefab.HumanSpeciesName, jobOrJobPrefab: job, variant: variant));
}
}
@@ -73,7 +74,8 @@ namespace Barotrauma
DebugConsole.ThrowError($"Couldn't create a hireable for the location: character prefab \"{character.NPCIdentifier}\" not found in the NPC set \"{character.NPCSetIdentifier}\".");
continue;
}
var characterInfo = humanPrefab.CreateCharacterInfo(Rand.RandSync.ServerAndClient);
//no need for synced rand, these only generate ones and are then included in the campaign save
var characterInfo = humanPrefab.CreateCharacterInfo(Rand.RandSync.Unsynced);
characterInfo.MinReputationToHire = (faction.Identifier, character.MinReputation);
AvailableCharacters.Add(characterInfo);
}