(d9829ac) v0.9.4.0

This commit is contained in:
Regalis
2019-10-24 18:05:42 +02:00
parent 9aa12bcac2
commit b39922a074
319 changed files with 12516 additions and 6815 deletions
@@ -1,12 +1,12 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Xml.Linq;
using System.Linq;
using Barotrauma.Extensions;
using Barotrauma.Networking;
namespace Barotrauma {
namespace Barotrauma
{
class TraitorMissionPrefab
{
public class TraitorMissionEntry
@@ -98,6 +98,7 @@ namespace Barotrauma {
private static Dictionary<string, TargetFilter> targetFilters = new Dictionary<string, TargetFilter>()
{
{ "job", (value, character) => value.Equals(character.Info.Job.Prefab.Identifier, StringComparison.OrdinalIgnoreCase) },
{ "role", (value, character) => value.Equals(GameMain.Server.TraitorManager.GetTraitorRole(character), StringComparison.OrdinalIgnoreCase) }
};
public Traitor.Goal Instantiate()
@@ -256,7 +257,16 @@ namespace Barotrauma {
}
}
public class Objective
public abstract class ObjectiveBase
{
public HashSet<string> Roles { get; } = new HashSet<string>();
public abstract void InstantiateGoals();
public abstract Traitor.Objective Instantiate(IEnumerable<string> roles);
}
protected class Objective : ObjectiveBase
{
public string InfoText { get; internal set; }
public string StartMessageTextId { get; internal set; }
@@ -271,16 +281,24 @@ namespace Barotrauma {
public readonly List<Goal> Goals = new List<Goal>();
public Traitor.Objective Instantiate()
private List<Traitor.Goal> goalInstances = null;
public override void InstantiateGoals()
{
var result = new Traitor.Objective(InfoText, ShuffleGoalsCount, Goals.ConvertAll(goal => {
goalInstances = Goals.ConvertAll(goal =>
{
var instance = goal.Instantiate();
if (instance == null)
{
GameServer.Log($"Failed to instantiate goal \"{goal.Type}\".", ServerLog.MessageType.Error);
}
return instance;
}).FindAll(goal => goal != null).ToArray());
}).FindAll(goal => goal != null);
}
public override Traitor.Objective Instantiate(IEnumerable<string> roles)
{
var result = new Traitor.Objective(InfoText, ShuffleGoalsCount, roles.ToArray(), goalInstances);
if (StartMessageTextId != null)
{
result.StartMessageTextId = StartMessageTextId;
@@ -316,14 +334,43 @@ namespace Barotrauma {
return result;
}
}
/*
public class Role
protected class WaitObjective : ObjectiveBase
{
public string Job;
private Traitor.GoalWaitForTraitors sharedGoal;
public override void InstantiateGoals()
{
sharedGoal = new Traitor.GoalWaitForTraitors(Roles.Count);
}
public override Traitor.Objective Instantiate(IEnumerable<string> roles)
{
return new Traitor.Objective("TraitorObjectiveInfoTextWaitForOtherTraitors", -1, roles.ToArray(), new[] { sharedGoal });
}
public WaitObjective(ICollection<string> roles)
{
Roles.UnionWith(roles);
}
}
public class Role
{
public readonly Traitor.TraitorMission.RoleFilter Filter;
public Role(IEnumerable<Traitor.TraitorMission.RoleFilter> filters)
{
Filter = character => filters.All(filter => filter(character));
}
public Role()
{
Filter = character => true;
}
}
public readonly Dictionary<string, Role> Roles = new Dictionary<string, Role>();
*/
public readonly string Identifier;
public readonly string StartText;
public readonly string EndMessageSuccessText;
@@ -333,11 +380,43 @@ namespace Barotrauma {
public readonly string EndMessageFailureDeadText;
public readonly string EndMessageFailureDetainedText;
public readonly List<Objective> Objectives = new List<Objective>();
public readonly List<ObjectiveBase> Objectives = new List<ObjectiveBase>();
public Traitor.TraitorMission Instantiate()
{
var objectivesWithSync = new List<ObjectiveBase>();
var objectivesCount = Objectives.Count;
if (objectivesCount > 0)
{
var pendingRoles = new HashSet<string>();
var pendingCount = 1;
objectivesWithSync.Add(Objectives[0]);
pendingRoles.UnionWith(Objectives[0].Roles);
for (var i = 1; i < objectivesCount; ++i)
{
var objective = Objectives[i];
if (pendingRoles.IsSupersetOf(objective.Roles))
{
if (pendingCount > 1)
{
objectivesWithSync.Add(new WaitObjective(objective.Roles));
}
pendingRoles.Clear();
pendingCount = 0;
}
objectivesWithSync.Add(objective);
pendingRoles.UnionWith(objective.Roles);
++pendingCount;
}
if (pendingCount > 1 && pendingRoles.IsSubsetOf(Roles.Keys))
{
// TODO: If last objective includes only one traitor, other traitors will get the wrong end message.
objectivesWithSync.Add(new WaitObjective(Roles.Keys));
}
}
return new Traitor.TraitorMission(
Identifier,
StartText ?? "TraitorMissionStartMessage",
EndMessageSuccessText ?? "TraitorObjectiveEndMessageSuccess",
EndMessageSuccessDeadText ?? "TraitorObjectiveEndMessageSuccessDead",
@@ -345,7 +424,12 @@ namespace Barotrauma {
EndMessageFailureText ?? "TraitorObjectiveEndMessageFailure",
EndMessageFailureDeadText ?? "TraitorObjectiveEndMessageFailureDead",
EndMessageFailureDetainedText ?? "TraitorObjectiveEndMessageFailureDetained",
Objectives.ConvertAll(objective => objective.Instantiate()).ToArray());
Roles.ToDictionary(kv => kv.Key, kv => kv.Value.Filter),
objectivesWithSync.SelectMany(objective =>
{
objective.InstantiateGoals();
return objective.Roles.Select(role => objective.Instantiate(new[] { role }));
}).ToArray());
}
protected Goal LoadGoal(XElement goalRoot)
@@ -354,10 +438,22 @@ namespace Barotrauma {
return new Goal(goalType, goalRoot);
}
protected Objective LoadObjective(XElement objectiveRoot)
{
var result = new Objective();
result.ShuffleGoalsCount = objectiveRoot.GetAttributeInt("shuffleGoalsCount", -1);
protected Objective LoadObjective(XElement objectiveRoot, string[] allRoles)
{
var allRolesSet = new HashSet<string>(allRoles);
var result = new Objective
{
ShuffleGoalsCount = objectiveRoot.GetAttributeInt("shuffleGoalsCount", -1)
};
var objectiveRoles = objectiveRoot.GetAttributeStringArray("roles", allRoles);
if (!allRolesSet.IsSupersetOf(objectiveRoles))
{
var unrecognized = new HashSet<string>(objectiveRoles);
unrecognized.ExceptWith(allRoles);
GameServer.Log($"Undefined role(s) \"{string.Join(", ", unrecognized)}\" set for Objective.", ServerLog.MessageType.Error);
}
result.Roles.UnionWith(allRolesSet.Intersect(objectiveRoles));
foreach (var element in objectiveRoot.Elements())
{
using (var checker = new AttributeChecker(element))
@@ -410,7 +506,7 @@ namespace Barotrauma {
break;
}
default:
GameServer.Log($"Unrecognized element \"{element.Name}\"under Objective.", ServerLog.MessageType.Error);
GameServer.Log($"Unrecognized element \"{element.Name}\" under Objective.", ServerLog.MessageType.Error);
break;
}
}
@@ -418,6 +514,18 @@ namespace Barotrauma {
return result;
}
protected Role LoadRole(XElement roleRoot)
{
var filters = new List<Traitor.TraitorMission.RoleFilter>();
var jobs = roleRoot.GetAttributeStringArray("jobs", null);
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)));
}
return new Role(filters);
}
public TraitorMissionPrefab(XElement missionRoot)
{
Identifier = missionRoot.GetAttributeString("identifier", null);
@@ -427,6 +535,27 @@ namespace Barotrauma {
{
switch (element.Name.ToString().ToLowerInvariant())
{
case "role":
checker.Required("id");
checker.Optional("jobs");
Roles.Add(element.GetAttributeString("id", null), LoadRole(element));
break;
}
}
}
if (!Roles.Any())
{
Roles.Add("traitor", new Role());
}
foreach (var element in missionRoot.Elements())
{
using (var checker = new AttributeChecker(element))
{
switch (element.Name.ToString().ToLowerInvariant())
{
case "role":
// handled above
break;
case "startinfotext":
checker.Required("id");
StartText = element.GetAttributeString("id", null);
@@ -457,7 +586,7 @@ namespace Barotrauma {
break;
case "objective":
{
var objective = LoadObjective(element);
var objective = LoadObjective(element, Roles.Keys.ToArray());
if (objective != null)
{
Objectives.Add(objective);