38f1ddb...178a853: v0.8.9.1, removed content folder
This commit is contained in:
@@ -8,13 +8,13 @@ namespace Barotrauma
|
||||
{
|
||||
class PurchasedItem
|
||||
{
|
||||
public ItemPrefab itemPrefab;
|
||||
public int quantity;
|
||||
public readonly ItemPrefab ItemPrefab;
|
||||
public int Quantity;
|
||||
|
||||
public PurchasedItem(ItemPrefab itemPrefab, int quantity)
|
||||
{
|
||||
this.itemPrefab = itemPrefab;
|
||||
this.quantity = quantity;
|
||||
this.ItemPrefab = itemPrefab;
|
||||
this.Quantity = quantity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,34 +45,31 @@ namespace Barotrauma
|
||||
OnItemsChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void PurchaseItem(ItemPrefab item, int Quantity = 1)
|
||||
public void PurchaseItem(ItemPrefab item, int quantity = 1)
|
||||
{
|
||||
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item);
|
||||
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.ItemPrefab == item);
|
||||
|
||||
if(purchasedItem != null && Quantity == 1)
|
||||
if (purchasedItem != null && quantity == 1)
|
||||
{
|
||||
campaign.Money -= item.Price;
|
||||
purchasedItem.quantity += 1;
|
||||
campaign.Money -= item.GetPrice(campaign.Map.CurrentLocation).BuyPrice;
|
||||
purchasedItem.Quantity += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
campaign.Money -= (item.Price * Quantity);
|
||||
purchasedItem = new PurchasedItem(item, Quantity);
|
||||
campaign.Money -= item.GetPrice(campaign.Map.CurrentLocation).BuyPrice * quantity;
|
||||
purchasedItem = new PurchasedItem(item, quantity);
|
||||
purchasedItems.Add(purchasedItem);
|
||||
}
|
||||
|
||||
OnItemsChanged?.Invoke();
|
||||
}
|
||||
|
||||
public void SellItem(ItemPrefab item, int quantity = 1)
|
||||
public void SellItem(PurchasedItem purchasedItem, int quantity = 1)
|
||||
{
|
||||
campaign.Money += (item.Price * quantity);
|
||||
PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item);
|
||||
if (purchasedItem != null && purchasedItem.quantity - quantity > 0)
|
||||
{
|
||||
purchasedItem.quantity -= quantity;
|
||||
}
|
||||
else
|
||||
quantity = Math.Min(purchasedItem.Quantity, quantity);
|
||||
campaign.Money += purchasedItem.ItemPrefab.GetPrice(campaign.Map.CurrentLocation).BuyPrice * quantity;
|
||||
purchasedItem.Quantity -= quantity;
|
||||
if (purchasedItem != null && purchasedItem.Quantity <= 0)
|
||||
{
|
||||
PurchasedItems.Remove(purchasedItem);
|
||||
}
|
||||
@@ -82,7 +79,7 @@ namespace Barotrauma
|
||||
|
||||
public int GetTotalItemCost()
|
||||
{
|
||||
return purchasedItems.Sum(i => (i.itemPrefab.Price * i.quantity));
|
||||
return purchasedItems.Sum(i => i.ItemPrefab.GetPrice(campaign.Map.CurrentLocation).BuyPrice * i.Quantity);
|
||||
}
|
||||
|
||||
public void CreateItems()
|
||||
@@ -115,20 +112,20 @@ namespace Barotrauma
|
||||
{
|
||||
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);
|
||||
cargoRoom.Rect.Y - cargoRoom.Rect.Height + pi.ItemPrefab.Size.Y / 2);
|
||||
|
||||
ItemContainer itemContainer = null;
|
||||
if (!string.IsNullOrEmpty(pi.itemPrefab.CargoContainerName))
|
||||
if (!string.IsNullOrEmpty(pi.ItemPrefab.CargoContainerIdentifier))
|
||||
{
|
||||
itemContainer = availableContainers.Keys.ToList().Find(ac =>
|
||||
ac.Item.Prefab.NameMatches(pi.itemPrefab.CargoContainerName) ||
|
||||
ac.Item.Prefab.Tags.Contains(pi.itemPrefab.CargoContainerName.ToLowerInvariant()));
|
||||
ac.Item.Prefab.Identifier == pi.ItemPrefab.CargoContainerIdentifier ||
|
||||
ac.Item.Prefab.Tags.Contains(pi.ItemPrefab.CargoContainerIdentifier.ToLowerInvariant()));
|
||||
|
||||
if (itemContainer == null)
|
||||
{
|
||||
containerPrefab = MapEntityPrefab.List.Find(ep =>
|
||||
ep.NameMatches(pi.itemPrefab.CargoContainerName) ||
|
||||
(ep.Tags != null && ep.Tags.Contains(pi.itemPrefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab;
|
||||
ep.Identifier == pi.ItemPrefab.CargoContainerIdentifier ||
|
||||
(ep.Tags != null && ep.Tags.Contains(pi.ItemPrefab.CargoContainerIdentifier.ToLowerInvariant()))) as ItemPrefab;
|
||||
|
||||
if (containerPrefab == null)
|
||||
{
|
||||
@@ -150,18 +147,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < pi.quantity; i++)
|
||||
for (int i = 0; i < pi.Quantity; i++)
|
||||
{
|
||||
if (itemContainer == null)
|
||||
{
|
||||
//no container, place at the waypoint
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(pi.itemPrefab, position, wp.Submarine);
|
||||
Entity.Spawner.AddToSpawnQueue(pi.ItemPrefab, position, wp.Submarine);
|
||||
}
|
||||
else
|
||||
{
|
||||
new Item(pi.itemPrefab, position, wp.Submarine);
|
||||
new Item(pi.ItemPrefab, position, wp.Submarine);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -181,11 +178,11 @@ namespace Barotrauma
|
||||
//place in the container
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
Entity.Spawner.AddToSpawnQueue(pi.itemPrefab, itemContainer.Inventory);
|
||||
Entity.Spawner.AddToSpawnQueue(pi.ItemPrefab, itemContainer.Inventory);
|
||||
}
|
||||
else
|
||||
{
|
||||
var item = new Item(pi.itemPrefab, position, wp.Submarine);
|
||||
var item = new Item(pi.ItemPrefab, position, wp.Submarine);
|
||||
itemContainer.Inventory.TryPutItem(item, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
using Barotrauma.Networking;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
partial class CrewManager
|
||||
{
|
||||
const float ConversationIntervalMin = 100.0f;
|
||||
const float ConversationIntervalMax = 180.0f;
|
||||
private float conversationTimer, conversationLineTimer;
|
||||
private List<Pair<Character, string>> pendingConversationLines = new List<Pair<Character, string>>();
|
||||
|
||||
//orders that have not been issued to a specific character
|
||||
private List<Pair<Order, float>> activeOrders = new List<Pair<Order, float>>();
|
||||
public List<Pair<Order, float>> ActiveOrders
|
||||
{
|
||||
get { return activeOrders; }
|
||||
}
|
||||
|
||||
private bool isSinglePlayer;
|
||||
public bool IsSinglePlayer
|
||||
{
|
||||
get { return isSinglePlayer; }
|
||||
}
|
||||
|
||||
public CrewManager(bool isSinglePlayer)
|
||||
{
|
||||
this.isSinglePlayer = isSinglePlayer;
|
||||
conversationTimer = 5.0f;
|
||||
|
||||
InitProjectSpecific();
|
||||
}
|
||||
|
||||
partial void InitProjectSpecific();
|
||||
|
||||
public bool AddOrder(Order order, float fadeOutTime)
|
||||
{
|
||||
if (order.TargetEntity == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Attempted to add an order with no target entity to CrewManager!\n" + Environment.StackTrace);
|
||||
return false;
|
||||
}
|
||||
|
||||
Pair<Order, float> existingOrder = activeOrders.Find(o => o.First.Prefab == order.Prefab && o.First.TargetEntity == order.TargetEntity);
|
||||
if (existingOrder != null)
|
||||
{
|
||||
existingOrder.Second = fadeOutTime;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
activeOrders.Add(new Pair<Order, float>(order, fadeOutTime));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveOrder(Order order)
|
||||
{
|
||||
activeOrders.RemoveAll(o => o.First == order);
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
foreach (Pair<Order, float> order in activeOrders)
|
||||
{
|
||||
order.Second -= deltaTime;
|
||||
}
|
||||
activeOrders.RemoveAll(o => o.Second <= 0.0f);
|
||||
|
||||
UpdateProjectSpecific(deltaTime);
|
||||
}
|
||||
|
||||
#region Dialog
|
||||
|
||||
public void AddConversation(List<Pair<Character, string>> conversationLines)
|
||||
{
|
||||
if (conversationLines == null || conversationLines.Count == 0) { return; }
|
||||
pendingConversationLines.AddRange(conversationLines);
|
||||
}
|
||||
|
||||
private void UpdateConversations(float deltaTime)
|
||||
{
|
||||
conversationTimer -= deltaTime;
|
||||
if (conversationTimer <= 0.0f)
|
||||
{
|
||||
#if CLIENT
|
||||
List<Character> availableSpeakers = GameMain.GameSession.CrewManager.GetCharacters().ToList();
|
||||
availableSpeakers.RemoveAll(c => !(c.AIController is HumanAIController) || c.IsDead || c.SpeechImpediment >= 100.0f);
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
foreach (Client client in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
if (client.Character != null) availableSpeakers.Remove(client.Character);
|
||||
}
|
||||
if (GameMain.Server.Character != null) availableSpeakers.Remove(GameMain.Server.Character);
|
||||
}
|
||||
#else
|
||||
List<Character> availableSpeakers = Character.CharacterList.FindAll(c =>
|
||||
c.AIController is HumanAIController &&
|
||||
!c.IsDead &&
|
||||
c.SpeechImpediment <= 100.0f);
|
||||
#endif
|
||||
pendingConversationLines.AddRange(NPCConversation.CreateRandom(availableSpeakers));
|
||||
conversationTimer = Rand.Range(ConversationIntervalMin, ConversationIntervalMax);
|
||||
}
|
||||
|
||||
if (pendingConversationLines.Count > 0)
|
||||
{
|
||||
conversationLineTimer -= deltaTime;
|
||||
if (conversationLineTimer <= 0.0f)
|
||||
{
|
||||
//speaker of the next line can't speak, interrupt the conversation
|
||||
if (pendingConversationLines[0].First.SpeechImpediment >= 100.0f)
|
||||
{
|
||||
pendingConversationLines.Clear();
|
||||
return;
|
||||
}
|
||||
|
||||
pendingConversationLines[0].First.Speak(pendingConversationLines[0].Second, null);
|
||||
if (pendingConversationLines.Count > 1)
|
||||
{
|
||||
conversationLineTimer = MathHelper.Clamp(pendingConversationLines[0].Second.Length * 0.1f, 1.0f, 5.0f);
|
||||
}
|
||||
pendingConversationLines.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
partial void UpdateProjectSpecific(float deltaTime);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -9,7 +10,15 @@ namespace Barotrauma
|
||||
{
|
||||
public readonly CargoManager CargoManager;
|
||||
|
||||
const int InitialMoney = 10000;
|
||||
public bool CheatsEnabled;
|
||||
|
||||
const int InitialMoney = 4500;
|
||||
|
||||
private bool watchmenSpawned;
|
||||
private Character startWatchman, endWatchman;
|
||||
|
||||
//key = dialog flag, double = Timing.TotalTime when the line was last said
|
||||
private Dictionary<string, double> dialogLastSpoken = new Dictionary<string, double>();
|
||||
|
||||
protected Map map;
|
||||
public Map Map
|
||||
@@ -21,7 +30,7 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
return Map.SelectedConnection.Mission;
|
||||
return Map.CurrentLocation?.SelectedMission;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +50,7 @@ namespace Barotrauma
|
||||
|
||||
public void GenerateMap(string seed)
|
||||
{
|
||||
map = new Map(seed, 1000);
|
||||
map = new Map(seed);
|
||||
}
|
||||
|
||||
protected List<Submarine> GetSubsToLeaveBehind(Submarine leavingSub)
|
||||
@@ -50,17 +59,98 @@ namespace Barotrauma
|
||||
return Submarine.Loaded.FindAll(s =>
|
||||
s != leavingSub &&
|
||||
!leavingSub.DockedTo.Contains(s) &&
|
||||
s != Level.Loaded.StartOutpost && s != Level.Loaded.EndOutpost &&
|
||||
(s.AtEndPosition != leavingSub.AtEndPosition || s.AtStartPosition != leavingSub.AtStartPosition));
|
||||
}
|
||||
|
||||
public override void End(string endMessage = "")
|
||||
public override void Start()
|
||||
{
|
||||
base.End(endMessage);
|
||||
base.Start();
|
||||
dialogLastSpoken.Clear();
|
||||
watchmenSpawned = false;
|
||||
startWatchman = null;
|
||||
endWatchman = null;
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
base.Update(deltaTime);
|
||||
|
||||
if (GameMain.Client != null || !IsRunning) { return; }
|
||||
|
||||
if (!watchmenSpawned)
|
||||
{
|
||||
if (Level.Loaded.StartOutpost != null) { startWatchman = SpawnWatchman(Level.Loaded.StartOutpost); }
|
||||
if (Level.Loaded.EndOutpost != null) { endWatchman = SpawnWatchman(Level.Loaded.EndOutpost); }
|
||||
watchmenSpawned = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (Character character in Character.CharacterList)
|
||||
{
|
||||
#if SERVER
|
||||
if (string.IsNullOrEmpty(character.OwnerClientIP)) { continue; }
|
||||
#else
|
||||
if (!CrewManager.GetCharacters().Contains(character)) { continue; }
|
||||
#endif
|
||||
if (character.Submarine == Level.Loaded.StartOutpost && character.CurrentHull == startWatchman.CurrentHull)
|
||||
{
|
||||
CreateDialog(new List<Character> { startWatchman }, "EnterStartOutpost", 5 * 60.0f);
|
||||
}
|
||||
else if (character.Submarine == Level.Loaded.EndOutpost && character.CurrentHull == endWatchman.CurrentHull)
|
||||
{
|
||||
CreateDialog(new List<Character> { endWatchman }, "EnterEndOutpost", 5 * 60.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void CreateDialog(List<Character> speakers, string conversationTag, float minInterval)
|
||||
{
|
||||
if (dialogLastSpoken.TryGetValue(conversationTag, out double lastTime))
|
||||
{
|
||||
if (Timing.TotalTime - lastTime < minInterval) { return; }
|
||||
}
|
||||
|
||||
CrewManager.AddConversation(
|
||||
NPCConversation.CreateRandom(speakers, new List<string>() { conversationTag }));
|
||||
dialogLastSpoken[conversationTag] = Timing.TotalTime;
|
||||
}
|
||||
|
||||
private Character SpawnWatchman(Submarine outpost)
|
||||
{
|
||||
WayPoint watchmanSpawnpoint = WayPoint.WayPointList.Find(wp => wp.Submarine == outpost);
|
||||
if (watchmanSpawnpoint == null)
|
||||
{
|
||||
DebugConsole.ThrowError("Failed to spawn a watchman at the outpost. No spawnpoints found inside the outpost.");
|
||||
return null;
|
||||
}
|
||||
|
||||
string seed = outpost == Level.Loaded.StartOutpost ? map.SelectedLocation.Name : map.CurrentLocation.Name;
|
||||
Rand.SetSyncedSeed(ToolBox.StringToInt(seed));
|
||||
|
||||
JobPrefab watchmanJob = JobPrefab.List.Find(jp => jp.Identifier == "watchman");
|
||||
CharacterInfo characterInfo = new CharacterInfo(Character.HumanConfigFile, jobPrefab: watchmanJob);
|
||||
var spawnedCharacter = Character.Create(characterInfo, watchmanSpawnpoint.WorldPosition,
|
||||
Level.Loaded.Seed + (outpost == Level.Loaded.StartOutpost ? "start" : "end"));
|
||||
spawnedCharacter.CharacterHealth.Unkillable = true;
|
||||
spawnedCharacter.CharacterHealth.UseHealthWindow = false;
|
||||
spawnedCharacter.SetCustomInteract(
|
||||
WatchmanInteract,
|
||||
hudText: TextManager.Get("TalkHint").Replace("[key]", GameMain.Config.KeyBind(InputType.Select).ToString()));
|
||||
(spawnedCharacter.AIController as HumanAIController)?.ObjectiveManager.SetOrder(
|
||||
new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, repeat: true, getDivingGearIfNeeded: false));
|
||||
if (watchmanJob != null)
|
||||
{
|
||||
spawnedCharacter.GiveJobItems();
|
||||
}
|
||||
return spawnedCharacter;
|
||||
}
|
||||
|
||||
protected abstract void WatchmanInteract(Character watchman, Character interactor);
|
||||
|
||||
public abstract void Save(XElement element);
|
||||
|
||||
|
||||
|
||||
public void LogState()
|
||||
{
|
||||
DebugConsole.NewMessage("********* CAMPAIGN STATUS *********", Color.White);
|
||||
@@ -81,11 +171,18 @@ namespace Barotrauma
|
||||
}
|
||||
}
|
||||
|
||||
if (map.SelectedConnection?.Mission != null)
|
||||
if (map.CurrentLocation?.SelectedMission != null)
|
||||
{
|
||||
DebugConsole.NewMessage(" Selected mission: " + map.SelectedConnection.Mission.Name, Color.White);
|
||||
DebugConsole.NewMessage("\n" + map.SelectedConnection.Mission.Description, Color.White);
|
||||
DebugConsole.NewMessage(" Selected mission: " + map.CurrentLocation.SelectedMission.Name, Color.White);
|
||||
DebugConsole.NewMessage("\n" + map.CurrentLocation.SelectedMission.Description, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Remove()
|
||||
{
|
||||
base.Remove();
|
||||
map?.Remove();
|
||||
map = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,124 @@
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using Lidgren.Network;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CharacterCampaignData
|
||||
{
|
||||
public readonly CharacterInfo CharacterInfo;
|
||||
|
||||
public readonly string Name;
|
||||
|
||||
public readonly bool IsHostCharacter;
|
||||
|
||||
public readonly string ClientIP;
|
||||
public readonly ulong SteamID;
|
||||
|
||||
private XElement itemData;
|
||||
|
||||
public CharacterCampaignData(Client client)
|
||||
{
|
||||
Name = client.Name;
|
||||
ClientIP = client.Connection.RemoteEndPoint.Address.ToString();
|
||||
SteamID = client.SteamID;
|
||||
CharacterInfo = client.CharacterInfo;
|
||||
|
||||
if (client.Character.Inventory != null)
|
||||
{
|
||||
itemData = new XElement("inventory");
|
||||
client.Character.SaveInventory(client.Character.Inventory, itemData);
|
||||
}
|
||||
}
|
||||
|
||||
public CharacterCampaignData(GameServer server)
|
||||
{
|
||||
Name = server.Character.Name;
|
||||
CharacterInfo = server.Character.Info;
|
||||
IsHostCharacter = true;
|
||||
|
||||
if (server.Character.Inventory != null)
|
||||
{
|
||||
itemData = new XElement("inventory");
|
||||
server.Character.SaveInventory(server.Character.Inventory, itemData);
|
||||
}
|
||||
}
|
||||
|
||||
public CharacterCampaignData(XElement element)
|
||||
{
|
||||
Name = element.GetAttributeString("name", "Unnamed");
|
||||
IsHostCharacter = element.GetAttributeBool("host", false);
|
||||
if (!IsHostCharacter)
|
||||
{
|
||||
ClientIP = element.GetAttributeString("ip", "");
|
||||
string steamID = element.GetAttributeString("steamid", "");
|
||||
if (!string.IsNullOrEmpty(steamID))
|
||||
{
|
||||
ulong.TryParse(steamID, out SteamID);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
{
|
||||
case "character":
|
||||
case "characterinfo":
|
||||
CharacterInfo = new CharacterInfo(subElement);
|
||||
break;
|
||||
case "inventory":
|
||||
itemData = subElement;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool MatchesClient(Client client)
|
||||
{
|
||||
if (IsHostCharacter) return false;
|
||||
if (SteamID > 0)
|
||||
{
|
||||
return SteamID == client.SteamID;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ClientIP == client.Connection.RemoteEndPoint.Address.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public XElement Save()
|
||||
{
|
||||
XElement element = new XElement("CharacterCampaignData",
|
||||
new XAttribute("name", Name));
|
||||
|
||||
if (IsHostCharacter)
|
||||
{
|
||||
element.Add(new XAttribute("host", true));
|
||||
}
|
||||
else
|
||||
{
|
||||
element.Add(new XAttribute("ip", ClientIP));
|
||||
element.Add(new XAttribute("steamid", SteamID));
|
||||
}
|
||||
|
||||
CharacterInfo?.Save(element);
|
||||
|
||||
if (itemData != null)
|
||||
{
|
||||
element.Add(itemData);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
public void SpawnInventoryItems(CharacterInfo characterInfo, Inventory inventory)
|
||||
{
|
||||
characterInfo.SpawnInventoryItems(inventory, itemData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,11 @@ namespace Barotrauma
|
||||
protected GameModePreset preset;
|
||||
|
||||
private string endMessage;
|
||||
|
||||
protected CrewManager CrewManager
|
||||
{
|
||||
get { return GameMain.GameSession?.CrewManager; }
|
||||
}
|
||||
|
||||
public virtual Mission Mission
|
||||
{
|
||||
@@ -60,10 +65,20 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
public virtual void MsgBox() { }
|
||||
|
||||
public virtual void AddToGUIUpdateList()
|
||||
{
|
||||
#if CLIENT
|
||||
if (!isRunning) return;
|
||||
|
||||
GameMain.GameSession?.CrewManager.AddToGUIUpdateList();
|
||||
#endif
|
||||
}
|
||||
|
||||
public virtual void AddToGUIUpdateList() { }
|
||||
|
||||
public virtual void Update(float deltaTime) { }
|
||||
public virtual void Update(float deltaTime)
|
||||
{
|
||||
CrewManager?.Update(deltaTime);
|
||||
}
|
||||
|
||||
public virtual void End(string endMessage = "")
|
||||
{
|
||||
@@ -74,6 +89,6 @@ namespace Barotrauma
|
||||
GameMain.GameSession.EndRound(endMessage);
|
||||
}
|
||||
|
||||
|
||||
public virtual void Remove() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,25 @@ namespace Barotrauma
|
||||
{
|
||||
class GameModePreset
|
||||
{
|
||||
public static List<GameModePreset> list = new List<GameModePreset>();
|
||||
public static List<GameModePreset> List = new List<GameModePreset>();
|
||||
|
||||
public ConstructorInfo Constructor
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public ConstructorInfo Constructor;
|
||||
public string Name;
|
||||
public string Name
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Identifier
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public bool IsSinglePlayer
|
||||
{
|
||||
@@ -30,16 +45,17 @@ namespace Barotrauma
|
||||
private set;
|
||||
}
|
||||
|
||||
public GameModePreset(string name, Type type, bool isSinglePlayer = false, bool votable = true)
|
||||
public GameModePreset(string identifier, Type type, bool isSinglePlayer = false, bool votable = true)
|
||||
{
|
||||
this.Name = name;
|
||||
Name = TextManager.Get("GameMode." + identifier);
|
||||
Identifier = identifier;
|
||||
|
||||
Constructor = type.GetConstructor(new Type[] { typeof(GameModePreset), typeof(object) });
|
||||
|
||||
IsSinglePlayer = isSinglePlayer;
|
||||
Votable = votable;
|
||||
|
||||
list.Add(this);
|
||||
List.Add(this);
|
||||
}
|
||||
|
||||
public GameMode Instantiate(object param)
|
||||
@@ -51,19 +67,27 @@ namespace Barotrauma
|
||||
public static void Init()
|
||||
{
|
||||
#if CLIENT
|
||||
new GameModePreset("Single Player", typeof(SinglePlayerCampaign), true);
|
||||
new GameModePreset("Tutorial", typeof(TutorialMode), true);
|
||||
new GameModePreset("singleplayercampaign", typeof(SinglePlayerCampaign), true);
|
||||
new GameModePreset("tutorial", typeof(TutorialMode), true);
|
||||
#endif
|
||||
new GameModePreset("devsandbox", typeof(GameMode), true)
|
||||
{
|
||||
Description = "Single player sandbox mode for debugging."
|
||||
};
|
||||
|
||||
var mode = new GameModePreset("SandBox", typeof(GameMode), false);
|
||||
mode.Description = "A game mode with no specific objectives.";
|
||||
|
||||
mode = new GameModePreset("Mission", typeof(MissionMode), false);
|
||||
mode.Description = "The crew must work together to complete a specific task, such as retrieving "
|
||||
new GameModePreset("sandbox", typeof(GameMode), false)
|
||||
{
|
||||
Description = "A game mode with no specific objectives."
|
||||
};
|
||||
|
||||
new GameModePreset("mission", typeof(MissionMode), false)
|
||||
{
|
||||
Description = "The crew must work together to complete a specific task, such as retrieving "
|
||||
+ "an alien artifact or killing a creature that's terrorizing nearby outposts. The game ends "
|
||||
+ "when the task is completed or everyone in the crew has died.";
|
||||
+ "when the task is completed or everyone in the crew has died."
|
||||
};
|
||||
|
||||
new GameModePreset("Campaign", typeof(MultiPlayerCampaign), false, false);
|
||||
//new GameModePreset("multiplayercampaign", typeof(MultiPlayerCampaign), false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
: base(preset, param)
|
||||
{
|
||||
Location[] locations = { GameMain.GameSession.StartLocation, GameMain.GameSession.EndLocation };
|
||||
if (param is string)
|
||||
if (param is MissionType missionType)
|
||||
{
|
||||
mission = Mission.LoadRandom(locations, GameMain.NetLobbyScreen.LevelSeed, (string)param);
|
||||
mission = Mission.LoadRandom(locations, GameMain.NetLobbyScreen.LevelSeed, false, missionType);
|
||||
}
|
||||
else if (param is MissionPrefab)
|
||||
else if (param is MissionPrefab missionPrefab)
|
||||
{
|
||||
mission = ((MissionPrefab)param).Instantiate(locations);
|
||||
mission = missionPrefab.Instantiate(locations);
|
||||
}
|
||||
else if (param is Mission)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using Lidgren.Network;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -32,6 +33,8 @@ namespace Barotrauma
|
||||
|
||||
private static byte currentCampaignID;
|
||||
|
||||
private List<CharacterCampaignData> characterData = new List<CharacterCampaignData>();
|
||||
|
||||
public byte CampaignID
|
||||
{
|
||||
get; private set;
|
||||
@@ -50,9 +53,55 @@ namespace Barotrauma
|
||||
{
|
||||
CargoManager.OnItemsChanged += () => { LastUpdateID++; };
|
||||
Map.OnLocationSelected += (loc, connection) => { LastUpdateID++; };
|
||||
Map.OnMissionSelected += (loc, mission) => { LastUpdateID++; };
|
||||
}
|
||||
}
|
||||
|
||||
public void DiscardClientCharacterData(Client client)
|
||||
{
|
||||
characterData.RemoveAll(cd => cd.MatchesClient(client));
|
||||
}
|
||||
|
||||
public CharacterCampaignData GetClientCharacterData(Client client)
|
||||
{
|
||||
return characterData.Find(cd => cd.MatchesClient(client));
|
||||
}
|
||||
|
||||
public CharacterCampaignData GetHostCharacterData()
|
||||
{
|
||||
return characterData.Find(cd => cd.IsHostCharacter);
|
||||
}
|
||||
|
||||
public void AssignPlayerCharacterInfos(IEnumerable<Client> connectedClients, bool assignHost)
|
||||
{
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
if (client.SpectateOnly && GameMain.Server.AllowSpectating) continue;
|
||||
var matchingData = GetClientCharacterData(client);
|
||||
if (matchingData != null) client.CharacterInfo = matchingData.CharacterInfo;
|
||||
}
|
||||
|
||||
if (assignHost)
|
||||
{
|
||||
var hostCharacterData = GetHostCharacterData();
|
||||
if (hostCharacterData?.CharacterInfo != null)
|
||||
{
|
||||
GameMain.Server.CharacterInfo = hostCharacterData.CharacterInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Dictionary<Client, Job> GetAssignedJobs(IEnumerable<Client> connectedClients)
|
||||
{
|
||||
var assignedJobs = new Dictionary<Client, Job>();
|
||||
foreach (Client client in connectedClients)
|
||||
{
|
||||
var matchingData = GetClientCharacterData(client);
|
||||
if (matchingData != null) assignedJobs.Add(client, matchingData.CharacterInfo.Job);
|
||||
}
|
||||
return assignedJobs;
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
base.Start();
|
||||
@@ -60,6 +109,44 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
protected override void WatchmanInteract(Character watchman, Character interactor)
|
||||
{
|
||||
if ((watchman.Submarine == Level.Loaded.StartOutpost && !Submarine.MainSub.AtStartPosition) ||
|
||||
(watchman.Submarine == Level.Loaded.EndOutpost && !Submarine.MainSub.AtEndPosition))
|
||||
{
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
CreateDialog(new List<Character> { watchman }, "WatchmanInteractNoLeavingSub", 5.0f);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool hasPermissions = true;
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
var client = GameMain.Server.ConnectedClients.Find(c => c.Character == interactor);
|
||||
hasPermissions = client != null &&
|
||||
(client.HasPermission(ClientPermissions.EndRound) || client.HasPermission(ClientPermissions.ManageCampaign));
|
||||
CreateDialog(new List<Character> { watchman }, hasPermissions ? "WatchmanInteract" : "WatchmanInteractNotAllowed", 1.0f);
|
||||
}
|
||||
#if CLIENT
|
||||
else if (GameMain.Client != null && interactor == Character.Controlled && hasPermissions)
|
||||
{
|
||||
var msgBox = new GUIMessageBox("", TextManager.Get("CampaignEnterOutpostPrompt")
|
||||
.Replace("[locationname]", Submarine.MainSub.AtStartPosition ? Map.CurrentLocation.Name : Map.SelectedLocation.Name),
|
||||
new string[] { TextManager.Get("Yes"), TextManager.Get("No") });
|
||||
msgBox.Buttons[0].OnClicked = (btn, userdata) =>
|
||||
{
|
||||
GameMain.Client.RequestRoundEnd();
|
||||
return true;
|
||||
};
|
||||
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void End(string endMessage = "")
|
||||
{
|
||||
isRunning = false;
|
||||
@@ -92,17 +179,42 @@ namespace Barotrauma
|
||||
}*/
|
||||
|
||||
GameMain.GameSession.EndRound("");
|
||||
|
||||
foreach (Client c in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
if (c.HasSpawned)
|
||||
{
|
||||
//client has spawned this round -> remove old data (and replace with new one if the client still has an alive character)
|
||||
characterData.RemoveAll(cd => cd.MatchesClient(c));
|
||||
}
|
||||
|
||||
if (c.Character?.Info != null && !c.Character.IsDead)
|
||||
{
|
||||
characterData.Add(new CharacterCampaignData(c));
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: save player inventories between mp campaign rounds
|
||||
#if CLIENT
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(null);
|
||||
#endif
|
||||
|
||||
if (GameMain.Server.Character != null)
|
||||
{
|
||||
characterData.RemoveAll(cd => cd.IsHostCharacter);
|
||||
if (!GameMain.Server.Character.IsDead)
|
||||
{
|
||||
var hostCharacterData = new CharacterCampaignData(GameMain.Server);
|
||||
characterData.Add(hostCharacterData);
|
||||
#if CLIENT
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(hostCharacterData.CharacterInfo);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//remove all items that are in someone's inventory
|
||||
foreach (Character c in Character.CharacterList)
|
||||
{
|
||||
if (c.Inventory == null) continue;
|
||||
foreach (Item item in c.Inventory.Items)
|
||||
{
|
||||
if (item != null) item.Remove();
|
||||
}
|
||||
c.Inventory?.DeleteAllItems();
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
@@ -128,29 +240,54 @@ namespace Barotrauma
|
||||
|
||||
if (atEndPosition)
|
||||
{
|
||||
Map.MoveToNextLocation();
|
||||
map.MoveToNextLocation();
|
||||
|
||||
//select a random location to make sure we've got some destination
|
||||
//to head towards even if the host/clients don't select anything
|
||||
map.SelectRandomLocation(true);
|
||||
}
|
||||
map.ProgressWorld();
|
||||
|
||||
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static MultiPlayerCampaign LoadNew(XElement element)
|
||||
{
|
||||
MultiPlayerCampaign campaign = new MultiPlayerCampaign(GameModePreset.list.Find(gm => gm.Name == "Campaign"), null);
|
||||
campaign.Load(element);
|
||||
MultiPlayerCampaign campaign = new MultiPlayerCampaign(GameModePreset.List.Find(gm => gm.Identifier == "multiplayercampaign"), null);
|
||||
campaign.Load(element);
|
||||
campaign.SetDelegates();
|
||||
|
||||
return campaign;
|
||||
}
|
||||
|
||||
public static string GetCharacterDataSavePath(string savePath)
|
||||
{
|
||||
return Path.Combine(SaveUtil.MultiplayerSaveFolder, Path.GetFileNameWithoutExtension(savePath) + "_CharacterData.xml");
|
||||
}
|
||||
|
||||
public string GetCharacterDataSavePath()
|
||||
{
|
||||
return GetCharacterDataSavePath(GameMain.GameSession.SavePath);
|
||||
}
|
||||
|
||||
public void Load(XElement element)
|
||||
{
|
||||
Money = element.GetAttributeInt("money", 0);
|
||||
CheatsEnabled = element.GetAttributeBool("cheatsenabled", false);
|
||||
if (CheatsEnabled)
|
||||
{
|
||||
DebugConsole.CheatsEnabled = true;
|
||||
if (GameMain.Config.UseSteam && !SteamAchievementManager.CheatsEnabled)
|
||||
{
|
||||
SteamAchievementManager.CheatsEnabled = true;
|
||||
#if CLIENT
|
||||
new GUIMessageBox("Cheats enabled", "Cheat commands have been enabled on the server. You will not receive Steam Achievements until you restart the game.");
|
||||
#else
|
||||
DebugConsole.NewMessage("Cheat commands have been enabled.", Color.Red);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XElement subElement in element.Elements())
|
||||
{
|
||||
@@ -159,24 +296,64 @@ namespace Barotrauma
|
||||
case "map":
|
||||
if (map == null)
|
||||
{
|
||||
//map not created yet, loading this campaign for the first time
|
||||
map = Map.LoadNew(subElement);
|
||||
}
|
||||
else
|
||||
{
|
||||
map.Load(subElement);
|
||||
//map already created, update it
|
||||
//if we're not downloading the initial save file (LastSaveID > 0),
|
||||
//show notifications about location type changes
|
||||
map.Load(subElement, LastSaveID > 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (GameMain.Server != null)
|
||||
{
|
||||
characterData.Clear();
|
||||
string characterDataPath = GetCharacterDataSavePath();
|
||||
var characterDataDoc = XMLExtensions.TryLoadXml(characterDataPath);
|
||||
if (characterDataDoc?.Root == null) return;
|
||||
foreach (XElement subElement in characterDataDoc.Root.Elements())
|
||||
{
|
||||
characterData.Add(new CharacterCampaignData(subElement));
|
||||
}
|
||||
#if CLIENT
|
||||
var hostCharacterData = GetHostCharacterData();
|
||||
if (hostCharacterData?.CharacterInfo != null)
|
||||
{
|
||||
GameMain.NetLobbyScreen.SetCampaignCharacterInfo(hostCharacterData.CharacterInfo);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public override void Save(XElement element)
|
||||
{
|
||||
XElement modeElement = new XElement("MultiPlayerCampaign");
|
||||
modeElement.Add(new XAttribute("money", Money));
|
||||
XElement modeElement = new XElement("MultiPlayerCampaign",
|
||||
new XAttribute("money", Money),
|
||||
new XAttribute("cheatsenabled", CheatsEnabled));
|
||||
Map.Save(modeElement);
|
||||
element.Add(modeElement);
|
||||
|
||||
//save character data to a separate file
|
||||
string characterDataPath = GetCharacterDataSavePath();
|
||||
XDocument characterDataDoc = new XDocument(new XElement("CharacterData"));
|
||||
foreach (CharacterCampaignData cd in characterData)
|
||||
{
|
||||
characterDataDoc.Root.Add(cd.Save());
|
||||
}
|
||||
try
|
||||
{
|
||||
characterDataDoc.Save(characterDataPath);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Saving multiplayer campaign characters to \"" + characterDataPath + "\" failed!", e);
|
||||
}
|
||||
|
||||
lastSaveID++;
|
||||
}
|
||||
|
||||
@@ -190,20 +367,33 @@ namespace Barotrauma
|
||||
msg.Write(map.Seed);
|
||||
msg.Write(map.CurrentLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.CurrentLocationIndex);
|
||||
msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex);
|
||||
msg.Write(map.SelectedMissionIndex == -1 ? byte.MaxValue : (byte)map.SelectedMissionIndex);
|
||||
|
||||
msg.Write(Money);
|
||||
|
||||
msg.Write((UInt16)CargoManager.PurchasedItems.Count);
|
||||
foreach (PurchasedItem pi in CargoManager.PurchasedItems)
|
||||
{
|
||||
msg.Write((UInt16)MapEntityPrefab.List.IndexOf(pi.itemPrefab));
|
||||
msg.Write((UInt16)pi.quantity);
|
||||
msg.Write((UInt16)MapEntityPrefab.List.IndexOf(pi.ItemPrefab));
|
||||
msg.Write((UInt16)pi.Quantity);
|
||||
}
|
||||
|
||||
var characterData = GetClientCharacterData(c);
|
||||
if (characterData?.CharacterInfo == null)
|
||||
{
|
||||
msg.Write(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
msg.Write(true);
|
||||
characterData.CharacterInfo.ServerWrite(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public void ServerRead(NetBuffer msg, Client sender)
|
||||
{
|
||||
UInt16 selectedLocIndex = msg.ReadUInt16();
|
||||
byte selectedMissionIndex = msg.ReadByte();
|
||||
UInt16 purchasedItemCount = msg.ReadUInt16();
|
||||
|
||||
List<PurchasedItem> purchasedItems = new List<PurchasedItem>();
|
||||
@@ -216,21 +406,25 @@ namespace Barotrauma
|
||||
|
||||
if (!sender.HasPermission(ClientPermissions.ManageCampaign))
|
||||
{
|
||||
DebugConsole.ThrowError("Client \""+sender.Name+"\" does not have a permission to manage the campaign");
|
||||
DebugConsole.ThrowError("Client \"" + sender.Name + "\" does not have a permission to manage the campaign");
|
||||
return;
|
||||
}
|
||||
|
||||
Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex);
|
||||
if (Map.SelectedConnection != null)
|
||||
{
|
||||
Map.SelectMission(selectedMissionIndex);
|
||||
}
|
||||
|
||||
List<PurchasedItem> currentItems = new List<PurchasedItem>(CargoManager.PurchasedItems);
|
||||
foreach (PurchasedItem pi in currentItems)
|
||||
{
|
||||
CargoManager.SellItem(pi.itemPrefab, pi.quantity);
|
||||
CargoManager.SellItem(pi, pi.Quantity);
|
||||
}
|
||||
|
||||
foreach (PurchasedItem pi in purchasedItems)
|
||||
{
|
||||
CargoManager.PurchaseItem(pi.itemPrefab, pi.quantity);
|
||||
CargoManager.PurchaseItem(pi.ItemPrefab, pi.Quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,10 +30,10 @@ namespace Barotrauma
|
||||
var moreAgentsMsgBox = ChatMessage.Create(null, moreAgentsMessage, ChatMessageType.MessageBox, null);
|
||||
|
||||
Client client = server.ConnectedClients.Find(c => c.Character == Character);
|
||||
GameMain.Server.SendChatMessage(greetingChatMsg, client);
|
||||
GameMain.Server.SendChatMessage(moreAgentsChatMsg, client);
|
||||
GameMain.Server.SendChatMessage(greetingMsgBox, client);
|
||||
GameMain.Server.SendChatMessage(moreAgentsMsgBox, client);
|
||||
GameMain.Server.SendDirectChatMessage(greetingChatMsg, client);
|
||||
GameMain.Server.SendDirectChatMessage(moreAgentsChatMsg, client);
|
||||
GameMain.Server.SendDirectChatMessage(greetingMsgBox, client);
|
||||
GameMain.Server.SendDirectChatMessage(moreAgentsMsgBox, client);
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
using Barotrauma.Items.Components;
|
||||
using Microsoft.Xna.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
@@ -18,10 +20,10 @@ namespace Barotrauma
|
||||
private string savePath;
|
||||
|
||||
private Submarine submarine;
|
||||
|
||||
#if CLIENT
|
||||
|
||||
public CrewManager CrewManager;
|
||||
#endif
|
||||
|
||||
public double RoundStartTime;
|
||||
|
||||
private Mission currentMission;
|
||||
|
||||
@@ -44,8 +46,7 @@ namespace Barotrauma
|
||||
{
|
||||
get
|
||||
{
|
||||
CampaignMode mode = (GameMode as CampaignMode);
|
||||
return (mode == null) ? null : mode.Map;
|
||||
return (GameMode as CampaignMode)?.Map;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,15 +93,17 @@ namespace Barotrauma
|
||||
}
|
||||
|
||||
|
||||
public GameSession(Submarine submarine, string savePath, GameModePreset gameModePreset, string missionType = "")
|
||||
public GameSession(Submarine submarine, string savePath, GameModePreset gameModePreset, MissionType missionType = MissionType.None)
|
||||
: this(submarine, 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)
|
||||
{
|
||||
CrewManager = new CrewManager(gameModePreset != null && gameModePreset.IsSinglePlayer);
|
||||
GameMode = gameModePreset.Instantiate(missionPrefab);
|
||||
}
|
||||
|
||||
@@ -111,10 +114,11 @@ namespace Barotrauma
|
||||
GameMain.GameSession = this;
|
||||
EventManager = new EventManager(this);
|
||||
this.savePath = savePath;
|
||||
|
||||
#if CLIENT
|
||||
CrewManager = new CrewManager();
|
||||
|
||||
infoButton = new GUIButton(new Rectangle(10, 10, 100, 20), "Info", "", null);
|
||||
int buttonHeight = (int)(HUDLayoutSettings.ButtonAreaTop.Height * 0.6f);
|
||||
infoButton = new GUIButton(HUDLayoutSettings.ToRectTransform(new Rectangle(HUDLayoutSettings.ButtonAreaTop.X, HUDLayoutSettings.ButtonAreaTop.Center.Y - buttonHeight / 2, 100, buttonHeight), GUICanvas.Instance),
|
||||
TextManager.Get("InfoButton"), textAlignment: Alignment.Center);
|
||||
infoButton.OnClicked = ToggleInfoFrame;
|
||||
#endif
|
||||
}
|
||||
@@ -127,10 +131,7 @@ namespace Barotrauma
|
||||
|
||||
GameMain.GameSession = this;
|
||||
selectedSub.Name = doc.Root.GetAttributeString("submarine", selectedSub.Name);
|
||||
#if CLIENT
|
||||
CrewManager = new CrewManager();
|
||||
#endif
|
||||
|
||||
|
||||
foreach (XElement subElement in doc.Root.Elements())
|
||||
{
|
||||
switch (subElement.Name.ToString().ToLowerInvariant())
|
||||
@@ -138,10 +139,12 @@ namespace Barotrauma
|
||||
#if CLIENT
|
||||
case "gamemode": //legacy support
|
||||
case "singleplayercampaign":
|
||||
CrewManager = new CrewManager(true);
|
||||
GameMode = SinglePlayerCampaign.Load(subElement);
|
||||
break;
|
||||
#endif
|
||||
case "multiplayercampaign":
|
||||
CrewManager = new CrewManager(false);
|
||||
GameMode = MultiPlayerCampaign.LoadNew(subElement);
|
||||
break;
|
||||
}
|
||||
@@ -165,7 +168,7 @@ namespace Barotrauma
|
||||
MTRandom rand = new MTRandom(ToolBox.StringToInt(seed));
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
dummyLocations[i] = Location.CreateRandom(new Vector2((float)rand.NextDouble() * 10000.0f, (float)rand.NextDouble() * 10000.0f));
|
||||
dummyLocations[i] = Location.CreateRandom(new Vector2((float)rand.NextDouble() * 10000.0f, (float)rand.NextDouble() * 10000.0f), null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,9 +178,9 @@ namespace Barotrauma
|
||||
SaveUtil.LoadGame(savePath);
|
||||
}
|
||||
|
||||
public void StartRound(string levelSeed, bool loadSecondSub = false)
|
||||
public void StartRound(string levelSeed, float? difficulty = null, bool loadSecondSub = false)
|
||||
{
|
||||
Level randomLevel = Level.CreateRandom(levelSeed);
|
||||
Level randomLevel = Level.CreateRandom(levelSeed, difficulty);
|
||||
|
||||
StartRound(randomLevel, true, loadSecondSub);
|
||||
}
|
||||
@@ -186,8 +189,8 @@ namespace Barotrauma
|
||||
{
|
||||
#if CLIENT
|
||||
GameMain.LightManager.LosEnabled = GameMain.NetworkMember == null || GameMain.NetworkMember.CharacterInfo != null;
|
||||
if (GameMain.Client == null) GameMain.LightManager.LosMode = GameMain.Config.LosMode;
|
||||
#endif
|
||||
|
||||
this.level = level;
|
||||
|
||||
if (submarine == null)
|
||||
@@ -202,7 +205,7 @@ namespace Barotrauma
|
||||
{
|
||||
if (Submarine.MainSubs[1] == null)
|
||||
{
|
||||
Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath,Submarine.MainSub.MD5Hash.Hash,true);
|
||||
Submarine.MainSubs[1] = new Submarine(Submarine.MainSub.FilePath, Submarine.MainSub.MD5Hash.Hash, true);
|
||||
Submarine.MainSubs[1].Load(false);
|
||||
}
|
||||
else if (reloadSub)
|
||||
@@ -210,11 +213,61 @@ namespace Barotrauma
|
||||
Submarine.MainSubs[1].Load(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (level != null)
|
||||
{
|
||||
level.Generate(mirrorLevel);
|
||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition - new Vector2(0.0f, 2000.0f)));
|
||||
if (level.StartOutpost != null)
|
||||
{
|
||||
//start by placing the sub below the outpost
|
||||
Rectangle outpostBorders = Level.Loaded.StartOutpost.GetDockedBorders();
|
||||
Rectangle subBorders = submarine.GetDockedBorders();
|
||||
|
||||
Vector2 startOutpostSize = Vector2.Zero;
|
||||
if (Level.Loaded.StartOutpost != null)
|
||||
{
|
||||
startOutpostSize = Level.Loaded.StartOutpost.Borders.Size.ToVector2();
|
||||
}
|
||||
submarine.SetPosition(
|
||||
Level.Loaded.StartOutpost.WorldPosition -
|
||||
new Vector2(0.0f, outpostBorders.Height / 2 + subBorders.Height / 2));
|
||||
|
||||
//find the port that's the nearest to the outpost and dock if one is found
|
||||
float closestDistance = 0.0f;
|
||||
DockingPort myPort = null, outPostPort = null;
|
||||
foreach (DockingPort port in DockingPort.List)
|
||||
{
|
||||
if (port.IsHorizontal) { continue; }
|
||||
if (port.Item.Submarine == level.StartOutpost)
|
||||
{
|
||||
outPostPort = port;
|
||||
continue;
|
||||
}
|
||||
if (port.Item.Submarine != submarine) { continue; }
|
||||
|
||||
//the submarine port has to be at the top of the sub
|
||||
if (port.Item.WorldPosition.Y < submarine.WorldPosition.Y) { continue; }
|
||||
|
||||
float dist = Vector2.DistanceSquared(port.Item.WorldPosition, level.StartOutpost.WorldPosition);
|
||||
if (myPort == null || dist < closestDistance)
|
||||
{
|
||||
myPort = port;
|
||||
closestDistance = dist;
|
||||
}
|
||||
}
|
||||
|
||||
if (myPort != null && outPostPort != null)
|
||||
{
|
||||
Vector2 portDiff = myPort.Item.WorldPosition - submarine.WorldPosition;
|
||||
submarine.SetPosition((outPostPort.Item.WorldPosition - portDiff) - Vector2.UnitY * outPostPort.DockedDistance);
|
||||
myPort.Dock(outPostPort);
|
||||
myPort.Lock(true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
submarine.SetPosition(submarine.FindSpawnPos(level.StartPosition));
|
||||
}
|
||||
}
|
||||
|
||||
Entity.Spawner = new EntitySpawner();
|
||||
@@ -224,6 +277,7 @@ namespace Barotrauma
|
||||
if (GameMode.Mission != null) Mission.Start(Level.Loaded);
|
||||
|
||||
EventManager.StartRound(level);
|
||||
SteamAchievementManager.OnStartRound();
|
||||
|
||||
if (GameMode != null)
|
||||
{
|
||||
@@ -237,23 +291,44 @@ namespace Barotrauma
|
||||
GameAnalyticsManager.AddDesignEvent("Submarine:" + submarine.Name);
|
||||
GameAnalyticsManager.AddDesignEvent("Level", ToolBox.StringToInt(level.Seed));
|
||||
GameAnalyticsManager.AddProgressionEvent(GameAnalyticsSDK.Net.EGAProgressionStatus.Start,
|
||||
GameMode.Name, (Mission == null ? "None" : Mission.GetType().ToString()));
|
||||
GameMode.Preset.Identifier, (Mission == null ? "None" : Mission.GetType().ToString()));
|
||||
|
||||
|
||||
#if CLIENT
|
||||
if (GameMode is SinglePlayerCampaign) SteamAchievementManager.OnBiomeDiscovered(level.Biome);
|
||||
roundSummary = new RoundSummary(this);
|
||||
|
||||
GameMain.GameScreen.ColorFade(Color.Black, Color.TransparentBlack, 5.0f);
|
||||
SoundPlayer.SwitchMusic();
|
||||
|
||||
if (!(GameMode is TutorialMode))
|
||||
{
|
||||
GUI.AddMessage("", Color.Transparent, 3.0f, playSound: false);
|
||||
GUI.AddMessage(level.Biome.Name, Color.Lerp(Color.CadetBlue, Color.DarkRed, level.Difficulty / 100.0f), 5.0f, playSound: false);
|
||||
GUI.AddMessage(TextManager.Get("Destination") + ": " + EndLocation.Name, Color.CadetBlue, playSound: false);
|
||||
GUI.AddMessage(TextManager.Get("Mission") + ": " + (Mission == null ? TextManager.Get("None") : Mission.Name), Color.CadetBlue, playSound: false);
|
||||
}
|
||||
#endif
|
||||
|
||||
RoundStartTime = Timing.TotalTime;
|
||||
}
|
||||
|
||||
public void Update(float deltaTime)
|
||||
{
|
||||
EventManager.Update(deltaTime);
|
||||
GameMode?.Update(deltaTime);
|
||||
Mission?.Update(deltaTime);
|
||||
|
||||
UpdateProjSpecific(deltaTime);
|
||||
}
|
||||
|
||||
partial void UpdateProjSpecific(float deltaTime);
|
||||
|
||||
public void EndRound(string endMessage)
|
||||
{
|
||||
if (Mission != null) Mission.End();
|
||||
GameAnalyticsManager.AddProgressionEvent(
|
||||
(Mission == null || Mission.Completed) ? GameAnalyticsSDK.Net.EGAProgressionStatus.Complete : GameAnalyticsSDK.Net.EGAProgressionStatus.Fail,
|
||||
GameMode.Name,
|
||||
GameMode.Preset.Identifier,
|
||||
(Mission == null ? "None" : Mission.GetType().ToString()));
|
||||
|
||||
#if CLIENT
|
||||
@@ -261,12 +336,16 @@ namespace Barotrauma
|
||||
{
|
||||
GUIFrame summaryFrame = roundSummary.CreateSummaryFrame(endMessage);
|
||||
GUIMessageBox.MessageBoxes.Add(summaryFrame);
|
||||
var okButton = new GUIButton(new Rectangle(0, 20, 100, 30), "Ok", Alignment.BottomRight, "", summaryFrame.children[0]);
|
||||
okButton.OnClicked = (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return true; };
|
||||
var okButton = new GUIButton(new RectTransform(new Vector2(0.2f, 1.0f), summaryFrame.Children.First().Children.First().FindChild("buttonarea").RectTransform),
|
||||
TextManager.Get("OK"))
|
||||
{
|
||||
OnClicked = (GUIButton button, object obj) => { GUIMessageBox.MessageBoxes.Remove(summaryFrame); return true; }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
EventManager.EndRound();
|
||||
SteamAchievementManager.OnRoundEnded(this);
|
||||
|
||||
currentMission = null;
|
||||
|
||||
@@ -308,9 +387,9 @@ namespace Barotrauma
|
||||
{
|
||||
doc.Save(filePath);
|
||||
}
|
||||
catch
|
||||
catch (Exception e)
|
||||
{
|
||||
DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!");
|
||||
DebugConsole.ThrowError("Saving gamesession to \"" + filePath + "\" failed!", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user