2f107db...5202af9

This commit is contained in:
Joonas Rikkonen
2019-03-18 21:42:26 +02:00
parent 58c92888b7
commit 044fd3344b
395 changed files with 27417 additions and 19754 deletions
@@ -14,8 +14,8 @@ namespace Barotrauma
const int InitialMoney = 4500;
private bool watchmenSpawned;
private Character startWatchman, endWatchman;
protected bool watchmenSpawned;
protected Character startWatchman, endWatchman;
//key = dialog flag, double = Timing.TotalTime when the line was last said
private Dictionary<string, double> dialogLastSpoken = new Dictionary<string, double>();
@@ -76,13 +76,18 @@ namespace Barotrauma
{
base.Update(deltaTime);
if (GameMain.Client != null || !IsRunning) { return; }
if (!IsRunning) { return; }
#if CLIENT
if (GameMain.Client != null) { return; }
#endif
if (!watchmenSpawned)
{
if (Level.Loaded.StartOutpost != null) { startWatchman = SpawnWatchman(Level.Loaded.StartOutpost); }
if (Level.Loaded.EndOutpost != null) { endWatchman = SpawnWatchman(Level.Loaded.EndOutpost); }
watchmenSpawned = true;
#if SERVER
(this as MultiPlayerCampaign).LastUpdateID++;
#endif
}
else
{
@@ -133,13 +138,7 @@ namespace Barotrauma
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.UseHealthWindow = false;
spawnedCharacter.CharacterHealth.Unkillable = true;
spawnedCharacter.CanInventoryBeAccessed = false;
spawnedCharacter.CanBeDragged = false;
spawnedCharacter.SetCustomInteract(
WatchmanInteract,
hudText: TextManager.Get("TalkHint").Replace("[key]", GameMain.Config.KeyBind(InputType.Select).ToString()));
InitializeWatchman(spawnedCharacter);
(spawnedCharacter.AIController as HumanAIController)?.ObjectiveManager.SetOrder(
new AIObjectiveGoTo(watchmanSpawnpoint, spawnedCharacter, repeat: true, getDivingGearIfNeeded: false));
if (watchmanJob != null)
@@ -149,6 +148,18 @@ namespace Barotrauma
return spawnedCharacter;
}
protected void InitializeWatchman(Character character)
{
character.CharacterHealth.UseHealthWindow = false;
character.CharacterHealth.Unkillable = true;
character.CanInventoryBeAccessed = false;
character.CanBeDragged = false;
character.TeamID = Character.TeamType.FriendlyNPC;
character.SetCustomInteract(
WatchmanInteract,
hudText: TextManager.Get("TalkHint").Replace("[key]", GameMain.Config.KeyBind(InputType.Select).ToString()));
}
protected abstract void WatchmanInteract(Character watchman, Character interactor);
public abstract void Save(XElement element);
@@ -1,33 +1,36 @@
using Barotrauma.Items.Components;
using Barotrauma.Networking;
using Lidgren.Network;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Barotrauma.Networking;
using System.Xml.Linq;
namespace Barotrauma
{
class CharacterCampaignData
partial class CharacterCampaignData
{
public readonly CharacterInfo CharacterInfo;
public CharacterInfo CharacterInfo
{
get;
private set;
}
public readonly string Name;
public readonly bool IsHostCharacter;
public readonly string ClientIP;
public readonly ulong SteamID;
public string ClientIP
{
get;
private set;
}
public ulong SteamID
{
get;
private set;
}
private XElement itemData;
partial void InitProjSpecific(Client client);
public CharacterCampaignData(Client client)
{
Name = client.Name;
ClientIP = client.Connection.RemoteEndPoint.Address.ToString();
SteamID = client.SteamID;
CharacterInfo = client.CharacterInfo;
InitProjSpecific(client);
if (client.Character.Inventory != null)
{
@@ -35,32 +38,16 @@ namespace Barotrauma
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)
Name = element.GetAttributeString("name", "Unnamed");
ClientIP = element.GetAttributeString("ip", "");
string steamID = element.GetAttributeString("steamid", "");
if (!string.IsNullOrEmpty(steamID))
{
ClientIP = element.GetAttributeString("ip", "");
string steamID = element.GetAttributeString("steamid", "");
if (!string.IsNullOrEmpty(steamID))
{
ulong.TryParse(steamID, out SteamID);
}
ulong.TryParse(steamID, out ulong parsedID);
SteamID = parsedID;
}
foreach (XElement subElement in element.Elements())
@@ -78,33 +65,12 @@ namespace Barotrauma
}
}
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));
}
XElement element = new XElement("CharacterCampaignData",
new XAttribute("name", Name),
new XAttribute("ip", ClientIP),
new XAttribute("steamid", SteamID));
CharacterInfo?.Save(element);
@@ -114,11 +80,6 @@ namespace Barotrauma
}
return element;
}
public void SpawnInventoryItems(CharacterInfo characterInfo, Inventory inventory)
{
characterInfo.SpawnInventoryItems(inventory, itemData);
}
}
}
}
@@ -69,12 +69,11 @@ namespace Barotrauma
#if CLIENT
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."
};
#endif
new GameModePreset("sandbox", typeof(GameMode), false)
{
Description = "A game mode with no specific objectives."
@@ -87,7 +86,9 @@ namespace Barotrauma
+ "when the task is completed or everyone in the crew has died."
};
//new GameModePreset("multiplayercampaign", typeof(MultiPlayerCampaign), false, false);
#if DEBUG
new GameModePreset("multiplayercampaign", typeof(MultiPlayerCampaign), false, false);
#endif
}
}
}
@@ -14,14 +14,26 @@ namespace Barotrauma
private UInt16 lastUpdateID;
public UInt16 LastUpdateID
{
get { if (GameMain.Server != null && lastUpdateID < 1) lastUpdateID++; return lastUpdateID; }
get
{
#if SERVER
if (GameMain.Server != null && lastUpdateID < 1) lastUpdateID++;
#endif
return lastUpdateID;
}
set { lastUpdateID = value; }
}
private UInt16 lastSaveID;
public UInt16 LastSaveID
{
get { if (GameMain.Server != null && lastSaveID < 1) lastSaveID++; return lastSaveID; }
get
{
#if SERVER
if (GameMain.Server != null && lastSaveID < 1) lastSaveID++;
#endif
return lastSaveID;
}
set { lastSaveID = value; }
}
@@ -47,124 +59,34 @@ namespace Barotrauma
CampaignID = currentCampaignID;
}
private void SetDelegates()
{
if (GameMain.Server != null)
{
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();
lastUpdateID++;
if (GameMain.NetworkMember.IsServer) lastUpdateID++;
}
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;
#if CLIENT
if (GameMain.Client != null)
{
GameMain.GameSession.EndRound("");
#if CLIENT
GameMain.GameSession.CrewManager.EndRound();
#endif
return;
}
#endif
#if SERVER
lastUpdateID++;
bool success =
GameMain.Server.ConnectedClients.Any(c => c.InGame && c.Character != null && !c.Character.IsDead) ||
(GameMain.Server.Character != null && !GameMain.Server.Character.IsDead);
bool success =
GameMain.Server.ConnectedClients.Any(c => c.InGame && c.Character != null && !c.Character.IsDead);
#if CLIENT
success = success || (GameMain.Server.Character != null && !GameMain.Server.Character.IsDead);
#endif
/*if (success)
{
@@ -194,21 +116,9 @@ namespace Barotrauma
}
}
#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
}
c.Inventory?.DeleteAllItems();
}
//remove all items that are in someone's inventory
@@ -250,8 +160,11 @@ namespace Barotrauma
SaveUtil.SaveGame(GameMain.GameSession.SavePath);
}
#endif
}
partial void SetDelegates();
public static MultiPlayerCampaign LoadNew(XElement element)
{
MultiPlayerCampaign campaign = new MultiPlayerCampaign(GameModePreset.List.Find(gm => gm.Identifier == "multiplayercampaign"), null);
@@ -310,23 +223,13 @@ namespace Barotrauma
}
}
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.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
characterData.Add(new CharacterCampaignData(subElement));
}
}
@@ -356,76 +259,5 @@ namespace Barotrauma
lastSaveID++;
}
public void ServerWrite(NetBuffer msg, Client c)
{
System.Diagnostics.Debug.Assert(map.Locations.Count < UInt16.MaxValue);
msg.Write(CampaignID);
msg.Write(lastUpdateID);
msg.Write(lastSaveID);
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);
}
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>();
for (int i = 0; i < purchasedItemCount; i++)
{
UInt16 itemPrefabIndex = msg.ReadUInt16();
UInt16 itemQuantity = msg.ReadUInt16();
purchasedItems.Add(new PurchasedItem(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab, itemQuantity));
}
if (!sender.HasPermission(ClientPermissions.ManageCampaign))
{
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, pi.Quantity);
}
foreach (PurchasedItem pi in purchasedItems)
{
CargoManager.PurchaseItem(pi.ItemPrefab, pi.Quantity);
}
}
}
}
@@ -1,188 +0,0 @@
using Barotrauma.Networking;
using System.Collections.Generic;
using System.IO;
namespace Barotrauma
{
partial class Traitor
{
public readonly Character Character;
public Character TargetCharacter; //TODO: make a modular objective system (similar to crew missions) that allows for things OTHER than assasinations.
public Traitor(Character character)
{
Character = character;
}
public void Greet(GameServer server, string codeWords, string codeResponse)
{
string greetingMessage = TextManager.Get("TraitorStartMessage").Replace("[targetname]", TargetCharacter.Name);
string moreAgentsMessage = TextManager.Get("TraitorMoreAgentsMessage")
.Replace("[codewords]", codeWords)
.Replace("[coderesponse]", codeResponse);
if (server.Character != Character)
{
var greetingChatMsg = ChatMessage.Create(null, greetingMessage, ChatMessageType.Server, null);
var moreAgentsChatMsg = ChatMessage.Create(null, moreAgentsMessage, ChatMessageType.Server, null);
var greetingMsgBox = ChatMessage.Create(null, greetingMessage, ChatMessageType.MessageBox, null);
var moreAgentsMsgBox = ChatMessage.Create(null, moreAgentsMessage, ChatMessageType.MessageBox, null);
Client client = server.ConnectedClients.Find(c => c.Character == Character);
GameMain.Server.SendDirectChatMessage(greetingChatMsg, client);
GameMain.Server.SendDirectChatMessage(moreAgentsChatMsg, client);
GameMain.Server.SendDirectChatMessage(greetingMsgBox, client);
GameMain.Server.SendDirectChatMessage(moreAgentsMsgBox, client);
}
#if CLIENT
if (server.Character == null)
{
new GUIMessageBox(
TextManager.Get("NewTraitor"),
TextManager.Get("TraitorStartMessageServer").Replace("[targetname]", TargetCharacter.Name).Replace("[traitorname]", Character.Name));
}
else if (server.Character == Character)
{
new GUIMessageBox("", greetingMessage);
new GUIMessageBox("", moreAgentsMessage);
GameMain.NetworkMember.AddChatMessage(greetingMessage, ChatMessageType.Server);
GameMain.NetworkMember.AddChatMessage(moreAgentsMessage, ChatMessageType.Server);
return;
}
#endif
}
}
partial class TraitorManager
{
private static string wordsTxt = Path.Combine("Content", "CodeWords.txt");
public List<Traitor> TraitorList
{
get { return traitorList; }
}
private List<Traitor> traitorList = new List<Traitor>();
public string codeWords, codeResponse;
public TraitorManager(GameServer server, int traitorCount)
{
if (traitorCount < 1) //what why how
{
traitorCount = 1;
DebugConsole.ThrowError("Traitor Manager: TraitorCount somehow ended up less than 1, setting it to 1.");
}
Start(server, traitorCount);
}
private void Start(GameServer server, int traitorCount)
{
if (server == null) return;
List<Character> characters = new List<Character>(); //ANYONE can be a target.
List<Character> traitorCandidates = new List<Character>(); //Keep this to not re-pick traitors twice
foreach (Client client in server.ConnectedClients)
{
if (client.Character != null)
{
characters.Add(client.Character);
traitorCandidates.Add(client.Character);
}
}
if (server.Character != null)
{
characters.Add(server.Character); //Add host character
traitorCandidates.Add(server.Character);
}
if (characters.Count < 2)
{
return;
}
codeWords = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt);
codeResponse = ToolBox.GetRandomLine(wordsTxt) + ", " + ToolBox.GetRandomLine(wordsTxt);
while (traitorCount-- > 0)
{
if (traitorCandidates.Count <= 0) break;
int traitorIndex = Rand.Int(traitorCandidates.Count);
Character traitorCharacter = traitorCandidates[traitorIndex];
traitorCandidates.Remove(traitorCharacter);
//Add them to the list
traitorList.Add(new Traitor(traitorCharacter));
}
//Now that traitors have been decided, let's do objectives in post for deciding things like Document Exchange.
foreach (Traitor traitor in traitorList)
{
Character traitorCharacter = traitor.Character;
int targetIndex = Rand.Int(characters.Count);
while (characters[targetIndex] == traitorCharacter) //Cannot target self
{
targetIndex = Rand.Int(characters.Count);
}
Character targetCharacter = characters[targetIndex];
traitor.TargetCharacter = targetCharacter;
traitor.Greet(server, codeWords, codeResponse);
}
}
public string GetEndMessage()
{
if (GameMain.Server == null || traitorList.Count <= 0) return "";
string endMessage = "";
foreach (Traitor traitor in traitorList)
{
Character traitorCharacter = traitor.Character;
Character targetCharacter = traitor.TargetCharacter;
string messageTag;
if (targetCharacter.IsDead) //Partial or complete mission success
{
if (traitorCharacter.IsDead)
{
messageTag = "TraitorEndMessageSuccessTraitorDead";
}
else if (traitorCharacter.LockHands)
{
messageTag = "TraitorEndMessageSuccessTraitorDetained";
}
else
messageTag = "TraitorEndMessageSuccess";
}
else //Partial or complete failure
{
if (traitorCharacter.IsDead)
{
messageTag = "TraitorEndMessageFailureTraitorDead";
}
else if (traitorCharacter.LockHands)
{
messageTag = "TraitorEndMessageFailureTraitorDetained";
}
else
{
messageTag = "TraitorEndMessageFailure";
}
}
endMessage += (TextManager.ReplaceGenderPronouns(TextManager.Get(messageTag), traitorCharacter.Info.Gender) + "\n")
.Replace("[traitorname]", traitorCharacter.Name)
.Replace("[targetname]", targetCharacter.Name);
}
return endMessage;
}
}
}