This commit is contained in:
EvilFactory
2023-10-19 13:36:40 -03:00
21 changed files with 196 additions and 89 deletions

View File

@@ -1,14 +1,13 @@
#nullable enable
using Barotrauma.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
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;
namespace Barotrauma
@@ -37,7 +36,9 @@ namespace Barotrauma
private OutpostGenerationParams? lastTestParam;
private LocationType? lastTestType;
private int CreateID()
private GUITickBox? isTraitorEventBox;
private static int CreateID()
{
int maxId = nodeList.Any() ? nodeList.Max(node => node.ID) : 0;
return ++maxId;
@@ -54,8 +55,8 @@ namespace Barotrauma
private void CreateGUI()
{
GuiFrame = new GUIFrame(new RectTransform(new Vector2(0.2f, 0.4f), GUI.Canvas) { MinSize = new Point(300, 400) });
GUILayoutGroup layoutGroup = new GUILayoutGroup(RectTransform(0.9f, 0.9f, GuiFrame, Anchor.Center)) { Stretch = true };
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, AbsoluteSpacing = GUI.IntScale(5) };
// === BUTTONS === //
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"));
// 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
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);
}
@@ -149,6 +155,9 @@ namespace Barotrauma
FileSelection.Open = true;
return true;
};
isTraitorEventBox = new GUITickBox(RectTransform(1.0f, 0.125f, layoutGroup), "Traitor event");
screenResolution = new Point(GameMain.GraphicsWidth, GameMain.GraphicsHeight);
}
@@ -304,7 +313,10 @@ namespace Barotrauma
nodeList.Clear();
selectedNodes.Clear();
markedNodes.Clear();
if (isTraitorEventBox != null)
{
isTraitorEventBox.Selected = prefab is TraitorEventPrefab;
}
bool hadNodes = true;
CreateNodes(prefab.ConfigElement, ref hadNodes);
if (!hadNodes)
@@ -409,17 +421,18 @@ namespace Barotrauma
}
var parentElement = subElement.Parent;
foreach (var xElement in subElement.Elements())
{
if (xElement.Name.ToString().ToLowerInvariant() == "option")
switch (xElement.Name.ToString().ToLowerInvariant())
{
EventEditorNodeConnection optionConnection = new EventEditorNodeConnection(newNode, NodeConnectionType.Option)
{
OptionText = xElement.GetAttributeString("text", string.Empty),
EndConversation = xElement.GetAttributeBool("endconversation", false)
};
newNode.Connections.Add(optionConnection);
case "option":
EventEditorNodeConnection optionConnection = new EventEditorNodeConnection(newNode, NodeConnectionType.Option)
{
OptionText = xElement.GetAttributeString("text", string.Empty),
EndConversation = xElement.GetAttributeBool("endconversation", false)
};
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())
{
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;
}
parent?.AddConnection(NodeConnectionType.Add);
parent?.Connect(newNode, NodeConnectionType.Add);
}
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;
@@ -542,7 +566,9 @@ namespace Barotrauma
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;
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 nodes = new XElement("Nodes");
@@ -635,7 +661,7 @@ namespace Barotrauma
return mainElement;
}
private void Load(XElement saveElement)
private static void Load(XElement saveElement)
{
nodeList.Clear();
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; }
@@ -884,8 +910,8 @@ namespace Barotrauma
XElement? eventXml = ExportXML();
EventPrefab? prefab;
if (eventXml != null)
{
prefab = new EventPrefab(eventXml.FromPackage(null), null);
{
prefab = EventPrefab.Create(eventXml.FromPackage(null), file: null);
}
else
{

View File

@@ -13,7 +13,7 @@ namespace Barotrauma
Identifier eventIdentifier = msg.ReadIdentifier();
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;
}
GameMain.Client.Character.IsTraitor = true;

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>1.1.15.0</Version>
<Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>1.1.15.0</Version>
<Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma</Product>
<Version>1.1.15.0</Version>
<Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>Barotrauma</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>1.1.15.0</Version>
<Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>1.1.15.0</Version>
<Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -152,8 +152,6 @@ namespace Barotrauma
.Where(e => playerCount >= e.MinPlayerCount)
.ToList();
var minDangerLevelPrefabs = suitablePrefabs.FindAll(e => e.DangerLevel == TraitorEventPrefab.MinDangerLevel);
if (!suitablePrefabs.Any())
{
//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;
}
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 &&
previousEvent.TraitorEvent.DangerLevel < maxDangerLevel &&
previousEvent.TraitorEvent.IsChainable &&
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 =
//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
{
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)
{
GameServer.Log($"Could not find a suitable danger level {TraitorEventPrefab.MinDangerLevel} traitor event. Choosing a random event instead.", ServerLog.MessageType.Traitors);

View File

@@ -6,7 +6,7 @@
<RootNamespace>Barotrauma</RootNamespace>
<Authors>FakeFish, Undertow Games</Authors>
<Product>Barotrauma Dedicated Server</Product>
<Version>1.1.15.0</Version>
<Version>1.1.18.0</Version>
<Copyright>Copyright © FakeFish 2018-2023</Copyright>
<Platforms>AnyCPU;x64</Platforms>
<AssemblyName>DedicatedServer</AssemblyName>

View File

@@ -265,7 +265,7 @@ namespace Barotrauma
{
if (!IgnoreAtOutpost) { 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; }
return character.Submarine.Info.IsOutpost && character.Submarine.TeamID == CharacterTeamType.FriendlyNPC;
}

View File

@@ -342,6 +342,8 @@ namespace Barotrauma
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 CombatAction CombatAction;

View File

@@ -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.");
}
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)
{
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)
{
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))
{

View File

@@ -28,6 +28,9 @@ namespace Barotrauma
[Serialize(false, IsPropertySaveable.Yes)]
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.")]
public float ChoosePercentage { get; set; }
@@ -279,7 +282,14 @@ namespace Barotrauma
}
}
isFinished = !targetNotFound;
if (ContinueIfNoTargetsFound)
{
isFinished = true;
}
else
{
isFinished = !targetNotFound;
}
}
public override string ToDebugString()

View File

@@ -230,7 +230,7 @@ namespace Barotrauma
Bank = new Wallet(Option<Character>.None(), subElement);
break;
#if SERVER
case nameof(TraitorManager):
case "traitormanager":
GameMain.Server?.TraitorManager?.Load(subElement);
break;
case "savedexperiencepoints":

View File

@@ -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).
SetContainedActive(true);
}
if (containedItem.FlippedX)
if (containedItem.FlippedX != item.FlippedX)
{
containedItem.FlipX(relativeToSub: false);
}
if (containedItem.FlippedY)
if (containedItem.FlippedY != item.FlippedY)
{
containedItem.FlipY(relativeToSub: false);
}

View File

@@ -1322,17 +1322,20 @@ namespace Barotrauma
}
}
for (int i = 0; i < components.Count && i < clone.components.Count; i++)
if (clonedContainedItems.Any())
{
ItemComponent component = components[i],
cloneComp = clone.components[i];
if (component is not CircuitBox origBox || cloneComp is not CircuitBox cloneBox)
for (int i = 0; i < components.Count && i < clone.components.Count; i++)
{
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;
@@ -3242,7 +3245,7 @@ namespace Barotrauma
SetDroppedStackItemStates();
droppedStack = null;
#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>()));
}

View File

@@ -1379,7 +1379,7 @@ namespace Barotrauma
if (sub.Info.IsOutpost)
{
#if CLIENT
if (GameMain.GameSession.GameMode is TutorialMode) { continue; }
if (GameMain.GameSession?.GameMode is TutorialMode) { continue; }
#endif
OutpostGenerator.PowerUpOutpost(sub);
}
@@ -2106,7 +2106,7 @@ namespace Barotrauma
DebugConsole.ThrowError("Failed to generate alien ruins. Could not find any RuinGenerationParameters!");
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;
if (locationType == null)
@@ -4559,7 +4559,7 @@ namespace Barotrauma
{
if (sub?.Info?.OutpostGenerationParams != null)
{
OutpostGenerator.SpawnNPCs((GameMain.GameSession?.GameMode as CampaignMode)?.Map?.CurrentLocation, sub);
OutpostGenerator.SpawnNPCs(StartLocation, sub);
}
}
}

View File

@@ -1281,6 +1281,8 @@ namespace Barotrauma
explosionOnBroken.Attack.Range = explosionRange * gap.Open;
explosionOnBroken.Attack.DamageMultiplier = explosionStrength;
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);
#if CLIENT
if (linkedHull != null)

View File

@@ -2186,11 +2186,11 @@ namespace Barotrauma
rotation += spread;
if (projectile != null)
{
var sourceEntity = (sourceBody as ISpatialEntity) ?? entity;
var sourceEntity = (sourceBody?.UserData as ISpatialEntity) ?? entity;
Vector2 spawnPos = sourceEntity.SimPosition;
projectile.Shoot(user, spawnPos, spawnPos, rotation,
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)
{

View File

@@ -218,6 +218,18 @@ namespace Barotrauma
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>
/// Minimum number of non-spectating human players on the server for the event to get selected.
/// </summary>
@@ -254,7 +266,10 @@ namespace Barotrauma
public TraitorEventPrefab(ContentXElement element, RandomEventsFile file, Identifier fallbackIdentifier = default)
: 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);

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
-------------------------------------------------------------------------------------------------------------------------------------------------
@@ -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.
AI:
- Fixed searchlights not attracting monsters.
- Fixed bots "cleaning up" (or stealing) batteries from portable pumps.
- Fixed bots never cleaning up detached wires.
- Fixed bots sometimes ignoring the leaks right next to doors/hatches.