v1.1.18.0 (Treacherous Tides Update)

This commit is contained in:
Regalis11
2023-10-19 19:28:43 +03:00
parent 34ffc520cc
commit df7e8f1625
21 changed files with 196 additions and 89 deletions
@@ -1,14 +1,13 @@
#nullable enable #nullable enable
using Barotrauma.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Xml.Linq; using System.Xml.Linq;
using Barotrauma.Extensions;
using Barotrauma.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Directory = System.IO.Directory; using Directory = System.IO.Directory;
namespace Barotrauma namespace Barotrauma
@@ -37,7 +36,9 @@ namespace Barotrauma
private OutpostGenerationParams? lastTestParam; private OutpostGenerationParams? lastTestParam;
private LocationType? lastTestType; private LocationType? lastTestType;
private int CreateID() private GUITickBox? isTraitorEventBox;
private static int CreateID()
{ {
int maxId = nodeList.Any() ? nodeList.Max(node => node.ID) : 0; int maxId = nodeList.Any() ? nodeList.Max(node => node.ID) : 0;
return ++maxId; return ++maxId;
@@ -54,8 +55,8 @@ namespace Barotrauma
private void CreateGUI() private void CreateGUI()
{ {
GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.4f), GUI.Canvas) { MinSize = new Point(300, 400) }); GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.4f), GUI.Canvas) { MinSize = new Point(300, 420) });
GUILayoutGroup layoutGroup = new GUILayoutGroup(RectTransform(0.9f, 0.9f, GuiFrame, Anchor.Center)) { Stretch = true }; GUILayoutGroup layoutGroup = new GUILayoutGroup(RectTransform(0.9f, 0.9f, GuiFrame, Anchor.Center)) { Stretch = true, AbsoluteSpacing = GUI.IntScale(5) };
// === BUTTONS === // // === BUTTONS === //
GUILayoutGroup buttonLayout = new GUILayoutGroup(RectTransform(1.0f, 0.50f, layoutGroup)) { RelativeSpacing = 0.04f }; GUILayoutGroup buttonLayout = new GUILayoutGroup(RectTransform(1.0f, 0.50f, layoutGroup)) { RelativeSpacing = 0.04f };
@@ -99,13 +100,18 @@ namespace Barotrauma
GUIButton addSpecialButton = new GUIButton(RectTransform(0.2f, 1.0f, addSpecialDropdownLayout), TextManager.Get("EventEditor.Add")); GUIButton addSpecialButton = new GUIButton(RectTransform(0.2f, 1.0f, addSpecialDropdownLayout), TextManager.Get("EventEditor.Add"));
// Add event prefabs with identifiers to the list // Add event prefabs with identifiers to the list
foreach (EventPrefab eventPrefab in EventSet.GetAllEventPrefabs().Where(prefab => !prefab.Identifier.IsEmpty).Distinct()) foreach (EventPrefab eventPrefab in EventSet.GetAllEventPrefabs().Where(p => !p.Identifier.IsEmpty).Distinct().OrderBy(p => p.Identifier))
{ {
loadDropdown.AddItem(eventPrefab.Identifier.Value!, eventPrefab); if (!typeof(ScriptedEvent).IsAssignableFrom(eventPrefab.EventType)) { continue; }
var textBlock = loadDropdown.AddItem(eventPrefab.Identifier.Value!, eventPrefab) as GUITextBlock;
if (eventPrefab is TraitorEventPrefab && textBlock != null)
{
textBlock.TextColor = Color.MediumPurple;
}
} }
// Add all types that inherit the EventAction class // Add all types that inherit the EventAction class
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(EventAction)))) foreach (Type type in Assembly.GetExecutingAssembly().GetTypes().Where(type => type.IsSubclassOf(typeof(EventAction))).OrderBy(t => t.Name))
{ {
addActionDropdown.AddItem(type.Name, type); addActionDropdown.AddItem(type.Name, type);
} }
@@ -149,6 +155,9 @@ namespace Barotrauma
FileSelection.Open = true; FileSelection.Open = true;
return true; return true;
}; };
isTraitorEventBox = new GUITickBox(RectTransform(1.0f, 0.125f, layoutGroup), "Traitor event");
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight); screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
} }
@@ -304,7 +313,10 @@ namespace Barotrauma
nodeList.Clear(); nodeList.Clear();
selectedNodes.Clear(); selectedNodes.Clear();
markedNodes.Clear(); markedNodes.Clear();
if (isTraitorEventBox != null)
{
isTraitorEventBox.Selected = prefab is TraitorEventPrefab;
}
bool hadNodes = true; bool hadNodes = true;
CreateNodes(prefab.ConfigElement, ref hadNodes); CreateNodes(prefab.ConfigElement, ref hadNodes);
if (!hadNodes) if (!hadNodes)
@@ -409,17 +421,18 @@ namespace Barotrauma
} }
var parentElement = subElement.Parent; var parentElement = subElement.Parent;
foreach (var xElement in subElement.Elements()) foreach (var xElement in subElement.Elements())
{ {
if (xElement.Name.ToString().ToLowerInvariant() == "option") switch (xElement.Name.ToString().ToLowerInvariant())
{ {
EventEditorNodeConnection optionConnection = new EventEditorNodeConnection(newNode, NodeConnectionType.Option) case "option":
{ EventEditorNodeConnection optionConnection = new EventEditorNodeConnection(newNode, NodeConnectionType.Option)
OptionText = xElement.GetAttributeString("text", string.Empty), {
EndConversation = xElement.GetAttributeBool("endconversation", false) OptionText = xElement.GetAttributeString("text", string.Empty),
}; EndConversation = xElement.GetAttributeBool("endconversation", false)
newNode.Connections.Add(optionConnection); };
newNode.Connections.Add(optionConnection);
break;
} }
} }
@@ -466,37 +479,48 @@ namespace Barotrauma
} }
} }
if (parentElement?.FirstElement() == subElement) if (subElement.Name.ToString().ToLowerInvariant() is "text" or "conditional")
{ {
switch (parentElement?.Name.ToString().ToLowerInvariant()) parent?.AddConnection(NodeConnectionType.Add);
{ parent?.Connect(newNode, NodeConnectionType.Add);
case "failure":
parent?.Connect(newNode, NodeConnectionType.Failure);
break;
case "success":
parent?.Connect(newNode, NodeConnectionType.Success);
break;
case "option":
if (parent != null)
{
EventEditorNodeConnection? activateConnection = newNode.Connections.Find(connection => connection.Type == NodeConnectionType.Activate);
EventEditorNodeConnection? optionConnection = parent.Connections.FirstOrDefault(connection =>
connection.Type == NodeConnectionType.Option && string.Equals(connection.OptionText, parentElement.GetAttributeString("text", string.Empty), StringComparison.Ordinal));
if (activateConnection != null)
{
optionConnection?.ConnectedTo.Add(activateConnection);
}
}
break;
default:
parent?.Connect(newNode, NodeConnectionType.Add);
break;
}
} }
else else
{ {
lastNode?.Connect(newNode, NodeConnectionType.Next); if (parentElement?.FirstElement() == subElement)
{
switch (parentElement?.Name.ToString().ToLowerInvariant())
{
case "failure":
parent?.Connect(newNode, NodeConnectionType.Failure);
break;
case "success":
parent?.Connect(newNode, NodeConnectionType.Success);
break;
case "onroundendaction":
parent?.Connect(newNode, NodeConnectionType.Next);
break;
case "option":
if (parent != null)
{
EventEditorNodeConnection? activateConnection = newNode.Connections.Find(connection => connection.Type == NodeConnectionType.Activate);
EventEditorNodeConnection? optionConnection = parent.Connections.FirstOrDefault(connection =>
connection.Type == NodeConnectionType.Option && string.Equals(connection.OptionText, parentElement.GetAttributeString("text", string.Empty), StringComparison.Ordinal));
if (activateConnection != null)
{
optionConnection?.ConnectedTo.Add(activateConnection);
}
}
break;
default:
parent?.Connect(newNode, NodeConnectionType.Add);
break;
}
}
else
{
lastNode?.Connect(newNode, NodeConnectionType.Next);
}
} }
lastNode = newNode; lastNode = newNode;
@@ -542,7 +566,9 @@ namespace Barotrauma
private XElement? ExportXML() private XElement? ExportXML()
{ {
XElement mainElement = new XElement("ScriptedEvent", new XAttribute("identifier", projectName.RemoveWhitespace().ToLowerInvariant())); XElement mainElement = new XElement(
isTraitorEventBox is { Selected: true } ? nameof(TraitorEvent) : nameof(ScriptedEvent),
new XAttribute("identifier", projectName.RemoveWhitespace().ToLowerInvariant()));
EditorNode? startNode = null; EditorNode? startNode = null;
foreach (EditorNode eventNode in nodeList.Where(node => node is EventNode || node is SpecialNode)) foreach (EditorNode eventNode in nodeList.Where(node => node is EventNode || node is SpecialNode))
{ {
@@ -614,7 +640,7 @@ namespace Barotrauma
} }
} }
private XElement SaveEvent(string name) private static XElement SaveEvent(string name)
{ {
XElement mainElement = new XElement("SavedEvent", new XAttribute("name", name)); XElement mainElement = new XElement("SavedEvent", new XAttribute("name", name));
XElement nodes = new XElement("Nodes"); XElement nodes = new XElement("Nodes");
@@ -635,7 +661,7 @@ namespace Barotrauma
return mainElement; return mainElement;
} }
private void Load(XElement saveElement) private static void Load(XElement saveElement)
{ {
nodeList.Clear(); nodeList.Clear();
projectName = saveElement.GetAttributeString("name", TextManager.Get("EventEditor.Unnamed").Value); projectName = saveElement.GetAttributeString("name", TextManager.Get("EventEditor.Unnamed").Value);
@@ -671,7 +697,7 @@ namespace Barotrauma
} }
} }
private void CreateContextMenu(EditorNode node, EventEditorNodeConnection? connection = null) private static void CreateContextMenu(EditorNode node, EventEditorNodeConnection? connection = null)
{ {
if (GUIContextMenu.CurrentContextMenu != null) { return; } if (GUIContextMenu.CurrentContextMenu != null) { return; }
@@ -884,8 +910,8 @@ namespace Barotrauma
XElement? eventXml = ExportXML(); XElement? eventXml = ExportXML();
EventPrefab? prefab; EventPrefab? prefab;
if (eventXml != null) if (eventXml != null)
{ {
prefab = new EventPrefab(eventXml.FromPackage(null), null); prefab = EventPrefab.Create(eventXml.FromPackage(null), file: null);
} }
else else
{ {
@@ -13,7 +13,7 @@ namespace Barotrauma
Identifier eventIdentifier = msg.ReadIdentifier(); Identifier eventIdentifier = msg.ReadIdentifier();
if (GameMain.Client?.Character == null) if (GameMain.Client?.Character == null)
{ {
DebugConsole.ThrowError("Received a traitor update when not controlling a character."); DebugConsole.AddSafeError("Received a traitor update when not controlling a character.");
return; return;
} }
GameMain.Client.Character.IsTraitor = true; GameMain.Client.Character.IsTraitor = true;
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>1.1.15.0</Version> <Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright> <Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>1.1.15.0</Version> <Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright> <Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product> <Product>Barotrauma</Product>
<Version>1.1.15.0</Version> <Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright> <Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName> <AssemblyName>Barotrauma</AssemblyName>
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>1.1.15.0</Version> <Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright> <Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
+1 -1
View File
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>1.1.15.0</Version> <Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright> <Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -152,8 +152,6 @@ namespace Barotrauma
.Where(e => playerCount >= e.MinPlayerCount) .Where(e => playerCount >= e.MinPlayerCount)
.ToList(); .ToList();
var minDangerLevelPrefabs = suitablePrefabs.FindAll(e => e.DangerLevel == TraitorEventPrefab.MinDangerLevel);
if (!suitablePrefabs.Any()) if (!suitablePrefabs.Any())
{ {
//this is normal, there e.g. might be no missions for an abandoned outpost or end level //this is normal, there e.g. might be no missions for an abandoned outpost or end level
@@ -161,14 +159,13 @@ namespace Barotrauma
return false; return false;
} }
foreach (var previousEvent in previousTraitorEvents.DistinctBy(e => e.Traitor).Reverse()) foreach (var previousEvent in previousTraitorEvents.Reverse<PreviousTraitorEvent>().DistinctBy(e => e.Traitor))
{ {
if (previousEvent.State == TraitorEvent.State.Completed && if (previousEvent.State == TraitorEvent.State.Completed &&
previousEvent.TraitorEvent.DangerLevel < maxDangerLevel &&
previousEvent.TraitorEvent.IsChainable && previousEvent.TraitorEvent.IsChainable &&
IsClientViableTraitor(previousEvent.Traitor)) IsClientViableTraitor(previousEvent.Traitor))
{ {
GameServer.Log($"{NetworkMember.ClientLogName(previousEvent.Traitor)} successfully completed a traitor event on a previous round. Attempting to give choose them a new, more dangerous event...", ServerLog.MessageType.Traitors); GameServer.Log($"{NetworkMember.ClientLogName(previousEvent.Traitor)} successfully completed a traitor event ({previousEvent.TraitorEvent.Identifier}) on a previous round. Attempting to give choose them a new, more dangerous event...", ServerLog.MessageType.Traitors);
var suitablePrefab = var suitablePrefab =
//try finding an event that's continuation from the previous one (= requires the previous one to be completed 1st) //try finding an event that's continuation from the previous one (= requires the previous one to be completed 1st)
@@ -201,7 +198,20 @@ namespace Barotrauma
} }
else else
{ {
selectedPrefab = minDangerLevelPrefabs.GetRandomByWeight(GetTraitorEventPrefabCommonness, Rand.RandSync.Unsynced); //events that are suitable as initial traitor events (not requiring some other event to be completed first)
var suitableInitialPrefabs = suitablePrefabs.FindAll(e => e.RequiredCompletedTags.None() && IsSuitableDangerLevel(e));
bool IsSuitableDangerLevel(TraitorEventPrefab prefab)
{
if (prefab.DangerLevel == TraitorEventPrefab.MinDangerLevel) { return true; }
//events that require another event to be completed are handled earlier in the method
if (prefab.RequirePreviousDangerLevelCompleted) { return false; }
return
prefab.RequiredPreviousDangerLevel < TraitorEventPrefab.MinDangerLevel ||
previousTraitorEvents.Any(e2 => e2.TraitorEvent.DangerLevel >= prefab.RequiredPreviousDangerLevel);
}
selectedPrefab = suitableInitialPrefabs.GetRandomByWeight(GetTraitorEventPrefabCommonness, Rand.RandSync.Unsynced);
if (selectedPrefab == null) if (selectedPrefab == null)
{ {
GameServer.Log($"Could not find a suitable danger level {TraitorEventPrefab.MinDangerLevel} traitor event. Choosing a random event instead.", ServerLog.MessageType.Traitors); GameServer.Log($"Could not find a suitable danger level {TraitorEventPrefab.MinDangerLevel} traitor event. Choosing a random event instead.", ServerLog.MessageType.Traitors);
@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace> <RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors> <Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product> <Product>Barotrauma Dedicated Server</Product>
<Version>1.1.15.0</Version> <Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright> <Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms> <Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName> <AssemblyName>DedicatedServer</AssemblyName>
@@ -265,7 +265,7 @@ namespace Barotrauma
{ {
if (!IgnoreAtOutpost) { return false; } if (!IgnoreAtOutpost) { return false; }
if (!Level.IsLoadedFriendlyOutpost) { return false; } if (!Level.IsLoadedFriendlyOutpost) { return false; }
if (!character.IsOnPlayerTeam) { return false; } if (!character.IsOnPlayerTeam || character.IsFriendlyNPCTurnedHostile) { return false; }
if (character.Submarine?.Info == null) { return false; } if (character.Submarine?.Info == null) { return false; }
return character.Submarine.Info.IsOutpost && character.Submarine.TeamID == CharacterTeamType.FriendlyNPC; return character.Submarine.Info.IsOutpost && character.Submarine.TeamID == CharacterTeamType.FriendlyNPC;
} }
@@ -339,6 +339,8 @@ namespace Barotrauma
public bool IsOriginallyOnPlayerTeam => originalTeamID == CharacterTeamType.Team1 || originalTeamID == CharacterTeamType.Team2; public bool IsOriginallyOnPlayerTeam => originalTeamID == CharacterTeamType.Team1 || originalTeamID == CharacterTeamType.Team2;
public bool IsFriendlyNPCTurnedHostile => originalTeamID == CharacterTeamType.FriendlyNPC && teamID == CharacterTeamType.Team2;
public bool IsInstigator => CombatAction != null && CombatAction.IsInstigator; public bool IsInstigator => CombatAction != null && CombatAction.IsInstigator;
public CombatAction CombatAction; public CombatAction CombatAction;
@@ -79,8 +79,11 @@ namespace Barotrauma
{ {
DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\". {nameof(CheckItemAction)} does't define either tags or identifiers of the item to check."); DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\". {nameof(CheckItemAction)} does't define either tags or identifiers of the item to check.");
} }
checkPercentage = element.GetAttribute(nameof(RequiredConditionalMatchPercentage)) is not null; checkPercentage = element.GetAttribute(nameof(RequiredConditionalMatchPercentage)) is not null;
if (checkPercentage && conditionals.None())
{
DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\". {nameof(CheckItemAction)} requires conditionals to be met on {requiredConditionalMatchPercentage}% of the targets, but there are no conditionals defined.");
}
if (Amount != 1 && checkPercentage) if (Amount != 1 && checkPercentage)
{ {
DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\". Cannot define both '{Amount}' and '{RequiredConditionalMatchPercentage}' in {nameof(CheckItemAction)}."); DebugConsole.ThrowError($"Error in event \"{ParentEvent.Prefab.Identifier}\". Cannot define both '{Amount}' and '{RequiredConditionalMatchPercentage}' in {nameof(CheckItemAction)}.");
@@ -134,7 +137,8 @@ namespace Barotrauma
foreach (var target in targets) foreach (var target in targets)
{ {
if (target is not Item item) { continue; } if (target is not Item item) { continue; }
if (itemTags.Any(item.HasTag) || itemIdentifierSplit.Contains(item.Prefab.Identifier)) if (itemTags.Any(item.HasTag) || itemIdentifierSplit.Contains(item.Prefab.Identifier) ||
(itemTags.None() && itemIdentifierSplit.None() && conditionals.Any()))
{ {
if (ConditionalsMatch(item, character: null)) if (ConditionalsMatch(item, character: null))
{ {
@@ -28,6 +28,9 @@ namespace Barotrauma
[Serialize(false, IsPropertySaveable.Yes)] [Serialize(false, IsPropertySaveable.Yes)]
public bool ChooseRandom { get; set; } public bool ChooseRandom { get; set; }
[Serialize(false, IsPropertySaveable.Yes, description: "Should the event continue if the TagAction can't find any valid targets?")]
public bool ContinueIfNoTargetsFound { get; set; }
[Serialize(0.0f, IsPropertySaveable.Yes, description: "If larger than 0, the specified percentage of the matching targets are tagged. Between 0-100.")] [Serialize(0.0f, IsPropertySaveable.Yes, description: "If larger than 0, the specified percentage of the matching targets are tagged. Between 0-100.")]
public float ChoosePercentage { get; set; } public float ChoosePercentage { get; set; }
@@ -279,7 +282,14 @@ namespace Barotrauma
} }
} }
isFinished = !targetNotFound; if (ContinueIfNoTargetsFound)
{
isFinished = true;
}
else
{
isFinished = !targetNotFound;
}
} }
public override string ToDebugString() public override string ToDebugString()
@@ -230,7 +230,7 @@ namespace Barotrauma
Bank = new Wallet(Option<Character>.None(), subElement); Bank = new Wallet(Option<Character>.None(), subElement);
break; break;
#if SERVER #if SERVER
case nameof(TraitorManager): case "traitormanager":
GameMain.Server?.TraitorManager?.Load(subElement); GameMain.Server?.TraitorManager?.Load(subElement);
break; break;
case "savedexperiencepoints": case "savedexperiencepoints":
@@ -443,11 +443,11 @@ namespace Barotrauma.Items.Components
// Set the contained items active if there's an item inserted inside the container. Enables e.g. the rifle flashlight when it's attached to the rifle (put inside of it). // Set the contained items active if there's an item inserted inside the container. Enables e.g. the rifle flashlight when it's attached to the rifle (put inside of it).
SetContainedActive(true); SetContainedActive(true);
} }
if (containedItem.FlippedX) if (containedItem.FlippedX != item.FlippedX)
{ {
containedItem.FlipX(relativeToSub: false); containedItem.FlipX(relativeToSub: false);
} }
if (containedItem.FlippedY) if (containedItem.FlippedY != item.FlippedY)
{ {
containedItem.FlipY(relativeToSub: false); containedItem.FlipY(relativeToSub: false);
} }
@@ -1319,17 +1319,20 @@ namespace Barotrauma
} }
} }
for (int i = 0; i < components.Count && i < clone.components.Count; i++) if (clonedContainedItems.Any())
{ {
ItemComponent component = components[i], for (int i = 0; i < components.Count && i < clone.components.Count; i++)
cloneComp = clone.components[i];
if (component is not CircuitBox origBox || cloneComp is not CircuitBox cloneBox)
{ {
continue; ItemComponent component = components[i],
} cloneComp = clone.components[i];
cloneBox.CloneFrom(origBox, clonedContainedItems); if (component is not CircuitBox origBox || cloneComp is not CircuitBox cloneBox)
{
continue;
}
cloneBox.CloneFrom(origBox, clonedContainedItems);
}
} }
clone.FullyInitialized = true; clone.FullyInitialized = true;
@@ -3230,7 +3233,7 @@ namespace Barotrauma
SetDroppedStackItemStates(); SetDroppedStackItemStates();
droppedStack = null; droppedStack = null;
#if SERVER #if SERVER
if (GameMain.NetworkMember is { IsServer: true } server) if (GameMain.NetworkMember is { IsServer: true } server && !Removed)
{ {
server.CreateEntityEvent(this, new DroppedStackEventData(Enumerable.Empty<Item>())); server.CreateEntityEvent(this, new DroppedStackEventData(Enumerable.Empty<Item>()));
} }
@@ -1379,7 +1379,7 @@ namespace Barotrauma
if (sub.Info.IsOutpost) if (sub.Info.IsOutpost)
{ {
#if CLIENT #if CLIENT
if (GameMain.GameSession.GameMode is TutorialMode) { continue; } if (GameMain.GameSession?.GameMode is TutorialMode) { continue; }
#endif #endif
OutpostGenerator.PowerUpOutpost(sub); OutpostGenerator.PowerUpOutpost(sub);
} }
@@ -2106,7 +2106,7 @@ namespace Barotrauma
DebugConsole.ThrowError("Failed to generate alien ruins. Could not find any RuinGenerationParameters!"); DebugConsole.ThrowError("Failed to generate alien ruins. Could not find any RuinGenerationParameters!");
return; return;
} }
DebugConsole.NewMessage($"Creating alien ruins using {selectedRuinGenerationParams.Identifier} (preferred difficulty: {selectedRuinGenerationParams.PreferredDifficulty}, current difficulty {Difficulty})", color: Color.Yellow); DebugConsole.NewMessage($"Creating alien ruins using {selectedRuinGenerationParams.Identifier} (preferred difficulty: {selectedRuinGenerationParams.PreferredDifficulty}, current difficulty {Difficulty})", color: Color.Yellow, debugOnly: true);
LocationType locationType = StartLocation?.Type; LocationType locationType = StartLocation?.Type;
if (locationType == null) if (locationType == null)
@@ -4559,7 +4559,7 @@ namespace Barotrauma
{ {
if (sub?.Info?.OutpostGenerationParams != null) if (sub?.Info?.OutpostGenerationParams != null)
{ {
OutpostGenerator.SpawnNPCs((GameMain.GameSession?.GameMode as CampaignMode)?.Map?.CurrentLocation, sub); OutpostGenerator.SpawnNPCs(StartLocation, sub);
} }
} }
} }
@@ -1281,6 +1281,8 @@ namespace Barotrauma
explosionOnBroken.Attack.Range = explosionRange * gap.Open; explosionOnBroken.Attack.Range = explosionRange * gap.Open;
explosionOnBroken.Attack.DamageMultiplier = explosionStrength; explosionOnBroken.Attack.DamageMultiplier = explosionStrength;
explosionOnBroken.Attack.Stun = MathHelper.Clamp(explosionStrength, 0.5f, 1.0f); explosionOnBroken.Attack.Stun = MathHelper.Clamp(explosionStrength, 0.5f, 1.0f);
explosionOnBroken.IgnoredCharacters.Clear();
if (attacker?.AIController is EnemyAIController) { explosionOnBroken.IgnoredCharacters.Add(attacker); }
explosionOnBroken?.Explode(gap.WorldPosition, damageSource: null, attacker: attacker); explosionOnBroken?.Explode(gap.WorldPosition, damageSource: null, attacker: attacker);
#if CLIENT #if CLIENT
if (linkedHull != null) if (linkedHull != null)
@@ -2155,11 +2155,11 @@ namespace Barotrauma
rotation += spread; rotation += spread;
if (projectile != null) if (projectile != null)
{ {
var sourceEntity = (sourceBody as ISpatialEntity) ?? entity; var sourceEntity = (sourceBody?.UserData as ISpatialEntity) ?? entity;
Vector2 spawnPos = sourceEntity.SimPosition; Vector2 spawnPos = sourceEntity.SimPosition;
projectile.Shoot(user, spawnPos, spawnPos, rotation, projectile.Shoot(user, spawnPos, spawnPos, rotation,
ignoredBodies: user?.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: true); ignoredBodies: user?.AnimController.Limbs.Where(l => !l.IsSevered).Select(l => l.body.FarseerBody).ToList(), createNetworkEvent: true);
projectile.Item.Submarine = sourceEntity?.Submarine; projectile.Item.Submarine = projectile.LaunchSub = sourceEntity?.Submarine;
} }
else if (newItem.body != null) else if (newItem.body != null)
{ {
@@ -218,6 +218,18 @@ namespace Barotrauma
public readonly int DangerLevel; public readonly int DangerLevel;
/// <summary>
/// An event of this danger level (or higher) must have been selected previously for this event to trigger.
/// It does not matter whether the event was completed successfully or not. Defaults to one less than the DangerLevel of this event.
/// </summary>
public readonly int RequiredPreviousDangerLevel;
/// <summary>
/// An event of a lower danger level must have been completed on the previous round for this event to trigger.
/// Defaults to false (no requirements)
/// </summary>
public readonly bool RequirePreviousDangerLevelCompleted;
/// <summary> /// <summary>
/// Minimum number of non-spectating human players on the server for the event to get selected. /// Minimum number of non-spectating human players on the server for the event to get selected.
/// </summary> /// </summary>
@@ -254,7 +266,10 @@ namespace Barotrauma
public TraitorEventPrefab(ContentXElement element, RandomEventsFile file, Identifier fallbackIdentifier = default) public TraitorEventPrefab(ContentXElement element, RandomEventsFile file, Identifier fallbackIdentifier = default)
: base(element, file, fallbackIdentifier) : base(element, file, fallbackIdentifier)
{ {
DangerLevel = MathHelper.Clamp(element.GetAttributeInt(nameof(DangerLevel), MinDangerLevel), MinDangerLevel, MaxDangerLevel); DangerLevel = MathHelper.Clamp(element.GetAttributeInt(nameof(DangerLevel), MinDangerLevel), min: MinDangerLevel, max: MaxDangerLevel);
RequiredPreviousDangerLevel = MathHelper.Clamp(element.GetAttributeInt(nameof(RequiredPreviousDangerLevel), def: DangerLevel - 1), min: 0, max: MaxDangerLevel - 1);
RequirePreviousDangerLevelCompleted = element.GetAttributeBool(nameof(RequirePreviousDangerLevelCompleted), false);
MinPlayerCount = element.GetAttributeInt(nameof(MinPlayerCount), 0); MinPlayerCount = element.GetAttributeInt(nameof(MinPlayerCount), 0);
+36 -1
View File
@@ -1,3 +1,39 @@
-------------------------------------------------------------------------------------------------------------------------------------------------
v1.1.18.0
-------------------------------------------------------------------------------------------------------------------------------------------------
- Updated translations.
- Modding: Added ContinueIfNoTargetsFound property to TagAction. Can be used to allow the event to continue even if the TagAction can't find any valid targets (by default the event wont continue until at least one target is found).
-------------------------------------------------------------------------------------------------------------------------------------------------
v1.1.17.0
-------------------------------------------------------------------------------------------------------------------------------------------------
- Changed traitor event selection logic a bit: most of the more dangerous events can trigger as long as a less dangerous event has been selected previously, even if that event wasn't completed successfully. Previously many of the dangerous events were extremely rare, because they required 1. completing an easier event first 2. a specific mission to be selected on the following round.
- Adjusted traitor event probabilities a bit to make some of the rarer ones more common.
- Fixes to some oddities and inconsistencies in containers: backpacks can't go in crates, duffel bags or outpost cabinets, fixed storage containers going in outpost cabinets.
- Fixed searchlights appearing as turrets in the "operate weapon" order (and the bots would complain about not being able to load ammo into them if you ordered them to operate one).
- Fixed security fleeing from the player during jailbreak missions.
- Fixed security not spawning in jailbreak missions in the mission mode.
- Fixed morphine not being shown as a suitable treatment for the concussion in the medic tutorial.
- Fixed abandoned outpost you're supposed to rescue Jacov Subra from sometimes turning into a normal outpost and cancelling the mission.
- Fixed some scripted events throwing unnecessary "no conditionals defined" console errors.
-------------------------------------------------------------------------------------------------------------------------------------------------
v1.1.16.0
-------------------------------------------------------------------------------------------------------------------------------------------------
- Fixed several issues when editing traitor events in the event editor (console errors, some actions not loading properly, inability to set a new event as a traitor event).
- Backpacks can't be put in cargo scooters.
- Fixed some traitor events being impossible to complete (harbringer of honks, faulty robes, handcuff shortage).
- Fixed latcher's tongue failing to attach to submarines.
- Fixed crashing when deleting a circuit box in the submarine editor. Undoing the deletion still does not work unfortunately, but we are looking into fixing that.
- Fixed errors when modifying any properties of an ItemLabel or Turret component in multiplayer.
- Fixed flashlights in guns (or other contained items) not getting flipped in the same direction as the container when put inside the container.
- Monsters don't get damaged by the hull shrapnel when they break a wall themselves.
- Fixed "can't create an entity event" error when ending a multiplayer round when there's dropped stacks around.
------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------
v1.1.15.0 v1.1.15.0
------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------
@@ -122,7 +158,6 @@ Multiplayer:
- Fixed characters getting removed at the end of the round if they've died and then been revived with the "revive" console command. - Fixed characters getting removed at the end of the round if they've died and then been revived with the "revive" console command.
AI: AI:
- Fixed searchlights not attracting monsters.
- Fixed bots "cleaning up" (or stealing) batteries from portable pumps. - Fixed bots "cleaning up" (or stealing) batteries from portable pumps.
- Fixed bots never cleaning up detached wires. - Fixed bots never cleaning up detached wires.
- Fixed bots sometimes ignoring the leaks right next to doors/hatches. - Fixed bots sometimes ignoring the leaks right next to doors/hatches.