Merge branch 'dev' of https://github.com/Regalis11/Barotrauma.git into unstable-tests

This commit is contained in:
Evil Factory
2022-04-08 12:52:28 -03:00
990 changed files with 44338 additions and 38589 deletions
@@ -29,7 +29,8 @@ namespace Barotrauma
public virtual IEnumerable<string> CompletedTextKeys => new string[] { };
public virtual IEnumerable<string> CompletedTextValues(Traitor traitor) => new string[] { };
protected virtual string FormatText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values) => TextManager.FormatServerMessageWithGenderPronouns(traitor?.Character?.Info?.Gender ?? Gender.None, textId, keys, values);
protected virtual string FormatText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values)
=> TextManager.FormatServerMessageWithPronouns(traitor.Character.Info, textId, keys.Zip(values, (k,v) => (k,v)).ToArray());
protected internal virtual string GetStatusText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values) => FormatText(traitor, textId, keys, values);
protected internal virtual string GetInfoText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values) => FormatText(traitor, textId, keys, values);
@@ -51,11 +51,11 @@ namespace Barotrauma
{
continue;
}
var identifierMatches = matchIdentifier && item.prefab.Identifier == tag;
var identifierMatches = matchIdentifier && ((MapEntity)item).Prefab.Identifier == tag;
if (identifierMatches && tagPrefabName == null)
{
var textId = item.Prefab.GetItemNameTextId();
tagPrefabName = textId != null ? TextManager.FormatServerMessage(textId) : item.Prefab.Name;
tagPrefabName = textId != null ? TextManager.FormatServerMessage(textId) : item.Prefab.Name.Value;
}
if (identifierMatches || (matchTag && item.HasTag(tag)))
{
@@ -28,7 +28,7 @@ namespace Barotrauma
private enum EntityTypes { Character, Item }
private string[] entities;
private Identifier[] entities;
private EntityTypes[] entityTypes;
public override void Update(float deltaTime)
@@ -67,7 +67,7 @@ namespace Barotrauma
{
continue;
}
if (character.SpeciesName.Equals(entities[activeEntityIndex], StringComparison.OrdinalIgnoreCase) && Vector2.Distance(activeEntitySavedPosition, character.WorldPosition) < graceDistance)
if (character.SpeciesName == entities[activeEntityIndex] && Vector2.Distance(activeEntitySavedPosition, character.WorldPosition) < graceDistance)
{
activeEntity = character;
transformationTime = 0.0;
@@ -82,7 +82,7 @@ namespace Barotrauma
{
continue;
}
if (item.prefab.Identifier == entities[activeEntityIndex] && Vector2.Distance(activeEntitySavedPosition, item.WorldPosition) < graceDistance)
if (((MapEntity)item).Prefab.Identifier == entities[activeEntityIndex] && Vector2.Distance(activeEntitySavedPosition, item.WorldPosition) < graceDistance)
{
activeEntity = item;
transformationTime = 0.0;
@@ -117,7 +117,7 @@ namespace Barotrauma
{
continue;
}
if (character.SpeciesName.Equals(entities[activeEntityIndex], StringComparison.OrdinalIgnoreCase))
if (character.SpeciesName == entities[activeEntityIndex])
{
activeEntity = character;
break;
@@ -131,7 +131,7 @@ namespace Barotrauma
{
continue;
}
if (item.prefab.Identifier.Equals(entities[0], StringComparison.OrdinalIgnoreCase))
if (((MapEntity)item).Prefab.Identifier == entities[0])
{
activeEntity = item;
break;
@@ -146,7 +146,7 @@ namespace Barotrauma
public GoalEntityTransformation(string[] entities, string[] entityTypes, string catalystItemIdentifier) : base()
{
this.entities = entities;
this.entities = entities.ToIdentifiers().ToArray();
this.entityTypes = new EntityTypes[entityTypes.Length];
@@ -15,7 +15,7 @@ namespace Barotrauma
private readonly bool preferNew;
private readonly bool allowNew;
private readonly bool allowExisting;
private readonly HashSet<string> allowedContainerIdentifiers = new HashSet<string>();
private readonly HashSet<Identifier> allowedContainerIdentifiers = new HashSet<Identifier>();
private ItemPrefab targetPrefab;
private ItemPrefab containedPrefab;
@@ -83,7 +83,7 @@ namespace Barotrauma
{
continue;
}
if (item.GetComponent<ItemContainer>() != null && allowedContainerIdentifiers.Contains(item.prefab.Identifier))
if (item.GetComponent<ItemContainer>() != null && allowedContainerIdentifiers.Contains(((MapEntity)item).Prefab.Identifier))
{
if ((includeNew && !item.OwnInventory.IsFull()) || (includeExisting && item.OwnInventory.FindItemByIdentifier(targetPrefabCandidate.Identifier) != null))
{
@@ -166,7 +166,7 @@ namespace Barotrauma
targetPrefabTextId = targetPrefab.GetItemNameTextId();
}
targetNameText = targetPrefabTextId != null ? TextManager.FormatServerMessage(targetPrefabTextId) : targetPrefab.Name;
targetNameText = targetPrefabTextId != null ? TextManager.FormatServerMessage(targetPrefabTextId) : targetPrefab.Name.Value;
targetContainer = FindTargetContainer(Traitors, targetPrefab);
if (targetContainer == null)
{
@@ -175,9 +175,9 @@ namespace Barotrauma
return false;
}
var containerPrefabTextId = targetContainer.Prefab.GetItemNameTextId();
targetContainerNameText = containerPrefabTextId != null ? TextManager.FormatServerMessage(containerPrefabTextId) : targetContainer.Prefab.Name;
var targetHullTextId = targetContainer.CurrentHull?.prefab.GetHullNameTextId();
targetHullNameText = targetHullTextId != null ? TextManager.FormatServerMessage(targetHullTextId) : targetContainer?.CurrentHull?.DisplayName ?? "";
targetContainerNameText = containerPrefabTextId != null ? TextManager.FormatServerMessage(containerPrefabTextId) : targetContainer.Prefab.Name.Value;
var targetHullTextId = targetContainer.CurrentHull?.Prefab.GetHullNameTextId();
targetHullNameText = targetHullTextId != null ? TextManager.FormatServerMessage(targetHullTextId) : targetContainer?.CurrentHull?.DisplayName.Value ?? "";
if (allowNew && !targetContainer.OwnInventory.IsFull())
{
existingItems.Clear();
@@ -185,7 +185,7 @@ namespace Barotrauma
{
existingItems.Add(item);
}
Entity.Spawner.AddToSpawnQueue(targetPrefab, targetContainer.OwnInventory, onSpawned: item =>
Entity.Spawner.AddItemToSpawnQueue(targetPrefab, targetContainer.OwnInventory, onSpawned: item =>
{
item.AddTag("traitormissionitem");
});
@@ -216,7 +216,7 @@ namespace Barotrauma
{
for (int i = 0; i < spawnAmount; i++)
{
Entity.Spawner.AddToSpawnQueue(containedPrefab, target.OwnInventory);
Entity.Spawner.AddItemToSpawnQueue(containedPrefab, target.OwnInventory);
}
}
existingItems.Clear();
@@ -224,7 +224,7 @@ namespace Barotrauma
}
}
public GoalFindItem(TraitorMission.CharacterFilter filter, string identifier, bool preferNew, bool allowNew, bool allowExisting, float percentage, params string[] allowedContainerIdentifiers)
public GoalFindItem(TraitorMission.CharacterFilter filter, string identifier, bool preferNew, bool allowNew, bool allowExisting, float percentage, params Identifier[] allowedContainerIdentifiers)
{
this.filter = filter;
this.identifier = identifier;
@@ -21,7 +21,7 @@ namespace Barotrauma
base.Update(deltaTime);
var validHullsCount = 0;
var floodingAmount = 0.0f;
foreach (Hull hull in Hull.hullList)
foreach (Hull hull in Hull.HullList)
{
if (hull.Submarine == null || hull.Submarine.Info.IsOutpost || Traitors.All(traitor => hull.Submarine.TeamID != traitor.Character.TeamID)) { continue; }
if (hull.Submarine == GameMain.Server?.RespawnManager?.RespawnShuttle) { continue; }
@@ -15,7 +15,7 @@ namespace Barotrauma
private bool isCompleted;
private const float gracePeriod = 1f;
private string speciesId;
private Identifier speciesId;
private string targetCharacterName;
private Character targetCharacter;
private float timer;
@@ -52,7 +52,7 @@ namespace Barotrauma
{
continue;
}
if (character.SpeciesName.Equals(speciesId, StringComparison.OrdinalIgnoreCase))
if (character.SpeciesName == speciesId)
{
targetCharacter = character;
break;
@@ -64,9 +64,9 @@ namespace Barotrauma
return targetCharacter != null;
}
public GoalKeepTransformedAlive(string speciesId) : base()
public GoalKeepTransformedAlive(Identifier speciesId) : base()
{
this.speciesId = speciesId.ToLowerInvariant();
this.speciesId = speciesId;
}
}
}
@@ -13,12 +13,12 @@ namespace Barotrauma
public override IEnumerable<string> InfoTextKeys => base.InfoTextKeys.Concat(new string[] { "[targetname]", "[causeofdeath]", "[targethullname]" });
public override IEnumerable<string> InfoTextValues(Traitor traitor) => base.InfoTextValues(traitor).Concat(new string[]
{ traitor.Mission.GetTargetNames(Targets) ?? "(unknown)", GetCauseOfDeath(), targetHull != null ? TextManager.Get($"roomname.{targetHull}") : string.Empty });
{ traitor.Mission.GetTargetNames(Targets) ?? "(unknown)", GetCauseOfDeath().Value, targetHull != null ? TextManager.Get($"roomname.{targetHull}").Value : string.Empty });
private bool isCompleted = false;
public override bool IsCompleted => isCompleted;
public override bool IsEnemy(Character character) => base.IsEnemy(character) || (!isCompleted && Targets.Contains(character));
public override bool IsEnemy(Character character) => base.IsEnemy(character) || (!isCompleted && Targets.Contains(character));
private CauseOfDeathType requiredCauseOfDeath;
private string afflictionId;
@@ -102,7 +102,7 @@ namespace Barotrauma
return true;
}
private string GetCauseOfDeath()
private LocalizedString GetCauseOfDeath()
{
if (requiredCauseOfDeath != CauseOfDeathType.Affliction || afflictionId == string.Empty)
{
@@ -8,8 +8,8 @@ namespace Barotrauma
{
public class GoalReplaceInventory : HumanoidGoal
{
private readonly HashSet<string> sabotageContainerIds = new HashSet<string>();
private readonly HashSet<string> validReplacementIds = new HashSet<string>();
private readonly HashSet<Identifier> sabotageContainerIds = new HashSet<Identifier>();
private readonly HashSet<Identifier> validReplacementIds = new HashSet<Identifier>();
private readonly float replaceAmount;
@@ -33,7 +33,7 @@ namespace Barotrauma
{
continue;
}
if (sabotageContainerIds.Contains(item.prefab.Identifier))
if (sabotageContainerIds.Contains(((MapEntity)item).Prefab.Identifier))
{
++totalAmount;
if (item.OwnInventory.AllItems.All(containedItem => !validReplacementIds.Contains(containedItem.Prefab.Identifier)))
@@ -59,7 +59,7 @@ namespace Barotrauma
return true;
}
public GoalReplaceInventory(string[] containerIds, string[] replacementIds, float replaceAmount)
public GoalReplaceInventory(Identifier[] containerIds, Identifier[] replacementIds, float replaceAmount)
{
sabotageContainerIds.UnionWith(containerIds);
validReplacementIds.UnionWith(replacementIds);
@@ -37,15 +37,10 @@ namespace Barotrauma
targetItems.Add(item);
}
}
//only target items in the main sub if there are any
if (targetItems.Count > 1 && targetItems.Any(it => it.Submarine == Submarine.MainSub))
{
targetItems.RemoveAll(it => it.Submarine != Submarine.MainSub);
}
if (targetItems.Count > 0)
{
var textId = targetItems[0].Prefab.GetItemNameTextId();
targetItemPrefabName = TextManager.FormatServerMessage(textId) ?? targetItems[0].Prefab.Name;
targetItemPrefabName = TextManager.FormatServerMessage(textId) ?? targetItems[0].Prefab.Name.Value;
}
return targetItems.Count > 0;
}
@@ -46,7 +46,7 @@ namespace Barotrauma
if (targetConnectionPanels.Count > 0)
{
var textId = targetConnectionPanels[0].Item.Prefab.GetItemNameTextId();
targetItemPrefabName = TextManager.FormatServerMessage(textId) ?? targetConnectionPanels[0].Item.Prefab.Name;
targetItemPrefabName = TextManager.FormatServerMessage(textId) ?? targetConnectionPanels[0].Item.Prefab.Name.Value;
}
return targetConnectionPanels.Count > 0;
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
namespace Barotrauma
@@ -14,12 +15,13 @@ namespace Barotrauma
public override IEnumerable<string> InfoTextKeys => base.InfoTextKeys.Concat(new string[] { "[duration]" });
public override IEnumerable<string> InfoTextValues(Traitor traitor) => base.InfoTextValues(traitor).Concat(new string[] { requiredDuration.ToString() });
public override IEnumerable<string> InfoTextValues(Traitor traitor) => base.InfoTextValues(traitor).Concat(new string[] { requiredDuration.ToString(CultureInfo.InvariantCulture) });
protected internal override string GetInfoText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values)
{
var infoText = base.GetInfoText(traitor, textId, keys, values);
return !string.IsNullOrEmpty(durationInfoTextId) && !infoText.Contains("[duration]") ? TextManager.FormatServerMessage(durationInfoTextId, new[] { "[infotext]", "[duration]" }, new[] { infoText, requiredDuration.ToString() }) : infoText;
return !string.IsNullOrEmpty(durationInfoTextId) && !infoText.Contains("[duration]") ? TextManager.FormatServerMessage(durationInfoTextId,
("[infotext]", infoText), ("[duration]", requiredDuration.ToString(CultureInfo.InvariantCulture))) : infoText;
}
private bool isCompleted = false;
@@ -17,7 +17,7 @@ namespace Barotrauma
protected internal override string GetInfoText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values)
{
var infoText = base.GetInfoText(traitor, textId, keys, values);
return !string.IsNullOrEmpty(timeLimitInfoTextId) ? TextManager.FormatServerMessage(timeLimitInfoTextId, new[] { "[infotext]", "[timelimit]" }, new[] { infoText, $"{TimeSpan.FromSeconds(timeLimit):g}" }) : infoText;
return !string.IsNullOrEmpty(timeLimitInfoTextId) ? TextManager.FormatServerMessage(timeLimitInfoTextId, ("[infotext]", infoText), ("[timelimit]", $"{TimeSpan.FromSeconds(timeLimit):g}")) : infoText;
}
public override bool CanBeCompleted(ICollection<Traitor> traitors) => base.CanBeCompleted(traitors) && (!Traitors.Any(IsStarted) || timeRemaining > 0.0f);
@@ -14,7 +14,7 @@ namespace Barotrauma
public override IEnumerable<string> StatusTextValues(Traitor traitor)
{
var values = base.StatusTextValues(traitor).ToArray();
values[1] = TextManager.GetServerMessage(StatusValueTextId);
values[1] = TextManager.FormatServerMessage(StatusValueTextId);
return values;
}
@@ -24,7 +24,7 @@ namespace Barotrauma
protected internal override string GetInfoText(Traitor traitor, string textId, IEnumerable<string> keys, IEnumerable<string> values)
{
var infoText = base.GetInfoText(traitor, textId, keys, values);
return !string.IsNullOrEmpty(optionalInfoTextId) ? TextManager.FormatServerMessage(optionalInfoTextId, new[] { "[infotext]" }, new[] { infoText }) : infoText;
return !string.IsNullOrEmpty(optionalInfoTextId) ? TextManager.FormatServerMessage(optionalInfoTextId, ("[infotext]", infoText)) : infoText;
}
public GoalIsOptional(Goal goal, string optionalInfoTextId) : base(goal)
@@ -30,7 +30,7 @@ namespace Barotrauma
}
public override IEnumerable<string> StatusTextKeys => Goal.StatusTextKeys;
public override IEnumerable<string> StatusTextValues(Traitor traitor) => new [] { InfoText(traitor), TextManager.FormatServerMessage(StatusValueTextId) };
public override IEnumerable<string> StatusTextValues(Traitor traitor) => new string[] { InfoText(traitor), TextManager.FormatServerMessage(StatusValueTextId) };
public override IEnumerable<string> InfoTextKeys => Goal.InfoTextKeys;
public override IEnumerable<string> InfoTextValues(Traitor traitor) => Goal.InfoTextValues(traitor);
@@ -39,7 +39,7 @@ namespace Barotrauma
{
var statusText = goal.StatusText(Traitor);
var startIndex = statusText.LastIndexOf('/') + 1;
return $"{statusText.Substring(0, startIndex)}[{index}.st]={statusText.Substring(startIndex)}/[{index}.sl]={TextManager.FormatServerMessage(GoalInfoFormatId, new string[] { "[statustext]" }, new string[] { $"[{index}.st]" })}";
return $"{statusText.Substring(0, startIndex)}[{index}.st]={statusText.Substring(startIndex)}/[{index}.sl]={TextManager.FormatServerMessage(GoalInfoFormatId, ("[statustext]", $"[{index}.st]"))}";
}).ToArray()),
string.Join("", activeGoals.Select((goal, index) => $"[{index}.sl]").ToArray()));
@@ -49,7 +49,7 @@ namespace Barotrauma
{
var statusText = goal.StatusText(Traitor);
var startIndex = statusText.LastIndexOf('/') + 1;
return $"{statusText.Substring(0, startIndex)}[{index}.st]={statusText.Substring(startIndex)}/[{index}.sl]={TextManager.FormatServerMessage(GoalInfoFormatId, new string[] { "[statustext]" }, new string[] { $"[{index}.st]" })}";
return $"{statusText.Substring(0, startIndex)}[{index}.st]={statusText.Substring(startIndex)}/[{index}.sl]={TextManager.FormatServerMessage(GoalInfoFormatId, ("[statustext]", $"[{index}.st]"))}";
}).ToArray()),
string.Join("", allGoals.Select((goal, index) => $"[{index}.sl]").ToArray()));
@@ -57,13 +57,14 @@ namespace Barotrauma
public virtual IEnumerable<string> StartMessageKeys => new string[] { "[traitorgoalinfos]" };
public virtual IEnumerable<string> StartMessageValues => new string[] { GoalInfos };
public virtual string StartMessageText => TextManager.FormatServerMessageWithGenderPronouns(Traitor?.Character?.Info?.Gender ?? Gender.None, StartMessageTextId, StartMessageKeys, StartMessageValues);
public virtual LocalizedString StartMessageText
=> TextManager.FormatServerMessageWithPronouns(Traitor.Character.Info, StartMessageTextId, StartMessageKeys.Zip(StartMessageValues, (k,v) => (k,v)).ToArray());
public virtual string StartMessageServerTextId { get; set; } = "TraitorObjectiveStartMessageServer";
public virtual IEnumerable<string> StartMessageServerKeys => StartMessageKeys.Concat(new string[] { "[traitorname]" });
public virtual IEnumerable<string> StartMessageServerValues => StartMessageValues.Concat(new string[] { Traitor?.Character?.Name ?? "(unknown)" });
public virtual string StartMessageServerText => TextManager.FormatServerMessageWithGenderPronouns(Traitor?.Character?.Info?.Gender ?? Gender.None, StartMessageServerTextId, StartMessageServerKeys, StartMessageServerValues);
public virtual LocalizedString StartMessageServerText => TextManager.FormatServerMessageWithPronouns(Traitor.Character.Info, StartMessageServerTextId, StartMessageServerKeys.Zip(StartMessageServerValues, (k,v) => (k,v)).ToArray());
public virtual string EndMessageSuccessTextId { get; set; } = "TraitorObjectiveEndMessageSuccess";
public virtual string EndMessageSuccessDeadTextId { get; set; } = "TraitorObjectiveEndMessageSuccessDead";
@@ -83,7 +84,7 @@ namespace Barotrauma
var messageId = IsCompleted
? (traitorIsDead ? EndMessageSuccessDeadTextId : traitorIsDetained ? EndMessageSuccessDetainedTextId : EndMessageSuccessTextId)
: (traitorIsDead ? EndMessageFailureDeadTextId : traitorIsDetained ? EndMessageFailureDetainedTextId : EndMessageFailureTextId);
return TextManager.FormatServerMessageWithGenderPronouns(Traitor?.Character?.Info?.Gender ?? Gender.None, messageId, EndMessageKeys.ToArray(), EndMessageValues.ToArray());
return TextManager.FormatServerMessageWithPronouns(Traitor.Character.Info, messageId, EndMessageKeys.Zip(EndMessageValues, (k,v)=>(k,v)).ToArray());
}
}
@@ -133,21 +134,21 @@ namespace Barotrauma
IsStarted = true;
traitor.SendChatMessageBox(StartMessageText, traitor.Mission?.Identifier);
traitor.UpdateCurrentObjective(GoalInfos, traitor.Mission?.Identifier);
traitor.SendChatMessageBox(StartMessageText.Value, traitor.Mission.Identifier);
traitor.UpdateCurrentObjective(GoalInfos, traitor.Mission.Identifier);
return true;
}
public void StartMessage()
{
Traitor.SendChatMessage(StartMessageText, Traitor.Mission?.Identifier);
Traitor.SendChatMessage(StartMessageText.Value, Traitor.Mission.Identifier);
}
public void EndMessage()
{
Traitor.SendChatMessageBox(EndMessageText, Traitor.Mission?.Identifier);
Traitor.SendChatMessage(EndMessageText, Traitor.Mission?.Identifier);
Traitor.SendChatMessageBox(EndMessageText, Traitor.Mission.Identifier);
Traitor.SendChatMessage(EndMessageText, Traitor.Mission.Identifier);
}
public void Update(float deltaTime)
@@ -170,12 +171,12 @@ namespace Barotrauma
pendingGoals.RemoveAt(i);
if (GameMain.Server != null)
{
Traitor.SendChatMessage(goal.CompletedText(Traitor), Traitor.Mission?.Identifier);
Traitor.SendChatMessage(goal.CompletedText(Traitor), Traitor.Mission.Identifier);
if (pendingGoals.Count > 0)
{
Traitor.SendChatMessageBox(goal.CompletedText(Traitor), Traitor.Mission?.Identifier);
Traitor.SendChatMessageBox(goal.CompletedText(Traitor), Traitor.Mission.Identifier);
}
Traitor.UpdateCurrentObjective(GoalInfos, Traitor.Mission?.Identifier);
Traitor.UpdateCurrentObjective(GoalInfos, Traitor.Mission.Identifier);
}
}
}
@@ -16,43 +16,41 @@ namespace Barotrauma
Role = role;
Character = character;
Character.IsTraitor = true;
GameMain.NetworkMember.CreateEntityEvent(Character, new object[] { NetEntityEvent.Type.Status });
GameMain.NetworkMember.CreateEntityEvent(Character, new Character.CharacterStatusEventData());
}
public delegate void MessageSender(string message);
public void Greet(GameServer server, string codeWords, string codeResponse, MessageSender messageSender)
{
string greetingMessage = TextManager.FormatServerMessage(Mission.StartText, new string[] {
"[codewords]", "[coderesponse]"
}, new string[] {
codeWords, codeResponse
});
string greetingMessage = TextManager.FormatServerMessage(Mission.StartText,
("[codewords]", codeWords),
("[coderesponse]", codeResponse));
messageSender(greetingMessage);
Client traitorClient = server.ConnectedClients.Find(c => c.Character == Character);
Client ownerClient = server.ConnectedClients.Find(c => c.Connection == server.OwnerConnection);
if (traitorClient != ownerClient && ownerClient != null && ownerClient.Character == null)
{
GameMain.Server.SendTraitorMessage(ownerClient, CurrentObjective.StartMessageServerText, Mission?.Identifier, TraitorMessageType.ServerMessageBox);
GameMain.Server.SendTraitorMessage(ownerClient, CurrentObjective.StartMessageServerText.Value, Mission.Identifier, TraitorMessageType.ServerMessageBox);
}
}
public void SendChatMessage(string serverText, string iconIdentifier)
public void SendChatMessage(string serverText, Identifier iconIdentifier)
{
Client traitorClient = GameMain.Server.ConnectedClients.Find(c => c.Character == Character);
GameMain.Server.SendTraitorMessage(traitorClient, serverText, iconIdentifier, TraitorMessageType.Server);
}
public void SendChatMessageBox(string serverText, string iconIdentifier)
public void SendChatMessageBox(string serverText, Identifier iconIdentifier)
{
Client traitorClient = GameMain.Server.ConnectedClients.Find(c => c.Character == Character);
GameMain.Server.SendTraitorMessage(traitorClient, serverText, iconIdentifier, TraitorMessageType.ServerMessageBox);
}
public void UpdateCurrentObjective(string objectiveText, string iconIdentifier)
public void UpdateCurrentObjective(string objectiveText, Identifier iconIdentifier)
{
Client traitorClient = GameMain.Server.ConnectedClients.Find(c => c.Character == Character);
Character.TraitorCurrentObjective = objectiveText;
GameMain.Server.SendTraitorMessage(traitorClient, Character.TraitorCurrentObjective, iconIdentifier, TraitorMessageType.Objective);
GameMain.Server.SendTraitorMessage(traitorClient, Character.TraitorCurrentObjective.Value, iconIdentifier, TraitorMessageType.Objective);
}
}
}
@@ -169,7 +169,8 @@ namespace Barotrauma
else
{
var mission = TraitorMissionPrefab.RandomPrefab()?.Instantiate();
if (mission != null) {
if (mission != null)
{
if (mission.CanBeStarted(server, this, CharacterTeamType.None))
{
if (mission.Start(server, this, CharacterTeamType.None))
@@ -43,7 +43,7 @@ namespace Barotrauma
public string GlobalEndMessageFailureDeadTextId { get; private set; }
public string GlobalEndMessageFailureDetainedTextId { get; private set; }
public readonly string Identifier;
public readonly Identifier Identifier;
public virtual IEnumerable<string> GlobalEndMessageKeys => new string[] { "[traitorname]", "[traitorgoalinfos]" };
public virtual IEnumerable<string> GlobalEndMessageValues {
@@ -60,7 +60,7 @@ namespace Barotrauma
{
get
{
if (Traitors.Any() && allObjectives.Count > 0)
if (Traitors.Any() && allObjectives.Count > 0)
{
return TextManager.JoinServerMessages("\n",
Traitors.Values.Select(traitor =>
@@ -71,7 +71,7 @@ namespace Barotrauma
var messageId = isSuccess
? (traitorIsDead ? GlobalEndMessageSuccessDeadTextId : traitorIsDetained ? GlobalEndMessageSuccessDetainedTextId : GlobalEndMessageSuccessTextId)
: (traitorIsDead ? GlobalEndMessageFailureDeadTextId : traitorIsDetained ? GlobalEndMessageFailureDetainedTextId : GlobalEndMessageFailureTextId);
return TextManager.FormatServerMessageWithGenderPronouns(traitor.Character?.Info?.Gender ?? Gender.None, messageId, GlobalEndMessageKeys.ToArray(), GlobalEndMessageValues.ToArray());
return TextManager.FormatServerMessageWithPronouns(traitor.Character.Info, messageId, GlobalEndMessageKeys.Zip(GlobalEndMessageValues).ToArray());
}).ToArray());
}
return "";
@@ -384,7 +384,7 @@ namespace Barotrauma
}
}
public TraitorMission(string identifier, string startText, string globalEndMessageSuccessTextId, string globalEndMessageSuccessDeadTextId, string globalEndMessageSuccessDetainedTextId, string globalEndMessageFailureTextId, string globalEndMessageFailureDeadTextId, string globalEndMessageFailureDetainedTextId, IEnumerable<KeyValuePair<string, RoleFilter>> roles, ICollection<Objective> objectives)
public TraitorMission(Identifier identifier, string startText, string globalEndMessageSuccessTextId, string globalEndMessageSuccessDeadTextId, string globalEndMessageSuccessDetainedTextId, string globalEndMessageFailureTextId, string globalEndMessageFailureDeadTextId, string globalEndMessageFailureDetainedTextId, IEnumerable<KeyValuePair<string, RoleFilter>> roles, ICollection<Objective> objectives)
{
Identifier = identifier;
StartText = startText;
@@ -9,38 +9,27 @@ namespace Barotrauma
{
class TraitorMissionPrefab
{
public class TraitorMissionEntry
public class TraitorMissionEntry : Prefab
{
public static PrefabCollection<TraitorMissionEntry> Prefabs => TraitorMissionPrefab.Prefabs;
public readonly TraitorMissionPrefab Prefab;
public float SelectedWeight;
public TraitorMissionEntry(XElement element)
public TraitorMissionEntry(ContentXElement element, TraitorMissionsFile file) : base(file, element)
{
Prefab = new TraitorMissionPrefab(element);
}
}
public static readonly List<TraitorMissionEntry> List = new List<TraitorMissionEntry>();
public static void Init()
{
var files = GameMain.Instance.GetFilesOfType(ContentType.TraitorMissions);
foreach (ContentFile file in files)
{
XDocument doc = XMLExtensions.TryLoadXml(file.Path);
if (doc?.Root == null) continue;
foreach (XElement element in doc.Root.Elements())
{
List.Add(new TraitorMissionEntry(element));
}
}
public override void Dispose() { }
}
public static readonly PrefabCollection<TraitorMissionEntry> Prefabs = new PrefabCollection<TraitorMissionEntry>();
public static TraitorMissionPrefab RandomPrefab()
{
var selected = ToolBox.SelectWeightedRandom(List, List.Select(mission => Math.Max(mission.SelectedWeight, 0.1f)).ToList(), TraitorManager.Random);
var selected = ToolBox.SelectWeightedRandom(Prefabs.ToList(), Prefabs.Select(mission => Math.Max(mission.SelectedWeight, 0.1f)).ToList(), TraitorManager.Random);
//the weight of the missions that didn't get selected keeps growing the make them more likely to get picked
foreach (var mission in List)
foreach (var mission in Prefabs)
{
mission.SelectedWeight += 10;
}
@@ -103,7 +92,7 @@ namespace Barotrauma
private delegate bool TargetFilter(string value, Character character);
private static Dictionary<string, TargetFilter> targetFilters = new Dictionary<string, TargetFilter>()
{
{ "job", (value, character) => value.Equals(character.Info.Job.Prefab.Identifier, StringComparison.OrdinalIgnoreCase) },
{ "job", (value, character) => value == character.Info.Job.Prefab.Identifier },
{ "role", (value, character) => value.Equals(GameMain.Server.TraitorManager.GetTraitorRole(character), StringComparison.OrdinalIgnoreCase) }
};
@@ -180,12 +169,29 @@ namespace Barotrauma
itemCountFilters.Add((character) => filter(attribute.Value, character));
}
}
goal = new Traitor.GoalFindItem((character) => itemCountFilters.All(f => f(character)), Config.GetAttributeString("identifier", null), Config.GetAttributeBool("preferNew", true), Config.GetAttributeBool("allowNew", true), Config.GetAttributeBool("allowExisting", true), Config.GetAttributeFloat("percentage", -1f), Config.GetAttributeStringArray("allowedContainers", new string[] {"steelcabinet", "mediumsteelcabinet", "suppliescabinet"}));
goal = new Traitor.GoalFindItem((character) => itemCountFilters.All(f => f(character)),
Config.GetAttributeString("identifier",
null),
Config.GetAttributeBool("preferNew",
true),
Config.GetAttributeBool("allowNew",
true),
Config.GetAttributeBool("allowExisting",
true),
Config.GetAttributeFloat("percentage",
-1f),
Config.GetAttributeIdentifierArray("allowedContainers",
new string[]
{
"steelcabinet",
"mediumsteelcabinet",
"suppliescabinet"
}.ToIdentifiers()));
break;
case "replaceinventory":
checker.Required("containers", "replacements");
checker.Optional("percentage");
goal = new Traitor.GoalReplaceInventory(Config.GetAttributeStringArray("containers", new string[] { }), Config.GetAttributeStringArray("replacements", new string[] { }), Config.GetAttributeFloat("percentage", 100.0f) / 100.0f);
goal = new Traitor.GoalReplaceInventory(Config.GetAttributeIdentifierArray("containers", new Identifier[] { }), Config.GetAttributeIdentifierArray("replacements", new Identifier[] { }), Config.GetAttributeFloat("percentage", 100.0f) / 100.0f);
break;
case "reachdistancefromsub":
checker.Optional("distance");
@@ -221,7 +227,7 @@ namespace Barotrauma
break;
case "keeptransformedalive":
checker.Required("speciesname");
goal = new Traitor.GoalKeepTransformedAlive(Config.GetAttributeString("speciesname", null));
goal = new Traitor.GoalKeepTransformedAlive(Config.GetAttributeIdentifier("speciesname", Identifier.Empty));
break;
default:
GameServer.Log($"Unrecognized goal type \"{goalType}\".", ServerLog.MessageType.Error);
@@ -425,7 +431,7 @@ namespace Barotrauma
}
public readonly Dictionary<string, Role> Roles = new Dictionary<string, Role>();
public readonly string Identifier;
public readonly Identifier Identifier;
public readonly string StartText;
public readonly string EndMessageSuccessText;
public readonly string EndMessageSuccessDeadText;
@@ -575,14 +581,14 @@ namespace Barotrauma
if (jobs != null)
{
var jobsSet = new HashSet<string>(jobs.Select(job => job.ToLower(CultureInfo.InvariantCulture)));
filters.Add(character => character.Info?.Job != null && jobsSet.Contains(character.Info.Job.Name.ToLower(CultureInfo.InvariantCulture)));
filters.Add(character => character.Info?.Job != null && jobsSet.Contains(character.Info.Job.Name.ToLower().Value));
}
return new Role(filters);
}
public TraitorMissionPrefab(XElement missionRoot)
public TraitorMissionPrefab(ContentXElement missionRoot)
{
Identifier = missionRoot.GetAttributeString("identifier", null);
Identifier = missionRoot.GetAttributeIdentifier("identifier", Identifier.Empty);
foreach (var element in missionRoot.Elements())
{
using (var checker = new AttributeChecker(element))