(f0d812055) v0.9.9.0

This commit is contained in:
Joonas Rikkonen
2020-04-23 19:19:37 +03:00
parent b647059b93
commit ac37a3b0e4
391 changed files with 15054 additions and 5420 deletions
@@ -23,11 +23,18 @@ namespace Barotrauma
{
if (Submarine.MainSubs[i] == null) { continue; }
List<Submarine> subs = new List<Submarine>() { Submarine.MainSubs[i] };
subs.AddRange(Submarine.MainSubs[i].DockedTo.Where(d => !d.IsOutpost));
subs.AddRange(Submarine.MainSubs[i].DockedTo.Where(d => !d.Info.IsOutpost));
Place(subs);
}
if (campaign != null) { campaign.InitialSuppliesSpawned = true; }
}
}
foreach (var wreck in Submarine.Loaded)
{
if (wreck.Info.IsWreck)
{
Place(wreck.ToEnumerable());
}
}
}
private static void Place(IEnumerable<Submarine> subs)
@@ -38,10 +45,10 @@ namespace Barotrauma
return;
}
int sizeApprox = MapEntityPrefab.List.Count() / 3;
var containers = new List<ItemContainer>(100);
var prefabsWithContainer = new List<ItemPrefab>(sizeApprox / 3);
var prefabsWithoutContainer = new List<ItemPrefab>(sizeApprox);
int itemCountApprox = MapEntityPrefab.List.Count() / 3;
var containers = new List<ItemContainer>(70 + 30 * subs.Count());
var prefabsWithContainer = new List<ItemPrefab>(itemCountApprox / 3);
var prefabsWithoutContainer = new List<ItemPrefab>(itemCountApprox);
var removals = new List<ItemPrefab>();
foreach (Item item in Item.ItemList)
@@ -49,6 +56,7 @@ namespace Barotrauma
if (!subs.Contains(item.Submarine)) { continue; }
containers.AddRange(item.GetComponents<ItemContainer>());
}
containers.Shuffle();
foreach (MapEntityPrefab prefab in MapEntityPrefab.List)
{
@@ -66,7 +74,7 @@ namespace Barotrauma
spawnedItems.Clear();
var validContainers = new Dictionary<ItemContainer, PreferredContainer>();
prefabsWithContainer.RandomizeList();
prefabsWithContainer.Shuffle();
// Spawn items that have an ItemContainer component first so we can fill them up with items if needed (oxygen tanks inside the spawned diving masks, etc)
for (int i = 0; i < prefabsWithContainer.Count; i++)
{
@@ -82,12 +90,13 @@ namespace Barotrauma
// Another pass for items with containers because also they can spawn inside other items (like smg magazine)
prefabsWithContainer.ForEach(i => SpawnItems(i));
// Spawn items that don't have containers last
prefabsWithoutContainer.RandomizeList();
prefabsWithoutContainer.Shuffle();
prefabsWithoutContainer.ForEach(i => SpawnItems(i));
if (OutputDebugInfo)
{
DebugConsole.NewMessage("Automatically placed items: ");
var subNames = subs.Select(s => s.Info.Name).ToList();
DebugConsole.NewMessage($"Automatically placed items in { string.Join(", ", subNames) }:");
foreach (string itemName in spawnedItems.Select(it => it.Name).Distinct())
{
DebugConsole.NewMessage(" - " + itemName + " x" + spawnedItems.Count(it => it.Name == itemName));
@@ -149,7 +158,12 @@ namespace Barotrauma
private static bool SpawnItem(ItemPrefab itemPrefab, List<ItemContainer> containers, KeyValuePair<ItemContainer, PreferredContainer> validContainer)
{
bool success = false;
if (Rand.Value() > validContainer.Value.SpawnProbability) { return success; }
if (Rand.Value() > validContainer.Value.SpawnProbability) { return false; }
// Don't add dangerously reactive materials in thalamus wrecks
if (validContainer.Key.Item.Submarine.WreckAI != null && itemPrefab.Tags.Contains("explodesinwater"))
{
return false;
}
int amount = Rand.Range(validContainer.Value.MinAmount, validContainer.Value.MaxAmount + 1);
for (int i = 0; i < amount; i++)
{
@@ -1,4 +1,5 @@
using Barotrauma.Items.Components;
using FarseerPhysics;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
@@ -20,8 +21,9 @@ namespace Barotrauma
class CargoManager
{
private readonly List<PurchasedItem> purchasedItems;
public const int MaxQuantity = 100;
private readonly List<PurchasedItem> purchasedItems;
private readonly CampaignMode campaign;
public Action OnItemsChanged;
@@ -115,9 +117,25 @@ namespace Barotrauma
ItemPrefab containerPrefab = null;
foreach (PurchasedItem pi in itemsToSpawn)
{
float floorPos = cargoRoom.Rect.Y - cargoRoom.Rect.Height;
Vector2 position = new Vector2(
Rand.Range(cargoRoom.Rect.X + 20, cargoRoom.Rect.Right - 20),
cargoRoom.Rect.Y - cargoRoom.Rect.Height + pi.ItemPrefab.Size.Y / 2);
floorPos);
//check where the actual floor structure is in case the bottom of the hull extends below it
if (Submarine.PickBody(
ConvertUnits.ToSimUnits(new Vector2(position.X, cargoRoom.Rect.Y - cargoRoom.Rect.Height / 2)),
ConvertUnits.ToSimUnits(position),
collisionCategory: Physics.CollisionWall) != null)
{
float floorStructurePos = ConvertUnits.ToDisplayUnits(Submarine.LastPickedPosition.Y);
if (floorStructurePos > floorPos)
{
floorPos = floorStructurePos;
}
}
position.Y = floorPos + pi.ItemPrefab.Size.Y / 2;
ItemContainer itemContainer = null;
if (!string.IsNullOrEmpty(pi.ItemPrefab.CargoContainerIdentifier))
@@ -8,6 +8,7 @@ namespace Barotrauma
{
const float ConversationIntervalMin = 100.0f;
const float ConversationIntervalMax = 180.0f;
const float ConversationIntervalMultiplierMultiplayer = 5.0f;
private float conversationTimer, conversationLineTimer;
private List<Pair<Character, string>> pendingConversationLines = new List<Pair<Character, string>>();
@@ -74,11 +75,17 @@ namespace Barotrauma
private void UpdateConversations(float deltaTime)
{
if (GameMain.NetworkMember != null && GameMain.NetworkMember.ServerSettings.DisableBotConversations) { return; }
conversationTimer -= deltaTime;
if (conversationTimer <= 0.0f)
{
CreateRandomConversation();
conversationTimer = Rand.Range(ConversationIntervalMin, ConversationIntervalMax);
if (GameMain.NetworkMember != null)
{
conversationTimer *= ConversationIntervalMultiplierMultiplayer;
}
}
if (pendingConversationLines.Count > 0)
@@ -64,7 +64,7 @@ namespace Barotrauma
return Submarine.Loaded.FindAll(s =>
s != leavingSub &&
!leavingSub.DockedTo.Contains(s) &&
s != Level.Loaded.StartOutpost && s != Level.Loaded.EndOutpost &&
s.Info.Type == SubmarineInfo.SubmarineType.Player &&
(s.AtEndPosition != leavingSub.AtEndPosition || s.AtStartPosition != leavingSub.AtStartPosition));
}
@@ -80,7 +80,7 @@ namespace Barotrauma
{
foreach (Structure wall in Structure.WallList)
{
if (wall.Submarine == null || wall.Submarine.IsOutpost) { continue; }
if (wall.Submarine == null || wall.Submarine.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; }
if (wall.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(wall.Submarine))
{
for (int i = 0; i < wall.SectionCount; i++)
@@ -95,7 +95,7 @@ namespace Barotrauma
{
foreach (Item item in Item.ItemList)
{
if (item.Submarine == null || item.Submarine.IsOutpost) { continue; }
if (item.Submarine == null || item.Submarine.Info.Type != SubmarineInfo.SubmarineType.Player) { continue; }
if (item.Submarine == Submarine.MainSub || Submarine.MainSub.DockedTo.Contains(item.Submarine))
{
if (item.GetComponent<Items.Components.Repairable>() != null)
@@ -44,6 +44,7 @@ namespace Barotrauma
{
#if CLIENT
new GameModePreset("singleplayercampaign", typeof(SinglePlayerCampaign), true);
new GameModePreset("subtest", typeof(SubTestMode), true);
new GameModePreset("tutorial", typeof(TutorialMode), true);
new GameModePreset("devsandbox", typeof(GameMode), true);
#endif
@@ -69,9 +69,18 @@ namespace Barotrauma
#if CLIENT
if (GameMain.Client != null)
{
bool success =
GameMain.Client.ConnectedClients.Any(c => c.Character != null && !c.Character.IsDead);
GameMain.GameSession.EndRound("");
GameMain.GameSession.CrewManager.EndRound();
return;
if (success)
{
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
}
return;
}
#endif
@@ -104,17 +113,12 @@ namespace Barotrauma
{
if (c.Character?.Info != null && !c.Character.IsDead)
{
c.Character.ResetCurrentOrder();
c.CharacterInfo = c.Character.Info;
characterData.Add(new CharacterCampaignData(c));
}
}
//remove all items that are in someone's inventory
foreach (Character c in Character.CharacterList)
{
c.Inventory?.DeleteAllItems();
}
if (success)
{
bool atEndPosition = Submarine.MainSub.AtEndPosition;
@@ -142,6 +146,8 @@ namespace Barotrauma
}
map.ProgressWorld();
GameMain.GameSession.SubmarineInfo = new SubmarineInfo(GameMain.GameSession.Submarine);
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
}
#endif
@@ -9,7 +9,7 @@ namespace Barotrauma
{
partial class GameSession
{
public enum InfoFrameTab { Crew, Mission, MyCharacter, ManagePlayers };
public enum InfoFrameTab { Crew, Mission, MyCharacter, Traitor };
public readonly EventManager EventManager;
@@ -65,44 +65,51 @@ namespace Barotrauma
}
}
public SubmarineInfo SubmarineInfo { get; set; }
public Submarine Submarine { get; set; }
public string SavePath { get; set; }
partial void InitProjSpecific();
public GameSession(Submarine submarine, string savePath, GameModePreset gameModePreset, MissionType missionType = MissionType.None)
: this(submarine, savePath)
public GameSession(SubmarineInfo submarineInfo, string savePath, GameModePreset gameModePreset, MissionType missionType = MissionType.None)
: this(submarineInfo, savePath)
{
CrewManager = new CrewManager(gameModePreset != null && gameModePreset.IsSinglePlayer);
GameMode = gameModePreset.Instantiate(missionType);
}
public GameSession(Submarine submarine, string savePath, GameModePreset gameModePreset, MissionPrefab missionPrefab)
: this(submarine, savePath)
public GameSession(SubmarineInfo submarineInfo, string savePath, GameModePreset gameModePreset, MissionPrefab missionPrefab)
: this(submarineInfo, savePath)
{
CrewManager = new CrewManager(gameModePreset != null && gameModePreset.IsSinglePlayer);
GameMode = gameModePreset.Instantiate(missionPrefab);
#if CLIENT
if (GameMode is SubTestMode) { EventManager = null; }
#endif
}
private GameSession(Submarine submarine, string savePath)
private GameSession(SubmarineInfo submarineInfo, string savePath)
{
InitProjSpecific();
Submarine.MainSub = submarine;
this.Submarine = submarine;
SubmarineInfo = submarineInfo;
/*Submarine = new Submarine(submarineInfo);
Submarine.MainSub = Submarine;*/
GameMain.GameSession = this;
EventManager = new EventManager();
this.SavePath = savePath;
}
public GameSession(Submarine selectedSub, string saveFile, XDocument doc)
: this(selectedSub, saveFile)
public GameSession(SubmarineInfo selectedSubInfo, string saveFile, XDocument doc)
: this(selectedSubInfo, saveFile)
{
Submarine.MainSub = Submarine;
GameMain.GameSession = this;
selectedSub.Name = doc.Root.GetAttributeString("submarine", selectedSub.Name);
//selectedSub.Name = doc.Root.GetAttributeString("submarine", selectedSub.Name);
foreach (XElement subElement in doc.Root.Elements())
{
@@ -154,10 +161,10 @@ namespace Barotrauma
{
Level randomLevel = Level.CreateRandom(levelSeed, difficulty);
StartRound(randomLevel, true);
StartRound(randomLevel);
}
public void StartRound(Level level, bool reloadSub = true, bool mirrorLevel = false)
public void StartRound(Level level, bool mirrorLevel = false)
{
//make sure no status effects have been carried on from the next round
//(they should be stopped in EndRound, this is a safeguard against cases where the round is ended ungracefully)
@@ -169,33 +176,26 @@ namespace Barotrauma
#endif
this.Level = level;
if (Submarine == null)
if (SubmarineInfo == null)
{
DebugConsole.ThrowError("Couldn't start game session, submarine not selected.");
return;
}
if (reloadSub || Submarine.MainSub != Submarine) { Submarine.Load(true); }
Submarine.MainSub = Submarine;
if (GameMode.Mission != null && GameMode.Mission.TeamCount > 1)
{
if (Submarine.MainSubs[1] == null)
{
Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
Submarine.MainSubs[1].Load(false);
}
else if (reloadSub)
{
Submarine.MainSubs[1].Load(false);
}
}
if (Submarine.IsFileCorrupted)
if (SubmarineInfo.IsFileCorrupted)
{
DebugConsole.ThrowError("Couldn't start game session, submarine file corrupted.");
return;
}
Submarine.Unload();
Submarine = Submarine.MainSub = new Submarine(SubmarineInfo);
Submarine.MainSub = Submarine;
if (GameMode.Mission != null && GameMode.Mission.TeamCount > 1 && Submarine.MainSubs[1] == null)
{
Submarine.MainSubs[1] = new Submarine(SubmarineInfo, true);
}
if (level != null)
{
level.Generate(mirrorLevel);
@@ -231,7 +231,7 @@ namespace Barotrauma
if (port.Item.WorldPosition.Y < Submarine.WorldPosition.Y) { continue; }
float dist = Vector2.DistanceSquared(port.Item.WorldPosition, level.StartOutpost.WorldPosition);
if (myPort == null || dist < closestDistance)
if (myPort == null || dist < closestDistance || (port.MainDockingPort && !myPort.MainDockingPort))
{
myPort = port;
closestDistance = dist;
@@ -254,14 +254,14 @@ namespace Barotrauma
foreach (var sub in Submarine.Loaded)
{
if (sub.IsOutpost)
if (sub.Info.IsOutpost)
{
sub.DisableObstructedWayPoints();
}
}
Entity.Spawner = new EntitySpawner();
if (GameMode.Mission != null) { Mission = GameMode.Mission; }
if (GameMode != null) { GameMode.Start(); }
if (GameMode.Mission != null)
@@ -277,7 +277,7 @@ namespace Barotrauma
}
}
EventManager.StartRound(level);
EventManager?.StartRound(level);
SteamAchievementManager.OnStartRound();
if (GameMode != null)
@@ -286,8 +286,9 @@ namespace Barotrauma
if (GameMain.NetworkMember == null)
{
//only autoplace items here in single player
//only place items and corpses here in single player
//the server does this after loading the respawn shuttle
Level?.SpawnCorpses();
AutoItemPlacer.PlaceIfNeeded(GameMode);
}
if (GameMode is MultiPlayerCampaign mpCampaign && GameMain.NetworkMember != null && GameMain.NetworkMember.IsServer)
@@ -296,18 +297,18 @@ namespace Barotrauma
}
}
GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Name);
GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
GameAnalyticsManager.AddDesignEvent("Submarine:" + Submarine.Info.Name);
GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level?.Seed ?? "[NO_LEVEL]"));
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));
#if CLIENT
if (GameMode is SinglePlayerCampaign) { SteamAchievementManager.OnBiomeDiscovered(level.Biome); }
RoundSummary = new RoundSummary(this);
if (!(GameMode is SubTestMode)) { RoundSummary = new RoundSummary(this); }
GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
if (!(GameMode is TutorialMode))
if (!(GameMode is TutorialMode) && !(GameMode is SubTestMode))
{
GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
GUI.AddMessage(level.Biome.DisplayName, Color.Lerp(Color.CadetBlue, Color.DarkRed, level.Difficulty / 100.0f), 5.0f, playSound: false);
@@ -322,7 +323,7 @@ namespace Barotrauma
public void Update(float deltaTime)
{
EventManager.Update(deltaTime);
EventManager?.Update(deltaTime);
GameMode?.Update(deltaTime);
Mission?.Update(deltaTime);
@@ -350,9 +351,11 @@ namespace Barotrauma
OnClicked = (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return true; }
};
}
TabMenu.OnRoundEnded();
#endif
EventManager.EndRound();
EventManager?.EndRound();
SteamAchievementManager.OnRoundEnded(this);
Mission = null;
@@ -451,7 +454,7 @@ namespace Barotrauma
XDocument doc = new XDocument(new XElement("Gamesession"));
doc.Root.Add(new XAttribute("savetime", ToolBox.Epoch.NowLocal));
doc.Root.Add(new XAttribute("submarine", Submarine == null ? "" : Submarine.Name));
doc.Root.Add(new XAttribute("submarine", SubmarineInfo == null ? "" : SubmarineInfo.Name));
doc.Root.Add(new XAttribute("mapseed", Map.Seed));
doc.Root.Add(new XAttribute("selectedcontentpackages",
string.Join("|", GameMain.Config.SelectedContentPackages.Where(cp => cp.HasMultiplayerIncompatibleContent).Select(cp => cp.Path))));