Unstable v0.19.3.0
This commit is contained in:
+6
-4
@@ -1,8 +1,6 @@
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -20,6 +18,9 @@ namespace Barotrauma
|
||||
[Serialize(true, IsPropertySaveable.Yes, "When set to false when TargetLimb is not specified prevent checking limb-specific afflictions")]
|
||||
public bool AllowLimbAfflictions { get; set; }
|
||||
|
||||
[Serialize(0.0f, IsPropertySaveable.Yes, "Minimum strength of the affliction")]
|
||||
public float MinStrength { get; set; }
|
||||
|
||||
public CheckAfflictionAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
@@ -32,14 +33,15 @@ namespace Barotrauma
|
||||
if (target.CharacterHealth == null) { continue; }
|
||||
if (TargetLimb == LimbType.None)
|
||||
{
|
||||
if (target.CharacterHealth.GetAffliction(Identifier, AllowLimbAfflictions) != null) { return true; }
|
||||
var affliction = target.CharacterHealth.GetAffliction(Identifier, AllowLimbAfflictions);
|
||||
if (affliction != null && affliction.Strength >= MinStrength) { return true; }
|
||||
}
|
||||
IEnumerable<Affliction> afflictions = target.CharacterHealth.GetAllAfflictions().Where(affliction =>
|
||||
{
|
||||
LimbType? limbType = target.CharacterHealth.GetAfflictionLimb(affliction)?.type;
|
||||
if (limbType == null) { return false; }
|
||||
|
||||
return limbType == TargetLimb || true;
|
||||
return limbType == TargetLimb && affliction.Strength >= MinStrength;
|
||||
});
|
||||
|
||||
if (afflictions.Any(a => a.Identifier == Identifier)) { return true; }
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CheckConditionalAction : BinaryOptionAction
|
||||
{
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
private PropertyConditional Conditional { get; }
|
||||
|
||||
public CheckConditionalAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
|
||||
{
|
||||
if (TargetTag.IsEmpty)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no target tag! This will cause the check to automatically succeed.");
|
||||
}
|
||||
foreach (var attribute in element.Attributes())
|
||||
{
|
||||
if (PropertyConditional.IsValid(attribute) && !IsTargetTagAttribute(attribute))
|
||||
{
|
||||
Conditional = new PropertyConditional(attribute);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Conditional == null)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction with no valid PropertyConditional! This will cause the check to automatically succeed.");
|
||||
}
|
||||
|
||||
static bool IsTargetTagAttribute(XAttribute attribute)
|
||||
{
|
||||
return attribute.Name.ToString().Equals("targettag", System.StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetEventName()
|
||||
{
|
||||
return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event";
|
||||
}
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
{
|
||||
ISerializableEntity target = null;
|
||||
if (!TargetTag.IsEmpty)
|
||||
{
|
||||
foreach (var t in ParentEvent.GetTargets(TargetTag))
|
||||
{
|
||||
if (t is ISerializableEntity e)
|
||||
{
|
||||
target = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target == null)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckConditionalAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed.");
|
||||
}
|
||||
if (target == null || Conditional == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (target is Item item)
|
||||
{
|
||||
return item.ConditionalMatches(Conditional);
|
||||
}
|
||||
return Conditional.Matches(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
namespace Barotrauma
|
||||
{
|
||||
class CheckOrderAction : BinaryOptionAction
|
||||
{
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier OrderIdentifier { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier OrderOption { get; set; }
|
||||
|
||||
public CheckOrderAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
protected override bool? DetermineSuccess()
|
||||
{
|
||||
ISerializableEntity target = null;
|
||||
if (!TargetTag.IsEmpty)
|
||||
{
|
||||
foreach (var t in ParentEvent.GetTargets(TargetTag))
|
||||
{
|
||||
if (t is ISerializableEntity e)
|
||||
{
|
||||
target = e;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (target == null)
|
||||
{
|
||||
DebugConsole.ShowError($"CheckConditionalAction error: {GetEventName()} uses a CheckOrderAction but no valid target was found for tag \"{TargetTag}\"! This will cause the check to automatically succeed.");
|
||||
return true;
|
||||
}
|
||||
if (target is Character character)
|
||||
{
|
||||
var currentOrderInfo = character.GetCurrentOrderWithTopPriority();
|
||||
if (currentOrderInfo?.Identifier == OrderIdentifier)
|
||||
{
|
||||
if (OrderOption.IsEmpty)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return currentOrderInfo?.Option == OrderOption;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private string GetEventName()
|
||||
{
|
||||
return ParentEvent?.Prefab?.Identifier is { IsEmpty: false } identifier ? $"the event \"{identifier}\"" : "an unknown event";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class MessageBoxAction : EventAction
|
||||
{
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier Header { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier Text { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public string IconStyle { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool HideCloseButton { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TargetTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public string CloseOnInput { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier CloseOnInteractTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier CloseOnPickUpTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier CloseOnEquipTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier CloseOnExitRoomName { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool IsTutorialObjective { get; set; }
|
||||
|
||||
private bool isFinished = false;
|
||||
|
||||
public MessageBoxAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (isFinished) { return; }
|
||||
#if CLIENT
|
||||
CreateMessageBox();
|
||||
if (IsTutorialObjective && GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
|
||||
{
|
||||
tutorialMode.Tutorial?.TriggerTutorialSegment(new Tutorials.Tutorial.Segment(Text, CreateMessageBox));
|
||||
}
|
||||
#endif
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
public void CreateMessageBox()
|
||||
{
|
||||
new GUIMessageBox(
|
||||
headerText: TextManager.Get(Header),
|
||||
text: RichString.Rich(TextManager.ParseInputTypes(TextManager.Get(Text).Fallback(Text.ToString()), useColorHighlight: true)),
|
||||
buttons: Array.Empty<LocalizedString>(),
|
||||
type: GUIMessageBox.Type.Tutorial,
|
||||
iconStyle: IconStyle,
|
||||
autoCloseCondition: GetAutoCloseCondition(),
|
||||
hideCloseButton: HideCloseButton);
|
||||
}
|
||||
#endif
|
||||
|
||||
private Func<bool> GetAutoCloseCondition()
|
||||
{
|
||||
var character = ParentEvent.GetTargets(TargetTag).FirstOrDefault() as Character;
|
||||
Func<bool> autoCloseCondition = null;
|
||||
if (!string.IsNullOrEmpty(CloseOnInput) && Enum.TryParse(CloseOnInput, true, out InputType closeOnInput))
|
||||
{
|
||||
#if CLIENT
|
||||
autoCloseCondition = () => PlayerInput.KeyDown(closeOnInput);
|
||||
#endif
|
||||
}
|
||||
else if (!CloseOnInteractTag.IsEmpty)
|
||||
{
|
||||
autoCloseCondition = () => character?.SelectedItem != null && character.SelectedItem.HasTag(CloseOnInteractTag);
|
||||
}
|
||||
else if (!CloseOnPickUpTag.IsEmpty)
|
||||
{
|
||||
autoCloseCondition = () => character?.Inventory != null && character.Inventory.FindItemByTag(CloseOnPickUpTag, recursive: true) != null;
|
||||
}
|
||||
else if (!CloseOnEquipTag.IsEmpty)
|
||||
{
|
||||
autoCloseCondition = () => character != null && character.HasEquippedItem(CloseOnEquipTag);
|
||||
}
|
||||
else if (!CloseOnExitRoomName.IsEmpty)
|
||||
{
|
||||
autoCloseCondition = () => character?.CurrentHull != null && character.CurrentHull.RoomName.ToIdentifier() != CloseOnExitRoomName;
|
||||
}
|
||||
return autoCloseCondition;
|
||||
}
|
||||
|
||||
public override bool IsFinished(ref string goToLabel)
|
||||
{
|
||||
return isFinished;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
isFinished = false;
|
||||
}
|
||||
|
||||
public override string ToDebugString()
|
||||
{
|
||||
return $"{ToolBox.GetDebugSymbol(isFinished)} {nameof(MessageBoxAction)}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -145,9 +145,9 @@ namespace Barotrauma
|
||||
foreach (Client client in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
IWriteMessage outmsg = new WriteOnlyMessage();
|
||||
outmsg.Write((byte)ServerPacketHeader.EVENTACTION);
|
||||
outmsg.Write((byte)EventManager.NetworkEventType.MISSION);
|
||||
outmsg.Write(prefab.Identifier);
|
||||
outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION);
|
||||
outmsg.WriteByte((byte)EventManager.NetworkEventType.MISSION);
|
||||
outmsg.WriteIdentifier(prefab.Identifier);
|
||||
GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ namespace Barotrauma
|
||||
|
||||
private readonly HashSet<Identifier> targetModuleTags = new HashSet<Identifier>();
|
||||
|
||||
[Serialize(true, IsPropertySaveable.Yes, description: "If false, we won't spawn another character if one with the same identifier has already been spawned.")]
|
||||
public bool AllowDuplicates { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes, "What outpost module tags does the entity prefer to spawn in.")]
|
||||
public string TargetModuleTags
|
||||
{
|
||||
@@ -115,6 +118,12 @@ namespace Barotrauma
|
||||
HumanPrefab humanPrefab = NPCSet.Get(NPCSetIdentifier, NPCIdentifier);
|
||||
if (humanPrefab != null)
|
||||
{
|
||||
if (!AllowDuplicates &&
|
||||
Character.CharacterList.Any(c => c.Info?.HumanPrefabIds.NpcIdentifier == NPCIdentifier && c.Info?.HumanPrefabIds.NpcSetIdentifier == NPCSetIdentifier))
|
||||
{
|
||||
spawned = true;
|
||||
return;
|
||||
}
|
||||
ISpatialEntity spawnPos = GetSpawnPos();
|
||||
if (spawnPos != null)
|
||||
{
|
||||
@@ -145,6 +154,11 @@ namespace Barotrauma
|
||||
}
|
||||
else if (!SpeciesName.IsEmpty)
|
||||
{
|
||||
if (!AllowDuplicates && Character.CharacterList.Any(c => c.SpeciesName == SpeciesName))
|
||||
{
|
||||
spawned = true;
|
||||
return;
|
||||
}
|
||||
ISpatialEntity spawnPos = GetSpawnPos();
|
||||
if (spawnPos != null)
|
||||
{
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using Barotrauma.Extensions;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
@@ -36,6 +33,7 @@ namespace Barotrauma
|
||||
("crew", v => TagCrew()),
|
||||
("humanprefabidentifier", TagHumansByIdentifier),
|
||||
("structureidentifier", TagStructuresByIdentifier),
|
||||
("structurespecialtag", TagStructuresBySpecialTag),
|
||||
("itemidentifier", TagItemsByIdentifier),
|
||||
("itemtag", TagItemsByTag),
|
||||
("hullname", TagHullsByName)
|
||||
@@ -100,6 +98,11 @@ namespace Barotrauma
|
||||
ParentEvent.AddTargetPredicate(Tag, e => e is Structure s && SubmarineTypeMatches(s.Submarine) && s.Prefab.Identifier == identifier);
|
||||
}
|
||||
|
||||
private void TagStructuresBySpecialTag(Identifier tag)
|
||||
{
|
||||
ParentEvent.AddTargetPredicate(Tag, e => e is Structure s && SubmarineTypeMatches(s.Submarine) && s.SpecialTag.ToIdentifier() == tag);
|
||||
}
|
||||
|
||||
private void TagItemsByIdentifier(Identifier identifier)
|
||||
{
|
||||
ParentEvent.AddTargetPredicate(Tag, e => e is Item it && SubmarineTypeMatches(it.Submarine) && it.Prefab.Identifier == identifier);
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
namespace Barotrauma
|
||||
{
|
||||
class TutorialCompleteAction : EventAction
|
||||
{
|
||||
private bool isFinished;
|
||||
|
||||
public TutorialCompleteAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element) { }
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (isFinished) { return; }
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
|
||||
{
|
||||
tutorialMode.Tutorial?.Complete();
|
||||
}
|
||||
#endif
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
public override bool IsFinished(ref string goToLabel)
|
||||
{
|
||||
return isFinished;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
isFinished = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#if CLIENT
|
||||
using Barotrauma.Tutorials;
|
||||
#endif
|
||||
|
||||
namespace Barotrauma
|
||||
{
|
||||
class TutorialSegmentAction : EventAction
|
||||
{
|
||||
public enum SegmentActionType { Trigger, Complete, Remove };
|
||||
|
||||
[Serialize(SegmentActionType.Trigger, IsPropertySaveable.Yes)]
|
||||
public SegmentActionType Type { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier Id { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier ObjectiveTextTag { get; set; }
|
||||
|
||||
[Serialize(false, IsPropertySaveable.Yes)]
|
||||
public bool AutoPlayVideo { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public Identifier TextTag { get; set; }
|
||||
|
||||
[Serialize("", IsPropertySaveable.Yes)]
|
||||
public string VideoFile { get; set; }
|
||||
|
||||
[Serialize(450, IsPropertySaveable.Yes)]
|
||||
public int Width { get; set; }
|
||||
|
||||
[Serialize(80, IsPropertySaveable.Yes)]
|
||||
public int Height { get; set; }
|
||||
|
||||
#if CLIENT
|
||||
private readonly Tutorial.Segment segment;
|
||||
#endif
|
||||
private bool isFinished;
|
||||
|
||||
public TutorialSegmentAction(ScriptedEvent parentEvent, ContentXElement element) : base(parentEvent, element)
|
||||
{
|
||||
#if CLIENT
|
||||
// Only need to create the segment when it's being triggered (otherwise the tutorial already has the segment instance)
|
||||
if (Type == SegmentActionType.Trigger)
|
||||
{
|
||||
segment = new Tutorial.Segment(Id, ObjectiveTextTag, AutoPlayVideo ? Tutorials.AutoPlayVideo.Yes : Tutorials.AutoPlayVideo.No,
|
||||
new Tutorial.Segment.Text(TextTag, Width, Height, Anchor.Center),
|
||||
new Tutorial.Segment.Video(VideoFile, TextTag, Width, Height));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime)
|
||||
{
|
||||
if (isFinished) { return; }
|
||||
|
||||
#if CLIENT
|
||||
if (GameMain.GameSession?.GameMode is TutorialMode tutorialMode)
|
||||
{
|
||||
if (tutorialMode.Tutorial is Tutorial tutorial)
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case SegmentActionType.Trigger:
|
||||
tutorial.TriggerTutorialSegment(segment);
|
||||
break;
|
||||
case SegmentActionType.Complete:
|
||||
tutorial.CompleteTutorialSegment(Id);
|
||||
break;
|
||||
case SegmentActionType.Remove:
|
||||
tutorial.RemoveTutorialSegment(Id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DebugConsole.ShowError($"Error in event \"{ParentEvent.Prefab.Identifier}\": attempting to use TutorialSegmentAction during a non-Tutorial game mode!");
|
||||
}
|
||||
#endif
|
||||
|
||||
isFinished = true;
|
||||
}
|
||||
|
||||
public override bool IsFinished(ref string goToLabel)
|
||||
{
|
||||
return isFinished;
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
isFinished = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,9 +55,9 @@ namespace Barotrauma
|
||||
foreach (Client client in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
IWriteMessage outmsg = new WriteOnlyMessage();
|
||||
outmsg.Write((byte)ServerPacketHeader.EVENTACTION);
|
||||
outmsg.Write((byte)EventManager.NetworkEventType.UNLOCKPATH);
|
||||
outmsg.Write((UInt16)GameMain.GameSession.Map.Connections.IndexOf(connection));
|
||||
outmsg.WriteByte((byte)ServerPacketHeader.EVENTACTION);
|
||||
outmsg.WriteByte((byte)EventManager.NetworkEventType.UNLOCKPATH);
|
||||
outmsg.WriteUInt16((UInt16)GameMain.GameSession.Map.Connections.IndexOf(connection));
|
||||
GameMain.Server.ServerPeer.Send(outmsg, client.Connection, DeliveryMethod.Reliable);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user